node-red-contrib-mobius-flow-base 2.5.90 → 3.0.0-beta.12

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/.github/ISSUE_TEMPLATE/bug_report.md +16 -0
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +16 -0
  3. package/.github/ISSUE_TEMPLATE/general.md +7 -0
  4. package/.github/workflows/build_publish.yml +80 -0
  5. package/README.md +4 -10
  6. package/dist/engine-api-calls.d.ts +18 -0
  7. package/dist/engine-api-calls.js +214 -0
  8. package/dist/engine-api-client.d.ts +7 -0
  9. package/dist/engine-api-client.js +92 -0
  10. package/dist/engine-websocket.d.ts +58 -0
  11. package/dist/engine-websocket.js +226 -0
  12. package/dist/node-red-ui-funcs.js +180 -0
  13. package/dist/nodes/common/mobsearch.js +576 -0
  14. package/dist/nodes/mobius-clear-resource.html +22 -3
  15. package/dist/nodes/mobius-clear-resource.js +17 -12
  16. package/dist/nodes/mobius-connection.html +30 -8
  17. package/dist/nodes/mobius-connection.js +194 -85
  18. package/dist/nodes/mobius-discover-object-list.html +185 -126
  19. package/dist/nodes/mobius-discover-object-list.js +27 -8
  20. package/dist/nodes/mobius-discover.js +7 -7
  21. package/dist/nodes/mobius-filter-by-rid-value.html +57 -41
  22. package/dist/nodes/mobius-filter-by-rid-value.js +38 -31
  23. package/dist/nodes/mobius-flow-inject.html +32 -2
  24. package/dist/nodes/mobius-get-multi-object.html +39 -5
  25. package/dist/nodes/mobius-get-multi-resource.html +36 -4
  26. package/dist/nodes/mobius-get-multi-resource.js +13 -12
  27. package/dist/nodes/mobius-get-object.html +25 -3
  28. package/dist/nodes/mobius-get-object.js +12 -9
  29. package/dist/nodes/mobius-get-resource.html +26 -3
  30. package/dist/nodes/mobius-get-resource.js +17 -12
  31. package/dist/nodes/mobius-object-cov.html +27 -3
  32. package/dist/nodes/mobius-object-cov.js +9 -6
  33. package/dist/nodes/mobius-resource-cov.html +23 -3
  34. package/dist/nodes/mobius-resource-cov.js +5 -5
  35. package/dist/nodes/mobius-set-multi-resource.html +24 -3
  36. package/dist/nodes/mobius-set-multi-resource.js +9 -11
  37. package/dist/nodes/mobius-set-resource.html +24 -3
  38. package/package.json +13 -7
  39. package/dist/nodes/node-red-ui-discover-devices.js +0 -103
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.unsubscribeToBCMD = exports.subscribeToBCMD = exports.unsubscribeToResourceCOV = exports.subscribeToResourceCOV = exports.unsubscribeToObjectCOV = exports.subscribeToObjectCOV = exports.disconnectFromWebSocket = exports.connectToWebSocket = exports.clearAllCallbacks = exports.registerCallback = exports.on = void 0;
7
+ const ws_1 = __importDefault(require("ws"));
8
+ const engine_api_client_1 = require("./engine-api-client");
9
+ let webSocket = null;
10
+ const pendingWebSocketMessages = [];
11
+ let pendingWebSocketMessageInterval = null;
12
+ let pingInterval = null;
13
+ let registeredCallbacks = [];
14
+ const eventListeners = [];
15
+ const on = (eventName, callback) => {
16
+ eventListeners.push({ eventName, callback });
17
+ };
18
+ exports.on = on;
19
+ const triggerEvent = (eventName) => {
20
+ const callbacks = eventListeners
21
+ .filter((cb) => cb.eventName === eventName)
22
+ .map((cb) => cb.callback);
23
+ callbacks.forEach((cb) => cb());
24
+ };
25
+ function registerCallback(topic, callback) {
26
+ registeredCallbacks.push({ topic, callback });
27
+ }
28
+ exports.registerCallback = registerCallback;
29
+ function clearAllCallbacks() {
30
+ registeredCallbacks = [];
31
+ }
32
+ exports.clearAllCallbacks = clearAllCallbacks;
33
+ function sendPingMessage() {
34
+ sendWebSocketMessage({
35
+ topic: 'ping',
36
+ payload: {},
37
+ });
38
+ }
39
+ function sendWebSocketMessage(message) {
40
+ if (webSocket?.readyState === ws_1.default.OPEN) {
41
+ webSocket.send(JSON.stringify(message));
42
+ }
43
+ else {
44
+ pendingWebSocketMessages.push(message);
45
+ }
46
+ }
47
+ function handleWebSocketMessage(message) {
48
+ if (message.topic === 'error') {
49
+ console.log(`Websocket Error: ${message.payload}`);
50
+ }
51
+ if (message.topic === 'authorized') {
52
+ console.log('Websocket Auth Success');
53
+ triggerEvent('connected');
54
+ }
55
+ const callbacks = registeredCallbacks
56
+ .filter((cb) => cb.topic === message.topic)
57
+ .map((cb) => cb.callback);
58
+ callbacks.forEach((cb) => cb(message.payload));
59
+ }
60
+ const reconnect = () => {
61
+ console.log('WebSocket Client reconnecting...');
62
+ (0, exports.connectToWebSocket)();
63
+ };
64
+ let reconnectInterval = null;
65
+ /**
66
+ * Connect to the Mobius WebSocket API
67
+ * This method will connect to the Mobius WebSocket API and authenticate with the API token
68
+ */
69
+ const connectToWebSocket = () => {
70
+ if (!engine_api_client_1.tokens) {
71
+ console.log('Unabled to connect to websocket as no tokens are available');
72
+ return;
73
+ }
74
+ if (webSocket) {
75
+ webSocket.close();
76
+ webSocket = null;
77
+ }
78
+ let webSocketProtocol = 'ws';
79
+ // if (window.location.protocol === 'http:') {
80
+ // webSocketProtocol = 'ws';
81
+ // }
82
+ webSocket = new ws_1.default(`ws://localhost:8443/api/v1/mobius/subscribe/connect`);
83
+ webSocket.onopen = () => {
84
+ console.log('WebSocket Client Connected');
85
+ pingInterval = setInterval(sendPingMessage, 30000);
86
+ clearInterval(reconnectInterval);
87
+ webSocket?.send(JSON.stringify({
88
+ topic: 'authorize',
89
+ payload: `Bearer ${engine_api_client_1.tokens?.token}`,
90
+ }));
91
+ pendingWebSocketMessageInterval = setInterval(() => {
92
+ for (let i = 0; i < pendingWebSocketMessages.length; i++) {
93
+ const pendingMessage = pendingWebSocketMessages.shift();
94
+ sendWebSocketMessage(pendingMessage);
95
+ }
96
+ }, 1000);
97
+ };
98
+ webSocket.onclose = () => {
99
+ console.log('WebSocket Client Closed');
100
+ if (pingInterval) {
101
+ clearInterval(pingInterval);
102
+ }
103
+ if (pendingWebSocketMessageInterval) {
104
+ clearInterval(pendingWebSocketMessageInterval);
105
+ reconnectInterval = setInterval(reconnect, 5000);
106
+ }
107
+ webSocket = null;
108
+ triggerEvent('disconnected');
109
+ };
110
+ webSocket.onmessage = (message) => {
111
+ try {
112
+ if (message.data) {
113
+ const parsedMessage = JSON.parse(message.data);
114
+ handleWebSocketMessage(parsedMessage);
115
+ }
116
+ }
117
+ catch (e) {
118
+ console.log('Error parsing message ', e);
119
+ }
120
+ };
121
+ webSocket.on('error', (e) => {
122
+ console.error(e);
123
+ });
124
+ };
125
+ exports.connectToWebSocket = connectToWebSocket;
126
+ /**
127
+ * Disconnect from the Mobius WebSocket API
128
+ * This method will close the connection to the Mobius WebSocket API
129
+ */
130
+ const disconnectFromWebSocket = () => {
131
+ if (webSocket) {
132
+ webSocket.close();
133
+ }
134
+ };
135
+ exports.disconnectFromWebSocket = disconnectFromWebSocket;
136
+ /**
137
+ * Subscribe to an object's COV
138
+ * This method will subscribe to an object's COV
139
+ * @param uri The URI of the object to subscribe to
140
+ * @param listener The listener to dispatch the event to
141
+ */
142
+ const subscribeToObjectCOV = (uri) => {
143
+ console.log('Subscribing to object COV', uri);
144
+ sendWebSocketMessage({
145
+ topic: 'subscribe',
146
+ payload: { type: 'object-cov', uri },
147
+ });
148
+ // subList.push({ topic: 'object-cov', uri });
149
+ };
150
+ exports.subscribeToObjectCOV = subscribeToObjectCOV;
151
+ /**
152
+ * Unsubscribe from an object's COV
153
+ * This method will unsubscribe from an object's COV
154
+ * @param uri The URI of the object to unsubscribe from
155
+ * @param listener The listener to remove
156
+ */
157
+ const unsubscribeToObjectCOV = (uri) => {
158
+ sendWebSocketMessage({
159
+ topic: 'unsubscribe',
160
+ payload: { type: 'object-cov', uri },
161
+ });
162
+ // subList = subList.filter(
163
+ // (sub) => JSON.stringify(sub) !== JSON.stringify({ topic: 'object-cov', uri })
164
+ // );
165
+ };
166
+ exports.unsubscribeToObjectCOV = unsubscribeToObjectCOV;
167
+ /**
168
+ * Subscribe to an object's COV
169
+ * This method will subscribe to an object's COV
170
+ * @param uri The URI of the object to subscribe to
171
+ * @param listener The listener to dispatch the event to
172
+ */
173
+ const subscribeToResourceCOV = (uri) => {
174
+ sendWebSocketMessage({
175
+ topic: 'subscribe',
176
+ payload: { type: 'resource-cov', uri },
177
+ });
178
+ // subList.push({ topic: 'resource-cov', uri });
179
+ };
180
+ exports.subscribeToResourceCOV = subscribeToResourceCOV;
181
+ /**
182
+ * Unsubscribe from an object's COV
183
+ * This method will unsubscribe from an object's COV
184
+ * @param uri The URI of the object to unsubscribe from
185
+ * @param listener The listener to remove
186
+ */
187
+ const unsubscribeToResourceCOV = (uri) => {
188
+ sendWebSocketMessage({
189
+ topic: 'unsubscribe',
190
+ payload: { type: 'resource-cov', uri },
191
+ });
192
+ // subList = subList.filter(
193
+ // (sub) => JSON.stringify(sub) !== JSON.stringify({ topic: 'resource-cov', uri })
194
+ // );
195
+ };
196
+ exports.unsubscribeToResourceCOV = unsubscribeToResourceCOV;
197
+ /**
198
+ * Subscribe to a BCMD event
199
+ * This method will subscribe to a BCMD event
200
+ * @param uri The URI of the object to subscribe to
201
+ * @param listener The listener to dispatch the event to
202
+ */
203
+ const subscribeToBCMD = (uri) => {
204
+ sendWebSocketMessage({
205
+ topic: 'subscribe',
206
+ payload: { type: 'broadcast-command', uri },
207
+ });
208
+ // subList.push({ topic: 'broadcast-command', uri });
209
+ };
210
+ exports.subscribeToBCMD = subscribeToBCMD;
211
+ /**
212
+ * Unsubscribe from a BCMD event
213
+ * This method will unsubscribe from a BCMD event
214
+ * @param uri The URI of the object to unsubscribe from
215
+ * @param listener The listener to remove
216
+ */
217
+ const unsubscribeToBCMD = (uri) => {
218
+ sendWebSocketMessage({
219
+ topic: 'unsubscribe',
220
+ payload: { type: 'broadcast-command', uri },
221
+ });
222
+ // subList = subList.filter(
223
+ // (sub) => JSON.stringify(sub) !== JSON.stringify({ topic: 'broadcast-command', uri })
224
+ // );
225
+ };
226
+ exports.unsubscribeToBCMD = unsubscribeToBCMD;
@@ -0,0 +1,180 @@
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
+ const _ = require('lodash');
30
+ const excludedSpids = ['0004', '0012'];
31
+
32
+ module.exports = {
33
+
34
+ // Promisified version of discover
35
+ discover (connection, uri) {
36
+ return new Promise((resolve, reject) => {
37
+ connection.discover(uri, (err, response) => {
38
+ if (err) {
39
+ reject(err);
40
+ } else {
41
+ resolve(response);
42
+ }
43
+ });
44
+ });
45
+ },
46
+
47
+ // Promisified version of getServiceConfig
48
+ getNodeConfig (connection, hid) {
49
+ return new Promise((resolve, reject) => {
50
+ connection.getNodeConfig(hid, (err, response) => {
51
+ if (!err) {
52
+ resolve(response);
53
+ } else {
54
+ reject(err);
55
+ }
56
+ });
57
+ });
58
+ },
59
+
60
+ // Promisified version of getServiceConfig
61
+ getServiceConfig (connection, hid, sid) {
62
+ return new Promise((resolve, reject) => {
63
+ connection.getServiceConfig(hid, sid, (err, response) => {
64
+ if (!err) {
65
+ resolve(response);
66
+ } else {
67
+ reject(err);
68
+ }
69
+ });
70
+ });
71
+ },
72
+
73
+ // Discover object by By PID
74
+ async discoverDevicesByPID (RED, connection, hid, spids, pid) {
75
+ let devices = [];
76
+ if (!hid || hid === '') {
77
+ hid = connection.service.hubId;
78
+ }
79
+ let services = null;
80
+ try {
81
+ services = await this.discover(connection, hid);
82
+ } catch (err) {
83
+ RED.log.error(`Discover devices failed (${hid}) - ${err.message}`);
84
+ throw new Error(`Discover devices failed (${hid}) - ${err.message}`);
85
+ }
86
+ for (let srvcLoop = 0; srvcLoop < services.data.length; srvcLoop++) {
87
+ if (services.data[srvcLoop].status === 'online' && (spids.length === 0 || spids.includes(services.data[srvcLoop].spid))) {
88
+ let insURI = `${hid}/${services.data[srvcLoop].id.split('/')[1]}/${pid}`;
89
+ try {
90
+ let instances = await this.discover(connection, insURI);
91
+ for (let insLoop = 0; insLoop < instances.data.length; insLoop++) {
92
+ let deviceURI = `${hid}/${services.data[srvcLoop].id.split('/')[1]}/${pid}/${instances.data[insLoop]}`;
93
+ let device = await this.discover(connection, deviceURI);
94
+ let resourcesByName = _.keyBy(device.data[0].resources, 'name');
95
+ let deviceName = resourcesByName['name'].pv;
96
+ if (deviceName !== '') {
97
+ devices.push(device.uri + ' ' + deviceName);
98
+ } else {
99
+ devices.push(device.uri);
100
+ }
101
+ }
102
+ } catch (err) {
103
+ RED.log.warn(`Discover devices failed (${insURI}) - ${err.message}`);
104
+ }
105
+ }
106
+ }
107
+ return devices;
108
+ },
109
+
110
+ // Discover services by SPID
111
+ async discoverServicesBySPID (RED, connection, hid, spid) {
112
+ if (!hid || hid === '') {
113
+ hid = connection.service.hubId;
114
+ }
115
+ let services = null;
116
+ try {
117
+ services = await this.discover(connection, hid);
118
+ } catch (err) {
119
+ RED.log.error(`Discover services failed (${hid}) - ${err.message}`);
120
+ throw new Error(`Discover services failed (${hid}) - ${err.message}`);
121
+ }
122
+ let srvcs = [];
123
+ for (let srvcLoop = 0; srvcLoop < services.data.length; srvcLoop++) {
124
+ if (services.data[srvcLoop].status === 'online' && services.data[srvcLoop].spid === spid) {
125
+ srvcs.push(`${hid}/${services.data[srvcLoop].id.split('/')[1]}`);
126
+ }
127
+ }
128
+ return srvcs;
129
+ },
130
+
131
+ // Get list of services
132
+ async getServiceList(connection, hid) {
133
+ try {
134
+ // Fetch information from node config
135
+ const nodeConfig = await this.getNodeConfig(connection, hid);
136
+ const servicesFromConfig = nodeConfig.data;
137
+ let services = [];
138
+ for (let i = 0; i < servicesFromConfig.length; i++) {
139
+ const spid = servicesFromConfig[i].id.split('/')[0];
140
+ if (!excludedSpids.includes(spid)) {
141
+ services.push({
142
+ id: servicesFromConfig[i].id,
143
+ spid,
144
+ sid: servicesFromConfig[i].id.split('/')[1],
145
+ uri: `${nodeConfig.uri}/${servicesFromConfig[i].id.split('/')[1]}`,
146
+ name: servicesFromConfig[i].name,
147
+ enabled: servicesFromConfig[i].enabled,
148
+ runAtStart: servicesFromConfig[i].runAtStart,
149
+ });
150
+ }
151
+ }
152
+ return services;
153
+ } catch (err) {
154
+ throw JSON.stringify(err);
155
+ }
156
+ },
157
+
158
+ // Get list og objects on given service
159
+ async getObjectList(connection, hid, sid) {
160
+ try {
161
+ let objectList = [];
162
+ const serviceResponse = await this.discover(connection, `${hid}/${sid}`);
163
+ const pids = [...new Set(serviceResponse.data)];
164
+ for (let i = 0; i < pids.length; i++) {
165
+ const inssResponse = await this.discover(connection, `${hid}/${sid}/${pids[i]}`);
166
+ const inss = inssResponse.data;
167
+ for (let j = 0; j < inss.length; j++) {
168
+ const objResponse = await this.discover(
169
+ connection,
170
+ `${hid}/${sid}/${pids[i]}/${inss[j]}`
171
+ );
172
+ objectList.push(objResponse.data[0]);
173
+ }
174
+ }
175
+ return objectList;
176
+ } catch (err) {
177
+ throw JSON.stringify(err);
178
+ }
179
+ },
180
+ };