System topology
Device (Android/iOS/Arduino/RPi)
└─ WebSocket ──► Soketi (Pusher-compatible)
└─ private-device.{imei}
├─ tad101.* events ──► TAD101 driver
└─ tad101.cmd.* ◄────── Command busChannel taxonomy
| Channel | Purpose | Auth |
|---|---|---|
tad101.device.{imei} | Per-device telemetry + command bus | Private, device secret |
admin.devices | Filament admin map feed | Private, admin |
tenant.{tenant_id}.devices | Tenant portal feed | Private, tenant |
user.{user_id}.devices | End-user app feed | Private, user |
tad101.commands | Admin observability mirror | Public |
Authentication flow
1. Device POST /api/tad101/auth { imei, secret }
2. Server validates secret → issues Soketi channel auth token
3. Device subscribes to private-device.{imei}
4. Telemetry pushed as tad101.telemetry eventsSoketi configuration
TAD101 reuses the same Soketi instance that powers Laravel broadcasting. Set PUSHER_* values for both Laravel and the Docker Compose soketi service — Laravel ships a config that maps to those env vars automatically.
.env
# Soketi / Pusher-compatible broadcaster
PUSHER_APP_ID=tad101
PUSHER_APP_KEY=tad101_key
PUSHER_APP_SECRET=change-in-production
PUSHER_HOST=soketi
PUSHER_PORT=6001
PUSHER_SCHEME=http
PUSHER_APP_CLUSTER=mt1
# TAD101 wiring
TAD101_SERVER_HOST=fleet.yourdomain.com
TAD101_WS_URL=wss://fleet.yourdomain.com
TAD101_WEBHOOK_SECRET=<hex32>REST fallback
Devices that cannot keep a long-lived WebSocket open may POST the same envelope to /api/tad101/inbound with the device secret as a bearer token. The envelope shape is identical — see Message Envelope.
