- Python 100%
| proto | ||
| tests | ||
| .gitignore | ||
| __init__.py | ||
| AGENTS.md | ||
| ble_protocol.py | ||
| ble_replayer.py | ||
| messages.json | ||
| README.md | ||
| receiver.py | ||
| recorder.py | ||
| recording_store.py | ||
| replayer.py | ||
| requirements.txt | ||
ScStw protocol recorder and replayer
These small Python tools inspect, record, and replay ScStw protobuf traffic over
UDP or Bluetooth Low Energy (BLE). Recordings are stored in messages.json and
retain their original timing.
Setup
Python 3.12 or newer is recommended. From the repository root, create an environment and install the UDP and BLE dependencies:
python -m venv venv
source venv/bin/activate
python -m pip install -r requirements.txt
protobuf decodes messages, bleak connects to the timer while recording, and
bless exposes the timer service while replaying.
UDP
python receiver.py
python recorder.py --transport udp
python replayer.py
receiver.py listens on 0.0.0.0:4999. The UDP recorder captures complete
SocketMessage datagrams on that port. The replayer sends a selected UDP
recording to 127.0.0.1:4999 with the captured timing. Running
python recorder.py without --transport opens an interactive transport
prompt.
Record Bluetooth traffic
python recorder.py --transport bluetooth
python recorder.py --transport bluetooth --device IDENTIFIER --scan-timeout 15
The recorder scans for the ScStw timer service, prompts when multiple devices
match, and connects as a BLE central. --device selects a known platform
identifier or address; --scan-timeout controls device discovery time.
On connection it reads and records the initial RaceFullState, Settings, and
optional SystemInfo characteristic values before capturing notifications.
Stop with Ctrl+C to save the session.
Replay Bluetooth traffic
Run python replayer.py, select Bluetooth, then choose a mode and recording.
The replayer advertises a BLE peripheral named ScStw and waits for a client.
Initial reads return the recorded starting values; subsequent
characteristic notifications follow the original timeline. This lets the Web
Bluetooth client connect and initialize in the same way it does with a timer.
BLE peripheral replay supports Linux through BlueZ and macOS through
CoreBluetooth. On Linux, the user must be allowed to register GATT services and
advertisements, and the adapter must expose BlueZ's GattManager1 and
LEAdvertisingManager1 interfaces. On macOS, enable Bluetooth and grant
Bluetooth access to the terminal or IDE running Python in System Settings under
Privacy & Security > Bluetooth. Test with a Web Bluetooth-capable browser on a
second physical device; a host generally cannot connect to its own
advertisement.
Recording format
messages.json separates recordings by transport, then by mode. UDP and
Bluetooth can therefore use the same mode and recording names without replacing
one another:
{
"udp": {
"Single, two lanes": [{
"name": "Example race",
"recording": [{"data": "0a081202220012022200", "time": 0.12}]
}]
},
"bluetooth": {
"Single, two lanes": [{
"name": "Example race",
"recording": [{
"data": "0a03120100",
"time": 0.12,
"characteristic_uuid": "97ed638a-690f-4ce4-bb12-d9c4e0010001",
"source": "initial_read"
}]
}]
}
}
The top-level key is authoritative; canonical recording entries omit redundant
transport metadata. Legacy mode-first files (for example,
{ "Single, two lanes": [...] }) are accepted and automatically partitioned
using each entry's old transport value. Unmarked entries default to UDP, and
legacy metadata is stripped during normalization, so no manual migration is
needed.
For every event, data is lowercase, even-length hexadecimal and time is
nonnegative elapsed seconds. BLE events additionally identify their
characteristic_uuid; source is initial_read or notification. Race state
(...0001) and settings (...0003) have required initial reads; system info
(...0004) is optional. Control (...0002) is write-only and is not recorded.
This lets replay preload readable values without emitting them as notifications.
Keep messages.json changes focused: it is both the fixture collection and the
recorder output.