node-red-contrib-dmx-for-ha 0.1.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.
@@ -0,0 +1,233 @@
1
+ <!-- ============================================================
2
+ ha-mqtt-config — Config Node Editor
3
+ Package: node-red-contrib-dmx-for-ha
4
+ Author: DeSwaggy — Discord: @deswaggy
5
+ ============================================================ -->
6
+
7
+ <script type="text/javascript">
8
+ RED.nodes.registerType('ha-mqtt-config', {
9
+ category: 'config',
10
+ defaults: {
11
+ name: { value: '', required: true },
12
+ siteId: { value: '', required: true },
13
+ zone: { value: '', required: true },
14
+ broker: { value: '', type: 'mqtt-broker', required: true },
15
+ discoveryPrefix: { value: 'homeassistant' },
16
+ qos: { value: '0' },
17
+ retain: { value: 'false' },
18
+ configTopic: { value: 'config' },
19
+ stateTopic: { value: 'state' },
20
+ commandTopic: { value: 'cmd' },
21
+ availTopic: { value: 'avty' },
22
+ enabledDefault: { value: 'true' },
23
+ diskDelay: { value: '10' },
24
+ flashShort: { value: '1' },
25
+ flashLong: { value: '10' },
26
+ },
27
+ label: function () {
28
+ return this.name || 'HA MQTT Config';
29
+ },
30
+ oneditprepare: function () {
31
+ // Zone is free text — no population needed
32
+ // Sanitisation happens in runtime .js
33
+ },
34
+ });
35
+ </script>
36
+
37
+ <!-- ============================================================
38
+ Editor Panel Template
39
+ ============================================================ -->
40
+ <script type="text/html" data-template-name="ha-mqtt-config">
41
+
42
+ <!-- NAME -->
43
+ <div class="form-row">
44
+ <label for="node-config-input-name">
45
+ <i class="fa fa-tag"></i> Name
46
+ </label>
47
+ <input type="text" id="node-config-input-name"
48
+ placeholder="e.g. Master Zone, Guest Wing" />
49
+ </div>
50
+
51
+ <hr/>
52
+
53
+ <!-- SITE -->
54
+ <div class="form-row">
55
+ <label style="width:100%; font-weight:bold; color:#999; font-size:0.85em; text-transform:uppercase; letter-spacing:0.05em;">
56
+ <i class="fa fa-home"></i> Site
57
+ </label>
58
+ </div>
59
+
60
+ <div class="form-row">
61
+ <label for="node-config-input-siteId">
62
+ <i class="fa fa-id-badge"></i> Site ID
63
+ </label>
64
+ <input type="text" id="node-config-input-siteId"
65
+ placeholder="e.g. home, unit4, smithresidence"
66
+ style="width:60%" />
67
+ <span style="margin-left:8px; color:#999; font-size:0.85em;">
68
+ Used in MQTT topic construction
69
+ </span>
70
+ </div>
71
+
72
+ <div class="form-row">
73
+ <label for="node-config-input-zone">
74
+ <i class="fa fa-location-arrow"></i> Zone
75
+ </label>
76
+ <input type="text" id="node-config-input-zone"
77
+ placeholder="e.g. Master, BnB, GuestWing"
78
+ style="width:60%" />
79
+ <div style="margin-left:106px; margin-top:4px; color:#999; font-size:0.85em;">
80
+ Used in MQTT topics — no spaces or special characters ( # + / ).
81
+ Spaces are automatically converted to underscores.
82
+ </div>
83
+ </div>
84
+
85
+ <hr/>
86
+
87
+ <!-- MQTT BROKER -->
88
+ <div class="form-row">
89
+ <label style="width:100%; font-weight:bold; color:#999; font-size:0.85em; text-transform:uppercase; letter-spacing:0.05em;">
90
+ <i class="fa fa-exchange"></i> MQTT Broker
91
+ </label>
92
+ </div>
93
+
94
+ <div class="form-row">
95
+ <label for="node-config-input-broker">
96
+ <i class="fa fa-server"></i> Broker
97
+ </label>
98
+ <input type="text" id="node-config-input-broker" />
99
+ </div>
100
+
101
+ <hr/>
102
+
103
+ <!-- HOME ASSISTANT -->
104
+ <div class="form-row">
105
+ <label style="width:100%; font-weight:bold; color:#999; font-size:0.85em; text-transform:uppercase; letter-spacing:0.05em;">
106
+ <i class="fa fa-home"></i> Home Assistant
107
+ </label>
108
+ </div>
109
+
110
+ <div class="form-row">
111
+ <label for="node-config-input-discoveryPrefix">
112
+ <i class="fa fa-search"></i> Discovery prefix
113
+ </label>
114
+ <input type="text" id="node-config-input-discoveryPrefix"
115
+ placeholder="homeassistant" style="width:40%" />
116
+ </div>
117
+
118
+ <div class="form-row">
119
+ <label for="node-config-input-qos">
120
+ <i class="fa fa-signal"></i> QoS
121
+ </label>
122
+ <select id="node-config-input-qos" style="width:80px">
123
+ <option value="0">0</option>
124
+ <option value="1">1</option>
125
+ <option value="2">2</option>
126
+ </select>
127
+ &nbsp;&nbsp;
128
+ <label for="node-config-input-retain" style="width:auto">
129
+ <i class="fa fa-thumb-tack"></i> Retain
130
+ </label>
131
+ <select id="node-config-input-retain" style="width:80px">
132
+ <option value="false">false</option>
133
+ <option value="true">true</option>
134
+ </select>
135
+ </div>
136
+
137
+ <hr/>
138
+
139
+ <!-- DEFAULTS -->
140
+ <div class="form-row">
141
+ <label style="width:100%; font-weight:bold; color:#999; font-size:0.85em; text-transform:uppercase; letter-spacing:0.05em;">
142
+ <i class="fa fa-sliders"></i> Defaults
143
+ </label>
144
+ </div>
145
+
146
+ <div class="form-row">
147
+ <label for="node-config-input-enabledDefault">
148
+ <i class="fa fa-toggle-on"></i> Enabled by default in HA
149
+ </label>
150
+ <select id="node-config-input-enabledDefault" style="width:80px">
151
+ <option value="true">true</option>
152
+ <option value="false">false</option>
153
+ </select>
154
+ </div>
155
+
156
+ <div class="form-row">
157
+ <label for="node-config-input-diskDelay">
158
+ <i class="fa fa-clock-o"></i> Disk save delay (s)
159
+ </label>
160
+ <input type="number" id="node-config-input-diskDelay"
161
+ min="1" max="60" style="width:70px" />
162
+ <span style="margin-left:8px; color:#999; font-size:0.85em;">
163
+ Debounce delay before writing state to disk
164
+ </span>
165
+ </div>
166
+
167
+ <div class="form-row">
168
+ <label style="margin-left:106px; color:#999; font-size:0.85em;">
169
+ Flash durations (seconds):
170
+ </label>
171
+ </div>
172
+ <div class="form-row">
173
+ <label for="node-config-input-flashShort">
174
+ <i class="fa fa-clock-o"></i> Flash Short
175
+ </label>
176
+ <input type="number" id="node-config-input-flashShort"
177
+ min="0.1" step="0.1" style="width:70px" />
178
+ &nbsp;&nbsp;
179
+ <label for="node-config-input-flashLong" style="width:auto">
180
+ Flash Long
181
+ </label>
182
+ <input type="number" id="node-config-input-flashLong"
183
+ min="1" style="width:70px" />
184
+ </div>
185
+
186
+ </script>
187
+
188
+ <!-- ============================================================
189
+ Help Panel
190
+ ============================================================ -->
191
+ <script type="text/html" data-help-name="ha-mqtt-config">
192
+ <p>
193
+ Shared configuration node for the <strong>DMX for HA</strong> package.
194
+ Create one config node per zone. All DMX, Relay, Button and PIR nodes
195
+ reference this config to inherit site-wide settings.
196
+ </p>
197
+
198
+ <h3>Setup</h3>
199
+ <ol>
200
+ <li>Set a meaningful <strong>Name</strong> — e.g. "Master Zone", "Guest Wing"</li>
201
+ <li>Enter your <strong>Site ID</strong> — a short slug used in MQTT topic construction (e.g. <code>home</code>)</li>
202
+ <li>Select your <strong>Zone</strong></li>
203
+ <li>Select your <strong>MQTT Broker</strong> from the dropdown</li>
204
+ <li>Leave HA defaults as-is unless you have a custom HA MQTT setup</li>
205
+ </ol>
206
+
207
+ <h3>Multi-zone deployments</h3>
208
+ <p>
209
+ Create one <code>ha-mqtt-config</code> node per zone. Each DMX, Relay,
210
+ Button or PIR node picks its zone via the Config dropdown in its own
211
+ editor panel.
212
+ </p>
213
+
214
+ <h3>MQTT topic format</h3>
215
+ <p>Topics are constructed as:</p>
216
+ <pre>{siteId}/{zone}/{controller}/...</pre>
217
+ <p>Example with Site ID <code>home</code> and Zone <code>Master</code>:</p>
218
+ <pre>home/Master/dmx/1</pre>
219
+
220
+ <h3>Details</h3>
221
+ <dl class="message-properties">
222
+ <dt>Site ID <span class="property-type">string</span></dt>
223
+ <dd>Short slug identifying this installation. Used in MQTT topic construction. No spaces.</dd>
224
+ <dt>Zone <span class="property-type">string</span></dt>
225
+ <dd>Physical zone of this config node. Becomes part of the MQTT topic.</dd>
226
+ <dt>Broker <span class="property-type">mqtt-broker</span></dt>
227
+ <dd>The MQTT broker all nodes in this zone connect to.</dd>
228
+ <dt>Discovery prefix <span class="property-type">string</span></dt>
229
+ <dd>HA MQTT discovery prefix. Default: <code>homeassistant</code></dd>
230
+ <dt>Disk save delay <span class="property-type">number</span></dt>
231
+ <dd>Seconds to debounce before writing fixture state to disk context store. Default: 10.</dd>
232
+ </dl>
233
+ </script>
@@ -0,0 +1,81 @@
1
+ // ============================================================
2
+ // ha-mqtt-config — Config Node Runtime
3
+ // Package: node-red-contrib-dmx-for-ha
4
+ // Author: DeSwaggy — Discord: @deswaggy
5
+ //
6
+ // Shared configuration node. Holds site-wide settings and
7
+ // exposes the MQTT broker connection to all child nodes
8
+ // (ha-mqtt-dmx, ha-mqtt-dmx-group, ha-mqtt-relay,
9
+ // ha-mqtt-button, ha-mqtt-pir).
10
+ //
11
+ // Child nodes access config via:
12
+ // const config = RED.nodes.getNode(this.config);
13
+ // config.broker → MQTT broker node
14
+ // config.siteId → site ID string
15
+ // config.zone → zone string
16
+ // config.settings → all other settings
17
+ // ============================================================
18
+
19
+ module.exports = function (RED) {
20
+
21
+ function HaMqttConfigNode(config) {
22
+ RED.nodes.createNode(this, config);
23
+
24
+ // Site
25
+ // Sanitise siteId — same rules as zone
26
+ this.siteId = (config.siteId || '')
27
+ .trim()
28
+ .replace(/\s+/g, '_')
29
+ .replace(/[#\+\/]/g, '')
30
+ .replace(/_+/g, '_');
31
+ // Sanitise zone — strip characters invalid in MQTT topics
32
+ // Spaces → underscores, remove # + / and other special chars
33
+ this.zone = (config.zone || '')
34
+ .trim()
35
+ .replace(/\s+/g, '_')
36
+ .replace(/[#\+\/]/g, '')
37
+ .replace(/_+/g, '_');
38
+
39
+ // MQTT broker — child nodes subscribe/publish via this
40
+ this.broker = config.broker;
41
+ this.brokerNode = RED.nodes.getNode(config.broker);
42
+
43
+ // HA MQTT topic segments
44
+ this.discoveryPrefix = config.discoveryPrefix || 'homeassistant';
45
+ this.configTopic = config.configTopic || 'config';
46
+ this.stateTopic = config.stateTopic || 'state';
47
+ this.commandTopic = config.commandTopic || 'cmd';
48
+ this.availTopic = config.availTopic || 'avty';
49
+
50
+ // MQTT settings
51
+ this.qos = parseInt(config.qos) || 0;
52
+ this.retain = config.retain === 'true';
53
+
54
+ // HA defaults
55
+ this.enabledDefault = config.enabledDefault !== 'false';
56
+
57
+ // Timing defaults
58
+ this.diskDelay = parseInt(config.diskDelay) || 10;
59
+ this.flashShort = parseFloat(config.flashShort) || 1;
60
+ this.flashLong = parseFloat(config.flashLong) || 10;
61
+
62
+ // Expose a convenience settings object for child nodes
63
+ this.settings = {
64
+ siteId: this.siteId,
65
+ zone: this.zone,
66
+ discoveryPrefix: this.discoveryPrefix,
67
+ configTopic: this.configTopic,
68
+ stateTopic: this.stateTopic,
69
+ commandTopic: this.commandTopic,
70
+ availTopic: this.availTopic,
71
+ qos: this.qos,
72
+ retain: this.retain,
73
+ enabledDefault: this.enabledDefault,
74
+ diskDelay: this.diskDelay,
75
+ flashShort: this.flashShort,
76
+ flashLong: this.flashLong,
77
+ };
78
+ }
79
+
80
+ RED.nodes.registerType('ha-mqtt-config', HaMqttConfigNode);
81
+ };