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.
Files changed (39) hide show
  1. package/dist/nodes/icons/mobius-inject.png +0 -0
  2. package/dist/nodes/icons/mobius.png +0 -0
  3. package/dist/nodes/mobius-clear-resource.html +178 -0
  4. package/dist/nodes/mobius-clear-resource.js +109 -0
  5. package/dist/nodes/mobius-connection.html +68 -0
  6. package/dist/nodes/mobius-connection.js +675 -0
  7. package/dist/nodes/mobius-discover-object-list.html +272 -0
  8. package/dist/nodes/mobius-discover-object-list.js +263 -0
  9. package/dist/nodes/mobius-discover.html +139 -0
  10. package/dist/nodes/mobius-discover.js +100 -0
  11. package/dist/nodes/mobius-filter-by-rid-value.html +206 -0
  12. package/dist/nodes/mobius-filter-by-rid-value.js +123 -0
  13. package/dist/nodes/mobius-flow-inject.html +162 -0
  14. package/dist/nodes/mobius-flow-inject.js +124 -0
  15. package/dist/nodes/mobius-get-multi-object.html +176 -0
  16. package/dist/nodes/mobius-get-multi-object.js +127 -0
  17. package/dist/nodes/mobius-get-multi-resource.html +195 -0
  18. package/dist/nodes/mobius-get-multi-resource.js +140 -0
  19. package/dist/nodes/mobius-get-object.html +168 -0
  20. package/dist/nodes/mobius-get-object.js +102 -0
  21. package/dist/nodes/mobius-get-resource.html +169 -0
  22. package/dist/nodes/mobius-get-resource.js +101 -0
  23. package/dist/nodes/mobius-object-cov.html +171 -0
  24. package/dist/nodes/mobius-object-cov.js +83 -0
  25. package/dist/nodes/mobius-resource-cov.html +155 -0
  26. package/dist/nodes/mobius-resource-cov.js +77 -0
  27. package/dist/nodes/mobius-send-bcmd.html +93 -0
  28. package/dist/nodes/mobius-send-bcmd.js +61 -0
  29. package/dist/nodes/mobius-send-dcmd.html +130 -0
  30. package/dist/nodes/mobius-send-dcmd.js +80 -0
  31. package/dist/nodes/mobius-set-multi-resource.html +150 -0
  32. package/dist/nodes/mobius-set-multi-resource.js +104 -0
  33. package/dist/nodes/mobius-set-resource.html +180 -0
  34. package/dist/nodes/mobius-set-resource.js +145 -0
  35. package/dist/nodes/mobius-sub-bcmd.html +94 -0
  36. package/dist/nodes/mobius-sub-bcmd.js +64 -0
  37. package/dist/nodes/node-red-ui-discover-devices.js +103 -0
  38. package/dist/nodes/validateURI.js +51 -0
  39. package/package.json +1 -1
@@ -0,0 +1,272 @@
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
+ <script type="text/x-red" data-template-name="mobius discover object list">
28
+ <div class="form-row">
29
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
30
+ <input type="text" id="node-input-name" placeholder="Name">
31
+ </div>
32
+ <hr>
33
+ <div class="form-row">
34
+ <label for="node-input-connection"><i class="fa fa-globe"></i> MOBiUS</label>
35
+ <input type="text" id="node-input-connection">
36
+ </div>
37
+ <div class="form-row">
38
+ <label for="node-input-hid"><i class="fa fa-tasks"></i> HID</label>
39
+ <input type="text" id="node-input-hid" placeholder="">
40
+ </div>
41
+ <hr>
42
+ <div class="form-row">
43
+ <label for="node-input-output"><i class="fa fa-sign-out"></i> Output</label>
44
+ <select type="text" id="node-input-output" style="display: inline-block; width: auto; vertical-align: center;">
45
+ <option value="objects">MOBiUS Objects</option>
46
+ <option value="uris">MOBiUS Object URIs</option>
47
+ </select>
48
+ </div>
49
+ <div class="form-row">
50
+ <label for="node-input-send"><i class="fa fa-ellipsis-h"></i> Send</label>
51
+ <select type="text" id="node-input-send" style="display: inline-block; width: auto; vertical-align: center;">
52
+ <option value="individual">Individual Items</option>
53
+ <option value="array">Array of Items</option>
54
+ </select>
55
+ </div>
56
+ <div class="form-row node-input-subs-container-row">
57
+ <label for="node-input-subs-container" style="width:105px;float:left;"><i class="fa fa-bars"></i> Discover</label>
58
+ <ol id="node-input-subs-container"></ol>
59
+ </div>
60
+ <div class="form-row">
61
+ <label for="node-input-useRIDValueFiltering" style="width:178px;float:left;"><i class="fa fa-filter"></i> Filter by Resource Value</label>
62
+ <input type="checkbox" id="node-input-useRIDValueFiltering" style="display: inline-block; width: auto; vertical-align: top;">
63
+ </div>
64
+ <div id="use-rid-filter-row" class="form-row hidden">
65
+ <div class="form-row">
66
+ <label for="node-input-rid"><i class="fa fa-tag"></i> RID</label>
67
+ <input type="text" id="node-input-rid" placeholder="Resource to test">
68
+ </div>
69
+ <div class="form-row">
70
+ <label for="node-input-limit"><i class="fa fa-arrow-up"></i> Limit</label>
71
+ <input type="text" id="node-input-limit" placeholder="Maximum number of objects to return">
72
+ </div>
73
+ <div class="form-row">
74
+ <label for="node-input-func-editor" style="width:105px;float:left;"><i class="fa fa-list-alt"></i> Function</label>
75
+ <div style="height: 150px; min-height:80px;" class="node-text-editor" id="node-input-func-editor"></div>
76
+ </div>
77
+ </div>
78
+ </script>
79
+
80
+ <script type="text/javascript">
81
+ RED.nodes.registerType('mobius discover object list', {
82
+ category: 'mobius',
83
+ defaults: {
84
+ name: {value:""},
85
+ useRIDValueFiltering: {value: false},
86
+ func: {value:""},
87
+ limit: {value:100, validate:RED.validators.number()},
88
+ rid: {value: "", validate:function(v) {
89
+ if(v === '') { return true; }
90
+ if(v.length === 2) { return true; }
91
+ return false;
92
+ }},
93
+ output: {value: "objects", required: true},
94
+ send: {value: "individual", required: true},
95
+ subscriptions: {value:[{uri: '', type: 'include'}]},
96
+ hid: {value: "", validate:function(v) {
97
+ if(v === '') { return true; }
98
+ if(v.length === 6) { return true; }
99
+ return false;
100
+ }},
101
+ connection: {type:"mobius connection", required:true}
102
+ },
103
+ color:"#9ee3fa",
104
+ inputs:1,
105
+ outputs:1,
106
+ outputLabels: ["MOBiUS objects or URIs"],
107
+ icon: "mobius.png",
108
+ align: "left",
109
+ paletteLabel: 'discover object list',
110
+ label: function() {
111
+ if(this.name) {
112
+ return this.name;
113
+ } else {
114
+ return "discover object list";
115
+ }
116
+ },
117
+ labelStyle: function() {
118
+ return this.name ? "node_label_italic":"";
119
+ },
120
+ oneditprepare: function () {
121
+ var node = this;
122
+
123
+ /** Create the subs container and populate it */
124
+ $('#node-input-subs-container').css('min-height', '200px').css('min-width', '345px').editableList ({
125
+ addButton: "add uri",
126
+ removable: true,
127
+ sortable: true,
128
+ addItem: function (container, i, subscription) {
129
+ container.css({
130
+ overflow: 'hidden',
131
+ whiteSpace: 'nowrap'
132
+ });
133
+
134
+ // Add a default subscription if it does not exist
135
+ if (!subscription.hasOwnProperty("uri")) {
136
+ subscription = {uri: '', type: 'include'};
137
+ }
138
+
139
+ var row = $('<div>URI</div>').appendTo(container);
140
+ var uriField = $('<input/>',{class: "node-input-sub-uri", type: "text", style: "width: 170px; margin-left: 5px; text-align: left;"}).appendTo(row);
141
+ var typeField = $('<select/>',{class: "node-input-sub-type", style: "width:auto; margin-left: 5px; text-align: center;"}).appendTo(row);
142
+ typeField.append($("<option></option>").val('include').text('Include'));
143
+ typeField.append($("<option></option>").val('exclude').text('Exclude'));
144
+
145
+ // Populate the new stat
146
+ uriField.val(subscription.uri);
147
+ typeField.val(subscription.type);
148
+ }
149
+ });
150
+
151
+ $('.red-ui-editableList-addButton').css('margin-left', '105px')
152
+
153
+ // If no stat exists, create a default one
154
+ if (!node.subscriptions) {
155
+ node.subscriptions = [subscription = {uri: '', type: 'include'}];
156
+ }
157
+ // Populate list with all saved filters
158
+ for (let i = 0; i < node.subscriptions.length; i++) {
159
+ let subscription = node.subscriptions[i];
160
+ $("#node-input-subs-container").editableList('addItem', subscription);
161
+ }
162
+
163
+ function showRIDFilterInputs() {
164
+ if($("#node-input-useRIDValueFiltering").is(':checked')) {
165
+ $("#use-rid-filter-row").show();
166
+ } else {
167
+ $("#use-rid-filter-row").hide();
168
+ }
169
+ }
170
+ showRIDFilterInputs();
171
+ $("#node-input-useRIDValueFiltering").change(function() {
172
+ showRIDFilterInputs();
173
+ });
174
+
175
+ this.editor = RED.editor.createEditor({
176
+ id: 'node-input-func-editor',
177
+ mode: 'ace/mode/javascript',
178
+ value: this.func
179
+ });
180
+ },
181
+ oneditresize(size) {
182
+ var rows = $("#dialog-form>div:not(.node-input-subs-container-row)");
183
+ var height = size.height;
184
+ for (var i=0; i<rows.size(); i++) {
185
+ height -= $(rows[i]).outerHeight(true);
186
+ }
187
+ var editorRow = $("#dialog-form>div.node-input-subs-container-row");
188
+ height -= 4 * ((parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom"))));
189
+
190
+ $("#node-input-subs-container").editableList('height',height);
191
+ },
192
+ oneditsave: function() {
193
+ let subscriptions = $("#node-input-subs-container").editableList('items');
194
+ let node = this;
195
+ node.subscriptions= [];
196
+ subscriptions.each(function (i) {
197
+ var subscription = $(this);
198
+ let uri = subscription.find(".node-input-sub-uri").val();
199
+ let type = subscription.find(".node-input-sub-type").val();
200
+ node.subscriptions.push({uri: uri, type: type});
201
+ });
202
+
203
+ this.func = this.editor.getValue();
204
+ this.editor.destroy();
205
+ delete this.editor;
206
+ },
207
+ oneditcancel: function() {
208
+ this.editor.destroy();
209
+ delete this.editor;
210
+ }
211
+ });
212
+ </script>
213
+
214
+ <script type="text/x-red" data-help-name="mobius discover object list">
215
+ <p>Discover MOBiUS objects and return a filtered list of objects or URIs.</p>
216
+
217
+ <h3>Configuration Page</h3>
218
+ <dl class="message-properties">
219
+ <dt>MOBiUS <span class="property-type">node</span></dt>
220
+ <dd>Shared MOBiUS connection for communication with the MOBiUS Hub.</dd>
221
+ <dt>HID <span class="property-type">string</span></dt>
222
+ <dd>Optional Mobius hub ID to use for discovery. Leave empty to use the local HID.</dd>
223
+ <dt>Output <span class="property-type">option</span></dt>
224
+ <dd>Output full MOBiUS objects or MOBiUS object URIs.</dd>
225
+ <dt>Send <span class="property-type">option</span></dt>
226
+ <dd>Send the outputs individually or as a single array.</dd>
227
+ <dt>Discover <span class="property-type">string</span></dt>
228
+ <dd>The MOBiUS URI of the objects to discover. This may contain MQTT type wildcards.</dd>
229
+ <dt>Filter by Resource Value <span class="property-type">checkbox</span></dt>
230
+ <dd>If checked the returned objects are also filtered by the value of a single resource.</dd>
231
+ <dt>RID <span class="property-type">string</span></dt>
232
+ <dd>The MOBiUS Object Resource ID of the resource to test.</dd>
233
+ <dt class="optional">Limit <span class="property-type">number</span></dt>
234
+ <dd>The maximum number of objects to return. Defaults to 100.</dd>
235
+ <dt>Function <span class="property-type">string</span></dt>
236
+ <dd>JavaScript used to test the resource value.</dd>
237
+ </dl>
238
+
239
+ <h3>Inputs</h3>
240
+ <ol class="node-ports">
241
+ <li>Input message to trigger discovery
242
+ <dl class="message-properties">
243
+ <dt class="optional">topic <span class="property-type">string</span></dt>
244
+ <dd>Topic is passed through to output.</dd>
245
+ </dl>
246
+ </li>
247
+ </ol>
248
+
249
+ <h3>Outputs</h3>
250
+ <ol class="node-ports">
251
+ <li>Array of URIs discovered.
252
+ <dl class="message-properties">
253
+ <dt>topic <span class="property-type">string</span></dt>
254
+ <dd>When outputting individual items the topic will be the object URI and when outputting arrays the topic is passed through from input.</dd>
255
+ <dt>payload <span class="property-type">array</span></dt>
256
+ <dd>Array or individual list of discovered objects or URIs.</dd>
257
+ </dl>
258
+ </li>
259
+ </ol>
260
+
261
+ <h3>Details</h3>
262
+ <p>
263
+ The <code>Function</code> configuration property is string containing the JavaScript expression used to test the resource value. The expression must return <b>true</b> or <b>false</b>.
264
+ The actual value of the resource is represented in the expression by <code>$PV</code>. A few examples are shown below:</br>
265
+ <code>return $PV === 5;</code><br>
266
+ <code>return $PV > 10 && $PV < 100;</code><br>
267
+ <code>return $PV.includes('test-string');</code>
268
+ </p>
269
+
270
+ <br>
271
+ <p align="center" style="color:#000080">iaconnects © 2019</p>
272
+ </script>
@@ -0,0 +1,263 @@
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
+ /* jshint elision: true */
28
+ 'use strict';
29
+
30
+ module.exports = function (RED) {
31
+ function MobiusFlowNode (n) {
32
+ RED.nodes.createNode(this, n);
33
+ this.subscriptions = n.subscriptions;
34
+ this.sendType = n.send;
35
+ this.outputType = n.output;
36
+ this.hid = n.hid;
37
+ this.useRIDValueFiltering = n.useRIDValueFiltering;
38
+ this.rid = n.rid;
39
+ this.limit = n.limit;
40
+ this.func = n.func;
41
+ this.serviceConn = RED.nodes.getNode(n.connection);
42
+ var node = this;
43
+
44
+ if (node.serviceConn) {
45
+ node.status({
46
+ fill: 'red',
47
+ shape: 'ring',
48
+ text: 'Disconnected'
49
+ });
50
+
51
+ node.serviceConn.register(node);
52
+
53
+ node.on('input', function (msg, done) {
54
+ node.status({
55
+ fill: 'green',
56
+ shape: 'ring',
57
+ text: 'Busy'
58
+ });
59
+
60
+ node.discoverAllObjectURIs(msg).then((objectList) => {
61
+ if (node.sendType === 'individual') {
62
+ objectList.forEach((mobiusObject) => {
63
+ if (node.outputType === 'uris') {
64
+ node.send({
65
+ topic: mobiusObject.uri,
66
+ payload: mobiusObject.uri
67
+ });
68
+ } else {
69
+ node.send({
70
+ topic: mobiusObject.uri,
71
+ payload: mobiusObject
72
+ });
73
+ }
74
+ });
75
+ } else {
76
+ if (node.outputType === 'uris') {
77
+ const uris = [];
78
+ objectList.forEach((mobiusObject) => {
79
+ uris.push(mobiusObject.uri);
80
+ });
81
+ node.send({
82
+ topic: msg.topic,
83
+ payload: uris
84
+ });
85
+ } else {
86
+ node.send({
87
+ topic: msg.topic,
88
+ payload: objectList
89
+ });
90
+ }
91
+ }
92
+
93
+ node.status({
94
+ fill: 'green',
95
+ shape: 'dot',
96
+ text: 'Done'
97
+ });
98
+ }).catch(() => {
99
+ node.status({
100
+ fill: 'yellow',
101
+ shape: 'dot',
102
+ text: 'Failed discovery'
103
+ });
104
+ });
105
+ if (done) {
106
+ done();
107
+ }
108
+ });
109
+
110
+ node.on('close', function (done) {
111
+ node.serviceConn.deregister(node, done);
112
+ });
113
+ } else {
114
+ node.error(RED._('Mobius service not defined'));
115
+ }
116
+
117
+ node.discoverAllObjectURIs = async function (msg) {
118
+ return new Promise(async (resolve, reject) => {
119
+ let objectList = [];
120
+ try {
121
+ const hid = node.hid === '' ? node.serviceConn.service.srvcAPI.status.hubId : node.hid;
122
+ const profiles = await discoverProfiles(node.serviceConn, hid, node.subscriptions);
123
+
124
+ for await (let entry of profiles.entries()) {
125
+ let discoverParams = {};
126
+ const serviceURI = entry[0];
127
+ const pids = entry[1];
128
+ if (node.useRIDValueFiltering) {
129
+ discoverParams = {
130
+ uri: serviceURI,
131
+ pids: pids,
132
+ rid: node.rid,
133
+ func: node.func,
134
+ limit: node.limit
135
+ };
136
+ } else {
137
+ discoverParams = {
138
+ uri: serviceURI,
139
+ pids: pids,
140
+ rid: '00',
141
+ func: 'return true;',
142
+ limit: 512
143
+ };
144
+ }
145
+ try {
146
+ let objects = await discover(node.serviceConn, discoverParams);
147
+ for (let lp = 0; lp < objects.value.length; lp++) {
148
+ objects.value[lp]['uri'] = `${serviceURI}/${objects.value[lp].pid}/${objects.value[lp].ins}`;
149
+ objectList.push(objects.value[lp]);
150
+ }
151
+ } catch (err) {
152
+ node.warn(`Discover object failed for service (${serviceURI}) - ${err.message}`);
153
+ }
154
+ }
155
+
156
+ if (objectList.length === 0) {
157
+ throw new Error('No discovery data found');
158
+ }
159
+ } catch (err) {
160
+ node.warn(`Failed discover all objects: ${err.message}`);
161
+ reject(err.message);
162
+ }
163
+ resolve(objectList);
164
+ });
165
+ };
166
+ }
167
+
168
+ async function discoverProfiles(serviceConn, hid, subscriptions) {
169
+ return new Promise(async (resolve) => {
170
+ let discoveredProfiles = new Map();
171
+ let services = await discover(serviceConn, hid);
172
+ for (const service of services.value) {
173
+ if (service.status === 'online') {
174
+ let sid = service.id.split('/')[1];
175
+ if (isIncluded(`${hid}/${sid}/#`, subscriptions)) {
176
+ let profiles = await discover(serviceConn, `${hid}/${sid}`);
177
+ let pids = [];
178
+ for (const pid of profiles.value) {
179
+ if (isIncluded(`${hid}/${sid}/${pid}/#`, subscriptions) && !isExcluded(`${hid}/${sid}/${pid}/#`, subscriptions)) {
180
+ pids.push(pid);
181
+ }
182
+ }
183
+ if (pids.length > 0) {
184
+ discoveredProfiles.set(`${hid}/${sid}`, pids);
185
+ }
186
+ }
187
+ } else {
188
+ RED.log.warn(`Failed to discover objects for service ${service.id.split('/')[1]} as it is offline.`);
189
+ }
190
+ }
191
+ resolve(discoveredProfiles);
192
+ });
193
+ }
194
+
195
+ async function discover (serviceConn, params) {
196
+ return new Promise((resolve, reject) => {
197
+ serviceConn.discover(params, (err, response) => {
198
+ if (err) {
199
+ reject(err);
200
+ } else {
201
+ resolve(response);
202
+ }
203
+ });
204
+ });
205
+ };
206
+
207
+ function isIncluded(uri, subscriptions) {
208
+ let include = false;
209
+ for (const subscription of subscriptions) {
210
+ if (subscription.type === 'include' && validateSubscription(subscription.uri)) {
211
+ if (matchTopic(subscription.uri, uri)) {
212
+ include = true;
213
+ }
214
+ }
215
+ }
216
+ return include;
217
+ }
218
+
219
+ function isExcluded (uri, subscriptions) {
220
+ let exclude = false;
221
+ for (const subscription of subscriptions) {
222
+ if (subscription.type === 'exclude' && validateSubscription(subscription.uri)) {
223
+ if (matchTopic(subscription.uri, uri)) {
224
+ exclude = true;
225
+ }
226
+ }
227
+ }
228
+ return exclude;
229
+ }
230
+
231
+ function validateSubscription (uri) {
232
+ let parts = uri.split('/');
233
+ for (let lp = 0; lp < parts.length; lp++) {
234
+ if (parts[lp] === null || parts[lp] === '') {
235
+ return false;
236
+ }
237
+ }
238
+ if (parts.length === 4) {
239
+ return true;
240
+ }
241
+ if (parts.length < 4 && parts[parts.length - 1] === '#') {
242
+ return true;
243
+ }
244
+ return false;
245
+ }
246
+
247
+ function matchTopic (filter, topic) {
248
+ const filterArray = filter.split('/');
249
+ const topicArray = topic.split('/');
250
+ const length = filterArray.length < topicArray.length ? filterArray.length : topicArray.length;
251
+
252
+ for (let i = 0; i < length; ++i) {
253
+ const left = filterArray[i];
254
+ const right = topicArray[i];
255
+ if (!(left === right || left === '+' || left === '#' || right === '+' || right === '#')) {
256
+ return false;
257
+ }
258
+ }
259
+ return true;
260
+ }
261
+
262
+ RED.nodes.registerType('mobius discover object list', MobiusFlowNode);
263
+ };
@@ -0,0 +1,139 @@
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
+ <script type="text/x-red" data-template-name="mobius discover">
28
+ <div class="form-row">
29
+ <label for="node-input-connection"><i class="fa fa-globe"></i> MOBiUS</label>
30
+ <input type="text" id="node-input-connection">
31
+ </div>
32
+ <hr>
33
+ <div class="form-row">
34
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
35
+ <input type="text" id="node-input-name" placeholder="Name">
36
+ </div>
37
+ </script>
38
+
39
+ <script type="text/javascript">
40
+ RED.nodes.registerType('mobius discover',{
41
+ category: 'mobius',
42
+ color: "#8abff5",
43
+ defaults: {
44
+ name: {value: ""},
45
+ connection: {type: "mobius connection", required: true}
46
+ },
47
+ inputs:1,
48
+ outputs:1,
49
+ inputLabels: "Trigger discovery",
50
+ outputLabels: ["Full MOBiUS response"],
51
+ icon: "mobius.png",
52
+ align: "left",
53
+ paletteLabel: "discover",
54
+ label: function() {
55
+ if(this.name) {
56
+ return this.name;
57
+ } else {
58
+ return "discover";
59
+ }
60
+ },
61
+ labelStyle: function() {
62
+ return this.name ? "node_label_italic":"";
63
+ }
64
+ });
65
+ </script>
66
+
67
+ <script type="text/x-red" data-help-name="mobius discover">
68
+ <p>Discover MOBiUS services, object profiles, and objects</p>
69
+
70
+ <h3>Configuration Page</h3>
71
+ <dl class="message-properties">
72
+ <dt>MOBiUS <span class="property-type">node</span></dt>
73
+ <dd>Shared MOBiUS connection for communication with the MOBiUS Hub.</dd>
74
+ </dl>
75
+
76
+ <h3>Inputs</h3>
77
+ <ol class="node-ports">
78
+ <li>Input message to trigger discovery
79
+ <dl class="message-properties">
80
+ <dt>topic <span class="property-type">string</span></dt>
81
+ <dd>The path (in the form of a partial MOBiUS URI) whose children are to be discovered.</dd>
82
+ <dt class="optional">payload <span class="property-type">object</span></dt>
83
+ <dd>If the following properties are supplied in the payload the discovery will filter the results based on a resource's value.
84
+ See the Details section below for more information.</dd>
85
+ <dt class="optional">payload.pids <span class="property-type">array of strings</span></dt>
86
+ <dd>An array of MOBiUS Object Profile IDs to filter. Defaults to an empty array.</dd>
87
+ <dt>payload.rid <span class="property-type">string</span></dt>
88
+ <dd>The MOBiUS Object Resource ID of the resource to test.</dd>
89
+ <dt class="optional">payload.limit <span class="property-type">number</span></dt>
90
+ <dd>The maximum number of objects to return. Defaults to 100.</dd>
91
+ <dt>payload.func <span class="property-type">string</span></dt>
92
+ <dd>JavaScript used to test the resource value.</dd>
93
+ </dl>
94
+ </li>
95
+ </ol>
96
+
97
+ <h3>Outputs</h3>
98
+ <ol class="node-ports">
99
+ <li>Full MOBiUS response
100
+ <dl class="message-properties">
101
+ <dt>topic <span class="property-type">string</span></dt>
102
+ <dd>The original path used in the disccovery.</dd>
103
+ <dt>error <span class="property-type">boolean</span></dt>
104
+ <dd>True if an error occured, else false.</dd>
105
+ <dt>response <span class="property-type">object</span></dt>
106
+ <dd>The full MOBiUS response message.</dd>
107
+ </dl>
108
+ </li>
109
+ </ol>
110
+
111
+ <h3>Details</h3>
112
+ <p>
113
+ In addition to discovering all MOBiUS services, object profiles, and objects it is possible filter the results based on the value of a resource.
114
+ This is done by passing in additional parameters in the payload. These parameters are detailed below.
115
+ <br><b>Filtering only works when discovering object profiles or objects.</b>
116
+ </p>
117
+ <p>To filter on objects of type 0201 and 0258 and only return the objects with a value of greater than 12 in resource 40 the message would be:<br>
118
+ <code>{ topic: "000001/021", payload: { pids: ["0201", "0258"], rid: "40", func: "return $PV > 12;" }</code>
119
+ <p>
120
+ <code><i>pids</i></code> When discovering object profiles an array of the profiles (as 4 digit hex strings) to be used in the filter can be supplied. If this is an empty array it acts as a
121
+ wild card and all objects belonging to a service will be used regardless of their object profile. If pids is not supplied it will default to an empty array.
122
+ <br>When discovering object instances the pids value will be ignored and only the pid supplied as part of the discovery URI is used.
123
+ </p>
124
+ <p>
125
+ <code>rid</code> The ID of resource whose value will be tested. This is a 2 digit hex string.
126
+ </p>
127
+ <p>
128
+ <code><i>limit</i></code> The maximum number of objects that will be returned. If not supplied it defaults to 100.
129
+ </p>
130
+ <p>
131
+ <code>func</code> A string containing the JavaScript expression used to test the resource value. The expression must return <b>true</b> or <b>false</b>.
132
+ The actual value of the resource is represented in the expression by <code>$PV</code>. A few examples are shown below:</br>
133
+ <code>return $PV === 5;</code><br>
134
+ <code>return $PV > 10 && $PV < 100;</code><br>
135
+ <code>return $PV.includes('test-string');</code>
136
+ </p>
137
+ <br>
138
+ <p align="center" style="color:#000080">iaconnects © 2017</p>
139
+ </script>