Skip to content

Commit 9204938

Browse files
authored
Merge pull request #38 from boschrexroth/bugfix/subscription_port
Bugfix/subscription port
2 parents 9b6469d + 3ca14be commit 9204938

File tree

9 files changed

+109
-18
lines changed

9 files changed

+109
-18
lines changed

.vscode/launch.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"type": "node",
1010
"request": "launch",
1111
"program": "C:/Apps/node-red-1.2.6/node-red/red.js",
12+
"runtimeArgs": ["--preserve-symlinks"],
1213
"env": {
1314
"DEBUG": "ctrlxcore,ctrlxcore:*",
1415
"DEBUG_COLORS": "true"

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,21 +79,23 @@ Any use of the source code and related documents of this repository in applicati
7979
Support custom port after hostname. E.g. 'localhost:8443'.
8080
* 2020-10-01: 1.8.1 - fix: automatic reconnect when device was not available on start of flow.
8181
* 2021-02-22: 1.8.2 - Switched to ctrlX Data Layer API version v2 which is only available with AutomationCore 1.8.0 or newer.
82-
Introduced new setting to request node, which allows to set payload format to return only `value` or `value` and `type`.
82+
Introduced new setting to request node, which allows to set payload format to return only 'value' or 'value' and 'type'.
8383
* 2021-03-10: 1.8.3 - Internal improvements for more compliant URI encoding of http requests.
8484
* 2021-05-07: 1.8.4 - fix: allow to make a write without arguments (msg.payload = null). E.g. for 'diagnosis/confirm/error'.
85-
* 2021-05-25: 1.8.5 - fix: make `BROWSE`requests to support the payload property `value only`.
85+
* 2021-05-25: 1.8.5 - fix: make 'BROWSE' requests to support the payload property 'value only'.
8686
* 2021-05-28: 1.8.6 - feat: make path tree view selection in property window to automatically expand to current path.
87-
fix: make subscribe node to emit an initial `msg` after deploy, even if value does not change.
87+
fix: make subscribe node to emit an initial 'msg' after deploy, even if value does not change.
8888
* 2021-06-29: 1.8.7 - fix: writing strings with non-ASCII symbols (e.g. 'ü') resulted in DL_TYPE_MISMATCH.
8989
* 2021-07-04: 1.8.8 - fix: give each of the subscribe nodes his own counter to show in the status text.
9090
fix: allow to make a create without arguments (msg.payload = null). E.g. for '/motion/axs/<axs_name>/cmd/reset'.
91-
* 2021-09-20: 1.8.9 - fix: read with argument failed with error DL_TYPE_MISMATCH.
91+
* 2021-09-20: 1.8.9 - fix: read with argument failed with error 'DL_TYPE_MISMATCH'.
9292
* 2021-10-19: 1.8.10 - fix: support 64bit integer as BigInt to prevent rounding errors on big integer values.
9393
* 2021-10-22: 1.8.11 - fix: prevent "Failed login attempts" after flow gets redeployed with correct credentials (Bug392030).
9494
* 2021-10-22: 1.8.12 - fix: make subscription to properly report error and reconnect when authorization token expires (Bug405282).
9595
* 2022-01-27: 1.8.13 - refactor: update dependency versions. No functional change.
9696
* 2022-03-02: 1.8.14 - fix: improve diagnostics for misconfigured subscriptions. E.g. when a single node of a subscription is missing (Bug449366).
97+
* 2022-03-14: 1.8.15 - fix: make subscribe node useable on other ports than 443 (Bug457112).
98+
fix: remove an uncaught exception which was introduced with version 1.8.14 (Bug454078).
9799

98100
## About
99101

lib/CtrlxCore.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,7 @@ class CtrlxCore {
807807
}
808808

809809
// The subscription is encapsulated in a separate object.
810-
let sub = new CtrlxDatalayerSubscription(this._hostname, this._servername, this._tokenType + ' ' + this._token, paths, publishIntervalMs);
810+
let sub = new CtrlxDatalayerSubscription(this._hostname, this._port, this._servername, this._tokenType + ' ' + this._token, paths, publishIntervalMs);
811811

812812
sub.open((err, subscription) => {
813813
if (err) {

lib/CtrlxDatalayerSubscription.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const debugUpdate = require('debug')('ctrlxcore:datalayer:subscription:update');
4141
* This class works as a facade around the EventSource interface (https://www.w3.org/TR/eventsource/).
4242
*
4343
* @example <caption>Example how to subscribe and print the updates.</caption>
44-
* let subscription = new CtrlxDatalayerSubscription('192.168.1.1', 'Bearer ABCD1234', ['framework/metrics/system/cpu-utilisation-percent']);
44+
* let subscription = new CtrlxDatalayerSubscription('192.168.1.1', 443, '', 'Bearer ABCD1234', ['framework/metrics/system/cpu-utilisation-percent']);
4545
*
4646
* subscription.open((err, sub) => {
4747
* if (err) throw err;
@@ -58,19 +58,21 @@ class CtrlxDatalayerSubscription extends EventEmitter {
5858
/**
5959
* Creates an instance of CtrlxDatalayerSubscription.
6060
*
61-
* @param {string} hostname - The hostname of the device. Can also be a ipv4-, ipv6-address or 'localhost'.
61+
* @param {string} hostname - The hostname of the device. Can also be an ipv4-, ipv6-address or 'localhost'.
62+
* @param {number} port - The port number of the device, where the web server is listening. Usually 443.
6263
* @param {string} servername - The TLS servername of the device as defined by RFC 6066. Empty string in case of an ip-address.
6364
* @param {string} authorization - The authorization token string for the http header.
6465
* @param {string[]} paths - An array of node addresses to subscribe to.
6566
* @param {number|undefined} publishIntervalMs - The interval in milliseconds that is requested as update interval from the server.
6667
* If omitted, then the server will chose a default value (usually 1s).
6768
* @memberof CtrlxCore
6869
*/
69-
constructor(hostname, servername, authorization, paths, publishIntervalMs = undefined) {
70+
constructor(hostname, port = 443, servername = '', authorization, paths, publishIntervalMs = undefined) {
7071
debug(`constructor(${hostname}, ...)`);
7172
super();
7273

7374
this._hostname = hostname;
75+
this._port = port;
7476
this._servername = servername;
7577
this._authorization = authorization;
7678
this._nodes = paths;
@@ -109,7 +111,7 @@ class CtrlxDatalayerSubscription extends EventEmitter {
109111
}
110112

111113
// Arguments are given as query parameter.
112-
let url = `https://${this._hostname}:443/automation/api/v2/events?nodes=${this._nodes}`;
114+
let url = `https://${this._hostname}:${this._port}/automation/api/v2/events?nodes=${this._nodes}`;
113115
if (typeof this._publishIntervalMs !== 'undefined') {
114116
url += `&publishIntervalMs=${this._publishIntervalMs}`;
115117
}
@@ -197,7 +199,7 @@ class CtrlxDatalayerSubscription extends EventEmitter {
197199
this._es.onerror = (e) => {
198200
debug(`onerror(${e.type})`);
199201

200-
if (e.data !== 'undefined') {
202+
if (typeof e.data !== 'undefined') {
201203

202204
// The error is of type 'MessageEvent'. This means, that not the stream has an error, but
203205
// an 'error' message is send over the stream (in contrast to an 'update' message if everything is fine).

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "node-red-contrib-ctrlx-automation",
3-
"version": "1.8.14",
3+
"version": "1.8.15",
44
"description": "Node-RED nodes for ctrlX AUTOMATION",
55
"repository": {
66
"type": "git",

test/CtrlxCore.events.test.js

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ describe('CtrlxCoreDataLayerEvents', function() {
5353
let testServer;
5454
before(function(done) {
5555
testServer = new CtrlxMockup();
56-
testServer.startServer('localhost', 443, () => {
56+
testServer.startServer('localhost', CtrlxCore._parseHost(getHostname()).port, () => {
5757
done();
5858
});
5959
});
@@ -256,3 +256,88 @@ describe('CtrlxCoreDataLayerEvents', function() {
256256
});
257257

258258
});
259+
260+
261+
262+
/*
263+
* This test group contains test cases for the subcription mechanism of the Data Layer
264+
* which is mapped to server sent events, but run on a different port.
265+
*/
266+
describe('CtrlxCoreDataLayerEvents - With different port', function() {
267+
268+
function getHostname() {
269+
return process.env.TEST_HOSTNAME || '127.0.0.1:8443';
270+
}
271+
function getUsername() {
272+
return process.env.TEST_USERNAME || 'boschrexroth';
273+
}
274+
function getPassword() {
275+
return process.env.TEST_PASSWORD || 'boschrexroth';
276+
}
277+
278+
let testServer;
279+
before(function(done) {
280+
testServer = new CtrlxMockup();
281+
testServer.startServer('localhost', 8443, () => {
282+
done();
283+
});
284+
});
285+
286+
after(function(done) {
287+
this.timeout(10000);
288+
testServer.stopServer(() => {
289+
done();
290+
});
291+
});
292+
293+
294+
describe('CtrlxCoreSubscription: Subscription Interface', function() {
295+
296+
297+
it('should subscribe to a single node', async function() {
298+
this.timeout(5000);
299+
let ctrlx = new CtrlxCore(getHostname(), getUsername(), getPassword());
300+
301+
try {
302+
303+
await ctrlx.logIn();
304+
305+
// Create the subscription
306+
let subscription = await ctrlx.datalayerSubscribe(['framework/metrics/system/cpu-utilisation-percent']);
307+
expect(subscription).to.exist;
308+
309+
// Check and count the updates
310+
let numReceived = 0;
311+
subscription.on('update', (data) => {
312+
313+
expect(data.node).to.be.a('string').eql('framework/metrics/system/cpu-utilisation-percent');
314+
expect(data.timestamp).to.be.a('number');
315+
expect(data.type).to.be.a('string').eql('double');
316+
expect(data.value).to.be.a('number').within(0, 100);
317+
318+
const timestamp = CtrlxDatalayerSubscription.convertTimestamp2Date(data.timestamp);
319+
const deltaTime = Math.abs(timestamp.valueOf() - Date.now());
320+
expect(deltaTime).to.be.below(500);
321+
322+
//console.log(`update: node=${data.node} value=${data.value} timestampUTC=${timestamp.toISOString()}`);
323+
numReceived++;
324+
});
325+
326+
// Give some time to receive the updates
327+
await sleep(3000);
328+
subscription.close();
329+
330+
// Check for the expected number of updates
331+
expect(numReceived).to.be.greaterThan(1);
332+
333+
} catch(err) {
334+
console.error('Housten we are in trouble: ' + err);
335+
throw err;
336+
} finally {
337+
await ctrlx.logOut();
338+
}
339+
});
340+
341+
});
342+
343+
});

test/CtrlxCore.nodes.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ describe('CtrlxCoreDataLayerNodes', function() {
5252
let testServer;
5353
before(function(done) {
5454
testServer = new CtrlxMockup();
55-
testServer.startServer('localhost', 443, () => {
55+
testServer.startServer('localhost', CtrlxCore._parseHost(getHostname()).port, () => {
5656
done();
5757
});
5858
});

test/ctrlx-config.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const ctrlxDatalayerRequestNode = require("../ctrlx-datalayer-request.js");
4040
// The the server mockup to test against
4141
const CtrlxMockup = require('./helper/CtrlxMockupV2')
4242

43-
43+
const CtrlxCore = require('../lib/CtrlxCore')
4444
const expect = require('chai').expect;
4545

4646

@@ -65,7 +65,7 @@ describe('ctrlx-config', function() {
6565
let testServer;
6666
before(function(done) {
6767
testServer = new CtrlxMockup();
68-
testServer.startServer('localhost', 443, () => {
68+
testServer.startServer('localhost', CtrlxCore._parseHost(getHostname()).port, () => {
6969
done();
7070
});
7171
});

test/ctrlx-datalayer-subscribe.test.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,9 @@ const ctrlxDatalayerSubscribeNode = require("../ctrlx-datalayer-subscribe.js");
4242
const CtrlxMockup = require('./helper/CtrlxMockupV2')
4343
const CtrlxDatalayerSubscription = require('../lib/CtrlxDatalayerSubscription');
4444

45+
// Additional helper
4546
const expect = require('chai').expect;
46-
47+
const CtrlxCore = require('../lib/CtrlxCore');
4748

4849

4950

@@ -66,7 +67,7 @@ describe('ctrlx-datalayer-subscribe', function() {
6667
let testServer;
6768
before(function(done) {
6869
testServer = new CtrlxMockup();
69-
testServer.startServer('localhost', 443, () => {
70+
testServer.startServer('localhost', CtrlxCore._parseHost(getHostname()).port, () => {
7071
done();
7172
});
7273
});
@@ -198,7 +199,7 @@ describe('ctrlx-datalayer-subscribe', function() {
198199
expect(numReceived).to.be.greaterThan(8);
199200
done();
200201
s1.subscription.close();
201-
}, 1000);
202+
}, 1200);
202203
});
203204
});
204205

0 commit comments

Comments
 (0)