dronecot 2.2.5__tar.gz → 2.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dronecot-2.3.1/CHANGELOG.md +180 -0
- {dronecot-2.2.5/dronecot.egg-info → dronecot-2.3.1}/PKG-INFO +1 -1
- {dronecot-2.2.5 → dronecot-2.3.1/dronecot.egg-info}/PKG-INFO +1 -1
- {dronecot-2.2.5 → dronecot-2.3.1}/dronecot.egg-info/SOURCES.txt +4 -0
- dronecot-2.3.1/src/dronecot/VERSION +1 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/src/dronecot/__init__.py +6 -0
- dronecot-2.3.1/src/dronecot/bluez_capture.py +521 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/src/dronecot/classes.py +101 -7
- {dronecot-2.2.5 → dronecot-2.3.1}/src/dronecot/constants.py +11 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/src/dronecot/functions.py +104 -13
- {dronecot-2.2.5 → dronecot-2.3.1}/src/dronecot/odid.py +18 -14
- dronecot-2.3.1/src/dronecot/rid_track.py +251 -0
- dronecot-2.3.1/tests/test_bluez_capture.py +264 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/tests/test_functions.py +20 -8
- dronecot-2.3.1/tests/test_rid_track.py +401 -0
- dronecot-2.2.5/CHANGELOG.md +0 -94
- dronecot-2.2.5/src/dronecot/VERSION +0 -1
- {dronecot-2.2.5 → dronecot-2.3.1}/LICENSE +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/MANIFEST.in +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/README.md +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/dronecot.egg-info/dependency_links.txt +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/dronecot.egg-info/entry_points.txt +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/dronecot.egg-info/requires.txt +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/dronecot.egg-info/top_level.txt +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/setup.cfg +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/setup.py +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/src/dronecot/ble_capture.py +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/src/dronecot/ble_parse.py +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/src/dronecot/commands.py +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/src/dronecot/dji_exceptions.py +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/src/dronecot/dji_functions.py +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/src/dronecot/dji_text_parser.py +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/src/dronecot/open_drone_id.py +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/src/dronecot/rid_normalize.py +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/src/dronecot/udp_rid.py +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/src/dronecot/wifi_capture.py +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/src/dronecot/wifi_parse.py +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/tests/test_adsb_vehicle.py +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/tests/test_rid_normalize.py +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/tests/test_sensor_detail.py +0 -0
- {dronecot-2.2.5 → dronecot-2.3.1}/tests/test_wifi_parse.py +0 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
## DroneCOT 2.3.1
|
|
2
|
+
|
|
3
|
+
- **Fix: CoT `ce`/`le` reported ODID accuracy ENUM CODES as if they were metres.**
|
|
4
|
+
ASTM F3411 accuracy fields are enum codes; CoT `<point ce= le=>` are metres.
|
|
5
|
+
Emitting the raw code claimed precision the aircraft never reported, and the
|
|
6
|
+
worst case inverted the meaning entirely: code `0` means *"unknown / >= 18.52
|
|
7
|
+
km"* but rendered as `ce="0"` — a perfect fix. Observed live on a DroneBeacon
|
|
8
|
+
DB120: `HorizAccuracy=9` (ODID *< 30 m*) was drawn on the map at **9 m**, and
|
|
9
|
+
`BaroAccuracy=0` (unknown) as **zero error**. Codes now decode to metres via
|
|
10
|
+
tables mirroring `decodeHorizontalAccuracy()`/`decodeVerticalAccuracy()` in
|
|
11
|
+
opendroneid-core-c; unknown and reserved codes emit the CoT unknown sentinel
|
|
12
|
+
rather than a fabricated number. Four existing tests asserted the old raw
|
|
13
|
+
codes and have been corrected.
|
|
14
|
+
- **Fix: absent altitude rendered as sea level.** `<height value>` defaulted to
|
|
15
|
+
`0`; an unknown altitude now uses the CoT unknown sentinel like `hae`/`ce`/`le`.
|
|
16
|
+
- **Fix: MAC-less feeds shared one placeholder UID.** Serial/MAVLink receivers
|
|
17
|
+
(DroneScout Bridge, SiK) report no MAC, so a Location- or System-only message
|
|
18
|
+
had neither MAC nor serial and rendered as `Unknown-BasicID_0`, colliding
|
|
19
|
+
across every such source. The UID now falls back to `FEED-<sensor_id>`.
|
|
20
|
+
Measured on a live DroneScout Bridge: 57 correctly identified events alongside
|
|
21
|
+
3 placeholders. Aggregation is deliberately NOT keyed on the feed — one
|
|
22
|
+
receiver reports many aircraft, so that would merge distinct drones.
|
|
23
|
+
|
|
24
|
+
## DroneCOT 2.3.0
|
|
25
|
+
|
|
26
|
+
Correctness release for single-message Remote ID. A BLE legacy transmitter fits
|
|
27
|
+
only ONE 25-byte ODID message per advertisement and rotates through message
|
|
28
|
+
types, so the serial, the UAS position and the operator location arrive in
|
|
29
|
+
*different* frames. DroneCOT rendered each frame independently, which broke
|
|
30
|
+
badly in the field.
|
|
31
|
+
|
|
32
|
+
- **Fix: CoT XML could contain NUL bytes and fail to parse.** ODID pads its
|
|
33
|
+
fixed-width ASCII fields (20-byte serial, 23-byte text) with NUL, and
|
|
34
|
+
`clean_SN()` / `clean_string()` stripped only whitespace. Any UAS whose serial
|
|
35
|
+
was shorter than the field emitted a CoT UID such as
|
|
36
|
+
`RID.SHORTSN\0\0\0....uas` — 82 NUL bytes in the document, which is illegal in
|
|
37
|
+
XML 1.0 and will not reparse. Both cleaners now strip NUL and all C0 control
|
|
38
|
+
characters. Affected every source (Wi-Fi, BLE, serial, MQTT); went unnoticed
|
|
39
|
+
because every committed fixture uses a full-width 20-character serial.
|
|
40
|
+
- **Fix: every drone collapsed onto one track.** A Location message carries a
|
|
41
|
+
position but no serial, so it rendered with the constant UID
|
|
42
|
+
`RID.Unknown-BasicID_0.uas` — all aircraft in range shared one track. The UID
|
|
43
|
+
now falls back to the advertiser MAC (`MAC-<addr>`) so distinct transmitters
|
|
44
|
+
stay distinct.
|
|
45
|
+
- **Fix: BasicID and System messages were silently dropped**, having no position
|
|
46
|
+
of their own.
|
|
47
|
+
- **New `rid_track.ODIDAggregator`**: merges successive single ODID messages per
|
|
48
|
+
transmitter (keyed on the advertiser MAC, which ASTM F3411 requires to be
|
|
49
|
+
stable for a flight session) so a CoT carries the serial from one
|
|
50
|
+
advertisement and the position from another. TTL-expired and hard-capped to
|
|
51
|
+
bound memory. Wired into `RIDWorker.handle_data()`, the single choke point all
|
|
52
|
+
workers feed, so Wi-Fi, BLE, serial, MQTT and UDP all benefit. Full `0xF`
|
|
53
|
+
message packs are unaffected — they already carry everything in one frame.
|
|
54
|
+
Tunable via `RID_TRACK_TTL` (default 120 s; set 0 to disable),
|
|
55
|
+
`RID_TRACK_MAX` (default 512) and `RID_TRACK_ID_GRACE` (default 5 s).
|
|
56
|
+
`RID_TRACK_ID_GRACE` briefly holds a position-only track while waiting for
|
|
57
|
+
its serial, so one aircraft does not appear as two TAK markers (first under a
|
|
58
|
+
MAC-derived UID, then under the real serial); after the grace period an
|
|
59
|
+
unidentified drone renders anyway.
|
|
60
|
+
|
|
61
|
+
**Measured against a live BlueMark DroneBeacon DB120** over 234 real BLE
|
|
62
|
+
advertisements: without aggregation only 57 (24%) rendered as CoT and the
|
|
63
|
+
real serial NEVER appeared — every event used the MAC fallback UID. With
|
|
64
|
+
aggregation 230 (98%) rendered, all under the correct serial
|
|
65
|
+
`RID.1787F04BM24010011195.uas`. The transmitter sent BasicID, Location and
|
|
66
|
+
System as separate advertisements and no `0xF` message packs at all,
|
|
67
|
+
confirming the single-message rotation this release exists to handle.
|
|
68
|
+
- **Fix: operator CoT UID ignored the MAC.** `rid_op_to_cot_xml()` read
|
|
69
|
+
`data["MAC address"]`, but wireless captures put it in `data["data"]`, so the
|
|
70
|
+
Drone-Hone-style `op-<mac>` UID never actually used a MAC.
|
|
71
|
+
- Replace deprecated `datetime.utcfromtimestamp()` (Python 3.12+ warning).
|
|
72
|
+
- Tests: 16 new, including a real ASTM F3411 advertisement captured off the air
|
|
73
|
+
from a BlueMark DroneBeacon DB120 — the existing fixtures are all message
|
|
74
|
+
packs or CUAS blobs and never exercised the single-message path.
|
|
75
|
+
|
|
76
|
+
## DroneCOT 2.2.5
|
|
77
|
+
|
|
78
|
+
- Enrich RID CoT `<__cuas>` detail and remarks with `sensor_model`,
|
|
79
|
+
`sensor_method` and `band`. New `SENSOR_MODEL` / `SENSOR_TYPE` config.
|
|
80
|
+
|
|
81
|
+
## DroneCOT 2.2.4
|
|
82
|
+
|
|
83
|
+
- `wifi_parse`: fix `extract_odid_from_scapy_packet()`, which decoded zero
|
|
84
|
+
beacons because `bytes(elt.oui)` on an int produced a 16 MB zero buffer. Now
|
|
85
|
+
delegates to `extract_odid_from_dot11(bytes(dot11))`.
|
|
86
|
+
|
|
87
|
+
## DroneCOT 2.2.3
|
|
88
|
+
|
|
89
|
+
- SerialWorker: handle MAVLink **ADSB_VEHICLE** messages (in addition to
|
|
90
|
+
OPEN_DRONE_ID_MESSAGE_PACK), so Remote ID receivers that emit ADS-B-style
|
|
91
|
+
frames — e.g. the **BlueMark DroneScout Bridge (DS101)** in ADS-B output mode
|
|
92
|
+
— are decoded to CoT. Adds a test for the ADSB_VEHICLE -> RID conversion.
|
|
93
|
+
|
|
94
|
+
## DroneCOT 2.2.2
|
|
95
|
+
|
|
96
|
+
- Fix UTC timestamp handling on Python 3.9 and 3.10.
|
|
97
|
+
|
|
98
|
+
## DroneCOT 2.2.1
|
|
99
|
+
|
|
100
|
+
- Use PyTAK shared CoT event, point, detail, remarks, and serialization helpers.
|
|
101
|
+
- Replace `pytz` timestamp handling with standard-library timezone handling.
|
|
102
|
+
- Require `pytak >= 7.3.12`.
|
|
103
|
+
|
|
104
|
+
## DroneCOT 2.2.0
|
|
105
|
+
|
|
106
|
+
- Add `SensorWorker`: periodic `a-f-G-E-S-E` sensor CoT heartbeat, emitted every `SENSOR_KEEPALIVE_PERIOD` seconds (default 30).
|
|
107
|
+
- Position sourced from system gpsd if present (mode 2/3 fix); falls back to static `SENSOR_LAT`/`SENSOR_LON`/`SENSOR_HAE` config; falls back to null island (0, 0, 0).
|
|
108
|
+
- Add `gen_sensor_cot()`: reusable CoT generator for sensor beacon events, used by `SensorWorker`.
|
|
109
|
+
- New constants: `DEFAULT_SENSOR_KEEPALIVE_PERIOD = 30`, `DEFAULT_SENSOR_LAT/LON/HAE = 0.0`.
|
|
110
|
+
- Add `gpsd-py3` as optional runtime dependency (soft import, gracefully absent).
|
|
111
|
+
|
|
112
|
+
## DroneCOT 2.1.5
|
|
113
|
+
|
|
114
|
+
- Add `takproto` to postinst pip install; enables TAK Protocol v1 protobuf encoding over WebSocket when connected to TAK Server via `wss://`.
|
|
115
|
+
|
|
116
|
+
## DroneCOT 2.1.4
|
|
117
|
+
|
|
118
|
+
- Fix packaging: `postinst` now installs `aiomqtt` and `pymavlink` via pip for Debian systems where these packages are not yet available in the distro repos.
|
|
119
|
+
|
|
120
|
+
## DroneCOT 2.1.3
|
|
121
|
+
|
|
122
|
+
- Fix: make `aiomqtt` a conditional import so the package loads without it when MQTT is not used; `MQTTWorker` raises `ImportError` with a helpful message if aiomqtt is missing at runtime.
|
|
123
|
+
|
|
124
|
+
## DroneCOT 2.1.2
|
|
125
|
+
|
|
126
|
+
- Fix: `DJI_TCP_PORT` and `UDP_RID_PORT` config keys now take precedence over `FEED_URL` in `create_tasks` routing, eliminating the need to set `FEED_URL=` when using the DJI listener or UDP Remote ID worker without an explicit feed URL.
|
|
127
|
+
|
|
128
|
+
## DroneCOT 2.1.1
|
|
129
|
+
|
|
130
|
+
- Fix: `DJIWorker` argument order in `create_tasks` (`net_queue` and `config` were swapped in all three call sites).
|
|
131
|
+
|
|
132
|
+
## DroneCOT 2.1.0
|
|
133
|
+
|
|
134
|
+
- Add `UDPRIDWorker`: UDP listener (default port 9999) for pre-decoded Wi-Fi / BLE Remote ID JSON broadcasts from drone detection nodes.
|
|
135
|
+
- Add `udp_rid.py` module: `parse_udp_rid_message()` and `parse_udp_rid_line()` convert flat decoded JSONL (`t`, `mac`, `radio`, `rssi`, `lat`, `lon`, `alt`, `speed`, `hdg`, `id`) to RIDWorker-compatible dicts.
|
|
136
|
+
- Map `radio` field values (`wifi_beacon`, `wifi_nan`, `ble_legacy`, `ble_long_range`, `ble_coded`) to sensor type labels used by CoT generator.
|
|
137
|
+
- `create_tasks` now routes `udp://` feed URL or `UDP_RID_PORT` config option to `UDPRIDWorker` + `RIDWorker`.
|
|
138
|
+
- Fix: `wifi://`, `ble://`, `wireless://` branches now correctly include `RIDWorker` to consume the net_queue they produce.
|
|
139
|
+
- New constants: `DEFAULT_UDP_RID_PORT = 9999`, `DEFAULT_UDP_RID_HOST = "0.0.0.0"`.
|
|
140
|
+
|
|
141
|
+
## DroneCOT 2.0.0
|
|
142
|
+
|
|
143
|
+
- Absorbed DJI Drone ID (DJICOT) support directly into dronecot package.
|
|
144
|
+
- Added `DJIWorker`, `DJINetWorker`, `DJITextWorker`, `DJIFileWorker`, `DJIListenerWorker` for AntSDR binary and text CSV feeds.
|
|
145
|
+
- Added `gen_dji_cot`, `dji_uas_to_cot`, `dji_op_to_cot`, `dji_home_to_cot`, `dji_sensor_to_cot` CoT generators.
|
|
146
|
+
- Added `dji_handle_frame`, `dji_handle_text_line`, `dji_handle_parsed_data` feed handlers.
|
|
147
|
+
- Added `dji_functions.py` (binary frame parser) and `dji_text_parser.py` (AntSDR CSV parser).
|
|
148
|
+
- Added `dji_exceptions.py`: `DJICOTError`, `DJIDataError`, `DJIConnectionError`, `DJIConfigurationError`.
|
|
149
|
+
- `create_tasks` now routes `tcp://` → DJI binary/text, `file://` → DJI replay, `DJI_TCP_PORT` set → DJI listener.
|
|
150
|
+
- Added DJI constants: `DEFAULT_DJI_FEED_URL`, `DEFAULT_DJI_TEXT_FEED_URL`, `DEFAULT_DJI_*_PORT`, etc.
|
|
151
|
+
- Backward-compat aliases: `NetWorker`, `BinaryNetWorker`, `TextNetWorker`, `FileReplayWorker`, `TCPListenerWorker`.
|
|
152
|
+
|
|
153
|
+
## DroneCOT 1.2.0
|
|
154
|
+
|
|
155
|
+
- Add native Linux wireless Remote ID capture: Wi-Fi monitor mode (Beacon + NAN)
|
|
156
|
+
and BLE via Sniffle-compatible dongle (`wifi://`, `ble://`, `wireless://` feeds).
|
|
157
|
+
- Add `rid_normalize`, `wifi_parse`, `wifi_capture`, `ble_parse`, and `ble_capture`
|
|
158
|
+
modules; optional `pip install 'dronecot[wireless]'` for Scapy.
|
|
159
|
+
|
|
160
|
+
## DroneCOT 1.1.3
|
|
161
|
+
|
|
162
|
+
- Add user-systemd instance template (`dronecot@.service`) to support running
|
|
163
|
+
serial and MQTT DroneCOT workers side-by-side with layered defaults files.
|
|
164
|
+
|
|
165
|
+
## DroneCOT 1.1.2
|
|
166
|
+
|
|
167
|
+
- Unfixes #2.
|
|
168
|
+
|
|
169
|
+
## DroneCOT 1.1.1
|
|
170
|
+
|
|
171
|
+
- Fixes #2: Missing cot_to_xml function export.
|
|
172
|
+
|
|
173
|
+
## DroneCOT 1.1.0
|
|
174
|
+
|
|
175
|
+
* Updates
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
## DroneCOT 1.0.0
|
|
179
|
+
|
|
180
|
+
Initial release of DroneCOT.
|
|
@@ -14,6 +14,7 @@ src/dronecot/VERSION
|
|
|
14
14
|
src/dronecot/__init__.py
|
|
15
15
|
src/dronecot/ble_capture.py
|
|
16
16
|
src/dronecot/ble_parse.py
|
|
17
|
+
src/dronecot/bluez_capture.py
|
|
17
18
|
src/dronecot/classes.py
|
|
18
19
|
src/dronecot/commands.py
|
|
19
20
|
src/dronecot/constants.py
|
|
@@ -24,11 +25,14 @@ src/dronecot/functions.py
|
|
|
24
25
|
src/dronecot/odid.py
|
|
25
26
|
src/dronecot/open_drone_id.py
|
|
26
27
|
src/dronecot/rid_normalize.py
|
|
28
|
+
src/dronecot/rid_track.py
|
|
27
29
|
src/dronecot/udp_rid.py
|
|
28
30
|
src/dronecot/wifi_capture.py
|
|
29
31
|
src/dronecot/wifi_parse.py
|
|
30
32
|
tests/test_adsb_vehicle.py
|
|
33
|
+
tests/test_bluez_capture.py
|
|
31
34
|
tests/test_functions.py
|
|
32
35
|
tests/test_rid_normalize.py
|
|
36
|
+
tests/test_rid_track.py
|
|
33
37
|
tests/test_sensor_detail.py
|
|
34
38
|
tests/test_wifi_parse.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.3.1
|
|
@@ -38,6 +38,10 @@ from .constants import ( # NOQA
|
|
|
38
38
|
DEFAULT_OP_COT_TYPE,
|
|
39
39
|
DEFAULT_HOME_COT_TYPE,
|
|
40
40
|
DEFAULT_UAS_COT_TYPE,
|
|
41
|
+
# Per-transmitter RID track aggregation constants
|
|
42
|
+
DEFAULT_RID_TRACK_TTL,
|
|
43
|
+
DEFAULT_RID_TRACK_MAX,
|
|
44
|
+
DEFAULT_RID_TRACK_ID_GRACE,
|
|
41
45
|
# UDP pre-decoded Remote ID constants
|
|
42
46
|
DEFAULT_UDP_RID_PORT,
|
|
43
47
|
DEFAULT_UDP_RID_HOST,
|
|
@@ -86,6 +90,7 @@ from .udp_rid import ( # NOQA
|
|
|
86
90
|
|
|
87
91
|
from .classes import ( # NOQA
|
|
88
92
|
BleWorker,
|
|
93
|
+
BlueZWorker,
|
|
89
94
|
MQTTWorker,
|
|
90
95
|
RIDWorker,
|
|
91
96
|
RXMockWorker,
|
|
@@ -117,6 +122,7 @@ from .dji_exceptions import ( # NOQA
|
|
|
117
122
|
|
|
118
123
|
from . import odid # NOQA
|
|
119
124
|
from . import rid_normalize # NOQA
|
|
125
|
+
from . import rid_track # NOQA
|
|
120
126
|
|
|
121
127
|
from .open_drone_id import (
|
|
122
128
|
ODIDValidBlocks,
|