node-red-contrib-alarm-ultimate 0.1.0 → 0.1.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/README.md +76 -13
- package/docs/images/alarm-panel-mock.svg +114 -0
- package/docs/images/banner.svg +63 -0
- package/docs/images/flow-overview.svg +85 -0
- package/examples/README.md +19 -11
- package/examples/alarm-ultimate-dashboard-controls.json +574 -0
- package/nodes/AlarmSystemUltimate.html +3 -3
- package/nodes/AlarmUltimateSiren.html +3 -3
- package/nodes/AlarmUltimateSiren.js +6 -2
- package/nodes/AlarmUltimateState.html +3 -3
- package/nodes/AlarmUltimateState.js +6 -2
- package/nodes/AlarmUltimateZone.html +9 -4
- package/nodes/AlarmUltimateZone.js +21 -3
- package/nodes/icons/alarm-ultimate-siren.svg +6 -0
- package/nodes/icons/alarm-ultimate-state.svg +5 -0
- package/nodes/icons/alarm-ultimate-zone.svg +5 -0
- package/nodes/icons/alarm-ultimate.svg +6 -0
- package/package.json +2 -2
- package/tools/alarm-json-mapper.html +1118 -465
package/README.md
CHANGED
|
@@ -1,15 +1,58 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs/images/banner.svg" alt="Alarm Ultimate for Node-RED" width="900">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
[![NPM version][npm-version-image]][npm-url]
|
|
6
|
+
[![NPM downloads][npm-downloads-image]][npm-url]
|
|
7
|
+
[![Node-RED Flows][flows-image]][flows-url]
|
|
8
|
+
[![License][license-image]][license-url]
|
|
9
|
+
[![GitHub issues][issues-image]][issues-url]
|
|
10
|
+
[![Status: beta][beta-image]][repo-url]
|
|
11
|
+
|
|
1
12
|
# node-red-contrib-alarm-ultimate
|
|
2
13
|
|
|
3
|
-
Alarm System Ultimate
|
|
14
|
+
Alarm System Ultimate nodes + web panel for Node-RED.
|
|
15
|
+
|
|
16
|
+
Includes:
|
|
17
|
+
|
|
18
|
+
- `AlarmSystemUltimate` (BETA): full alarm control panel node (zones, entry/exit delays, bypass, chime, 24h/fire/tamper, siren, event log).
|
|
19
|
+
- Output-only helper nodes: `AlarmUltimateState`, `AlarmUltimateZone`, `AlarmUltimateSiren`.
|
|
20
|
+
- Web tools: Zones JSON mapper + web Alarm Panel (embeddable in Node-RED Dashboard).
|
|
4
21
|
|
|
5
|
-
|
|
22
|
+
Note: `AlarmSystemUltimate` is currently **BETA**.
|
|
6
23
|
|
|
7
|
-
|
|
8
|
-
- Output-only helper nodes to mirror alarm state into your flows (`AlarmUltimateState`, `AlarmUltimateZone`, `AlarmUltimateSiren`).
|
|
9
|
-
- Web tools: a Zones JSON mapper and a web Alarm Panel (also embeddable in Node-RED Dashboard).
|
|
24
|
+
## Table of contents
|
|
10
25
|
|
|
11
|
-
|
|
26
|
+
- [Install](#install)
|
|
27
|
+
- [Screenshots](#screenshots)
|
|
28
|
+
- [Nodes](#nodes)
|
|
29
|
+
- [Web tools](#web-tools)
|
|
30
|
+
- [Examples](#examples)
|
|
31
|
+
- [Permissions and endpoints](#permissions-and-endpoints)
|
|
32
|
+
- [Development](#development)
|
|
12
33
|
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
- Palette Manager: Menu → **Manage palette** → **Install** → search `alarm ultimate`
|
|
37
|
+
- NPM:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm i node-red-contrib-alarm-ultimate
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Screenshots
|
|
44
|
+
|
|
45
|
+
### Alarm Panel (web)
|
|
46
|
+
|
|
47
|
+
<p align="center">
|
|
48
|
+
<img src="docs/images/alarm-panel-mock.svg" alt="Alarm Panel mock" width="900">
|
|
49
|
+
</p>
|
|
50
|
+
|
|
51
|
+
### Flow overview
|
|
52
|
+
|
|
53
|
+
<p align="center">
|
|
54
|
+
<img src="docs/images/flow-overview.svg" alt="Typical flow overview" width="900">
|
|
55
|
+
</p>
|
|
13
56
|
|
|
14
57
|
## Nodes
|
|
15
58
|
|
|
@@ -42,13 +85,27 @@ The Alarm Panel supports:
|
|
|
42
85
|
- Preselect node: `/alarm-ultimate/alarm-panel?id=<alarmNodeId>`
|
|
43
86
|
- Embed mode (for Dashboard iframes): `/alarm-ultimate/alarm-panel?embed=1&id=<alarmNodeId>`
|
|
44
87
|
|
|
88
|
+
The Zones JSON Mapper supports:
|
|
89
|
+
|
|
90
|
+
- Sample message mapping (e.g. KNX Ultimate): map `topic`/`payload` fields and generate a zone template.
|
|
91
|
+
- ETS Group Addresses export (TSV): paste the exported table and generate zones in batch (boolean datapoints only).
|
|
92
|
+
|
|
45
93
|
## Examples
|
|
46
94
|
|
|
47
95
|
- `examples/alarm-ultimate-basic.json`: ready-to-import flow with `AlarmSystemUltimate`, injects and debug nodes.
|
|
48
96
|
- `examples/alarm-ultimate-dashboard.json`: Node-RED Dashboard example embedding the Alarm Panel in a `ui_template` iframe.
|
|
97
|
+
- `examples/alarm-ultimate-dashboard-controls.json`: Node-RED Dashboard example with the embedded panel plus command buttons (and a small sensor simulator).
|
|
49
98
|
|
|
50
99
|
See `examples/README.md`.
|
|
51
100
|
|
|
101
|
+
## Development
|
|
102
|
+
|
|
103
|
+
Run tests:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
npm test
|
|
107
|
+
```
|
|
108
|
+
|
|
52
109
|
## Permissions and endpoints
|
|
53
110
|
|
|
54
111
|
When Node-RED authentication is enabled, the admin endpoints use these permissions (if available):
|
|
@@ -64,10 +121,16 @@ HTTP admin endpoints:
|
|
|
64
121
|
- `GET /alarm-ultimate/alarm-json-mapper`
|
|
65
122
|
- `GET /alarm-ultimate/alarm-panel`
|
|
66
123
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
124
|
+
<!-- Badges (reference-style links) -->
|
|
125
|
+
|
|
126
|
+
[repo-url]: https://github.com/Supergiovane/node-red-contrib-alarm-ultimate
|
|
127
|
+
[npm-url]: https://www.npmjs.com/package/node-red-contrib-alarm-ultimate
|
|
128
|
+
[flows-url]: https://flows.nodered.org/node/node-red-contrib-alarm-ultimate
|
|
129
|
+
[license-url]: LICENSE
|
|
130
|
+
[issues-url]: https://github.com/Supergiovane/node-red-contrib-alarm-ultimate/issues
|
|
131
|
+
[npm-version-image]: https://img.shields.io/npm/v/node-red-contrib-alarm-ultimate.svg
|
|
132
|
+
[npm-downloads-image]: https://img.shields.io/npm/dm/node-red-contrib-alarm-ultimate.svg
|
|
133
|
+
[flows-image]: https://img.shields.io/badge/Node--RED%20Flows-library-8f0000?logo=nodered&logoColor=white
|
|
134
|
+
[license-image]: https://img.shields.io/npm/l/node-red-contrib-alarm-ultimate.svg
|
|
135
|
+
[issues-image]: https://img.shields.io/github/issues/Supergiovane/node-red-contrib-alarm-ultimate.svg
|
|
136
|
+
[beta-image]: https://img.shields.io/badge/status-beta-orange.svg
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="700" viewBox="0 0 1200 700" role="img" aria-label="Alarm Panel mock screenshot">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
|
|
4
|
+
<stop offset="0" stop-color="#0b1020"/>
|
|
5
|
+
<stop offset="1" stop-color="#11162a"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
<linearGradient id="accent" x1="0" y1="0" x2="1" y2="0">
|
|
8
|
+
<stop offset="0" stop-color="#ff375f"/>
|
|
9
|
+
<stop offset="1" stop-color="#ff9f0a"/>
|
|
10
|
+
</linearGradient>
|
|
11
|
+
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
|
|
12
|
+
<feDropShadow dx="0" dy="10" stdDeviation="14" flood-color="#000" flood-opacity="0.4"/>
|
|
13
|
+
</filter>
|
|
14
|
+
<style>
|
|
15
|
+
.h1 { font: 700 22px ui-sans-serif, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial; fill: #fff; }
|
|
16
|
+
.h2 { font: 600 14px ui-sans-serif, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial; fill: rgba(255,255,255,0.78); }
|
|
17
|
+
.label { font: 600 13px ui-sans-serif, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial; fill: rgba(255,255,255,0.86); }
|
|
18
|
+
.value { font: 700 18px ui-sans-serif, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial; fill: #fff; }
|
|
19
|
+
.tiny { font: 600 12px ui-sans-serif, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial; fill: rgba(255,255,255,0.68); }
|
|
20
|
+
</style>
|
|
21
|
+
</defs>
|
|
22
|
+
|
|
23
|
+
<rect width="1200" height="700" fill="url(#bg)"/>
|
|
24
|
+
<rect x="0" y="0" width="1200" height="10" fill="url(#accent)"/>
|
|
25
|
+
|
|
26
|
+
<!-- Window -->
|
|
27
|
+
<g filter="url(#shadow)">
|
|
28
|
+
<rect x="80" y="70" width="1040" height="560" rx="18" fill="rgba(255,255,255,0.06)" stroke="rgba(255,255,255,0.14)"/>
|
|
29
|
+
</g>
|
|
30
|
+
|
|
31
|
+
<!-- Top bar -->
|
|
32
|
+
<g>
|
|
33
|
+
<rect x="80" y="70" width="1040" height="64" rx="18" fill="rgba(255,255,255,0.07)"/>
|
|
34
|
+
<circle cx="118" cy="102" r="7" fill="#ff375f"/>
|
|
35
|
+
<circle cx="142" cy="102" r="7" fill="#ff9f0a"/>
|
|
36
|
+
<circle cx="166" cy="102" r="7" fill="#34c759"/>
|
|
37
|
+
<text class="h1" x="210" y="110">Alarm Panel</text>
|
|
38
|
+
<text class="h2" x="340" y="110">demo layout</text>
|
|
39
|
+
</g>
|
|
40
|
+
|
|
41
|
+
<!-- Status -->
|
|
42
|
+
<g transform="translate(120,160)">
|
|
43
|
+
<rect x="0" y="0" width="420" height="110" rx="16" fill="rgba(255,255,255,0.06)" stroke="rgba(255,255,255,0.12)"/>
|
|
44
|
+
<text class="label" x="22" y="32">Status</text>
|
|
45
|
+
<text class="value" x="22" y="70">DISARMED</text>
|
|
46
|
+
<rect x="280" y="30" width="120" height="56" rx="14" fill="rgba(52,199,89,0.18)" stroke="rgba(52,199,89,0.55)"/>
|
|
47
|
+
<text class="label" x="308" y="64">Ready</text>
|
|
48
|
+
</g>
|
|
49
|
+
|
|
50
|
+
<!-- Actions -->
|
|
51
|
+
<g transform="translate(560,160)">
|
|
52
|
+
<rect x="0" y="0" width="520" height="110" rx="16" fill="rgba(255,255,255,0.06)" stroke="rgba(255,255,255,0.12)"/>
|
|
53
|
+
<text class="label" x="22" y="32">Actions</text>
|
|
54
|
+
<g transform="translate(22,48)">
|
|
55
|
+
<rect x="0" y="0" width="140" height="44" rx="12" fill="rgba(255,55,95,0.18)" stroke="rgba(255,55,95,0.6)"/>
|
|
56
|
+
<text class="label" x="38" y="28">Arm</text>
|
|
57
|
+
<rect x="160" y="0" width="160" height="44" rx="12" fill="rgba(255,159,10,0.16)" stroke="rgba(255,159,10,0.55)"/>
|
|
58
|
+
<text class="label" x="202" y="28">Arm stay</text>
|
|
59
|
+
<rect x="340" y="0" width="158" height="44" rx="12" fill="rgba(255,255,255,0.08)" stroke="rgba(255,255,255,0.18)"/>
|
|
60
|
+
<text class="label" x="382" y="28">Disarm</text>
|
|
61
|
+
</g>
|
|
62
|
+
</g>
|
|
63
|
+
|
|
64
|
+
<!-- Zones list -->
|
|
65
|
+
<g transform="translate(120,300)">
|
|
66
|
+
<rect x="0" y="0" width="700" height="290" rx="16" fill="rgba(255,255,255,0.06)" stroke="rgba(255,255,255,0.12)"/>
|
|
67
|
+
<text class="label" x="22" y="34">Zones</text>
|
|
68
|
+
|
|
69
|
+
<!-- rows -->
|
|
70
|
+
<g transform="translate(22,56)">
|
|
71
|
+
<rect x="0" y="0" width="656" height="44" rx="12" fill="rgba(255,255,255,0.07)"/>
|
|
72
|
+
<text class="label" x="16" y="28">01 • Front door</text>
|
|
73
|
+
<rect x="540" y="10" width="100" height="24" rx="10" fill="rgba(52,199,89,0.18)" stroke="rgba(52,199,89,0.55)"/>
|
|
74
|
+
<text class="tiny" x="570" y="27">closed</text>
|
|
75
|
+
|
|
76
|
+
<rect x="0" y="58" width="656" height="44" rx="12" fill="rgba(255,255,255,0.07)"/>
|
|
77
|
+
<text class="label" x="16" y="86">02 • Living room PIR</text>
|
|
78
|
+
<rect x="540" y="68" width="100" height="24" rx="10" fill="rgba(52,199,89,0.18)" stroke="rgba(52,199,89,0.55)"/>
|
|
79
|
+
<text class="tiny" x="570" y="85">idle</text>
|
|
80
|
+
|
|
81
|
+
<rect x="0" y="116" width="656" height="44" rx="12" fill="rgba(255,255,255,0.07)"/>
|
|
82
|
+
<text class="label" x="16" y="144">03 • Garage</text>
|
|
83
|
+
<rect x="540" y="126" width="100" height="24" rx="10" fill="rgba(255,55,95,0.18)" stroke="rgba(255,55,95,0.6)"/>
|
|
84
|
+
<text class="tiny" x="572" y="143">open</text>
|
|
85
|
+
|
|
86
|
+
<rect x="0" y="174" width="656" height="44" rx="12" fill="rgba(255,255,255,0.07)"/>
|
|
87
|
+
<text class="label" x="16" y="202">04 • Smoke detector</text>
|
|
88
|
+
<rect x="540" y="184" width="100" height="24" rx="10" fill="rgba(255,159,10,0.16)" stroke="rgba(255,159,10,0.55)"/>
|
|
89
|
+
<text class="tiny" x="567" y="201">24h</text>
|
|
90
|
+
</g>
|
|
91
|
+
</g>
|
|
92
|
+
|
|
93
|
+
<!-- Side panel -->
|
|
94
|
+
<g transform="translate(840,300)">
|
|
95
|
+
<rect x="0" y="0" width="240" height="290" rx="16" fill="rgba(255,255,255,0.06)" stroke="rgba(255,255,255,0.12)"/>
|
|
96
|
+
<text class="label" x="20" y="34">Last events</text>
|
|
97
|
+
<g transform="translate(20,56)">
|
|
98
|
+
<rect x="0" y="0" width="200" height="54" rx="12" fill="rgba(255,255,255,0.07)"/>
|
|
99
|
+
<text class="tiny" x="14" y="22">10:24</text>
|
|
100
|
+
<text class="label" x="14" y="42">Zone 03 opened</text>
|
|
101
|
+
|
|
102
|
+
<rect x="0" y="66" width="200" height="54" rx="12" fill="rgba(255,255,255,0.07)"/>
|
|
103
|
+
<text class="tiny" x="14" y="88">10:26</text>
|
|
104
|
+
<text class="label" x="14" y="108">Disarmed</text>
|
|
105
|
+
|
|
106
|
+
<rect x="0" y="132" width="200" height="54" rx="12" fill="rgba(255,255,255,0.07)"/>
|
|
107
|
+
<text class="tiny" x="14" y="154">10:28</text>
|
|
108
|
+
<text class="label" x="14" y="174">Siren off</text>
|
|
109
|
+
</g>
|
|
110
|
+
</g>
|
|
111
|
+
|
|
112
|
+
<!-- Footnote -->
|
|
113
|
+
<text class="tiny" x="80" y="670">Illustration only (mock). The real panel is served at /alarm-ultimate/alarm-panel</text>
|
|
114
|
+
</svg>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="320" viewBox="0 0 1200 320" role="img" aria-label="Alarm Ultimate for Node-RED banner">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
|
|
4
|
+
<stop offset="0" stop-color="#0b1020"/>
|
|
5
|
+
<stop offset="1" stop-color="#171a2a"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
<linearGradient id="accent" x1="0" y1="0" x2="1" y2="0">
|
|
8
|
+
<stop offset="0" stop-color="#ff375f"/>
|
|
9
|
+
<stop offset="1" stop-color="#ff9f0a"/>
|
|
10
|
+
</linearGradient>
|
|
11
|
+
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
|
|
12
|
+
<feDropShadow dx="0" dy="8" stdDeviation="10" flood-color="#000" flood-opacity="0.35"/>
|
|
13
|
+
</filter>
|
|
14
|
+
<style>
|
|
15
|
+
.title { font: 700 54px ui-sans-serif, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial; fill: #ffffff; }
|
|
16
|
+
.subtitle { font: 500 22px ui-sans-serif, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial; fill: rgba(255,255,255,0.78); }
|
|
17
|
+
.chip { font: 600 14px ui-sans-serif, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial; fill: rgba(255,255,255,0.92); letter-spacing: 0.2px; }
|
|
18
|
+
.mono { font: 600 14px ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; fill: rgba(255,255,255,0.92); }
|
|
19
|
+
</style>
|
|
20
|
+
</defs>
|
|
21
|
+
|
|
22
|
+
<rect width="1200" height="320" fill="url(#bg)"/>
|
|
23
|
+
|
|
24
|
+
<!-- Accent ribbon -->
|
|
25
|
+
<rect x="0" y="0" width="1200" height="10" fill="url(#accent)"/>
|
|
26
|
+
|
|
27
|
+
<!-- Decorative grid -->
|
|
28
|
+
<g opacity="0.16">
|
|
29
|
+
<path d="M80 0V320M160 0V320M240 0V320M320 0V320M400 0V320M480 0V320M560 0V320M640 0V320M720 0V320M800 0V320M880 0V320M960 0V320M1040 0V320M1120 0V320" stroke="#ffffff" stroke-width="1"/>
|
|
30
|
+
<path d="M0 60H1200M0 120H1200M0 180H1200M0 240H1200" stroke="#ffffff" stroke-width="1"/>
|
|
31
|
+
</g>
|
|
32
|
+
|
|
33
|
+
<!-- Card -->
|
|
34
|
+
<g filter="url(#shadow)">
|
|
35
|
+
<rect x="70" y="70" width="1060" height="180" rx="18" fill="rgba(255,255,255,0.06)" stroke="rgba(255,255,255,0.14)"/>
|
|
36
|
+
</g>
|
|
37
|
+
|
|
38
|
+
<!-- Icon -->
|
|
39
|
+
<g transform="translate(120,115)">
|
|
40
|
+
<rect x="0" y="0" width="86" height="86" rx="18" fill="rgba(255,55,95,0.15)" stroke="rgba(255,55,95,0.5)"/>
|
|
41
|
+
<path d="M43 16c-10.5 0-19 8.5-19 19v11.3l-5.7 11.4c-1.2 2.3 0.4 5.1 3 5.1H64c2.6 0 4.2-2.8 3-5.1l-5.7-11.4V35c0-10.5-8.5-19-19-19z" fill="#ff375f"/>
|
|
42
|
+
<path d="M32 68c0 6.1 4.9 11 11 11s11-4.9 11-11H32z" fill="#ff9f0a"/>
|
|
43
|
+
</g>
|
|
44
|
+
|
|
45
|
+
<!-- Text -->
|
|
46
|
+
<text class="title" x="240" y="150">Alarm Ultimate</text>
|
|
47
|
+
<text class="subtitle" x="240" y="186">Alarm nodes + web panel for Node-RED</text>
|
|
48
|
+
|
|
49
|
+
<!-- Chips -->
|
|
50
|
+
<g transform="translate(240,206)">
|
|
51
|
+
<rect x="0" y="0" width="132" height="30" rx="10" fill="rgba(255,255,255,0.08)" stroke="rgba(255,255,255,0.14)"/>
|
|
52
|
+
<text class="chip" x="16" y="20">Zones</text>
|
|
53
|
+
|
|
54
|
+
<rect x="148" y="0" width="170" height="30" rx="10" fill="rgba(255,255,255,0.08)" stroke="rgba(255,255,255,0.14)"/>
|
|
55
|
+
<text class="chip" x="164" y="20">Siren & events</text>
|
|
56
|
+
|
|
57
|
+
<rect x="334" y="0" width="232" height="30" rx="10" fill="rgba(255,255,255,0.08)" stroke="rgba(255,255,255,0.14)"/>
|
|
58
|
+
<text class="chip" x="350" y="20">Dashboard embed</text>
|
|
59
|
+
|
|
60
|
+
<rect x="582" y="0" width="214" height="30" rx="10" fill="rgba(255,255,255,0.08)" stroke="rgba(255,255,255,0.14)"/>
|
|
61
|
+
<text class="mono" x="598" y="20">/alarm-ultimate</text>
|
|
62
|
+
</g>
|
|
63
|
+
</svg>
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="520" viewBox="0 0 1200 520" role="img" aria-label="Flow overview diagram">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
|
|
4
|
+
<stop offset="0" stop-color="#0b1020"/>
|
|
5
|
+
<stop offset="1" stop-color="#11162a"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
<linearGradient id="accent" x1="0" y1="0" x2="1" y2="0">
|
|
8
|
+
<stop offset="0" stop-color="#ff375f"/>
|
|
9
|
+
<stop offset="1" stop-color="#ff9f0a"/>
|
|
10
|
+
</linearGradient>
|
|
11
|
+
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
|
|
12
|
+
<feDropShadow dx="0" dy="10" stdDeviation="14" flood-color="#000" flood-opacity="0.35"/>
|
|
13
|
+
</filter>
|
|
14
|
+
<style>
|
|
15
|
+
.title { font: 800 20px ui-sans-serif, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial; fill: #fff; }
|
|
16
|
+
.label { font: 650 14px ui-sans-serif, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial; fill: rgba(255,255,255,0.85); }
|
|
17
|
+
.tiny { font: 600 12px ui-sans-serif, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial; fill: rgba(255,255,255,0.65); }
|
|
18
|
+
.mono { font: 650 12px ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; fill: rgba(255,255,255,0.8); }
|
|
19
|
+
</style>
|
|
20
|
+
<marker id="arrow" viewBox="0 0 10 10" refX="9.2" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
|
21
|
+
<path d="M 0 0 L 10 5 L 0 10 z" fill="rgba(255,255,255,0.65)"/>
|
|
22
|
+
</marker>
|
|
23
|
+
</defs>
|
|
24
|
+
|
|
25
|
+
<rect width="1200" height="520" fill="url(#bg)"/>
|
|
26
|
+
<rect x="0" y="0" width="1200" height="10" fill="url(#accent)"/>
|
|
27
|
+
|
|
28
|
+
<text class="title" x="80" y="58">Typical Node-RED flow</text>
|
|
29
|
+
<text class="tiny" x="80" y="84">Sensors publish to per-zone topics; commands go to a dedicated control topic; helper nodes mirror state.</text>
|
|
30
|
+
|
|
31
|
+
<!-- Nodes -->
|
|
32
|
+
<g filter="url(#shadow)">
|
|
33
|
+
<!-- Sensors -->
|
|
34
|
+
<rect x="80" y="140" width="260" height="300" rx="18" fill="rgba(255,255,255,0.06)" stroke="rgba(255,255,255,0.14)"/>
|
|
35
|
+
<text class="label" x="110" y="176">Sensors</text>
|
|
36
|
+
<text class="mono" x="110" y="202">topic: house/zone/01</text>
|
|
37
|
+
<text class="mono" x="110" y="226">payload: true/false</text>
|
|
38
|
+
<text class="mono" x="110" y="262">topic: house/zone/02</text>
|
|
39
|
+
<text class="mono" x="110" y="286">payload: true/false</text>
|
|
40
|
+
<text class="mono" x="110" y="322">topic: house/zone/03</text>
|
|
41
|
+
<text class="mono" x="110" y="346">payload: true/false</text>
|
|
42
|
+
<text class="tiny" x="110" y="392">Any topic != controlTopic</text>
|
|
43
|
+
</g>
|
|
44
|
+
|
|
45
|
+
<g filter="url(#shadow)">
|
|
46
|
+
<!-- Main node -->
|
|
47
|
+
<rect x="420" y="200" width="360" height="180" rx="18" fill="rgba(255,55,95,0.12)" stroke="rgba(255,55,95,0.55)"/>
|
|
48
|
+
<text class="label" x="450" y="240">AlarmSystemUltimate</text>
|
|
49
|
+
<text class="tiny" x="450" y="266">Zones + delays + bypass + siren + log</text>
|
|
50
|
+
<rect x="450" y="292" width="300" height="56" rx="14" fill="rgba(255,255,255,0.08)" stroke="rgba(255,255,255,0.16)"/>
|
|
51
|
+
<text class="mono" x="468" y="326">msg.topic === controlTopic</text>
|
|
52
|
+
</g>
|
|
53
|
+
|
|
54
|
+
<g filter="url(#shadow)">
|
|
55
|
+
<!-- Commands -->
|
|
56
|
+
<rect x="420" y="140" width="360" height="46" rx="14" fill="rgba(255,159,10,0.14)" stroke="rgba(255,159,10,0.55)"/>
|
|
57
|
+
<text class="label" x="450" y="170">Commands (Inject / MQTT / UI)</text>
|
|
58
|
+
</g>
|
|
59
|
+
|
|
60
|
+
<g filter="url(#shadow)">
|
|
61
|
+
<!-- Helpers -->
|
|
62
|
+
<rect x="860" y="140" width="260" height="300" rx="18" fill="rgba(255,255,255,0.06)" stroke="rgba(255,255,255,0.14)"/>
|
|
63
|
+
<text class="label" x="890" y="176">Output-only nodes</text>
|
|
64
|
+
|
|
65
|
+
<rect x="890" y="200" width="200" height="56" rx="14" fill="rgba(255,255,255,0.07)" stroke="rgba(255,255,255,0.14)"/>
|
|
66
|
+
<text class="label" x="910" y="234">AlarmUltimateState</text>
|
|
67
|
+
<text class="tiny" x="910" y="252">payload: \"armed\" | \"disarmed\"</text>
|
|
68
|
+
|
|
69
|
+
<rect x="890" y="270" width="200" height="56" rx="14" fill="rgba(255,255,255,0.07)" stroke="rgba(255,255,255,0.14)"/>
|
|
70
|
+
<text class="label" x="910" y="304">AlarmUltimateZone</text>
|
|
71
|
+
<text class="tiny" x="910" y="322">payload: true/false (selected)</text>
|
|
72
|
+
|
|
73
|
+
<rect x="890" y="340" width="200" height="56" rx="14" fill="rgba(255,255,255,0.07)" stroke="rgba(255,255,255,0.14)"/>
|
|
74
|
+
<text class="label" x="910" y="374">AlarmUltimateSiren</text>
|
|
75
|
+
<text class="tiny" x="910" y="392">payload: true/false</text>
|
|
76
|
+
</g>
|
|
77
|
+
|
|
78
|
+
<!-- Arrows -->
|
|
79
|
+
<path d="M340 290H420" stroke="rgba(255,255,255,0.65)" stroke-width="2.2" marker-end="url(#arrow)"/>
|
|
80
|
+
<path d="M600 186V200" stroke="rgba(255,255,255,0.65)" stroke-width="2.2" marker-end="url(#arrow)"/>
|
|
81
|
+
<path d="M780 290H860" stroke="rgba(255,255,255,0.65)" stroke-width="2.2" marker-end="url(#arrow)"/>
|
|
82
|
+
|
|
83
|
+
<!-- Footer -->
|
|
84
|
+
<text class="tiny" x="80" y="486">Web tools: /alarm-ultimate/alarm-json-mapper • /alarm-ultimate/alarm-panel (also embeddable)</text>
|
|
85
|
+
</svg>
|
package/examples/README.md
CHANGED
|
@@ -1,21 +1,29 @@
|
|
|
1
|
-
##
|
|
1
|
+
## Examples
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Import the flow from `examples/alarm-ultimate-basic.json` into Node-RED:
|
|
4
4
|
|
|
5
5
|
1. Menu → **Import**
|
|
6
|
-
2.
|
|
6
|
+
2. Paste the JSON file content
|
|
7
7
|
3. Deploy
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
This flow includes:
|
|
10
10
|
|
|
11
|
-
- 1
|
|
12
|
-
- Inject
|
|
13
|
-
-
|
|
11
|
+
- 1 `AlarmSystemUltimate` node with 2 example zones
|
|
12
|
+
- Inject nodes for arm/disarm, bypass, sensor open/close
|
|
13
|
+
- Output-only nodes (`Alarm State`, `Alarm Zone`, `Alarm Siren`) connected to debug
|
|
14
14
|
|
|
15
15
|
## Dashboard (node-red-dashboard)
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Import `examples/alarm-ultimate-dashboard.json`.
|
|
18
18
|
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
19
|
+
- Requires `node-red-dashboard` installed (`ui_*` nodes).
|
|
20
|
+
- The widget uses an iframe pointing to `"/alarm-ultimate/alarm-panel?embed=1&id=<alarmNodeId>"`.
|
|
21
|
+
- If you changed `httpAdminRoot`, update the iframe URL accordingly (e.g. `"/red/alarm-ultimate/alarm-panel?...`).
|
|
22
|
+
|
|
23
|
+
### Dashboard + commands (panel + controls)
|
|
24
|
+
|
|
25
|
+
Import `examples/alarm-ultimate-dashboard-controls.json`.
|
|
26
|
+
|
|
27
|
+
- Includes the panel (iframe) + Dashboard buttons for `arm`, `disarm`, `status`, `list_open_zones`, `siren_on/off`, `panic`.
|
|
28
|
+
- Also includes a small “sensor simulator” (buttons that send `true/false` on `sensor/frontdoor` and `sensor/living_pir`).
|
|
29
|
+
- The iframe uses a *relative* URL (`alarm-ultimate/...`) so it works even when Node-RED is served under a path prefix (e.g. Home Assistant Ingress).
|