node-red-contrib-ntrip 0.2.7 → 0.2.8
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/.github/workflows/node.js.yml +2 -2
- package/.github/workflows/release.yml +6 -6
- package/CHANGELOG.md +8 -0
- package/README.md +40 -0
- package/examples/rtcm-encode.json +1 -0
- package/ntrip/99-ntrip.html +82 -0
- package/ntrip/99-ntrip.js +3 -0
- package/ntrip/nodes/rtcm-encoder-node.js +90 -0
- package/package.json +1 -1
- package/test/rtcm-encoder.spec.js +144 -0
|
@@ -19,9 +19,9 @@ jobs:
|
|
|
19
19
|
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
|
20
20
|
|
|
21
21
|
steps:
|
|
22
|
-
- uses: actions/checkout@
|
|
22
|
+
- uses: actions/checkout@v6
|
|
23
23
|
- name: Use Node.js ${{ matrix.node-version }}
|
|
24
|
-
uses: actions/setup-node@
|
|
24
|
+
uses: actions/setup-node@v6
|
|
25
25
|
with:
|
|
26
26
|
node-version: ${{ matrix.node-version }}
|
|
27
27
|
cache: 'npm'
|
|
@@ -23,9 +23,9 @@ jobs:
|
|
|
23
23
|
matrix:
|
|
24
24
|
node-version: [18.x, 20.x, 22.x]
|
|
25
25
|
steps:
|
|
26
|
-
- uses: actions/checkout@
|
|
26
|
+
- uses: actions/checkout@v6
|
|
27
27
|
- name: Use Node.js ${{ matrix.node-version }}
|
|
28
|
-
uses: actions/setup-node@
|
|
28
|
+
uses: actions/setup-node@v6
|
|
29
29
|
with:
|
|
30
30
|
node-version: ${{ matrix.node-version }}
|
|
31
31
|
cache: 'npm'
|
|
@@ -38,8 +38,8 @@ jobs:
|
|
|
38
38
|
needs: test
|
|
39
39
|
runs-on: ubuntu-latest
|
|
40
40
|
steps:
|
|
41
|
-
- uses: actions/checkout@
|
|
42
|
-
- uses: actions/setup-node@
|
|
41
|
+
- uses: actions/checkout@v6
|
|
42
|
+
- uses: actions/setup-node@v6
|
|
43
43
|
with:
|
|
44
44
|
node-version: 20
|
|
45
45
|
registry-url: 'https://registry.npmjs.org/'
|
|
@@ -54,11 +54,11 @@ jobs:
|
|
|
54
54
|
permissions:
|
|
55
55
|
contents: write
|
|
56
56
|
steps:
|
|
57
|
-
- uses: actions/checkout@
|
|
57
|
+
- uses: actions/checkout@v6
|
|
58
58
|
with:
|
|
59
59
|
fetch-depth: 0
|
|
60
60
|
- name: Create GitHub Release
|
|
61
|
-
uses: softprops/action-gh-release@
|
|
61
|
+
uses: softprops/action-gh-release@v3
|
|
62
62
|
with:
|
|
63
63
|
tag_name: ${{ github.ref_name }}
|
|
64
64
|
name: ${{ github.ref_name }}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
All notable changes to this project will be documented in this file.
|
|
3
3
|
|
|
4
|
+
## [0.2.8]
|
|
5
|
+
### Added RTCM Encoder node
|
|
6
|
+
- New `RtcmEncoder` node — inverse of `RtcmDecoder`. Accepts an `RtcmMessage` instance (or `msg.payload.message` from the decoder) and emits the encoded RTCM 3 frame as `msg.payload.rtcmMessage` (Buffer).
|
|
7
|
+
- Designed for round-trip flows: decode, optionally mutate, then re-encode for forwarding.
|
|
8
|
+
- Does not construct messages from plain fields (unlike the NMEA encoder) — there are 187 RTCM message types in `@gnss/rtcm` and per-type constructors are rarely needed for real flows.
|
|
9
|
+
- New example flow `examples/rtcm-encode.json` demonstrating the decode → encode round-trip.
|
|
10
|
+
- 6 new specs in `test/rtcm-encoder.spec.js` covering: round-trip from decoder instance, decoder-output-shape input, non-`RtcmMessage` rejected to error output, empty payload rejected, no `node.error` flood on bad input, fixture sanity.
|
|
11
|
+
|
|
4
12
|
## [0.2.7]
|
|
5
13
|
### Internal — tooling, tests, docs (no runtime changes)
|
|
6
14
|
- Added a mocha test suite (14 specs across `NmeaDecoder`, `NmeaEncoder`, `RtcmDecoder`) using `node-red-node-test-helper`. Regression specs are tagged so they can be re-run with `mocha -g regression`.
|
package/README.md
CHANGED
|
@@ -155,6 +155,46 @@ msg.payload =
|
|
|
155
155
|
};
|
|
156
156
|
```
|
|
157
157
|
|
|
158
|
+
# RTCM Encoder Node
|
|
159
|
+
Encodes an `RtcmMessage` instance back into a binary RTCM 3 frame using the
|
|
160
|
+
`@gnss/rtcm` library. The inverse of the RTCM Decoder — useful for re-emitting
|
|
161
|
+
a decoded frame after modification (e.g. rewriting a station ID before
|
|
162
|
+
forwarding) or for synthesising test fixtures.
|
|
163
|
+
|
|
164
|
+
The node has **two outputs**: encoded frames go to the first, failures to the
|
|
165
|
+
second.
|
|
166
|
+
|
|
167
|
+
This encoder does **not** construct an `RtcmMessage` from plain fields. The
|
|
168
|
+
input must already be an instance — typically `msg.payload.message` from the
|
|
169
|
+
RTCM Decoder.
|
|
170
|
+
|
|
171
|
+
Input shape:
|
|
172
|
+
```javascript
|
|
173
|
+
// Direct: pass an RtcmMessage instance
|
|
174
|
+
msg.payload = <RtcmMessage instance>;
|
|
175
|
+
|
|
176
|
+
// Or pipe the decoder's success output straight through:
|
|
177
|
+
msg.payload = {
|
|
178
|
+
rtcm, // number — echoed back
|
|
179
|
+
messageType, // string — echoed back
|
|
180
|
+
message, // RtcmMessage instance — what gets encoded
|
|
181
|
+
input // ignored
|
|
182
|
+
};
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Successful output:
|
|
186
|
+
```javascript
|
|
187
|
+
msg.payload =
|
|
188
|
+
{
|
|
189
|
+
rtcmMessage, // Buffer — the encoded RTCM 3 frame, ready to forward
|
|
190
|
+
rtcm, // number — the RTCM message type identifier
|
|
191
|
+
messageType, // string — the constructor name
|
|
192
|
+
input, // the original input as supplied
|
|
193
|
+
};
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
See also example flow [**RTCM encode flow**](examples/rtcm-encode.json).
|
|
197
|
+
|
|
158
198
|
# NMEA Decoder Node
|
|
159
199
|
This node accepts NMEA 0183 sentences as a string or `Buffer`. Multiple
|
|
160
200
|
sentences in a single input (delimited by `\r\n`) are split and decoded
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[{"id":"rtcm-encode-tab","type":"tab","label":"RTCM encode round-trip","disabled":false,"info":"Decode a known RTCM 1005 frame, then re-encode it via the RTCM Encoder node.\nWatch the two debug nodes — the encoded output should match the original bytes.\n"},{"id":"inj-1","type":"inject","z":"rtcm-encode-tab","name":"Trigger","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":140,"y":140,"wires":[["fn-load-rtcm"]]},{"id":"fn-load-rtcm","type":"function","z":"rtcm-encode-tab","name":"Load RTCM 1005 sample","func":"// A real RTCM 3 type 1005 (Stationary RTK Reference Station ARP) frame.\nmsg.payload = Buffer.from('D300133ED7D30202980EDEEF34B4BD62AC0941986F33360B98', 'hex');\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":140,"wires":[["decoder","dbg-raw"]]},{"id":"dbg-raw","type":"debug","z":"rtcm-encode-tab","name":"Raw RTCM bytes","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":540,"y":80,"wires":[]},{"id":"decoder","type":"RtcmDecoder","z":"rtcm-encode-tab","description":"","x":540,"y":140,"wires":[["encoder","dbg-decoded"],["dbg-err"]]},{"id":"dbg-decoded","type":"debug","z":"rtcm-encode-tab","name":"Decoded frame","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":740,"y":80,"wires":[]},{"id":"encoder","type":"RtcmEncoder","z":"rtcm-encode-tab","description":"","x":740,"y":140,"wires":[["dbg-encoded"],["dbg-err"]]},{"id":"dbg-encoded","type":"debug","z":"rtcm-encode-tab","name":"Re-encoded RTCM","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":940,"y":140,"wires":[]},{"id":"dbg-err","type":"debug","z":"rtcm-encode-tab","name":"decode/encode error","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":740,"y":220,"wires":[]}]
|
package/ntrip/99-ntrip.html
CHANGED
|
@@ -301,6 +301,88 @@
|
|
|
301
301
|
|
|
302
302
|
<!-- ------------------------------------------------------------------------------------------ -->
|
|
303
303
|
|
|
304
|
+
<script type="text/javascript">
|
|
305
|
+
RED.nodes.registerType('RtcmEncoder', {
|
|
306
|
+
category: 'GNSS',
|
|
307
|
+
color: '#C0DEED',
|
|
308
|
+
defaults: {
|
|
309
|
+
description: { value:"" },
|
|
310
|
+
},
|
|
311
|
+
inputs: 1,
|
|
312
|
+
outputs: 2,
|
|
313
|
+
icon: "function.png",
|
|
314
|
+
paletteLabel: "RTCM Encoder",
|
|
315
|
+
label: function () {
|
|
316
|
+
return this.description || "RTCM Encoder";
|
|
317
|
+
},
|
|
318
|
+
labelStyle: function() {
|
|
319
|
+
return this.description?"node_label_italic":"";
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
</script>
|
|
324
|
+
|
|
325
|
+
<script type="text/x-red" data-template-name="RtcmEncoder">
|
|
326
|
+
<div class="form-row">
|
|
327
|
+
<label for="node-input-description"><i class="fa fa-comment"></i> Description</label>
|
|
328
|
+
<input type="text" id="node-input-description" placeholder="The description of the node (optional)">
|
|
329
|
+
</div>
|
|
330
|
+
</script>
|
|
331
|
+
|
|
332
|
+
<script type="text/x-red" data-help-name="RtcmEncoder">
|
|
333
|
+
<p>Encodes an <code>RtcmMessage</code> instance back into a binary RTCM 3
|
|
334
|
+
frame using the <code>@gnss/rtcm</code> library. The inverse of the
|
|
335
|
+
<i>RTCM Decoder</i> — useful for re-emitting a decoded frame after
|
|
336
|
+
modification (e.g. rewriting a station ID before forwarding upstream).</p>
|
|
337
|
+
<p>This encoder does not construct an <code>RtcmMessage</code> from plain
|
|
338
|
+
fields. The input must already be an instance — typically the
|
|
339
|
+
<code>msg.payload.message</code> emitted by the decoder.</p>
|
|
340
|
+
|
|
341
|
+
<h3>Configuration</h3>
|
|
342
|
+
<dl class="message-properties">
|
|
343
|
+
<dt>Description <span class="property-type">string</span></dt>
|
|
344
|
+
<dd>Optional label shown in the flow editor.</dd>
|
|
345
|
+
</dl>
|
|
346
|
+
|
|
347
|
+
<h3>Inputs</h3>
|
|
348
|
+
<dl class="message-properties">
|
|
349
|
+
<dt>payload <span class="property-type">RtcmMessage</span></dt>
|
|
350
|
+
<dd>An <code>RtcmMessage</code> instance, encoded directly.</dd>
|
|
351
|
+
<dt>payload.message <span class="property-type">RtcmMessage</span></dt>
|
|
352
|
+
<dd>Round-trip shape from the <i>RTCM Decoder</i> — the encoder picks
|
|
353
|
+
up <code>msg.payload.message</code> and encodes that.</dd>
|
|
354
|
+
</dl>
|
|
355
|
+
|
|
356
|
+
<h3>Outputs</h3>
|
|
357
|
+
<p>Two outputs: successfully encoded frames go to the first; failures go to the second.</p>
|
|
358
|
+
<ol class="node-ports">
|
|
359
|
+
<li>Encoded
|
|
360
|
+
<dl class="message-properties">
|
|
361
|
+
<dt>payload.rtcmMessage <span class="property-type">Buffer</span></dt>
|
|
362
|
+
<dd>The encoded RTCM 3 frame, ready to forward to an NTRIP
|
|
363
|
+
uploader or a TCP sink.</dd>
|
|
364
|
+
<dt>payload.rtcm <span class="property-type">number</span></dt>
|
|
365
|
+
<dd>The RTCM message type identifier (e.g. <code>1005</code>).</dd>
|
|
366
|
+
<dt>payload.messageType <span class="property-type">string</span></dt>
|
|
367
|
+
<dd>The constructor name (e.g. <code>StationArp</code>).</dd>
|
|
368
|
+
<dt>payload.input <span class="property-type">any</span></dt>
|
|
369
|
+
<dd>The original input as supplied.</dd>
|
|
370
|
+
</dl>
|
|
371
|
+
</li>
|
|
372
|
+
<li>Error
|
|
373
|
+
<dl class="message-properties">
|
|
374
|
+
<dt>payload.error <span class="property-type">Error | string</span></dt>
|
|
375
|
+
<dd>The exception thrown by the encoder, or a string describing
|
|
376
|
+
invalid input.</dd>
|
|
377
|
+
<dt>payload.input <span class="property-type">any</span></dt>
|
|
378
|
+
<dd>The offending input.</dd>
|
|
379
|
+
</dl>
|
|
380
|
+
</li>
|
|
381
|
+
</ol>
|
|
382
|
+
</script>
|
|
383
|
+
|
|
384
|
+
<!-- ------------------------------------------------------------------------------------------ -->
|
|
385
|
+
|
|
304
386
|
<script type="text/javascript">
|
|
305
387
|
RED.nodes.registerType('NmeaDecoder', {
|
|
306
388
|
category: 'GNSS',
|
package/ntrip/99-ntrip.js
CHANGED
|
@@ -19,6 +19,9 @@ module.exports = function (RED) {
|
|
|
19
19
|
const RtcmDecoderNode = require('./nodes/rtcm-decoder-node.js')(RED);
|
|
20
20
|
RED.nodes.registerType('RtcmDecoder', RtcmDecoderNode);
|
|
21
21
|
|
|
22
|
+
const RtcmEncoderNode = require('./nodes/rtcm-encoder-node.js')(RED);
|
|
23
|
+
RED.nodes.registerType('RtcmEncoder', RtcmEncoderNode);
|
|
24
|
+
|
|
22
25
|
const NmeaDecoderNode = require('./nodes/nmea-decoder-node.js')(RED);
|
|
23
26
|
RED.nodes.registerType('NmeaDecoder', NmeaDecoderNode);
|
|
24
27
|
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
module.exports = function (RED) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const { RtcmTransport, RtcmMessage } = require('@gnss/rtcm');
|
|
5
|
+
|
|
6
|
+
// Maximum RTCM 3 frame size — 3-byte header + 1023-byte payload + 3-byte CRC.
|
|
7
|
+
const MaxFrameBytes = 1029;
|
|
8
|
+
|
|
9
|
+
function RtcmEncoderNode(config) {
|
|
10
|
+
RED.nodes.createNode(this, config);
|
|
11
|
+
let node = this;
|
|
12
|
+
node.rtcmMessagesReceived = 0;
|
|
13
|
+
node.invalidMessagesReceived = 0;
|
|
14
|
+
|
|
15
|
+
function updateStatus(ok) {
|
|
16
|
+
node.status({
|
|
17
|
+
fill: ok ? 'green' : 'red',
|
|
18
|
+
shape: 'ring',
|
|
19
|
+
text: 'RTCM: ' + node.rtcmMessagesReceived + ' Invalid: ' + node.invalidMessagesReceived,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
this.on('input', function (msg) {
|
|
24
|
+
let payload = msg.payload;
|
|
25
|
+
|
|
26
|
+
// Accept either an RtcmMessage instance directly as msg.payload, or the
|
|
27
|
+
// shape emitted by the RtcmDecoder (msg.payload.message). Anything else
|
|
28
|
+
// routes to the error output.
|
|
29
|
+
let message;
|
|
30
|
+
if (payload instanceof RtcmMessage) {
|
|
31
|
+
message = payload;
|
|
32
|
+
} else if (payload != null && payload.message instanceof RtcmMessage) {
|
|
33
|
+
message = payload.message;
|
|
34
|
+
} else {
|
|
35
|
+
node.send([
|
|
36
|
+
null,
|
|
37
|
+
{
|
|
38
|
+
payload: {
|
|
39
|
+
error: 'Invalid input. Expected an RtcmMessage instance as msg.payload, or msg.payload.message.',
|
|
40
|
+
input: payload,
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
]);
|
|
44
|
+
node.invalidMessagesReceived++;
|
|
45
|
+
updateStatus(false);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
let buffer = Buffer.alloc(MaxFrameBytes);
|
|
51
|
+
let length = RtcmTransport.encode(message, buffer);
|
|
52
|
+
let encoded = buffer.slice(0, length);
|
|
53
|
+
let messageType = message.constructor.name.replace('RtcmMessage', '');
|
|
54
|
+
|
|
55
|
+
node.send([
|
|
56
|
+
{
|
|
57
|
+
payload: {
|
|
58
|
+
rtcmMessage: encoded,
|
|
59
|
+
rtcm: message.messageType,
|
|
60
|
+
messageType: messageType,
|
|
61
|
+
input: payload,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
null,
|
|
65
|
+
]);
|
|
66
|
+
node.rtcmMessagesReceived++;
|
|
67
|
+
updateStatus(true);
|
|
68
|
+
} catch (ex) {
|
|
69
|
+
node.send([
|
|
70
|
+
null,
|
|
71
|
+
{
|
|
72
|
+
payload: {
|
|
73
|
+
error: ex,
|
|
74
|
+
input: payload,
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
]);
|
|
78
|
+
node.invalidMessagesReceived++;
|
|
79
|
+
updateStatus(false);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
this.on('close', function (done) {
|
|
84
|
+
node.status({});
|
|
85
|
+
done();
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return RtcmEncoderNode;
|
|
90
|
+
};
|
package/package.json
CHANGED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const helper = require('node-red-node-test-helper');
|
|
4
|
+
const { expect } = require('chai');
|
|
5
|
+
const { RtcmTransport, RtcmMessage } = require('@gnss/rtcm');
|
|
6
|
+
const ntripModule = require('../ntrip/99-ntrip.js');
|
|
7
|
+
|
|
8
|
+
helper.init(require.resolve('node-red'));
|
|
9
|
+
|
|
10
|
+
// A real RTCM 3 message type 1005 (Stationary RTK Reference Station ARP).
|
|
11
|
+
const RTCM_1005 = Buffer.from('D300133ED7D30202980EDEEF34B4BD62AC0941986F33360B98', 'hex');
|
|
12
|
+
|
|
13
|
+
function flow() {
|
|
14
|
+
return [
|
|
15
|
+
{ id: 'n1', type: 'RtcmEncoder', wires: [['ok'], ['err']] },
|
|
16
|
+
{ id: 'ok', type: 'helper' },
|
|
17
|
+
{ id: 'err', type: 'helper' },
|
|
18
|
+
];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
describe('RtcmEncoder', function () {
|
|
22
|
+
before(() => helper.startServer());
|
|
23
|
+
after(() => helper.stopServer());
|
|
24
|
+
afterEach(() => helper.unload());
|
|
25
|
+
|
|
26
|
+
it('encodes an RtcmMessage instance round-tripped from the decoder', function () {
|
|
27
|
+
return new Promise((resolve, reject) => {
|
|
28
|
+
helper.load(ntripModule, flow(), () => {
|
|
29
|
+
const n1 = helper.getNode('n1');
|
|
30
|
+
const ok = helper.getNode('ok');
|
|
31
|
+
const [instance] = RtcmTransport.decode(RTCM_1005);
|
|
32
|
+
ok.on('input', (msg) => {
|
|
33
|
+
try {
|
|
34
|
+
expect(msg.payload.rtcm).to.equal(1005);
|
|
35
|
+
expect(msg.payload.messageType).to.be.a('string');
|
|
36
|
+
expect(Buffer.isBuffer(msg.payload.rtcmMessage)).to.equal(true);
|
|
37
|
+
expect(msg.payload.rtcmMessage).to.deep.equal(RTCM_1005);
|
|
38
|
+
resolve();
|
|
39
|
+
} catch (e) {
|
|
40
|
+
reject(e);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
n1.receive({ payload: instance });
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('accepts the decoder output shape (msg.payload.message)', function () {
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
helper.load(ntripModule, flow(), () => {
|
|
51
|
+
const n1 = helper.getNode('n1');
|
|
52
|
+
const ok = helper.getNode('ok');
|
|
53
|
+
const [instance, length] = RtcmTransport.decode(RTCM_1005);
|
|
54
|
+
ok.on('input', (msg) => {
|
|
55
|
+
try {
|
|
56
|
+
expect(msg.payload.rtcm).to.equal(1005);
|
|
57
|
+
expect(Buffer.isBuffer(msg.payload.rtcmMessage)).to.equal(true);
|
|
58
|
+
expect(msg.payload.rtcmMessage.length).to.equal(length);
|
|
59
|
+
resolve();
|
|
60
|
+
} catch (e) {
|
|
61
|
+
reject(e);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
// Mimic the RtcmDecoder's success payload shape.
|
|
65
|
+
n1.receive({
|
|
66
|
+
payload: {
|
|
67
|
+
rtcm: instance.messageType,
|
|
68
|
+
messageType: 'StationArp',
|
|
69
|
+
message: instance,
|
|
70
|
+
input: RTCM_1005,
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('routes a non-RtcmMessage payload to the error output', function () {
|
|
78
|
+
return new Promise((resolve, reject) => {
|
|
79
|
+
helper.load(ntripModule, flow(), () => {
|
|
80
|
+
const n1 = helper.getNode('n1');
|
|
81
|
+
const ok = helper.getNode('ok');
|
|
82
|
+
const err = helper.getNode('err');
|
|
83
|
+
ok.on('input', () => reject(new Error('unexpected success output')));
|
|
84
|
+
err.on('input', (msg) => {
|
|
85
|
+
try {
|
|
86
|
+
expect(msg.payload.error).to.be.a('string');
|
|
87
|
+
expect(msg.payload.error.toLowerCase()).to.include('invalid');
|
|
88
|
+
resolve();
|
|
89
|
+
} catch (e) {
|
|
90
|
+
reject(e);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
n1.receive({ payload: { foo: 'bar' } });
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('routes empty payload to the error output', function () {
|
|
99
|
+
return new Promise((resolve, reject) => {
|
|
100
|
+
helper.load(ntripModule, flow(), () => {
|
|
101
|
+
const n1 = helper.getNode('n1');
|
|
102
|
+
const err = helper.getNode('err');
|
|
103
|
+
err.on('input', (msg) => {
|
|
104
|
+
try {
|
|
105
|
+
expect(msg.payload.error).to.exist;
|
|
106
|
+
resolve();
|
|
107
|
+
} catch (e) {
|
|
108
|
+
reject(e);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
n1.receive({ payload: null });
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('does not call node.error on decode-shape failure (regression: log flood)', function () {
|
|
117
|
+
return new Promise((resolve, reject) => {
|
|
118
|
+
helper.load(ntripModule, flow(), () => {
|
|
119
|
+
const n1 = helper.getNode('n1');
|
|
120
|
+
let errorCalled = false;
|
|
121
|
+
const originalError = n1.error.bind(n1);
|
|
122
|
+
n1.error = function (...args) {
|
|
123
|
+
errorCalled = true;
|
|
124
|
+
return originalError(...args);
|
|
125
|
+
};
|
|
126
|
+
n1.receive({ payload: 'not-an-rtcm-message' });
|
|
127
|
+
setTimeout(() => {
|
|
128
|
+
try {
|
|
129
|
+
expect(errorCalled).to.equal(false);
|
|
130
|
+
resolve();
|
|
131
|
+
} catch (e) {
|
|
132
|
+
reject(e);
|
|
133
|
+
}
|
|
134
|
+
}, 50);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Sanity check: RtcmMessage is exported and the test fixture decodes to an instance.
|
|
140
|
+
it('test fixture sanity: decoded 1005 frame is an RtcmMessage instance', function () {
|
|
141
|
+
const [instance] = RtcmTransport.decode(RTCM_1005);
|
|
142
|
+
expect(instance).to.be.instanceOf(RtcmMessage);
|
|
143
|
+
});
|
|
144
|
+
});
|