@tak-ps/node-cot 3.5.3 → 4.0.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.
@@ -80,14 +80,14 @@ export interface JSONCoT {
80
80
  *
81
81
  * @prop raw Raw XML-JS representation of CoT
82
82
  */
83
- export default class XMLCot {
83
+ export default class CoT {
84
84
  raw: JSONCoT;
85
85
 
86
86
  constructor(cot: Buffer | JSONCoT | string) {
87
87
  if (typeof cot === 'string' || cot instanceof Buffer) {
88
88
  if (cot instanceof Buffer) cot = String(cot);
89
89
 
90
- const raw: any = xmljs.xml2js(cot, { compact: true });
90
+ const raw = xmljs.xml2js(cot, { compact: true });
91
91
  this.raw = raw as JSONCoT;
92
92
  } else {
93
93
  this.raw = cot;
@@ -100,11 +100,11 @@ export default class XMLCot {
100
100
  }
101
101
 
102
102
  /**
103
- * Return an XMLCot Message
103
+ * Return an CoT Message
104
104
  *
105
105
  * @param {Object} feature GeoJSON Point Feature
106
106
  *
107
- * @return {XMLCot}
107
+ * @return {CoT}
108
108
  */
109
109
  static from_geojson(feature: Feature) {
110
110
  if (feature.type !== 'Feature') throw new Error('Must be GeoJSON Feature');
@@ -199,7 +199,7 @@ export default class XMLCot {
199
199
  cot.event.point._attributes.lat = String(centre.geometry.coordinates[1]);
200
200
  }
201
201
 
202
- return new XMLCot(cot);
202
+ return new CoT(cot);
203
203
  }
204
204
 
205
205
  /**
@@ -226,7 +226,7 @@ export default class XMLCot {
226
226
  type: 'Point',
227
227
  coordinates: [
228
228
  Number(raw.event.point._attributes.lon),
229
- Number(raw.event.point._attributes.lon),
229
+ Number(raw.event.point._attributes.lat),
230
230
  Number(raw.event.point._attributes.hae)
231
231
  ]
232
232
  }
@@ -235,19 +235,15 @@ export default class XMLCot {
235
235
  return geojson;
236
236
  }
237
237
 
238
- to_xml() {
239
- return xmljs.js2xml(this.raw, {
240
- compact: true
241
- });
238
+ to_xml(): string {
239
+ return xmljs.js2xml(this.raw, { compact: true });
242
240
  }
243
241
 
244
242
  /**
245
243
  * Return a CoT Message
246
- *
247
- * @returns {XMLCot}
248
244
  */
249
- static ping() {
250
- return new XMLCot({
245
+ static ping(): CoT {
246
+ return new CoT({
251
247
  event: {
252
248
  _attributes: Util.cot_event_attr('t-x-c-t', 'h-g-i-g-o'),
253
249
  detail: {},
@@ -255,4 +251,166 @@ export default class XMLCot {
255
251
  }
256
252
  });
257
253
  }
254
+
255
+ /**
256
+ * Determines if the CoT message represents a Friendly Element
257
+ *
258
+ * @return {boolean}
259
+ */
260
+ is_friend(): boolean {
261
+ return !!this.raw.event._attributes.type.match(/^a-f-/)
262
+ }
263
+
264
+ /**
265
+ * Determines if the CoT message represents a Hostile Element
266
+ *
267
+ * @return {boolean}
268
+ */
269
+ is_hostile(): boolean {
270
+ return !!this.raw.event._attributes.type.match(/^a-h-/)
271
+ }
272
+
273
+ /**
274
+ * Determines if the CoT message represents a Unknown Element
275
+ *
276
+ * @return {boolean}
277
+ */
278
+ is_unknown(): boolean {
279
+ return !!this.raw.event._attributes.type.match(/^a-u-/)
280
+ }
281
+
282
+ /**
283
+ * Determines if the CoT message represents a Pending Element
284
+ *
285
+ * @return {boolean}
286
+ */
287
+ is_pending(): boolean {
288
+ return !!this.raw.event._attributes.type.match(/^a-p-/)
289
+ }
290
+
291
+ /**
292
+ * Determines if the CoT message represents an Assumed Element
293
+ *
294
+ * @return {boolean}
295
+ */
296
+ is_assumed(): boolean {
297
+ return !!this.raw.event._attributes.type.match(/^a-a-/)
298
+ }
299
+
300
+ /**
301
+ * Determines if the CoT message represents a Neutral Element
302
+ *
303
+ * @return {boolean}
304
+ */
305
+ is_neutral(): boolean {
306
+ return !!this.raw.event._attributes.type.match(/^a-n-/)
307
+ }
308
+
309
+ /**
310
+ * Determines if the CoT message represents a Suspect Element
311
+ *
312
+ * @return {boolean}
313
+ */
314
+ is_suspect(): boolean {
315
+ return !!this.raw.event._attributes.type.match(/^a-s-/)
316
+ }
317
+
318
+ /**
319
+ * Determines if the CoT message represents a Joker Element
320
+ *
321
+ * @return {boolean}
322
+ */
323
+ is_joker(): boolean {
324
+ return !!this.raw.event._attributes.type.match(/^a-j-/)
325
+ }
326
+
327
+ /**
328
+ * Determines if the CoT message represents a Faker Element
329
+ *
330
+ * @return {boolean}
331
+ */
332
+ is_faker(): boolean {
333
+ return !!this.raw.event._attributes.type.match(/^a-k-/)
334
+ }
335
+
336
+ /**
337
+ * Determines if the CoT message represents an Element
338
+ *
339
+ * @return {boolean}
340
+ */
341
+ is_atom(): boolean {
342
+ return !!this.raw.event._attributes.type.match(/^a-/)
343
+ }
344
+
345
+ /**
346
+ * Determines if the CoT message represents an Airborne Element
347
+ *
348
+ * @return {boolean}
349
+ */
350
+ is_airborne(): boolean {
351
+ return !!this.raw.event._attributes.type.match(/^a-.-A/)
352
+ }
353
+
354
+ /**
355
+ * Determines if the CoT message represents a Ground Element
356
+ *
357
+ * @return {boolean}
358
+ */
359
+ is_ground(): boolean {
360
+ return !!this.raw.event._attributes.type.match(/^a-.-G/)
361
+ }
362
+
363
+ /**
364
+ * Determines if the CoT message represents an Installation
365
+ *
366
+ * @return {boolean}
367
+ */
368
+ is_installation(): boolean {
369
+ return !!this.raw.event._attributes.type.match(/^a-.-G-I/)
370
+ }
371
+
372
+ /**
373
+ * Determines if the CoT message represents a Vehicle
374
+ *
375
+ * @return {boolean}
376
+ */
377
+ is_vehicle(): boolean {
378
+ return !!this.raw.event._attributes.type.match(/^a-.-G-E-V/)
379
+ }
380
+
381
+ /**
382
+ * Determines if the CoT message represents Equipment
383
+ *
384
+ * @return {boolean}
385
+ */
386
+ is_equipment(): boolean {
387
+ return !!this.raw.event._attributes.type.match(/^a-.-G-E/)
388
+ }
389
+
390
+ /**
391
+ * Determines if the CoT message represents a Surface Element
392
+ *
393
+ * @return {boolean}
394
+ */
395
+ is_surface(): boolean {
396
+ return !!this.raw.event._attributes.type.match(/^a-.-S/)
397
+ }
398
+
399
+ /**
400
+ * Determines if the CoT message represents a Subsurface Element
401
+ *
402
+ * @return {boolean}
403
+ */
404
+ is_subsurface(): boolean {
405
+ return !!this.raw.event._attributes.type.match(/^a-.-U/)
406
+ }
407
+
408
+ /**
409
+ * Determines if the CoT message represents a UAV Element
410
+ *
411
+ * @return {boolean}
412
+ */
413
+ is_uav(): boolean {
414
+ return !!this.raw.event._attributes.type.match(/^a-f-A-M-F-Q-r/)
415
+ }
258
416
  }
package/lib/util.ts CHANGED
@@ -4,7 +4,7 @@ import type {
4
4
  TrackAttributes,
5
5
  Detail,
6
6
  Point
7
- } from './xml.js';
7
+ } from './cot.js';
8
8
 
9
9
  /**
10
10
  * Helper functions for generating CoT data
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tak-ps/node-cot",
3
3
  "type": "module",
4
- "version": "3.5.3",
4
+ "version": "4.0.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",
@@ -26,8 +26,8 @@
26
26
  "devDependencies": {
27
27
  "@types/node": "^20.0.0",
28
28
  "@types/tape": "^5.6.0",
29
- "@typescript-eslint/eslint-plugin": "^5.54.0",
30
- "@typescript-eslint/parser": "^5.54.0",
29
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
30
+ "@typescript-eslint/parser": "^6.0.0",
31
31
  "eslint": "^8.35.0",
32
32
  "eslint-plugin-node": "^11.1.0",
33
33
  "tape": "^5.6.1",
package/test/cot.test.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import test from 'tape';
2
- import { XML } from '../index.js';
2
+ import CoT from '../index.js';
3
3
 
4
4
  test('Decode COT message', (t) => {
5
5
  const packet = '<event version="2.0" uid="ANDROID-deadbeef" type="a-f-G-U-C" how="m-g" time="2021-02-27T20:32:24.771Z" start="2021-02-27T20:32:24.771Z" stale="2021-02-27T20:38:39.771Z"><point lat="1.234567" lon="-3.141592" hae="-25.7" ce="9.9" le="9999999.0"/><detail><takv os="29" version="4.0.0.0 (deadbeef).1234567890-CIV" device="Some Android Device" platform="ATAK-CIV"/><contact xmppUsername="xmpp@host.com" endpoint="*:-1:stcp" callsign="JENNY"/><uid Droid="JENNY"/><precisionlocation altsrc="GPS" geopointsrc="GPS"/><__group role="Team Member" name="Cyan"/><status battery="78"/><track course="80.24833892285461" speed="0.0"/></detail></event>';
6
6
 
7
- t.deepEquals((new XML(packet)).raw, {
7
+ t.deepEquals((new CoT(packet)).raw, {
8
8
  'event': {
9
9
  '_attributes': {
10
10
  'version': '2.0',
@@ -55,7 +55,7 @@ test('Decode COT message', (t) => {
55
55
  test('Decode COT message', (t) => {
56
56
  const packet = '<event version="2.0" uid="TEST-deadbeef" type="a" how="m-g" time="2021-03-12T15:49:07.138Z" start="2021-03-12T15:49:07.138Z" stale="2021-03-12T15:49:07.138Z"><point lat="0.000000" lon="0.000000" hae="0.0" ce="9999999.0" le="9999999.0"/><detail><takv os="Android" version="10" device="Some Device" platform="python unittest"/><status battery="83"/><uid Droid="JENNY"/><contact callsign="JENNY" endpoint="*:-1:stcp" phone="800-867-5309"/><__group role="Team Member" name="Cyan"/><track course="90.1" speed="10.3"/></detail></event>';
57
57
 
58
- t.deepEquals((new XML(packet)).raw, {
58
+ t.deepEquals((new CoT(packet)).raw, {
59
59
  'event': {
60
60
  '_attributes': {
61
61
  'version': '2.0',
@@ -167,7 +167,7 @@ test('Encode COT message', (t) => {
167
167
  };
168
168
 
169
169
  t.deepEquals(
170
- (new XML(packet)).to_xml(),
170
+ (new CoT(packet)).to_xml(),
171
171
  '<event version="2.0" uid="ANDROID-deadbeef" type="a-f-G-U-C" how="m-g" time="2021-02-27T20:32:24.771Z" start="2021-02-27T20:32:24.771Z" stale="2021-02-27T20:38:39.771Z"><point lat="1.234567" lon="-3.141592" hae="-25.7" ce="9.9" le="9999999"/><detail><takv os="29" version="4.0.0.0 (deadbeef).1234567890-CIV" device="Some Android Device" platform="ATAK-CIV"/><contact xmppUsername="xmpp@host.com" endpoint="*:-1:stcp" callsign="JENNY"/><uid Droid="JENNY"/><precisionlocation altsrc="GPS" geopointsrc="GPS"/><__group role="Team Member" name="Cyan"/><status battery="78"/><track course="80.24833892285461" speed="0.0"/></detail></event>'
172
172
  );
173
173
 
@@ -190,7 +190,7 @@ test('Parse GeoChat message', (t) => {
190
190
  ' </detail>\n' +
191
191
  '</event>';
192
192
 
193
- t.deepEquals((new XML(geochat)).raw, {
193
+ t.deepEquals((new CoT(geochat)).raw, {
194
194
  'event': {
195
195
  '_attributes': {
196
196
  'version': '2.0',