node-red-contrib-thingsboard-gateway 0.2.0 → 1.0.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.
package/README.md CHANGED
@@ -1,2 +1,25 @@
1
1
  # node-red-contrib-thingsboard-gateway
2
2
 
3
+ A Node-RED node for sending data to [ThingsBoard](https://thingsboard.io/) via Gateway Device using the MQTT protocol.
4
+
5
+ ## Installation
6
+
7
+ Install this module using npm in your Node-RED directory:
8
+
9
+ ```bash
10
+ npm install node-red-contrib-thingsboard-gateway
11
+ ```
12
+
13
+ Or search for `node-red-contrib-thingsboard-gateway` in the Node-RED Palette Manager.
14
+
15
+
16
+
17
+ ## License
18
+
19
+ Apache-2.0
20
+
21
+ ## References
22
+
23
+ - [ThingsBoard MQTT Gateway API](https://thingsboard.io/docs/reference/gateway-mqtt-api)
24
+ - [Node-RED Documentation](https://nodered.org/docs/)
25
+ - [MQTT Protocol](http://mqtt.org/)
@@ -1,336 +1,455 @@
1
- {
2
- "id": "8d3bffe93912093b",
3
- "type": "subflow",
4
- "name": "gateway out",
5
- "info": "Node-RED Subflow to use the [Thingsboard MQTT Gateway API](https://thingsboard.io/docs/reference/gateway-mqtt-api) for direct integration with FlexIoT.\r\n\r\n### Details\r\n\r\n#### Node Status\r\n\r\nThe node status color indicates the connection status to the Thingsboard platform.\r\n\r\n`Con`: connected / disconnected / errors (total)\r\n`Tel`: success / errors (total)\r\n`Attr`: success / errors (total)\r\n\r\n#### Device Connection\r\n\r\nUsed to connect a device to the Thingsboard platform.\r\nIt handles the connection process, including authentication and device registration.\r\n\r\nMessage properties:\r\n\r\n: api_method (string) : Must be set to \"connection\" for device connection.\r\n: device_name (string) : Device name to be targeted in Device List on FlexIoT.\r\n: device_type (string) : Device type, required for first connection. See FlexIoT Device Profile.\r\n: value (object) : Connection status.\r\n\r\nExample:\r\n\r\n```json\r\n{\r\n \"api_method\": \"connection\",\r\n \"device_name\": \"xinergis_32A3D\",\r\n \"device_type\": \"Xinergis Device\",\r\n \"value\": {\r\n \"active\": true\r\n }\r\n}\r\n```\r\n\r\n#### Attributes\r\n\r\nUsed to set device attributes.\r\nIt allows you to send key-value pairs as attributes to the device.\r\n\r\nMessage properties:\r\n\r\n: api_method (string) : Must be set to \"attributes\" for setting attributes.\r\n: device_name (string) : Device name to be targeted in Device List on FlexIoT.\r\n: value (object) : Key-value pairs representing the attributes.\r\n\r\nExample:\r\n\r\n```json\r\n{\r\n \"api_method\": \"attributes\",\r\n \"device_name\": \"xinergis_32A3D\",\r\n \"value\": {\r\n \"attribute_key_1\": \"value_1\",\r\n \"attribute_key_2\": \"value_2\"\r\n }\r\n}\r\n```\r\n\r\n#### Telemetry\r\n\r\nUsed to send telemetry data to the device.\r\nIt allows you to send various types of telemetry data.\r\n\r\nMessage properties:\r\n\r\n: api_method (string) : Must be set to \"telemetry\" for sending telemetry data.\r\n: device_name (string) : Device name to be targeted in Device List on FlexIoT.\r\n: value (object | array) : Key-value pairs representing the telemetry data.\r\n\r\nSingle object example:\r\n\r\n```json\r\n{\r\n \"api_method\": \"telemetry\",\r\n \"device_name\": \"xinergis_32A3D\",\r\n \"value\": {\r\n \"telemetry_key_1\": \"value_1\",\r\n \"telemetry_key_2\": \"value_2\"\r\n }\r\n}\r\n```\r\n\r\nArray example:\r\n\r\n```json\r\n{\r\n \"api_method\": \"telemetry\",\r\n \"device_name\": \"xinergis_32A3D\",\r\n \"value\": [\r\n {\r\n \"ts\": 1700000000000,\r\n \"values\": {\r\n \"telemetry_key_1\": \"value_1\",\r\n \"telemetry_key_2\": \"value_2\"\r\n }\r\n },\r\n {\r\n \"ts\": 1700000001000,\r\n \"values\": {\r\n \"telemetry_key_1\": \"value_3\",\r\n \"telemetry_key_2\": \"value_4\"\r\n }\r\n }\r\n ]\r\n}\r\n```\r\n\r\n### References\r\n\r\n* [Thingsboard MQTT Gateway API](https://thingsboard.io/docs/reference/gateway-mqtt-api)\r\n",
6
- "category": "",
7
- "in": [
8
- {
9
- "x": 360,
10
- "y": 560,
11
- "wires": [
12
- {
13
- "id": "4b7e9a3f7a1c5324"
14
- }
15
- ]
16
- }
17
- ],
18
- "out": [],
19
- "env": [
20
- {
21
- "name": "Server",
22
- "type": "mqtt-broker",
23
- "value": "",
24
- "ui": {
25
- "icon": "font-awesome/fa-globe",
26
- "type": "conf-types"
27
- }
28
- }
29
- ],
30
- "meta": {
31
- "module": "gateway-out",
32
- "type": "network",
33
- "version": "1.0.0",
34
- "author": "farisrfp <farisrafp@gmail.com>",
35
- "license": "MIT"
36
- },
37
- "color": "#8083fa",
38
- "inputLabels": [
39
- "paylod-in"
40
- ],
41
- "icon": "node-red/bridge-dash.svg",
42
- "flow": [
43
-
44
- {
45
- "id": "aab53e74b7e5cb53",
46
- "type": "function",
47
- "z": "8d3bffe93912093b",
48
- "name": "Connection Process",
49
- "func": "const device_name = msg.payload.device_name;\nconst device_type = msg.payload.device_type;\nconst payload = msg.payload.value;\n\nif (typeof payload?.active !== 'boolean') {\n const connection_error = flow.get('connection_error') || 0;\n flow.set('connection_error', connection_error + 1);\n\n return null;\n}\n\nconst is_active = payload.active;\nmsg.topic = is_active ? 'v1/gateway/connect' : 'v1/gateway/disconnect';\nmsg.payload = is_active ? { device: device_name, type: device_type } : { device: device_name };\n\nconst connection_connected = flow.get('connection_connected') || 0;\nconst connection_disconnected = flow.get('connection_disconnected') || 0;\nconst connection_success = flow.get('connection_success') || 0;\nif (is_active) {\n flow.set('connection_connected', connection_connected + 1);\n} else {\n flow.set('connection_disconnected', connection_disconnected + 1);\n}\nflow.set('connection_success', connection_success + 1);\n\nreturn msg;",
50
- "outputs": 1,
51
- "timeout": 0,
52
- "noerr": 0,
53
- "initialize": "",
54
- "finalize": "",
55
- "libs": [],
56
- "x": 1320,
57
- "y": 520,
58
- "wires": [
59
- [
60
- "a9dd9c6e8b0c3ef8"
61
- ]
62
- ]
63
- },
64
- {
65
- "id": "0c9017a47fbd43e3",
66
- "type": "switch",
67
- "z": "8d3bffe93912093b",
68
- "name": "Switch API",
69
- "property": "payload.api_method",
70
- "propertyType": "msg",
71
- "rules": [
72
- {
73
- "t": "eq",
74
- "v": "connection",
75
- "vt": "str"
76
- },
77
- {
78
- "t": "eq",
79
- "v": "attributes",
80
- "vt": "str"
81
- },
82
- {
83
- "t": "eq",
84
- "v": "telemetry",
85
- "vt": "str"
86
- }
87
- ],
88
- "checkall": "true",
89
- "repair": false,
90
- "outputs": 3,
91
- "x": 1050,
92
- "y": 560,
93
- "wires": [
94
- [
95
- "aab53e74b7e5cb53"
96
- ],
97
- [
98
- "7e858adb86eafa1c"
99
- ],
100
- [
101
- "bcfc701b1b986ff3"
102
- ]
103
- ]
104
- },
105
- {
106
- "id": "aef5609072e8f7cf",
107
- "type": "function",
108
- "z": "8d3bffe93912093b",
109
- "name": "Summary Status",
110
- "func": "const status = flow.get('status') || { fill: \"gray\", dot: \"fill\" }\n\nmsg = {};\nmsg.status = {\n fill: status.fill,\n shape: status.shape,\n text: status.text\n};\n\nnode.status(msg.status)\n\nreturn msg;",
111
- "outputs": 1,
112
- "timeout": 0,
113
- "noerr": 0,
114
- "initialize": "",
115
- "finalize": "",
116
- "libs": [],
117
- "x": 2020,
118
- "y": 660,
119
- "wires": [
120
- []
121
- ]
122
- },
123
- {
124
- "id": "dc4e55611ccff866",
125
- "type": "delay",
126
- "z": "8d3bffe93912093b",
127
- "name": "limit message",
128
- "pauseType": "rate",
129
- "timeout": "5",
130
- "timeoutUnits": "seconds",
131
- "rate": "1",
132
- "nbRateUnits": "0.5",
133
- "rateUnits": "second",
134
- "randomFirst": "1",
135
- "randomLast": "5",
136
- "randomUnits": "seconds",
137
- "drop": false,
138
- "allowrate": false,
139
- "outputs": 1,
140
- "x": 2040,
141
- "y": 520,
142
- "wires": [
143
- [
144
- "ea599d3aca06a643"
145
- ]
146
- ]
147
- },
148
- {
149
- "id": "7e858adb86eafa1c",
150
- "type": "function",
151
- "z": "8d3bffe93912093b",
152
- "name": "Attributes Process",
153
- "func": "const device_name = msg.payload.device_name;\nconst payload = msg.payload.value;\n\nif (!device_name || msg.payload == null) {\n const attributes_error = flow.get('attributes_error') || 0;\n flow.set('attributes_error', attributes_error + 1);\n\n return null;\n}\n\nmsg.topic = 'v1/gateway/attributes';\nmsg.payload = { [device_name]: payload };\n\nconst attributes_success = flow.get('attributes_success') || 0;\nflow.set('attributes_success', attributes_success + 1);\n\nreturn msg;",
154
- "outputs": 1,
155
- "timeout": 0,
156
- "noerr": 0,
157
- "initialize": "",
158
- "finalize": "",
159
- "libs": [],
160
- "x": 1310,
161
- "y": 560,
162
- "wires": [
163
- [
164
- "a9dd9c6e8b0c3ef8"
165
- ]
166
- ]
167
- },
168
- {
169
- "id": "cee336a87dd1a38f",
170
- "type": "split",
171
- "z": "8d3bffe93912093b",
172
- "name": "Split Values",
173
- "splt": "\\n",
174
- "spltType": "str",
175
- "arraySplt": "5",
176
- "arraySpltType": "len",
177
- "stream": false,
178
- "addname": "",
179
- "property": "payload.split",
180
- "x": 1510,
181
- "y": 600,
182
- "wires": [
183
- [
184
- "b24e3d9340162324"
185
- ]
186
- ]
187
- },
188
- {
189
- "id": "bcfc701b1b986ff3",
190
- "type": "function",
191
- "z": "8d3bffe93912093b",
192
- "name": "Telemetry Process",
193
- "func": "let device_name = msg.payload.device_name\nconst payload = Array.isArray(msg.payload.value) ? msg.payload.value : [msg.payload.value];\n\nif (!device_name || typeof msg.payload == undefined) {\n const telemetry_error = flow.get('telemetry_error') || 0;\n flow.set('telemetry_error', telemetry_error + 1);\n return null;\n}\n\n/* Temporary for splittring payload */\nmsg.device_name = device_name;\ndevice_name = \"split\";\n\nmsg.topic = 'v1/gateway/telemetry';\nmsg.payload = { [device_name]: payload };\n\nconst telemetry_success = flow.get('telemetry_success') || 0;\nflow.set('telemetry_success', telemetry_success + 1);\n\nreturn msg;",
194
- "outputs": 1,
195
- "timeout": 0,
196
- "noerr": 0,
197
- "initialize": "",
198
- "finalize": "",
199
- "libs": [],
200
- "x": 1310,
201
- "y": 600,
202
- "wires": [
203
- [
204
- "cee336a87dd1a38f"
205
- ]
206
- ]
207
- },
208
- {
209
- "id": "b24e3d9340162324",
210
- "type": "function",
211
- "z": "8d3bffe93912093b",
212
- "name": "Return Device Name",
213
- "func": "const device_name = msg.device_name;\nconst data_array = msg.payload.split;\n\nmsg.payload = {\n [device_name]: data_array\n};\n\nreturn msg;\n",
214
- "outputs": 1,
215
- "timeout": 0,
216
- "noerr": 0,
217
- "initialize": "",
218
- "finalize": "",
219
- "libs": [],
220
- "x": 1740,
221
- "y": 600,
222
- "wires": [
223
- [
224
- "a9dd9c6e8b0c3ef8"
225
- ]
226
- ]
227
- },
228
- {
229
- "id": "3380c50a90b10d49",
230
- "type": "status",
231
- "z": "8d3bffe93912093b",
232
- "name": "",
233
- "scope": [
234
- "ea599d3aca06a643"
235
- ],
236
- "x": 1560,
237
- "y": 660,
238
- "wires": [
239
- [
240
- "af3fc41d0edfe224"
241
- ]
242
- ]
243
- },
244
- {
245
- "id": "af3fc41d0edfe224",
246
- "type": "function",
247
- "z": "8d3bffe93912093b",
248
- "name": "MQTT Publish Status",
249
- "func": "flow.set(\"status\", msg.status)\n\nreturn msg;",
250
- "outputs": 1,
251
- "timeout": 0,
252
- "noerr": 0,
253
- "initialize": "",
254
- "finalize": "",
255
- "libs": [],
256
- "x": 1760,
257
- "y": 660,
258
- "wires": [
259
- [
260
- "aef5609072e8f7cf"
261
- ]
262
- ]
263
- },
264
- {
265
- "id": "4b7e9a3f7a1c5324",
266
- "type": "function",
267
- "z": "8d3bffe93912093b",
268
- "name": "Format Device Name",
269
- "func": "let oldKey = msg.payload.device_name;\nlet newKey = oldKey.replace(/_/g, \"-\").toUpperCase();\nmsg.payload.device_name = newKey;\nreturn msg;\n",
270
- "outputs": 1,
271
- "timeout": 0,
272
- "noerr": 0,
273
- "initialize": "",
274
- "finalize": "",
275
- "libs": [],
276
- "x": 580,
277
- "y": 560,
278
- "wires": [
279
- [
280
- "7689c6c186fb5477"
281
- ]
282
- ]
283
- },
284
- {
285
- "id": "7689c6c186fb5477",
286
- "type": "function",
287
- "z": "8d3bffe93912093b",
288
- "name": "Check Database",
289
- "func": "const flexiot_devices = global.get(\"flexiot_devices\") || [];\nconst device_name = msg.payload.device_name;\n\nif (!flexiot_devices.includes(device_name)) {\n msg.payload.api_method = \"connection\";\n msg.payload.value.active = true;\n\n if (device_name.includes(\"IR\")) {\n msg.payload.device_type = \"PowerSense - IR Blaster Device\";\n }\n\n if (device_name.includes(\"METER\")) {\n msg.payload.device_type = \"PowerSense - Meter Device\";\n }\n\n if (device_name.includes(\"SWITCH\")) {\n msg.payload.device_type = \"PowerSense - Energy Device\";\n }\n\n if (device_name.includes(\"TEMP\")) {\n msg.payload.device_type = \"PowerSense - Temperature Sensor\";\n }\n\n if (device_name.includes(\"DOOR\")) {\n msg.payload.device_type = \"PowerSense - Door Sensor\";\n }\n\n if (device_name.includes(\"DR502\")) {\n msg.payload.device_type = \"KC-LINK - Stand Alone\";\n }\n\n flexiot_devices.push(device_name);\n global.set(\"flexiot_devices\", flexiot_devices);\n} \n\nreturn msg;\n\n// PZEM-004T — Single-phase energy monitor\n// JSY-MK-354 — 3-phase energy meter\n// NGSC-430 — Kobelindo compressor controller\n// TUF-2000 — Ultrasonic flow / power meter\n// XY-MD02",
290
- "outputs": 1,
291
- "timeout": 0,
292
- "noerr": 0,
293
- "initialize": "",
294
- "finalize": "",
295
- "libs": [],
296
- "x": 830,
297
- "y": 560,
298
- "wires": [
299
- [
300
- "0c9017a47fbd43e3"
301
- ]
302
- ]
303
- },
304
- {
305
- "id": "ea599d3aca06a643",
306
- "type": "mqtt out",
307
- "z": "8d3bffe93912093b",
308
- "name": "Out",
309
- "topic": "",
310
- "qos": "",
311
- "retain": "",
312
- "respTopic": "",
313
- "contentType": "",
314
- "userProps": "",
315
- "correl": "",
316
- "expiry": "",
317
- "broker": "${Server}",
318
- "x": 2230,
319
- "y": 520,
320
- "wires": []
321
- },
322
- {
323
- "id": "a9dd9c6e8b0c3ef8",
324
- "type": "junction",
325
- "z": "8d3bffe93912093b",
326
- "x": 1900,
327
- "y": 520,
328
- "wires": [
329
- [
330
- "dc4e55611ccff866",
331
- "aef5609072e8f7cf"
332
- ]
333
- ]
334
- }
335
- ]
336
- }
1
+ {
2
+ "id": "8d3bffe93912093b",
3
+ "type": "subflow",
4
+ "name": "gateway out",
5
+ "info": "Use the [Thingsboard MQTT Gateway API](https://thingsboard.io/docs/reference/gateway-mqtt-api) direct integration with Node-RED.\r\n## Details \r\n\r\n### Node Server\r\n\r\nThis node uses the same configuration as the MQTT broker. \r\nSet the broker URL to the ThingsBoard server, and create a device as a gateway in ThingsBoard first. Then copy the device access token into this MQTT configuration.\r\n\r\n> Use the device name as the configuration name.\r\n### Node Status \r\n\r\nThe node status color indicates the connection status to the Thingsboard platform.\r\n### Node Payload\r\n\r\nMessage properties:\r\n\r\n: api_method (string) : Must be set to \"connection\" / \"attributes\" / \"telemetry\" depends on the target values. \r\n: device_name (string) : Device name to be targeted in Device List on FlexIoT.\r\n: device_type [optional] (string) : Device type, required for first connection. See FlexIoT Device Profile.\r\n: value (object) : Values based on the `api_method`\r\n### Connection\r\nUsed to connect a device to the Thingsboard platform.\r\nIt handles the connection process, including authentication and device registration.\r\n\r\nExample:\r\n```json\r\n{\r\n  \"api_method\": \"connection\",\r\n  \"device_name\": \"device_01\",\r\n  \"device_type\": \"Device A\",\r\n  \"value\": {\r\n    \"active\": true\r\n  }\r\n}\r\n```\r\n\r\n### Attributes \r\nUsed to set device attributes.\r\nIt allows you to send key-value pairs as attributes to the device.\r\n\r\nExample:\r\n```json\r\n{\r\n  \"api_method\": \"attributes\",\r\n  \"device_name\": \"device_01\",\r\n  \"value\": {\r\n    \"attribute_key_1\": \"value_1\",\r\n    \"attribute_key_2\": \"value_2\"\r\n  }\r\n}\r\n```\r\n\r\n### Telemetry\r\nUsed to send telemetry data to the device.\r\nIt allows you to send various types of telemetry data.\r\n\r\nSingle object example:\r\n```json\r\n{\r\n  \"api_method\": \"telemetry\",\r\n  \"device_name\": \"device_01\",\r\n  \"value\": {\r\n    \"telemetry_key_1\": \"value_1\",\r\n    \"telemetry_key_2\": \"value_2\"\r\n  }\r\n}\r\n```\r\nSingle object with `timestamp` example:\r\n```json\r\n{\r\n  \"api_method\": \"telemetry\",\r\n  \"device_name\": \"device_01\",\r\n  \"value\": {\r\n\t\"ts\": 1700000000000,\r\n\t\"values\": {\r\n\t\t\"telemetry_key_1\": \"value_1\",\r\n\t    \"telemetry_key_2\": \"value_2\"\r\n\t}\r\n  }\r\n}\r\n```\r\nArray example:\r\n```json\r\n{\r\n  \"api_method\": \"telemetry\",\r\n  \"device_name\": \"device_01\",\r\n  \"value\": [\r\n    {\r\n      \"ts\": 1700000000000,\r\n      \"values\": {\r\n        \"telemetry_key_1\": \"value_1\",\r\n        \"telemetry_key_2\": \"value_2\"\r\n      }\r\n    },\r\n    {\r\n      \"ts\": 1700000001000,\r\n      \"values\": {\r\n        \"telemetry_key_1\": \"value_3\",\r\n        \"telemetry_key_2\": \"value_4\"\r\n      }\r\n    }\r\n  ]\r\n}\r\n```\r\n### References\r\n* [Thingsboard MQTT Gateway API](https://thingsboard.io/docs/reference/gateway-mqtt-api)",
6
+ "category": "network",
7
+ "in": [
8
+ {
9
+ "x": 360,
10
+ "y": 560,
11
+ "wires": [
12
+ {
13
+ "id": "4eaeb645d8730373"
14
+ }
15
+ ]
16
+ }
17
+ ],
18
+ "out": [],
19
+ "env": [
20
+ {
21
+ "name": "Server",
22
+ "type": "mqtt-broker",
23
+ "value": "",
24
+ "ui": {
25
+ "icon": "font-awesome/fa-globe",
26
+ "type": "conf-types"
27
+ }
28
+ }
29
+ ],
30
+ "meta": {
31
+ "module": "gateway-out",
32
+ "type": "network",
33
+ "version": "1.0.0",
34
+ "author": "farisrfp <farisrafp@gmail.com>",
35
+ "license": "MIT"
36
+ },
37
+ "color": "#8083fa",
38
+ "inputLabels": [
39
+ "paylod-in"
40
+ ],
41
+ "icon": "node-red/bridge-dash.svg",
42
+ "status": {
43
+ "x": 1780,
44
+ "y": 800,
45
+ "wires": [
46
+ {
47
+ "id": "fe35d287f438b97e",
48
+ "port": 0
49
+ }
50
+ ]
51
+ },
52
+ "flow": [
53
+ {
54
+ "id": "d25b701d3135153b",
55
+ "type": "function",
56
+ "z": "8d3bffe93912093b",
57
+ "g": "ea3c50801e2c2103",
58
+ "name": "Connect",
59
+ "func": "const device_name = msg.payload.device_name;\nconst device_type = msg.payload.device_type;\nconst payload = msg.payload.value;\n\nif (typeof payload?.active !== 'boolean') {\n node.error(\"Payload for connection is not valid\");\n\n return null;\n}\n\nconst is_active = payload.active;\nmsg.topic = is_active ? 'v1/gateway/connect' : 'v1/gateway/disconnect';\nmsg.payload = is_active ? { device: device_name, type: device_type } : { device: device_name };\n\nreturn msg;",
60
+ "outputs": 1,
61
+ "timeout": 0,
62
+ "noerr": 0,
63
+ "initialize": "",
64
+ "finalize": "",
65
+ "libs": [],
66
+ "x": 1160,
67
+ "y": 560,
68
+ "wires": [
69
+ [
70
+ "38632d8a682e173c"
71
+ ]
72
+ ]
73
+ },
74
+ {
75
+ "id": "40d26740997854db",
76
+ "type": "switch",
77
+ "z": "8d3bffe93912093b",
78
+ "g": "ea3c50801e2c2103",
79
+ "name": "Switch API",
80
+ "property": "payload.api_method",
81
+ "propertyType": "msg",
82
+ "rules": [
83
+ {
84
+ "t": "eq",
85
+ "v": "connection",
86
+ "vt": "str"
87
+ },
88
+ {
89
+ "t": "eq",
90
+ "v": "attributes",
91
+ "vt": "str"
92
+ },
93
+ {
94
+ "t": "eq",
95
+ "v": "telemetry",
96
+ "vt": "str"
97
+ }
98
+ ],
99
+ "checkall": "true",
100
+ "repair": false,
101
+ "outputs": 3,
102
+ "x": 870,
103
+ "y": 640,
104
+ "wires": [
105
+ [
106
+ "d25b701d3135153b"
107
+ ],
108
+ [
109
+ "03f287b6e0612e55"
110
+ ],
111
+ [
112
+ "348e52544251e693"
113
+ ]
114
+ ]
115
+ },
116
+ {
117
+ "id": "38632d8a682e173c",
118
+ "type": "delay",
119
+ "z": "8d3bffe93912093b",
120
+ "g": "ea3c50801e2c2103",
121
+ "name": "limit message",
122
+ "pauseType": "rate",
123
+ "timeout": "5",
124
+ "timeoutUnits": "seconds",
125
+ "rate": "1",
126
+ "nbRateUnits": "0.5",
127
+ "rateUnits": "second",
128
+ "randomFirst": "1",
129
+ "randomLast": "5",
130
+ "randomUnits": "seconds",
131
+ "drop": false,
132
+ "allowrate": false,
133
+ "outputs": 1,
134
+ "x": 1480,
135
+ "y": 620,
136
+ "wires": [
137
+ [
138
+ "1588f20f9476689c"
139
+ ]
140
+ ]
141
+ },
142
+ {
143
+ "id": "03f287b6e0612e55",
144
+ "type": "function",
145
+ "z": "8d3bffe93912093b",
146
+ "g": "ea3c50801e2c2103",
147
+ "name": "Attributes",
148
+ "func": "const device_name = msg.payload.device_name;\nconst payload = msg.payload.value;\n\nif (!device_name || msg.payload == null) {\n node.error(\"Payload for connection is not valid\");\n\n return null;\n}\n\nmsg.topic = 'v1/gateway/attributes';\nmsg.payload = { [device_name]: payload };\n\nreturn msg;",
149
+ "outputs": 1,
150
+ "timeout": 0,
151
+ "noerr": 0,
152
+ "initialize": "",
153
+ "finalize": "",
154
+ "libs": [],
155
+ "x": 1160,
156
+ "y": 620,
157
+ "wires": [
158
+ [
159
+ "38632d8a682e173c"
160
+ ]
161
+ ]
162
+ },
163
+ {
164
+ "id": "947f3125090f22c7",
165
+ "type": "split",
166
+ "z": "8d3bffe93912093b",
167
+ "g": "ea3c50801e2c2103",
168
+ "name": "Split",
169
+ "splt": "\\n",
170
+ "spltType": "str",
171
+ "arraySplt": "5",
172
+ "arraySpltType": "len",
173
+ "stream": false,
174
+ "addname": "",
175
+ "property": "payload.split",
176
+ "x": 650,
177
+ "y": 760,
178
+ "wires": [
179
+ [
180
+ "1d72b39233427fd0"
181
+ ]
182
+ ]
183
+ },
184
+ {
185
+ "id": "348e52544251e693",
186
+ "type": "function",
187
+ "z": "8d3bffe93912093b",
188
+ "g": "ea3c50801e2c2103",
189
+ "name": "Telemetry",
190
+ "func": "let device_name = msg.payload.device_name\nconst payload = Array.isArray(msg.payload.value) ? msg.payload.value : [msg.payload.value];\n\nif (!device_name || typeof msg.payload == undefined) {\n node.error(\"Payload for attibutes is not valid\");\n \n return null;\n}\n\n/* Temporary for splittring payload */\nmsg.device_name = device_name;\ndevice_name = \"split\";\n\nmsg.topic = 'v1/gateway/telemetry';\nmsg.payload = { [device_name]: payload };\n\nreturn msg;",
191
+ "outputs": 1,
192
+ "timeout": 0,
193
+ "noerr": 0,
194
+ "initialize": "",
195
+ "finalize": "",
196
+ "libs": [],
197
+ "x": 1160,
198
+ "y": 680,
199
+ "wires": [
200
+ [
201
+ "5655fcdeab1760eb"
202
+ ]
203
+ ]
204
+ },
205
+ {
206
+ "id": "1d72b39233427fd0",
207
+ "type": "function",
208
+ "z": "8d3bffe93912093b",
209
+ "g": "ea3c50801e2c2103",
210
+ "name": "Return Device Name",
211
+ "func": "const device_name = msg.device_name;\nconst data_array = msg.payload.split;\n\nmsg.payload = {\n [device_name]: data_array\n};\n\nreturn msg;\n",
212
+ "outputs": 1,
213
+ "timeout": 0,
214
+ "noerr": 0,
215
+ "initialize": "",
216
+ "finalize": "",
217
+ "libs": [],
218
+ "x": 840,
219
+ "y": 760,
220
+ "wires": [
221
+ [
222
+ "64630d49fda7bc36"
223
+ ]
224
+ ]
225
+ },
226
+ {
227
+ "id": "4eaeb645d8730373",
228
+ "type": "function",
229
+ "z": "8d3bffe93912093b",
230
+ "g": "ea3c50801e2c2103",
231
+ "name": "Format Device Name",
232
+ "func": "let oldKey = msg.payload.device_name;\nlet newKey = oldKey.replace(/_/g, \"-\").toUpperCase();\nmsg.payload.device_name = newKey;\n\nreturn msg;",
233
+ "outputs": 1,
234
+ "timeout": 0,
235
+ "noerr": 0,
236
+ "initialize": "",
237
+ "finalize": "",
238
+ "libs": [],
239
+ "x": 600,
240
+ "y": 560,
241
+ "wires": [
242
+ [
243
+ "c1f6b2fdf16047f8"
244
+ ]
245
+ ]
246
+ },
247
+ {
248
+ "id": "c1f6b2fdf16047f8",
249
+ "type": "function",
250
+ "z": "8d3bffe93912093b",
251
+ "g": "ea3c50801e2c2103",
252
+ "name": "Check Database",
253
+ "func": "const flexiot_devices = global.get(\"flexiot_devices\") || [];\nconst device_name = msg.payload.device_name;\n\nif (!flexiot_devices.includes(device_name)) {\n msg.payload.api_method = \"connection\";\n msg.payload.value.active = true;\n\n if (device_name.includes(\"IR\")) {\n msg.payload.device_type = \"PowerSense - IR Blaster Device\";\n }\n\n if (device_name.includes(\"METER\")) {\n msg.payload.device_type = \"PowerSense - Meter Device\";\n }\n\n if (device_name.includes(\"SWITCH\")) {\n msg.payload.device_type = \"PowerSense - Energy Device\";\n }\n\n if (device_name.includes(\"TEMP\")) {\n msg.payload.device_type = \"PowerSense - Temperature Sensor\";\n }\n\n if (device_name.includes(\"DOOR\")) {\n msg.payload.device_type = \"PowerSense - Door Sensor\";\n }\n\n if (device_name.includes(\"DR502\")) {\n msg.payload.device_type = \"KC-LINK - Stand Alone\";\n }\n\n flexiot_devices.push(device_name);\n global.set(\"flexiot_devices\", flexiot_devices);\n} \n\nreturn msg;",
254
+ "outputs": 1,
255
+ "timeout": 0,
256
+ "noerr": 0,
257
+ "initialize": "",
258
+ "finalize": "",
259
+ "libs": [],
260
+ "x": 850,
261
+ "y": 560,
262
+ "wires": [
263
+ [
264
+ "40d26740997854db"
265
+ ]
266
+ ]
267
+ },
268
+ {
269
+ "id": "b6fad5c9837dd745",
270
+ "type": "link in",
271
+ "z": "8d3bffe93912093b",
272
+ "g": "ea3c50801e2c2103",
273
+ "name": "link in 2",
274
+ "links": [],
275
+ "x": 545,
276
+ "y": 760,
277
+ "wires": [
278
+ [
279
+ "947f3125090f22c7"
280
+ ]
281
+ ]
282
+ },
283
+ {
284
+ "id": "5655fcdeab1760eb",
285
+ "type": "link call",
286
+ "z": "8d3bffe93912093b",
287
+ "g": "ea3c50801e2c2103",
288
+ "name": "Split",
289
+ "links": [
290
+ "b6fad5c9837dd745"
291
+ ],
292
+ "linkType": "static",
293
+ "timeout": "1",
294
+ "x": 1310,
295
+ "y": 680,
296
+ "wires": [
297
+ [
298
+ "38632d8a682e173c"
299
+ ]
300
+ ]
301
+ },
302
+ {
303
+ "id": "64630d49fda7bc36",
304
+ "type": "link out",
305
+ "z": "8d3bffe93912093b",
306
+ "g": "ea3c50801e2c2103",
307
+ "name": "link out 2",
308
+ "mode": "return",
309
+ "links": [],
310
+ "x": 985,
311
+ "y": 760,
312
+ "wires": []
313
+ },
314
+ {
315
+ "id": "1588f20f9476689c",
316
+ "type": "mqtt out",
317
+ "z": "8d3bffe93912093b",
318
+ "g": "ea3c50801e2c2103",
319
+ "name": "Out",
320
+ "topic": "",
321
+ "qos": "",
322
+ "retain": "",
323
+ "respTopic": "",
324
+ "contentType": "",
325
+ "userProps": "",
326
+ "correl": "",
327
+ "expiry": "",
328
+ "broker": "${Server}",
329
+ "x": 1650,
330
+ "y": 620,
331
+ "wires": []
332
+ },
333
+ {
334
+ "id": "110bd7c24d907f5d",
335
+ "type": "inject",
336
+ "z": "8d3bffe93912093b",
337
+ "g": "ea3c50801e2c2103",
338
+ "name": "Automatic",
339
+ "props": [
340
+ {
341
+ "p": "payload"
342
+ },
343
+ {
344
+ "p": "topic",
345
+ "vt": "str"
346
+ }
347
+ ],
348
+ "repeat": "60",
349
+ "crontab": "",
350
+ "once": true,
351
+ "onceDelay": "1",
352
+ "topic": "",
353
+ "payload": "",
354
+ "payloadType": "date",
355
+ "x": 1410,
356
+ "y": 760,
357
+ "wires": [
358
+ [
359
+ "fe35d287f438b97e"
360
+ ]
361
+ ]
362
+ },
363
+ {
364
+ "id": "f72d1c9fa04306d6",
365
+ "type": "status",
366
+ "z": "8d3bffe93912093b",
367
+ "g": "ea3c50801e2c2103",
368
+ "name": "Status",
369
+ "scope": [
370
+ "1588f20f9476689c"
371
+ ],
372
+ "x": 1250,
373
+ "y": 800,
374
+ "wires": [
375
+ [
376
+ "e4a1d3310f3f0e8a"
377
+ ]
378
+ ]
379
+ },
380
+ {
381
+ "id": "e4a1d3310f3f0e8a",
382
+ "type": "function",
383
+ "z": "8d3bffe93912093b",
384
+ "g": "ea3c50801e2c2103",
385
+ "name": "Set Status",
386
+ "func": "const status = {};\n\nstatus.fill = msg.status.fill;\nstatus.shape = msg.status.shape;\nstatus.text = msg.status.text;\n\nflow.set(\"status\", status);\n\nreturn msg;",
387
+ "outputs": 1,
388
+ "timeout": 0,
389
+ "noerr": 0,
390
+ "initialize": "",
391
+ "finalize": "",
392
+ "libs": [],
393
+ "x": 1410,
394
+ "y": 800,
395
+ "wires": [
396
+ [
397
+ "fe35d287f438b97e"
398
+ ]
399
+ ]
400
+ },
401
+ {
402
+ "id": "fe35d287f438b97e",
403
+ "type": "function",
404
+ "z": "8d3bffe93912093b",
405
+ "g": "ea3c50801e2c2103",
406
+ "name": "Summary Status",
407
+ "func": "const status = flow.get('status') || { fill: \"gray\", shape: \"fill\", text: \"Status not found!\" }\n\nmsg = {};\n// msg.payload = {\n// fill: \"green\",\n// shape: \"dot\",\n// text: \"connectedd\"\n// };\nmsg.payload = {\n fill: status.fill,\n shape: status.shape,\n text: status.text\n};\n\n// node.status(msg.status)\n\nreturn msg;",
408
+ "outputs": 1,
409
+ "timeout": 0,
410
+ "noerr": 0,
411
+ "initialize": "",
412
+ "finalize": "",
413
+ "libs": [],
414
+ "x": 1600,
415
+ "y": 800,
416
+ "wires": [
417
+ []
418
+ ]
419
+ },
420
+ {
421
+ "id": "ea3c50801e2c2103",
422
+ "type": "group",
423
+ "z": "8d3bffe93912093b",
424
+ "name": "",
425
+ "style": {
426
+ "stroke": "#000000",
427
+ "fill": "#ffffff",
428
+ "label": true
429
+ },
430
+ "nodes": [
431
+ "d25b701d3135153b",
432
+ "40d26740997854db",
433
+ "38632d8a682e173c",
434
+ "03f287b6e0612e55",
435
+ "947f3125090f22c7",
436
+ "348e52544251e693",
437
+ "1d72b39233427fd0",
438
+ "4eaeb645d8730373",
439
+ "c1f6b2fdf16047f8",
440
+ "b6fad5c9837dd745",
441
+ "5655fcdeab1760eb",
442
+ "64630d49fda7bc36",
443
+ "1588f20f9476689c",
444
+ "110bd7c24d907f5d",
445
+ "f72d1c9fa04306d6",
446
+ "e4a1d3310f3f0e8a",
447
+ "fe35d287f438b97e"
448
+ ],
449
+ "x": 474,
450
+ "y": 519,
451
+ "w": 1252,
452
+ "h": 322
453
+ }
454
+ ]
455
+ }
package/package.json CHANGED
@@ -1,21 +1,21 @@
1
- {
2
- "name": "node-red-contrib-thingsboard-gateway",
3
- "version": "0.2.0",
4
- "description": "Node-RED node for sending data to ThingsBoard via Gateway Device using MQTT protocol.",
5
- "keywords": [
6
- "node-red",
7
- "node-red-contrib",
8
- "thingsboard",
9
- "mqtt",
10
- "iot"
11
- ],
12
- "license": "Apache-2.0",
13
- "engines": {
14
- "node": ">=16"
15
- },
16
- "node-red": {
17
- "nodes": {
18
- "gateway-out": "nodes/gateway_out.js"
19
- }
20
- }
21
- }
1
+ {
2
+ "name": "node-red-contrib-thingsboard-gateway",
3
+ "version": "1.0.0",
4
+ "description": "Node-RED node for sending data to ThingsBoard via Gateway Device using MQTT protocol.",
5
+ "keywords": [
6
+ "node-red",
7
+ "node-red-contrib",
8
+ "thingsboard",
9
+ "mqtt",
10
+ "iot"
11
+ ],
12
+ "license": "Apache-2.0",
13
+ "engines": {
14
+ "node": ">=16"
15
+ },
16
+ "node-red": {
17
+ "nodes": {
18
+ "gateway-out": "nodes/gateway_out.js"
19
+ }
20
+ }
21
+ }