Skip to content

Commit

Permalink
Add Version Info section to webroot, add check to make sure webroot a…
Browse files Browse the repository at this point in the history
…nd wire-pod are matched, inbuilt BLE can now run onboarding wake-up animation, better error-handling, add HTTP proxy for OTA update as Vector can't download from HTTPS source, use dropdown list for time zone
  • Loading branch information
kercre123 committed Apr 21, 2024
1 parent 2da2347 commit 3f49c06
Show file tree
Hide file tree
Showing 22 changed files with 3,358 additions and 2,408 deletions.
2 changes: 2 additions & 0 deletions chipper/pkg/vars/vars.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ var (
WhisperModelPath string = "../whisper.cpp/models/"
SessionCertPath string = "./session-certs/"
SavedChatsPath string = "./openaiChats.json"
VersionFile string = "./version"
)

var (
Expand Down Expand Up @@ -172,6 +173,7 @@ func Init() {
Certs = join(podDir, "./certs")
SessionCertPath = join(podDir, SessionCertPath)
SavedChatsPath = join(podDir, SavedChatsPath)
VersionFile = join(podDir, VersionFile)
os.Mkdir(JdocsDir, 0777)
os.Mkdir(SessionCertPath, 0777)
os.Mkdir(Certs, 0777)
Expand Down
87 changes: 87 additions & 0 deletions chipper/pkg/wirepod/config-ws/webserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package webserver
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
"path"
"path/filepath"
Expand Down Expand Up @@ -356,6 +358,67 @@ func apiHandler(w http.ResponseWriter, r *http.Request) {
vars.RememberedChats = []vars.RememberedChat{}
fmt.Fprintf(w, "done")
return
case strings.Contains(r.URL.Path, "/api/get_ota"):
otaName := strings.Split(r.URL.Path, "/")[3]
//https://archive.org/download/vector-pod-firmware/vicos-2.0.1.6076ep.ota
targetURL, err := url.Parse("https://archive.org/download/vector-pod-firmware/" + strings.TrimSpace(otaName))
if err != nil {
http.Error(w, "Failed to parse URL", http.StatusInternalServerError)
return
}
req, err := http.NewRequest(r.Method, targetURL.String(), nil)
if err != nil {
http.Error(w, "Failed to create request", http.StatusInternalServerError)
return
}
for key, values := range r.Header {
for _, value := range values {
req.Header.Add(key, value)
}
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
http.Error(w, "Failed to perform request", http.StatusInternalServerError)
return
}
defer resp.Body.Close()
for key, values := range resp.Header {
for _, value := range values {
w.Header().Add(key, value)
}
}
//w.WriteHeader(resp.StatusCode)
_, err = io.Copy(w, resp.Body)
if err != nil {
http.Error(w, "failed to copy response body", http.StatusInternalServerError)
return
}
case r.URL.Path == "/api/get_version_info":
type VerInfo struct {
Installed string `json:"installed"`
Current string `json:"current"`
UpdateAvailable bool `json:"avail"`
}
var verInfo VerInfo
ver, err := os.ReadFile(vars.VersionFile)
if err != nil {
fmt.Fprint(w, "error: version file doesn't exist")
return
}
installedVer := strings.TrimSpace(string(ver))
currentVer, err := GetLatestReleaseTag("kercre123", "WirePod")
if err != nil {
fmt.Fprint(w, "error comming with github: "+err.Error())
return
}
verInfo.Installed = installedVer
verInfo.Current = strings.TrimSpace(currentVer)
if installedVer != strings.TrimSpace(currentVer) {
verInfo.UpdateAvailable = true
}
marshalled, _ := json.Marshal(verInfo)
w.Write(marshalled)
case r.URL.Path == "/api/generate_certs":
err := botsetup.CreateCertCombo()
if err != nil {
Expand All @@ -366,6 +429,30 @@ func apiHandler(w http.ResponseWriter, r *http.Request) {
}
}

func GetLatestReleaseTag(owner, repo string) (string, error) {
url := fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/latest", owner, repo)

resp, err := http.Get(url)
if err != nil {
return "", err
}
defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
type Release struct {
TagName string `json:"tag_name"`
}
var release Release
if err := json.Unmarshal(body, &release); err != nil {
return "", err
}

return release.TagName, nil
}

func certHandler(w http.ResponseWriter, r *http.Request) {
switch {
case strings.Contains(r.URL.Path, "/session-certs/"):
Expand Down
70 changes: 51 additions & 19 deletions chipper/pkg/wirepod/setup/ble.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"archive/tar"
"compress/bzip2"
"encoding/json"
"errors"
"fmt"
"io"
"math"
Expand Down Expand Up @@ -125,23 +126,34 @@ func InitBle() (*ble.VectorBLE, error) {
}
return client, err
case <-time.After(5 * time.Second):
done2 := make(chan bool)
FixBLEDriver()
client, err = ble.New(
ble.WithStatusChan(BleStatusChan),
ble.WithLogDirectory(os.TempDir()),
)
return client, err
go func() {
client, err = ble.New(
ble.WithStatusChan(BleStatusChan),
ble.WithLogDirectory(os.TempDir()),
)
done2 <- true
}()

select {
case <-done2:
return client, err
case <-time.After(5 * time.Second):
return nil, errors.New("error: took more than 5 seconds")
}
}
}

func FixBLEDriver() {
logger.Println("BLE driver has broken. Removing then inserting bluetooth kernel modules")
modList := []string{"btrtl", "btmtk", "btintel", "btbcm", "btusb"}
for _, mod := range modList {
rmmodList := []string{"btusb", "btrtl", "btmtk", "btintel", "btbcm"}
modprobeList := []string{"btrtl", "btmtk", "btintel", "btbcm", "btusb"}
for _, mod := range rmmodList {
exec.Command("/bin/rmmod", mod).Run()
}
time.Sleep(time.Second / 3)
for _, mod := range modList {
time.Sleep(time.Second / 2)
for _, mod := range modprobeList {
exec.Command("/bin/modprobe", mod).Run()
}
time.Sleep(time.Second / 2)
Expand Down Expand Up @@ -311,6 +323,11 @@ func BluetoothSetupAPI(w http.ResponseWriter, r *http.Request) {
return
case r.URL.Path == "/api-ble/start_ota":
otaUrl := r.FormValue("url")
if strings.TrimSpace(otaUrl) == "local" {
logger.Println("Starting proxy download from archive.org")
otaUrl = "http://" + vars.GetOutboundIP().String() + ":" + vars.WebPort + "/api/get_ota/vicos-2.0.1.6076ep.ota"
logger.Println("(" + otaUrl + ")")
}
if strings.Contains(otaUrl, "https://") {
fmt.Fprint(w, "error: ota URL must be http")
return
Expand Down Expand Up @@ -428,16 +445,6 @@ func BluetoothSetupAPI(w http.ResponseWriter, r *http.Request) {
}
if resp {
time.Sleep(time.Second)
logger.Println("BLE authentication successful")
BleClient.SDKProxy(&ble.SDKProxyRequest{
URLPath: "/v1/send_onboarding_input",
Body: `{"onboarding_mark_complete_and_exit": {}}`,
},
)
go func() {
time.Sleep(time.Second * 2)
mdnshandler.PostmDNSNow()
}()
fmt.Fprint(w, "success")
return
} else {
Expand All @@ -456,6 +463,31 @@ func BluetoothSetupAPI(w http.ResponseWriter, r *http.Request) {
logger.Println("BLE authentication attempts exhausted")
fmt.Fprint(w, "error authenticating")
return
case r.URL.Path == "/api-ble/reset_onboarding":
BleClient.SDKProxy(
&ble.SDKProxyRequest{
URLPath: "/v1/send_onboarding_input",
Body: `{"onboarding_set_phase_request": {"phase": 2}}`,
},
)
case r.URL.Path == "/api-ble/onboard":
wAnim := r.FormValue("with_anim")
if wAnim == "true" {
BleClient.SDKProxy(
&ble.SDKProxyRequest{
URLPath: "/v1/send_onboarding_input",
Body: `{"onboarding_wake_up_request": {}}`,
},
)
time.Sleep(time.Second * 21)
}
BleClient.SDKProxy(
&ble.SDKProxyRequest{
URLPath: "/v1/send_onboarding_input",
Body: `{"onboarding_mark_complete_and_exit": {}}`,
},
)
fmt.Fprint(w, "done")
case r.URL.Path == "/api-ble/disconnect":
err := BleClient.Close()
if err != nil {
Expand Down
38 changes: 38 additions & 0 deletions chipper/pkg/wirepod/stt/vosk/Vosk.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"os"
"path/filepath"
"sync"
"time"

vosk "github.com/kercre123/vosk-api/go"
"github.com/kercre123/wire-pod/chipper/pkg/logger"
Expand Down Expand Up @@ -94,10 +95,47 @@ func Init() error {
}
modelLoaded = true
logger.Println("VOSK initiated successfully")
runTest()
}
return nil
}

func runTest() {
// make sure recognizer is all loaded into RAM
logger.Println("Running recognizer test")
var withGrm bool
if GrammerEnable {
logger.Println("Using grammer-optimized recognizer")
withGrm = true
} else {
logger.Println("Using general recognizer")
withGrm = false
}
rec, recind := getRec(withGrm)
pcmBytes, _ := os.ReadFile("./stttest.pcm")
var micData [][]byte
cTime := time.Now()
micData = sr.SplitVAD(pcmBytes)
for _, sample := range micData {
rec.AcceptWaveform(sample)
}
var jres map[string]interface{}
json.Unmarshal([]byte(rec.FinalResult()), &jres)
if withGrm {
grmRecs[recind].InUse = false
} else {
gpRecs[recind].InUse = false
}
transcribedText := jres["text"].(string)
tTime := time.Now().Sub(cTime)
logger.Println("Text (from test):", transcribedText)
if tTime.Seconds() > 3 {
logger.Println("Vosk test took a while, performance may be degraded. (" + fmt.Sprint(tTime) + ")")
}
logger.Println("Vosk test successful! (Took " + fmt.Sprint(tTime) + ")")

}

func getRec(withGrm bool) (*vosk.VoskRecognizer, int) {
recsmu.Lock()
defer recsmu.Unlock()
Expand Down
Loading

0 comments on commit 3f49c06

Please sign in to comment.