node-red-contrib-alarm-ultimate 0.1.0 → 0.1.2

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 (35) hide show
  1. package/README.md +87 -13
  2. package/docs/images/alarm-panel-mock.svg +114 -0
  3. package/docs/images/banner.svg +63 -0
  4. package/docs/images/flow-overview.svg +85 -0
  5. package/examples/README.md +32 -11
  6. package/examples/alarm-ultimate-basic.json +0 -1
  7. package/examples/alarm-ultimate-dashboard-controls.json +575 -0
  8. package/examples/alarm-ultimate-dashboard-v2.json +762 -0
  9. package/examples/alarm-ultimate-dashboard.json +3 -3
  10. package/flowfuse-node-red-dashboard-1.30.2.tgz +0 -0
  11. package/nodes/AlarmSystemUltimate.html +174 -85
  12. package/nodes/AlarmSystemUltimate.js +39 -8
  13. package/nodes/AlarmUltimateInputAdapter.html +304 -0
  14. package/nodes/AlarmUltimateInputAdapter.js +188 -0
  15. package/nodes/AlarmUltimateSiren.html +3 -3
  16. package/nodes/AlarmUltimateSiren.js +6 -2
  17. package/nodes/AlarmUltimateState.html +3 -3
  18. package/nodes/AlarmUltimateState.js +6 -2
  19. package/nodes/AlarmUltimateZone.html +11 -6
  20. package/nodes/AlarmUltimateZone.js +27 -6
  21. package/nodes/icons/alarm-ultimate-siren.svg +6 -0
  22. package/nodes/icons/alarm-ultimate-state.svg +5 -0
  23. package/nodes/icons/alarm-ultimate-zone.svg +5 -0
  24. package/nodes/icons/alarm-ultimate.svg +6 -0
  25. package/nodes/presets/input-adapter/ax-pro-hikvision-ultimate.js +34 -0
  26. package/nodes/presets/input-adapter/boolean-from-payload.js +10 -0
  27. package/nodes/presets/input-adapter/ha-on-off.js +24 -0
  28. package/nodes/presets/input-adapter/knx-ultimate.js +29 -0
  29. package/nodes/presets/input-adapter/passthrough.js +7 -0
  30. package/package.json +5 -4
  31. package/test/alarm-system.spec.js +51 -0
  32. package/test/input-adapter.spec.js +243 -0
  33. package/test/output-nodes.spec.js +3 -0
  34. package/tools/alarm-json-mapper.html +1882 -460
  35. package/tools/alarm-panel.html +630 -131
@@ -0,0 +1,575 @@
1
+ [
2
+ {
3
+ "id": "b81f9a4b2f9c1a10",
4
+ "type": "tab",
5
+ "label": "Alarm Ultimate - Dashboard (Panel + Controls)",
6
+ "disabled": false,
7
+ "info": ""
8
+ },
9
+ {
10
+ "id": "2f9d4c2b8a1c9b70",
11
+ "type": "comment",
12
+ "z": "b81f9a4b2f9c1a10",
13
+ "name": "Requires node-red-dashboard",
14
+ "info": "Install `node-red-dashboard`, then import this flow.\n\nThe iframe uses a *relative* URL so it works even if Node-RED is hosted under a path prefix (eg Home Assistant Ingress).\nIf you changed `httpAdminRoot` / `httpRoot`, adjust the iframe URL accordingly.\n\nTip: Open the panel directly at `alarm-ultimate/alarm-panel?id=<alarmNodeId>` to test outside Dashboard.",
15
+ "x": 250,
16
+ "y": 60,
17
+ "wires": []
18
+ },
19
+ {
20
+ "id": "d9078c5d2b1a4f30",
21
+ "type": "ui_tab",
22
+ "name": "Alarm Ultimate",
23
+ "icon": "dashboard",
24
+ "disabled": false,
25
+ "hidden": false
26
+ },
27
+ {
28
+ "id": "a1a3c4e5f6078890",
29
+ "type": "ui_group",
30
+ "name": "Panel",
31
+ "tab": "d9078c5d2b1a4f30",
32
+ "order": 1,
33
+ "disp": true,
34
+ "width": "12",
35
+ "collapse": false,
36
+ "className": ""
37
+ },
38
+ {
39
+ "id": "b2b3c4e5f6078891",
40
+ "type": "ui_group",
41
+ "name": "Controls",
42
+ "tab": "d9078c5d2b1a4f30",
43
+ "order": 2,
44
+ "disp": true,
45
+ "width": "12",
46
+ "collapse": false,
47
+ "className": ""
48
+ },
49
+ {
50
+ "id": "c3c3c4e5f6078892",
51
+ "type": "ui_group",
52
+ "name": "Sensor simulator",
53
+ "tab": "d9078c5d2b1a4f30",
54
+ "order": 3,
55
+ "disp": true,
56
+ "width": "12",
57
+ "collapse": false,
58
+ "className": ""
59
+ },
60
+ {
61
+ "id": "d0c1b2a3f4e50617",
62
+ "type": "AlarmSystemUltimate",
63
+ "z": "b81f9a4b2f9c1a10",
64
+ "name": "Home Alarm",
65
+ "controlTopic": "alarm",
66
+ "payloadPropName": "payload",
67
+ "persistState": true,
68
+ "requireCodeForArm": false,
69
+ "requireCodeForDisarm": false,
70
+ "armCode": "",
71
+ "duressCode": "",
72
+ "blockArmOnViolations": true,
73
+ "exitDelaySeconds": 10,
74
+ "entryDelaySeconds": 30,
75
+ "emitOpenZonesDuringArming": false,
76
+ "openZonesArmingIntervalSeconds": 1,
77
+ "openZonesRequestTopic": "alarm/listOpenZones",
78
+ "openZonesRequestIntervalSeconds": 0,
79
+ "sirenDurationSeconds": 180,
80
+ "sirenLatchUntilDisarm": false,
81
+ "sirenTopic": "alarm/siren",
82
+ "sirenOnPayload": true,
83
+ "sirenOnPayloadType": "bool",
84
+ "sirenOffPayload": false,
85
+ "sirenOffPayloadType": "bool",
86
+ "emitRestoreEvents": false,
87
+ "maxLogEntries": 50,
88
+ "zones": "[\n {\n \"id\": \"front_door\",\n \"name\": \"Front door\",\n \"topic\": \"sensor/frontdoor\",\n \"type\": \"perimeter\",\n \"entry\": true,\n \"bypassable\": true,\n \"chime\": true\n },\n {\n \"id\": \"living_pir\",\n \"name\": \"Living PIR\",\n \"topic\": \"sensor/living_pir\",\n \"type\": \"motion\",\n \"entry\": false,\n \"bypassable\": true,\n \"cooldownSeconds\": 10\n }\n]",
89
+ "x": 220,
90
+ "y": 180,
91
+ "wires": [
92
+ [
93
+ "f50b6a7c1c8b3d10"
94
+ ],
95
+ [
96
+ "f50b6a7c1c8b3d11"
97
+ ],
98
+ [],
99
+ [],
100
+ [],
101
+ [
102
+ "f50b6a7c1c8b3d12"
103
+ ],
104
+ [],
105
+ [],
106
+ []
107
+ ]
108
+ },
109
+ {
110
+ "id": "e1f2a3b4c5d60718",
111
+ "type": "ui_template",
112
+ "z": "b81f9a4b2f9c1a10",
113
+ "group": "a1a3c4e5f6078890",
114
+ "name": "Alarm Panel (embed)",
115
+ "order": 1,
116
+ "width": "12",
117
+ "height": "18",
118
+ "format": "<iframe src=\"alarm-ultimate/alarm-panel?embed=1&id=d0c1b2a3f4e50617\" style=\"width:100%; height:720px; border:0; border-radius:10px;\"></iframe>",
119
+ "storeOutMessages": false,
120
+ "fwdInMessages": false,
121
+ "resendOnRefresh": true,
122
+ "templateScope": "local",
123
+ "className": "",
124
+ "x": 520,
125
+ "y": 180
126
+ },
127
+ {
128
+ "id": "c44ac2b6af1a1e20",
129
+ "type": "ui_button",
130
+ "z": "b81f9a4b2f9c1a10",
131
+ "name": "Arm",
132
+ "group": "b2b3c4e5f6078891",
133
+ "order": 1,
134
+ "width": "3",
135
+ "height": "1",
136
+ "passthru": false,
137
+ "label": "Arm",
138
+ "tooltip": "",
139
+ "color": "white",
140
+ "bgcolor": "#ff375f",
141
+ "icon": "fa-lock",
142
+ "payload": "arm",
143
+ "payloadType": "str",
144
+ "topic": "",
145
+ "topicType": "str",
146
+ "x": 160,
147
+ "y": 320,
148
+ "wires": [
149
+ [
150
+ "c44ac2b6af1a1e2a"
151
+ ]
152
+ ]
153
+ },
154
+ {
155
+ "id": "c44ac2b6af1a1e21",
156
+ "type": "ui_button",
157
+ "z": "b81f9a4b2f9c1a10",
158
+ "name": "Disarm",
159
+ "group": "b2b3c4e5f6078891",
160
+ "order": 2,
161
+ "width": "3",
162
+ "height": "1",
163
+ "passthru": false,
164
+ "label": "Disarm",
165
+ "tooltip": "",
166
+ "color": "white",
167
+ "bgcolor": "#1f6feb",
168
+ "icon": "fa-unlock",
169
+ "payload": "disarm",
170
+ "payloadType": "str",
171
+ "topic": "",
172
+ "topicType": "str",
173
+ "x": 160,
174
+ "y": 360,
175
+ "wires": [
176
+ [
177
+ "c44ac2b6af1a1e2a"
178
+ ]
179
+ ]
180
+ },
181
+ {
182
+ "id": "c44ac2b6af1a1e22",
183
+ "type": "ui_button",
184
+ "z": "b81f9a4b2f9c1a10",
185
+ "name": "Status",
186
+ "group": "b2b3c4e5f6078891",
187
+ "order": 3,
188
+ "width": "3",
189
+ "height": "1",
190
+ "passthru": false,
191
+ "label": "Status",
192
+ "tooltip": "Emits a full snapshot on output 1",
193
+ "color": "white",
194
+ "bgcolor": "#6e7681",
195
+ "icon": "fa-info-circle",
196
+ "payload": "status",
197
+ "payloadType": "str",
198
+ "topic": "",
199
+ "topicType": "str",
200
+ "x": 160,
201
+ "y": 400,
202
+ "wires": [
203
+ [
204
+ "c44ac2b6af1a1e2a"
205
+ ]
206
+ ]
207
+ },
208
+ {
209
+ "id": "c44ac2b6af1a1e23",
210
+ "type": "ui_button",
211
+ "z": "b81f9a4b2f9c1a10",
212
+ "name": "List open zones",
213
+ "group": "b2b3c4e5f6078891",
214
+ "order": 4,
215
+ "width": "6",
216
+ "height": "1",
217
+ "passthru": false,
218
+ "label": "List open zones",
219
+ "tooltip": "Emits one message per open zone on output 9",
220
+ "color": "white",
221
+ "bgcolor": "#6e7681",
222
+ "icon": "fa-list",
223
+ "payload": "list_open_zones",
224
+ "payloadType": "str",
225
+ "topic": "",
226
+ "topicType": "str",
227
+ "x": 170,
228
+ "y": 440,
229
+ "wires": [
230
+ [
231
+ "c44ac2b6af1a1e2a"
232
+ ]
233
+ ]
234
+ },
235
+ {
236
+ "id": "c44ac2b6af1a1e24",
237
+ "type": "ui_button",
238
+ "z": "b81f9a4b2f9c1a10",
239
+ "name": "Siren on",
240
+ "group": "b2b3c4e5f6078891",
241
+ "order": 5,
242
+ "width": "3",
243
+ "height": "1",
244
+ "passthru": false,
245
+ "label": "Siren ON",
246
+ "tooltip": "",
247
+ "color": "white",
248
+ "bgcolor": "#ff9f0a",
249
+ "icon": "fa-bullhorn",
250
+ "payload": "siren_on",
251
+ "payloadType": "str",
252
+ "topic": "",
253
+ "topicType": "str",
254
+ "x": 160,
255
+ "y": 480,
256
+ "wires": [
257
+ [
258
+ "c44ac2b6af1a1e2a"
259
+ ]
260
+ ]
261
+ },
262
+ {
263
+ "id": "c44ac2b6af1a1e25",
264
+ "type": "ui_button",
265
+ "z": "b81f9a4b2f9c1a10",
266
+ "name": "Siren off",
267
+ "group": "b2b3c4e5f6078891",
268
+ "order": 6,
269
+ "width": "3",
270
+ "height": "1",
271
+ "passthru": false,
272
+ "label": "Siren OFF",
273
+ "tooltip": "",
274
+ "color": "white",
275
+ "bgcolor": "#6e7681",
276
+ "icon": "fa-bullhorn",
277
+ "payload": "siren_off",
278
+ "payloadType": "str",
279
+ "topic": "",
280
+ "topicType": "str",
281
+ "x": 160,
282
+ "y": 520,
283
+ "wires": [
284
+ [
285
+ "c44ac2b6af1a1e2a"
286
+ ]
287
+ ]
288
+ },
289
+ {
290
+ "id": "c44ac2b6af1a1e26",
291
+ "type": "ui_button",
292
+ "z": "b81f9a4b2f9c1a10",
293
+ "name": "Panic",
294
+ "group": "b2b3c4e5f6078891",
295
+ "order": 7,
296
+ "width": "3",
297
+ "height": "1",
298
+ "passthru": false,
299
+ "label": "Panic",
300
+ "tooltip": "",
301
+ "color": "white",
302
+ "bgcolor": "#d1242f",
303
+ "icon": "fa-exclamation-triangle",
304
+ "payload": "panic",
305
+ "payloadType": "str",
306
+ "topic": "",
307
+ "topicType": "str",
308
+ "x": 150,
309
+ "y": 560,
310
+ "wires": [
311
+ [
312
+ "c44ac2b6af1a1e2a"
313
+ ]
314
+ ]
315
+ },
316
+ {
317
+ "id": "c44ac2b6af1a1e27",
318
+ "type": "ui_button",
319
+ "z": "b81f9a4b2f9c1a10",
320
+ "name": "Silent panic",
321
+ "group": "b2b3c4e5f6078891",
322
+ "order": 8,
323
+ "width": "3",
324
+ "height": "1",
325
+ "passthru": false,
326
+ "label": "Silent panic",
327
+ "tooltip": "",
328
+ "color": "white",
329
+ "bgcolor": "#6e7681",
330
+ "icon": "fa-eye-slash",
331
+ "payload": "panic_silent",
332
+ "payloadType": "str",
333
+ "topic": "",
334
+ "topicType": "str",
335
+ "x": 170,
336
+ "y": 600,
337
+ "wires": [
338
+ [
339
+ "c44ac2b6af1a1e2a"
340
+ ]
341
+ ]
342
+ },
343
+ {
344
+ "id": "c44ac2b6af1a1e28",
345
+ "type": "ui_button",
346
+ "z": "b81f9a4b2f9c1a10",
347
+ "name": "Bypass front door",
348
+ "group": "b2b3c4e5f6078891",
349
+ "order": 9,
350
+ "width": "6",
351
+ "height": "1",
352
+ "passthru": false,
353
+ "label": "Bypass: front_door",
354
+ "tooltip": "",
355
+ "color": "white",
356
+ "bgcolor": "#6e7681",
357
+ "icon": "fa-ban",
358
+ "payload": "{\"command\":\"bypass\",\"zone\":\"front_door\"}",
359
+ "payloadType": "json",
360
+ "topic": "",
361
+ "topicType": "str",
362
+ "x": 180,
363
+ "y": 640,
364
+ "wires": [
365
+ [
366
+ "c44ac2b6af1a1e2a"
367
+ ]
368
+ ]
369
+ },
370
+ {
371
+ "id": "c44ac2b6af1a1e29",
372
+ "type": "ui_button",
373
+ "z": "b81f9a4b2f9c1a10",
374
+ "name": "Unbypass front door",
375
+ "group": "b2b3c4e5f6078891",
376
+ "order": 10,
377
+ "width": "6",
378
+ "height": "1",
379
+ "passthru": false,
380
+ "label": "Unbypass: front_door",
381
+ "tooltip": "",
382
+ "color": "white",
383
+ "bgcolor": "#6e7681",
384
+ "icon": "fa-check",
385
+ "payload": "{\"command\":\"unbypass\",\"zone\":\"front_door\"}",
386
+ "payloadType": "json",
387
+ "topic": "",
388
+ "topicType": "str",
389
+ "x": 190,
390
+ "y": 680,
391
+ "wires": [
392
+ [
393
+ "c44ac2b6af1a1e2a"
394
+ ]
395
+ ]
396
+ },
397
+ {
398
+ "id": "c44ac2b6af1a1e2a",
399
+ "type": "function",
400
+ "z": "b81f9a4b2f9c1a10",
401
+ "name": "Build control msg",
402
+ "func": "const payload = msg.payload;\n\nmsg.topic = \"alarm\";\n\nif (payload && typeof payload === \"object\") {\n if (typeof payload.command === \"string\") msg.command = payload.command;\n if (payload.zone != null) msg.zone = payload.zone;\n if (payload.code != null) msg.code = payload.code;\n} else if (typeof payload === \"string\") {\n msg.command = payload;\n}\n\nreturn msg;",
403
+ "outputs": 1,
404
+ "noerr": 0,
405
+ "initialize": "",
406
+ "finalize": "",
407
+ "libs": [],
408
+ "x": 450,
409
+ "y": 460,
410
+ "wires": [
411
+ [
412
+ "d0c1b2a3f4e50617"
413
+ ]
414
+ ]
415
+ },
416
+ {
417
+ "id": "d2e3f4a5b6c7d801",
418
+ "type": "ui_button",
419
+ "z": "b81f9a4b2f9c1a10",
420
+ "name": "Front door OPEN",
421
+ "group": "c3c3c4e5f6078892",
422
+ "order": 1,
423
+ "width": "6",
424
+ "height": "1",
425
+ "passthru": false,
426
+ "label": "Front door: OPEN",
427
+ "tooltip": "Sends topic sensor/frontdoor payload true",
428
+ "color": "white",
429
+ "bgcolor": "#d1242f",
430
+ "icon": "fa-door-open",
431
+ "payload": "true",
432
+ "payloadType": "bool",
433
+ "topic": "sensor/frontdoor",
434
+ "topicType": "str",
435
+ "x": 190,
436
+ "y": 760,
437
+ "wires": [
438
+ [
439
+ "d0c1b2a3f4e50617"
440
+ ]
441
+ ]
442
+ },
443
+ {
444
+ "id": "d2e3f4a5b6c7d802",
445
+ "type": "ui_button",
446
+ "z": "b81f9a4b2f9c1a10",
447
+ "name": "Front door CLOSED",
448
+ "group": "c3c3c4e5f6078892",
449
+ "order": 2,
450
+ "width": "6",
451
+ "height": "1",
452
+ "passthru": false,
453
+ "label": "Front door: CLOSED",
454
+ "tooltip": "Sends topic sensor/frontdoor payload false",
455
+ "color": "white",
456
+ "bgcolor": "#2ea043",
457
+ "icon": "fa-door-closed",
458
+ "payload": "false",
459
+ "payloadType": "bool",
460
+ "topic": "sensor/frontdoor",
461
+ "topicType": "str",
462
+ "x": 200,
463
+ "y": 800,
464
+ "wires": [
465
+ [
466
+ "d0c1b2a3f4e50617"
467
+ ]
468
+ ]
469
+ },
470
+ {
471
+ "id": "d2e3f4a5b6c7d803",
472
+ "type": "ui_button",
473
+ "z": "b81f9a4b2f9c1a10",
474
+ "name": "Living PIR MOTION",
475
+ "group": "c3c3c4e5f6078892",
476
+ "order": 3,
477
+ "width": "6",
478
+ "height": "1",
479
+ "passthru": false,
480
+ "label": "Living PIR: MOTION",
481
+ "tooltip": "Sends topic sensor/living_pir payload true",
482
+ "color": "white",
483
+ "bgcolor": "#ff9f0a",
484
+ "icon": "fa-walking",
485
+ "payload": "true",
486
+ "payloadType": "bool",
487
+ "topic": "sensor/living_pir",
488
+ "topicType": "str",
489
+ "x": 200,
490
+ "y": 840,
491
+ "wires": [
492
+ [
493
+ "d0c1b2a3f4e50617"
494
+ ]
495
+ ]
496
+ },
497
+ {
498
+ "id": "d2e3f4a5b6c7d804",
499
+ "type": "ui_button",
500
+ "z": "b81f9a4b2f9c1a10",
501
+ "name": "Living PIR CLEAR",
502
+ "group": "c3c3c4e5f6078892",
503
+ "order": 4,
504
+ "width": "6",
505
+ "height": "1",
506
+ "passthru": false,
507
+ "label": "Living PIR: CLEAR",
508
+ "tooltip": "Sends topic sensor/living_pir payload false",
509
+ "color": "white",
510
+ "bgcolor": "#6e7681",
511
+ "icon": "fa-pause",
512
+ "payload": "false",
513
+ "payloadType": "bool",
514
+ "topic": "sensor/living_pir",
515
+ "topicType": "str",
516
+ "x": 190,
517
+ "y": 880,
518
+ "wires": [
519
+ [
520
+ "d0c1b2a3f4e50617"
521
+ ]
522
+ ]
523
+ },
524
+ {
525
+ "id": "f50b6a7c1c8b3d10",
526
+ "type": "debug",
527
+ "z": "b81f9a4b2f9c1a10",
528
+ "name": "All events",
529
+ "active": true,
530
+ "tosidebar": true,
531
+ "console": false,
532
+ "tostatus": false,
533
+ "complete": "true",
534
+ "targetType": "full",
535
+ "statusVal": "",
536
+ "statusType": "auto",
537
+ "x": 520,
538
+ "y": 160,
539
+ "wires": []
540
+ },
541
+ {
542
+ "id": "f50b6a7c1c8b3d11",
543
+ "type": "debug",
544
+ "z": "b81f9a4b2f9c1a10",
545
+ "name": "Siren output",
546
+ "active": true,
547
+ "tosidebar": true,
548
+ "console": false,
549
+ "tostatus": false,
550
+ "complete": "true",
551
+ "targetType": "full",
552
+ "statusVal": "",
553
+ "statusType": "auto",
554
+ "x": 530,
555
+ "y": 200,
556
+ "wires": []
557
+ },
558
+ {
559
+ "id": "f50b6a7c1c8b3d12",
560
+ "type": "debug",
561
+ "z": "b81f9a4b2f9c1a10",
562
+ "name": "Errors / denied",
563
+ "active": true,
564
+ "tosidebar": true,
565
+ "console": false,
566
+ "tostatus": false,
567
+ "complete": "true",
568
+ "targetType": "full",
569
+ "statusVal": "",
570
+ "statusType": "auto",
571
+ "x": 550,
572
+ "y": 240,
573
+ "wires": []
574
+ }
575
+ ]