103 lines
2.1 KiB
Go
103 lines
2.1 KiB
Go
package frontend
|
|
|
|
import (
|
|
"context"
|
|
"embed"
|
|
"io/fs"
|
|
"log"
|
|
"net/http"
|
|
"time"
|
|
|
|
"alox.tool/api"
|
|
"alox.tool/eventbus"
|
|
"github.com/gorilla/websocket"
|
|
)
|
|
|
|
//go:embed www
|
|
var staticFiles embed.FS
|
|
|
|
var upgrader = websocket.Upgrader{}
|
|
|
|
type FServer struct {
|
|
bus eventbus.EventBus
|
|
mux *http.ServeMux
|
|
}
|
|
|
|
func New(bus eventbus.EventBus) *FServer {
|
|
fsrv := &FServer{
|
|
bus: bus,
|
|
mux: http.NewServeMux(),
|
|
}
|
|
fsrv.routes()
|
|
return fsrv
|
|
}
|
|
|
|
func (fsrv *FServer) routes() {
|
|
// Statische Dateien aus dem Embed-FS
|
|
// "www" Präfix entfernen, damit index.html unter / verfügbar ist
|
|
root, _ := fs.Sub(staticFiles, "www")
|
|
fsrv.mux.Handle("/", http.FileServer(http.FS(root)))
|
|
|
|
// WebSocket Endpunkt
|
|
fsrv.mux.HandleFunc("/ws", fsrv.handleWS)
|
|
}
|
|
|
|
func (fsrv *FServer) handleWS(w http.ResponseWriter, r *http.Request) {
|
|
conn, err := upgrader.Upgrade(w, r, nil)
|
|
if err != nil {
|
|
log.Printf("Upgrade error: %v", err)
|
|
return
|
|
}
|
|
defer conn.Close()
|
|
|
|
// Kanäle für die Hardware-Events abonnieren
|
|
rxChan := fsrv.bus.Subscribe(api.TopicUARTRx)
|
|
txChan := fsrv.bus.Subscribe(api.TopicUARTTx)
|
|
|
|
// Context nutzen, um Goroutinen zu stoppen, wenn die Verbindung abreißt
|
|
ctx, cancel := context.WithCancel(r.Context())
|
|
defer cancel()
|
|
|
|
// WRITER: Send Events to Browser
|
|
go func() {
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
case f := <-rxChan:
|
|
if err := conn.WriteJSON(map[string]any{"type": "rx", "frame": f}); err != nil {
|
|
return
|
|
}
|
|
case f := <-txChan:
|
|
if err := conn.WriteJSON(map[string]any{"type": "tx", "frame": f}); err != nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
|
|
// READER: Commands from Browser
|
|
for {
|
|
var cmd api.FrontendCmd
|
|
if err := conn.ReadJSON(&cmd); err != nil {
|
|
log.Printf("WS Read Error: %v", err)
|
|
break
|
|
}
|
|
|
|
fsrv.bus.Publish(api.TopicFrontendCmd, cmd)
|
|
log.Printf("Browser Action: %s auf ID 0x%02X", cmd.Action, cmd.ID)
|
|
}
|
|
}
|
|
|
|
func (fsrv *FServer) Start(addr string) error {
|
|
server := &http.Server{
|
|
Addr: addr,
|
|
Handler: fsrv.mux,
|
|
ReadTimeout: 5 * time.Second,
|
|
WriteTimeout: 10 * time.Second,
|
|
}
|
|
|
|
log.Printf("Frontend Server gestartet auf %s", addr)
|
|
return server.ListenAndServe()
|
|
}
|