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 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 node for Node-RED.
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
- This package provides:
22
+ Note: `AlarmSystemUltimate` is currently **BETA**.
6
23
 
7
- - `AlarmSystemUltimate`: a full alarm control panel node (zones, entry/exit delays, bypass, chime, 24h/fire/tamper, siren, event log).
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
- Note: this repository currently ships `AlarmSystemUltimate` as **BETA**.
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
- ## Development
68
-
69
- Run tests:
70
-
71
- ```bash
72
- npm test
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 &amp; 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>
@@ -1,21 +1,29 @@
1
- ## Esempi
1
+ ## Examples
2
2
 
3
- Importa il flow da `examples/alarm-ultimate-basic.json` in Node-RED:
3
+ Import the flow from `examples/alarm-ultimate-basic.json` into Node-RED:
4
4
 
5
5
  1. Menu → **Import**
6
- 2. Incolla il contenuto del file JSON
6
+ 2. Paste the JSON file content
7
7
  3. Deploy
8
8
 
9
- Il flow include:
9
+ This flow includes:
10
10
 
11
- - 1 nodo `AlarmSystemUltimate` con 2 zone di esempio
12
- - Inject per arm/disarm, bypass, sensori open/close
13
- - I nodi output-only (`Alarm State`, `Alarm Zone`, `Alarm Siren`) collegati a debug
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
- Importa `examples/alarm-ultimate-dashboard.json`.
17
+ Import `examples/alarm-ultimate-dashboard.json`.
18
18
 
19
- - Richiede `node-red-dashboard` installato (nodi `ui_*`).
20
- - Il widget usa un iframe verso `"/alarm-ultimate/alarm-panel?embed=1&id=<alarmNodeId>"`.
21
- - Se hai cambiato `httpAdminRoot`, aggiorna l'URL dell'iframe di conseguenza (es: `"/red/alarm-ultimate/alarm-panel?...`).
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).