Bridges F1 MultiViewer live timing to Meross smart bulbs.
When the safety car comes out, your room knows before the commentators finish their sentence.
iot-pitwall subscribes to MultiViewer's GraphQL live timing feed and translates track status changes into real-time lighting effects on Meross Wi-Fi bulbs. Green flag, yellow flag, red flag, safety car, VSC — each state triggers a distinct strobe pattern tuned to minimize perceived latency without overwhelming the bulb's command queue.
iotpitwall.mp4
| Track Status | Bulb Behavior |
|---|---|
| Green / Clear | 4 fast green flashes, then off |
| Yellow | Continuous amber strobe loop |
| Safety Car | Continuous amber strobe loop |
| Virtual Safety Car | Continuous amber strobe loop |
| VSC Ending | Alternating yellow/green fast strobes |
| Red Flag | 10 rapid red flashes, then solid red |
Transport is WebSocket-first with automatic subprotocol negotiation (graphql-transport-ws → Apollo → bare). Falls back to HTTP polling if WebSocket upgrade is unavailable.
- Python 3.10+
- MultiViewer 2.x running locally with a live timing or replay session active
- A Meross account and a compatible RGB bulb (tested on MSL120DR)
git clone https://github.com/eftekin/iot-pitwall.git
cd iot-pitwall
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txtCopy the example and fill in your credentials:
cp .env.example .envRequired:
MEROSS_EMAIL=your-email@example.com
MEROSS_PASSWORD=your-passwordDevice targeting — use UUID to avoid ambiguity:
python tools/find_devices.pyMEROSS_DEVICE_UUID=your-device-uuidFull reference:
| Variable | Default | Description |
|---|---|---|
MEROSS_EMAIL |
— | Meross account email (required) |
MEROSS_PASSWORD |
— | Meross account password (required) |
MEROSS_DEVICE_UUID |
— | Target bulb UUID (recommended) |
MEROSS_DEVICE_NAME |
— | Target bulb name (fallback) |
MEROSS_DEVICE_TYPE |
— | Device type filter, e.g. msl120dr |
MVF1_TRANSPORT |
auto |
auto, websocket, or http_poll |
MVF1_GRAPHQL_WS_URL |
ws://localhost:10101/api/graphql |
MultiViewer WebSocket endpoint |
MVF1_GRAPHQL_HTTP_URL |
(derived from WS URL) | MultiViewer HTTP endpoint |
GQL_WEBSOCKET_SUBPROTOCOL |
auto |
auto, graphql-transport-ws, graphql-ws |
HTTP_POLL_INTERVAL_SECONDS |
2.0 |
Poll interval when WebSocket is unavailable |
STROBE_ON_SECONDS |
0.15 |
Bulb on-time per strobe cycle |
STROBE_OFF_SECONDS |
0.15 |
Bulb off-time per strobe cycle |
MEROSS_MIN_COMMAND_INTERVAL |
0.1 |
Minimum gap between bulb commands |
RECONNECT_MIN_SECONDS |
1.0 |
Initial reconnect backoff |
RECONNECT_MAX_SECONDS |
60.0 |
Maximum reconnect backoff cap |
Strobe timing note: Values below ~0.3 s may cause bulb firmware to drop commands. The defaults are intentionally aggressive for responsiveness — increase if you observe missed flashes.
python run.pyMultiViewer must be running with a live or replay timing session active. Replay sessions behave identically to live — useful for tuning strobe timing without waiting for a race weekend.
Logging is minimal by default: pitwall.* logs at INFO, everything else at WARNING. The Meross SDK is silenced to CRITICAL.
run.py
└── pitwall/
├── __init__.py Async entrypoint and consume loop
├── listener.py GraphQL client — emits TrackStatus to a shared queue
├── controller.py Meross bulb effects with rate-limited command queue
└── config.py Settings loaded from environment variables
The listener and controller run as concurrent asyncio tasks sharing a queue. Status changes are deduplicated — the same status won't re-trigger an effect until a different one is received. Effect tasks are cancellable: a new status preempts the current strobe loop with a short transition buffer.
- Requires MultiViewer 2.x or later. The
liveTimingStatefield was deprecated in favor off1LiveTimingStatein recent builds — the listener handles both. - Meross commands route through the cloud by default. Local LAN control is not used. Keep this in mind if your internet connection is unreliable during races.
- If the bulb stops responding mid-session, increase
MEROSS_MIN_COMMAND_INTERVALandSTROBE_ON/OFF_SECONDSto reduce command frequency.
Issues and pull requests are welcome. Please open an issue first for significant changes.
MIT. See LICENSE.