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() 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) }