Serve starts without a required port; REST/WS/UI can scan and switch transports, with BLE live ticks and UART-only OTA. Co-authored-by: Cursor <cursoragent@cursor.com>
76 lines
1.9 KiB
Go
76 lines
1.9 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"powerpod/gotool/pb"
|
|
|
|
"google.golang.org/protobuf/proto"
|
|
)
|
|
|
|
// accelSamplesFromCacheStatus maps combined CACHE_STATUS entries to AccelSample
|
|
// (for dashboard / WebSocket accel push).
|
|
func accelSamplesFromCacheStatus(r *pb.CacheStatusResponse) []*pb.AccelSample {
|
|
if r == nil {
|
|
return nil
|
|
}
|
|
out := make([]*pb.AccelSample, 0, len(r.GetClients()))
|
|
for _, c := range r.GetClients() {
|
|
if c.GetAccel() == nil {
|
|
continue
|
|
}
|
|
a := c.GetAccel()
|
|
out = append(out, &pb.AccelSample{
|
|
ClientId: c.GetClientId(),
|
|
Valid: a.GetValid(),
|
|
X: a.GetX(),
|
|
Y: a.GetY(),
|
|
Z: a.GetZ(),
|
|
AgeMs: a.GetAgeMs(),
|
|
})
|
|
}
|
|
return out
|
|
}
|
|
|
|
// tapEventsFromCacheStatus maps combined CACHE_STATUS entries to TapEvent
|
|
// (only clients with a consumed pending tap).
|
|
func tapEventsFromCacheStatus(r *pb.CacheStatusResponse) []*pb.TapEvent {
|
|
if r == nil {
|
|
return nil
|
|
}
|
|
out := make([]*pb.TapEvent, 0, len(r.GetClients()))
|
|
for _, c := range r.GetClients() {
|
|
if c.GetTap() == nil {
|
|
continue
|
|
}
|
|
t := c.GetTap()
|
|
out = append(out, &pb.TapEvent{
|
|
ClientId: c.GetClientId(),
|
|
Valid: true,
|
|
Kind: t.GetKind(),
|
|
AgeMs: t.GetAgeMs(),
|
|
})
|
|
}
|
|
return out
|
|
}
|
|
|
|
// cacheStatusFromBLEStreamPayload parses a framed BLE_STREAM_TICK payload
|
|
// (type byte + protobuf UartMessage) into a CacheStatusResponse-shaped view.
|
|
func cacheStatusFromBLEStreamPayload(payload []byte) (*pb.CacheStatusResponse, error) {
|
|
if len(payload) < 2 {
|
|
return nil, fmt.Errorf("BLE stream tick too short")
|
|
}
|
|
if payload[0] != byte(pb.MessageType_BLE_STREAM_TICK) {
|
|
return nil, fmt.Errorf("unexpected BLE tick type 0x%02x", payload[0])
|
|
}
|
|
var msg pb.UartMessage
|
|
if err := proto.Unmarshal(payload[1:], &msg); err != nil {
|
|
return nil, err
|
|
}
|
|
tick := msg.GetBleStreamTick()
|
|
if tick == nil {
|
|
return nil, fmt.Errorf("missing ble_stream_tick")
|
|
}
|
|
return &pb.CacheStatusResponse{Clients: tick.GetClients()}, nil
|
|
}
|