powerpods/goTool/cmd_serve.go
simon 85aeab85c0 Add web dashboard configuration for master and slaves.
Expose deadzone and unicast-test via HTTP API and UI, reusing the same UART commands as the CLI.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-19 00:10:33 +02:00

71 lines
1.5 KiB
Go

package main
import (
"embed"
"flag"
"fmt"
"io/fs"
"log"
"net/http"
"time"
"github.com/gorilla/websocket"
)
//go:embed webui/*
var webUI embed.FS
var wsUpgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { return true },
}
func runServe(portName string, baud int, args []string) error {
serveFlags := flag.NewFlagSet("serve", flag.ExitOnError)
addr := serveFlags.String("addr", ":8080", "HTTP listen address")
interval := serveFlags.Duration("interval", 2*time.Second, "UART poll interval")
if err := serveFlags.Parse(args); err != nil {
return err
}
if portName == "" {
return fmt.Errorf("serve requires -port (master UART)")
}
link := newManagedSerial(portName, baud)
link.quiet = true
defer link.Close()
hub := newWSHub()
stop := make(chan struct{})
defer close(stop)
go runPoller(link, portName, hub, *interval, stop)
mux := http.NewServeMux()
mountServeAPI(mux, link)
mux.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
conn, err := wsUpgrader.Upgrade(w, r, nil)
if err != nil {
log.Printf("websocket upgrade: %v", err)
return
}
hub.register(conn)
defer hub.unregister(conn)
defer conn.Close()
for {
if _, _, err := conn.ReadMessage(); err != nil {
return
}
}
})
ui, err := fs.Sub(webUI, "webui")
if err != nil {
return err
}
mux.Handle("/", http.FileServer(http.FS(ui)))
log.Printf("dashboard http://localhost%s (UART %s @ %d baud, poll %s, auto-reconnect)",
*addr, portName, baud, interval.String())
return http.ListenAndServe(*addr, mux)
}