node-red-contrib-mobius-flow-base 3.2.0 → 3.4.0-beta.1
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/engine-api-calls.js +26 -6
- package/dist/engine-api-client.d.ts +4 -4
- package/dist/engine-api-client.js +10 -10
- package/dist/nodes/common/mobsearch.js +7 -3
- package/dist/nodes/mobius-clear-resource.js +96 -65
- package/dist/nodes/mobius-discover.html +43 -19
- package/dist/nodes/mobius-discover.js +8 -0
- package/dist/nodes/mobius-filter-by-rid-value.js +51 -3
- package/dist/nodes/mobius-flow-inject.js +40 -12
- package/dist/nodes/mobius-get-multi-object.html +98 -76
- package/dist/nodes/mobius-get-multi-object.js +22 -19
- package/dist/nodes/mobius-get-multi-resource.html +99 -75
- package/dist/nodes/mobius-get-multi-resource.js +22 -19
- package/dist/nodes/mobius-get-object.js +39 -7
- package/dist/nodes/mobius-get-resource.js +39 -7
- package/dist/nodes/mobius-set-multi-resource.js +73 -53
- package/dist/nodes/mobius-set-resource.js +57 -11
- package/package.json +1 -1
package/dist/engine-api-calls.js
CHANGED
|
@@ -48,8 +48,12 @@ class EngineApiCalls {
|
|
|
48
48
|
callback(null, response.data);
|
|
49
49
|
}
|
|
50
50
|
catch (err) {
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
if (err.response?.status === 404) {
|
|
52
|
+
callback(null, { ts: new Date().toISOString(), uri, data: [] });
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
callback(err);
|
|
56
|
+
}
|
|
53
57
|
}
|
|
54
58
|
};
|
|
55
59
|
this.loggedIn ? func() : this.messageQueue.queue.push(func);
|
|
@@ -228,11 +232,27 @@ class EngineApiCalls {
|
|
|
228
232
|
if (!this.apiClient)
|
|
229
233
|
throw new Error('No API client set');
|
|
230
234
|
const discoveries = [];
|
|
235
|
+
const discoverOnPid = (pid) => {
|
|
236
|
+
return (async () => {
|
|
237
|
+
try {
|
|
238
|
+
const response = await this.apiClient({
|
|
239
|
+
method: 'get',
|
|
240
|
+
url: `/mobius/discover/${uri}/${pid}`,
|
|
241
|
+
});
|
|
242
|
+
return response;
|
|
243
|
+
}
|
|
244
|
+
catch (err) {
|
|
245
|
+
if (err.response?.status === 404) {
|
|
246
|
+
return { data: { data: [], uri: uri } };
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
throw err;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
})();
|
|
253
|
+
};
|
|
231
254
|
for (let pid of pids) {
|
|
232
|
-
discoveries.push(
|
|
233
|
-
method: 'get',
|
|
234
|
-
url: `/mobius/discover/${uri}/${pid}`,
|
|
235
|
-
}));
|
|
255
|
+
discoveries.push(discoverOnPid(pid));
|
|
236
256
|
}
|
|
237
257
|
const pidGroups = (await Promise.all(discoveries)).map((response) => ({
|
|
238
258
|
uri: response.data.uri,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { AxiosInstance } from
|
|
2
|
-
import { EngineWebSocket } from
|
|
3
|
-
import { EngineApiCalls } from
|
|
1
|
+
import { AxiosInstance } from "axios";
|
|
2
|
+
import { EngineWebSocket } from "./engine-websocket";
|
|
3
|
+
import { EngineApiCalls } from "./engine-api-calls";
|
|
4
4
|
export declare class EngineApiClient extends EngineApiCalls {
|
|
5
5
|
private reloginInterval;
|
|
6
6
|
client: AxiosInstance | null;
|
|
@@ -14,7 +14,7 @@ export declare class EngineApiClient extends EngineApiCalls {
|
|
|
14
14
|
EngineWebSocket: EngineWebSocket;
|
|
15
15
|
private hostname;
|
|
16
16
|
private protocol;
|
|
17
|
-
constructor(protocol:
|
|
17
|
+
constructor(protocol: "http" | "https", host: string, username: string, password: string);
|
|
18
18
|
private login;
|
|
19
19
|
private refresh;
|
|
20
20
|
close: () => void;
|
|
@@ -24,11 +24,11 @@ class EngineApiClient extends engine_api_calls_1.EngineApiCalls {
|
|
|
24
24
|
this.password = password;
|
|
25
25
|
this.hostname = host;
|
|
26
26
|
this.protocol = protocol;
|
|
27
|
-
const baseURL = `${this.protocol}://${this.hostname}/api/v1`;
|
|
27
|
+
const baseURL = `${this.protocol}://${this.hostname}/api/engine/v1`;
|
|
28
28
|
this.client = axios_1.default.create({
|
|
29
29
|
baseURL: baseURL,
|
|
30
30
|
headers: {
|
|
31
|
-
|
|
31
|
+
"Content-Type": "application/json",
|
|
32
32
|
},
|
|
33
33
|
});
|
|
34
34
|
this.setApiClient(this.client);
|
|
@@ -41,15 +41,15 @@ class EngineApiClient extends engine_api_calls_1.EngineApiCalls {
|
|
|
41
41
|
this.login();
|
|
42
42
|
}
|
|
43
43
|
else {
|
|
44
|
-
console.log(
|
|
44
|
+
console.log("No username, password, host, or port provided. Not attempting to login to Mobius Engine API.");
|
|
45
45
|
this.reloginInterval && clearInterval(this.reloginInterval);
|
|
46
46
|
this.reloginInterval = null;
|
|
47
47
|
}
|
|
48
48
|
// Add auth headers to all axios calls
|
|
49
49
|
this.client.interceptors.request.use((config) => {
|
|
50
|
-
if (!config.url?.endsWith(
|
|
50
|
+
if (!config.url?.endsWith("/auth/login")) {
|
|
51
51
|
if (this.tokens && config.headers) {
|
|
52
|
-
config.headers[
|
|
52
|
+
config.headers["Authorization"] = `Bearer ${this.tokens.token}`;
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
return config;
|
|
@@ -62,7 +62,7 @@ class EngineApiClient extends engine_api_calls_1.EngineApiCalls {
|
|
|
62
62
|
throw error;
|
|
63
63
|
});
|
|
64
64
|
this.EngineWebSocket = new engine_websocket_1.EngineWebSocket(this.hostname, this.protocol);
|
|
65
|
-
this.EngineWebSocket.on(
|
|
65
|
+
this.EngineWebSocket.on("disconnected", () => {
|
|
66
66
|
this.loggedIn = false;
|
|
67
67
|
});
|
|
68
68
|
}
|
|
@@ -70,8 +70,8 @@ class EngineApiClient extends engine_api_calls_1.EngineApiCalls {
|
|
|
70
70
|
console.log(`(${this.hostname}) -> Attempting Mobius Engine API Login`);
|
|
71
71
|
try {
|
|
72
72
|
const response = await this.client({
|
|
73
|
-
method:
|
|
74
|
-
url:
|
|
73
|
+
method: "post",
|
|
74
|
+
url: "/auth/login",
|
|
75
75
|
data: {
|
|
76
76
|
username: this.username,
|
|
77
77
|
password: this.password,
|
|
@@ -97,8 +97,8 @@ class EngineApiClient extends engine_api_calls_1.EngineApiCalls {
|
|
|
97
97
|
}
|
|
98
98
|
try {
|
|
99
99
|
const response = await this.client({
|
|
100
|
-
method:
|
|
101
|
-
url:
|
|
100
|
+
method: "post",
|
|
101
|
+
url: "/auth/refresh",
|
|
102
102
|
data: {
|
|
103
103
|
refreshToken: this.tokens.refreshToken,
|
|
104
104
|
},
|
|
@@ -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
|
-
|
|
578
|
-
JSON.
|
|
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
|
-
|
|
62
|
+
uriValidTest.test(msg.topic) &&
|
|
63
|
+
uriValidTest.test(node.resource)
|
|
51
64
|
) {
|
|
52
|
-
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
});
|
|
81
|
+
node.status({
|
|
82
|
+
fill: 'green',
|
|
83
|
+
shape: 'ring',
|
|
84
|
+
text: 'Busy',
|
|
85
|
+
});
|
|
64
86
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
err.code ? err.code : 'Unknown'
|
|
75
|
-
}
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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);
|
|
@@ -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
|
|
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:
|
|
53
|
+
color: '#8abff5',
|
|
43
54
|
defaults: {
|
|
44
|
-
name: {value:
|
|
45
|
-
|
|
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:
|
|
50
|
-
outputLabels: [
|
|
51
|
-
icon:
|
|
52
|
-
align:
|
|
53
|
-
paletteLabel:
|
|
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
|
|
79
|
+
return 'discover';
|
|
59
80
|
}
|
|
60
81
|
},
|
|
61
|
-
labelStyle: function() {
|
|
62
|
-
return this.name ?
|
|
63
|
-
}
|
|
82
|
+
labelStyle: function () {
|
|
83
|
+
return this.name ? 'node_label_italic' : '';
|
|
84
|
+
},
|
|
64
85
|
});
|
|
65
86
|
</script>
|
|
66
87
|
|
|
67
|
-
<script
|
|
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
|
-
|
|
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
|
-
|
|
78
|
+
uriValidTest.test(msg.topic) &&
|
|
79
|
+
uriValidTest.test(node.service)
|
|
60
80
|
) {
|
|
61
|
-
|
|
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
|
|
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 (
|
|
48
|
-
node.
|
|
49
|
-
|
|
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
|
|
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
|
|
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(
|
|
92
|
-
|
|
93
|
-
|
|
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
|
|
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 {
|