node-red-contrib-mobius-flow-base 3.1.7 → 3.3.0

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.
@@ -9,7 +9,6 @@ export declare class EngineApiClient extends EngineApiCalls {
9
9
  token: string;
10
10
  refreshToken: string;
11
11
  };
12
- loggedIn: boolean;
13
12
  private username;
14
13
  private password;
15
14
  EngineWebSocket: EngineWebSocket;
@@ -13,7 +13,6 @@ class EngineApiClient extends engine_api_calls_1.EngineApiCalls {
13
13
  client = null;
14
14
  refreshLoop = null;
15
15
  tokens = null;
16
- loggedIn = false;
17
16
  username;
18
17
  password;
19
18
  EngineWebSocket;
@@ -112,6 +111,7 @@ class EngineApiClient extends engine_api_calls_1.EngineApiCalls {
112
111
  }
113
112
  };
114
113
  close = () => {
114
+ this.stopQueueInterval();
115
115
  if (this.refreshLoop) {
116
116
  clearInterval(this.refreshLoop);
117
117
  }
@@ -574,9 +574,13 @@ function getMobsearch(mobiusSrvc, level, listed, opts) {
574
574
  .each(function (i) {
575
575
  let item = $(this);
576
576
  let secondField = item.find(`.${opts.containerSecondFieldName}`).val();
577
- tempList[i][Object.keys(tempList[i])[1]] = JSON.parse(
578
- JSON.stringify(secondField)
579
- );
577
+ if (secondField) {
578
+ tempList[i][Object.keys(tempList[i])[1]] = JSON.parse(
579
+ JSON.stringify(secondField)
580
+ );
581
+ } else {
582
+ tempList[i][Object.keys(tempList[i])[1]] = '';
583
+ }
580
584
  });
581
585
  $(`#${opts.containerName}`).editableList('empty');
582
586
  for (let i = 0; i < tempList.length; i++) {
@@ -35,6 +35,11 @@ module.exports = function (RED) {
35
35
  this.priority = n.priority;
36
36
  this.serviceConn = RED.nodes.getNode(n.connection);
37
37
  var node = this;
38
+
39
+ const uriValidTest = new RegExp(
40
+ `^[0-9A-Fa-f]{6}/[0-9A-Fa-f]{3}/[0-9A-Fa-f]{4}/[0-9A-Fa-f]{4}/[0-9A-Fa-f]{2}$`
41
+ );
42
+
38
43
  if (node.serviceConn) {
39
44
  node.status({
40
45
  fill: 'red',
@@ -43,83 +48,109 @@ module.exports = function (RED) {
43
48
  });
44
49
 
45
50
  node.on('input', function (msg) {
46
- let uri = node.resource;
47
51
  let pri = parseInt(node.priority);
52
+
53
+ let uri = '';
54
+ if (msg.hasOwnProperty('topic') && uriValidTest.test(msg.topic)) {
55
+ uri = msg.topic;
56
+ }
57
+ if (uriValidTest.test(node.resource)) {
58
+ uri = node.resource;
59
+ }
48
60
  if (
49
61
  msg.hasOwnProperty('topic') &&
50
- require('./validateURI')(msg.topic, 5)
62
+ uriValidTest.test(msg.topic) &&
63
+ uriValidTest.test(node.resource)
51
64
  ) {
52
- uri = msg.topic;
65
+ node.warn('URI defined in config and input topic. Using config URI.');
66
+ }
67
+ if (uri === '') {
68
+ node.status({
69
+ fill: 'yellow',
70
+ shape: 'dot',
71
+ text: 'Error: URI invalid',
72
+ });
73
+ node.error('Error: URI invalid');
74
+ return;
53
75
  }
76
+
54
77
  if (msg.hasOwnProperty('priority')) {
55
78
  pri = msg.priority;
56
79
  }
57
80
 
58
- if (uri) {
59
- node.status({
60
- fill: 'green',
61
- shape: 'ring',
62
- text: 'Busy',
63
- });
81
+ node.status({
82
+ fill: 'green',
83
+ shape: 'ring',
84
+ text: 'Busy',
85
+ });
64
86
 
65
- node.serviceConn.clearResourcePriority(uri, pri, (err, response) => {
66
- if (err) {
67
- node.status({
68
- fill: 'yellow',
69
- shape: 'dot',
70
- text: `Error: ${err.code ? err.code : 'Unknown'}`,
71
- });
72
- node.error(
73
- `Mobius error clearing resource priority: ${
74
- err.code ? err.code : 'Unknown'
75
- }, ${err.message ? err.message : ''}`
76
- );
77
- if (node.detailedOutput === true) {
78
- node.send([
79
- null,
80
- null,
81
- null,
82
- {
83
- ...msg,
84
- topic: uri,
85
- payload: { error: true, response: err },
86
- },
87
- ]);
88
- }
87
+ node.serviceConn.clearResourcePriority(uri, pri, (err, response) => {
88
+ if (err) {
89
+ node.status({
90
+ fill: 'yellow',
91
+ shape: 'dot',
92
+ text: (() => {
93
+ if (err.response.status === 404) {
94
+ return `Error: Resource not found`;
95
+ } else {
96
+ return `Error: ${err.code ? err.code : 'Unknown'}`;
97
+ }
98
+ })(),
99
+ });
100
+ node.error(
101
+ (() => {
102
+ if (err.response.status === 404) {
103
+ return `Error: Resource not found`;
104
+ } else {
105
+ return `Error: ${err.code ? err.code : 'Unknown'}`;
106
+ }
107
+ })()
108
+ );
109
+ if (node.detailedOutput === true) {
110
+ node.send([
111
+ null,
112
+ null,
113
+ null,
114
+ {
115
+ ...msg,
116
+ topic: uri,
117
+ payload: { error: true, response: err },
118
+ },
119
+ ]);
120
+ }
121
+ } else {
122
+ node.status({
123
+ fill: 'green',
124
+ shape: 'dot',
125
+ text: JSON.stringify(response.data.pv),
126
+ });
127
+ if (node.detailedOutput === true) {
128
+ node.send([
129
+ { ...msg, topic: uri, payload: response.data.pv },
130
+ {
131
+ ...msg,
132
+ topic: uri,
133
+ payload: { pv: response.data.pv, name: response.data.name },
134
+ },
135
+ { ...msg, topic: uri, payload: response.data },
136
+ {
137
+ ...msg,
138
+ topic: uri,
139
+ payload: { error: false, response: response },
140
+ },
141
+ ]);
89
142
  } else {
90
- node.status({
91
- fill: 'green',
92
- shape: 'dot',
93
- text: JSON.stringify(response.data.pv),
94
- });
95
- if (node.detailedOutput === true) {
96
- node.send([
97
- { ...msg, topic: uri, payload: response.data.pv },
98
- {
99
- ...msg,
100
- topic: uri,
101
- payload: { pv: response.data.pv, name: response.data.name },
102
- },
103
- { ...msg, topic: uri, payload: response.data },
104
- {
105
- ...msg,
106
- topic: uri,
107
- payload: { error: false, response: response },
108
- },
109
- ]);
110
- } else {
111
- node.send([
112
- { ...msg, topic: uri, payload: response.data.pv },
113
- {
114
- ...msg,
115
- topic: uri,
116
- payload: { pv: response.data.pv, name: response.data.name },
117
- },
118
- ]);
119
- }
143
+ node.send([
144
+ { ...msg, topic: uri, payload: response.data.pv },
145
+ {
146
+ ...msg,
147
+ topic: uri,
148
+ payload: { pv: response.data.pv, name: response.data.name },
149
+ },
150
+ ]);
120
151
  }
121
- });
122
- }
152
+ }
153
+ });
123
154
  });
124
155
 
125
156
  node.serviceConn.register(node);
@@ -34,7 +34,7 @@ export interface MobiusConnectionInterface {
34
34
  unsubscribeToObjectCOV(uri: string, ref: string, callback: (err: any, response: any) => void): void;
35
35
  subscribeToBCMD(uri: string, ref: string, callback: (err: any, response: any) => void): void;
36
36
  unsubscribeToBCMD(uri: string, ref: string, callback: (err: any, response: any) => void): void;
37
- sendBroadcastCommand(cid: string, commandData: any): void;
37
+ sendBroadcastCommand(cid: string, commandData: any, callback: (err: any, response: any) => void): void;
38
38
  sendDirectCommand(uri: string, cid: string, timeout: number, callback: (err: any, response: any) => void): void;
39
39
  getServiceConfig(hid: string, sid: string, callback: (err: any, response: any) => void): void;
40
40
  updateObjectInServiceConfig(hid: string, sid: string, pid: string, ins: string, config: any, callback: (err: any, response: any) => void): void;
@@ -542,8 +542,8 @@ module.exports = function (RED) {
542
542
  * @param {string} cid - The command ID
543
543
  * @param {Object} commandData - An object containing the command data
544
544
  */
545
- node.sendBroadcastCommand = function (cid, commandData) {
546
- this.apiClient.sendBroadcastCommand(cid, commandData);
545
+ node.sendBroadcastCommand = function (cid, commandData, callback) {
546
+ this.apiClient.sendBroadcastCommand(cid, commandData, callback);
547
547
  };
548
548
 
549
549
  /**
@@ -24,11 +24,22 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24
24
  POSSIBILITY OF SUCH DAMAGE.
25
25
  -->
26
26
 
27
- <script type="text/x-red" data-template-name="mobius discover">
27
+ <script
28
+ type="text/x-red"
29
+ data-template-name="mobius discover"
30
+ >
28
31
  <div class="form-row">
29
32
  <label for="node-input-connection"><i class="fa fa-globe"></i> MOBiUS</label>
30
33
  <input type="text" id="node-input-connection">
31
34
  </div>
35
+ <hr>
36
+ <div id="instance-row">
37
+ <div class="form-row" id="input-row">
38
+ <label for="node-input-uri"><i class="fa fa-tasks"></i> URI</label>
39
+ <input type="text" id="node-input-uri" style="width:61%;" placeholder="Discovery URI">
40
+ </div>
41
+ </div>
42
+
32
43
  <hr>
33
44
  <div class="form-row">
34
45
  <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
@@ -37,34 +48,47 @@ POSSIBILITY OF SUCH DAMAGE.
37
48
  </script>
38
49
 
39
50
  <script type="text/javascript">
40
- RED.nodes.registerType('mobius discover',{
51
+ RED.nodes.registerType('mobius discover', {
41
52
  category: 'mobius',
42
- color: "#8abff5",
53
+ color: '#8abff5',
43
54
  defaults: {
44
- name: {value: ""},
45
- connection: {type: "mobius connection", required: true}
55
+ name: { value: '' },
56
+ uri: {
57
+ value: '',
58
+ required: false,
59
+ validate: function (v) {
60
+ if (v === '') return true;
61
+ return new RegExp(
62
+ `^[0-9A-Fa-f]{6}(?:/[0-9A-Fa-f]{3}(?:/[0-9A-Fa-f]{4}(?:/[0-9A-Fa-f]{4})?)?)?$`
63
+ ).test(v);
64
+ },
65
+ },
66
+ connection: { type: 'mobius connection', required: true },
46
67
  },
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) {
68
+ inputs: 1,
69
+ outputs: 1,
70
+ inputLabels: 'Trigger discovery',
71
+ outputLabels: ['Full MOBiUS response'],
72
+ icon: 'mobius.png',
73
+ align: 'left',
74
+ paletteLabel: 'discover',
75
+ label: function () {
76
+ if (this.name) {
56
77
  return this.name;
57
78
  } else {
58
- return "discover";
79
+ return 'discover';
59
80
  }
60
81
  },
61
- labelStyle: function() {
62
- return this.name ? "node_label_italic":"";
63
- }
82
+ labelStyle: function () {
83
+ return this.name ? 'node_label_italic' : '';
84
+ },
64
85
  });
65
86
  </script>
66
87
 
67
- <script type="text/x-red" data-help-name="mobius discover">
88
+ <script
89
+ type="text/x-red"
90
+ data-help-name="mobius discover"
91
+ >
68
92
  <p>Discover MOBiUS services, object profiles, and objects</p>
69
93
 
70
94
  <h3>Configuration Page</h3>
@@ -31,8 +31,13 @@ module.exports = function (RED) {
31
31
  function MobiusDiscoverNode(n) {
32
32
  RED.nodes.createNode(this, n);
33
33
  this.serviceConn = RED.nodes.getNode(n.connection);
34
+ this.configUri = n.uri;
34
35
  var node = this;
35
36
 
37
+ const uriValidTest = new RegExp(
38
+ `^[0-9A-Fa-f]{6}(?:/[0-9A-Fa-f]{3}(?:/[0-9A-Fa-f]{4}(?:/[0-9A-Fa-f]{4})?)?)?$`
39
+ );
40
+
36
41
  if (node.serviceConn) {
37
42
  node.status({
38
43
  fill: 'red',
@@ -45,6 +50,9 @@ module.exports = function (RED) {
45
50
  if (msg.hasOwnProperty('topic')) {
46
51
  path = msg.topic;
47
52
  }
53
+ if (uriValidTest.test(node.configUri)) {
54
+ path = node.configUri;
55
+ }
48
56
 
49
57
  if (path === '') {
50
58
  node.status({
@@ -41,6 +41,8 @@ module.exports = function (RED) {
41
41
  this.serviceConn = RED.nodes.getNode(n.connection);
42
42
  var node = this;
43
43
 
44
+ const uriValidTest = new RegExp(`^[0-9A-Fa-f]{6}/[0-9A-Fa-f]{3}$`);
45
+
44
46
  if (node.serviceConn) {
45
47
  node.status({
46
48
  fill: 'red',
@@ -49,16 +51,45 @@ module.exports = function (RED) {
49
51
  });
50
52
 
51
53
  node.on('input', function (msg) {
52
- let uri = node.service;
54
+ // check pids of is array of 4char hex strings
55
+ if (!checkPidsValid(node.pids)) {
56
+ node.status({
57
+ fill: 'yellow',
58
+ shape: 'dot',
59
+ text: 'Error: PIDs invalid',
60
+ });
61
+ node.error('Error: PIDs list invalid');
62
+ return;
63
+ }
64
+
53
65
  let pids = JSON.parse(node.pids);
54
66
  let rid = node.rid;
55
67
  let limit = node.limit;
56
68
  let func = node.func;
69
+ let uri = '';
70
+ if (msg.hasOwnProperty('topic') && uriValidTest.test(msg.topic)) {
71
+ uri = msg.topic;
72
+ }
73
+ if (uriValidTest.test(node.service)) {
74
+ uri = node.service;
75
+ }
57
76
  if (
58
77
  msg.hasOwnProperty('topic') &&
59
- require('./validateURI')(msg.topic, 2)
78
+ uriValidTest.test(msg.topic) &&
79
+ uriValidTest.test(node.service)
60
80
  ) {
61
- uri = msg.topic;
81
+ node.warn(
82
+ 'Service URI defined in config and input topic. Using config Service URI.'
83
+ );
84
+ }
85
+ if (uri === '') {
86
+ node.status({
87
+ fill: 'yellow',
88
+ shape: 'dot',
89
+ text: 'Error: URI invalid',
90
+ });
91
+ node.error('Error: URI invalid');
92
+ return;
62
93
  }
63
94
  if (msg.hasOwnProperty('payload')) {
64
95
  if (msg.payload.hasOwnProperty('pids')) {
@@ -144,3 +175,20 @@ module.exports = function (RED) {
144
175
 
145
176
  RED.nodes.registerType('mobius filter by rid value', MobiusFilterNode);
146
177
  };
178
+
179
+ const checkPidsValid = (pids) => {
180
+ try {
181
+ pids = JSON.parse(pids);
182
+ } catch {
183
+ return false;
184
+ }
185
+ if (!Array.isArray(pids) || pids.length === 0) {
186
+ return false;
187
+ }
188
+ for (let i = 0; i < pids.length; i++) {
189
+ if (!/^[0-9A-Fa-f]{4}$/.test(pids[i])) {
190
+ return false;
191
+ }
192
+ }
193
+ return true;
194
+ };
@@ -30,24 +30,46 @@
30
30
  const _ = require('lodash');
31
31
 
32
32
  module.exports = function (RED) {
33
- function MobiusFlowNode (n) {
33
+ function MobiusFlowNode(n) {
34
34
  RED.nodes.createNode(this, n);
35
35
  this.subscriptions = n.subscriptions;
36
36
  this.serviceConn = RED.nodes.getNode(n.connection);
37
37
  var node = this;
38
38
 
39
+ const uriValidTest = new RegExp(
40
+ `^([0-9A-Fa-f]{6}|\\+)(/([0-9A-Fa-f]{3}|\\+))?(/([0-9A-Fa-f]{4}|\\+))?(/([0-9A-Fa-f]{4}|\\+)|/\\#)?$`
41
+ );
42
+
39
43
  if (node.serviceConn) {
40
44
  node.status({
41
45
  fill: 'red',
42
46
  shape: 'ring',
43
- text: 'Disconnected'
47
+ text: 'Disconnected',
44
48
  });
45
49
 
46
50
  for (const subscription of node.subscriptions) {
47
- if (subscription.type === 'include' && validateSubscription(subscription.uri)) {
48
- node.serviceConn.subscribeToObjectCOV(subscription.uri, this.id, (response) => {
49
- handleSubscription(node, response);
51
+ if (!uriValidTest.test(subscription.uri)) {
52
+ node.status({
53
+ fill: 'yellow',
54
+ shape: 'dot',
55
+ text: 'Error: URIs not Valid',
50
56
  });
57
+ return;
58
+ }
59
+ }
60
+
61
+ for (const subscription of node.subscriptions) {
62
+ if (
63
+ subscription.type === 'include' &&
64
+ validateSubscription(subscription.uri)
65
+ ) {
66
+ node.serviceConn.subscribeToObjectCOV(
67
+ subscription.uri,
68
+ this.id,
69
+ (response) => {
70
+ handleSubscription(node, response);
71
+ }
72
+ );
51
73
  }
52
74
  }
53
75
 
@@ -61,7 +83,7 @@ module.exports = function (RED) {
61
83
  }
62
84
  }
63
85
 
64
- function validateSubscription (uri) {
86
+ function validateSubscription(uri) {
65
87
  let parts = uri.split('/');
66
88
  for (let lp = 0; lp < parts.length; lp++) {
67
89
  if (parts[lp] === null || parts[lp] === '') {
@@ -83,18 +105,24 @@ module.exports = function (RED) {
83
105
  * @param {string} messageTopic - The topic in an actual message
84
106
  * @return {boolean} - True if the topics match, else false
85
107
  */
86
- function matchTopic (topic, messageTopic) {
108
+ function matchTopic(topic, messageTopic) {
87
109
  if (topic === '#') {
88
110
  return true;
89
111
  }
90
112
  // eslint-disable-next-line no-useless-escape
91
- var regex = new RegExp('^' + topic.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g, '\\$1')
92
- // eslint-disable-next-line no-useless-escape
93
- .replace(/\+/g, '[^/]+').replace(/\/#$/, '(\/.*)?') + '$');
113
+ var regex = new RegExp(
114
+ '^' +
115
+ topic
116
+ .replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g, '\\$1')
117
+ // eslint-disable-next-line no-useless-escape
118
+ .replace(/\+/g, '[^/]+')
119
+ .replace(/\/#$/, '(/.*)?') +
120
+ '$'
121
+ );
94
122
  return regex.test(messageTopic);
95
123
  }
96
124
 
97
- function handleSubscription (node, response) {
125
+ function handleSubscription(node, response) {
98
126
  for (const subscription of node.subscriptions) {
99
127
  if (subscription.type === 'exclude') {
100
128
  if (matchTopic(subscription.uri, response.uri)) {
@@ -106,7 +134,7 @@ module.exports = function (RED) {
106
134
  node.status({
107
135
  fill: 'green',
108
136
  shape: 'dot',
109
- text: JSON.stringify(response.uri)
137
+ text: JSON.stringify(response.uri),
110
138
  });
111
139
  let outObject = response.value;
112
140
  try {