From 3f49c06a5cafd96d98aa666570545d65a069f63c Mon Sep 17 00:00:00 2001 From: kercre123 Date: Sun, 21 Apr 2024 14:19:54 -0500 Subject: [PATCH] Add Version Info section to webroot, add check to make sure webroot and 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 --- chipper/pkg/vars/vars.go | 2 + chipper/pkg/wirepod/config-ws/webserver.go | 87 ++ chipper/pkg/wirepod/setup/ble.go | 70 +- chipper/pkg/wirepod/stt/vosk/Vosk.go | 38 + chipper/start.sh | 151 +-- chipper/webroot/index.html | 378 +++--- chipper/webroot/initial.html | 448 ++++--- chipper/webroot/js/ble.js | 758 ++++++------ chipper/webroot/js/initial.js | 346 +++--- chipper/webroot/js/main.js | 1222 +++++++++++--------- chipper/webroot/js/ssh.js | 94 +- chipper/webroot/sdkapp/control.html | 161 ++- chipper/webroot/sdkapp/index.html | 65 +- chipper/webroot/sdkapp/js/auth.js | 44 +- chipper/webroot/sdkapp/js/control.js | 503 ++++---- chipper/webroot/sdkapp/js/faces.js | 127 +- chipper/webroot/sdkapp/js/httprequest.js | 22 +- chipper/webroot/sdkapp/js/main.js | 552 ++++----- chipper/webroot/sdkapp/js/settings.js | 23 +- chipper/webroot/sdkapp/settings.html | 54 +- chipper/webroot/setup.html | 506 +++++--- setup.sh | 115 +- 22 files changed, 3358 insertions(+), 2408 deletions(-) diff --git a/chipper/pkg/vars/vars.go b/chipper/pkg/vars/vars.go index 586d37ed..8c6869db 100644 --- a/chipper/pkg/vars/vars.go +++ b/chipper/pkg/vars/vars.go @@ -42,6 +42,7 @@ var ( WhisperModelPath string = "../whisper.cpp/models/" SessionCertPath string = "./session-certs/" SavedChatsPath string = "./openaiChats.json" + VersionFile string = "./version" ) var ( @@ -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) diff --git a/chipper/pkg/wirepod/config-ws/webserver.go b/chipper/pkg/wirepod/config-ws/webserver.go index 6c70eda1..a0a4443e 100755 --- a/chipper/pkg/wirepod/config-ws/webserver.go +++ b/chipper/pkg/wirepod/config-ws/webserver.go @@ -3,7 +3,9 @@ package webserver import ( "encoding/json" "fmt" + "io" "net/http" + "net/url" "os" "path" "path/filepath" @@ -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 { @@ -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/"): diff --git a/chipper/pkg/wirepod/setup/ble.go b/chipper/pkg/wirepod/setup/ble.go index de939053..95fa040d 100644 --- a/chipper/pkg/wirepod/setup/ble.go +++ b/chipper/pkg/wirepod/setup/ble.go @@ -7,6 +7,7 @@ import ( "archive/tar" "compress/bzip2" "encoding/json" + "errors" "fmt" "io" "math" @@ -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) @@ -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 @@ -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 { @@ -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 { diff --git a/chipper/pkg/wirepod/stt/vosk/Vosk.go b/chipper/pkg/wirepod/stt/vosk/Vosk.go index 31990dec..8d644760 100755 --- a/chipper/pkg/wirepod/stt/vosk/Vosk.go +++ b/chipper/pkg/wirepod/stt/vosk/Vosk.go @@ -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" @@ -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() diff --git a/chipper/start.sh b/chipper/start.sh index 57065af4..323404bc 100755 --- a/chipper/start.sh +++ b/chipper/start.sh @@ -3,12 +3,12 @@ UNAME=$(uname -a) if [[ $EUID -ne 0 ]]; then - echo "This script must be run as root. sudo ./start.sh" - exit 1 + echo "This script must be run as root. sudo ./start.sh" + exit 1 fi if [[ -d ./chipper ]]; then - cd chipper + cd chipper fi #if [[ ! -f ./chipper ]]; then @@ -21,82 +21,89 @@ fi #fi if [[ ! -f ./source.sh ]]; then - echo "You need to make a source.sh file. This can be done with the setup.sh script." - exit 0 + echo "You need to make a source.sh file. This can be done with the setup.sh script." + exit 0 fi source source.sh +# set go tags +export GOTAGS="nolibopusfile" + +if [[ ${USE_INBUILT_BLE} == "true" ]]; then + GOTAGS="${GOTAGS},inbuiltble" +fi + #./chipper if [[ ${STT_SERVICE} == "leopard" ]]; then - if [[ -f ./chipper ]]; then - ./chipper - else - /usr/local/go/bin/go run cmd/leopard/main.go - fi -elif [[ ${STT_SERVICE} == "rhino" ]]; then - if [[ -f ./chipper ]]; then - ./chipper - else - /usr/local/go/bin/go run cmd/experimental/rhino/main.go - fi -elif [[ ${STT_SERVICE} == "houndify" ]]; then - if [[ -f ./chipper ]]; then - ./chipper - else - /usr/local/go/bin/go run cmd/experimental/houndify/main.go - fi -elif [[ ${STT_SERVICE} == "whisper" ]]; then - if [[ -f ./chipper ]]; then - ./chipper - else - /usr/local/go/bin/go run cmd/experimental/whisper/main.go - fi -elif [[ ${STT_SERVICE} == "whisper.cpp" ]]; then - if [[ -f ./chipper ]]; then - export C_INCLUDE_PATH="../whisper.cpp" - export LIBRARY_PATH="../whisper.cpp" - export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$(pwd)/../whisper.cpp" - export CGO_LDFLAGS="-L$(pwd)/../whisper.cpp" - export CGO_CFLAGS="-I$(pwd)/../whisper.cpp" - ./chipper - else - export C_INCLUDE_PATH="../whisper.cpp" - export LIBRARY_PATH="../whisper.cpp" - export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$(pwd)/../whisper.cpp" - export CGO_LDFLAGS="-L$(pwd)/../whisper.cpp" - export CGO_CFLAGS="-I$(pwd)/../whisper.cpp" - if [[ ${UNAME} == *"Darwin"* ]]; then - export GGML_METAL_PATH_RESOURCES="../whisper.cpp" - /usr/local/go/bin/go run -ldflags "-extldflags '-framework Foundation -framework Metal -framework MetalKit'" cmd/experimental/whisper.cpp/main.go + if [[ -f ./chipper ]]; then + ./chipper + else + /usr/local/go/bin/go -tags $GOTAGS run cmd/leopard/main.go + fi + elif [[ ${STT_SERVICE} == "rhino" ]]; then + if [[ -f ./chipper ]]; then + ./chipper + else + /usr/local/go/bin/go -tags $GOTAGS run cmd/experimental/rhino/main.go + fi + elif [[ ${STT_SERVICE} == "houndify" ]]; then + if [[ -f ./chipper ]]; then + ./chipper else - /usr/local/go/bin/go run cmd/experimental/whisper.cpp/main.go + /usr/local/go/bin/go -tags $GOTAGS run cmd/experimental/houndify/main.go + fi + elif [[ ${STT_SERVICE} == "whisper" ]]; then + if [[ -f ./chipper ]]; then + ./chipper + else + /usr/local/go/bin/go -tags $GOTAGS run cmd/experimental/whisper/main.go + fi + elif [[ ${STT_SERVICE} == "whisper.cpp" ]]; then + if [[ -f ./chipper ]]; then + export C_INCLUDE_PATH="../whisper.cpp" + export LIBRARY_PATH="../whisper.cpp" + export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$(pwd)/../whisper.cpp" + export CGO_LDFLAGS="-L$(pwd)/../whisper.cpp" + export CGO_CFLAGS="-I$(pwd)/../whisper.cpp" + ./chipper + else + export C_INCLUDE_PATH="../whisper.cpp" + export LIBRARY_PATH="../whisper.cpp" + export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$(pwd)/../whisper.cpp" + export CGO_LDFLAGS="-L$(pwd)/../whisper.cpp" + export CGO_CFLAGS="-I$(pwd)/../whisper.cpp" + if [[ ${UNAME} == *"Darwin"* ]]; then + export GGML_METAL_PATH_RESOURCES="../whisper.cpp" + /usr/local/go/bin/go run -tags $GOTAGS -ldflags "-extldflags '-framework Foundation -framework Metal -framework MetalKit'" cmd/experimental/whisper.cpp/main.go + else + /usr/local/go/bin/go run -tags $GOTAGS cmd/experimental/whisper.cpp/main.go + fi + fi + elif [[ ${STT_SERVICE} == "vosk" ]]; then + if [[ -f ./chipper ]]; then + export CGO_ENABLED=1 + export CGO_CFLAGS="-I/root/.vosk/libvosk" + export CGO_LDFLAGS="-L /root/.vosk/libvosk -lvosk -ldl -lpthread" + export LD_LIBRARY_PATH="/root/.vosk/libvosk:$LD_LIBRARY_PATH" + ./chipper + else + export CGO_ENABLED=1 + export CGO_CFLAGS="-I/root/.vosk/libvosk" + export CGO_LDFLAGS="-L /root/.vosk/libvosk -lvosk -ldl -lpthread" + export LD_LIBRARY_PATH="/root/.vosk/libvosk:$LD_LIBRARY_PATH" + /usr/local/go/bin/go run -tags $GOTAGS -exec "env DYLD_LIBRARY_PATH=$HOME/.vosk/libvosk" cmd/vosk/main.go fi - fi -elif [[ ${STT_SERVICE} == "vosk" ]]; then - if [[ -f ./chipper ]]; then - export CGO_ENABLED=1 - export CGO_CFLAGS="-I/root/.vosk/libvosk" - export CGO_LDFLAGS="-L /root/.vosk/libvosk -lvosk -ldl -lpthread" - export LD_LIBRARY_PATH="/root/.vosk/libvosk:$LD_LIBRARY_PATH" - ./chipper - else - export CGO_ENABLED=1 - export CGO_CFLAGS="-I/root/.vosk/libvosk" - export CGO_LDFLAGS="-L /root/.vosk/libvosk -lvosk -ldl -lpthread" - export LD_LIBRARY_PATH="/root/.vosk/libvosk:$LD_LIBRARY_PATH" - /usr/local/go/bin/go run -tags nolibopusfile -exec "env DYLD_LIBRARY_PATH=$HOME/.vosk/libvosk" cmd/vosk/main.go - fi else - if [[ -f ./chipper ]]; then - export CGO_LDFLAGS="-L/root/.coqui/" - export CGO_CXXFLAGS="-I/root/.coqui/" - export LD_LIBRARY_PATH="/root/.coqui/:$LD_LIBRARY_PATH" - ./chipper - else - export CGO_LDFLAGS="-L$HOME/.coqui/" - export CGO_CXXFLAGS="-I$HOME/.coqui/" - export LD_LIBRARY_PATH="$HOME/.coqui/:$LD_LIBRARY_PATH" - /usr/local/go/bin/go run cmd/coqui/main.go - fi + if [[ -f ./chipper ]]; then + export CGO_LDFLAGS="-L/root/.coqui/" + export CGO_CXXFLAGS="-I/root/.coqui/" + export LD_LIBRARY_PATH="/root/.coqui/:$LD_LIBRARY_PATH" + ./chipper + else + export CGO_LDFLAGS="-L$HOME/.coqui/" + export CGO_CXXFLAGS="-I$HOME/.coqui/" + export LD_LIBRARY_PATH="$HOME/.coqui/:$LD_LIBRARY_PATH" + /usr/local/go/bin/go run -tags $GOTAGS cmd/coqui/main.go + fi fi diff --git a/chipper/webroot/index.html b/chipper/webroot/index.html index 9c871e67..c805b34f 100755 --- a/chipper/webroot/index.html +++ b/chipper/webroot/index.html @@ -1,146 +1,266 @@ - - Wire-Pod Interface - - - - - -
-
-

Wire-Pod Interface

-
+ + Wire-Pod Interface + + + + + +
+
+

Wire-Pod Interface

+
- -
- - -