node-red-contrib-tak-registration 0.9.0 → 0.11.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 (65) hide show
  1. package/README.md +7 -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-ingest.html +3 -0
  63. package/tak-ingest.js +21 -1
  64. package/tak-registration.html +9 -2
  65. package/tak-registration.js +95 -57
@@ -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.9.0",
3
+ "version": "0.11.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",
package/tak-ingest.html CHANGED
@@ -37,4 +37,7 @@
37
37
  <code>_takgatewaycs</code> and <code>_takgatewayId</code> that can be used
38
38
  as look ups for other messages.</p>
39
39
  <p>It also sets <code>msg.topic</code> to the event type to make switching easier.</p>
40
+ <p>If an event arrives with a <i>fileshare</i> link, it will fetch the file and add
41
+ <code>msg.filename</code> and <code>msg.datapackage</code> to the output msg.
42
+ The datapackage will be a buffer.</p>
40
43
  </script>
package/tak-ingest.js CHANGED
@@ -1,4 +1,5 @@
1
1
  const { XMLParser, XMLBuilder, XMLValidator} = require("fast-xml-parser");
2
+ const axios = require('axios').default;
2
3
  var Long = require('long').Long;
3
4
  var protobuf = require('protobufjs');
4
5
  var path = require('path');
@@ -86,7 +87,26 @@ module.exports = function(RED) {
86
87
  global.set("_takgatewayid", b);
87
88
  }
88
89
  if (msg.payload?.event?.type) { msg.topic = msg.payload?.event?.type; }
89
- node.send(msg);
90
+ if (msg.payload?.event?.detail?.fileshare) {
91
+ msg.filename = msg.payload.event.detail.fileshare.filename;
92
+ axios({
93
+ method: 'get',
94
+ url: msg.payload.event.detail.fileshare.senderUrl,
95
+ headers: { 'Accept': 'application/zip' },
96
+ responseType: 'arraybuffer'
97
+ })
98
+ .then(function (response) {
99
+ msg.datapackage = Buffer.from(response.data);
100
+ node.send(msg);
101
+ })
102
+ .catch(function (error) {
103
+ node.error(error.message, error);
104
+ node.send(msg);
105
+ })
106
+ }
107
+ else {
108
+ node.send(msg);
109
+ }
90
110
  });
91
111
 
92
112
  node.on("close", function() {
@@ -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 buffer 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,30 +145,52 @@ 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
+ mf += `<Content ignore="false" zipEntry="${hsh+'/'+hsh+'.cot'}"><Parameter name="uid" value="${UUID}"/></Content>\n`;
133
170
  }
134
- mf +=`</Contents></MissionPackageManifest>`;
171
+
172
+ mf += `</Contents></MissionPackageManifest>`;
135
173
  mf = mf.replace(/>\s+</g, "><");
136
- zip.addFile('MANIFEST/manifest.xml', Buffer.from(mf,'utf8'), msg.topic);
174
+ zip.addFile('MANIFEST/manifest.xml', Buffer.from(mf, 'utf8'), msg.topic);
137
175
  var zipbuff = zip.toBuffer();
138
- //zip.writeZip("/tmp/takfile")
176
+ zip.writeZip("/tmp/takfile.zip")
139
177
 
140
178
  msg = {
141
- from: node.callsign || msg.from || "Anonymous",
179
+ from: msg.from || node.callsign || "Anonymous",
142
180
  sendTo: msg.sendTo,
143
- lat: node.lat || msg.lat || 0,
144
- lon: node.lon || msg.lon || 0,
181
+ lat: msg.lat || node.lat || 0,
182
+ lon: msg.lon || node.lon || 0,
145
183
  assetfile: fname,
146
184
  len: zipbuff.length,
147
185
  uid: node.uuid,
148
- hash: crypto.createHash('sha256').update(zipbuff).digest('hex')
186
+ hash: crypto.createHash('sha256').update(zipbuff).digest('hex')
149
187
  }
150
188
 
151
189
  let formData = new FormData();
152
- const opts = { filename:fname, contentType:'application/x-zip-compressed' };
190
+ const opts = { filename: fname, contentType: 'application/x-zip-compressed' };
153
191
  formData.append('assetfile', zipbuff, opts);
154
192
 
155
- const url = encodeURI(node.host+'/Marti/sync/missionupload?hash='+msg.hash+'&filename='+fname+'&creatorUid='+node.uuid);
193
+ const url = encodeURI(node.host + '/Marti/sync/missionupload?hash=' + msg.hash + '&filename=' + fname + '&creatorUid=' + node.uuid);
156
194
  axios({
157
195
  method: 'post',
158
196
  url: url,
@@ -160,7 +198,7 @@ module.exports = function(RED) {
160
198
  data: formData
161
199
  })
162
200
  .then(function (response) {
163
- const urlp = encodeURI(node.host+'/Marti/api/sync/metadata/'+msg.hash+'/tool');
201
+ const urlp = encodeURI(node.host + '/Marti/api/sync/metadata/' + msg.hash + '/tool');
164
202
  var priv = (msg.sendTo === "public") ? "public" : "private";
165
203
  axios({
166
204
  method: 'put',
@@ -173,31 +211,31 @@ module.exports = function(RED) {
173
211
  const stale = new Date(new Date().getTime() + (10000)).toISOString();
174
212
 
175
213
  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" />
214
+ <point lat="${msg.lat}" lon="${msg.lon}" hae="${msg.alt || 9999999.0}" ce="9999999.0" le="9999999.0" />
177
215
  <detail>
178
216
  <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
217
  if (msg.sendTo !== "broadcast") {
180
218
  var t = msg.sendTo;
181
- if (!Array.isArray(t)) { t = [ t ]; }
182
- m += '<marti>' + t.map(v => '<dest callsign="' + v +'"/>') + '</marti>';
219
+ if (!Array.isArray(t)) { t = [t]; }
220
+ m += '<marti>' + t.map(v => '<dest callsign="' + v + '"/>') + '</marti>';
183
221
  }
184
222
  m += '</detail></event>';
185
- node.log( "DP: " + node.host + "/Marti/sync/content?hash=" + msg.hash );
223
+ node.log("DP: " + node.host + "/Marti/sync/content?hash=" + msg.hash);
186
224
  msg.payload = m.replace(/>\s+</g, "><");
187
225
  msg.topic = "b-f-t-r";
188
226
  node.send(msg);
189
227
  }
190
228
  })
191
229
  .catch(function (error) {
192
- node.error(error.message,error);
230
+ node.error(error.message, error);
193
231
  })
194
232
  })
195
233
  .catch(function (error) {
196
- node.error(error.message,error);
234
+ node.error(error.message, error);
197
235
  })
198
236
  }
199
237
  // 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" ) {
238
+ else if (typeof msg.payload === "string") {
201
239
  if (msg.payload.trim().startsWith('<') && msg.payload.trim().endsWith('>')) { // Assume it's proper XML event so pass straight through
202
240
  msg.topic = msg.payload.split('type="')[1].split('"')[0];
203
241
  node.send(msg);
@@ -206,9 +244,9 @@ module.exports = function(RED) {
206
244
  // console.log("It's NMEA",msg.payload);
207
245
  var nm = msg.payload.trim().split(',');
208
246
  if (nm[0] === '$GPGGA' && nm[6] > 0) {
209
- const la = parseInt(nm[2].substr(0,2)) + parseFloat(nm[2].substr(2))/60;
247
+ const la = parseInt(nm[2].substr(0, 2)) + parseFloat(nm[2].substr(2)) / 60;
210
248
  node.lat = ((nm[3] === "N") ? la : -la).toFixed(6);
211
- const lo = parseInt(nm[4].substr(0,3)) + parseFloat(nm[4].substr(3))/60;
249
+ const lo = parseInt(nm[4].substr(0, 3)) + parseFloat(nm[4].substr(3)) / 60;
212
250
  node.lon = ((nm[5] === "E") ? lo : -lo).toFixed(6);
213
251
  node.alt = nm[9];
214
252
  }
@@ -223,14 +261,14 @@ module.exports = function(RED) {
223
261
  var type = "a-f-G-I-B";
224
262
  var par = '';
225
263
 
226
- for (var t=0; t < msg.sendTo.length; t++) {
264
+ for (var t = 0; t < msg.sendTo.length; t++) {
227
265
  var m = RED.util.cloneMessage(msg);
228
266
  const to = m.sendTo[t];
229
267
  m.sendTo = to;
230
268
  const toid = globalContext.get("_takgatewaycs")[m.sendTo] || m.sendTo;
231
269
  var ma = `<marti><dest callsign="${m.sendTo}"/></marti>`;
232
270
  if (m.sendTo === "broadcast") { m.sendTo = "All Chat Rooms"; }
233
- if (m.sendTo === "All Chat Rooms") { ma = ""; }
271
+ if (m.sendTo === "All Chat Rooms") { ma = ""; }
234
272
  if (teamList.includes(m.sendTo)) { par = 'parent="TeamGroups"'; }
235
273
 
236
274
  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 +297,7 @@ module.exports = function(RED) {
259
297
  if (msg.payload.hasOwnProperty("alt")) { node.alt = parseInt(msg.payload.alt); }
260
298
  }
261
299
  // Handle a generic worldmap style object
262
- else if (typeof msg.payload === "object" && msg.payload.hasOwnProperty("name") ) {
300
+ else if (typeof msg.payload === "object" && msg.payload.hasOwnProperty("name")) {
263
301
  var shapeXML = ``;
264
302
  var d = new Date();
265
303
  var st = d.toISOString();
@@ -278,19 +316,19 @@ module.exports = function(RED) {
278
316
  if (!msg.payload.cottype && msg.payload.SIDC) {
279
317
  var s = msg.payload.SIDC.split('-')[0].toLowerCase();
280
318
  if (s.startsWith('s')) {
281
- type = s.split('').join('-').replace('s-','a-').replace('-p-','-');
319
+ type = s.split('').join('-').replace('s-', 'a-').replace('-p-', '-');
282
320
  }
283
321
  }
284
322
  if (msg.payload.icon === 'fa-circle fa-fw') {
285
323
  type = 'b-m-p-s-m';
286
324
  shapeXML = '<color argb="' + convertWMtoCOTColour(msg.payload.iconColor.replace('#', '')) + '"/>';
287
- shapeXML = shapeXML+'<usericon iconsetpath="COT_MAPPING_SPOTMAP/b-m-p-s-m/-16711681"/>';
325
+ shapeXML = shapeXML + '<usericon iconsetpath="COT_MAPPING_SPOTMAP/b-m-p-s-m/-16711681"/>';
288
326
  }
289
327
  }
290
328
 
291
329
  // Handle Worldmap drawing shapes
292
330
  if (msg.payload.hasOwnProperty("action") && msg.payload.action === "draw") {
293
- ttl = 24*60*60*1000; /// set TTL to 1 day for shapes...
331
+ ttl = 24 * 60 * 60 * 1000; /// set TTL to 1 day for shapes...
294
332
 
295
333
  var shape = {
296
334
  "strokeColor": (msg.payload.options.color || "910000").replace('#', ''),
@@ -364,7 +402,7 @@ module.exports = function(RED) {
364
402
  <width>${shape.weight || 2.0}</width>
365
403
  </LineStyle>
366
404
  <PolyStyle>
367
- <color>${convertWMtoKMLColour(shape.fillColor,shape.fillOpacity)}</color>
405
+ <color>${convertWMtoKMLColour(shape.fillColor, shape.fillOpacity)}</color>
368
406
  </PolyStyle>
369
407
  </Style>
370
408
  </link>
@@ -391,7 +429,7 @@ module.exports = function(RED) {
391
429
  }
392
430
 
393
431
  if (shape.type === 'poly') {
394
- shapeXML += `<fillColor value="${convertWMtoCOTColour(shape.fillColor,shape.fillOpacity)}"/>`;
432
+ shapeXML += `<fillColor value="${convertWMtoCOTColour(shape.fillColor, shape.fillOpacity)}"/>`;
395
433
  type = "u-d-f";
396
434
  if (shape.points.length === 4) {
397
435
  type = "u-d-r";
@@ -409,7 +447,7 @@ module.exports = function(RED) {
409
447
  <takv device="${os.hostname()}" os="${os.platform()}" platform="NRedTAK" version="${ver}"/>
410
448
  <track course="${msg.payload.bearing || 9999999.0}" speed="${parseInt(msg.payload.speed) || 0}"/>
411
449
  <contact callsign="${msg.payload.name}"/>
412
- <remarks source="NRedTAK">${tag}</remarks>
450
+ <remarks source="${node.callsign}">${tag}</remarks>
413
451
  ${shapeXML}
414
452
  </detail>
415
453
  </event>`
@@ -420,19 +458,19 @@ module.exports = function(RED) {
420
458
 
421
459
  // Maybe a simple event json update (eg from an ingest - tweak and send back)
422
460
  // Note this is not 100% reverse of the ingest... but seems to work mostly...
423
- else if (typeof msg.payload === "object" && msg.payload.hasOwnProperty("event") ) {
461
+ else if (typeof msg.payload === "object" && msg.payload.hasOwnProperty("event")) {
424
462
  const ev = msg.payload.event;
425
463
  msg.topic = ev.type;
426
464
  msg.payload = `<event version="${ev.version}" uid="${ev.uid}" type="${ev.type}" time="${ev.time}" start="${ev.start}" stale="${ev.stale}" how="${ev.how}">
427
465
  <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}"/>
428
466
  <detail>
429
467
  <takv device="${os.hostname()}" os="${os.platform()}" platform="NRedTAK" version="${ver}"/>`
430
- if (ev.detail?.track) {
431
- msg.payload += `<track speed="${ev.detail.track.speed}" course="${ev.detail.track.course}"/>`;
432
- }
433
- if (ev.detail?.color) {
434
- msg.payload += `<color argb="${ev.detail.color.argb}"/>`;
435
- }
468
+ if (ev.detail?.track) {
469
+ msg.payload += `<track speed="${ev.detail.track.speed}" course="${ev.detail.track.course}"/>`;
470
+ }
471
+ if (ev.detail?.color) {
472
+ msg.payload += `<color argb="${ev.detail.color.argb}"/>`;
473
+ }
436
474
  msg.payload += `<contact callsign="${ev.detail?.contact?.callsign}"/>
437
475
  <remarks source="${node.callsign}">${msg.remarks || ev.detail?.remarks}</remarks>
438
476
  </detail>
@@ -443,7 +481,7 @@ module.exports = function(RED) {
443
481
 
444
482
  // Drop anything we don't handle yet.
445
483
  else {
446
- node.log("Dropped: "+JSON.stringify(msg.payload));
484
+ node.log("Dropped: " + JSON.stringify(msg.payload));
447
485
  }
448
486
  });
449
487