Python scripts
Read distance, calibrate a pair, and save CSVs from a terminal. These tools collect TWR distance, not Location position records.
Setup
- Install Python 3.10 or newer.
- Download all scripts and extract the ZIP into a folder named
opentags-host-scripts. - Open a terminal in that folder. Keep the scripts together; they share
opentag_serial.py.
On macOS or Linux:
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install -r requirements.txt
Windows PowerShell
py -3 -m venv .venv
.venv\Scripts\python.exe -m pip install -r requirements.txt
.venv\Scripts\python.exe list_ports.pyFor subsequent commands, use .venv\Scripts\python.exe instead of python3 and your device's COM port.
Disconnect the tag from the browser or ROS 2 first. Run python3 list_ports.py and replace every example path below with the actual responder port: macOS often uses /dev/cu.usbmodem…, Linux /dev/ttyACM0, and Windows COM3. The initiator must stay powered.
Download all scripts · requirements.txt · opentag_serial.py
python3 list_ports.pyRead device info
Requests role, firmware, ID, PHY, counters, and calibration. By default it restores this computer's saved responder offset, waits for acknowledgement, and reads INFO again.
Download info.pypython3 info.py /dev/tty.usbmodem1101
# Inspect the boot value without restoring a saved offset:
python3 info.py /dev/tty.usbmodem1101 --no-restorepython3 monitor.py /dev/tty.usbmodem1201
python3 monitor.py /dev/tty.usbmodem1201 --csv live.csvCalibrate a pair
Uses the responder stream, trims the outer 10%, writes the new DTU offset, and saves it by hardware ID.
Download calibrate.pypython3 calibrate.py /dev/tty.usbmodem1201 \
--true-mm 1000 --samples 100 --timeout 30The firmware command changes RAM. The script saves the offset only after the device acknowledges it. It stops if the requested samples do not arrive within the timeout. Saved values live in ~/.config/opentags/calibration.json; info, monitor, and static-test tools restore them when connecting to the same responder. Browser storage is separate.
Run a static test
Collects a timed responder stream and writes metadata, summary metrics, every sample, exchange time, and RSSI.
Download static_test.pypython3 static_test.py /dev/tty.usbmodem1201 \
--true-mm 5000 --seconds 60 --output test-5m.csvThe output is written in the current directory unless you choose another path. The CSV contains metadata, summary, and sample sections; it is not one flat table. Rate and packet-success values use the legacy sample-window estimates and can hide long outages. Record interruptions separately; see measurement limitations.
Flash firmware
Optional macOS/Linux Bash workflow. Requires dfu-util and curl or wget; requirements.txt does not install them. The script downloads the current distance-role image. Connect only the device you intend to flash. For the browser workflow, follow the quickstart.
chmod +x flash.sh
./flash.sh initiator
./flash.sh responderThe downloaded image contains the default offset. Run calibrate.py, or reconnect through the browser console, after flashing the responder.
A nonzero dfu-util result leaves completion unconfirmed, even if the device reset at the end. Reconnect normally and check INFO before assuming the expected image is installed.
If a script stops or waits
Confirm the selected port is the responder, close competing serial readers, and keep the initiator powered. Use --help for each script's options. Stop monitoring with Ctrl+C. A calibration timeout or missing acknowledgement is a failed operation, not a saved calibration.