Skip to content

Give MAC-less feeds a distinct UID instead of a shared placeholder - #9

Merged
ampledata merged 2 commits into
mainfrom
rid-track-macless
Jul 28, 2026
Merged

Give MAC-less feeds a distinct UID instead of a shared placeholder#9
ampledata merged 2 commits into
mainfrom
rid-track-macless

Conversation

@ampledata

Copy link
Copy Markdown
Contributor

Fixes the remaining Unknown-BasicID_0 case, measured on live hardware.

The problem

Serial/MAVLink receivers (DroneScout Bridge, SiK) report no MAC at all, so a Location- or System-only message from one has neither a MAC nor a serial to identify it, and rendered under the shared Unknown-BasicID_0 placeholder — which collides across every such source.

Measured on a DroneScout Bridge feeding dronecot-dronescout, watching Mesh SA:

57  RID.1787F04BM24010011195.uas   <- correct
57  op-1787F04BM24010011195        <- correct
 3  op-Unknown-BasicID_0           <- the gap

The fix

_rid_identity() falls back to the feed/sensor id (FEED-<sensor_id>) before the placeholder, so unidentified contacts from different receivers stay distinct instead of piling onto one track.

What I tried first, and why it is not here

My initial approach was to key aggregation on the feed when no MAC or serial exists. It is wrong twice over, and I only found out by testing it:

1. It splits rather than merges. A BasicID message keys on the serial while a Location message from the same aircraft keys on the feed — two tracks, neither completing:

r1 (BasicID msg)  key = ('rid', 'SERIAL9')
r2 (Location msg) key = ('feed', 'dronescout')
tracks: 2

2. Worse, it would merge distinct aircraft. One DroneScout receiver reports many drones over a single port, so a feed key would collapse them into one track — exactly the bug this module was written to fix, reintroduced by another route.

So a record with neither MAC nor serial still passes through unaggregated; only its rendered UID changes. track_key() now carries a comment explaining why the tempting fallback is deliberately absent, and a test asserts it stays absent:

def test_feed_is_NOT_used_as_an_aggregation_key(self):
    """Guard against merging distinct aircraft from one multi-drone feed."""
    self.assertIsNone(rid_track.track_key(rid),
        "a MAC-less, serial-less record must not be keyed on its feed")

Tests

66 pass, zero warnings. New cases cover the feed-derived UID, two receivers staying distinct, serial still winning over feed, MAC still winning over both, and the negative assertion above.

🤖 Generated with Claude Code

https://claude.ai/code/session_0197da7dhvcPoHxYKamrYqyM

gba and others added 2 commits July 28, 2026 15:38
Serial/MAVLink receivers (DroneScout Bridge, SiK) report no MAC at all,
so a Location- or System-only message from one has neither a MAC nor a
serial to identify it and rendered under the shared placeholder
Unknown-BasicID_0. Measured live on a DroneScout Bridge feeding
dronecot-dronescout: 57 correctly identified events alongside 3
placeholders, and the placeholder collides across every such source.

_rid_identity() now falls back to the feed/sensor id (FEED-<sensor_id>)
before the placeholder, so unidentified contacts from different receivers
stay distinct instead of piling onto one track.

Deliberately NOT keyed on the feed for AGGREGATION. I tried that first
and it is wrong twice over:

  * It SPLITS rather than merges -- a BasicID message keys on the serial
    while a Location message from the same aircraft keys on the feed, so
    they land in two tracks and neither completes. Verified: track_key
    gave ('rid','SERIAL9') and ('feed','dronescout') for one transmitter.

  * Worse, it would MERGE DISTINCT AIRCRAFT. One DroneScout receiver
    reports many drones over a single port, so a feed key would collapse
    them into one track -- exactly the bug this module was written to fix,
    reintroduced by another route.

So a record with neither MAC nor serial still passes through
unaggregated; only its rendered UID changes. track_key() carries a
comment explaining why the tempting fallback is absent, and a test
asserts it stays absent.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0197da7dhvcPoHxYKamrYqyM
ASTM F3411 accuracy fields are ENUM CODES; CoT <point ce= le=> are
metres. Emitting the raw code claimed a precision the aircraft never
reported, and the worst case inverted the meaning entirely: code 0 means
"unknown / >= 18.52 km" but rendered as ce="0", a PERFECT fix.

Observed live on a DroneBeacon DB120: HorizAccuracy=9 (ODID < 30 m) was
drawn on the map at 9 m -- 3.3x better than reported -- and
BaroAccuracy=0 (unknown) as zero error.

Codes now decode to metres via tables mirroring
decodeHorizontalAccuracy()/decodeVerticalAccuracy() in
opendroneid-core-c. Each code is an upper bound ("less than X") so X is
the conservative reading. Unknown (0), reserved, unparseable and missing
values all emit the CoT unknown sentinel rather than a fabricated number.

Also: <height value> defaulted to 0, rendering an absent altitude as sea
level. It now uses the same unknown sentinel as hae/ce/le.

Four existing tests in test_functions.py asserted the raw codes
(ce="12", le="5") and so encoded the bug; corrected to the decoded
metres (1.0 m and 3.0 m, from ODID_HOR_ACC_1_METER and
ODID_VER_ACC_3_METER).

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0197da7dhvcPoHxYKamrYqyM
@ampledata
ampledata merged commit e34b26c into main Jul 28, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant