node-red-contrib-tak-registration 0.8.3 → 0.10.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.
Files changed (63) hide show
  1. package/README.md +5 -0
  2. package/node_modules/@types/node/README.md +1 -1
  3. package/node_modules/@types/node/async_hooks.d.ts +2 -0
  4. package/node_modules/@types/node/fs.d.ts +12 -7
  5. package/node_modules/@types/node/http.d.ts +40 -8
  6. package/node_modules/@types/node/index.d.ts +1 -1
  7. package/node_modules/@types/node/inspector.d.ts +2 -2
  8. package/node_modules/@types/node/module.d.ts +29 -4
  9. package/node_modules/@types/node/package.json +2 -2
  10. package/node_modules/@types/node/process.d.ts +3 -2
  11. package/node_modules/@types/node/ts4.8/async_hooks.d.ts +2 -0
  12. package/node_modules/@types/node/ts4.8/fs.d.ts +12 -7
  13. package/node_modules/@types/node/ts4.8/http.d.ts +40 -8
  14. package/node_modules/@types/node/ts4.8/inspector.d.ts +2 -2
  15. package/node_modules/@types/node/ts4.8/module.d.ts +29 -4
  16. package/node_modules/@types/node/ts4.8/process.d.ts +3 -2
  17. package/node_modules/@types/node/ts4.8/worker_threads.d.ts +2 -1
  18. package/node_modules/@types/node/worker_threads.d.ts +2 -1
  19. package/node_modules/define-data-property/.eslintrc +24 -0
  20. package/node_modules/define-data-property/.github/FUNDING.yml +12 -0
  21. package/node_modules/define-data-property/.nycrc +13 -0
  22. package/node_modules/define-data-property/CHANGELOG.md +31 -0
  23. package/node_modules/define-data-property/LICENSE +21 -0
  24. package/node_modules/define-data-property/README.md +67 -0
  25. package/node_modules/define-data-property/index.d.ts +3 -0
  26. package/node_modules/define-data-property/index.d.ts.map +1 -0
  27. package/node_modules/define-data-property/index.js +60 -0
  28. package/node_modules/define-data-property/package.json +111 -0
  29. package/node_modules/define-data-property/test/index.js +397 -0
  30. package/node_modules/define-data-property/tsconfig.json +58 -0
  31. package/node_modules/define-data-property/tsinit +109 -0
  32. package/node_modules/define-properties/CHANGELOG.md +8 -0
  33. package/node_modules/define-properties/index.js +5 -11
  34. package/node_modules/define-properties/package.json +5 -4
  35. package/node_modules/gopd/.eslintrc +16 -0
  36. package/node_modules/gopd/.github/FUNDING.yml +12 -0
  37. package/node_modules/gopd/CHANGELOG.md +25 -0
  38. package/node_modules/gopd/LICENSE +21 -0
  39. package/node_modules/gopd/README.md +40 -0
  40. package/node_modules/gopd/index.js +16 -0
  41. package/node_modules/gopd/package.json +71 -0
  42. package/node_modules/gopd/test/index.js +35 -0
  43. package/node_modules/regexp.prototype.flags/.eslintrc +1 -0
  44. package/node_modules/regexp.prototype.flags/CHANGELOG.md +8 -0
  45. package/node_modules/regexp.prototype.flags/implementation.js +3 -6
  46. package/node_modules/regexp.prototype.flags/package.json +8 -7
  47. package/node_modules/set-function-name/.eslintrc +20 -0
  48. package/node_modules/set-function-name/.github/FUNDING.yml +12 -0
  49. package/node_modules/set-function-name/CHANGELOG.md +39 -0
  50. package/node_modules/set-function-name/LICENSE +21 -0
  51. package/node_modules/set-function-name/README.md +61 -0
  52. package/node_modules/set-function-name/index.js +22 -0
  53. package/node_modules/set-function-name/package.json +80 -0
  54. package/node_modules/uuid/CHANGELOG.md +6 -0
  55. package/node_modules/uuid/README.md +9 -5
  56. package/node_modules/uuid/dist/commonjs-browser/stringify.js +1 -1
  57. package/node_modules/uuid/dist/esm-browser/stringify.js +1 -1
  58. package/node_modules/uuid/dist/esm-node/stringify.js +1 -1
  59. package/node_modules/uuid/dist/stringify.js +1 -1
  60. package/node_modules/uuid/package.json +7 -3
  61. package/package.json +2 -2
  62. package/tak-registration.html +9 -2
  63. package/tak-registration.js +110 -48
@@ -2,6 +2,7 @@
2
2
  -- This file is auto-generated from README_js.md. Changes should be made there.
3
3
  -->
4
4
 
5
+
5
6
  # uuid [![CI](https://github.com/uuidjs/uuid/workflows/CI/badge.svg)](https://github.com/uuidjs/uuid/actions?query=workflow%3ACI) [![Browser](https://github.com/uuidjs/uuid/workflows/Browser/badge.svg)](https://github.com/uuidjs/uuid/actions?query=workflow%3ABrowser)
6
7
 
7
8
  For the creation of [RFC4122](https://www.ietf.org/rfc/rfc4122.txt) UUIDs
@@ -9,7 +10,7 @@ For the creation of [RFC4122](https://www.ietf.org/rfc/rfc4122.txt) UUIDs
9
10
  - **Complete** - Support for RFC4122 version 1, 3, 4, and 5 UUIDs
10
11
  - **Cross-platform** - Support for ...
11
12
  - CommonJS, [ECMAScript Modules](#ecmascript-modules) and [CDN builds](#cdn-builds)
12
- - Node 12, 14, 16, 18
13
+ - NodeJS 12+ ([LTS releases](https://github.com/nodejs/Release))
13
14
  - Chrome, Safari, Firefox, Edge browsers
14
15
  - Webpack and rollup.js module bundlers
15
16
  - [React Native / Expo](#react-native--expo)
@@ -17,7 +18,9 @@ For the creation of [RFC4122](https://www.ietf.org/rfc/rfc4122.txt) UUIDs
17
18
  - **Small** - Zero-dependency, small footprint, plays nice with "tree shaking" packagers
18
19
  - **CLI** - Includes the [`uuid` command line](#command-line) utility
19
20
 
20
- **Upgrading from `uuid@3`?** Your code is probably okay, but check out [Upgrading From `uuid@3`](#upgrading-from-uuid3) for details.
21
+ > **Note** Upgrading from `uuid@3`? Your code is probably okay, but check out [Upgrading From `uuid@3`](#upgrading-from-uuid3) for details.
22
+
23
+ > **Note** Only interested in creating a version 4 UUID? You might be able to use [`crypto.randomUUID()`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/randomUUID), eliminating the need to install this library.
21
24
 
22
25
  ## Quickstart
23
26
 
@@ -138,7 +141,7 @@ Create an RFC version 1 (timestamp) UUID
138
141
  | [`options.node` ] | RFC "node" field as an `Array[6]` of byte values (per 4.1.6) |
139
142
  | [`options.clockseq`] | RFC "clock sequence" as a `Number` between 0 - 0x3fff |
140
143
  | [`options.msecs`] | RFC "timestamp" field (`Number` of milliseconds, unix epoch) |
141
- | [`options.nsecs`] | RFC "timestamp" field (`Number` of nanseconds to add to `msecs`, should be 0-10,000) |
144
+ | [`options.nsecs`] | RFC "timestamp" field (`Number` of nanoseconds to add to `msecs`, should be 0-10,000) |
142
145
  | [`options.random`] | `Array` of 16 random bytes (0-255) |
143
146
  | [`options.rng`] | Alternative to `options.random`, a `Function` that returns an `Array` of 16 random bytes (0-255) |
144
147
  | [`buffer`] | `Array \| Buffer` If specified, uuid will be written here in byte-form, starting at `offset` |
@@ -458,5 +461,6 @@ const uuid = require('uuid'); // <== REMOVED!
458
461
 
459
462
  This usage pattern was already discouraged in `uuid@3` and has been removed in `uuid@7`.
460
463
 
461
- ----
462
- Markdown generated from [README_js.md](README_js.md) by [![RunMD Logo](https://i.imgur.com/h0FVyzU.png)](https://github.com/broofa/runmd)
464
+ ---
465
+
466
+ Markdown generated from [README_js.md](README_js.md) by <a href="https://github.com/broofa/runmd"><image height="12px" src="https://camo.githubusercontent.com/5c7c603cd1e6a43370b0a5063d457e0dabb74cf317adc7baba183acb686ee8d0/687474703a2f2f692e696d6775722e636f6d2f634a4b6f3662552e706e67" /></a>
@@ -23,7 +23,7 @@ for (let i = 0; i < 256; ++i) {
23
23
  function unsafeStringify(arr, offset = 0) {
24
24
  // Note: Be careful editing this code! It's been tuned for performance
25
25
  // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
26
- return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
26
+ return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
27
27
  }
28
28
 
29
29
  function stringify(arr, offset = 0) {
@@ -13,7 +13,7 @@ for (let i = 0; i < 256; ++i) {
13
13
  export function unsafeStringify(arr, offset = 0) {
14
14
  // Note: Be careful editing this code! It's been tuned for performance
15
15
  // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
16
- return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
16
+ return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
17
17
  }
18
18
 
19
19
  function stringify(arr, offset = 0) {
@@ -13,7 +13,7 @@ for (let i = 0; i < 256; ++i) {
13
13
  export function unsafeStringify(arr, offset = 0) {
14
14
  // Note: Be careful editing this code! It's been tuned for performance
15
15
  // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
16
- return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
16
+ return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
17
17
  }
18
18
 
19
19
  function stringify(arr, offset = 0) {
@@ -23,7 +23,7 @@ for (let i = 0; i < 256; ++i) {
23
23
  function unsafeStringify(arr, offset = 0) {
24
24
  // Note: Be careful editing this code! It's been tuned for performance
25
25
  // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
26
- return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
26
+ return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
27
27
  }
28
28
 
29
29
  function stringify(arr, offset = 0) {
@@ -1,7 +1,11 @@
1
1
  {
2
2
  "name": "uuid",
3
- "version": "9.0.0",
3
+ "version": "9.0.1",
4
4
  "description": "RFC4122 (v1, v4, and v5) UUIDs",
5
+ "funding": [
6
+ "https://github.com/sponsors/broofa",
7
+ "https://github.com/sponsors/ctavan"
8
+ ],
5
9
  "commitlint": {
6
10
  "extends": [
7
11
  "@commitlint/config-conventional"
@@ -71,7 +75,7 @@
71
75
  "optional-dev-dependency": "2.0.1",
72
76
  "prettier": "2.7.1",
73
77
  "random-seed": "0.3.0",
74
- "runmd": "1.3.6",
78
+ "runmd": "1.3.9",
75
79
  "standard-version": "9.5.0"
76
80
  },
77
81
  "optionalDevDependencies": {
@@ -105,7 +109,7 @@
105
109
  "prettier:fix": "prettier --write '**/*.{js,jsx,json,md}'",
106
110
  "bundlewatch": "npm run pretest:browser && bundlewatch --config bundlewatch.config.json",
107
111
  "md": "runmd --watch --output=README.md README_js.md",
108
- "docs": "( node --version | grep -q 'v16' ) && ( npm run build && runmd --output=README.md README_js.md )",
112
+ "docs": "( node --version | grep -q 'v18' ) && ( npm run build && npx runmd --output=README.md README_js.md )",
109
113
  "docs:diff": "npm run docs && git diff --quiet README.md",
110
114
  "build": "./scripts/build.sh",
111
115
  "prepack": "npm run build",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-tak-registration",
3
- "version": "0.8.3",
3
+ "version": "0.10.0",
4
4
  "description": "A Node-RED node to register to TAK and to help wrap files as datapackages to send to TAK",
5
5
  "dependencies": {
6
6
  "@turf/turf": "6.5.0",
@@ -10,7 +10,7 @@
10
10
  "form-data": "4.0.0",
11
11
  "long": "5.2.3",
12
12
  "protobufjs": "7.2.5",
13
- "uuid": "9.0.0"
13
+ "uuid": "9.0.1"
14
14
  },
15
15
  "bundledDependencies": [
16
16
  "@turf/turf",
@@ -58,7 +58,7 @@
58
58
  </div>
59
59
  <div class="form-row">
60
60
  <label for="node-input-dphost"><i class="fa fa-globe"></i> DP-Host url:port</label>
61
- <input type="text" id="node-input-dphost" placeholder="Data package url http://server:port">
61
+ <input type="text" id="node-input-dphost" placeholder="Data package server url http://server:port">
62
62
  </div>
63
63
  <div class="form-row">
64
64
  <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
@@ -66,7 +66,7 @@
66
66
  </div>
67
67
  <div class="form-tips" id="pin-tip"><b>Note</b>: This node MUST be used in conjunction with a TCP request node,
68
68
  configured to point to your TAK server tcp address and port (usually 8087 or 8089), set to return strings,
69
- <i>keep connection open</i> mode, and split on "&lt;/event&gt;"</div>
69
+ <i>keep connection open</i> mode, and split on <code>&lt;/event&gt;</code></div>
70
70
  </script>
71
71
  <style>
72
72
  .inject-time-count {
@@ -138,7 +138,14 @@
138
138
  <dt>attachments <span class="property-type">array of objects</span></dt>
139
139
  <dd>each object must contain at least a <b>filename</b> (string) and <b>content</b> a buffer of the file/data.
140
140
  eg <code>[{filename:"foo.kml", content: &lt;buffer of the file&gt;}]</code></dd>
141
+ <dt>from <span class="property-type">string</span></dt>
142
+ <dd>(optional) callsign of the person sending the file - defaults to the gateway node callsign.</dd>
143
+ <dt>lat <span class="property-type">number | (string)</span></dt>
144
+ <dd>(optional) latitude of the marker for the file.</dd>
145
+ <dt>lon <span class="property-type">number | (string)</span></dt>
146
+ <dd>(optional) longitude of the marker for the file.</dd>
141
147
  </dl>
148
+ If you just need to send a single file then you can use <code>msg.filename</code> to set the filename and the <code>msg.payload</code> should be a binary buffer.
142
149
 
143
150
  <h3>Sending simple GeoChat messages...</h3>
144
151
  <dl class="message-properties">
@@ -1,7 +1,7 @@
1
1
  const { methodToString } = require('adm-zip/util');
2
2
  const { isArray } = require('util');
3
3
 
4
- module.exports = function(RED) {
4
+ module.exports = function (RED) {
5
5
  "use strict";
6
6
  const os = require('os');
7
7
  const AdmZip = require('adm-zip');
@@ -12,10 +12,10 @@ module.exports = function(RED) {
12
12
  const uuid = require('uuid');
13
13
  const turf = require("@turf/turf");
14
14
  const ver = require('./package.json').version;
15
- const teamList = ["Cyan","Red","Green","Blue","Magenta","Yellow","Orange","Maroon","Purple","Dark Blue","Dark Green","Teal","Brown"];
15
+ const teamList = ["Cyan", "Red", "Green", "Blue", "Magenta", "Yellow", "Orange", "Maroon", "Purple", "Dark Blue", "Dark Green", "Teal", "Brown"];
16
16
 
17
17
  function TakRegistrationNode(n) {
18
- RED.nodes.createNode(this,n);
18
+ RED.nodes.createNode(this, n);
19
19
  const invalid = "9999999.0";
20
20
  this.group = n.group;
21
21
  this.role = n.role || "Gateway";
@@ -25,17 +25,17 @@ module.exports = function(RED) {
25
25
  this.callsign = n.callsign;
26
26
  this.repeat = n.repeat;
27
27
  this.host = n.dphost;
28
- this.uuid = "GATEWAY-"+(crypto.createHash('md5').update(Buffer.from(this.id)).digest('hex')).slice(0,16);
28
+ this.uuid = "GATEWAY-" + (crypto.createHash('md5').update(Buffer.from(this.id)).digest('hex')).slice(0, 16);
29
29
  var node = this;
30
30
  node.alt = invalid;
31
31
  var globalContext = this.context().global;
32
32
  var g = {};
33
33
  g[node.uuid] = node.callsign;
34
- globalContext.set("_takgatewayid",g);
34
+ globalContext.set("_takgatewayid", g);
35
35
  var gr = {};
36
36
  gr[node.callsign] = node.uuid;
37
- globalContext.set("_takgatewaycs",gr);
38
- globalContext.set("_takdphost",node.host);
37
+ globalContext.set("_takgatewaycs", gr);
38
+ globalContext.set("_takdphost", node.host);
39
39
 
40
40
  if (node.role !== "Gateway") { node.ntype = "a-f-G-U-C" }
41
41
 
@@ -44,13 +44,13 @@ module.exports = function(RED) {
44
44
  delete node.repeat;
45
45
  }
46
46
 
47
- var convertWMtoKMLColour = function(colour,opacity) {
47
+ var convertWMtoKMLColour = function (colour, opacity) {
48
48
  if (opacity == undefined) { opacity = 100; }
49
49
  var alfa = parseInt(opacity * 255 / 100).toString(16);
50
50
  return alfa + colour;
51
51
  };
52
52
 
53
- var convertWMtoCOTColour = function(colour,opacity) {
53
+ var convertWMtoCOTColour = function (colour, opacity) {
54
54
  var c;
55
55
  if (opacity != undefined) {
56
56
  c = Buffer.from(parseInt(opacity * 255 / 100).toString(16) + colour, "hex");
@@ -61,7 +61,7 @@ module.exports = function(RED) {
61
61
  return c.readInt32BE()
62
62
  };
63
63
 
64
- var findCentroidOfPoints = function(points) {
64
+ var findCentroidOfPoints = function (points) {
65
65
  if (points.length < 4) { // pad if necessary (needs 4 points minimum)
66
66
  points.push(points[2]);
67
67
  points.unshift(points[0]);
@@ -71,7 +71,7 @@ module.exports = function(RED) {
71
71
  return centroid;
72
72
  };
73
73
 
74
- var sendIt = function() {
74
+ var sendIt = function () {
75
75
  node.emit("input", {
76
76
  time: new Date().toISOString(),
77
77
  etime: new Date(Date.now() + (2 * node.repeat)).toISOString(),
@@ -97,25 +97,41 @@ module.exports = function(RED) {
97
97
  node.repeaterSetup();
98
98
  setTimeout(sendIt, 2500);
99
99
 
100
- node.on("input",function(msg) {
100
+ node.on("input", function (msg) {
101
101
  if (msg.heartbeat) { // Register gateway and do the heartbeats
102
- var template = `<event version="2.0" uid="${node.uuid}" type="${msg.type}" how="h-e" time="${msg.time}" start="${msg.time}" stale="${msg.etime}"><point lat="${msg.lat}" lon="${msg.lon}" hae="${msg.alt}" ce="9999999" le="9999999"/><detail><takv device="${os.hostname()}" os="${os.platform()}" platform="NRedTAK" version="${ver}"/><contact endpoint="*:-1:stcp" callsign="${msg.callsign}"/><uid Droid="${msg.callsign}"/><__group name="${msg.group}" role="${msg.role}"/><status battery="99"/><track course="0.00000000" speed="0.00000000"/></detail></event>`;
103
- node.send({payload:template, topic:msg.type});
104
- node.status({fill:"green", shape:"dot", text:node.repeat/1000+"s - "+node.callsign});
102
+ var template = `<event version="2.0" uid="${node.uuid}" type="${msg.type}" how="h-e" time="${msg.time}" start="${msg.time}" stale="${msg.etime}"><point lat="${msg.lat}" lon="${msg.lon}" hae="${msg.alt}" ce="9999999" le="9999999"/><detail><takv device="${os.hostname()}" os="${os.platform()}" platform="NRedTAK" version="${ver}"/><contact endpoint="*:-1:stcp" callsign="${msg.callsign}"/><uid Droid="${msg.callsign}"/><__group name="${msg.group}" role="${msg.role}"/><status battery="99"/><track course="9999999.0" speed="0"/></detail></event>`;
103
+ node.send({ payload: template, topic: "TAKreg" });
104
+ node.status({ fill: "green", shape: "dot", text: node.repeat / 1000 + "s - " + node.callsign });
105
105
  return;
106
106
  }
107
+ // if it's just a simple filename and payload then make it look like an attachment etc...
108
+ if (msg.hasOwnProperty("filename") && Buffer.isBuffer(msg.payload) && !msg.hasOwnProperty("attachments")) {
109
+ msg.attachments = [{
110
+ filename: msg.filename.split('/').pop(),
111
+ content: msg.payload
112
+ }]
113
+ if (!msg.hasOwnProperty("topic")) { msg.topic = "File - " + msg.filename.split('/').pop(); }
114
+ delete msg.filename;
115
+ delete msg.payload;
116
+ }
107
117
  // If there are attachments handle them first. (Datapackage)
108
118
  if (msg.hasOwnProperty("attachments") && Array.isArray(msg.attachments) && msg.attachments.length > 0) {
109
- if (!msg.sendTo) { node.error("Missing 'sendTo' user TAK callsign property.",msg); return; }
110
- var UUID = uuid.v5(msg.topic,'d5d4a57d-48fb-58b6-93b8-d9fde658481a');
119
+ if (!msg.sendTo) { node.error("Missing 'sendTo' user TAK callsign property.", msg); return; }
120
+ var UUID = uuid.v5(msg.topic, 'd5d4a57d-48fb-58b6-93b8-d9fde658481a');
111
121
  var fnam = msg.topic;
112
- var fname = msg.topic+'.zip';
122
+ var fname = msg.topic + '.zip';
123
+ var da = new Date();
124
+ var dn = da.toISOString().split('-')[2].split('.')[0];
125
+ var calls = msg.from || node.callsign;
126
+ calls = calls + '.' + dn.split('T')[0] + '.' + dn.split('T')[1].split(':').join('');
113
127
  var mf = `<MissionPackageManifest version="2"><Configuration>
114
128
  <Parameter name="uid" value="${UUID}"/>
115
129
  <Parameter name="name" value="${msg.topic}"/>
116
- </Configuration><Contents>`;
130
+ <Parameter name="onReceiveImport" value="true"/>
131
+ <Parameter name="callsign" value="${calls}"/>
132
+ </Configuration><Contents>\n`;
117
133
  var zip = new AdmZip();
118
- for (var i=0; i < msg.attachments.length; i++) {
134
+ for (var i = 0; i < msg.attachments.length; i++) {
119
135
  var data;
120
136
  if (Buffer.isBuffer(msg.attachments[i].content)) {
121
137
  data = msg.attachments[i].content;
@@ -129,13 +145,36 @@ module.exports = function(RED) {
129
145
  var hash = crypto.createHash('md5').update(data).digest('hex');
130
146
  var fhash = hash + '/' + msg.attachments[i].filename;
131
147
  zip.addFile(fhash, data, "Added by Node-RED");
132
- mf +=`<Content ignore="false" zipEntry="${fhash}" />`;
148
+ mf += `<Content ignore="false" zipEntry="${fhash}"><Parameter name="uid" value="${UUID}"/></Content>\n`;
149
+ }
150
+
151
+ if (msg.hasOwnProperty("lat") && msg.hasOwnProperty("lon")) {
152
+ var timeo = new Date(Date.now() + (1000*60*60*4)).toISOString(); // stale time to 4 hours
153
+ var cott = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
154
+ <event version="2.0" uid="${UUID}" type="b-i-x-i" time="${da.toISOString()}" start="${da.toISOString()}" stale="${timeo}" how="h-g-i-g-o">
155
+ <point lat="${msg.lat}" lon="${msg.lon}" hae="${msg.alt || "9999999.0"}" ce="9999999.0" le="9999999.0" />
156
+ <detail>
157
+ <status readiness="true" />
158
+ <contact callsign="${calls}" />
159
+ <remarks>${msg.remarks || ''}</remarks>
160
+ <color argb="-1" />
161
+ <link uid="${node.uuid}" production_time="${da.toISOString()}" type="a-f-G-U-C" parent_callsign="${msg.from || node.callsign}" relation="p-p" />
162
+ <archive />
163
+ </detail>
164
+ </event>`
165
+
166
+ cott = cott.replace(/>\s+</g, "><");
167
+ var hsh = crypto.createHash('md5').update(cott).digest('hex');
168
+ zip.addFile(hsh+'/'+hsh+'.cot', cott, "Added by Node-RED");
169
+
170
+ mf += `<Content ignore="false" zipEntry="${hsh+'/'+hsh+'.cot'}"><Parameter name="uid" value="${UUID}"/></Content>\n`;
133
171
  }
134
- mf +=`</Contents></MissionPackageManifest>`;
172
+
173
+ mf += `</Contents></MissionPackageManifest>`;
135
174
  mf = mf.replace(/>\s+</g, "><");
136
- zip.addFile('MANIFEST/manifest.xml', Buffer.from(mf,'utf8'), msg.topic);
175
+ zip.addFile('MANIFEST/manifest.xml', Buffer.from(mf, 'utf8'), msg.topic);
137
176
  var zipbuff = zip.toBuffer();
138
- //zip.writeZip("/tmp/takfile")
177
+ zip.writeZip("/tmp/takfile.zip")
139
178
 
140
179
  msg = {
141
180
  from: node.callsign || msg.from || "Anonymous",
@@ -145,14 +184,14 @@ module.exports = function(RED) {
145
184
  assetfile: fname,
146
185
  len: zipbuff.length,
147
186
  uid: node.uuid,
148
- hash: crypto.createHash('sha256').update(zipbuff).digest('hex')
187
+ hash: crypto.createHash('sha256').update(zipbuff).digest('hex')
149
188
  }
150
189
 
151
190
  let formData = new FormData();
152
- const opts = { filename:fname, contentType:'application/x-zip-compressed' };
191
+ const opts = { filename: fname, contentType: 'application/x-zip-compressed' };
153
192
  formData.append('assetfile', zipbuff, opts);
154
193
 
155
- const url = encodeURI(node.host+'/Marti/sync/missionupload?hash='+msg.hash+'&filename='+fname+'&creatorUid='+node.uuid);
194
+ const url = encodeURI(node.host + '/Marti/sync/missionupload?hash=' + msg.hash + '&filename=' + fname + '&creatorUid=' + node.uuid);
156
195
  axios({
157
196
  method: 'post',
158
197
  url: url,
@@ -160,7 +199,7 @@ module.exports = function(RED) {
160
199
  data: formData
161
200
  })
162
201
  .then(function (response) {
163
- const urlp = encodeURI(node.host+'/Marti/api/sync/metadata/'+msg.hash+'/tool');
202
+ const urlp = encodeURI(node.host + '/Marti/api/sync/metadata/' + msg.hash + '/tool');
164
203
  var priv = (msg.sendTo === "public") ? "public" : "private";
165
204
  axios({
166
205
  method: 'put',
@@ -173,31 +212,31 @@ module.exports = function(RED) {
173
212
  const stale = new Date(new Date().getTime() + (10000)).toISOString();
174
213
 
175
214
  var m = `<event version="2.0" uid="${uuidv4()}" type="b-f-t-r" how="h-e" time="${start}" start="${start}" stale="${stale}">
176
- <point lat="${msg.lat}" lon="${msg.lon}" hae="9999999.0" ce="9999999.0" le="9999999.0" />
215
+ <point lat="${msg.lat}" lon="${msg.lon}" hae="${msg.alt || 9999999.0}" ce="9999999.0" le="9999999.0" />
177
216
  <detail>
178
217
  <fileshare filename="${fname}" senderUrl="${node.host}/Marti/sync/content?hash=${msg.hash}" sizeInBytes="${msg.len}" sha256="${msg.hash}" senderUid="${msg.uid}" senderCallsign="${msg.from}" name="${fnam}" />`
179
218
  if (msg.sendTo !== "broadcast") {
180
219
  var t = msg.sendTo;
181
- if (!Array.isArray(t)) { t = [ t ]; }
182
- m += '<marti>' + t.map(v => '<dest callsign="' + v +'"/>') + '</marti>';
220
+ if (!Array.isArray(t)) { t = [t]; }
221
+ m += '<marti>' + t.map(v => '<dest callsign="' + v + '"/>') + '</marti>';
183
222
  }
184
223
  m += '</detail></event>';
185
- node.log( "DP: " + node.host + "/Marti/sync/content?hash=" + msg.hash );
224
+ node.log("DP: " + node.host + "/Marti/sync/content?hash=" + msg.hash);
186
225
  msg.payload = m.replace(/>\s+</g, "><");
187
226
  msg.topic = "b-f-t-r";
188
227
  node.send(msg);
189
228
  }
190
229
  })
191
230
  .catch(function (error) {
192
- node.error(error.message,error);
231
+ node.error(error.message, error);
193
232
  })
194
233
  })
195
234
  .catch(function (error) {
196
- node.error(error.message,error);
235
+ node.error(error.message, error);
197
236
  })
198
237
  }
199
238
  // Otherwise if it's a string maybe it's raw cot xml - or NMEA from GPS - or maybe a simple chat message
200
- else if (typeof msg.payload === "string" ) {
239
+ else if (typeof msg.payload === "string") {
201
240
  if (msg.payload.trim().startsWith('<') && msg.payload.trim().endsWith('>')) { // Assume it's proper XML event so pass straight through
202
241
  msg.topic = msg.payload.split('type="')[1].split('"')[0];
203
242
  node.send(msg);
@@ -206,9 +245,9 @@ module.exports = function(RED) {
206
245
  // console.log("It's NMEA",msg.payload);
207
246
  var nm = msg.payload.trim().split(',');
208
247
  if (nm[0] === '$GPGGA' && nm[6] > 0) {
209
- const la = parseInt(nm[2].substr(0,2)) + parseFloat(nm[2].substr(2))/60;
248
+ const la = parseInt(nm[2].substr(0, 2)) + parseFloat(nm[2].substr(2)) / 60;
210
249
  node.lat = ((nm[3] === "N") ? la : -la).toFixed(6);
211
- const lo = parseInt(nm[4].substr(0,3)) + parseFloat(nm[4].substr(3))/60;
250
+ const lo = parseInt(nm[4].substr(0, 3)) + parseFloat(nm[4].substr(3)) / 60;
212
251
  node.lon = ((nm[5] === "E") ? lo : -lo).toFixed(6);
213
252
  node.alt = nm[9];
214
253
  }
@@ -223,14 +262,14 @@ module.exports = function(RED) {
223
262
  var type = "a-f-G-I-B";
224
263
  var par = '';
225
264
 
226
- for (var t=0; t < msg.sendTo.length; t++) {
265
+ for (var t = 0; t < msg.sendTo.length; t++) {
227
266
  var m = RED.util.cloneMessage(msg);
228
267
  const to = m.sendTo[t];
229
268
  m.sendTo = to;
230
269
  const toid = globalContext.get("_takgatewaycs")[m.sendTo] || m.sendTo;
231
270
  var ma = `<marti><dest callsign="${m.sendTo}"/></marti>`;
232
271
  if (m.sendTo === "broadcast") { m.sendTo = "All Chat Rooms"; }
233
- if (m.sendTo === "All Chat Rooms") { ma = ""; }
272
+ if (m.sendTo === "All Chat Rooms") { ma = ""; }
234
273
  if (teamList.includes(m.sendTo)) { par = 'parent="TeamGroups"'; }
235
274
 
236
275
  var xm = `<event version="2.0" uid="GeoChat.${node.uuid}.${toid}.${mid}" type="b-t-f" time="${start}" start="${start}" stale="${stale}" how="h-g-i-g-o">
@@ -259,7 +298,7 @@ module.exports = function(RED) {
259
298
  if (msg.payload.hasOwnProperty("alt")) { node.alt = parseInt(msg.payload.alt); }
260
299
  }
261
300
  // Handle a generic worldmap style object
262
- else if (typeof msg.payload === "object" && msg.payload.hasOwnProperty("name") ) {
301
+ else if (typeof msg.payload === "object" && msg.payload.hasOwnProperty("name")) {
263
302
  var shapeXML = ``;
264
303
  var d = new Date();
265
304
  var st = d.toISOString();
@@ -278,19 +317,19 @@ module.exports = function(RED) {
278
317
  if (!msg.payload.cottype && msg.payload.SIDC) {
279
318
  var s = msg.payload.SIDC.split('-')[0].toLowerCase();
280
319
  if (s.startsWith('s')) {
281
- type = s.split('').join('-').replace('s-','a-').replace('-p-','-');
320
+ type = s.split('').join('-').replace('s-', 'a-').replace('-p-', '-');
282
321
  }
283
322
  }
284
323
  if (msg.payload.icon === 'fa-circle fa-fw') {
285
324
  type = 'b-m-p-s-m';
286
325
  shapeXML = '<color argb="' + convertWMtoCOTColour(msg.payload.iconColor.replace('#', '')) + '"/>';
287
- shapeXML = shapeXML+'<usericon iconsetpath="COT_MAPPING_SPOTMAP/b-m-p-s-m/-16711681"/>';
326
+ shapeXML = shapeXML + '<usericon iconsetpath="COT_MAPPING_SPOTMAP/b-m-p-s-m/-16711681"/>';
288
327
  }
289
328
  }
290
329
 
291
330
  // Handle Worldmap drawing shapes
292
331
  if (msg.payload.hasOwnProperty("action") && msg.payload.action === "draw") {
293
- ttl = 24*60*60*1000; /// set TTL to 1 day for shapes...
332
+ ttl = 24 * 60 * 60 * 1000; /// set TTL to 1 day for shapes...
294
333
 
295
334
  var shape = {
296
335
  "strokeColor": (msg.payload.options.color || "910000").replace('#', ''),
@@ -364,7 +403,7 @@ module.exports = function(RED) {
364
403
  <width>${shape.weight || 2.0}</width>
365
404
  </LineStyle>
366
405
  <PolyStyle>
367
- <color>${convertWMtoKMLColour(shape.fillColor,shape.fillOpacity)}</color>
406
+ <color>${convertWMtoKMLColour(shape.fillColor, shape.fillOpacity)}</color>
368
407
  </PolyStyle>
369
408
  </Style>
370
409
  </link>
@@ -391,7 +430,7 @@ module.exports = function(RED) {
391
430
  }
392
431
 
393
432
  if (shape.type === 'poly') {
394
- shapeXML += `<fillColor value="${convertWMtoCOTColour(shape.fillColor,shape.fillOpacity)}"/>`;
433
+ shapeXML += `<fillColor value="${convertWMtoCOTColour(shape.fillColor, shape.fillOpacity)}"/>`;
395
434
  type = "u-d-f";
396
435
  if (shape.points.length === 4) {
397
436
  type = "u-d-r";
@@ -407,9 +446,9 @@ module.exports = function(RED) {
407
446
  <point lat="${msg.payload.lat || 0}" lon="${msg.payload.lon || 0}" hae="${parseInt(msg.payload.alt || invalid)}" le="9999999.0" ce="9999999.0"/>
408
447
  <detail>
409
448
  <takv device="${os.hostname()}" os="${os.platform()}" platform="NRedTAK" version="${ver}"/>
410
- <track course="${msg.payload.bearing || 0}" speed="${parseInt(msg.payload.speed) || 0}"/>
449
+ <track course="${msg.payload.bearing || 9999999.0}" speed="${parseInt(msg.payload.speed) || 0}"/>
411
450
  <contact callsign="${msg.payload.name}"/>
412
- <remarks source="NRedTAK">${tag}</remarks>
451
+ <remarks source="${node.callsign}">${tag}</remarks>
413
452
  ${shapeXML}
414
453
  </detail>
415
454
  </event>`
@@ -418,9 +457,32 @@ module.exports = function(RED) {
418
457
  node.send(msg);
419
458
  }
420
459
 
460
+ // Maybe a simple event json update (eg from an ingest - tweak and send back)
461
+ // Note this is not 100% reverse of the ingest... but seems to work mostly...
462
+ else if (typeof msg.payload === "object" && msg.payload.hasOwnProperty("event")) {
463
+ const ev = msg.payload.event;
464
+ msg.topic = ev.type;
465
+ msg.payload = `<event version="${ev.version}" uid="${ev.uid}" type="${ev.type}" time="${ev.time}" start="${ev.start}" stale="${ev.stale}" how="${ev.how}">
466
+ <point lat="${ev.point.lat || 0}" lon="${ev.point.lon || 0}" hae="${ev.detail?.height?.value || ev.point.hae || 9999999.0}" le="${ev.point.le}" ce="${ev.point.ce}"/>
467
+ <detail>
468
+ <takv device="${os.hostname()}" os="${os.platform()}" platform="NRedTAK" version="${ver}"/>`
469
+ if (ev.detail?.track) {
470
+ msg.payload += `<track speed="${ev.detail.track.speed}" course="${ev.detail.track.course}"/>`;
471
+ }
472
+ if (ev.detail?.color) {
473
+ msg.payload += `<color argb="${ev.detail.color.argb}"/>`;
474
+ }
475
+ msg.payload += `<contact callsign="${ev.detail?.contact?.callsign}"/>
476
+ <remarks source="${node.callsign}">${msg.remarks || ev.detail?.remarks}</remarks>
477
+ </detail>
478
+ </event>`
479
+ msg.payload = msg.payload.replace(/>\s+</g, "><");
480
+ node.send(msg);
481
+ }
482
+
421
483
  // Drop anything we don't handle yet.
422
484
  else {
423
- node.log("Dropped: "+JSON.stringify(msg.payload));
485
+ node.log("Dropped: " + JSON.stringify(msg.payload));
424
486
  }
425
487
  });
426
488