dronecot 2.2.0__tar.gz → 2.2.2__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.2.0 → dronecot-2.2.2}/CHANGELOG.md +10 -0
- {dronecot-2.2.0/dronecot.egg-info → dronecot-2.2.2}/PKG-INFO +25 -3
- {dronecot-2.2.0 → dronecot-2.2.2}/README.md +23 -0
- {dronecot-2.2.0 → dronecot-2.2.2/dronecot.egg-info}/PKG-INFO +25 -3
- {dronecot-2.2.0 → dronecot-2.2.2}/dronecot.egg-info/requires.txt +1 -2
- {dronecot-2.2.0 → dronecot-2.2.2}/setup.cfg +1 -2
- dronecot-2.2.2/src/dronecot/VERSION +1 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/src/dronecot/functions.py +107 -127
- {dronecot-2.2.0 → dronecot-2.2.2}/src/dronecot/open_drone_id.py +2 -4
- {dronecot-2.2.0 → dronecot-2.2.2}/tests/test_functions.py +8 -8
- dronecot-2.2.0/src/dronecot/VERSION +0 -1
- {dronecot-2.2.0 → dronecot-2.2.2}/LICENSE +0 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/MANIFEST.in +0 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/dronecot.egg-info/SOURCES.txt +0 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/dronecot.egg-info/dependency_links.txt +0 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/dronecot.egg-info/entry_points.txt +0 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/dronecot.egg-info/top_level.txt +0 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/setup.py +0 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/src/dronecot/__init__.py +0 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/src/dronecot/ble_capture.py +0 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/src/dronecot/ble_parse.py +0 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/src/dronecot/classes.py +0 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/src/dronecot/commands.py +0 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/src/dronecot/constants.py +0 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/src/dronecot/dji_exceptions.py +0 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/src/dronecot/dji_functions.py +0 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/src/dronecot/dji_text_parser.py +0 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/src/dronecot/odid.py +0 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/src/dronecot/rid_normalize.py +0 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/src/dronecot/udp_rid.py +0 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/src/dronecot/wifi_capture.py +0 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/src/dronecot/wifi_parse.py +0 -0
- {dronecot-2.2.0 → dronecot-2.2.2}/tests/test_rid_normalize.py +0 -0
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## DroneCOT 2.2.2
|
|
2
|
+
|
|
3
|
+
- Fix UTC timestamp handling on Python 3.9 and 3.10.
|
|
4
|
+
|
|
5
|
+
## DroneCOT 2.2.1
|
|
6
|
+
|
|
7
|
+
- Use PyTAK shared CoT event, point, detail, remarks, and serialization helpers.
|
|
8
|
+
- Replace `pytz` timestamp handling with standard-library timezone handling.
|
|
9
|
+
- Require `pytak >= 7.3.12`.
|
|
10
|
+
|
|
1
11
|
## DroneCOT 2.2.0
|
|
2
12
|
|
|
3
13
|
- Add `SensorWorker`: periodic `a-f-G-E-S-E` sensor CoT heartbeat, emitted every `SENSOR_KEEPALIVE_PERIOD` seconds (default 30).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dronecot
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2
|
|
4
4
|
Summary: Display Drones in Team Awareness Kit (TAK).
|
|
5
5
|
Home-page: https://github.com/snstac/dronecot
|
|
6
6
|
Maintainer: Greg Albrecht <oss@undef.net>
|
|
@@ -22,14 +22,13 @@ Classifier: Operating System :: OS Independent
|
|
|
22
22
|
Requires-Python: <4,>=3.9
|
|
23
23
|
Description-Content-Type: text/markdown
|
|
24
24
|
License-File: LICENSE
|
|
25
|
-
Requires-Dist: pytak>=7.3.
|
|
25
|
+
Requires-Dist: pytak>=7.3.12
|
|
26
26
|
Requires-Dist: paho-mqtt<2.0.0
|
|
27
27
|
Requires-Dist: bitstruct
|
|
28
28
|
Requires-Dist: pymavlink
|
|
29
29
|
Requires-Dist: pyserial
|
|
30
30
|
Requires-Dist: cryptography
|
|
31
31
|
Requires-Dist: aiohttp
|
|
32
|
-
Requires-Dist: pytz
|
|
33
32
|
Requires-Dist: aiomqtt
|
|
34
33
|
Provides-Extra: with-takproto
|
|
35
34
|
Requires-Dist: takproto>=2.0.0; extra == "with-takproto"
|
|
@@ -244,6 +243,29 @@ Contact: [info@snstac.com](mailto:info@snstac.com) · [snstac.com](https://www.s
|
|
|
244
243
|
|
|
245
244
|
---
|
|
246
245
|
|
|
246
|
+
## The snstac TAK sensor ecosystem
|
|
247
|
+
|
|
248
|
+
Different sensor, same workflow — pick the gateway for your application; most have a
|
|
249
|
+
matching Cockpit plugin for browser-based management:
|
|
250
|
+
|
|
251
|
+
| Application | Gateway | Cockpit plugin |
|
|
252
|
+
|---|---|---|
|
|
253
|
+
| Aircraft via ADS-B (1090 MHz / 978 MHz UAT) | [adsbcot](https://github.com/snstac/adsbcot) | [cockpit-adsbcot](https://github.com/snstac/cockpit-adsbcot) |
|
|
254
|
+
| Ships & vessels via AIS | [aiscot](https://github.com/snstac/aiscot) | [cockpit-aiscot](https://github.com/snstac/cockpit-aiscot), [cockpit-aiscatcher](https://github.com/snstac/cockpit-aiscatcher) |
|
|
255
|
+
| Drone / UAS Remote ID (counter-UAS) | [dronecot](https://github.com/snstac/dronecot) | [cockpit-dronecot](https://github.com/snstac/cockpit-dronecot) |
|
|
256
|
+
| Own position via GPS/GNSS | [lincot](https://github.com/snstac/lincot) | [cockpit-lincot](https://github.com/snstac/cockpit-lincot), [cockpit-gps](https://github.com/snstac/cockpit-gps) |
|
|
257
|
+
| Radio direction finding (KrakenSDR) | [kraktak](https://github.com/snstac/kraktak) | — |
|
|
258
|
+
| APRS amateur radio | [aprscot](https://github.com/snstac/aprscot) | — |
|
|
259
|
+
| Weather stations | [windtak](https://github.com/snstac/windtak) | — |
|
|
260
|
+
| CoT routing / TAK Server bridging | [charontak](https://github.com/snstac/charontak) | — |
|
|
261
|
+
|
|
262
|
+
All gateways are built on [PyTAK](https://github.com/snstac/pytak), speak
|
|
263
|
+
**Cursor on Target (CoT)** to **ATAK, WinTAK, iTAK, TAK Server, and Mesh SA**, ship as
|
|
264
|
+
signed Debian/RPM packages at [snstac.github.io/packages](https://snstac.github.io/packages),
|
|
265
|
+
and come pre-installed on [AryaOS](https://github.com/snstac/aryaos), the
|
|
266
|
+
situational-awareness OS for Raspberry Pi.
|
|
267
|
+
|
|
268
|
+
|
|
247
269
|
## License
|
|
248
270
|
|
|
249
271
|
### DroneCOT
|
|
@@ -196,6 +196,29 @@ Contact: [info@snstac.com](mailto:info@snstac.com) · [snstac.com](https://www.s
|
|
|
196
196
|
|
|
197
197
|
---
|
|
198
198
|
|
|
199
|
+
## The snstac TAK sensor ecosystem
|
|
200
|
+
|
|
201
|
+
Different sensor, same workflow — pick the gateway for your application; most have a
|
|
202
|
+
matching Cockpit plugin for browser-based management:
|
|
203
|
+
|
|
204
|
+
| Application | Gateway | Cockpit plugin |
|
|
205
|
+
|---|---|---|
|
|
206
|
+
| Aircraft via ADS-B (1090 MHz / 978 MHz UAT) | [adsbcot](https://github.com/snstac/adsbcot) | [cockpit-adsbcot](https://github.com/snstac/cockpit-adsbcot) |
|
|
207
|
+
| Ships & vessels via AIS | [aiscot](https://github.com/snstac/aiscot) | [cockpit-aiscot](https://github.com/snstac/cockpit-aiscot), [cockpit-aiscatcher](https://github.com/snstac/cockpit-aiscatcher) |
|
|
208
|
+
| Drone / UAS Remote ID (counter-UAS) | [dronecot](https://github.com/snstac/dronecot) | [cockpit-dronecot](https://github.com/snstac/cockpit-dronecot) |
|
|
209
|
+
| Own position via GPS/GNSS | [lincot](https://github.com/snstac/lincot) | [cockpit-lincot](https://github.com/snstac/cockpit-lincot), [cockpit-gps](https://github.com/snstac/cockpit-gps) |
|
|
210
|
+
| Radio direction finding (KrakenSDR) | [kraktak](https://github.com/snstac/kraktak) | — |
|
|
211
|
+
| APRS amateur radio | [aprscot](https://github.com/snstac/aprscot) | — |
|
|
212
|
+
| Weather stations | [windtak](https://github.com/snstac/windtak) | — |
|
|
213
|
+
| CoT routing / TAK Server bridging | [charontak](https://github.com/snstac/charontak) | — |
|
|
214
|
+
|
|
215
|
+
All gateways are built on [PyTAK](https://github.com/snstac/pytak), speak
|
|
216
|
+
**Cursor on Target (CoT)** to **ATAK, WinTAK, iTAK, TAK Server, and Mesh SA**, ship as
|
|
217
|
+
signed Debian/RPM packages at [snstac.github.io/packages](https://snstac.github.io/packages),
|
|
218
|
+
and come pre-installed on [AryaOS](https://github.com/snstac/aryaos), the
|
|
219
|
+
situational-awareness OS for Raspberry Pi.
|
|
220
|
+
|
|
221
|
+
|
|
199
222
|
## License
|
|
200
223
|
|
|
201
224
|
### DroneCOT
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dronecot
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2
|
|
4
4
|
Summary: Display Drones in Team Awareness Kit (TAK).
|
|
5
5
|
Home-page: https://github.com/snstac/dronecot
|
|
6
6
|
Maintainer: Greg Albrecht <oss@undef.net>
|
|
@@ -22,14 +22,13 @@ Classifier: Operating System :: OS Independent
|
|
|
22
22
|
Requires-Python: <4,>=3.9
|
|
23
23
|
Description-Content-Type: text/markdown
|
|
24
24
|
License-File: LICENSE
|
|
25
|
-
Requires-Dist: pytak>=7.3.
|
|
25
|
+
Requires-Dist: pytak>=7.3.12
|
|
26
26
|
Requires-Dist: paho-mqtt<2.0.0
|
|
27
27
|
Requires-Dist: bitstruct
|
|
28
28
|
Requires-Dist: pymavlink
|
|
29
29
|
Requires-Dist: pyserial
|
|
30
30
|
Requires-Dist: cryptography
|
|
31
31
|
Requires-Dist: aiohttp
|
|
32
|
-
Requires-Dist: pytz
|
|
33
32
|
Requires-Dist: aiomqtt
|
|
34
33
|
Provides-Extra: with-takproto
|
|
35
34
|
Requires-Dist: takproto>=2.0.0; extra == "with-takproto"
|
|
@@ -244,6 +243,29 @@ Contact: [info@snstac.com](mailto:info@snstac.com) · [snstac.com](https://www.s
|
|
|
244
243
|
|
|
245
244
|
---
|
|
246
245
|
|
|
246
|
+
## The snstac TAK sensor ecosystem
|
|
247
|
+
|
|
248
|
+
Different sensor, same workflow — pick the gateway for your application; most have a
|
|
249
|
+
matching Cockpit plugin for browser-based management:
|
|
250
|
+
|
|
251
|
+
| Application | Gateway | Cockpit plugin |
|
|
252
|
+
|---|---|---|
|
|
253
|
+
| Aircraft via ADS-B (1090 MHz / 978 MHz UAT) | [adsbcot](https://github.com/snstac/adsbcot) | [cockpit-adsbcot](https://github.com/snstac/cockpit-adsbcot) |
|
|
254
|
+
| Ships & vessels via AIS | [aiscot](https://github.com/snstac/aiscot) | [cockpit-aiscot](https://github.com/snstac/cockpit-aiscot), [cockpit-aiscatcher](https://github.com/snstac/cockpit-aiscatcher) |
|
|
255
|
+
| Drone / UAS Remote ID (counter-UAS) | [dronecot](https://github.com/snstac/dronecot) | [cockpit-dronecot](https://github.com/snstac/cockpit-dronecot) |
|
|
256
|
+
| Own position via GPS/GNSS | [lincot](https://github.com/snstac/lincot) | [cockpit-lincot](https://github.com/snstac/cockpit-lincot), [cockpit-gps](https://github.com/snstac/cockpit-gps) |
|
|
257
|
+
| Radio direction finding (KrakenSDR) | [kraktak](https://github.com/snstac/kraktak) | — |
|
|
258
|
+
| APRS amateur radio | [aprscot](https://github.com/snstac/aprscot) | — |
|
|
259
|
+
| Weather stations | [windtak](https://github.com/snstac/windtak) | — |
|
|
260
|
+
| CoT routing / TAK Server bridging | [charontak](https://github.com/snstac/charontak) | — |
|
|
261
|
+
|
|
262
|
+
All gateways are built on [PyTAK](https://github.com/snstac/pytak), speak
|
|
263
|
+
**Cursor on Target (CoT)** to **ATAK, WinTAK, iTAK, TAK Server, and Mesh SA**, ship as
|
|
264
|
+
signed Debian/RPM packages at [snstac.github.io/packages](https://snstac.github.io/packages),
|
|
265
|
+
and come pre-installed on [AryaOS](https://github.com/snstac/aryaos), the
|
|
266
|
+
situational-awareness OS for Raspberry Pi.
|
|
267
|
+
|
|
268
|
+
|
|
247
269
|
## License
|
|
248
270
|
|
|
249
271
|
### DroneCOT
|
|
@@ -48,14 +48,13 @@ package_dir =
|
|
|
48
48
|
dronecot = src/dronecot
|
|
49
49
|
python_requires = >=3.9, <4
|
|
50
50
|
install_requires =
|
|
51
|
-
pytak >= 7.3.
|
|
51
|
+
pytak >= 7.3.12
|
|
52
52
|
paho-mqtt < 2.0.0
|
|
53
53
|
bitstruct
|
|
54
54
|
pymavlink
|
|
55
55
|
pyserial
|
|
56
56
|
cryptography
|
|
57
57
|
aiohttp
|
|
58
|
-
pytz
|
|
59
58
|
aiomqtt
|
|
60
59
|
|
|
61
60
|
[options.packages.find]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.2.2
|
|
@@ -29,11 +29,11 @@ import xml.etree.ElementTree as ET
|
|
|
29
29
|
from configparser import SectionProxy
|
|
30
30
|
from typing import Optional, Set, Union
|
|
31
31
|
from urllib.parse import urlparse
|
|
32
|
+
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
|
|
32
33
|
|
|
33
34
|
import pytak
|
|
34
35
|
import dronecot
|
|
35
36
|
from datetime import datetime
|
|
36
|
-
import pytz
|
|
37
37
|
|
|
38
38
|
from .dji_functions import parse_frame, parse_data
|
|
39
39
|
from .dji_text_parser import dji_parse_text_line
|
|
@@ -65,6 +65,15 @@ _DJI_Logger = logging.getLogger(__name__)
|
|
|
65
65
|
APP_NAME = "dronecot"
|
|
66
66
|
|
|
67
67
|
|
|
68
|
+
def _pacific_timestamp() -> str:
|
|
69
|
+
"""Return a human-readable last-seen timestamp, falling back if tzdata is absent."""
|
|
70
|
+
try:
|
|
71
|
+
tzinfo = ZoneInfo("US/Pacific")
|
|
72
|
+
except ZoneInfoNotFoundError:
|
|
73
|
+
tzinfo = datetime.now().astimezone().tzinfo
|
|
74
|
+
return datetime.now(tzinfo).strftime("%Y-%m-%d %H:%M:%S %Z")
|
|
75
|
+
|
|
76
|
+
|
|
68
77
|
def _dji_feed_uses_text(config, feed_url: str, parsed) -> bool:
|
|
69
78
|
"""Return True if the configured DJI feed uses AntSDR text CSV format."""
|
|
70
79
|
feed_format = str(config.get("FEED_FORMAT", "")).lower()
|
|
@@ -138,6 +147,31 @@ def create_tasks(config: SectionProxy, clitool: pytak.CLITool) -> Set[pytak.Work
|
|
|
138
147
|
return tasks
|
|
139
148
|
|
|
140
149
|
|
|
150
|
+
def _cot_event_with_detail(
|
|
151
|
+
*,
|
|
152
|
+
uid: str,
|
|
153
|
+
cot_type: str,
|
|
154
|
+
stale,
|
|
155
|
+
lat,
|
|
156
|
+
lon,
|
|
157
|
+
hae,
|
|
158
|
+
ce,
|
|
159
|
+
le,
|
|
160
|
+
detail: ET.Element,
|
|
161
|
+
config: Union[SectionProxy, dict],
|
|
162
|
+
cot_host_id: str,
|
|
163
|
+
) -> ET.Element:
|
|
164
|
+
"""Build a standard CoT event around DroneCOT-specific detail children."""
|
|
165
|
+
return pytak.cot_event(
|
|
166
|
+
uid=uid,
|
|
167
|
+
cot_type=cot_type,
|
|
168
|
+
stale=stale,
|
|
169
|
+
point=pytak.cot_point(lat=lat, lon=lon, ce=ce, hae=hae, le=le),
|
|
170
|
+
detail=pytak.cot_detail(*list(detail), flow_tag_host_id=cot_host_id),
|
|
171
|
+
access=config.get("COT_ACCESS", pytak.DEFAULT_COT_ACCESS),
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
|
|
141
175
|
def rid_op_to_cot_xml( # NOQA pylint: disable=too-many-locals,too-many-branches,too-many-statements
|
|
142
176
|
data: dict,
|
|
143
177
|
config: Union[SectionProxy, dict, None] = None,
|
|
@@ -218,26 +252,19 @@ def rid_op_to_cot_xml( # NOQA pylint: disable=too-many-locals,too-many-branches
|
|
|
218
252
|
remarks.text = _remarks
|
|
219
253
|
detail.append(remarks)
|
|
220
254
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
"
|
|
228
|
-
"
|
|
229
|
-
"
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
_detail = cot.findall("detail")[0]
|
|
235
|
-
flowtags = _detail.findall("_flow-tags_")
|
|
236
|
-
detail.extend(flowtags)
|
|
237
|
-
cot.remove(_detail)
|
|
238
|
-
cot.append(detail)
|
|
239
|
-
|
|
240
|
-
return cot
|
|
255
|
+
return _cot_event_with_detail(
|
|
256
|
+
uid=cot_uid,
|
|
257
|
+
cot_type=cot_type,
|
|
258
|
+
stale=cot_stale,
|
|
259
|
+
lat=lat,
|
|
260
|
+
lon=lon,
|
|
261
|
+
ce=str(data.get("HorizAccuracy", "9999999.0")),
|
|
262
|
+
le=str(data.get("VertAccuracy", "9999999.0")),
|
|
263
|
+
hae=str(data.get("OperatorAltitudeGeo", "9999999.0")),
|
|
264
|
+
detail=detail,
|
|
265
|
+
config=config,
|
|
266
|
+
cot_host_id=cot_host_id,
|
|
267
|
+
)
|
|
241
268
|
|
|
242
269
|
|
|
243
270
|
def rid_uas_to_cot_xml( # NOQA pylint: disable=too-many-locals,too-many-branches,too-many-statements
|
|
@@ -287,8 +314,7 @@ def rid_uas_to_cot_xml( # NOQA pylint: disable=too-many-locals,too-many-branche
|
|
|
287
314
|
cot_host_id: str = config.get("COT_HOST_ID", pytak.DEFAULT_HOST_ID)
|
|
288
315
|
|
|
289
316
|
# Show last-seen time in Pacific Time Zone in remarks
|
|
290
|
-
|
|
291
|
-
pacific_time = datetime.now(pacific).strftime('%Y-%m-%d %H:%M:%S %Z')
|
|
317
|
+
pacific_time = _pacific_timestamp()
|
|
292
318
|
remarks_fields.append(f"Last Seen (Pacific): {pacific_time}")
|
|
293
319
|
|
|
294
320
|
remarks_fields.append(f"Remote ID: {uasid}")
|
|
@@ -405,26 +431,19 @@ def rid_uas_to_cot_xml( # NOQA pylint: disable=too-many-locals,too-many-branche
|
|
|
405
431
|
remarks.text = _remarks
|
|
406
432
|
detail.append(remarks)
|
|
407
433
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
"
|
|
415
|
-
"
|
|
416
|
-
"
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
_detail = cot.findall("detail")[0]
|
|
422
|
-
flowtags = _detail.findall("_flow-tags_")
|
|
423
|
-
detail.extend(flowtags)
|
|
424
|
-
cot.remove(_detail)
|
|
425
|
-
cot.append(detail)
|
|
426
|
-
|
|
427
|
-
return cot
|
|
434
|
+
return _cot_event_with_detail(
|
|
435
|
+
uid=cot_uid,
|
|
436
|
+
cot_type=cot_type,
|
|
437
|
+
stale=cot_stale,
|
|
438
|
+
lat=lat,
|
|
439
|
+
lon=lon,
|
|
440
|
+
ce=str(data.get("HorizAccuracy", "9999999.0")),
|
|
441
|
+
le=str(data.get("VertAccuracy", "9999999.0")),
|
|
442
|
+
hae=str(data.get("AltitudeGeo", "9999999.0")),
|
|
443
|
+
detail=detail,
|
|
444
|
+
config=config,
|
|
445
|
+
cot_host_id=cot_host_id,
|
|
446
|
+
)
|
|
428
447
|
|
|
429
448
|
|
|
430
449
|
def sensor_status_to_cot( # NOQA pylint: disable=too-many-locals,too-many-branches,too-many-statements
|
|
@@ -494,26 +513,19 @@ def sensor_status_to_cot( # NOQA pylint: disable=too-many-locals,too-many-branc
|
|
|
494
513
|
remarks.text = _remarks
|
|
495
514
|
detail.append(remarks)
|
|
496
515
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
"
|
|
504
|
-
"
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
_detail = cot.findall("detail")[0]
|
|
511
|
-
flowtags = _detail.findall("_flow-tags_")
|
|
512
|
-
detail.extend(flowtags)
|
|
513
|
-
cot.remove(_detail)
|
|
514
|
-
cot.append(detail)
|
|
515
|
-
|
|
516
|
-
return cot
|
|
516
|
+
return _cot_event_with_detail(
|
|
517
|
+
uid=cot_uid,
|
|
518
|
+
cot_type=cot_type,
|
|
519
|
+
stale=cot_stale,
|
|
520
|
+
lat=lat,
|
|
521
|
+
lon=lon,
|
|
522
|
+
ce=str(data.get("HorizAccuracy", "9999999.0")),
|
|
523
|
+
le=str(data.get("VertAccuracy", "9999999.0")),
|
|
524
|
+
hae=hae,
|
|
525
|
+
detail=detail,
|
|
526
|
+
config=config,
|
|
527
|
+
cot_host_id=cot_host_id,
|
|
528
|
+
)
|
|
517
529
|
|
|
518
530
|
|
|
519
531
|
def xml_to_cot(
|
|
@@ -521,9 +533,7 @@ def xml_to_cot(
|
|
|
521
533
|
) -> Optional[bytes]:
|
|
522
534
|
"""Return a CoT XML object as an XML string, using the given func."""
|
|
523
535
|
cot: Optional[ET.Element] = getattr(dronecot.functions, func)(data, config)
|
|
524
|
-
return (
|
|
525
|
-
b"\n".join([pytak.DEFAULT_XML_DECLARATION, ET.tostring(cot)]) if cot else None
|
|
526
|
-
)
|
|
536
|
+
return pytak.serialize_cot(cot) if cot is not None else None
|
|
527
537
|
|
|
528
538
|
|
|
529
539
|
def cot_to_xml(
|
|
@@ -703,27 +713,19 @@ def gen_dji_cot( # NOQA pylint: disable=too-many-locals,too-many-branches,too-m
|
|
|
703
713
|
detail.append(cuas)
|
|
704
714
|
detail.append(crumbs)
|
|
705
715
|
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
"
|
|
714
|
-
"
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
_detail = cot.find("detail")
|
|
720
|
-
if _detail is not None:
|
|
721
|
-
flowtags = _detail.findall("_flow-tags_")
|
|
722
|
-
detail.extend(flowtags)
|
|
723
|
-
cot.remove(_detail)
|
|
724
|
-
cot.append(detail)
|
|
725
|
-
|
|
726
|
-
return cot
|
|
716
|
+
return _cot_event_with_detail(
|
|
717
|
+
uid=cot_uid,
|
|
718
|
+
cot_type=cot_type,
|
|
719
|
+
stale=cot_stale,
|
|
720
|
+
lat=lat,
|
|
721
|
+
lon=lon,
|
|
722
|
+
ce=ce,
|
|
723
|
+
le=str(data.get("nac_v", "9999999.0")),
|
|
724
|
+
hae=str(data.get("alt_geom", "9999999.0")),
|
|
725
|
+
detail=detail,
|
|
726
|
+
config=config,
|
|
727
|
+
cot_host_id=cot_host_id,
|
|
728
|
+
)
|
|
727
729
|
|
|
728
730
|
|
|
729
731
|
def dji_sensor_to_cot(
|
|
@@ -762,27 +764,19 @@ def dji_sensor_to_cot(
|
|
|
762
764
|
detail.append(contact)
|
|
763
765
|
detail.append(cuas)
|
|
764
766
|
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
"
|
|
772
|
-
"
|
|
773
|
-
"
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
_detail = cot.find("detail")
|
|
779
|
-
if _detail is not None:
|
|
780
|
-
flowtags = _detail.findall("_flow-tags_")
|
|
781
|
-
detail.extend(flowtags)
|
|
782
|
-
cot.remove(_detail)
|
|
783
|
-
cot.append(detail)
|
|
784
|
-
|
|
785
|
-
return cot
|
|
767
|
+
return _cot_event_with_detail(
|
|
768
|
+
uid=cot_uid,
|
|
769
|
+
cot_type=cot_type,
|
|
770
|
+
stale=cot_stale,
|
|
771
|
+
lat=lat,
|
|
772
|
+
lon=lon,
|
|
773
|
+
ce=str(config.get("SENSOR_CE", DEFAULT_DJI_SENSOR_CE)),
|
|
774
|
+
le=str(config.get("SENSOR_LE", DEFAULT_DJI_SENSOR_LE)),
|
|
775
|
+
hae=str(config.get("SENSOR_HAE", DEFAULT_DJI_SENSOR_HAE)),
|
|
776
|
+
detail=detail,
|
|
777
|
+
config=config,
|
|
778
|
+
cot_host_id=cot_host_id,
|
|
779
|
+
)
|
|
786
780
|
|
|
787
781
|
|
|
788
782
|
def dji_uas_to_cot(data, config: Union[SectionProxy, dict, None] = None) -> Optional[ET.Element]:
|
|
@@ -874,26 +868,12 @@ def gen_sensor_cot(
|
|
|
874
868
|
cuas.set("sensor_id", sensor_id)
|
|
875
869
|
cuas.set("type", payload_type)
|
|
876
870
|
|
|
877
|
-
|
|
878
|
-
detail.append(contact)
|
|
879
|
-
detail.append(cuas)
|
|
880
|
-
|
|
881
|
-
cot = pytak.gen_cot_xml(
|
|
882
|
-
lat=str(lat),
|
|
883
|
-
lon=str(lon),
|
|
884
|
-
hae=str(hae),
|
|
885
|
-
ce=ce,
|
|
886
|
-
le=le,
|
|
871
|
+
return pytak.cot_event(
|
|
887
872
|
uid=f"SENSOR.{sensor_id}",
|
|
888
873
|
cot_type=cot_type,
|
|
889
874
|
stale=cot_stale,
|
|
875
|
+
point=pytak.cot_point(lat=lat, lon=lon, hae=hae, ce=ce, le=le),
|
|
876
|
+
detail=pytak.cot_detail(contact, cuas, flow_tag=False),
|
|
877
|
+
how="m-g",
|
|
878
|
+
access=config.get("COT_ACCESS", pytak.DEFAULT_COT_ACCESS),
|
|
890
879
|
)
|
|
891
|
-
cot.set("how", "m-g")
|
|
892
|
-
cot.set("access", config.get("COT_ACCESS", pytak.DEFAULT_COT_ACCESS))
|
|
893
|
-
|
|
894
|
-
_detail = cot.find("detail")
|
|
895
|
-
if _detail is not None:
|
|
896
|
-
cot.remove(_detail)
|
|
897
|
-
cot.append(detail)
|
|
898
|
-
|
|
899
|
-
return cot
|
|
@@ -27,8 +27,6 @@
|
|
|
27
27
|
import datetime
|
|
28
28
|
import struct
|
|
29
29
|
|
|
30
|
-
import pytz
|
|
31
|
-
|
|
32
30
|
from bitstruct import *
|
|
33
31
|
|
|
34
32
|
|
|
@@ -356,7 +354,7 @@ def parse_System(payload):
|
|
|
356
354
|
if Timestamp != float("NaN") and Timestamp != 0:
|
|
357
355
|
pl["Timestamp"] = (
|
|
358
356
|
datetime.datetime.fromtimestamp(
|
|
359
|
-
(int(Timestamp) + 1546300800),
|
|
357
|
+
(int(Timestamp) + 1546300800), datetime.timezone.utc
|
|
360
358
|
).strftime("%Y-%m-%d %H:%M %Z"),
|
|
361
359
|
)
|
|
362
360
|
pl["TimestampRaw"] = Timestamp
|
|
@@ -411,7 +409,7 @@ def parse_AuthPage(payload, page):
|
|
|
411
409
|
|
|
412
410
|
if Timestamp != float("NaN") and Timestamp != 0:
|
|
413
411
|
pl["Timestamp"] = datetime.datetime.fromtimestamp(
|
|
414
|
-
(int(Timestamp) + 1546300800),
|
|
412
|
+
(int(Timestamp) + 1546300800), datetime.timezone.utc
|
|
415
413
|
).strftime("%Y-%m-%d %H:%M %Z")
|
|
416
414
|
|
|
417
415
|
AuthData = payload[AuthPage_start_byte + 16 : AuthPage_start_byte + 16 + 17]
|
|
@@ -71,8 +71,8 @@ class FunctionsTestCase(unittest.TestCase):
|
|
|
71
71
|
|
|
72
72
|
point = cot_xml.find("point")
|
|
73
73
|
self.assertIsNotNone(point)
|
|
74
|
-
self.assertEqual(point.get("lat"), "37.
|
|
75
|
-
self.assertEqual(point.get("lon"), "-122.
|
|
74
|
+
self.assertEqual(point.get("lat"), "37.7599")
|
|
75
|
+
self.assertEqual(point.get("lon"), "-122.4977")
|
|
76
76
|
self.assertEqual(point.get("ce"), "12")
|
|
77
77
|
self.assertEqual(point.get("le"), "5")
|
|
78
78
|
self.assertEqual(point.get("hae"), "28.0")
|
|
@@ -111,8 +111,8 @@ class FunctionsTestCase(unittest.TestCase):
|
|
|
111
111
|
|
|
112
112
|
point = cot_xml.find("point")
|
|
113
113
|
self.assertIsNotNone(point)
|
|
114
|
-
self.assertEqual(point.get("lat"), "37.
|
|
115
|
-
self.assertEqual(point.get("lon"), "-122.
|
|
114
|
+
self.assertEqual(point.get("lat"), "37.7599")
|
|
115
|
+
self.assertEqual(point.get("lon"), "-122.4977")
|
|
116
116
|
self.assertEqual(point.get("ce"), "12")
|
|
117
117
|
self.assertEqual(point.get("le"), "5")
|
|
118
118
|
self.assertEqual(point.get("hae"), "28.0")
|
|
@@ -151,8 +151,8 @@ class FunctionsTestCase(unittest.TestCase):
|
|
|
151
151
|
|
|
152
152
|
point = cot_xml.find("point")
|
|
153
153
|
self.assertIsNotNone(point)
|
|
154
|
-
self.assertEqual(point.get("lat"), "37.
|
|
155
|
-
self.assertEqual(point.get("lon"), "-122.
|
|
154
|
+
self.assertEqual(point.get("lat"), "37.7599")
|
|
155
|
+
self.assertEqual(point.get("lon"), "-122.4977")
|
|
156
156
|
self.assertEqual(point.get("ce"), "12")
|
|
157
157
|
self.assertEqual(point.get("le"), "5")
|
|
158
158
|
self.assertEqual(point.get("hae"), "28.0")
|
|
@@ -191,8 +191,8 @@ class FunctionsTestCase(unittest.TestCase):
|
|
|
191
191
|
|
|
192
192
|
point = cot_xml.find("point")
|
|
193
193
|
self.assertIsNotNone(point)
|
|
194
|
-
self.assertEqual(point.get("lat"), "37.
|
|
195
|
-
self.assertEqual(point.get("lon"), "-122.
|
|
194
|
+
self.assertEqual(point.get("lat"), "37.7599")
|
|
195
|
+
self.assertEqual(point.get("lon"), "-122.4977")
|
|
196
196
|
self.assertEqual(point.get("ce"), "12")
|
|
197
197
|
self.assertEqual(point.get("le"), "5")
|
|
198
198
|
self.assertEqual(point.get("hae"), "28.0")
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2.2.0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|