Skip to content

Theseus RTLS field test ​

Approved: 22 October 2026

A guided test a hospital tester runs with one watch and an Android phone. He walks the floor, presses the watch button, sees where SafeCall thinks he is, and answers Yes or No. On No he taps where he really is. The box records everything needed to answer three questions:

  • A. Which tracking algorithm is the most accurate on this site?
  • B. Where do the algorithms fail (rooms without a gateway, doorways, corridors, open halls, sector borders)?
  • C. What would make them better? The raw stream is replayable offline through any algorithm, including new ones.

The first site is floor 2NP of the CEDR psychiatric building (RTLS map 9, sectors 2A–2D). Some of the code is specific to that floor. Any other floor falls back to a generic classification.

How the test runs ​

  1. An admin on the hospital VPN opens Mobile Access and goes to the RTLS field test card. They pick the test watch, which must be a spare, silenced watch, and generate a QR. The QR is valid for 12 h by default (at most 72 h) and can be revoked.
  2. The tester installs Theseus from the Play Internal track. On the unlock screen he taps Scan the test QR. The app opens straight into the testing tool. It does not need the Wantok passphrase and it does not show the ops inbox. The QR and the locked watch survive closing the app.
  3. He locks the watch. He can either pick it from the list or press its button (identify by pressing).
  4. He says which sectors he can enter and whether patient rooms are OK, then picks a duration. The default is 30 minutes.
  5. Warm-up, about 2 minutes: he walks a corridor while every algorithm warms up.
  6. Tasks. The phone names a target and highlights it on the floor plan, for example "Go to: 2B · Pokoj 5". He taps I'm there. A countdown covers both the dwell and the cooldown. Then the phone tells him to press. Tasks rotate through these kinds:
    • settled: stand still for 20 s, then press;
    • arrival: press right away;
    • doorway: stand half in the room;
    • walking: press while walking a corridor.
  7. Verify. The phone shows the zone SafeCall reported, by name and on the map. He answers Yes or No. On No, he taps his position or chooses I'm at the target. He can change the answer for 10 s.
  8. He can skip a target (closed, occupied, not found) or mark a whole sector as closed. He can end the session whenever he likes. When the planned time is up, the phone suggests ending.

The tester only ever sees directions and simple questions. Every text comes from the box in Czech and English, so the protocol can change without an app release.

Architecture ​

Theseus ──HTTPS──▶ rtls-relay (updates.wantok.cz/rtls) ◀──HTTPS, outbound only── SafeCall box
renders the view    one mailbox per QR:                                          shadow + press capture
sends actions       state · actions · blobs                                      + session engine + files
  • Why a relay. The box sits behind the hospital VPN, so the phone cannot reach it. The box can already reach updates.wantok.cz, which the hospital's IT has cleared. The relay (guide) is a mailbox that cannot read what passes through it:

    • The box publishes one versioned view.
    • The phone long-polls the view and posts actions.
    • The box long-polls the actions.
    • The floor image and layout travel as blobs, addressed by hash.

    The relay purges a channel 1 h after the channel expires or is revoked.

  • Contracts.

  • Box auth. The box registers a channel with the bug-collector fleet secret it already has. After that it uses a per-channel box token. The phone uses the per-channel phone token from the QR. The relay stores only hashes.

  • Box transport. The box calls out with curl, not Bun fetch, because Bun's TLS client fails behind some EDR products.

Comparing algorithms without touching the hospital ​

The live algorithm is never switched. A switch wipes the zone of every watch in the hospital and changes what real SOS alerts report.

  • Shadow. For the locked test watch only, the box runs every catalog algorithm side by side. Legacy zone_voting is included through its pure port. All algorithms share the stepping code with the offline replay, so a session replays exactly.
  • Snapshot at each press. At every press the box records:
    • SafeCall's live answer, read the way an SOS reads it, plus %LOCATION_RECENT%;
    • every shadow algorithm's answer and debug object.
  • The "API switch". It only changes which algorithm's answer the tester sees. The options are production (default), one fixed algorithm, or rotating through all of them. The admin changes it on Zones → Debug → Field tests or with POST /api/v1/rtls-test/sessions/:id/display.

Safety ​

  • Silenced watches only. A QR is bound to 1–3 watches that are active, have every button action off (Single, Double, Long) and have KISS off. "Silenced" is judged on the same cache entry the SOS path uses.
  • If a watch stops being silenced mid-test, the session ends and the phone shows STOP – do not press.
  • Zabbix bridge. When the bridge feature is on (the SafeCall default), Zabbix records every press whatever the actions say, and the box cannot see whether anyone acts on it. The card then shows a warning and a box: The staff who watch Zabbix know that presses of the test watch are a test. The admin ticks it for each QR; without it the box refuses the mint. The QR keeps the answer (zabbix_ack, also in the mint's log line). A QR minted without it stops its session with STOP if the bridge is switched on later.
  • Watch still silenced after the test. If a test watch stays silenced once its QR has ended, the admin pages show a standing warning until its actions are switched back on. A silenced watch must not go back into service.
  • Data off the box. Only the bound watches' names and the locked watch's zones leave the box. Nothing about any other watch does.
  • Box load. Hooks into the MQTT and tracking path cost one map lookup when no test runs, and they never throw. Heavy work stays out of them. The service resumes 10 s after boot, so the nightly update restart is safe.

What is recorded ​

<server root>/rtls/field_tests/<session>.jsonl holds one line per event. It records:

  • every advert of the test watch that reached tracking (raw RSSI stream);
  • press-burst frames with per-gateway RSSI;
  • every answer change of the live algorithm and of each shadow algorithm, and the tracker lifecycle;
  • tasks, arrival taps (on the box clock), skips and closed sectors;
  • each press with all answers and what the tester was shown;
  • each answer with its truth zones and where the truth came from:
    • target: the task's target;
    • shown: the zone shown to the tester;
    • tap: the tester's tap on the map;
    • conflict: the tester said Yes, but the shown zone was not the target;
    • none: no truth.

Using the target as truth stops a Yes from favouring whichever algorithm was shown.

Reading the results ​

Zones → Debug → Field tests pools any set of sessions into one report. The same report is available at GET /api/v1/rtls-test/report?sessions=a,b.

For each algorithm the report gives:

  • exact accuracy with a 95 % interval;
  • adjacent, sector and kind accuracy;
  • the room → corridor count, which is the costly error;
  • lost answers and answers on another floor;
  • results split by measured press mode, sector, zone kind, and zones with or without a gateway;
  • separate results for doorway and walking presses;
  • dwell accuracy, accuracy in the first 30 s, convergence by the time of the press, and latency;
  • paired McNemar comparisons against production and against zone_voting_v2.

A winner is highlighted only with at least 30 scored presses and p < 0.05.

Offline replay uses the session files:

bash
cd tools/rtls-sim
bun tools/replay_field_test.ts session-a.jsonl session-b.jsonl --presses
bun tools/replay_field_test.ts session-a.jsonl --algs zone_voting_v2,my_new_alg --check

Operator checklist ​

  1. One time: set up the relay on the update host (OA-AT-rtls-relay, guide).
  2. Ship a Theseus build with the testing tool to Play Internal and add the tester's Google account (Theseus operator close-out).
  3. Make sure the box runs a SafeCall version with this feature. The nightly update installs it.
  4. On the box:
    • pick a spare watch;
    • switch off Single, Double, Long and KISS on it, and keep it active;
    • if the Zabbix bridge is on, tell the staff who watch Zabbix about the test, then tick the Zabbix box on the card;
    • mint the QR.
  5. After the test:
    • revoke the QR;
    • download the session files;
    • switch the watch's actions back on, or deactivate it.

Non-goals ​

This tool does not:

  • switch the live algorithm;
  • silence any watch from code;
  • show the tester algorithm names or debug data;
  • use FCM or keep running in the background (the screen stays on while the tool is open);
  • bundle hospital rasters in the APK or in git;
  • run on iOS beyond what Flutter gives for free (the field device is Android).