@tak-ps/node-cot 12.10.0 → 12.12.0

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.
@@ -362,7 +362,7 @@ export class DataPackage {
362
362
  * @param opts.ignore - Should the file be ignore, defaults to false
363
363
  * @param opts.attachment - Should the file be associated as an attachment to a CoT. If so this should contain the UID of the CoT
364
364
  */
365
- async addFile(file: Readable, opts: {
365
+ async addFile(file: Readable | Buffer | string, opts: {
366
366
  uid?: string;
367
367
  name: string;
368
368
  ignore?: boolean;
@@ -6,6 +6,7 @@ import {
6
6
  GeofenceAttributes,
7
7
  StatusAttributes,
8
8
  PrecisionLocationAttributes,
9
+ VideoConnectionEntryAttributes,
9
10
  MartiDestAttributes,
10
11
  TakVersionAttributes,
11
12
  FileShareAttributes,
@@ -88,7 +89,12 @@ export const InputProperties = Type.Object({
88
89
  attachments: Type.Optional(Type.Array(Type.String())),
89
90
  ackrequest: Type.Optional(ACKRequestAttributes),
90
91
  sensor: Type.Optional(SensorAttributes),
91
- video: Type.Optional(VideoAttributes),
92
+ video: Type.Optional(Type.Composite([
93
+ VideoAttributes,
94
+ Type.Optional(Type.Object({
95
+ connection: Type.Optional(VideoConnectionEntryAttributes)
96
+ }))
97
+ ])),
92
98
  links: Type.Optional(Type.Array(LinkAttributes)),
93
99
  chat: Type.Optional(Type.Object({
94
100
  parent: Type.Optional(Type.String()),
@@ -145,7 +151,12 @@ export const Properties = Type.Object({
145
151
  ackrequest: Type.Optional(ACKRequestAttributes),
146
152
  attachments: Type.Optional(Type.Array(Type.String())),
147
153
  sensor: Type.Optional(SensorAttributes),
148
- video: Type.Optional(VideoAttributes),
154
+ video: Type.Optional(Type.Composite([
155
+ VideoAttributes,
156
+ Type.Optional(Type.Object({
157
+ connection: Type.Optional(VideoConnectionEntryAttributes)
158
+ }))
159
+ ])),
149
160
  links: Type.Optional(Type.Array(LinkAttributes)),
150
161
  chat: Type.Optional(Type.Object({
151
162
  parent: Type.Optional(Type.String()),
@@ -261,6 +261,7 @@ export const Sensor = Type.Object({
261
261
  })
262
262
 
263
263
  export const VideoAttributes = Type.Object({
264
+ uid: Type.Optional(Type.String()),
264
265
  sensor: Type.Optional(Type.String()),
265
266
  spi: Type.Optional(Type.String()),
266
267
  url: Type.Optional(Type.String())
@@ -281,12 +282,12 @@ export const VideoConnectionEntryAttributes = Type.Object({
281
282
  })
282
283
 
283
284
  export const VideoConnectionEntry = Type.Object({
284
- _attributes: Type.Optional(VideoConnectionEntryAttributes)
285
+ _attributes: VideoConnectionEntryAttributes
285
286
  })
286
287
 
287
288
  export const Video = Type.Object({
288
289
  _attributes: Type.Optional(VideoAttributes),
289
- ConnectionEntry: Type.Optional(Type.Union([Type.Array(VideoConnectionEntry), VideoConnectionEntry]))
290
+ ConnectionEntry: Type.Optional(VideoConnectionEntry)
290
291
  })
291
292
 
292
293
  export const GeofenceAttributes = Type.Object({
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tak-ps/node-cot",
3
3
  "type": "module",
4
- "version": "12.10.0",
4
+ "version": "12.12.0",
5
5
  "description": "Lightweight JavaScript library for parsing and manipulating TAK messages",
6
6
  "author": "Nick Ingalls <nick@ingalls.ca>",
7
7
  "main": "dist/index.js",
@@ -1,6 +1,60 @@
1
1
  import test from 'tape';
2
2
  import CoT from '../index.js';
3
3
 
4
+ test('CoT.addVideo', (t) => {
5
+ const cot = new CoT(`<event version='2.0' uid='0ed16b9e-a0c8-480f-8860-284b9afb2b1d' type='b-m-p-s-p-loc' time='2023-11-15T20:48:16.097Z' start='2023-11-15T20:48:16.097Z' stale='2024-11-14T20:48:16.097Z' how='h-g-i-g-o' access='Undefined'><point lat='38.2089117' lon='-104.6282182' hae='1455.285' ce='9999999.0' le='9999999.0' /></event>`);
6
+
7
+ cot.addVideo({ uid: '123', url: 'https://publicstreamer3.cotrip.org/rtplive/123/playlist.m3u8' })
8
+
9
+ if (!cot.raw.event.detail) {
10
+ throw new Error('Detail Object must be populated');
11
+ }
12
+
13
+ t.ok(cot.raw.event.detail['_flow-tags_']);
14
+ delete cot.raw.event.detail['_flow-tags_'];
15
+
16
+ t.deepEquals(cot.raw, {
17
+ event: {
18
+ _attributes: {
19
+ version: '2.0',
20
+ uid: '0ed16b9e-a0c8-480f-8860-284b9afb2b1d',
21
+ type: 'b-m-p-s-p-loc',
22
+ time: '2023-11-15T20:48:16.097Z',
23
+ start: '2023-11-15T20:48:16.097Z',
24
+ stale: '2024-11-14T20:48:16.097Z',
25
+ how: 'h-g-i-g-o',
26
+ access: 'Undefined'
27
+ },
28
+ point: { _attributes: { lat: '38.2089117', lon: '-104.6282182', hae: '1455.285', ce: '9999999.0', le: '9999999.0' } },
29
+ detail: {
30
+ __video: {
31
+ _attributes: {
32
+ url: 'https://publicstreamer3.cotrip.org/rtplive/123/playlist.m3u8',
33
+ uid: '123'
34
+ },
35
+ ConnectionEntry: {
36
+ _attributes: {
37
+ uid: '123',
38
+ networkTimeout: 12000,
39
+ path: '',
40
+ protocol: 'raw',
41
+ bufferTime: -1,
42
+ address: 'https://publicstreamer3.cotrip.org/rtplive/123/playlist.m3u8',
43
+ port: -1,
44
+ roverPort: -1,
45
+ rtspReliable: 0,
46
+ ignoreEmbeddedKLV: false,
47
+ alias: 'UNKNOWN'
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }
53
+ });
54
+
55
+ t.end();
56
+ });
57
+
4
58
  test('Decode MultiMissionAircraft CoTs', (t) => {
5
59
  const cot = new CoT(`<event version='2.0' uid='0ed16b9e-a0c8-480f-8860-284b9afb2b1d' type='b-m-p-s-p-loc' time='2023-11-15T20:48:16.097Z' start='2023-11-15T20:48:16.097Z' stale='2024-11-14T20:48:16.097Z' how='h-g-i-g-o' access='Undefined'><point lat='38.2089117' lon='-104.6282182' hae='1455.285' ce='9999999.0' le='9999999.0' /><detail><status readiness='true'/><archive/><__video uid='05bf6c59-c7ea-465f-8337-da16ddcc82d4' url='https://publicstreamer3.cotrip.org/rtplive/123/playlist.m3u8'><ConnectionEntry networkTimeout='12000' uid='05bf6c59-c7ea-465f-8337-da16ddcc82d4' path='' protocol='raw' bufferTime='-1' address='https://publicstreamer3.cotrip.org/rtplive/123/playlist.m3u8' port='-1' roverPort='-1' rtspReliable='0' ignoreEmbeddedKLV='false' alias='I-25 .8 mi S CO-45'/></__video><color argb='-1'/><link uid='ANDROID-94e13cc4880cbcce' production_time='2022-01-31T17:35:49.565Z' type='a-f-G-U-C' parent_callsign='CO-DFPC-54-Schmidt' relation='p-p'/><sensor vfov='45' elevation='0' fovBlue='1.0' fovRed='1.0' strokeWeight='0.0' roll='0' range='100' azimuth='270' rangeLineStrokeWeight='0.0' fov='45' hideFov='true' rangeLineStrokeColor='-3355444' fovGreen='1.0' displayMagneticReference='0' strokeColor='-16777216' rangeLines='100' fovAlpha='0.2980392156862745'/><archive/><contact callsign='I-25 .8 mi S CO-45'/><remarks></remarks><precisionlocation altsrc='DTED2'/></detail></event>`);
6
60
  if (!cot.raw.event.detail) {
@@ -114,7 +168,23 @@ test('Decode MultiMissionAircraft CoTs', (t) => {
114
168
  rangeLines: 100,
115
169
  fovAlpha: 0.2980392156862745
116
170
  },
117
- video: { uid: '05bf6c59-c7ea-465f-8337-da16ddcc82d4', url: 'https://publicstreamer3.cotrip.org/rtplive/123/playlist.m3u8' },
171
+ video: {
172
+ uid: '05bf6c59-c7ea-465f-8337-da16ddcc82d4',
173
+ url: 'https://publicstreamer3.cotrip.org/rtplive/123/playlist.m3u8',
174
+ connection: {
175
+ "networkTimeout": 12000,
176
+ "uid": "05bf6c59-c7ea-465f-8337-da16ddcc82d4",
177
+ "path": "",
178
+ "protocol": "raw",
179
+ "bufferTime": -1,
180
+ "address": "https://publicstreamer3.cotrip.org/rtplive/123/playlist.m3u8",
181
+ "port": -1,
182
+ "roverPort": -1,
183
+ "rtspReliable": 0,
184
+ "ignoreEmbeddedKLV": false,
185
+ "alias": "I-25 .8 mi S CO-45"
186
+ }
187
+ },
118
188
  archived: true,
119
189
  status: { readiness: 'true' },
120
190
  precisionlocation: { altsrc: 'DTED2' },
@@ -0,0 +1,26 @@
1
+ {
2
+ "id": "123",
3
+ "type": "Feature",
4
+ "properties": {
5
+ "type": "a-f-G",
6
+ "how": "m-g",
7
+ "callsign": "BasicTest",
8
+ "center": [ 1.1, 2.2, 0 ],
9
+ "time": "2023-08-04T15:17:43.649Z",
10
+ "start": "2023-08-04T15:17:43.649Z",
11
+ "stale": "2023-08-04T15:17:43.649Z",
12
+ "video": {
13
+ "uid": "123",
14
+ "url": "rtsp://18.254.132.90:8554/money",
15
+ "connection": {
16
+ "uid": "123",
17
+ "address": "rtsp://18.254.132.90:8554/money"
18
+ }
19
+ },
20
+ "metadata": {}
21
+ },
22
+ "geometry": {
23
+ "type": "Point",
24
+ "coordinates": [1.1, 2.2, 0]
25
+ }
26
+ }
@@ -11,6 +11,7 @@ for (const fixturename of await fs.readdir(new URL('./fixtures/', import.meta.ur
11
11
  const fixture: Static<typeof Feature> = JSON.parse(String(await fs.readFile(path.join(path.parse(fileURLToPath(import.meta.url)).dir, 'fixtures/', fixturename))));
12
12
  const geo = CoT.from_geojson(fixture)
13
13
  const output = geo.to_geojson();
14
+
14
15
  t.deepEquals(fixture, output, fixturename);
15
16
 
16
17
  t.end();