Documentation / Integrate / Python scripts

Python scripts

Read distance, calibrate a pair, and save CSVs from a terminal. These tools collect TWR distance, not Location position records.

Setup

  1. Install Python 3.10 or newer.
  2. Download all scripts and extract the ZIP into a folder named opentags-host-scripts.
  3. 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.py

For 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

Discover ports

Lists serial paths, descriptions, and hardware identifiers.

Download list_ports.py
python3 list_ports.py

Read 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.py
python3 info.py /dev/tty.usbmodem1101
# Inspect the boot value without restoring a saved offset:
python3 info.py /dev/tty.usbmodem1101 --no-restore

Monitor live distance

Prints live range and RSSI. Add --csv for a flat log.

Download monitor.py
python3 monitor.py /dev/tty.usbmodem1201
python3 monitor.py /dev/tty.usbmodem1201 --csv live.csv

Calibrate a pair

Uses the responder stream, trims the outer 10%, writes the new DTU offset, and saves it by hardware ID.

Download calibrate.py
python3 calibrate.py /dev/tty.usbmodem1201 \
  --true-mm 1000 --samples 100 --timeout 30
Persistence

The 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.py
python3 static_test.py /dev/tty.usbmodem1201 \
  --true-mm 5000 --seconds 60 --output test-5m.csv

The 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.

Download flash.sh
chmod +x flash.sh
./flash.sh initiator
./flash.sh responder
Responder calibration

The 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.