Skip to content

Commit

Permalink
Update CHANGELOG
Browse files Browse the repository at this point in the history
  • Loading branch information
ingalls committed May 1, 2024
1 parent 0934022 commit a5d1d83
Show file tree
Hide file tree
Showing 7 changed files with 285 additions and 10 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@

## Version History

### v6.10.0

- :tada: :arrow_up: Add basic support for UAS generated CoTs
- :tada: Add `video` parsing
- :tada: Add `sensor` parsing

### v6.9.1

- :bug: Only pass in _attributes in GeoJSONified Links
Expand Down
23 changes: 20 additions & 3 deletions lib/cot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,14 @@ export default class CoT {
cot.event.detail.takv = { _attributes: { ...feature.properties.takv } };
}

if (feature.properties.sensor) {
cot.event.detail.sensor = { _attributes: { ...feature.properties.sensor } };
}

if (feature.properties.video) {
cot.event.detail.__video = { _attributes: { ...feature.properties.video } };
}

if (feature.properties.contact) {
cot.event.detail.contact = { _attributes: { ...feature.properties.contact } };
}
Expand All @@ -214,9 +222,9 @@ export default class CoT {
cot.event.detail.fileshare = { _attributes: { ...feature.properties.fileshare } };
}

if (feature.properties.speed && feature.properties.course) {
if (feature.properties.course !== undefined || feature.properties.speed !== undefined || feature.properties.slope !== undefined) {
cot.event.detail.track = {
_attributes: Util.cot_track_attr(feature.properties.course, feature.properties.speed)
_attributes: Util.cot_track_attr(feature.properties.course, feature.properties.speed, feature.properties.slope)
}
}

Expand Down Expand Up @@ -338,7 +346,7 @@ export default class CoT {
callsign: raw.event.detail.contact._attributes.callsign || 'UNKNOWN',
center: [ Number(raw.event.point._attributes.lon), Number(raw.event.point._attributes.lat), Number(raw.event.point._attributes.hae) ],
type: raw.event._attributes.type,
how: raw.event._attributes.how,
how: raw.event._attributes.how || '',
time: raw.event._attributes.time,
start: raw.event._attributes.start,
stale: raw.event._attributes.stale,
Expand All @@ -365,6 +373,14 @@ export default class CoT {
feat.properties.fileshare = raw.event.detail.fileshare._attributes;
}

if (raw.event.detail.sensor) {
feat.properties.sensor = raw.event.detail.sensor._attributes;
}

if (raw.event.detail.__video) {
feat.properties.video = raw.event.detail.__video._attributes;
}

if (raw.event.detail.link) {
if (!Array.isArray(raw.event.detail.link)) raw.event.detail.link = [raw.event.detail.link];
feat.properties.links = raw.event.detail.link.filter((link) => {
Expand All @@ -389,6 +405,7 @@ export default class CoT {

if (raw.event.detail.track && raw.event.detail.track._attributes) {
if (raw.event.detail.track._attributes.course) feat.properties.course = Number(raw.event.detail.track._attributes.course);
if (raw.event.detail.track._attributes.slope) feat.properties.slope = Number(raw.event.detail.track._attributes.slope);
if (raw.event.detail.track._attributes.course) feat.properties.speed = Number(raw.event.detail.track._attributes.speed);
}

Expand Down
32 changes: 30 additions & 2 deletions lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export const EventAttributes = Type.Object({
version: Type.String(),
uid: Type.String(),
type: Type.String(),
how: Type.String(),
how: Type.Optional(Type.String()),

time: Type.String(),
stale: Type.String(),
Expand Down Expand Up @@ -57,11 +57,37 @@ export const TrackAttributes = Type.Object({
eSlope: Type.Optional(Type.String())
});


export const Track = Type.Object({
_attributes: TrackAttributes
})

export const SensorAttributes = Type.Object({
elevation: Type.Optional(Type.String()),
vfov: Type.Optional(Type.String()),
fov: Type.Optional(Type.String()),
type: Type.Optional(Type.String()),
version: Type.Optional(Type.String()),
north: Type.Optional(Type.String()),
roll: Type.Optional(Type.String()),
range: Type.Optional(Type.String()),
azimuth: Type.Optional(Type.String()),
model: Type.Optional(Type.String())
});

export const Sensor = Type.Object({
_attributes: SensorAttributes
})

export const VideoAttributes = Type.Object({
sensor: Type.Optional(Type.String()),
spi: Type.Optional(Type.String()),
url: Type.Optional(Type.String())
});

export const Video = Type.Object({
_attributes: VideoAttributes
})

export const Chat = Type.Object({
_attributes: Type.Object({
parent: Type.Optional(Type.String()),
Expand Down Expand Up @@ -179,6 +205,7 @@ export const Detail = Type.Object({
tog: Type.Optional(TogAttributes),
'__group': Type.Optional(Group),
'__chat': Type.Optional(Chat),
'__video': Type.Optional(Video),
'_flow-tags_': Type.Optional(FlowTags),
uid: Type.Optional(Uid),
status: Type.Optional(Status),
Expand All @@ -195,6 +222,7 @@ export const Detail = Type.Object({
link: Type.Optional(Type.Union([Link, Type.Array(Link)])),
usericon: Type.Optional(UserIcon),
track: Type.Optional(Track),
sensor: Type.Optional(Sensor),
takv: Type.Optional(TakVersion),
marti: Type.Optional(Marti),
TakControl: Type.Optional(Type.Object({
Expand Down
13 changes: 8 additions & 5 deletions lib/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,14 @@ export default class Util {
* @param [course] Speed in degrees from north
* @param [speed=0] Speed in m/s
*/
static cot_track_attr(course: number, speed = 0): Static<typeof TrackAttributes> {
return {
course: String(course || 0),
speed: String(speed || 0)
};
static cot_track_attr(course?: number, speed?: number, slope?: number): Static<typeof TrackAttributes> {
const attr: Static<typeof TrackAttributes> = {};

if (course) attr.course = String(course);
if (speed) attr.speed = String(speed);
if (slope) attr.slope = String(slope);

return attr;
}

/**
Expand Down
168 changes: 168 additions & 0 deletions test/cot-uas-tool.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import test from 'tape';
import CoT from '../index.js';

test('Decode iTAK COT message', (t) => {
const packet = '<event version="2" uid="2983J8B001V013" type="a-f-A-M-H-Q" time="2024-04-24T16:37:38.002Z" start="2024-04-24T16:37:38.002Z" stale="2024-04-24T16:37:41.502Z" > <detail> <_uastool extendedCot="" activeRoute="" > </_uastool> <track course="140.8" slope="0" speed="0" > </track> <sensor elevation="0" vfov="41.6" north="320.8000030518" roll="0" range="300" azimuth="140" model="Mavic 2 Enterprise Dual-Visual" fov="66.9" type="r-e" version="0.6" > </sensor> <spatial> <attitude roll="-0.2" pitch="3.8" yaw="140.8" > </attitude> <spin roll="0" pitch="0.0896860987" yaw="0" > </spin> </spatial> <vehicle goHomeBatteryPercent="15" hal="0" flightTimeRemaining="0" typeTag="_DJI_" batteryRemainingCapacity="2216" isFlying="" flightTime="0" type="DJI" batteryMaxCapacity="3672" voltage="15.71" > </vehicle> <_radio rssi="100" gps="" > </_radio> <waypointCollection> </waypointCollection> <_route sender="ANDROID-c96c2c467371208c" > </_route> <commandedData climbRate="0" > </commandedData> <__video sensor="UAS-CO DFPC Lawrence" spi="UAS-CO DFPC Lawrence.SPI1" url="rtsp://18.254.132.96:8554/money" > </__video> <link uid="ANDROID-c96c2c467371208c" type="a-f-G-U-C" relation="p-p" > </link> <_flow-tags_ TAK-Server-e87a0e02420b44a08f6032bcf1877745="2024-04-24T16:37:38Z" > </_flow-tags_> </detail> <point lat="39.1" lon="-108.6" ce="0" hae="1381.333" le="0" > </point></event>';

const cot = new CoT(packet);

if (!cot.raw.event.detail) {
t.fail('No Detail Section')
} else {
t.ok(cot.raw.event.detail['_flow-tags_']);
delete cot.raw.event.detail['_flow-tags_'];

t.deepEquals(cot.raw, {
"event": {
"_attributes": {
"version": "2",
"uid": "2983J8B001V013",
"type": "a-f-A-M-H-Q",
"time": "2024-04-24T16:37:38.002Z",
"start": "2024-04-24T16:37:38.002Z",
"stale": "2024-04-24T16:37:41.502Z"
},
"detail": {
"_uastool": {
"_attributes": {
"extendedCot": "",
"activeRoute": ""
}
},
"track": {
"_attributes": {
"course": "140.8",
"slope": "0",
"speed": "0"
}
},
"sensor": {
"_attributes": {
"elevation": "0",
"vfov": "41.6",
"north": "320.8000030518",
"roll": "0",
"range": "300",
"azimuth": "140",
"model": "Mavic 2 Enterprise Dual-Visual",
"fov": "66.9",
"type": "r-e",
"version": "0.6"
}
},
"spatial": {
"attitude": {
"_attributes": {
"roll": "-0.2",
"pitch": "3.8",
"yaw": "140.8"
}
},
"spin": {
"_attributes": {
"roll": "0",
"pitch": "0.0896860987",
"yaw": "0"
}
}
},
"vehicle": {
"_attributes": {
"goHomeBatteryPercent": "15",
"hal": "0",
"flightTimeRemaining": "0",
"typeTag": "_DJI_",
"batteryRemainingCapacity": "2216",
"isFlying": "",
"flightTime": "0",
"type": "DJI",
"batteryMaxCapacity": "3672",
"voltage": "15.71"
}
},
"_radio": {
"_attributes": {
"rssi": "100",
"gps": ""
}
},
"waypointCollection": {},
"_route": {
"_attributes": {
"sender": "ANDROID-c96c2c467371208c"
}
},
"commandedData": {
"_attributes": {
"climbRate": "0"
}
},
"__video": {
"_attributes": {
"sensor": "UAS-CO DFPC Lawrence",
"spi": "UAS-CO DFPC Lawrence.SPI1",
"url": "rtsp://18.254.132.96:8554/money"
}
},
"link": {
"_attributes": {
"uid": "ANDROID-c96c2c467371208c",
"type": "a-f-G-U-C",
"relation": "p-p"
}
}
},
"point": {
"_attributes": {
"lat": "39.1",
"lon": "-108.6",
"ce": "0",
"hae": "1381.333",
"le": "0"
}
}
}
});

t.deepEquals(cot.to_geojson(), {
id: '2983J8B001V013',
type: 'Feature',
properties: {
callsign: 'UNKNOWN',
center: [ -108.6, 39.1, 1381.333 ],
type: 'a-f-A-M-H-Q',
how: '',
time: '2024-04-24T16:37:38.002Z',
start: '2024-04-24T16:37:38.002Z',
stale: '2024-04-24T16:37:41.502Z',
video: {
sensor: 'UAS-CO DFPC Lawrence',
spi: 'UAS-CO DFPC Lawrence.SPI1',
url: 'rtsp://18.254.132.96:8554/money'
},
sensor: {
elevation: '0',
vfov: '41.6',
north: '320.8000030518',
roll: '0',
range: '300',
azimuth: '140',
model: 'Mavic 2 Enterprise Dual-Visual',
fov: '66.9',
type: 'r-e',
version: '0.6'
},
course: 140.8,
slope: 0,
speed: 0,
metadata: {}
},
geometry: {
type: 'Point',
coordinates: [ -108.6, 39.1, 1381.333 ]
}
});
}

t.end();
});
30 changes: 30 additions & 0 deletions test/fixtures/sensor.geojson
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"id": "123",
"type": "Feature",
"properties": {
"type": "a-f-G",
"how": "m-g",
"callsign": "BasicTest",
"center": [ 1.1, 2.2, 0 ],
"time": "2023-08-04T15:17:43.649Z",
"start": "2023-08-04T15:17:43.649Z",
"stale": "2023-08-04T15:17:43.649Z",
"sensor": {
"elevation": "0",
"vfov": "41.6",
"north": "320.8000030518",
"roll": "0",
"range": "300",
"azimuth": "140",
"model": "Mavic 2 Enterprise Dual-Visual",
"fov": "66.9",
"type": "r-e",
"version": "0.6"
},
"metadata": {}
},
"geometry": {
"type": "Point",
"coordinates": [1.1, 2.2, 0]
}
}
23 changes: 23 additions & 0 deletions test/fixtures/video.geojson
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"id": "123",
"type": "Feature",
"properties": {
"type": "a-f-G",
"how": "m-g",
"callsign": "BasicTest",
"center": [ 1.1, 2.2, 0 ],
"time": "2023-08-04T15:17:43.649Z",
"start": "2023-08-04T15:17:43.649Z",
"stale": "2023-08-04T15:17:43.649Z",
"video": {
"sensor": "UAS-CO DFPC Lawrence",
"spi": "UAS-CO DFPC Lawrence.SPI1",
"url": "rtsp://18.254.132.90:8554/money"
},
"metadata": {}
},
"geometry": {
"type": "Point",
"coordinates": [1.1, 2.2, 0]
}
}

0 comments on commit a5d1d83

Please sign in to comment.