node-red-contrib-ccu 3.4.1 → 4.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.
Files changed (49) hide show
  1. package/.prettierignore +10 -0
  2. package/.prettierrc +14 -0
  3. package/AGENTS.md +96 -0
  4. package/CHANGELOG.md +66 -0
  5. package/README.md +17 -21
  6. package/ROADMAP.md +402 -0
  7. package/eslint.config.js +45 -0
  8. package/examples/rpc-events.json +65 -0
  9. package/examples/switch-datapoint.json +86 -0
  10. package/examples/system-variable.json +60 -0
  11. package/nodes/ccu-alexa.html +12 -7
  12. package/nodes/ccu-alexa.js +43 -15
  13. package/nodes/ccu-connection.html +9 -1
  14. package/nodes/ccu-connection.js +602 -337
  15. package/nodes/ccu-display.html +11 -4
  16. package/nodes/ccu-display.js +26 -9
  17. package/nodes/ccu-get-value.html +23 -14
  18. package/nodes/ccu-get-value.js +10 -5
  19. package/nodes/ccu-mqtt.html +9 -10
  20. package/nodes/ccu-mqtt.js +55 -29
  21. package/nodes/ccu-program.html +1 -1
  22. package/nodes/ccu-program.js +9 -7
  23. package/nodes/ccu-rpc-event.html +12 -7
  24. package/nodes/ccu-rpc-event.js +4 -5
  25. package/nodes/ccu-rpc.html +12 -5
  26. package/nodes/ccu-rpc.js +8 -6
  27. package/nodes/ccu-script.html +1 -1
  28. package/nodes/ccu-script.js +4 -3
  29. package/nodes/ccu-set-value.html +11 -7
  30. package/nodes/ccu-set-value.js +47 -16
  31. package/nodes/ccu-signal.html +11 -5
  32. package/nodes/ccu-signal.js +34 -23
  33. package/nodes/ccu-switch.html +23 -13
  34. package/nodes/ccu-sysvar.html +1 -1
  35. package/nodes/ccu-sysvar.js +11 -7
  36. package/nodes/ccu-value.html +12 -7
  37. package/nodes/ccu-value.js +36 -13
  38. package/nodes/lib/base62.js +22 -0
  39. package/nodes/lib/discover.js +127 -0
  40. package/nodes/lib/nextport.js +30 -0
  41. package/nodes/lib/similarity.js +51 -0
  42. package/nodes/lib/status.js +1 -1
  43. package/package.json +105 -144
  44. package/roadmap-archive/README.md +20 -0
  45. package/roadmap-archive/phase-1.md +48 -0
  46. package/roadmap-archive/todo-history.md +39 -0
  47. package/TODO.md +0 -41
  48. package/ccu_rega_localhost.json +0 -1
  49. package/ccu_values_localhost.json +0 -1
@@ -0,0 +1,60 @@
1
+ [
2
+ {
3
+ "id": "sysvar-watch",
4
+ "type": "ccu-sysvar",
5
+ "name": "Presence",
6
+ "ccuConfig": "ccu-conn-example",
7
+ "topic": "${CCU}/SysVar/${Name}",
8
+ "change": true,
9
+ "cache": true,
10
+ "x": 340,
11
+ "y": 100,
12
+ "wires": [["debug-sysvar"]]
13
+ },
14
+ {
15
+ "id": "debug-sysvar",
16
+ "type": "debug",
17
+ "name": "sysvar",
18
+ "active": true,
19
+ "tosidebar": true,
20
+ "complete": "payload",
21
+ "x": 550,
22
+ "y": 100,
23
+ "wires": []
24
+ },
25
+ {
26
+ "id": "inject-set",
27
+ "type": "inject",
28
+ "name": "set true",
29
+ "props": [
30
+ {
31
+ "p": "payload"
32
+ }
33
+ ],
34
+ "payload": "true",
35
+ "payloadType": "bool",
36
+ "x": 140,
37
+ "y": 100,
38
+ "wires": [["sysvar-watch"]]
39
+ },
40
+ {
41
+ "id": "ccu-conn-example",
42
+ "type": "ccu-connection",
43
+ "name": "CCU",
44
+ "host": "ccu3-hostname-or-ip",
45
+ "regaEnabled": true,
46
+ "bcrfEnabled": true,
47
+ "iprfEnabled": true,
48
+ "virtEnabled": false,
49
+ "bcwiEnabled": false,
50
+ "cuxdEnabled": false,
51
+ "jackEnabled": false,
52
+ "regaPoll": true,
53
+ "regaInterval": "30",
54
+ "rpcPingTimeout": "60",
55
+ "rpcInitAddress": "",
56
+ "rpcServerHost": "",
57
+ "rpcBinPort": "2047",
58
+ "rpcXmlPort": "2048"
59
+ }
60
+ ]
@@ -21,7 +21,6 @@
21
21
  return this.name ? 'node_label_italic' : '';
22
22
  },
23
23
  oneditprepare() {
24
- console.log(this);
25
24
 
26
25
  const $nodeInputIface = $('#node-input-iface');
27
26
  const $nodeInputCcuConfig = $('#node-input-ccuConfig');
@@ -30,6 +29,7 @@
30
29
  let data;
31
30
  let ifacesLoaded = false;
32
31
  let ifacesPending = false;
32
+ let ifaceLoadRetries = 5;
33
33
 
34
34
  function loadIfaces(iface, cb) {
35
35
  if (ifacesPending) {
@@ -37,7 +37,6 @@
37
37
  }
38
38
 
39
39
  ifacesPending = true;
40
- console.log('loadIfaces()');
41
40
  $nodeInputIface.html('<option value=""></option>');
42
41
  const nodeId = $nodeInputCcuConfig.val();
43
42
  if (nodeId === '_ADD_') {
@@ -57,6 +56,12 @@
57
56
  cb();
58
57
  ifacesPending = false;
59
58
  }
59
+ }).fail(() => {
60
+ // config node not (yet) available in the runtime - allow retrying
61
+ ifacesPending = false;
62
+ if (ifaceLoadRetries-- > 0) {
63
+ setTimeout(() => loadIfaces(iface, cb), 1000);
64
+ }
60
65
  });
61
66
  }
62
67
  }
@@ -66,18 +71,15 @@
66
71
  return;
67
72
  }
68
73
 
69
- console.log('loadConfig()');
70
74
  const nodeId = $nodeInputCcuConfig.val();
71
75
  const url = 'ccu?config=' + nodeId + '&type=channels&iface=' + $nodeInputIface.val();
72
76
  $.getJSON(url, d => {
73
77
  data = d;
74
- console.log(d);
75
78
  autocompleteChannel();
76
79
  });
77
80
  }
78
81
 
79
82
  $nodeInputCcuConfig.change(() => {
80
- console.log('$nodeInputCcuConfig change');
81
83
  loadIfaces(this.iface, () => {
82
84
  ifacesLoaded = true;
83
85
  $nodeInputIface.removeAttr('disabled');
@@ -85,6 +87,10 @@
85
87
  });
86
88
  });
87
89
 
90
+ // Node-RED 4.x does not reliably fire the change event on dialog
91
+ // open - trigger the initial load explicitly (see ROADMAP.md 8.1)
92
+ $nodeInputCcuConfig.trigger('change');
93
+
88
94
  $nodeInputChannel.autocomplete({
89
95
  source: [],
90
96
  close: () => {
@@ -122,7 +128,6 @@
122
128
  }
123
129
 
124
130
  $nodeInputIface.change(() => {
125
- console.log('$nodeInputIface change');
126
131
  loadConfig();
127
132
  });
128
133
  },
@@ -172,7 +177,7 @@
172
177
 
173
178
  </script>
174
179
 
175
- <script type="text/x-red" data-template-name="ccu-alexa">
180
+ <script type="text/x-red" data-help-name="ccu-alexa" lang="de">
176
181
  <p>Homematic Geräte mit node-red-contrib-alexa-smart-home verbinden. Am Eingang den Node "alexa smart home v3"
177
182
  anschließen, am Ausgang "alexa smart home v3 state".</p>
178
183
  </script>
@@ -36,21 +36,21 @@ module.exports = function (RED) {
36
36
  change: true,
37
37
  stable: true,
38
38
  iface: config.iface,
39
- channel: String(config.channel).split(' ')[0]
39
+ channel: String(config.channel).split(' ')[0],
40
40
  };
41
41
 
42
42
  const payload = {
43
43
  acknowledge: true,
44
- state: {}
44
+ state: {},
45
45
  };
46
46
 
47
- this.idSubscription = this.ccu.subscribe(filter, message => {
47
+ this.idSubscription = this.ccu.subscribe(filter, (message) => {
48
48
  let change = false;
49
49
  switch (channelType) {
50
50
  case 'SHUTTER_CONTACT':
51
51
  case 'ROTARY_HANDLE_SENSOR':
52
52
  if (message.datapoint === 'STATE') {
53
- payload.state.contact = message.payload ? 'NOT_DETECTED' : 'DETECTED';
53
+ payload.state.contact = message.payload ? 'DETECTED' : 'NOT_DETECTED';
54
54
  change = true;
55
55
  }
56
56
 
@@ -145,18 +145,31 @@ module.exports = function (RED) {
145
145
  return;
146
146
  }
147
147
 
148
- if (Object.keys(payload.state).length > 0) {
148
+ const keys = Object.keys(payload.state);
149
+
150
+ if (keys.length > 0) {
149
151
  if (change) {
150
152
  this.debug(JSON.stringify(payload));
151
- this.send({payload});
152
- this.status({fill: 'green', shape: 'ring', text: JSON.stringify(payload.state).replace(/^{/, '').replace(/}$/, '')});
153
+ this.status({
154
+ fill: 'green',
155
+ shape: 'ring',
156
+ text: JSON.stringify(payload.state).replace(/^{/, '').replace(/}$/, ''),
157
+ });
158
+ keys.forEach((key) => {
159
+ const distinctPayload = {
160
+ acknowledge: true,
161
+ state: {},
162
+ };
163
+ distinctPayload.state[key] = payload.state[key];
164
+ this.send({payload: distinctPayload});
165
+ });
153
166
  }
154
167
  } else {
155
168
  this.debug('empty state object');
156
169
  }
157
170
  });
158
171
 
159
- this.on('input', message => {
172
+ this.on('input', (message) => {
160
173
  this.debug('alexa > ' + JSON.stringify(message));
161
174
 
162
175
  if (!this.iface) {
@@ -173,7 +186,12 @@ module.exports = function (RED) {
173
186
  case 'TurnOn':
174
187
  case 'TurnOff':
175
188
  if (channelType.startsWith('DIMMER')) {
176
- this.ccu.setValueQueued(this.iface, this.channel, 'LEVEL', message.payload === 'ON' ? 1 : 0);
189
+ this.ccu.setValueQueued(
190
+ this.iface,
191
+ this.channel,
192
+ 'LEVEL',
193
+ message.payload === 'ON' ? 1 : 0,
194
+ );
177
195
  } else {
178
196
  this.ccu.setValueQueued(this.iface, this.channel, 'STATE', message.payload === 'ON');
179
197
  }
@@ -191,7 +209,12 @@ module.exports = function (RED) {
191
209
 
192
210
  case 'AdjustBrightness':
193
211
  if (channelType.startsWith('DIMMER')) {
194
- this.ccu.setValueQueued(this.iface, this.channel, 'LEVEL', (this.values.brightness + message.payload) / 100);
212
+ this.ccu.setValueQueued(
213
+ this.iface,
214
+ this.channel,
215
+ 'LEVEL',
216
+ (this.values.brightness + message.payload) / 100,
217
+ );
195
218
  } else {
196
219
  this.ccu.setValueQueued(this.iface, this.channel, 'STATE', message.payload > 0);
197
220
  }
@@ -206,7 +229,12 @@ module.exports = function (RED) {
206
229
  break;
207
230
 
208
231
  case 'HEATING_CLIMATECONTROL_TRANSCEIVER':
209
- this.ccu.setValueQueued(this.iface, this.channel, 'SET_POINT_TEMPERATURE', message.payload);
232
+ this.ccu.setValueQueued(
233
+ this.iface,
234
+ this.channel,
235
+ 'SET_POINT_TEMPERATURE',
236
+ message.payload,
237
+ );
210
238
  break;
211
239
 
212
240
  default:
@@ -226,10 +254,10 @@ module.exports = function (RED) {
226
254
 
227
255
  break;
228
256
 
229
- // Todo case 'SetColor':
230
- // Todo case 'SetColorTemperature':
231
- // Todo case 'AdjustTargetTemperature':
232
- // todo case 'SetThermostatMode':
257
+ // Todo case 'SetColor':
258
+ // Todo case 'SetColorTemperature':
259
+ // Todo case 'AdjustTargetTemperature':
260
+ // todo case 'SetThermostatMode':
233
261
 
234
262
  default:
235
263
  this.warn('unknown command ' + message.command);
@@ -11,6 +11,8 @@
11
11
  virtEnabled: {value: true},
12
12
  bcwiEnabled: {value: false},
13
13
  cuxdEnabled: {value: false},
14
+ jackEnabled: {value: false},
15
+ jackPort: {value: 2121},
14
16
 
15
17
  regaPoll: {value: true},
16
18
  regaInterval: {value: 30},
@@ -80,6 +82,7 @@
80
82
  $('#node-config-input-virtEnabled').prop('checked', ccu.interfaces.VirtualDevices);
81
83
  $('#node-config-input-bcwiEnabled').prop('checked', ccu.interfaces['BidCos-Wired']);
82
84
  $('#node-config-input-cuxdEnabled').prop('checked', ccu.interfaces.CuXD);
85
+ $('#node-config-input-jackEnabled').prop('checked', ccu.interfaces['CCU-Jack']);
83
86
  }
84
87
  });
85
88
  },
@@ -116,6 +119,8 @@
116
119
  }
117
120
  });
118
121
 
122
+ // called from the inline onclick attribute of the authentication checkbox
123
+ // eslint-disable-next-line no-unused-vars
119
124
  function TLSSSL(){
120
125
  if (document.getElementById('node-config-input-authentication').checked && !document.getElementById('node-config-input-tls').checked){
121
126
  document.getElementById('node-config-input-tls').checked = true
@@ -168,7 +173,9 @@
168
173
  <label class="ccu-checkbox"><input type="checkbox" id="node-config-input-bcwiEnabled"> BidCos-Wired</label><br>
169
174
  <label class="ccu-checkbox"><input type="checkbox" id="node-config-input-iprfEnabled"> HmIP-RF</label><br>
170
175
  <label class="ccu-checkbox"><input type="checkbox" id="node-config-input-virtEnabled"> VirtualDevices</label><br>
171
- <label class="ccu-checkbox"><input type="checkbox" id="node-config-input-cuxdEnabled"> CUxD</label>
176
+ <label class="ccu-checkbox"><input type="checkbox" id="node-config-input-cuxdEnabled"> CUxD</label><br>
177
+ <label class="ccu-checkbox"><input type="checkbox" id="node-config-input-jackEnabled"> CCU-Jack</label>
178
+ <input type="text" id="node-config-input-jackPort" style="width: 70px;" placeholder="2121">
172
179
  </div>
173
180
  </div>
174
181
  <div class="form-row">
@@ -254,6 +261,7 @@
254
261
  <li>HmIP-RF: Homematic-IP Funk</li>
255
262
  <li>VirtualDevices: Heizungsgruppen, in CCU eingebundene Systeme wie Osram Lightify</li>
256
263
  <li>CUxD</li>
264
+ <li>CCU-Jack: XMLRPC-Schnittstelle des <a href="https://github.com/mdzio/ccu-jack" target="_blank">CCU-Jack</a> Addons (Port konfigurierbar, Standard 2121 bzw. 2122 mit TLS)</li>
257
265
  </ul>
258
266
 
259
267
  </li>