node-red-contrib-tak-registration 0.1.0 → 0.2.1

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 CHANGED
@@ -1,35 +1,50 @@
1
1
  node-red-contrib-tak-registration
2
2
  =================================
3
3
 
4
- A <a href="http://nodered.org" target="_new">Node-RED</a> node to register to a TAK server,
5
- and to help send wrap files as datapackages for TAK.
4
+ A <a href="http://nodered.org" target="_new">Node-RED</a> node to register to a TAK server, to help send wrap files as datapackages for TAK, and to create simple markers from json messages.
6
5
 
7
6
  **NOTE**: NOT yet for production use.
8
7
 
9
- Install
10
- -------
8
+ ## Install
11
9
 
12
10
  Run the following command in your Node-RED user directory - typically `~/.node-red`
13
11
 
14
12
  npm i node-red-contrib-tak-registration
15
13
 
16
- Usage
17
- -----
14
+ ## Usage
18
15
 
19
16
  Registers a TAK gateway node and sets up a heartbeat.
20
17
 
21
18
  Works in conjunction with a TCP request node, set to point to the TAK server tcp address and port
22
19
  (usually 8087 or 8089), set to return strings, <i>keep connection open</i> mode, and split on "&lt;event/&gt;".
23
20
 
24
- It can also accepts files to be sent to the TAK server by sending a msg as follows:
21
+ It can send various types of messages to TAK.
25
22
 
26
- ### Inputs
23
+ ### Standard COT event
27
24
 
28
- - **sendTo** - *string|array* - can either be an individual TAK callsign, an array of callsigns, or **broadcast**
25
+ If the `msg.payload` is an XML string it will be passed directly though.
26
+
27
+ ### Sending data packages...
28
+
29
+ requires a msg containing the following properties
30
+
31
+ - **sendTo** - *string|array* - can either be an individual TAK callsign, an array of callsigns, or **broadcast**
29
32
  to send to all users, or **public** to just upload the package to the TAK server.
30
33
  - **topic** - *string* - the overall package name - IE what you want it to be called on the TAK device (keep it short).
31
34
  - **attachments** - *array of objects* - each object must contain at least a **filename** (string) and *content** a buffer of the file/data, for example `[{filename:"foo.kml", content: <buffer of the file>}]`
32
35
 
36
+ ### Sending marker position...
37
+
38
+ To create or update a simple marker send a msg with the following property
39
+
40
+ - **payload** - *object* - a "standard" node-red worldmap format msg.payload containing `name, lat, lon, type or SIDC, (alt), (speed), (bearing), (layer)`, where type is the CoT type eg a-f-g-u or the SIDC is the standard mil 2525C code, eg SFGPU. The layer will get turned int a hastag which can then be selected on/off in the TAK app.
41
+
42
+ ### Updating gateway position...
43
+
44
+ To update the location of the gateway dynamically the node can accept a payload
45
+
46
+ - **payload** - *string|object* - Either a string starting `$GPGGA` or an object containing `lat` and `lon` and optional `alt` properties (but no name property).
47
+
33
48
  ### Details
34
49
 
35
50
  This should work almost directly with messages received from an email-in node for example - but you will need to add the recipients in the sendTo property and may need to filter out unwanted messages first.
@@ -1,9 +1,64 @@
1
1
  # Changelog
2
2
 
3
+ ### 0.25.0 (January 18, 2022)
4
+
5
+ Breaking changes:
6
+ - Fixing maxBodyLength enforcement ([#3786](https://github.com/axios/axios/pull/3786))
7
+ - Don't rely on strict mode behaviour for arguments ([#3470](https://github.com/axios/axios/pull/3470))
8
+ - Adding error handling when missing url ([#3791](https://github.com/axios/axios/pull/3791))
9
+ - Update isAbsoluteURL.js removing escaping of non-special characters ([#3809](https://github.com/axios/axios/pull/3809))
10
+ - Use native Array.isArray() in utils.js ([#3836](https://github.com/axios/axios/pull/3836))
11
+ - Adding error handling inside stream end callback ([#3967](https://github.com/axios/axios/pull/3967))
12
+
13
+ Fixes and Functionality:
14
+ - Added aborted even handler ([#3916](https://github.com/axios/axios/pull/3916))
15
+ - Header types expanded allowing `boolean` and `number` types ([#4144](https://github.com/axios/axios/pull/4144))
16
+ - Fix cancel signature allowing cancel message to be `undefined` ([#3153](https://github.com/axios/axios/pull/3153))
17
+ - Updated type checks to be formulated better ([#3342](https://github.com/axios/axios/pull/3342))
18
+ - Avoid unnecessary buffer allocations ([#3321](https://github.com/axios/axios/pull/3321))
19
+ - Adding a socket handler to keep TCP connection live when processing long living requests ([#3422](https://github.com/axios/axios/pull/3422))
20
+ - Added toFormData helper function ([#3757](https://github.com/axios/axios/pull/3757))
21
+ - Adding responseEncoding prop type in AxiosRequestConfig ([#3918](https://github.com/axios/axios/pull/3918))
22
+
23
+ Internal and Tests:
24
+ - Adding axios-test-instance to ecosystem ([#3786](https://github.com/axios/axios/pull/3786))
25
+ - Optimize the logic of isAxiosError ([#3546](https://github.com/axios/axios/pull/3546))
26
+ - Add tests and documentation to display how multiple inceptors work ([#3564](https://github.com/axios/axios/pull/3564))
27
+ - Updating follow-redirects to version 1.14.7 ([#4379](https://github.com/axios/axios/pull/4379))
28
+
29
+
30
+ Documentation:
31
+ - Fixing changelog to show corrext pull request ([#4219](https://github.com/axios/axios/pull/4219))
32
+ - Update upgrade guide for https proxy setting ([#3604](https://github.com/axios/axios/pull/3604))
33
+
34
+ Huge thanks to everyone who contributed to this release via code (authors listed below) or via reviews and triaging on GitHub:
35
+
36
+ - [Jay](mailto:jasonsaayman@gmail.com)
37
+ - [Rijk van Zanten](https://github.com/rijkvanzanten)
38
+ - [Kohta Ito](https://github.com/koh110)
39
+ - [Brandon Faulkner](https://github.com/bfaulk96)
40
+ - [Stefano Magni](https://github.com/NoriSte)
41
+ - [enofan](https://github.com/fanguangyi)
42
+ - [Andrey Pechkurov](https://github.com/puzpuzpuz)
43
+ - [Doowonee](https://github.com/doowonee)
44
+ - [Emil Broman](https://github.com/emilbroman-eqt)
45
+ - [Remco Haszing](https://github.com/remcohaszing)
46
+ - [Black-Hole](https://github.com/BlackHole1)
47
+ - [Wolfram Kriesing](https://github.com/wolframkriesing)
48
+ - [Andrew Ovens](https://github.com/repl-andrew-ovens)
49
+ - [Paulo Renato](https://github.com/PauloRSF)
50
+ - [Ben Carp](https://github.com/carpben)
51
+ - [Hirotaka Tagawa](https://github.com/wafuwafu13)
52
+ - [狼族小狈](https://github.com/lzxb)
53
+ - [C. Lewis](https://github.com/ctjlewis)
54
+ - [Felipe Carvalho](https://github.com/FCarvalhoVII)
55
+ - [Daniel](https://github.com/djs113)
56
+ - [Gustavo Sales](https://github.com/gussalesdev)
57
+
3
58
  ### 0.24.0 (October 25, 2021)
4
59
 
5
60
  Breaking changes:
6
- - Revert: change type of AxiosResponse to any, please read lengthy discussion here: ([4141](https://github.com/axios/axios/issues/4141)) pull request: ([#4114](https://github.com/axios/axios/pull/4114))
61
+ - Revert: change type of AxiosResponse to any, please read lengthy discussion here: ([#4141](https://github.com/axios/axios/issues/4141)) pull request: ([#4186](https://github.com/axios/axios/pull/4186))
7
62
 
8
63
  Huge thanks to everyone who contributed to this release via code (authors listed below) or via reviews and triaging on GitHub:
9
64
 
@@ -32,6 +32,7 @@ Promise based HTTP client for the browser and node.js
32
32
  - [Custom instance defaults](#custom-instance-defaults)
33
33
  - [Config order of precedence](#config-order-of-precedence)
34
34
  - [Interceptors](#interceptors)
35
+ - [Multiple Interceptors](#multiple-interceptors)
35
36
  - [Handling Errors](#handling-errors)
36
37
  - [Cancellation](#cancellation)
37
38
  - [Using application/x-www-form-urlencoded format](#using-applicationx-www-form-urlencoded-format)
@@ -645,6 +646,21 @@ axios.interceptors.request.use(function (config) {
645
646
  }, null, { runWhen: onGetCall });
646
647
  ```
647
648
 
649
+ ### Multiple Interceptors
650
+
651
+ Given you add multiple response interceptors
652
+ and when the response was fulfilled
653
+ - then each interceptor is executed
654
+ - then they are executed in the order they were added
655
+ - then only the last interceptor's result is returned
656
+ - then every interceptor receives the result of it's predecessor
657
+ - and when the fulfillment-interceptor throws
658
+ - then the following fulfillment-interceptor is not called
659
+ - then the following rejection-interceptor is called
660
+ - once caught, another following fulfill-interceptor is called again (just like in a promise chain).
661
+
662
+ Read [the interceptor tests](./test/specs/interceptors.spec.js) for seeing all this in code.
663
+
648
664
  ## Handling Errors
649
665
 
650
666
  ```js
@@ -1,5 +1,11 @@
1
1
  # Upgrade Guide
2
2
 
3
+ ### 0.18.x -> 0.19.0
4
+
5
+ #### HTTPS Proxies
6
+
7
+ Routing through an https proxy now requires setting the `protocol` attribute of the proxy configuration to `https`
8
+
3
9
  ### 0.15.x -> 0.16.0
4
10
 
5
11
  #### `Promise` Type Declarations
@@ -1,3 +1,5 @@
1
+ /* axios v0.25.0 | (c) 2022 by Matt Zabriskie */
2
+ /* axios v0.24.0 | (c) 2022 by Matt Zabriskie */
1
3
  (function webpackUniversalModuleDefinition(root, factory) {
2
4
  if(typeof exports === 'object' && typeof module === 'object')
3
5
  module.exports = factory();
@@ -1,2 +1,4 @@
1
+ /* axios v0.25.0 | (c) 2022 by Matt Zabriskie */
2
+ /* axios v0.24.0 | (c) 2022 by Matt Zabriskie */
1
3
  !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.axios=t():e.axios=t()}(this,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=11)}([function(e,t,n){"use strict";var r=n(3),o=Object.prototype.toString;function i(e){return"[object Array]"===o.call(e)}function s(e){return void 0===e}function a(e){return null!==e&&"object"==typeof e}function u(e){if("[object Object]"!==o.call(e))return!1;var t=Object.getPrototypeOf(e);return null===t||t===Object.prototype}function c(e){return"[object Function]"===o.call(e)}function f(e,t){if(null!=e)if("object"!=typeof e&&(e=[e]),i(e))for(var n=0,r=e.length;n<r;n++)t.call(null,e[n],n,e);else for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&t.call(null,e[o],o,e)}e.exports={isArray:i,isArrayBuffer:function(e){return"[object ArrayBuffer]"===o.call(e)},isBuffer:function(e){return null!==e&&!s(e)&&null!==e.constructor&&!s(e.constructor)&&"function"==typeof e.constructor.isBuffer&&e.constructor.isBuffer(e)},isFormData:function(e){return"undefined"!=typeof FormData&&e instanceof FormData},isArrayBufferView:function(e){return"undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&e.buffer instanceof ArrayBuffer},isString:function(e){return"string"==typeof e},isNumber:function(e){return"number"==typeof e},isObject:a,isPlainObject:u,isUndefined:s,isDate:function(e){return"[object Date]"===o.call(e)},isFile:function(e){return"[object File]"===o.call(e)},isBlob:function(e){return"[object Blob]"===o.call(e)},isFunction:c,isStream:function(e){return a(e)&&c(e.pipe)},isURLSearchParams:function(e){return"undefined"!=typeof URLSearchParams&&e instanceof URLSearchParams},isStandardBrowserEnv:function(){return("undefined"==typeof navigator||"ReactNative"!==navigator.product&&"NativeScript"!==navigator.product&&"NS"!==navigator.product)&&("undefined"!=typeof window&&"undefined"!=typeof document)},forEach:f,merge:function e(){var t={};function n(n,r){u(t[r])&&u(n)?t[r]=e(t[r],n):u(n)?t[r]=e({},n):i(n)?t[r]=n.slice():t[r]=n}for(var r=0,o=arguments.length;r<o;r++)f(arguments[r],n);return t},extend:function(e,t,n){return f(t,(function(t,o){e[o]=n&&"function"==typeof t?r(t,n):t})),e},trim:function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")},stripBOM:function(e){return 65279===e.charCodeAt(0)&&(e=e.slice(1)),e}}},function(e,t,n){"use strict";var r=n(0),o=n(17),i=n(5),s={"Content-Type":"application/x-www-form-urlencoded"};function a(e,t){!r.isUndefined(e)&&r.isUndefined(e["Content-Type"])&&(e["Content-Type"]=t)}var u,c={transitional:{silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1},adapter:(("undefined"!=typeof XMLHttpRequest||"undefined"!=typeof process&&"[object process]"===Object.prototype.toString.call(process))&&(u=n(6)),u),transformRequest:[function(e,t){return o(t,"Accept"),o(t,"Content-Type"),r.isFormData(e)||r.isArrayBuffer(e)||r.isBuffer(e)||r.isStream(e)||r.isFile(e)||r.isBlob(e)?e:r.isArrayBufferView(e)?e.buffer:r.isURLSearchParams(e)?(a(t,"application/x-www-form-urlencoded;charset=utf-8"),e.toString()):r.isObject(e)||t&&"application/json"===t["Content-Type"]?(a(t,"application/json"),function(e,t,n){if(r.isString(e))try{return(t||JSON.parse)(e),r.trim(e)}catch(e){if("SyntaxError"!==e.name)throw e}return(n||JSON.stringify)(e)}(e)):e}],transformResponse:[function(e){var t=this.transitional||c.transitional,n=t&&t.silentJSONParsing,o=t&&t.forcedJSONParsing,s=!n&&"json"===this.responseType;if(s||o&&r.isString(e)&&e.length)try{return JSON.parse(e)}catch(e){if(s){if("SyntaxError"===e.name)throw i(e,this,"E_JSON_PARSE");throw e}}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,validateStatus:function(e){return e>=200&&e<300},headers:{common:{Accept:"application/json, text/plain, */*"}}};r.forEach(["delete","get","head"],(function(e){c.headers[e]={}})),r.forEach(["post","put","patch"],(function(e){c.headers[e]=r.merge(s)})),e.exports=c},function(e,t,n){"use strict";function r(e){this.message=e}r.prototype.toString=function(){return"Cancel"+(this.message?": "+this.message:"")},r.prototype.__CANCEL__=!0,e.exports=r},function(e,t,n){"use strict";e.exports=function(e,t){return function(){for(var n=new Array(arguments.length),r=0;r<n.length;r++)n[r]=arguments[r];return e.apply(t,n)}}},function(e,t,n){"use strict";var r=n(0);function o(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}e.exports=function(e,t,n){if(!t)return e;var i;if(n)i=n(t);else if(r.isURLSearchParams(t))i=t.toString();else{var s=[];r.forEach(t,(function(e,t){null!=e&&(r.isArray(e)?t+="[]":e=[e],r.forEach(e,(function(e){r.isDate(e)?e=e.toISOString():r.isObject(e)&&(e=JSON.stringify(e)),s.push(o(t)+"="+o(e))})))})),i=s.join("&")}if(i){var a=e.indexOf("#");-1!==a&&(e=e.slice(0,a)),e+=(-1===e.indexOf("?")?"?":"&")+i}return e}},function(e,t,n){"use strict";e.exports=function(e,t,n,r,o){return e.config=t,n&&(e.code=n),e.request=r,e.response=o,e.isAxiosError=!0,e.toJSON=function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:this.config,code:this.code,status:this.response&&this.response.status?this.response.status:null}},e}},function(e,t,n){"use strict";var r=n(0),o=n(18),i=n(19),s=n(4),a=n(20),u=n(23),c=n(24),f=n(7),l=n(1),p=n(2);e.exports=function(e){return new Promise((function(t,n){var d,h=e.data,m=e.headers,v=e.responseType;function y(){e.cancelToken&&e.cancelToken.unsubscribe(d),e.signal&&e.signal.removeEventListener("abort",d)}r.isFormData(h)&&delete m["Content-Type"];var g=new XMLHttpRequest;if(e.auth){var b=e.auth.username||"",x=e.auth.password?unescape(encodeURIComponent(e.auth.password)):"";m.Authorization="Basic "+btoa(b+":"+x)}var w=a(e.baseURL,e.url);function E(){if(g){var r="getAllResponseHeaders"in g?u(g.getAllResponseHeaders()):null,i={data:v&&"text"!==v&&"json"!==v?g.response:g.responseText,status:g.status,statusText:g.statusText,headers:r,config:e,request:g};o((function(e){t(e),y()}),(function(e){n(e),y()}),i),g=null}}if(g.open(e.method.toUpperCase(),s(w,e.params,e.paramsSerializer),!0),g.timeout=e.timeout,"onloadend"in g?g.onloadend=E:g.onreadystatechange=function(){g&&4===g.readyState&&(0!==g.status||g.responseURL&&0===g.responseURL.indexOf("file:"))&&setTimeout(E)},g.onabort=function(){g&&(n(f("Request aborted",e,"ECONNABORTED",g)),g=null)},g.onerror=function(){n(f("Network Error",e,null,g)),g=null},g.ontimeout=function(){var t=e.timeout?"timeout of "+e.timeout+"ms exceeded":"timeout exceeded",r=e.transitional||l.transitional;e.timeoutErrorMessage&&(t=e.timeoutErrorMessage),n(f(t,e,r.clarifyTimeoutError?"ETIMEDOUT":"ECONNABORTED",g)),g=null},r.isStandardBrowserEnv()){var S=(e.withCredentials||c(w))&&e.xsrfCookieName?i.read(e.xsrfCookieName):void 0;S&&(m[e.xsrfHeaderName]=S)}"setRequestHeader"in g&&r.forEach(m,(function(e,t){void 0===h&&"content-type"===t.toLowerCase()?delete m[t]:g.setRequestHeader(t,e)})),r.isUndefined(e.withCredentials)||(g.withCredentials=!!e.withCredentials),v&&"json"!==v&&(g.responseType=e.responseType),"function"==typeof e.onDownloadProgress&&g.addEventListener("progress",e.onDownloadProgress),"function"==typeof e.onUploadProgress&&g.upload&&g.upload.addEventListener("progress",e.onUploadProgress),(e.cancelToken||e.signal)&&(d=function(e){g&&(n(!e||e&&e.type?new p("canceled"):e),g.abort(),g=null)},e.cancelToken&&e.cancelToken.subscribe(d),e.signal&&(e.signal.aborted?d():e.signal.addEventListener("abort",d))),h||(h=null),g.send(h)}))}},function(e,t,n){"use strict";var r=n(5);e.exports=function(e,t,n,o,i){var s=new Error(e);return r(s,t,n,o,i)}},function(e,t,n){"use strict";e.exports=function(e){return!(!e||!e.__CANCEL__)}},function(e,t,n){"use strict";var r=n(0);e.exports=function(e,t){t=t||{};var n={};function o(e,t){return r.isPlainObject(e)&&r.isPlainObject(t)?r.merge(e,t):r.isPlainObject(t)?r.merge({},t):r.isArray(t)?t.slice():t}function i(n){return r.isUndefined(t[n])?r.isUndefined(e[n])?void 0:o(void 0,e[n]):o(e[n],t[n])}function s(e){if(!r.isUndefined(t[e]))return o(void 0,t[e])}function a(n){return r.isUndefined(t[n])?r.isUndefined(e[n])?void 0:o(void 0,e[n]):o(void 0,t[n])}function u(n){return n in t?o(e[n],t[n]):n in e?o(void 0,e[n]):void 0}var c={url:s,method:s,data:s,baseURL:a,transformRequest:a,transformResponse:a,paramsSerializer:a,timeout:a,timeoutMessage:a,withCredentials:a,adapter:a,responseType:a,xsrfCookieName:a,xsrfHeaderName:a,onUploadProgress:a,onDownloadProgress:a,decompress:a,maxContentLength:a,maxBodyLength:a,transport:a,httpAgent:a,httpsAgent:a,cancelToken:a,socketPath:a,responseEncoding:a,validateStatus:u};return r.forEach(Object.keys(e).concat(Object.keys(t)),(function(e){var t=c[e]||i,o=t(e);r.isUndefined(o)&&t!==u||(n[e]=o)})),n}},function(e,t){e.exports={version:"0.24.0"}},function(e,t,n){e.exports=n(12)},function(e,t,n){"use strict";var r=n(0),o=n(3),i=n(13),s=n(9);var a=function e(t){var n=new i(t),a=o(i.prototype.request,n);return r.extend(a,i.prototype,n),r.extend(a,n),a.create=function(n){return e(s(t,n))},a}(n(1));a.Axios=i,a.Cancel=n(2),a.CancelToken=n(26),a.isCancel=n(8),a.VERSION=n(10).version,a.all=function(e){return Promise.all(e)},a.spread=n(27),a.isAxiosError=n(28),e.exports=a,e.exports.default=a},function(e,t,n){"use strict";var r=n(0),o=n(4),i=n(14),s=n(15),a=n(9),u=n(25),c=u.validators;function f(e){this.defaults=e,this.interceptors={request:new i,response:new i}}f.prototype.request=function(e){"string"==typeof e?(e=arguments[1]||{}).url=arguments[0]:e=e||{},(e=a(this.defaults,e)).method?e.method=e.method.toLowerCase():this.defaults.method?e.method=this.defaults.method.toLowerCase():e.method="get";var t=e.transitional;void 0!==t&&u.assertOptions(t,{silentJSONParsing:c.transitional(c.boolean),forcedJSONParsing:c.transitional(c.boolean),clarifyTimeoutError:c.transitional(c.boolean)},!1);var n=[],r=!0;this.interceptors.request.forEach((function(t){"function"==typeof t.runWhen&&!1===t.runWhen(e)||(r=r&&t.synchronous,n.unshift(t.fulfilled,t.rejected))}));var o,i=[];if(this.interceptors.response.forEach((function(e){i.push(e.fulfilled,e.rejected)})),!r){var f=[s,void 0];for(Array.prototype.unshift.apply(f,n),f=f.concat(i),o=Promise.resolve(e);f.length;)o=o.then(f.shift(),f.shift());return o}for(var l=e;n.length;){var p=n.shift(),d=n.shift();try{l=p(l)}catch(e){d(e);break}}try{o=s(l)}catch(e){return Promise.reject(e)}for(;i.length;)o=o.then(i.shift(),i.shift());return o},f.prototype.getUri=function(e){return e=a(this.defaults,e),o(e.url,e.params,e.paramsSerializer).replace(/^\?/,"")},r.forEach(["delete","get","head","options"],(function(e){f.prototype[e]=function(t,n){return this.request(a(n||{},{method:e,url:t,data:(n||{}).data}))}})),r.forEach(["post","put","patch"],(function(e){f.prototype[e]=function(t,n,r){return this.request(a(r||{},{method:e,url:t,data:n}))}})),e.exports=f},function(e,t,n){"use strict";var r=n(0);function o(){this.handlers=[]}o.prototype.use=function(e,t,n){return this.handlers.push({fulfilled:e,rejected:t,synchronous:!!n&&n.synchronous,runWhen:n?n.runWhen:null}),this.handlers.length-1},o.prototype.eject=function(e){this.handlers[e]&&(this.handlers[e]=null)},o.prototype.forEach=function(e){r.forEach(this.handlers,(function(t){null!==t&&e(t)}))},e.exports=o},function(e,t,n){"use strict";var r=n(0),o=n(16),i=n(8),s=n(1),a=n(2);function u(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.signal&&e.signal.aborted)throw new a("canceled")}e.exports=function(e){return u(e),e.headers=e.headers||{},e.data=o.call(e,e.data,e.headers,e.transformRequest),e.headers=r.merge(e.headers.common||{},e.headers[e.method]||{},e.headers),r.forEach(["delete","get","head","post","put","patch","common"],(function(t){delete e.headers[t]})),(e.adapter||s.adapter)(e).then((function(t){return u(e),t.data=o.call(e,t.data,t.headers,e.transformResponse),t}),(function(t){return i(t)||(u(e),t&&t.response&&(t.response.data=o.call(e,t.response.data,t.response.headers,e.transformResponse))),Promise.reject(t)}))}},function(e,t,n){"use strict";var r=n(0),o=n(1);e.exports=function(e,t,n){var i=this||o;return r.forEach(n,(function(n){e=n.call(i,e,t)})),e}},function(e,t,n){"use strict";var r=n(0);e.exports=function(e,t){r.forEach(e,(function(n,r){r!==t&&r.toUpperCase()===t.toUpperCase()&&(e[t]=n,delete e[r])}))}},function(e,t,n){"use strict";var r=n(7);e.exports=function(e,t,n){var o=n.config.validateStatus;n.status&&o&&!o(n.status)?t(r("Request failed with status code "+n.status,n.config,null,n.request,n)):e(n)}},function(e,t,n){"use strict";var r=n(0);e.exports=r.isStandardBrowserEnv()?{write:function(e,t,n,o,i,s){var a=[];a.push(e+"="+encodeURIComponent(t)),r.isNumber(n)&&a.push("expires="+new Date(n).toGMTString()),r.isString(o)&&a.push("path="+o),r.isString(i)&&a.push("domain="+i),!0===s&&a.push("secure"),document.cookie=a.join("; ")},read:function(e){var t=document.cookie.match(new RegExp("(^|;\\s*)("+e+")=([^;]*)"));return t?decodeURIComponent(t[3]):null},remove:function(e){this.write(e,"",Date.now()-864e5)}}:{write:function(){},read:function(){return null},remove:function(){}}},function(e,t,n){"use strict";var r=n(21),o=n(22);e.exports=function(e,t){return e&&!r(t)?o(e,t):t}},function(e,t,n){"use strict";e.exports=function(e){return/^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(e)}},function(e,t,n){"use strict";e.exports=function(e,t){return t?e.replace(/\/+$/,"")+"/"+t.replace(/^\/+/,""):e}},function(e,t,n){"use strict";var r=n(0),o=["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"];e.exports=function(e){var t,n,i,s={};return e?(r.forEach(e.split("\n"),(function(e){if(i=e.indexOf(":"),t=r.trim(e.substr(0,i)).toLowerCase(),n=r.trim(e.substr(i+1)),t){if(s[t]&&o.indexOf(t)>=0)return;s[t]="set-cookie"===t?(s[t]?s[t]:[]).concat([n]):s[t]?s[t]+", "+n:n}})),s):s}},function(e,t,n){"use strict";var r=n(0);e.exports=r.isStandardBrowserEnv()?function(){var e,t=/(msie|trident)/i.test(navigator.userAgent),n=document.createElement("a");function o(e){var r=e;return t&&(n.setAttribute("href",r),r=n.href),n.setAttribute("href",r),{href:n.href,protocol:n.protocol?n.protocol.replace(/:$/,""):"",host:n.host,search:n.search?n.search.replace(/^\?/,""):"",hash:n.hash?n.hash.replace(/^#/,""):"",hostname:n.hostname,port:n.port,pathname:"/"===n.pathname.charAt(0)?n.pathname:"/"+n.pathname}}return e=o(window.location.href),function(t){var n=r.isString(t)?o(t):t;return n.protocol===e.protocol&&n.host===e.host}}():function(){return!0}},function(e,t,n){"use strict";var r=n(10).version,o={};["object","boolean","number","function","string","symbol"].forEach((function(e,t){o[e]=function(n){return typeof n===e||"a"+(t<1?"n ":" ")+e}}));var i={};o.transitional=function(e,t,n){function o(e,t){return"[Axios v"+r+"] Transitional option '"+e+"'"+t+(n?". "+n:"")}return function(n,r,s){if(!1===e)throw new Error(o(r," has been removed"+(t?" in "+t:"")));return t&&!i[r]&&(i[r]=!0,console.warn(o(r," has been deprecated since v"+t+" and will be removed in the near future"))),!e||e(n,r,s)}},e.exports={assertOptions:function(e,t,n){if("object"!=typeof e)throw new TypeError("options must be an object");for(var r=Object.keys(e),o=r.length;o-- >0;){var i=r[o],s=t[i];if(s){var a=e[i],u=void 0===a||s(a,i,e);if(!0!==u)throw new TypeError("option "+i+" must be "+u)}else if(!0!==n)throw Error("Unknown option "+i)}},validators:o}},function(e,t,n){"use strict";var r=n(2);function o(e){if("function"!=typeof e)throw new TypeError("executor must be a function.");var t;this.promise=new Promise((function(e){t=e}));var n=this;this.promise.then((function(e){if(n._listeners){var t,r=n._listeners.length;for(t=0;t<r;t++)n._listeners[t](e);n._listeners=null}})),this.promise.then=function(e){var t,r=new Promise((function(e){n.subscribe(e),t=e})).then(e);return r.cancel=function(){n.unsubscribe(t)},r},e((function(e){n.reason||(n.reason=new r(e),t(n.reason))}))}o.prototype.throwIfRequested=function(){if(this.reason)throw this.reason},o.prototype.subscribe=function(e){this.reason?e(this.reason):this._listeners?this._listeners.push(e):this._listeners=[e]},o.prototype.unsubscribe=function(e){if(this._listeners){var t=this._listeners.indexOf(e);-1!==t&&this._listeners.splice(t,1)}},o.source=function(){var e;return{token:new o((function(t){e=t})),cancel:e}},e.exports=o},function(e,t,n){"use strict";e.exports=function(e){return function(t){return e.apply(null,t)}}},function(e,t,n){"use strict";e.exports=function(e){return"object"==typeof e&&!0===e.isAxiosError}}])}));
2
4
  //# sourceMappingURL=axios.min.map
@@ -1,6 +1,6 @@
1
1
  // TypeScript Version: 3.0
2
2
 
3
- export type AxiosRequestHeaders = Record<string, string>;
3
+ export type AxiosRequestHeaders = Record<string, string | number | boolean>;
4
4
 
5
5
  export type AxiosResponseHeaders = Record<string, string> & {
6
6
  "set-cookie"?: string[]
@@ -53,6 +53,20 @@ export type ResponseType =
53
53
  | 'text'
54
54
  | 'stream';
55
55
 
56
+ export type responseEncoding =
57
+ | 'ascii' | 'ASCII'
58
+ | 'ansi' | 'ANSI'
59
+ | 'binary' | 'BINARY'
60
+ | 'base64' | 'BASE64'
61
+ | 'base64url' | 'BASE64URL'
62
+ | 'hex' | 'HEX'
63
+ | 'latin1' | 'LATIN1'
64
+ | 'ucs-2' | 'UCS-2'
65
+ | 'ucs2' | 'UCS2'
66
+ | 'utf-8' | 'UTF-8'
67
+ | 'utf8' | 'UTF8'
68
+ | 'utf16le' | 'UTF16LE';
69
+
56
70
  export interface TransitionalOptions {
57
71
  silentJSONParsing?: boolean;
58
72
  forcedJSONParsing?: boolean;
@@ -75,6 +89,7 @@ export interface AxiosRequestConfig<D = any> {
75
89
  adapter?: AxiosAdapter;
76
90
  auth?: AxiosBasicCredentials;
77
91
  responseType?: ResponseType;
92
+ responseEncoding?: responseEncoding | string;
78
93
  xsrfCookieName?: string;
79
94
  xsrfHeaderName?: string;
80
95
  onUploadProgress?: (progressEvent: any) => void;
@@ -138,7 +153,7 @@ export interface CancelStatic {
138
153
  }
139
154
 
140
155
  export interface Cancel {
141
- message: string;
156
+ message: string | undefined;
142
157
  }
143
158
 
144
159
  export interface Canceler {
@@ -60,8 +60,10 @@ module.exports = function httpAdapter(config) {
60
60
  done();
61
61
  resolvePromise(value);
62
62
  };
63
+ var rejected = false;
63
64
  var reject = function reject(value) {
64
65
  done();
66
+ rejected = true;
65
67
  rejectPromise(value);
66
68
  };
67
69
  var data = config.data;
@@ -99,6 +101,10 @@ module.exports = function httpAdapter(config) {
99
101
  ));
100
102
  }
101
103
 
104
+ if (config.maxBodyLength > -1 && data.length > config.maxBodyLength) {
105
+ return reject(createError('Request body larger than maxBodyLength limit', config));
106
+ }
107
+
102
108
  // Add Content-Length header if data exists
103
109
  if (!headerNames['content-length']) {
104
110
  headers['Content-Length'] = data.length;
@@ -269,27 +275,40 @@ module.exports = function httpAdapter(config) {
269
275
 
270
276
  // make sure the content length is not over the maxContentLength if specified
271
277
  if (config.maxContentLength > -1 && totalResponseBytes > config.maxContentLength) {
278
+ // stream.destoy() emit aborted event before calling reject() on Node.js v16
279
+ rejected = true;
272
280
  stream.destroy();
273
281
  reject(createError('maxContentLength size of ' + config.maxContentLength + ' exceeded',
274
282
  config, null, lastRequest));
275
283
  }
276
284
  });
277
285
 
286
+ stream.on('aborted', function handlerStreamAborted() {
287
+ if (rejected) {
288
+ return;
289
+ }
290
+ stream.destroy();
291
+ reject(createError('error request aborted', config, 'ERR_REQUEST_ABORTED', lastRequest));
292
+ });
293
+
278
294
  stream.on('error', function handleStreamError(err) {
279
295
  if (req.aborted) return;
280
296
  reject(enhanceError(err, config, null, lastRequest));
281
297
  });
282
298
 
283
299
  stream.on('end', function handleStreamEnd() {
284
- var responseData = Buffer.concat(responseBuffer);
285
- if (config.responseType !== 'arraybuffer') {
286
- responseData = responseData.toString(config.responseEncoding);
287
- if (!config.responseEncoding || config.responseEncoding === 'utf8') {
288
- responseData = utils.stripBOM(responseData);
300
+ try {
301
+ var responseData = responseBuffer.length === 1 ? responseBuffer[0] : Buffer.concat(responseBuffer);
302
+ if (config.responseType !== 'arraybuffer') {
303
+ responseData = responseData.toString(config.responseEncoding);
304
+ if (!config.responseEncoding || config.responseEncoding === 'utf8') {
305
+ responseData = utils.stripBOM(responseData);
306
+ }
289
307
  }
308
+ response.data = responseData;
309
+ } catch (err) {
310
+ reject(enhanceError(err, config, err.code, response.request, response));
290
311
  }
291
-
292
- response.data = responseData;
293
312
  settle(resolve, reject, response);
294
313
  });
295
314
  }
@@ -301,6 +320,12 @@ module.exports = function httpAdapter(config) {
301
320
  reject(enhanceError(err, config, null, req));
302
321
  });
303
322
 
323
+ // set tcp keep alive to prevent drop connection by peer
324
+ req.on('socket', function handleRequestSocket(socket) {
325
+ // default interval of sending ack packet is 1 minute
326
+ socket.setKeepAlive(true, 1000 * 60);
327
+ });
328
+
304
329
  // Handle request timeout
305
330
  if (config.timeout) {
306
331
  // This is forcing a int timeout to avoid problems if the `req` interface doesn't handle other types.
@@ -26,14 +26,18 @@ function Axios(instanceConfig) {
26
26
  *
27
27
  * @param {Object} config The config specific for this request (merged with this.defaults)
28
28
  */
29
- Axios.prototype.request = function request(config) {
29
+ Axios.prototype.request = function request(configOrUrl, config) {
30
30
  /*eslint no-param-reassign:0*/
31
31
  // Allow for axios('example/url'[, config]) a la fetch API
32
- if (typeof config === 'string') {
33
- config = arguments[1] || {};
34
- config.url = arguments[0];
35
- } else {
32
+ if (typeof configOrUrl === 'string') {
36
33
  config = config || {};
34
+ config.url = configOrUrl;
35
+ } else {
36
+ config = configOrUrl || {};
37
+ }
38
+
39
+ if (!config.url) {
40
+ throw new Error('Provided config url is not valid');
37
41
  }
38
42
 
39
43
  config = mergeConfig(this.defaults, config);
@@ -118,6 +122,9 @@ Axios.prototype.request = function request(config) {
118
122
  };
119
123
 
120
124
  Axios.prototype.getUri = function getUri(config) {
125
+ if (!config.url) {
126
+ throw new Error('Provided config url is not valid');
127
+ }
121
128
  config = mergeConfig(this.defaults, config);
122
129
  return buildURL(config.url, config.params, config.paramsSerializer).replace(/^\?/, '');
123
130
  };
@@ -1,3 +1,3 @@
1
1
  module.exports = {
2
- "version": "0.24.0"
2
+ "version": "0.25.0"
3
3
  };
@@ -10,5 +10,5 @@ module.exports = function isAbsoluteURL(url) {
10
10
  // A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL).
11
11
  // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
12
12
  // by any combination of letters, digits, plus, period, or hyphen.
13
- return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url);
13
+ return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url);
14
14
  };
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ var utils = require('./../utils');
4
+
3
5
  /**
4
6
  * Determines whether the payload is an error thrown by Axios
5
7
  *
@@ -7,5 +9,5 @@
7
9
  * @returns {boolean} True if the payload is an error thrown by Axios, otherwise false
8
10
  */
9
11
  module.exports = function isAxiosError(payload) {
10
- return (typeof payload === 'object') && (payload.isAxiosError === true);
12
+ return utils.isObject(payload) && (payload.isAxiosError === true);
11
13
  };
@@ -0,0 +1,55 @@
1
+ 'use strict';
2
+
3
+ function combinedKey(parentKey, elKey) {
4
+ return parentKey + '.' + elKey;
5
+ }
6
+
7
+ function buildFormData(formData, data, parentKey) {
8
+ if (Array.isArray(data)) {
9
+ data.forEach(function buildArray(el, i) {
10
+ buildFormData(formData, el, combinedKey(parentKey, i));
11
+ });
12
+ } else if (
13
+ typeof data === 'object' &&
14
+ !(data instanceof File || data === null)
15
+ ) {
16
+ Object.keys(data).forEach(function buildObject(key) {
17
+ buildFormData(
18
+ formData,
19
+ data[key],
20
+ parentKey ? combinedKey(parentKey, key) : key
21
+ );
22
+ });
23
+ } else {
24
+ if (data === undefined) {
25
+ return;
26
+ }
27
+
28
+ var value =
29
+ typeof data === 'boolean' || typeof data === 'number'
30
+ ? data.toString()
31
+ : data;
32
+ formData.append(parentKey, value);
33
+ }
34
+ }
35
+
36
+ /**
37
+ * convert a data object to FormData
38
+ *
39
+ * type FormDataPrimitive = string | Blob | number | boolean
40
+ * interface FormDataNest {
41
+ * [x: string]: FormVal
42
+ * }
43
+ *
44
+ * type FormVal = FormDataNest | FormDataPrimitive
45
+ *
46
+ * @param {FormVal} data
47
+ */
48
+
49
+ module.exports = function getFormData(data) {
50
+ var formData = new FormData();
51
+
52
+ buildFormData(formData, data);
53
+
54
+ return formData;
55
+ };
@@ -13,7 +13,7 @@ var toString = Object.prototype.toString;
13
13
  * @returns {boolean} True if value is an Array, otherwise false
14
14
  */
15
15
  function isArray(val) {
16
- return toString.call(val) === '[object Array]';
16
+ return Array.isArray(val);
17
17
  }
18
18
 
19
19
  /**
@@ -54,7 +54,7 @@ function isArrayBuffer(val) {
54
54
  * @returns {boolean} True if value is an FormData, otherwise false
55
55
  */
56
56
  function isFormData(val) {
57
- return (typeof FormData !== 'undefined') && (val instanceof FormData);
57
+ return toString.call(val) === '[object FormData]';
58
58
  }
59
59
 
60
60
  /**
@@ -68,7 +68,7 @@ function isArrayBufferView(val) {
68
68
  if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) {
69
69
  result = ArrayBuffer.isView(val);
70
70
  } else {
71
- result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer);
71
+ result = (val) && (val.buffer) && (isArrayBuffer(val.buffer));
72
72
  }
73
73
  return result;
74
74
  }
@@ -175,7 +175,7 @@ function isStream(val) {
175
175
  * @returns {boolean} True if value is a URLSearchParams object, otherwise false
176
176
  */
177
177
  function isURLSearchParams(val) {
178
- return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams;
178
+ return toString.call(val) === '[object URLSearchParams]';
179
179
  }
180
180
 
181
181
  /**
@@ -1,48 +1,37 @@
1
1
  {
2
- "_from": "axios@^0.24.0",
3
- "_id": "axios@0.24.0",
4
- "_inBundle": false,
5
- "_integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==",
6
- "_location": "/node-red-contrib-takfiles/axios",
7
- "_phantomChildren": {},
8
- "_requested": {
9
- "type": "range",
10
- "registry": true,
11
- "raw": "axios@^0.24.0",
12
- "name": "axios",
13
- "escapedName": "axios",
14
- "rawSpec": "^0.24.0",
15
- "saveSpec": null,
16
- "fetchSpec": "^0.24.0"
17
- },
18
- "_requiredBy": [
19
- "/node-red-contrib-takfiles"
20
- ],
21
- "_resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz",
22
- "_shasum": "804e6fa1e4b9c5288501dd9dff56a7a0940d20d6",
23
- "_spec": "axios@^0.24.0",
24
- "_where": "/Users/conway/Projects/DCJNodes/takfile/",
25
- "author": {
26
- "name": "Matt Zabriskie"
2
+ "name": "axios",
3
+ "version": "0.25.0",
4
+ "description": "Promise based HTTP client for the browser and node.js",
5
+ "main": "index.js",
6
+ "types": "index.d.ts",
7
+ "scripts": {
8
+ "test": "grunt test && dtslint",
9
+ "start": "node ./sandbox/server.js",
10
+ "build": "NODE_ENV=production grunt build",
11
+ "preversion": "grunt version && npm test",
12
+ "version": "npm run build && git add -A dist && git add CHANGELOG.md bower.json package.json",
13
+ "postversion": "git push && git push --tags",
14
+ "examples": "node ./examples/server.js",
15
+ "coveralls": "cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js",
16
+ "fix": "eslint --fix lib/**/*.js"
27
17
  },
28
- "browser": {
29
- "./lib/adapters/http.js": "./lib/adapters/xhr.js"
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/axios/axios.git"
30
21
  },
22
+ "keywords": [
23
+ "xhr",
24
+ "http",
25
+ "ajax",
26
+ "promise",
27
+ "node"
28
+ ],
29
+ "author": "Matt Zabriskie",
30
+ "license": "MIT",
31
31
  "bugs": {
32
32
  "url": "https://github.com/axios/axios/issues"
33
33
  },
34
- "bundleDependencies": false,
35
- "bundlesize": [
36
- {
37
- "path": "./dist/axios.min.js",
38
- "threshold": "5kB"
39
- }
40
- ],
41
- "dependencies": {
42
- "follow-redirects": "^1.14.4"
43
- },
44
- "deprecated": false,
45
- "description": "Promise based HTTP client for the browser and node.js",
34
+ "homepage": "https://axios-http.com",
46
35
  "devDependencies": {
47
36
  "abortcontroller-polyfill": "^1.5.0",
48
37
  "coveralls": "^3.0.0",
@@ -79,35 +68,19 @@
79
68
  "webpack": "^4.44.2",
80
69
  "webpack-dev-server": "^3.11.0"
81
70
  },
82
- "homepage": "https://axios-http.com",
83
- "jsdelivr": "dist/axios.min.js",
84
- "keywords": [
85
- "xhr",
86
- "http",
87
- "ajax",
88
- "promise",
89
- "node"
90
- ],
91
- "license": "MIT",
92
- "main": "index.js",
93
- "name": "axios",
94
- "repository": {
95
- "type": "git",
96
- "url": "git+https://github.com/axios/axios.git"
97
- },
98
- "scripts": {
99
- "build": "NODE_ENV=production grunt build",
100
- "coveralls": "cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js",
101
- "examples": "node ./examples/server.js",
102
- "fix": "eslint --fix lib/**/*.js",
103
- "postversion": "git push && git push --tags",
104
- "preversion": "grunt version && npm test",
105
- "start": "node ./sandbox/server.js",
106
- "test": "grunt test && dtslint",
107
- "version": "npm run build && git add -A dist && git add CHANGELOG.md bower.json package.json"
71
+ "browser": {
72
+ "./lib/adapters/http.js": "./lib/adapters/xhr.js"
108
73
  },
109
- "types": "index.d.ts",
110
- "typings": "./index.d.ts",
74
+ "jsdelivr": "dist/axios.min.js",
111
75
  "unpkg": "dist/axios.min.js",
112
- "version": "0.24.0"
76
+ "typings": "./index.d.ts",
77
+ "dependencies": {
78
+ "follow-redirects": "^1.14.7"
79
+ },
80
+ "bundlesize": [
81
+ {
82
+ "path": "./dist/axios.min.js",
83
+ "threshold": "5kB"
84
+ }
85
+ ]
113
86
  }
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name" : "node-red-contrib-tak-registration",
3
- "version" : "0.1.0",
3
+ "version" : "0.2.1",
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
  "adm-zip": "^0.5.9",
7
- "axios": "^0.24.0",
7
+ "axios": "^0.25.0",
8
8
  "form-data": "^4.0.0",
9
9
  "uuid": "^8.3.2"
10
10
  },
@@ -13,7 +13,37 @@
13
13
  </div>
14
14
  <div class="form-row">
15
15
  <label for="node-input-group"><i class="fa fa-users"></i> Group</label>
16
- <input type="text" id="node-input-group" placeholder="Group (if any)">
16
+ <!-- <input type="text" id="node-input-group" placeholder="Group (if any)"> -->
17
+ <select id="node-input-group">
18
+ <option value="Cyan">Cyan</option>
19
+ <option value="Yellow">Yellow</option>
20
+ <option value="Red">Red</option>
21
+ <option value="Blue">Blue</option>
22
+ <option value="Green">Green</option>
23
+ <option value="Orange">Orange</option>
24
+ <option value="Magenta">Magenta</option>
25
+ <option value="Maroon">Maroon</option>
26
+ <option value="Purple">Purple</option>
27
+ <option value="Dark Blue">Dark Blue</option>
28
+ <option value="Dark Green">Dark Green</option>
29
+ <option value="Teal">Teal</option>
30
+ <option value="Brown">Brown</option>
31
+ </select>
32
+ </div>
33
+ <div class="form-row">
34
+ <label for="node-input-role"><i class="fa fa-crosshairs"></i> Role</label>
35
+ <!-- <input type="text" id="node-input-group" placeholder="Group (if any)"> -->
36
+ <select id="node-input-role">
37
+ <option value="Gateway">Gateway</option>
38
+ <option value="Team Member">Team Member</option>
39
+ <option value="Team Lead">Team Lead</option>
40
+ <option value="HQ">HQ</option>
41
+ <option value="Sniper">Sniper</option>
42
+ <option value="Medic">Medic</option>
43
+ <option value="Forward Observer">Forward Observer</option>
44
+ <option value="RTO">RTO</option>
45
+ <option value="K9">K9</option>
46
+ </select>
17
47
  </div>
18
48
  <div class="form-row" id="node-timing">
19
49
  <label for="node-once"><i class="fa fa-heartbeat"></i> Heartbeat</label>
@@ -23,7 +53,7 @@
23
53
  <option value="s">Seconds</option>
24
54
  <option value="m">Minutes</option>
25
55
  <option value="h">Hours</option>
26
- </select><br/>
56
+ </select>
27
57
  <input type="hidden" id="node-input-repeat">
28
58
  </div>
29
59
  <div class="form-row">
@@ -49,6 +79,7 @@
49
79
  name: {value:""},
50
80
  callsign: {value: ""},
51
81
  group: {value: "Cyan"},
82
+ role: {value: "Gateway"},
52
83
  latitude: {value: ""},
53
84
  longitude: {value: ""},
54
85
  repeat: {value:"60", validate:function(v) { return ((v === "") || (RED.validators.number(v) && (v >= 0) && (v <= 2147483))) }},
@@ -92,10 +123,11 @@
92
123
  <p>Registers a TAK gateway node and sets up a heartbeat.</p>
93
124
  <p>Works in conjunction with a TCP request node, set to point to the TAK server tcp address and port
94
125
  (usually 8087 or 8089), set to return strings, <i>keep connection open</i> mode, and split on <code>&lt;event/&gt;</code>.</p>
95
- <p>It can also accepts files to be sent to the TAK server by sending a msg as follows:</p>
96
- <h3>Inputs</h3>
126
+ <p>If the `msg.payload` is an XML string it will be passed directly though.</p>
127
+
128
+ <h3>Sending data packages...</h3>
97
129
  <dl class="message-properties">
98
- <dt>sendTo <span class="property-type">string|array</span></dt>
130
+ <dt>sendTo <span class="property-type">string | array</span></dt>
99
131
  <dd>can either be an individual TAK callsign, an array of callsigns, or <b>broadcast</b>
100
132
  to send to all users, or <b>public</b> to just upload the package to the TAK server.</dd>
101
133
  <dt>topic <span class="property-type">string</span></dt>
@@ -104,6 +136,23 @@
104
136
  <dd>each object must contain at least a <b>filename</b> (string) and <b>content</b> a buffer of the file/data.
105
137
  eg <code>[{filename:"foo.kml", content: &lt;buffer of the file&gt;}]</code></dd>
106
138
  </dl>
139
+
140
+ <h3>Sending marker position...</h3>
141
+ <dl class="message-properties">
142
+ <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, type or SIDC,
144
+ (alt), (speed), (bearing), (layer)`, where type is the CoT type eg a-f-g-u or the SIDC is
145
+ the standard mil 2525C code, eg SFGPU. The layer will get turned int a hastag which can then
146
+ be selected on/off in the TAK app.</dd>
147
+ </dl>
148
+
149
+ <h3>Updating gateway position...</h3>
150
+ <dl class="message-properties">
151
+ <dt>payload <span class="property-type">string | object</span></dt>
152
+ <dd>Either an NMEA string starting `$GPGGA` or an object containing `lat` and `lon` and
153
+ optional `alt` properties (but no name property).</dd>
154
+ </dl>
155
+
107
156
  <h3>Details</h3>
108
157
  <p>This should work almost directly with messages received from an email-in node for example -
109
158
  but you will need to add the recipients in the sendTo property and may need to filter out
@@ -1,3 +1,4 @@
1
+ const { methodToString } = require('adm-zip/util');
1
2
 
2
3
  module.exports = function(RED) {
3
4
  "use strict";
@@ -8,12 +9,16 @@ module.exports = function(RED) {
8
9
  const FormData = require('form-data')
9
10
  const { v4: uuidv4 } = require('uuid');
10
11
  const uuid = require('uuid');
12
+ const ver = require('./package.json').version;
11
13
 
12
14
  function TakRegistrationNode(n) {
13
15
  RED.nodes.createNode(this,n);
14
16
  this.group = n.group;
17
+ this.role = n.role || "Gateway";
18
+ this.type = n.type || "a-f-G-I-B";
15
19
  this.lat = n.latitude;
16
20
  this.lon = n.longitude;
21
+ this.alt = 9999999;
17
22
  this.callsign = n.callsign;
18
23
  this.repeat = n.repeat;
19
24
  this.host = n.dphost;
@@ -31,8 +36,11 @@ module.exports = function(RED) {
31
36
  etime: new Date(Date.now() + 2000 * node.repeat).toISOString(),
32
37
  lat: node.lat,
33
38
  lon: node.lon,
39
+ alt: node.alt,
34
40
  callsign: node.callsign,
35
41
  group: node.group,
42
+ role: node.role,
43
+ type: node.type,
36
44
  heartbeat: true
37
45
  });
38
46
  };
@@ -46,11 +54,11 @@ module.exports = function(RED) {
46
54
  };
47
55
 
48
56
  node.repeaterSetup();
49
- setTimeout(sendIt, 2000);
57
+ setTimeout(sendIt, 2500);
50
58
 
51
- this.on("input",function(msg) {
52
- if (msg.heartbeat) { // Register gateway and do the heartbeats
53
- var template = `<event version="2.0" uid="${node.uuid}" type="a-f-G-I-B" how="h-e" time="${msg.time}" start="${msg.time}" stale="${msg.etime}"><point lat="${msg.lat}" lon="${msg.lon}" hae="9999999" ce="9999999" le="9999999"/><detail><takv os="${os.platform()}" version="4.1.0.231" device="${os.hostname()}" platform="ATAK-CIV"/><contact endpoint="*:-1:stcp" callsign="${msg.callsign}"/><uid Droid="${msg.callsign}"/><__group name="${msg.group}" role="Gateway"/><status battery="99"/></detail></event>`;
59
+ node.on("input",function(msg) {
60
+ if (msg.heartbeat) { // Register gateway and do the heartbeats √<takv device="${os.hostname()}" platform="${os.type()}" />
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>`;
54
62
  node.send({payload:template});
55
63
  node.status({fill:"green", shape:"dot", text: node.repeat/1000+"s - "+node.callsign});
56
64
  return;
@@ -146,17 +154,63 @@ module.exports = function(RED) {
146
154
  node.error(error.message,error);
147
155
  })
148
156
  }
149
- else if (typeof msg.payload === "string") { // Assume it's proper XML event so pass straight through
150
- if (msg.payload.trim().startsWith('<') && msg.payload.trim().endsWith('>')) {
157
+ else if (typeof msg.payload === "string" ) {
158
+ if (msg.payload.trim().startsWith('<') && msg.payload.trim().endsWith('>')) { // Assume it's proper XML event so pass straight through
151
159
  node.send(msg);
152
160
  }
161
+ else if (msg.payload.trim().startsWith('$GPGGA')) { // maybe it's an NMEA string
162
+ // console.log("It's NMEA",msg.payload);
163
+ var nm = msg.payload.trim().split(',');
164
+ if (nm[0] === '$GPGGA' && nm[6] > 0) {
165
+ const la = parseInt(nm[2].substr(0,2)) + parseFloat(nm[2].substr(2))/60;
166
+ node.lat = ((nm[3] === "N") ? la : -la).toFixed(6);
167
+ const lo = parseInt(nm[4].substr(0,3)) + parseFloat(nm[4].substr(3))/60;
168
+ node.lon = ((nm[5] === "E") ? lo : -lo).toFixed(6);
169
+ node.alt = nm[9];
170
+ }
171
+ }
172
+ }
173
+ // Handle a generic worldmap marker style as a normal marker -
174
+ else if (typeof msg.payload === "object" && msg.payload.hasOwnProperty("name") && msg.payload.hasOwnProperty("lat") && msg.payload.hasOwnProperty("lon")) {
175
+ var d = new Date();
176
+ var st = d.toISOString();
177
+ var ttl = ((msg.payload.ttl || 0) * 1000) || 60000;
178
+ var et = Date.now() + ttl;
179
+ et = (new Date(et)).toISOString();
180
+ var tag ="#Worldmap";
181
+ if (msg.payload.layer) { tag = "#" + msg.payload.layer }
182
+ var type = msg.payload.type || "a-u-g-u";
183
+ if (!msg.payload.type && msg.payload.SIDC) {
184
+ var s = msg.payload.SIDC.split('-')[0].toLowerCase();
185
+ if (s.startsWith('s')) {
186
+ type = s.split('').join('-').replace('s-','a-').replace('-p-','-');
187
+ }
188
+ }
189
+ // console.log("TYPE",type)
190
+ msg.payload = `<event version="2.0" type="${type}" uid="${msg.payload.name}" time="${st}" start="${st}" stale="${et}" how="h-e">
191
+ <point lat="${msg.payload.lat || 0}" lon="${msg.payload.lon || 0}" hae="${parseInt(msg.payload.alt || 9999999.0)}" le="9999999.0" ce="9999999.0"/>
192
+ <detail>
193
+ <takv device="${os.hostname()}" os="${os.platform()}" platform="NRedTAK" version="${ver}"/>
194
+ <track course="${msg.payload.bearing || 0}" speed="${parseInt(msg.payload.speed) || 0}"/>
195
+ <contact callsign="${msg.payload.name}"/>
196
+ <remarks source="NRedTAK">${tag}</remarks>
197
+ </detail>
198
+ </event>`
199
+ msg.payload = msg.payload.replace(/>\s+</g, "><");
200
+ node.send(msg);
201
+ }
202
+ 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
+ node.lat = msg.payload.lat;
205
+ node.lon = msg.payload.lon;
206
+ if (msg.payload.hasOwnProperty("alt")) { node.alt = parseInt(msg.payload.alt); }
153
207
  }
154
208
  else { // Drop anything we don't handle yet.
155
209
  node.log("Dropped: "+JSON.stringify(msg.payload));
156
210
  }
157
211
  });
158
212
 
159
- this.on("close", function() {
213
+ node.on("close", function() {
160
214
  // var tim = new Date().toISOString();
161
215
  // var template = `<?xml version="1.0" encoding="utf-8" standalone="yes"?><event version="2.0" uid="${node.uuid}" type="t-x-d-d" how="h-g-i-g-o" time="${tim}" start="${tim}" stale="${tim}"><detail><link uid="${node.uuid}" relation="p-p" type="a-f-G-I-B" /></detail><point le="9999999.0" ce="9999999.0" hae="9999999.0" lon="0" lat="0" /></event>"`;
162
216
  // node.send({payload:template}); // This never happens in time so not useful