Add list_clients WebSocket command to external API.
Lets API clients discover slave IDs and stream/notify flags before configuring per-slave accel or tap. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
f512936d97
commit
a85d48320e
@ -106,7 +106,19 @@ Tap polling runs only when at least one connection has `receive_tap: true` (via
|
|||||||
**Hello** (on connect; accel/tap receive off until `set_stream` / `set_tap_stream`):
|
**Hello** (on connect; accel/tap receive off until `set_stream` / `set_tap_stream`):
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{"type":"hello","serial_port":"/dev/ttyUSB0","interval_ms":16,"tap_display_min_ms":2000,"note":"set_tap_notify configures slave S/D/T only; set_tap_stream enables tap polling/push","commands":["set_stream","get_stream","set_accel_stream","get_accel_stream","set_tap_stream","get_tap_stream","set_tap_notify","get_tap_notify","set_led_ring","get_battery"]}
|
{"type":"hello","serial_port":"/dev/ttyUSB0","interval_ms":16,"tap_display_min_ms":2000,"note":"set_tap_notify configures slave S/D/T only; set_tap_stream enables tap polling/push","commands":["list_clients","set_stream","get_stream","set_accel_stream","get_accel_stream","set_tap_stream","get_tap_stream","set_tap_notify","get_tap_notify","set_led_ring","get_battery"]}
|
||||||
|
```
|
||||||
|
|
||||||
|
**List registered slaves** (UART `CLIENT_INFO`; use before per-slave `set_accel_stream` / `set_tap_notify`):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"type":"list_clients"}
|
||||||
|
```
|
||||||
|
|
||||||
|
Reply:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"type":"client_list","success":true,"clients":[{"id":16,"mac":"aa:bb:cc:dd:ee:10","version":1,"available":true,"used":true,"last_ping":1234,"last_success_ping":1200,"accel_stream":false,"tap_notify_single":false,"tap_notify_double":false,"tap_notify_triple":false}]}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Receive accel on this connection** (optional `interval_ms`, default from `-accel-interval`):
|
**Receive accel on this connection** (optional `interval_ms`, default from `-accel-interval`):
|
||||||
@ -192,6 +204,13 @@ import asyncio, json, websockets
|
|||||||
async def main():
|
async def main():
|
||||||
async with websockets.connect("ws://127.0.0.1:8081/ws") as ws:
|
async with websockets.connect("ws://127.0.0.1:8081/ws") as ws:
|
||||||
print(await ws.recv()) # hello
|
print(await ws.recv()) # hello
|
||||||
|
await ws.send(json.dumps({"type": "list_clients"}))
|
||||||
|
clients = json.loads(await ws.recv())["clients"]
|
||||||
|
for c in clients:
|
||||||
|
if not c.get("available"):
|
||||||
|
continue
|
||||||
|
await ws.send(json.dumps({"type": "set_accel_stream", "client_id": c["id"], "enable": True}))
|
||||||
|
print(await ws.recv()) # accel_stream_status
|
||||||
await ws.send(json.dumps({"type": "set_stream", "enable": True, "interval_ms": 16}))
|
await ws.send(json.dumps({"type": "set_stream", "enable": True, "interval_ms": 16}))
|
||||||
print(await ws.recv()) # stream_status
|
print(await ws.recv()) # stream_status
|
||||||
await ws.send(json.dumps({"type": "set_accel_stream", "client_id": 16, "enable": True}))
|
await ws.send(json.dumps({"type": "set_accel_stream", "client_id": 16, "enable": True}))
|
||||||
|
|||||||
@ -92,6 +92,29 @@ type TapStreamStatusMessage struct {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// APIClientInfo is one registered slave (or slot) from CLIENT_INFO.
|
||||||
|
type APIClientInfo struct {
|
||||||
|
ID uint32 `json:"id"`
|
||||||
|
MAC string `json:"mac"`
|
||||||
|
Version uint32 `json:"version"`
|
||||||
|
Available bool `json:"available"`
|
||||||
|
Used bool `json:"used"`
|
||||||
|
LastPing uint32 `json:"last_ping"`
|
||||||
|
LastSuccessPing uint32 `json:"last_success_ping"`
|
||||||
|
AccelStream bool `json:"accel_stream"`
|
||||||
|
TapNotifySingle bool `json:"tap_notify_single"`
|
||||||
|
TapNotifyDouble bool `json:"tap_notify_double"`
|
||||||
|
TapNotifyTriple bool `json:"tap_notify_triple"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClientListMessage is the reply to list_clients.
|
||||||
|
type ClientListMessage struct {
|
||||||
|
Type string `json:"type"` // "client_list"
|
||||||
|
Success bool `json:"success"`
|
||||||
|
Clients []APIClientInfo `json:"clients,omitempty"`
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// TapNotifyStatusMessage is the reply to set_tap_notify / get_tap_notify (slave).
|
// TapNotifyStatusMessage is the reply to set_tap_notify / get_tap_notify (slave).
|
||||||
type TapNotifyStatusMessage struct {
|
type TapNotifyStatusMessage struct {
|
||||||
Type string `json:"type"` // "tap_notify_status"
|
Type string `json:"type"` // "tap_notify_status"
|
||||||
@ -191,6 +214,7 @@ func (h *accelStreamHub) register(conn *websocket.Conn, portName string) *wsSubs
|
|||||||
TapDisplayMinMs: apiTapDisplayMinMs,
|
TapDisplayMinMs: apiTapDisplayMinMs,
|
||||||
Note: "set_tap_notify configures slave S/D/T only; set_tap_stream enables tap polling/push",
|
Note: "set_tap_notify configures slave S/D/T only; set_tap_stream enables tap polling/push",
|
||||||
Commands: []string{
|
Commands: []string{
|
||||||
|
"list_clients",
|
||||||
"set_stream", "get_stream", "set_accel_stream", "get_accel_stream",
|
"set_stream", "get_stream", "set_accel_stream", "get_accel_stream",
|
||||||
"set_tap_stream", "get_tap_stream", "set_tap_notify", "get_tap_notify",
|
"set_tap_stream", "get_tap_stream", "set_tap_notify", "get_tap_notify",
|
||||||
"set_led_ring", "get_battery",
|
"set_led_ring", "get_battery",
|
||||||
@ -584,6 +608,30 @@ func writeTapStreamStatus(conn *websocket.Conn, msg TapStreamStatusMessage) {
|
|||||||
_ = conn.WriteMessage(websocket.TextMessage, data)
|
_ = conn.WriteMessage(websocket.TextMessage, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func clientInfoToAPI(c *pb.ClientInfo) APIClientInfo {
|
||||||
|
return APIClientInfo{
|
||||||
|
ID: c.GetId(),
|
||||||
|
MAC: formatMAC(c.GetMac()),
|
||||||
|
Version: c.GetVersion(),
|
||||||
|
Available: c.GetAvailable(),
|
||||||
|
Used: c.GetUsed(),
|
||||||
|
LastPing: c.GetLastPing(),
|
||||||
|
LastSuccessPing: c.GetLastSuccessPing(),
|
||||||
|
AccelStream: c.GetAccelStreamEnabled(),
|
||||||
|
TapNotifySingle: c.GetTapNotifySingle(),
|
||||||
|
TapNotifyDouble: c.GetTapNotifyDouble(),
|
||||||
|
TapNotifyTriple: c.GetTapNotifyTriple(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeClientList(conn *websocket.Conn, msg ClientListMessage) {
|
||||||
|
data, err := json.Marshal(msg)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_ = conn.WriteMessage(websocket.TextMessage, data)
|
||||||
|
}
|
||||||
|
|
||||||
func writeTapNotifyStatus(conn *websocket.Conn, out tapNotifyAPIResponse) {
|
func writeTapNotifyStatus(conn *websocket.Conn, out tapNotifyAPIResponse) {
|
||||||
msg := TapNotifyStatusMessage{
|
msg := TapNotifyStatusMessage{
|
||||||
Type: "tap_notify_status",
|
Type: "tap_notify_status",
|
||||||
@ -640,6 +688,25 @@ func handleAccelWSCommand(conn *websocket.Conn, sub *wsSubscriber, data []byte,
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch cmd.Type {
|
switch cmd.Type {
|
||||||
|
case "list_clients":
|
||||||
|
clients, err := link.listClientsPoll()
|
||||||
|
if err != nil {
|
||||||
|
writeClientList(conn, ClientListMessage{
|
||||||
|
Type: "client_list",
|
||||||
|
Error: err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
out := make([]APIClientInfo, 0, len(clients))
|
||||||
|
for _, c := range clients {
|
||||||
|
out = append(out, clientInfoToAPI(c))
|
||||||
|
}
|
||||||
|
writeClientList(conn, ClientListMessage{
|
||||||
|
Type: "client_list",
|
||||||
|
Success: true,
|
||||||
|
Clients: out,
|
||||||
|
})
|
||||||
|
|
||||||
case "set_stream":
|
case "set_stream":
|
||||||
if cmd.Enable == nil {
|
if cmd.Enable == nil {
|
||||||
writeStreamStatus(conn, StreamStatusMessage{
|
writeStreamStatus(conn, StreamStatusMessage{
|
||||||
@ -791,7 +858,7 @@ func handleAccelWSCommand(conn *websocket.Conn, sub *wsSubscriber, data []byte,
|
|||||||
default:
|
default:
|
||||||
writeStreamStatus(conn, StreamStatusMessage{
|
writeStreamStatus(conn, StreamStatusMessage{
|
||||||
Type: "stream_status",
|
Type: "stream_status",
|
||||||
Error: "unknown type (set_stream, get_stream, set_accel_stream, get_accel_stream, set_tap_stream, get_tap_stream, set_tap_notify, get_tap_notify, set_led_ring, get_battery)",
|
Error: "unknown type (list_clients, set_stream, get_stream, set_accel_stream, get_accel_stream, set_tap_stream, get_tap_stream, set_tap_notify, get_tap_notify, set_led_ring, get_battery)",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user