node-red-contrib-tak-registration 0.2.1 → 0.2.2
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.
- package/README.md +5 -5
- package/node_modules/axios/CHANGELOG.md +15 -0
- package/node_modules/axios/README.md +1 -0
- package/node_modules/axios/dist/axios.js +49 -33
- package/node_modules/axios/dist/axios.map +1 -1
- package/node_modules/axios/dist/axios.min.js +1 -3
- package/node_modules/axios/dist/axios.min.map +1 -1
- package/node_modules/axios/lib/adapters/http.js +19 -3
- package/node_modules/axios/lib/adapters/xhr.js +2 -2
- package/node_modules/axios/lib/core/Axios.js +0 -7
- package/node_modules/axios/lib/core/transformData.js +1 -1
- package/node_modules/axios/lib/{defaults.js → defaults/index.js} +7 -10
- package/node_modules/axios/lib/defaults/transitional.js +7 -0
- package/node_modules/axios/lib/env/data.js +1 -1
- package/node_modules/axios/package.json +69 -41
- package/node_modules/follow-redirects/index.js +82 -77
- package/node_modules/follow-redirects/package.json +13 -13
- package/package.json +19 -12
- package/tak-registration.html +12 -11
- package/tak-registration.js +62 -11
|
@@ -1,37 +1,49 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
2
|
+
"_from": "axios@0.26.1",
|
|
3
|
+
"_id": "axios@0.26.1",
|
|
4
|
+
"_inBundle": false,
|
|
5
|
+
"_integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
|
|
6
|
+
"_location": "/axios",
|
|
7
|
+
"_phantomChildren": {},
|
|
8
|
+
"_requested": {
|
|
9
|
+
"type": "version",
|
|
10
|
+
"registry": true,
|
|
11
|
+
"raw": "axios@0.26.1",
|
|
12
|
+
"name": "axios",
|
|
13
|
+
"escapedName": "axios",
|
|
14
|
+
"rawSpec": "0.26.1",
|
|
15
|
+
"saveSpec": null,
|
|
16
|
+
"fetchSpec": "0.26.1"
|
|
17
17
|
},
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
},
|
|
22
|
-
"keywords": [
|
|
23
|
-
"xhr",
|
|
24
|
-
"http",
|
|
25
|
-
"ajax",
|
|
26
|
-
"promise",
|
|
27
|
-
"node"
|
|
18
|
+
"_requiredBy": [
|
|
19
|
+
"#USER",
|
|
20
|
+
"/"
|
|
28
21
|
],
|
|
29
|
-
"
|
|
30
|
-
"
|
|
22
|
+
"_resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
|
|
23
|
+
"_shasum": "1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9",
|
|
24
|
+
"_spec": "axios@0.26.1",
|
|
25
|
+
"_where": "/Users/conway/Projects/TAKreg",
|
|
26
|
+
"author": {
|
|
27
|
+
"name": "Matt Zabriskie"
|
|
28
|
+
},
|
|
29
|
+
"browser": {
|
|
30
|
+
"./lib/adapters/http.js": "./lib/adapters/xhr.js"
|
|
31
|
+
},
|
|
31
32
|
"bugs": {
|
|
32
33
|
"url": "https://github.com/axios/axios/issues"
|
|
33
34
|
},
|
|
34
|
-
"
|
|
35
|
+
"bundleDependencies": false,
|
|
36
|
+
"bundlesize": [
|
|
37
|
+
{
|
|
38
|
+
"path": "./dist/axios.min.js",
|
|
39
|
+
"threshold": "5kB"
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"follow-redirects": "^1.14.8"
|
|
44
|
+
},
|
|
45
|
+
"deprecated": false,
|
|
46
|
+
"description": "Promise based HTTP client for the browser and node.js",
|
|
35
47
|
"devDependencies": {
|
|
36
48
|
"abortcontroller-polyfill": "^1.5.0",
|
|
37
49
|
"coveralls": "^3.0.0",
|
|
@@ -68,19 +80,35 @@
|
|
|
68
80
|
"webpack": "^4.44.2",
|
|
69
81
|
"webpack-dev-server": "^3.11.0"
|
|
70
82
|
},
|
|
71
|
-
"
|
|
72
|
-
"./lib/adapters/http.js": "./lib/adapters/xhr.js"
|
|
73
|
-
},
|
|
83
|
+
"homepage": "https://axios-http.com",
|
|
74
84
|
"jsdelivr": "dist/axios.min.js",
|
|
75
|
-
"
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
"
|
|
85
|
+
"keywords": [
|
|
86
|
+
"xhr",
|
|
87
|
+
"http",
|
|
88
|
+
"ajax",
|
|
89
|
+
"promise",
|
|
90
|
+
"node"
|
|
91
|
+
],
|
|
92
|
+
"license": "MIT",
|
|
93
|
+
"main": "index.js",
|
|
94
|
+
"name": "axios",
|
|
95
|
+
"repository": {
|
|
96
|
+
"type": "git",
|
|
97
|
+
"url": "git+https://github.com/axios/axios.git"
|
|
79
98
|
},
|
|
80
|
-
"
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
99
|
+
"scripts": {
|
|
100
|
+
"build": "NODE_ENV=production grunt build",
|
|
101
|
+
"coveralls": "cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js",
|
|
102
|
+
"examples": "node ./examples/server.js",
|
|
103
|
+
"fix": "eslint --fix lib/**/*.js",
|
|
104
|
+
"postversion": "git push && git push --tags",
|
|
105
|
+
"preversion": "grunt version && npm test",
|
|
106
|
+
"start": "node ./sandbox/server.js",
|
|
107
|
+
"test": "grunt test && dtslint",
|
|
108
|
+
"version": "npm run build && git add -A dist && git add CHANGELOG.md bower.json package.json"
|
|
109
|
+
},
|
|
110
|
+
"types": "index.d.ts",
|
|
111
|
+
"typings": "./index.d.ts",
|
|
112
|
+
"unpkg": "dist/axios.min.js",
|
|
113
|
+
"version": "0.26.1"
|
|
86
114
|
}
|
|
@@ -336,96 +336,101 @@ RedirectableRequest.prototype._processResponse = function (response) {
|
|
|
336
336
|
// the user agent MAY automatically redirect its request to the URI
|
|
337
337
|
// referenced by the Location field value,
|
|
338
338
|
// even if the specific status code is not understood.
|
|
339
|
+
|
|
340
|
+
// If the response is not a redirect; return it as-is
|
|
339
341
|
var location = response.headers.location;
|
|
340
|
-
if (location
|
|
341
|
-
statusCode
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
response.destroy();
|
|
346
|
-
|
|
347
|
-
// RFC7231§6.4: A client SHOULD detect and intervene
|
|
348
|
-
// in cyclical redirections (i.e., "infinite" redirection loops).
|
|
349
|
-
if (++this._redirectCount > this._options.maxRedirects) {
|
|
350
|
-
this.emit("error", new TooManyRedirectsError());
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
342
|
+
if (!location || this._options.followRedirects === false ||
|
|
343
|
+
statusCode < 300 || statusCode >= 400) {
|
|
344
|
+
response.responseUrl = this._currentUrl;
|
|
345
|
+
response.redirects = this._redirects;
|
|
346
|
+
this.emit("response", response);
|
|
353
347
|
|
|
354
|
-
//
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
if ((statusCode === 301 || statusCode === 302) && this._options.method === "POST" ||
|
|
359
|
-
// RFC7231§6.4.4: The 303 (See Other) status code indicates that
|
|
360
|
-
// the server is redirecting the user agent to a different resource […]
|
|
361
|
-
// A user agent can perform a retrieval request targeting that URI
|
|
362
|
-
// (a GET or HEAD request if using HTTP) […]
|
|
363
|
-
(statusCode === 303) && !/^(?:GET|HEAD)$/.test(this._options.method)) {
|
|
364
|
-
this._options.method = "GET";
|
|
365
|
-
// Drop a possible entity and headers related to it
|
|
366
|
-
this._requestBodyBuffers = [];
|
|
367
|
-
removeMatchingHeaders(/^content-/i, this._options.headers);
|
|
368
|
-
}
|
|
348
|
+
// Clean up
|
|
349
|
+
this._requestBodyBuffers = [];
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
369
352
|
|
|
370
|
-
|
|
371
|
-
|
|
353
|
+
// The response is a redirect, so abort the current request
|
|
354
|
+
abortRequest(this._currentRequest);
|
|
355
|
+
// Discard the remainder of the response to avoid waiting for data
|
|
356
|
+
response.destroy();
|
|
372
357
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
358
|
+
// RFC7231§6.4: A client SHOULD detect and intervene
|
|
359
|
+
// in cyclical redirections (i.e., "infinite" redirection loops).
|
|
360
|
+
if (++this._redirectCount > this._options.maxRedirects) {
|
|
361
|
+
this.emit("error", new TooManyRedirectsError());
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
378
364
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
365
|
+
// RFC7231§6.4: Automatic redirection needs to done with
|
|
366
|
+
// care for methods not known to be safe, […]
|
|
367
|
+
// RFC7231§6.4.2–3: For historical reasons, a user agent MAY change
|
|
368
|
+
// the request method from POST to GET for the subsequent request.
|
|
369
|
+
if ((statusCode === 301 || statusCode === 302) && this._options.method === "POST" ||
|
|
370
|
+
// RFC7231§6.4.4: The 303 (See Other) status code indicates that
|
|
371
|
+
// the server is redirecting the user agent to a different resource […]
|
|
372
|
+
// A user agent can perform a retrieval request targeting that URI
|
|
373
|
+
// (a GET or HEAD request if using HTTP) […]
|
|
374
|
+
(statusCode === 303) && !/^(?:GET|HEAD)$/.test(this._options.method)) {
|
|
375
|
+
this._options.method = "GET";
|
|
376
|
+
// Drop a possible entity and headers related to it
|
|
377
|
+
this._requestBodyBuffers = [];
|
|
378
|
+
removeMatchingHeaders(/^content-/i, this._options.headers);
|
|
379
|
+
}
|
|
388
380
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
this._isRedirect = true;
|
|
392
|
-
var redirectUrlParts = url.parse(redirectUrl);
|
|
393
|
-
Object.assign(this._options, redirectUrlParts);
|
|
381
|
+
// Drop the Host header, as the redirect might lead to a different host
|
|
382
|
+
var currentHostHeader = removeMatchingHeaders(/^host$/i, this._options.headers);
|
|
394
383
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
384
|
+
// If the redirect is relative, carry over the host of the last request
|
|
385
|
+
var currentUrlParts = url.parse(this._currentUrl);
|
|
386
|
+
var currentHost = currentHostHeader || currentUrlParts.host;
|
|
387
|
+
var currentUrl = /^\w+:/.test(location) ? this._currentUrl :
|
|
388
|
+
url.format(Object.assign(currentUrlParts, { host: currentHost }));
|
|
399
389
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
390
|
+
// Determine the URL of the redirection
|
|
391
|
+
var redirectUrl;
|
|
392
|
+
try {
|
|
393
|
+
redirectUrl = url.resolve(currentUrl, location);
|
|
394
|
+
}
|
|
395
|
+
catch (cause) {
|
|
396
|
+
this.emit("error", new RedirectionError(cause));
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Create the redirected request
|
|
401
|
+
debug("redirecting to", redirectUrl);
|
|
402
|
+
this._isRedirect = true;
|
|
403
|
+
var redirectUrlParts = url.parse(redirectUrl);
|
|
404
|
+
Object.assign(this._options, redirectUrlParts);
|
|
405
|
+
|
|
406
|
+
// Drop confidential headers when redirecting to a less secure protocol
|
|
407
|
+
// or to a different domain that is not a superdomain
|
|
408
|
+
if (redirectUrlParts.protocol !== currentUrlParts.protocol &&
|
|
409
|
+
redirectUrlParts.protocol !== "https:" ||
|
|
410
|
+
redirectUrlParts.host !== currentHost &&
|
|
411
|
+
!isSubdomain(redirectUrlParts.host, currentHost)) {
|
|
412
|
+
removeMatchingHeaders(/^(?:authorization|cookie)$/i, this._options.headers);
|
|
413
|
+
}
|
|
412
414
|
|
|
413
|
-
|
|
415
|
+
// Evaluate the beforeRedirect callback
|
|
416
|
+
if (typeof this._options.beforeRedirect === "function") {
|
|
417
|
+
var responseDetails = { headers: response.headers };
|
|
414
418
|
try {
|
|
415
|
-
this.
|
|
419
|
+
this._options.beforeRedirect.call(null, this._options, responseDetails);
|
|
416
420
|
}
|
|
417
|
-
catch (
|
|
418
|
-
this.emit("error",
|
|
421
|
+
catch (err) {
|
|
422
|
+
this.emit("error", err);
|
|
423
|
+
return;
|
|
419
424
|
}
|
|
425
|
+
this._sanitizeOptions(this._options);
|
|
420
426
|
}
|
|
421
|
-
else {
|
|
422
|
-
// The response is not a redirect; return it as-is
|
|
423
|
-
response.responseUrl = this._currentUrl;
|
|
424
|
-
response.redirects = this._redirects;
|
|
425
|
-
this.emit("response", response);
|
|
426
427
|
|
|
427
|
-
|
|
428
|
-
|
|
428
|
+
// Perform the redirected request
|
|
429
|
+
try {
|
|
430
|
+
this._performRequest();
|
|
431
|
+
}
|
|
432
|
+
catch (cause) {
|
|
433
|
+
this.emit("error", new RedirectionError(cause));
|
|
429
434
|
}
|
|
430
435
|
};
|
|
431
436
|
|
|
@@ -559,7 +564,7 @@ function abortRequest(request) {
|
|
|
559
564
|
request.abort();
|
|
560
565
|
}
|
|
561
566
|
|
|
562
|
-
function
|
|
567
|
+
function isSubdomain(subdomain, domain) {
|
|
563
568
|
const dot = subdomain.length - domain.length - 1;
|
|
564
569
|
return dot > 0 && subdomain[dot] === "." && subdomain.endsWith(domain);
|
|
565
570
|
}
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
{
|
|
2
|
-
"_from": "follow-redirects@^1.14.
|
|
3
|
-
"_id": "follow-redirects@1.14.
|
|
2
|
+
"_from": "follow-redirects@^1.14.8",
|
|
3
|
+
"_id": "follow-redirects@1.14.9",
|
|
4
4
|
"_inBundle": false,
|
|
5
|
-
"_integrity": "sha512
|
|
6
|
-
"_location": "/
|
|
5
|
+
"_integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==",
|
|
6
|
+
"_location": "/follow-redirects",
|
|
7
7
|
"_phantomChildren": {},
|
|
8
8
|
"_requested": {
|
|
9
9
|
"type": "range",
|
|
10
10
|
"registry": true,
|
|
11
|
-
"raw": "follow-redirects@^1.14.
|
|
11
|
+
"raw": "follow-redirects@^1.14.8",
|
|
12
12
|
"name": "follow-redirects",
|
|
13
13
|
"escapedName": "follow-redirects",
|
|
14
|
-
"rawSpec": "^1.14.
|
|
14
|
+
"rawSpec": "^1.14.8",
|
|
15
15
|
"saveSpec": null,
|
|
16
|
-
"fetchSpec": "^1.14.
|
|
16
|
+
"fetchSpec": "^1.14.8"
|
|
17
17
|
},
|
|
18
18
|
"_requiredBy": [
|
|
19
|
-
"/
|
|
19
|
+
"/axios"
|
|
20
20
|
],
|
|
21
|
-
"_resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.
|
|
22
|
-
"_shasum": "
|
|
23
|
-
"_spec": "follow-redirects@^1.14.
|
|
24
|
-
"_where": "/Users/conway/Projects/
|
|
21
|
+
"_resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
|
|
22
|
+
"_shasum": "dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7",
|
|
23
|
+
"_spec": "follow-redirects@^1.14.8",
|
|
24
|
+
"_where": "/Users/conway/Projects/TAKreg/node_modules/axios",
|
|
25
25
|
"author": {
|
|
26
26
|
"name": "Ruben Verborgh",
|
|
27
27
|
"email": "ruben@verborgh.org",
|
|
@@ -91,5 +91,5 @@
|
|
|
91
91
|
"mocha": "nyc mocha",
|
|
92
92
|
"test": "npm run lint && npm run mocha"
|
|
93
93
|
},
|
|
94
|
-
"version": "1.14.
|
|
94
|
+
"version": "1.14.9"
|
|
95
95
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name"
|
|
3
|
-
"version"
|
|
4
|
-
"description"
|
|
5
|
-
"dependencies"
|
|
2
|
+
"name": "node-red-contrib-tak-registration",
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"description": "A Node-RED node to register to TAK and to help wrap files as datapackages to send to TAK",
|
|
5
|
+
"dependencies": {
|
|
6
6
|
"adm-zip": "^0.5.9",
|
|
7
|
-
"axios": "^0.
|
|
7
|
+
"axios": "^0.26.1",
|
|
8
8
|
"form-data": "^4.0.0",
|
|
9
9
|
"uuid": "^8.3.2"
|
|
10
10
|
},
|
|
@@ -14,19 +14,26 @@
|
|
|
14
14
|
"form-data",
|
|
15
15
|
"uuid"
|
|
16
16
|
],
|
|
17
|
-
"repository"
|
|
18
|
-
"type":"git",
|
|
19
|
-
"url":"https://github.com/dceejay/takreg/tree/master/"
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/dceejay/takreg/tree/master/"
|
|
20
20
|
},
|
|
21
21
|
"license": "Apache-2.0",
|
|
22
|
-
"keywords": [
|
|
23
|
-
|
|
24
|
-
"
|
|
25
|
-
|
|
22
|
+
"keywords": [
|
|
23
|
+
"TAK",
|
|
24
|
+
"node-red"
|
|
25
|
+
],
|
|
26
|
+
"node-red": {
|
|
27
|
+
"version": ">=2.0.0",
|
|
28
|
+
"nodes": {
|
|
29
|
+
"tak registration": "tak-registration.js"
|
|
26
30
|
}
|
|
27
31
|
},
|
|
28
32
|
"author": {
|
|
29
33
|
"name": "Dave Conway-Jones",
|
|
30
34
|
"email": "dceejay@gmail.com"
|
|
35
|
+
},
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=12"
|
|
31
38
|
}
|
|
32
39
|
}
|
package/tak-registration.html
CHANGED
|
@@ -64,6 +64,9 @@
|
|
|
64
64
|
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
65
65
|
<input type="text" id="node-input-name">
|
|
66
66
|
</div>
|
|
67
|
+
<div class="form-tips" id="pin-tip"><b>Note</b>: This node MUST be used in conjunction with a TCP request node,
|
|
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 "</event>"</div>
|
|
67
70
|
</script>
|
|
68
71
|
<style>
|
|
69
72
|
.inject-time-count {
|
|
@@ -122,8 +125,8 @@
|
|
|
122
125
|
<script type="text/html" data-help-name="tak registration">
|
|
123
126
|
<p>Registers a TAK gateway node and sets up a heartbeat.</p>
|
|
124
127
|
<p>Works in conjunction with a TCP request node, set to point to the TAK server tcp address and port
|
|
125
|
-
(usually 8087 or 8089), set to return strings, <i>keep connection open</i> mode, and split on <code><
|
|
126
|
-
<p>If the
|
|
128
|
+
(usually 8087 or 8089), set to return strings, <i>keep connection open</i> mode, and split on <code></event></code>.</p>
|
|
129
|
+
<p>If the <code>msg.payload</code> is an XML string it will be passed directly though.</p>
|
|
127
130
|
|
|
128
131
|
<h3>Sending data packages...</h3>
|
|
129
132
|
<dl class="message-properties">
|
|
@@ -136,25 +139,23 @@
|
|
|
136
139
|
<dd>each object must contain at least a <b>filename</b> (string) and <b>content</b> a buffer of the file/data.
|
|
137
140
|
eg <code>[{filename:"foo.kml", content: <buffer of the file>}]</code></dd>
|
|
138
141
|
</dl>
|
|
139
|
-
|
|
140
142
|
<h3>Sending marker position...</h3>
|
|
141
143
|
<dl class="message-properties">
|
|
142
144
|
<dt>payload <span class="property-type">object</span></dt>
|
|
143
|
-
<dd>a "standard" <b>node-red worldmap</b> format msg.payload containing `name, lat, lon,
|
|
144
|
-
(alt), (speed), (bearing), (layer)`, where
|
|
145
|
-
the
|
|
146
|
-
be selected on/off in the TAK app.</dd>
|
|
145
|
+
<dd>a "standard" <b>node-red worldmap</b> format msg.payload containing `name, lat, lon, SIDC or cottype or aistype,
|
|
146
|
+
(alt), (speed), (bearing), (layer)`, where SIDC is the standard mil 2525C code, eg SFGPU, or cottype is the
|
|
147
|
+
CoT type, eg a-f-g-u, or aistype is the AIS type code, eg 80 for a tanker. The layer will get turned into a hashtag
|
|
148
|
+
which can then be selected on/off in the TAK app layers control.</dd>
|
|
147
149
|
</dl>
|
|
148
150
|
|
|
149
151
|
<h3>Updating gateway position...</h3>
|
|
150
152
|
<dl class="message-properties">
|
|
151
153
|
<dt>payload <span class="property-type">string | object</span></dt>
|
|
152
|
-
<dd>Either an NMEA string starting `$GPGGA
|
|
153
|
-
optional `alt` properties (but no name property).</dd>
|
|
154
|
+
<dd>Either an NMEA string starting `$GPGGA`, for example from a locally attached serial GPS, or an object
|
|
155
|
+
containing `lat` and `lon` and optional `alt` properties (but no name property).</dd>
|
|
154
156
|
</dl>
|
|
155
|
-
|
|
156
157
|
<h3>Details</h3>
|
|
157
158
|
<p>This should work almost directly with messages received from an email-in node for example -
|
|
158
159
|
but you will need to add the recipients in the sendTo property and may need to filter out
|
|
159
160
|
unwanted messages first.</p>
|
|
160
|
-
</script>
|
|
161
|
+
</script>
|
package/tak-registration.js
CHANGED
|
@@ -57,10 +57,10 @@ module.exports = function(RED) {
|
|
|
57
57
|
setTimeout(sendIt, 2500);
|
|
58
58
|
|
|
59
59
|
node.on("input",function(msg) {
|
|
60
|
-
if (msg.heartbeat) { // Register gateway and do the heartbeats
|
|
60
|
+
if (msg.heartbeat) { // Register gateway and do the heartbeats
|
|
61
61
|
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"/></detail></event>`;
|
|
62
62
|
node.send({payload:template});
|
|
63
|
-
node.status({fill:"green", shape:"dot", text:
|
|
63
|
+
node.status({fill:"green", shape:"dot", text:node.repeat/1000+"s - "+node.callsign});
|
|
64
64
|
return;
|
|
65
65
|
}
|
|
66
66
|
// If there are attachments handle them first.
|
|
@@ -170,17 +170,22 @@ module.exports = function(RED) {
|
|
|
170
170
|
}
|
|
171
171
|
}
|
|
172
172
|
}
|
|
173
|
-
// Handle a generic worldmap marker style as a normal marker
|
|
173
|
+
// Handle a generic worldmap marker style as a normal marker
|
|
174
174
|
else if (typeof msg.payload === "object" && msg.payload.hasOwnProperty("name") && msg.payload.hasOwnProperty("lat") && msg.payload.hasOwnProperty("lon")) {
|
|
175
175
|
var d = new Date();
|
|
176
176
|
var st = d.toISOString();
|
|
177
177
|
var ttl = ((msg.payload.ttl || 0) * 1000) || 60000;
|
|
178
178
|
var et = Date.now() + ttl;
|
|
179
179
|
et = (new Date(et)).toISOString();
|
|
180
|
-
var tag ="
|
|
181
|
-
if (msg.payload.
|
|
182
|
-
|
|
183
|
-
|
|
180
|
+
var tag = msg.payload.remarks || "";
|
|
181
|
+
if (msg.payload.tag) { tag += " " + msg.payload.tag }
|
|
182
|
+
if (msg.payload.layer) { tag += " #" + msg.payload.layer }
|
|
183
|
+
else { tag += " #Worldmap"; }
|
|
184
|
+
var type = msg.payload.cottype || "a-u-g-u";
|
|
185
|
+
if (!msg.payload.cottype && !msg.payload.SIDC && msg.payload.aistype) {
|
|
186
|
+
msg.payload.SIDC = ais2sidc(msg.payload.aistype);
|
|
187
|
+
}
|
|
188
|
+
if (!msg.payload.cottype && msg.payload.SIDC) {
|
|
184
189
|
var s = msg.payload.SIDC.split('-')[0].toLowerCase();
|
|
185
190
|
if (s.startsWith('s')) {
|
|
186
191
|
type = s.split('').join('-').replace('s-','a-').replace('-p-','-');
|
|
@@ -199,13 +204,14 @@ module.exports = function(RED) {
|
|
|
199
204
|
msg.payload = msg.payload.replace(/>\s+</g, "><");
|
|
200
205
|
node.send(msg);
|
|
201
206
|
}
|
|
207
|
+
// Just has lat, lon (and alt) but no name - assume it's our local position we're updating
|
|
202
208
|
else if (typeof msg.payload === "object" && !msg.payload.hasOwnProperty("name") && msg.payload.hasOwnProperty("lat") && msg.payload.hasOwnProperty("lon")) {
|
|
203
|
-
// just has lat, lon (and alt) but no name - assume it's us we're updating
|
|
204
209
|
node.lat = msg.payload.lat;
|
|
205
210
|
node.lon = msg.payload.lon;
|
|
206
211
|
if (msg.payload.hasOwnProperty("alt")) { node.alt = parseInt(msg.payload.alt); }
|
|
207
212
|
}
|
|
208
|
-
|
|
213
|
+
// Drop anything we don't handle yet.
|
|
214
|
+
else {
|
|
209
215
|
node.log("Dropped: "+JSON.stringify(msg.payload));
|
|
210
216
|
}
|
|
211
217
|
});
|
|
@@ -219,5 +225,50 @@ module.exports = function(RED) {
|
|
|
219
225
|
});
|
|
220
226
|
}
|
|
221
227
|
|
|
222
|
-
|
|
223
|
-
|
|
228
|
+
var aisToSidc1 = {
|
|
229
|
+
4: "SFSPXA------",
|
|
230
|
+
5: "SFSPXM------",
|
|
231
|
+
6: "SFSPXMP-----",
|
|
232
|
+
7: "SFSPXMC-----",
|
|
233
|
+
8: "SFSPXMO-----",
|
|
234
|
+
9: "SFSPXM------"
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
var aisToSidc2 = {
|
|
238
|
+
30: "SFSPXF------",
|
|
239
|
+
31: "SFSPXMTO----",
|
|
240
|
+
32: "SFSPXMTO--NS",
|
|
241
|
+
33: "SFSPXFDR----",
|
|
242
|
+
34: "SFUPND------",
|
|
243
|
+
35: "SFSP--------",
|
|
244
|
+
36: "SFSPXR------",
|
|
245
|
+
37: "SFSPXA------",
|
|
246
|
+
40: "SFSPXA------", //-
|
|
247
|
+
50: "SFSPXM------", //-
|
|
248
|
+
52: "SFSPXMTU----",
|
|
249
|
+
53: "SFSPNS------",
|
|
250
|
+
55: "SFSPXL------",
|
|
251
|
+
58: "SFSPNM------",
|
|
252
|
+
60: "SFSPXMP-----", //-
|
|
253
|
+
70: "SFSPXMC-----", //-
|
|
254
|
+
71: "SFSPXMH-----",
|
|
255
|
+
72: "SFSPXMH-----",
|
|
256
|
+
73: "SFSPXMH-----",
|
|
257
|
+
74: "SFSPXMH-----",
|
|
258
|
+
80: "SFSPXMO-----", //-
|
|
259
|
+
90: "SFSPXM------", //-
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
var ais2sidc = function (aisType) {
|
|
263
|
+
//aisType = Number(aisType);
|
|
264
|
+
if (aisType >= 100) { return "GNMPOHTH----"; }
|
|
265
|
+
aisType = aisToSidc2[aisType];
|
|
266
|
+
if (aisType && isNaN(aisType)) { return aisType; }
|
|
267
|
+
aisType = parseInt(aisType / 10);
|
|
268
|
+
aisType = aisToSidc1[aisType];
|
|
269
|
+
if (aisType && isNaN(aisType)) { return aisType; }
|
|
270
|
+
return "SFSPXM------";
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
RED.nodes.registerType("tak registration", TakRegistrationNode);
|
|
274
|
+
};
|