System Architecture
This page decomposes GroupLoop into services and protocols so you can understand how sensor frames, commands, and UI flows move through the stack.
Logical View
flowchart TD
subgraph Infra
Docker[Docker Compose]
end
subgraph Backend
Socket[Socket Server\nPython + websockets]
Docs[Docs\nMkDocs]
end
subgraph Frontend
Hub[Client Hub\nFlask + static apps]
Apps[Apps\np5.js, dashboards, games]
Vendor[Vendor libs\nHitloopDevice*]
end
subgraph Devices
FW[ESP32 Firmware]
end
Docker --> Socket
Docker --> Hub
Docker --> Docs
FW <--> Socket
Apps -- served by --> Hub
Apps --> Vendor
Apps <--> Socket
Data plane
- Devices emit fixed-length hex frames containing ID, IMU, distance sensors, and tap flag.
- Socket server fans out frames over WebSocket to any connected browser clients.
- Browser apps use HitloopDeviceManager to manage connections, validate commands against commands.json, and send back cmd:<id>:<command>:... strings.
- Firmware CommandRegistry executes the parsed commands and updates LEDs, vibration motors, or configuration.
Control plane
- ProcessManager in firmware starts/stops processes (BLE scanning, IMU sampling, Wi‑Fi, LED behaviors) based on connectivity state.
- Client hub auto-discovers app folders; landing page renders READMEs and links.
Component Responsibilities
- Socket server: stateless relay, validates frame length/charset, binds on configurable host/port.
- Client hub: serves static apps, exposes
/config.jswithWS_DEFAULT_URL,CDN_BASE_URL, andDEFAULT_APP. - Hitloop games:
SceneManagerroutes key presses to the activeScene, whileHitloopDeviceManagerkeeps device state fresh and prunes inactive devices. - Firmware: shares a single
WebSocketManagerfor outbound commands and inbound frames;Processsubclasses isolate concerns (LED, vibration, IMU, BLE).
Message Formats
erDiagram
FRAME {
string idHex "4 hex chars"
uint8 ax "0-255"
uint8 ay
uint8 az
uint8 dNW
uint8 dNE
uint8 dSE
uint8 dSW
uint8 tap "255=true, 0=false"
}
COMMAND {
string idHex "device target"
string name "e.g. led, vibrate"
string params "colon-delimited"
}
Keep the frames tight
Frames are sliced to 20 hex characters before parsing. If you add fields, align client and firmware parsers and update commands.json plus any data visualizations.