Spaces:
Paused
Paused
|
Download README.md from secutorpro/dispatch-console: direct link, hf CLI and curl.
- Browser
- Download file 3.81 kB
-
https://huggingface.co/spaces/secutorpro/dispatch-console/resolve/main/README.md
- Command line
-
hf download hf://spaces/secutorpro/dispatch-console/README.md
-
curl -L -o README.md https://huggingface.co/spaces/secutorpro/dispatch-console/resolve/main/README.md
3.81 kB
| title: Dispatch Console | |
| emoji: πΊοΈ | |
| colorFrom: blue | |
| colorTo: green | |
| sdk: docker | |
| app_port: 8080 | |
| pinned: false | |
| # Dispatch Console | |
| A self-hostable PoC-style fleet dispatch console β in the spirit of platforms like Global-PTT's dispatch: a live map of members, SOS alert handling, group push-to-talk, and member/talkgroup management. One process, one SQLite file, no external services. | |
| ## Features | |
| - **Live map + GPS** β Leaflet/OpenStreetMap map, member markers colored by talkgroup, online/offline styling, SOS pulse, popup with battery and coordinates; devices push positions over WebSocket, every ping is stored for trails (`GET /api/members/:id/trail`) | |
| - **SOS alerts** β devices raise SOS, console shows a queue with Ack β Resolve flow and an audio alarm; state is broadcast to all consoles instantly | |
| - **Intercom / PTT** β talkgroups with floor control (one speaker per group); dispatcher holds a button to talk, mic is captured at 16 kHz via AudioWorklet and relayed as PCM over the same WebSocket; floor indicator shows who is talking; call log recorded | |
| - **Member management** β add/edit/remove members, assign talkgroups, see status/battery/last-seen; talkgroup list with colors | |
| ## Architecture | |
| ``` | |
| browser / devices | |
| β HTTPS (REST: members, groups, SOS, trails) | |
| β WSS /ws (GPS, SOS, PTT control, PCM audio frames) | |
| βΌ | |
| Node + Express ββ better-sqlite3 (dispatch.db) | |
| ββ ws Hub: auth, floor control per talkgroup, audio relay | |
| React + Vite + Leaflet frontend (served statically by the same process) | |
| ``` | |
| Binary audio frame on the WebSocket: | |
| `[1B type=0x01][4B groupId BE][4B memberId BE][Int16LE PCM @ 16 kHz]` | |
| Only the current floor holder of a talkgroup may transmit; the server drops audio from anyone else. | |
| ## Quickstart (Docker) | |
| ```bash | |
| docker compose up --build | |
| # open http://localhost:8080 β log in with admin / admin (change it) | |
| ``` | |
| ## Quickstart (dev) | |
| ```bash | |
| cd server && npm install && npm run dev # API + WS on :8080 | |
| cd web && npm install && npm run dev # Vite on :5173, proxied to :8080 | |
| ``` | |
| ## Simulated fleet | |
| With the server running, drive a fake fleet so you can see the console come alive: | |
| ```bash | |
| cd server && npm run sim | |
| # 5 units driving around Paris, one SOS after ~25 s, rotating PTT floor requests | |
| ``` | |
| ## Device integration | |
| A device (or backend integration) authenticates with a dispatcher JWT and identifies as a member: | |
| ```json | |
| {"type": "auth", "token": "<jwt>", "memberId": 12} | |
| ``` | |
| Then, per message: `{"type":"gps","lat":48.85,"lng":2.35,"speed":34,"battery":80}`, | |
| `{"type":"sos"}`, `{"type":"ptt_start"}`, `{"type":"ptt_stop"}`, | |
| and raw binary frames for audio (format above). | |
| ## Configuration | |
| | Env | Meaning | | |
| | --- | --- | | |
| | `PORT` | HTTP/WS port (default 8080) | | |
| | `DATA_DIR` | where `dispatch.db` and the JWT secret live (default `server/data`) | | |
| | `JWT_SECRET` | signing secret; generated and persisted on first run if unset | | |
| | `ADMIN_PASSWORD` | password for the first-run `admin` dispatcher | | |
| ## Limitations & next steps | |
| - **Device auth is trusted-by-JWT**: any valid token can claim any `memberId`. Production needs per-device credentials and revocation. | |
| - **Audio is uncompressed 16 kHz PCM relayed over WebSocket** β fine for small fleets on good links; swap in Opus + an SFU (LiveKit, mediasoup) for larger ones and lossy networks. | |
| - Single-node SQLite; horizontal scale would need Postgres and a Redis pub/sub fan-out. | |
| - Map tiles come from public OpenStreetMap servers β self-host tiles for production privacy. | |
| - No TLS in the container β terminate TLS at your reverse proxy (devices require WSS/HTTPS for mic access anyway). | |
| - On HF Spaces, storage is ephemeral: the SQLite file resets on rebuild (fine for demos; use a mounted volume or external DB for real data). |