- C++ 70%
- Python 24%
- C 5.6%
- Batchfile 0.2%
- CMake 0.2%
|
All checks were successful
Build Fuel Server Image / build (push) Successful in 18s
With maxsize=1, when two daemons sent telemetry simultaneously to a shared queue, only one daemon's message fit — the other was silently dropped via queue.Full. This starved one daemon's data from reaching consumers. The Channels class now accepts a configurable maxsize (default 1 for single-daemon Client compatibility). The Server uses maxsize=200 to buffer interleaving frames from multiple daemons without dropping them. |
||
|---|---|---|
| .forgejo/workflows | ||
| iro_daemon | ||
| irsdk_1_20 | ||
| tests | ||
| .dockerignore | ||
| .gitignore | ||
| Dockerfile | ||
| fuel_server.py | ||
| iro.py | ||
| iro_protocol.py | ||
| PROTOCOL.md | ||
| README.md | ||
| server_test.py | ||
| web_test_client.py | ||
iRO - iRacing Telemetry Daemon & Protocol
iRO is a Windows system-tray daemon that reads live telemetry from iRacing shared memory and streams it over TCP to remote applications. It also exposes a local endpoint for unfiltered dashboard-style access.
How It Works
┌──────────┐ shared memory ┌──────────────┐ TCP (42001) ┌──────────────┐
│ iRacing │ ────────────────────── │ iro_daemon │ ─────────────────► │ Your App │
│ (sim) │ Local\IRSDKMemMap* │ (bridge) │ filtered vars │ (server) │
└──────────┘ │ │ + YAML sections └──────────────┘
│ │
│ TCP (42002) │ ┌──────────────┐
│ ◄─────────── │ │ Dashboard │
│ unfiltered │ │ (browser) │
│ all vars │ └──────────────┘
└──────────────┘
Route A — Remote server (port 42001): The daemon connects outbound as a TCP client. Your application listens as a TCP server. You send a filter list of variable names you care about; the daemon sends back only those variables at ~60 Hz as compressed float32 frames. You can also request specific YAML sections from the session info (track, drivers, weather, etc.) instead of the full ~100 KB blob.
Route B — Local clients (port 42002): The daemon listens on loopback as a TCP server. Connect and receive every iRacing variable, unfiltered, plus the full session YAML. The reference dashboard (web_test_client.py) uses this.
Build
Real daemon
cd iro_daemon
build.bat → x64\Release\iro_daemon.exe
Test daemon (SDK stub)
cd tests
build_test_daemon.bat → build\iro_daemon_test.exe
The test daemon links against irsdk_stub.cpp instead of the real irsdk_utils.cpp. The stub fakes 27 telemetry variables and session YAML so no iRacing installation is needed.
Run
iro_daemon.exe [server_host] [server_port] [local_port]
# defaults:
iro_daemon.exe → 127.0.0.1:42001 :42002
iro_daemon.exe 192.168.1.5 42001 42002 → explicit
server_host:server_port— where the daemon connects as a TCP clientlocal_port— where the daemon listens for local dashboard connections
The daemon runs silently in the system tray. Right-click → Exit to stop.
Protocol
All communication uses raw TCP with little-endian binary messages. Five message types:
| ID | Name | Direction | Purpose |
|---|---|---|---|
0x01 |
MSG_FILTER_LIST |
Server → Daemon | Subscribe to specific telemetry variables |
0x02 |
MSG_TELEMETRY |
Daemon → Server | 60 Hz telemetry frame (~7 + 4N bytes) |
0x03 |
MSG_SESSION_INFO |
Daemon → Local only | Full session YAML (port 42002 only) |
0x04 |
MSG_SESSION_FILTER |
Server → Daemon | Request specific YAML sections |
0x05 |
MSG_SESSION_DATA |
Daemon → Server | Filtered YAML sections |
Full spec is in PROTOCOL.md. The reference implementations in server_test.py and web_test_client.py show working Python send/receive for every message type.
Test Suite
python -m tests.run_tests # all 50 tests (~45 s)
python -m tests.run_tests --protocol # protocol-only, no daemon needed
The suite covers:
- Protocol (24 tests) — every message type roundtrip, little-endian byte order, truncation detection
- Remote interface (8 tests) — daemon connects to server, accepts filter subscriptions, disconnects/reconnects, retries when server is down
- Local interface (12 tests) — client receives init messages, telemetry frames, session YAML; multiple concurrent clients; tick monotonicity; value sanity checks
- Connection lifecycle (6 tests) — clean start/stop, port release, garbage data resilience, rapid disconnect cycles, loopback-only binding
All daemon tests use the C++ SDK stub — no iRacing required.
Reference Scripts
| Script | Role |
|---|---|
server_test.py |
TCP server on port 42001. Sends filter lists, receives & logs telemetry and session data. |
web_test_client.py |
TCP client on port 42002. Serves a real-time HTML dashboard at http://127.0.0.1:8080 via Server-Sent Events. |
python server_test.py --port 42001 --filters Speed,RPM,Gear
python web_test_client.py --daemon-port 42002 --http-port 8080