node-red-contrib-mobius-flow-base 2.5.86-beta.1 → 2.5.86-beta.101
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/dist/nodes/icons/mobius-inject.png +0 -0
- package/dist/nodes/icons/mobius.png +0 -0
- package/dist/nodes/mobius-clear-resource.html +178 -0
- package/dist/nodes/mobius-clear-resource.js +109 -0
- package/dist/nodes/mobius-connection.html +68 -0
- package/dist/nodes/mobius-connection.js +675 -0
- package/dist/nodes/mobius-discover-object-list.html +272 -0
- package/dist/nodes/mobius-discover-object-list.js +263 -0
- package/dist/nodes/mobius-discover.html +139 -0
- package/dist/nodes/mobius-discover.js +100 -0
- package/dist/nodes/mobius-filter-by-rid-value.html +206 -0
- package/dist/nodes/mobius-filter-by-rid-value.js +123 -0
- package/dist/nodes/mobius-flow-inject.html +162 -0
- package/dist/nodes/mobius-flow-inject.js +124 -0
- package/dist/nodes/mobius-get-multi-object.html +176 -0
- package/dist/nodes/mobius-get-multi-object.js +127 -0
- package/dist/nodes/mobius-get-multi-resource.html +195 -0
- package/dist/nodes/mobius-get-multi-resource.js +140 -0
- package/dist/nodes/mobius-get-object.html +168 -0
- package/dist/nodes/mobius-get-object.js +102 -0
- package/dist/nodes/mobius-get-resource.html +169 -0
- package/dist/nodes/mobius-get-resource.js +101 -0
- package/dist/nodes/mobius-object-cov.html +171 -0
- package/dist/nodes/mobius-object-cov.js +83 -0
- package/dist/nodes/mobius-resource-cov.html +155 -0
- package/dist/nodes/mobius-resource-cov.js +77 -0
- package/dist/nodes/mobius-send-bcmd.html +93 -0
- package/dist/nodes/mobius-send-bcmd.js +61 -0
- package/dist/nodes/mobius-send-dcmd.html +130 -0
- package/dist/nodes/mobius-send-dcmd.js +80 -0
- package/dist/nodes/mobius-set-multi-resource.html +150 -0
- package/dist/nodes/mobius-set-multi-resource.js +104 -0
- package/dist/nodes/mobius-set-resource.html +180 -0
- package/dist/nodes/mobius-set-resource.js +145 -0
- package/dist/nodes/mobius-sub-bcmd.html +94 -0
- package/dist/nodes/mobius-sub-bcmd.js +64 -0
- package/dist/nodes/node-red-ui-discover-devices.js +103 -0
- package/dist/nodes/validateURI.js +51 -0
- package/package.json +1 -1
|
@@ -0,0 +1,675 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Copyright (C) 2016, IAConnects Technology Limited
|
|
3
|
+
All Rights Reserved
|
|
4
|
+
|
|
5
|
+
ALL INFORMATION CONTAINED HEREIN IS, AND REMAINS
|
|
6
|
+
THE PROPERTY OF IACONNECTS TECHNOLOGY LIMITED AND ITS SUPPLIERS,
|
|
7
|
+
IF ANY. THE INTELLECTUAL AND TECHNICAL CONCEPTS CONTAINED
|
|
8
|
+
HEREIN ARE PROPRIETARY TO IACONNECTS TECHNOLOGY LIMITED
|
|
9
|
+
AND ITS SUPPLIERS AND ARE PROTECTED BY TRADE SECRET OR COPYRIGHT LAW.
|
|
10
|
+
DISSEMINATION OF THIS INFORMATION OR REPRODUCTION OF THIS MATERIAL
|
|
11
|
+
IS STRICTLY FORBIDDEN UNLESS PRIOR WRITTEN PERMISSION IS OBTAINED
|
|
12
|
+
FROM IACONNECTS TECHNOLOGY LIMITED.
|
|
13
|
+
|
|
14
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
15
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
16
|
+
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
17
|
+
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
|
|
18
|
+
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
19
|
+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
20
|
+
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
21
|
+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
22
|
+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
23
|
+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
24
|
+
POSSIBILITY OF SUCH DAMAGE.
|
|
25
|
+
**/
|
|
26
|
+
|
|
27
|
+
'use strict';
|
|
28
|
+
|
|
29
|
+
var _ = require('lodash');
|
|
30
|
+
var tcpAPI = require('@ia/mobius-tcpip-service-api');
|
|
31
|
+
var uiDeviceDiscovery = require('./node-red-ui-discover-devices');
|
|
32
|
+
|
|
33
|
+
module.exports = function (RED) {
|
|
34
|
+
/**
|
|
35
|
+
* Helper function to match topic subscriptions
|
|
36
|
+
* @param {string} topic - The subscribed topic
|
|
37
|
+
* @param {string} messageTopic - The topic in an actual message
|
|
38
|
+
* @return {boolean} - True if the topics match, else false
|
|
39
|
+
*/
|
|
40
|
+
function matchTopic(topic, messageTopic) {
|
|
41
|
+
if (topic === '#') {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
// eslint-disable-next-line no-useless-escape
|
|
45
|
+
var regex = new RegExp(
|
|
46
|
+
'^' +
|
|
47
|
+
topic
|
|
48
|
+
.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g, '\\$1')
|
|
49
|
+
// eslint-disable-next-line no-useless-escape
|
|
50
|
+
.replace(/\+/g, '[^/]+')
|
|
51
|
+
.replace(/\/#$/, '(/.*)?') +
|
|
52
|
+
'$'
|
|
53
|
+
);
|
|
54
|
+
return regex.test(messageTopic);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Constructor for a Mobius service configuration node
|
|
59
|
+
* @param {Object} n - The node being created
|
|
60
|
+
*/
|
|
61
|
+
function MobiusConnectionNode(n) {
|
|
62
|
+
RED.nodes.createNode(this, n);
|
|
63
|
+
this.host = n.host;
|
|
64
|
+
this.port = n.port;
|
|
65
|
+
this.psk = n.psk;
|
|
66
|
+
this.service = new tcpAPI.TCPIPServiceAPI(n.host, n.port, n.psk);
|
|
67
|
+
this.service.srvcAPI.removeAllListeners('cov');
|
|
68
|
+
this.service.srvcAPI.removeAllListeners('obcov');
|
|
69
|
+
this.service.srvcAPI.removeAllListeners('bcmd');
|
|
70
|
+
this.service.srvcAPI.on('cov', (response) => {
|
|
71
|
+
this.handleCOVEvents(response);
|
|
72
|
+
});
|
|
73
|
+
this.service.srvcAPI.on('obcov', (response) => {
|
|
74
|
+
this.handleObjectCOVEvents(response);
|
|
75
|
+
});
|
|
76
|
+
this.service.srvcAPI.on('bcmd', (response) => {
|
|
77
|
+
this.handleBCMDEvents(response);
|
|
78
|
+
});
|
|
79
|
+
var node = this;
|
|
80
|
+
node.serviceList = [];
|
|
81
|
+
node.hasStarted = false;
|
|
82
|
+
node.users = {};
|
|
83
|
+
node.resourceSubscriptions = new Map();
|
|
84
|
+
node.objectSubscriptions = new Map();
|
|
85
|
+
node.bcmdSubscriptions = new Map();
|
|
86
|
+
node.connected = false;
|
|
87
|
+
node.unsubscribeTimeout = 0;
|
|
88
|
+
|
|
89
|
+
// Connected to the mobius TCPIP spoke
|
|
90
|
+
// Update the status indicators
|
|
91
|
+
node.service.on('connected', () => {
|
|
92
|
+
this.log(`Connected to ${n.host} : ${n.port}`);
|
|
93
|
+
node.connected = true;
|
|
94
|
+
_.forEach(node.users, (user, id) => {
|
|
95
|
+
if (node.users.hasOwnProperty(id)) {
|
|
96
|
+
node.users[id].status({
|
|
97
|
+
fill: 'green',
|
|
98
|
+
shape: 'dot',
|
|
99
|
+
text: 'Connected',
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
// Subscribe to all COVs
|
|
104
|
+
this.resourceSubscriptions.forEach((subs, key) => {
|
|
105
|
+
node.service.srvcAPI.subscribeToCOV(key);
|
|
106
|
+
});
|
|
107
|
+
// Subscribe to all object COVs
|
|
108
|
+
node.objectSubscriptions.forEach((subs, key) => {
|
|
109
|
+
node.service.srvcAPI.subscribeToObjectCOV(key);
|
|
110
|
+
});
|
|
111
|
+
// Subscribe to all BCMDs
|
|
112
|
+
node.bcmdSubscriptions.forEach((subs, key) => {
|
|
113
|
+
node.service.srvcAPI.subscribeToBCMD(key);
|
|
114
|
+
});
|
|
115
|
+
// Discover all service IDs
|
|
116
|
+
node.service.srvcAPI.discover(node.service.srvcAPI.status.hubId, (err, response) => {
|
|
117
|
+
if (err) {
|
|
118
|
+
node.error('Mobius error discovering service list' + JSON.stringify(err));
|
|
119
|
+
} else {
|
|
120
|
+
node.serviceList = response.value;
|
|
121
|
+
node.hasStarted = true;
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Disconnected from the mobius TCPIP spoke
|
|
127
|
+
// Update the status indicators
|
|
128
|
+
node.service.on('disconnected', () => {
|
|
129
|
+
this.log(`Disconnected from ${n.host} : ${n.port}`);
|
|
130
|
+
node.connected = false;
|
|
131
|
+
for (var id in node.users) {
|
|
132
|
+
if (node.users.hasOwnProperty(id)) {
|
|
133
|
+
node.users[id].status({
|
|
134
|
+
fill: 'red',
|
|
135
|
+
shape: 'ring',
|
|
136
|
+
text: 'Disconnected',
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Handle all resource COVs
|
|
144
|
+
* @param {Object} response - The resource that has changed
|
|
145
|
+
*/
|
|
146
|
+
node.handleCOVEvents = function (response) {
|
|
147
|
+
let covsFired = [];
|
|
148
|
+
node.resourceSubscriptions.forEach((subs, key) => {
|
|
149
|
+
if (matchTopic(key, response.uri)) {
|
|
150
|
+
_.forEach(subs, (sub) => {
|
|
151
|
+
if (!_.includes(covsFired, sub.node)) {
|
|
152
|
+
covsFired.push(sub.node);
|
|
153
|
+
sub.cb(response);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Handle all object COVs
|
|
162
|
+
* @param {Object} response - The object that has changed
|
|
163
|
+
*/
|
|
164
|
+
node.handleObjectCOVEvents = function (response) {
|
|
165
|
+
let covsFired = [];
|
|
166
|
+
node.objectSubscriptions.forEach((subs, key) => {
|
|
167
|
+
if (matchTopic(key, response.uri)) {
|
|
168
|
+
_.forEach(subs, (sub) => {
|
|
169
|
+
if (!_.includes(covsFired, sub.node)) {
|
|
170
|
+
covsFired.push(sub.node);
|
|
171
|
+
sub.cb(response);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Handle all BCMDs
|
|
180
|
+
* @param {Object} response - The BCMD
|
|
181
|
+
*/
|
|
182
|
+
node.handleBCMDEvents = function (response) {
|
|
183
|
+
let bcmdsFired = [];
|
|
184
|
+
node.bcmdSubscriptions.forEach((subs, key) => {
|
|
185
|
+
if (matchTopic(key, response.uri)) {
|
|
186
|
+
_.forEach(subs, (sub) => {
|
|
187
|
+
if (!_.includes(bcmdsFired, sub.node)) {
|
|
188
|
+
bcmdsFired.push(sub.node);
|
|
189
|
+
sub.cb(response);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Select status text and colour of node status based on last active time
|
|
198
|
+
* @param {number} lastActiveTime - The node's last active time
|
|
199
|
+
* @returns Object containing status text and status colour
|
|
200
|
+
*/
|
|
201
|
+
node.buildLastActiveTimeStatus = function (lastActiveTime) {
|
|
202
|
+
let response = {
|
|
203
|
+
text: 'Unknown',
|
|
204
|
+
colour: 'green',
|
|
205
|
+
};
|
|
206
|
+
const timeSinceLastActive = Date.now() - lastActiveTime;
|
|
207
|
+
if (timeSinceLastActive < 15 * 60000) {
|
|
208
|
+
response.text = 'Active less than 15 minutes ago';
|
|
209
|
+
}
|
|
210
|
+
if (timeSinceLastActive >= 15 * 60000 && timeSinceLastActive < 3 * 60 * 60000) {
|
|
211
|
+
response.text = 'Active less than 3 hours ago';
|
|
212
|
+
}
|
|
213
|
+
if (timeSinceLastActive >= 3 * 60 * 60000 && timeSinceLastActive < 12 * 60 * 60000) {
|
|
214
|
+
response.text = 'Active less than 12 hours ago';
|
|
215
|
+
}
|
|
216
|
+
if (timeSinceLastActive >= 12 * 60 * 60000 && timeSinceLastActive < 24 * 60 * 60000) {
|
|
217
|
+
response.text = 'Active less than 24 hours ago';
|
|
218
|
+
}
|
|
219
|
+
if (timeSinceLastActive > 24 * 60 * 60000 && lastActiveTime > 0) {
|
|
220
|
+
response.colour = 'grey';
|
|
221
|
+
response.text = 'Active more than 24 hours ago';
|
|
222
|
+
}
|
|
223
|
+
if (lastActiveTime === 0) {
|
|
224
|
+
response.colour = 'grey';
|
|
225
|
+
response.text = 'Never Active';
|
|
226
|
+
}
|
|
227
|
+
return {
|
|
228
|
+
fill: response.colour,
|
|
229
|
+
shape: 'dot',
|
|
230
|
+
text: response.text,
|
|
231
|
+
};
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Update a given node's node status based on last active time
|
|
236
|
+
* @param {Object} mobiusNode - The node whos status is to be updated
|
|
237
|
+
*/
|
|
238
|
+
node.updateNodeStatus = function (mobiusNode) {
|
|
239
|
+
node.users[mobiusNode.id] = mobiusNode;
|
|
240
|
+
let newStatus = {
|
|
241
|
+
fill: 'green',
|
|
242
|
+
shape: 'dot',
|
|
243
|
+
text: 'Connected',
|
|
244
|
+
};
|
|
245
|
+
switch (node.users[mobiusNode.id].statusType) {
|
|
246
|
+
case 'timeSinceLastActive':
|
|
247
|
+
newStatus = node.buildLastActiveTimeStatus(node.users[mobiusNode.id].lastActiveTime);
|
|
248
|
+
case 'lastUri':
|
|
249
|
+
const uri = node.users[mobiusNode.id].latestUri;
|
|
250
|
+
if (uri !== '') {
|
|
251
|
+
newStatus = {
|
|
252
|
+
fill: 'green',
|
|
253
|
+
shape: 'dot',
|
|
254
|
+
text: uri,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
node.users[mobiusNode.id].status(newStatus);
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Update a given node's node latest URI record
|
|
263
|
+
* @param {Object} mobiusNode - The node whos last URI record is to be updated
|
|
264
|
+
*/
|
|
265
|
+
node.updateLatestUri = function (mobiusNode, uri) {
|
|
266
|
+
node.users[mobiusNode.id] = mobiusNode;
|
|
267
|
+
node.users[mobiusNode.id].latestUri = uri;
|
|
268
|
+
node.updateNodeStatus(mobiusNode);
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Update a given node's node last active time
|
|
273
|
+
* @param {Object} mobiusNode - The node whos last active time is to be updated
|
|
274
|
+
*/
|
|
275
|
+
node.updateLastActiveTime = function (mobiusNode) {
|
|
276
|
+
node.users[mobiusNode.id] = mobiusNode;
|
|
277
|
+
node.users[mobiusNode.id].lastActiveTime = Date.now();
|
|
278
|
+
node.updateNodeStatus(mobiusNode);
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Register a new Mobius node with this config node
|
|
283
|
+
* @param {Object} mobiusNode - The new node to register
|
|
284
|
+
*/
|
|
285
|
+
node.register = function (mobiusNode) {
|
|
286
|
+
node.users[mobiusNode.id] = mobiusNode;
|
|
287
|
+
if (node.connected) {
|
|
288
|
+
node.users[mobiusNode.id].status({
|
|
289
|
+
fill: 'green',
|
|
290
|
+
shape: 'dot',
|
|
291
|
+
text: 'Connected',
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
node.users[mobiusNode.id].lastActiveTime = 0;
|
|
295
|
+
node.users[mobiusNode.id].statusCheckLoop = setInterval(() => {
|
|
296
|
+
if (node.connected) {
|
|
297
|
+
node.updateNodeStatus(mobiusNode);
|
|
298
|
+
}
|
|
299
|
+
}, 60000);
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Deregister a previously registered Mobius node
|
|
304
|
+
* @param {[Object} mobiusNode - The node to deregister
|
|
305
|
+
* @param {Function} done - A callback to be run by the node after it has been deregistered
|
|
306
|
+
*/
|
|
307
|
+
node.deregister = function (mobiusNode, done) {
|
|
308
|
+
clearInterval(node.users[mobiusNode.id].statusCheckLoop);
|
|
309
|
+
delete node.users[mobiusNode.id];
|
|
310
|
+
if (node.service) {
|
|
311
|
+
try {
|
|
312
|
+
node.resourceSubscriptions.forEach((subs, key) => {
|
|
313
|
+
subs.forEach((sub, index) => {
|
|
314
|
+
if (mobiusNode.id === sub.node) {
|
|
315
|
+
subs.splice(index, 1);
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
if (subs.length === 0) {
|
|
319
|
+
node.service.srvcAPI.unsubscribeToCOV(key);
|
|
320
|
+
node.resourceSubscriptions.delete(key);
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
node.objectSubscriptions.forEach((subs, key) => {
|
|
324
|
+
subs.forEach((sub, index) => {
|
|
325
|
+
if (mobiusNode.id === sub.node) {
|
|
326
|
+
subs.splice(index, 1);
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
if (subs.length === 0) {
|
|
330
|
+
node.service.srvcAPI.unsubscribeToObjectCOV(key);
|
|
331
|
+
node.objectSubscriptions.delete(key);
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
node.bcmdSubscriptions.forEach((subs, key) => {
|
|
335
|
+
subs.forEach((sub, index) => {
|
|
336
|
+
if (mobiusNode.id === sub.node) {
|
|
337
|
+
subs.splice(index, 1);
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
if (subs.length === 0) {
|
|
341
|
+
node.service.srvcAPI.unsubscribeToBCMD(key);
|
|
342
|
+
node.bcmdSubscriptions.delete(key);
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
} catch (err) {
|
|
346
|
+
console.log(`Failed to unsubscribe from event: ${err.message}`);
|
|
347
|
+
}
|
|
348
|
+
return done();
|
|
349
|
+
}
|
|
350
|
+
done();
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Register the close connection handler
|
|
355
|
+
*/
|
|
356
|
+
node.on('close', (done) => {
|
|
357
|
+
if (node.connected) {
|
|
358
|
+
// Wait for all nodes to unsubscribe before terminating the connection
|
|
359
|
+
node.unsubscribeTimeout = 0;
|
|
360
|
+
var waitForCleanup = setInterval(() => {
|
|
361
|
+
if (
|
|
362
|
+
(node.resourceSubscriptions.size === 0 &&
|
|
363
|
+
node.objectSubscriptions.size === 0 &&
|
|
364
|
+
node.bcmdSubscriptions.size === 0) ||
|
|
365
|
+
node.unsubscribeTimeout > 50
|
|
366
|
+
) {
|
|
367
|
+
clearInterval(waitForCleanup);
|
|
368
|
+
node.service.end();
|
|
369
|
+
node.service.once('disconnected', () => {
|
|
370
|
+
node.connected = false;
|
|
371
|
+
done();
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
node.unsubscribeTimeout++;
|
|
375
|
+
}, 100);
|
|
376
|
+
} else {
|
|
377
|
+
node.service.end();
|
|
378
|
+
done();
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Discover the services on a hub, the object profiles used by a service or the instances of
|
|
384
|
+
* objects of a profile type.
|
|
385
|
+
* @param {string} uri - The identifier of the hub, service or profile
|
|
386
|
+
* @param {Function} callback - function(err, [object]) {}
|
|
387
|
+
* @return {string} - A random unique request response ID. This is also returned in
|
|
388
|
+
* the response message event
|
|
389
|
+
*/
|
|
390
|
+
node.discover = function (uri, callback) {
|
|
391
|
+
node.service.srvcAPI.discover(uri, callback);
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Write a value to a resource
|
|
396
|
+
* @param {string} uri - The full URI of the resource
|
|
397
|
+
* @param {Object} value - The value to write
|
|
398
|
+
* @param {number} priority - The priority to write to
|
|
399
|
+
* @param {Function} callback - Callback when complete
|
|
400
|
+
*/
|
|
401
|
+
node.writeResourceValue = function (uri, value, priority, callback) {
|
|
402
|
+
node.service.srvcAPI.writeResourceValue(uri, value, priority, callback);
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Write a value to multiple resources of a single object in a microservice
|
|
407
|
+
* Values can be anything as long as its type matches the resource's value type
|
|
408
|
+
* @param {string} uri - The object identifier
|
|
409
|
+
* @param {Object} updates - An array containing all of the resources to be updated
|
|
410
|
+
* @param {Function} callback - function(err, [object]) {}
|
|
411
|
+
* @return {string} - A random unique request response ID. This is also returned in
|
|
412
|
+
* the response message event
|
|
413
|
+
*/
|
|
414
|
+
node.multiWriteResourceValue = function (uri, updates, callback) {
|
|
415
|
+
node.service.srvcAPI.multiWriteResourceValue(uri, updates, callback);
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Clear a resource's priority
|
|
420
|
+
* @param {string} uri - The full URI of the resource
|
|
421
|
+
* @param {number} priority - The priority to clear
|
|
422
|
+
* @param {Function} callback - Callback when complete
|
|
423
|
+
*/
|
|
424
|
+
node.clearResourcePriority = function (uri, priority, callback) {
|
|
425
|
+
node.service.srvcAPI.clearResourcePriority(uri, priority, callback);
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Read a resource's value
|
|
430
|
+
* @param {string} uri - The full URI of the resource
|
|
431
|
+
* @param {Function} callback - Callback when complete
|
|
432
|
+
*/
|
|
433
|
+
node.readResource = function (uri, callback) {
|
|
434
|
+
node.service.srvcAPI.readResource(uri, callback);
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Read a resource's value
|
|
439
|
+
* @param {string} uri - The full URI of the object
|
|
440
|
+
* @param {Function} callback - Callback when complete
|
|
441
|
+
*/
|
|
442
|
+
node.readObject = function (uri, callback) {
|
|
443
|
+
node.service.srvcAPI.readObject(uri, callback);
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Filter objects by resource value
|
|
448
|
+
* @param {string} uri - The resource identifier
|
|
449
|
+
* @param {array} pids - The profile ids to search (as an array of four digit hex string)
|
|
450
|
+
* @param {string} rid - The id of the resource to test values against (as a two digit hex string)
|
|
451
|
+
* @param {number} limit - The maximum number of objects to return
|
|
452
|
+
* @param {Function} func - The function used to test the resource values
|
|
453
|
+
* @param {Function} callback - function(err, [object]) {}
|
|
454
|
+
*/
|
|
455
|
+
node.filterObjectsByRIDValue = function (uri, pids, rid, limit, func, callback) {
|
|
456
|
+
node.service.srvcAPI.filterObjectsByRIDValue(uri, pids, rid, limit, func, callback);
|
|
457
|
+
};
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Subscribe to a resource COV
|
|
461
|
+
* @param {string} uri - The full URI of the resource
|
|
462
|
+
* @param {Object} ref - The ID of the node that is registering for this COV
|
|
463
|
+
* @param {Function} callback - Callback when complete
|
|
464
|
+
*/
|
|
465
|
+
node.subscribeToCOV = function (uri, ref, callback) {
|
|
466
|
+
let sub = {
|
|
467
|
+
node: ref,
|
|
468
|
+
cb: callback,
|
|
469
|
+
};
|
|
470
|
+
if (!node.resourceSubscriptions.has(uri)) {
|
|
471
|
+
node.service.srvcAPI.subscribeToCOV(uri);
|
|
472
|
+
node.resourceSubscriptions.set(uri, [sub]);
|
|
473
|
+
} else {
|
|
474
|
+
// _.pullAllBy(node.resourceSubscriptions.get(uri), [{node: ref}], node);
|
|
475
|
+
node.resourceSubscriptions.get(uri).push(sub);
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Unsubscribe to a resource COV
|
|
481
|
+
* @param {string} uri - The full URI of the resource
|
|
482
|
+
* @param {Object} ref - The ID of the node that is registering for this COV
|
|
483
|
+
*/
|
|
484
|
+
node.unsubscribeToCOV = function (uri, ref) {
|
|
485
|
+
if (node.resourceSubscriptions.has(uri)) {
|
|
486
|
+
node.resourceSubscriptions.set(
|
|
487
|
+
uri,
|
|
488
|
+
node.resourceSubscriptions.get(uri).filter((sub) => sub.node !== ref)
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
if (node.resourceSubscriptions.get(uri).length === 0) {
|
|
492
|
+
node.service.srvcAPI.unsubscribeToCOV(uri);
|
|
493
|
+
node.resourceSubscriptions.delete(uri);
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* Subscribe to an object COV
|
|
499
|
+
* @param {string} uri - The full URI of the object
|
|
500
|
+
* @param {Object} ref - The ID of the node that is registering for this COV
|
|
501
|
+
* @param {Function} callback - Callback when complete
|
|
502
|
+
*/
|
|
503
|
+
node.subscribeToObjectCOV = function (uri, ref, callback) {
|
|
504
|
+
let sub = {
|
|
505
|
+
node: ref,
|
|
506
|
+
cb: callback,
|
|
507
|
+
};
|
|
508
|
+
if (!node.objectSubscriptions.has(uri)) {
|
|
509
|
+
node.service.srvcAPI.subscribeToObjectCOV(uri);
|
|
510
|
+
node.objectSubscriptions.set(uri, [sub]);
|
|
511
|
+
} else {
|
|
512
|
+
// _.pullAllBy(node.objectSubscriptions.get(uri), [{node: ref}], node);
|
|
513
|
+
node.objectSubscriptions.get(uri).push(sub);
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
* Unsubscribe to an object COV
|
|
519
|
+
* @param {string} uri - The full URI of the object
|
|
520
|
+
* @param {Object} ref - The ID of the node that is registering for this COV
|
|
521
|
+
*/
|
|
522
|
+
node.unsubscribeToObjectCOV = function (uri, ref) {
|
|
523
|
+
if (node.objectSubscriptions.has(uri)) {
|
|
524
|
+
node.objectSubscriptions.set(
|
|
525
|
+
uri,
|
|
526
|
+
node.objectSubscriptions.get(uri).filter((sub) => sub.node !== ref)
|
|
527
|
+
);
|
|
528
|
+
}
|
|
529
|
+
if (node.objectSubscriptions.get(uri).length === 0) {
|
|
530
|
+
node.service.srvcAPI.unsubscribeToObjectCOV(uri);
|
|
531
|
+
node.objectSubscriptions.delete(uri);
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Subscribe to a broadcast command
|
|
537
|
+
* @param {string} uri - The full URI of the broadcast command
|
|
538
|
+
* @param {Object} ref - The ID of the node that is registering for this broadcast command event
|
|
539
|
+
* @param {Function} callback - Callback when complete
|
|
540
|
+
*/
|
|
541
|
+
node.subscribeToBCMD = function (uri, ref, callback) {
|
|
542
|
+
let sub = {
|
|
543
|
+
node: ref,
|
|
544
|
+
cb: callback,
|
|
545
|
+
};
|
|
546
|
+
if (!node.bcmdSubscriptions.has(uri)) {
|
|
547
|
+
node.service.srvcAPI.subscribeToBCMD(uri);
|
|
548
|
+
node.bcmdSubscriptions.set(uri, [sub]);
|
|
549
|
+
} else {
|
|
550
|
+
node.bcmdSubscriptions.get(uri).push(sub);
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* Unsubscribe to a broadcast command
|
|
556
|
+
* @param {string} uri - The full URI of the broadcast command
|
|
557
|
+
* @param {Object} ref - The ID of the node that is registering for this broadcast command event
|
|
558
|
+
*/
|
|
559
|
+
node.unsubscribeToBCMD = function (uri, ref) {
|
|
560
|
+
if (node.bcmdSubscriptions.has(uri)) {
|
|
561
|
+
node.bcmdSubscriptions.set(
|
|
562
|
+
uri,
|
|
563
|
+
node.bcmdSubscriptions.get(uri).filter((sub) => sub.node !== ref)
|
|
564
|
+
);
|
|
565
|
+
}
|
|
566
|
+
if (node.bcmdSubscriptions.get(uri).length === 0) {
|
|
567
|
+
node.service.srvcAPI.unsubscribeToBCMD(uri);
|
|
568
|
+
node.bcmdSubscriptions.delete(uri);
|
|
569
|
+
}
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* Send broadcast command
|
|
574
|
+
* @param {string} cid - The command ID
|
|
575
|
+
* @param {Object} commandData - An object containing the command data
|
|
576
|
+
*/
|
|
577
|
+
node.sendBroadcastCommand = function (cid, commandData) {
|
|
578
|
+
node.service.srvcAPI.sendBroadcastCommand(cid, commandData);
|
|
579
|
+
};
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* Send direct command
|
|
583
|
+
* @param {string} uri - The full URI of the service to send the command to
|
|
584
|
+
* @param {string} cid - The command ID
|
|
585
|
+
* @param {Object} commandData - An object containing the command data
|
|
586
|
+
* @param {number} timeout - Optional timeout in ms which overrides the default timeout if > 0
|
|
587
|
+
* @param {Function} callback - Callback when complete
|
|
588
|
+
*/
|
|
589
|
+
node.sendDirectCommand = function (uri, cid, commandData, timeout, callback) {
|
|
590
|
+
node.service.srvcAPI.sendDirectCommand(uri, cid, commandData, timeout, callback);
|
|
591
|
+
};
|
|
592
|
+
|
|
593
|
+
/**
|
|
594
|
+
* Get service configuration
|
|
595
|
+
* @param {string} hid - The hub ID of the hub the desired service is a child to
|
|
596
|
+
* @param {string} sid - The service ID of the desired service
|
|
597
|
+
* @param {Function} callback - Callback when complete
|
|
598
|
+
*/
|
|
599
|
+
node.getServiceConfig = function (hid, sid, callback) {
|
|
600
|
+
node.service.srvcAPI.getServiceConfig(hid, sid, callback);
|
|
601
|
+
};
|
|
602
|
+
|
|
603
|
+
/**
|
|
604
|
+
* Update configuration of a given object
|
|
605
|
+
* @param {string} hid - The hub ID of the hub the target object is a child of
|
|
606
|
+
* @param {string} sid - The serbice ID of the service the target object is a child of
|
|
607
|
+
* @param {string} pid - The profile ID of target object type
|
|
608
|
+
* @param {string} ins - The object instance
|
|
609
|
+
* @param {Object} config - The new object configuration, structure given by {ins: string, pid: string, uiname: string, rids: array}
|
|
610
|
+
* @param {Function} callback - Callback when complete
|
|
611
|
+
*/
|
|
612
|
+
node.updateObjectInServiceConfig = function (hid, sid, pid, ins, config, callback) {
|
|
613
|
+
node.service.srvcAPI.updateObjectInServiceConfig(hid, sid, pid, ins, config, callback);
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
RED.nodes.registerType('mobius connection', MobiusConnectionNode);
|
|
618
|
+
|
|
619
|
+
// Register the endpoint for node-red mobius object discovery in node-red node config pages
|
|
620
|
+
RED.httpAdmin.get(
|
|
621
|
+
'/mobjectdiscover',
|
|
622
|
+
RED.auth.needsPermission('serial.read'),
|
|
623
|
+
function (req, res) {
|
|
624
|
+
let conn = RED.nodes.getNode(req.query.mobius);
|
|
625
|
+
let hid = req.query.hid;
|
|
626
|
+
let spids = [];
|
|
627
|
+
try {
|
|
628
|
+
if (req.query.hasOwnProperty('spids')) {
|
|
629
|
+
spids = JSON.parse(req.query.spids);
|
|
630
|
+
}
|
|
631
|
+
} catch (e) {
|
|
632
|
+
spids = [];
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
let pid = req.query.pid;
|
|
636
|
+
if (conn === null || !conn.service.connected) {
|
|
637
|
+
RED.log.error('Discover objects failed - could not to connect to MOBiUS hub.');
|
|
638
|
+
throw new Error('Discover objects failed - could not to connect to MOBiUS hub.');
|
|
639
|
+
} else {
|
|
640
|
+
uiDeviceDiscovery
|
|
641
|
+
.discoverDevicesByPID(RED, conn, hid, spids, pid)
|
|
642
|
+
.then((devices) => {
|
|
643
|
+
res.json(devices);
|
|
644
|
+
})
|
|
645
|
+
.catch((err) => {
|
|
646
|
+
throw err;
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
);
|
|
651
|
+
|
|
652
|
+
// Register the endpoint for node-red mobius service discovery in node-red node config pages
|
|
653
|
+
RED.httpAdmin.get(
|
|
654
|
+
'/mservicediscover',
|
|
655
|
+
RED.auth.needsPermission('serial.read'),
|
|
656
|
+
function (req, res) {
|
|
657
|
+
let conn = RED.nodes.getNode(req.query.mobius);
|
|
658
|
+
let hid = req.query.hid;
|
|
659
|
+
let spid = req.query.spid;
|
|
660
|
+
if (conn === null || !conn.service.connected) {
|
|
661
|
+
RED.log.error('Discover services failed - could not to connect to MOBiUS hub.');
|
|
662
|
+
throw new Error('Discover services failed - could not to connect to MOBiUS hub.');
|
|
663
|
+
} else {
|
|
664
|
+
uiDeviceDiscovery
|
|
665
|
+
.discoverServicesBySPID(RED, conn, hid, spid)
|
|
666
|
+
.then((services) => {
|
|
667
|
+
res.json(services);
|
|
668
|
+
})
|
|
669
|
+
.catch((err) => {
|
|
670
|
+
throw err;
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
);
|
|
675
|
+
};
|