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
@@ -101,6 +101,7 @@
101
101
 
102
102
  let ifacesLoaded = false;
103
103
  let ifacesPending = false;
104
+ let ifaceLoadRetries = 5;
104
105
 
105
106
  function loadIfaces(iface, cb) {
106
107
  if (ifacesPending) {
@@ -108,7 +109,6 @@
108
109
  }
109
110
 
110
111
  ifacesPending = true;
111
- console.log('loadIfaces()');
112
112
  $nodeInputIface.html('');
113
113
  const nodeId = $nodeInputCcuConfig.val();
114
114
  if (nodeId === '_ADD_') {
@@ -128,6 +128,12 @@
128
128
  cb();
129
129
  ifacesPending = false;
130
130
  }
131
+ }).fail(() => {
132
+ // config node not (yet) available in the runtime - allow retrying
133
+ ifacesPending = false;
134
+ if (ifaceLoadRetries-- > 0) {
135
+ setTimeout(() => loadIfaces(iface, cb), 1000);
136
+ }
131
137
  });
132
138
  }
133
139
  }
@@ -136,7 +142,6 @@
136
142
  if (ifacesLoaded) {
137
143
  const nodeId = $nodeInputCcuConfig.val();
138
144
  if (nodeId && nodeId !== '__ADD__') {
139
- console.log('loadConfig()');
140
145
  $.getJSON('ccu?type=display&config=' + nodeId + '&iface=' + $nodeInputIface.val(), d => {
141
146
  data = d;
142
147
  autoCompleteChannel();
@@ -148,7 +153,6 @@
148
153
  }
149
154
 
150
155
  $nodeInputCcuConfig.change(() => {
151
- console.log('$nodeInputCcuConfig change');
152
156
  loadIfaces(this.iface, () => {
153
157
  ifacesLoaded = true;
154
158
  $nodeInputIface.removeAttr('disabled');
@@ -156,6 +160,10 @@
156
160
  });
157
161
  });
158
162
 
163
+ // Node-RED 4.x does not reliably fire the change event on dialog
164
+ // open - trigger the initial load explicitly (see ROADMAP.md 8.1)
165
+ $nodeInputCcuConfig.trigger('change');
166
+
159
167
  $nodeInputIface.change(() => {
160
168
  if (ifacesLoaded) {
161
169
  loadConfig();
@@ -198,7 +206,6 @@
198
206
  });
199
207
  }
200
208
 
201
- console.log('autoCompleteChannel()', arr.length);
202
209
  $nodeInputChannel.autocomplete('option', 'source', arr);
203
210
  }
204
211
 
@@ -31,7 +31,7 @@ module.exports = function (RED) {
31
31
  gruen: '0x84',
32
32
  grün: '0x84',
33
33
  green: '0x84',
34
- blue: '0x85'
34
+ blue: '0x85',
35
35
  };
36
36
 
37
37
  if (map[col]) {
@@ -87,18 +87,33 @@ module.exports = function (RED) {
87
87
  'signal rot': '0x8B',
88
88
  red: '0x8B',
89
89
  signalred: '0x8B',
90
- 'signal red': '0x8B'
90
+ 'signal red': '0x8B',
91
91
  };
92
92
 
93
93
  if (map[ico]) {
94
94
  ico = map[ico];
95
95
  }
96
96
 
97
- if (!['0x80', '0x81', '0x82', '0x83', '0x84', '0x85', '0x86', '0x87', '0x88', '0x89', '0x8a', '0x8b'].includes(ico)) {
97
+ if (
98
+ ![
99
+ '0x80',
100
+ '0x81',
101
+ '0x82',
102
+ '0x83',
103
+ '0x84',
104
+ '0x85',
105
+ '0x86',
106
+ '0x87',
107
+ '0x88',
108
+ '0x89',
109
+ '0x8a',
110
+ '0x8b',
111
+ ].includes(ico)
112
+ ) {
98
113
  ico = '';
99
114
  }
100
115
 
101
- return ico ? (',0x13,' + ico) : '';
116
+ return ico ? ',0x13,' + ico : '';
102
117
  }
103
118
 
104
119
  function convertString(string) {
@@ -117,11 +132,11 @@ module.exports = function (RED) {
117
132
  ä: '0x7B',
118
133
  ö: '0x7C',
119
134
  ü: '0x7D',
120
- ß: '0x5F'
135
+ ß: '0x5F',
121
136
  };
122
137
  const res = [];
123
- string.split('').forEach(c => {
124
- res.push(charcodes[c] || ('0x' + c.charCodeAt(0).toString(16).toUpperCase()));
138
+ string.split('').forEach((c) => {
139
+ res.push(charcodes[c] || '0x' + c.charCodeAt(0).toString(16).toUpperCase());
125
140
  });
126
141
 
127
142
  return ',0x12,' + res.slice(0, 12).join(',');
@@ -163,10 +178,12 @@ module.exports = function (RED) {
163
178
 
164
179
  payload += ',0x03';
165
180
 
166
- this.ccu.setValue(config.iface, config.channel, 'SUBMIT', payload)
181
+ this.ccu
182
+ .setValue(config.iface, config.channel, 'SUBMIT', payload)
167
183
  .then(() => {
168
184
  done();
169
- }).catch(error => {
185
+ })
186
+ .catch((error) => {
170
187
  done(error);
171
188
  });
172
189
  });
@@ -46,6 +46,7 @@
46
46
 
47
47
  let ifacesLoaded = false;
48
48
  let ifacesPending = false;
49
+ let ifaceLoadRetries = 5;
49
50
 
50
51
  if (!this.setProp) {
51
52
  this.setProp = 'payload';
@@ -69,17 +70,17 @@
69
70
  $('.form-row.datapoint').hide();
70
71
  $('.form-row.sysvar').hide();
71
72
 
72
- const sysvarPropertys = ['value', 'valueEnum', 'ts', 'lc'];
73
- const datapointPropertys = ['value', 'ts', 'lc', 'working', 'direction', 'all'];
73
+ const sysvarProperties = ['value', 'valueEnum', 'ts', 'lc'];
74
+ const datapointProperties = ['value', 'ts', 'lc', 'working', 'direction', 'all'];
74
75
 
75
- sysvarPropertys.forEach(val => $nodeInputSysvarProperty.append(
76
+ sysvarProperties.forEach(val => $nodeInputSysvarProperty.append(
76
77
  $('<option></option>').val(val).text(node._('node-red-contrib-ccu/ccu-connection:common.label.' + val))
77
78
  ));
78
- datapointPropertys.forEach(val => $nodeInputDatapointProperty.append(
79
+ datapointProperties.forEach(val => $nodeInputDatapointProperty.append(
79
80
  $('<option></option>').val(val).text(node._('node-red-contrib-ccu/ccu-connection:common.label.' + val))
80
81
  ));
81
- $nodeInputSysvarProperty.val(node.sysvarProperty || sysvarPropertys[0]);
82
- $nodeInputDatapointProperty.val(node.datapointProperty || datapointPropertys[0]);
82
+ $nodeInputSysvarProperty.val(node.sysvarProperty || sysvarProperties[0]);
83
+ $nodeInputDatapointProperty.val(node.datapointProperty || datapointProperties[0]);
83
84
 
84
85
  function loadIfaces(iface, cb) {
85
86
  if (ifacesPending) {
@@ -87,7 +88,6 @@
87
88
  }
88
89
 
89
90
  ifacesPending = true;
90
- console.log('loadIfaces()');
91
91
 
92
92
  $nodeInputIface.html('');
93
93
 
@@ -108,6 +108,12 @@
108
108
  cb();
109
109
  ifacesPending = false;
110
110
  }
111
+ }).fail(() => {
112
+ // config node not (yet) available in the runtime - allow retrying
113
+ ifacesPending = false;
114
+ if (ifaceLoadRetries-- > 0) {
115
+ setTimeout(() => loadIfaces(iface, cb), 1000);
116
+ }
111
117
  });
112
118
  $.getJSON('ccu?type=sysvar&config=' + nodeId, data => {
113
119
  $nodeInputSysvar.html('<option></option>');
@@ -117,6 +123,8 @@
117
123
  });
118
124
  }
119
125
  });
126
+ } else {
127
+ ifacesPending = false;
120
128
  }
121
129
  }
122
130
 
@@ -125,7 +133,6 @@
125
133
  return;
126
134
  }
127
135
 
128
- console.log('loadConfig()');
129
136
  const nodeId = $nodeInputCcuConfig.val();
130
137
  const url = 'ccu?config=' + nodeId + '&type=channels&iface=' + $nodeInputIface.val();
131
138
  $.getJSON(url, d => {
@@ -136,13 +143,16 @@
136
143
  }
137
144
 
138
145
  $nodeInputCcuConfig.change(() => {
139
- console.log('$nodeInputCcuConfig change');
140
146
  loadIfaces(this.iface, () => {
141
147
  ifacesLoaded = true;
142
148
  loadConfig();
143
149
  });
144
150
  });
145
151
 
152
+ // Node-RED 4.x does not reliably fire the change event on dialog
153
+ // open - trigger the initial load explicitly (see ROADMAP.md 8.1)
154
+ $nodeInputCcuConfig.trigger('change');
155
+
146
156
  $nodeInputChannel.autocomplete({
147
157
  source: [],
148
158
  close: () => {
@@ -203,7 +213,6 @@
203
213
  }
204
214
 
205
215
  $nodeInputIface.change(() => {
206
- console.log('$nodeInputIface change');
207
216
  if ($nodeInputIface.val() === 'ReGaHSS') {
208
217
  $('.form-row.datapoint').hide();
209
218
  $('.form-row.sysvar').show();
@@ -313,7 +322,7 @@
313
322
  function getDPProp(dp) {
314
323
  const retVal = [];
315
324
 
316
- datapointPropertys.forEach(val => {
325
+ datapointProperties.forEach(val => {
317
326
  retVal.push({
318
327
  id: dp.id + '.' + val,
319
328
  label: node._('node-red-contrib-ccu/ccu-connection:common.label.' + val),
@@ -367,7 +376,7 @@
367
376
  icon: 'fa fa-tags fa-fw',
368
377
  children: done => {
369
378
  const retVal = [];
370
- sysvarPropertys.forEach(val => {
379
+ sysvarProperties.forEach(val => {
371
380
  retVal.push({
372
381
  label: node._('node-red-contrib-ccu/ccu-connection:common.label.' + val),
373
382
  icon: 'fa fa-tag fa-fw',
@@ -438,7 +447,7 @@
438
447
  <select id="node-input-sysvar" style="width:70%;">
439
448
  </select>
440
449
  </div>
441
- <div class="form-row sysvar">
450
+ <div class="form-row sysvar property">
442
451
  <label for="node-input-sysvarProperty"><i class="icon-tags"></i> Property</label>
443
452
  <select id="node-input-sysvarProperty" style="width:70%;">
444
453
  </select>
@@ -451,7 +460,7 @@
451
460
  <label for="node-input-datapoint"><i class="icon-tag"></i> Datapoint</label>
452
461
  <input type="text" id="node-input-datapoint">
453
462
  </div>
454
- <div class="form-row datapoint">
463
+ <div class="form-row datapoint property">
455
464
  <label for="node-input-datapointProperty"><i class="icon-tags"></i> Property</label>
456
465
  <select id="node-input-datapointProperty" style="width:70%;">
457
466
  </select>
@@ -39,17 +39,22 @@ module.exports = function (RED) {
39
39
  }
40
40
  }
41
41
 
42
- this.status({fill: 'green', shape: 'ring', text: String(value.payload)});
43
42
  if (config.setPropType === 'cmsg') {
44
43
  Object.assign(message, value);
45
44
  send(message);
46
-
45
+ this.status({fill: 'green', shape: 'ring', text: String(value.payload)});
47
46
  done();
48
47
  } else {
49
- if (config.datapointProperty !== 'all') {
48
+ if (iface === 'ReGaHSS') {
49
+ if (config.sysvarProperty !== 'all') {
50
+ value = value[config.sysvarProperty];
51
+ }
52
+ } else if (config.datapointProperty !== 'all') {
50
53
  value = value[config.datapointProperty];
51
54
  }
52
55
 
56
+ this.status({fill: 'green', shape: 'ring', text: String(value)});
57
+
53
58
  if (config.setPropType === 'msg') {
54
59
  RED.util.setMessageProperty(message, config.setProp, value);
55
60
  if (send) {
@@ -61,10 +66,10 @@ module.exports = function (RED) {
61
66
  if (done) {
62
67
  done();
63
68
  }
64
- } else if ((this.setPropType === 'flow') || (this.setPropType === 'global')) {
69
+ } else if (this.setPropType === 'flow' || this.setPropType === 'global') {
65
70
  const context = RED.util.parseContextStore(this.setProp);
66
71
  const target = this.context()[this.setPropType];
67
- target.set(context.key, value, context.store, err => {
72
+ target.set(context.key, value, context.store, (err) => {
68
73
  if (err) {
69
74
  done(err);
70
75
  } else {
@@ -8,19 +8,19 @@
8
8
 
9
9
  cache: {value: false},
10
10
 
11
- topicOutputEvent: {value: 'hm/status/${channelName}/${datapoint}'}, // eslint-disable-line no-template-curly-in-string
12
- topicInputSetValue: {value: 'hm/set/${channelNameOrAddress}/${datapoint}'}, // eslint-disable-line no-template-curly-in-string
11
+ topicOutputEvent: {value: 'hm/status/${channelName}/${datapoint}'},
12
+ topicInputSetValue: {value: 'hm/set/${channelNameOrAddress}/${datapoint}'},
13
13
 
14
- topicOutputSysvar: {value: 'hm/status/${name}'}, // eslint-disable-line no-template-curly-in-string
15
- topicInputSysvar: {value: 'hm/set/${name}'}, // eslint-disable-line no-template-curly-in-string
14
+ topicOutputSysvar: {value: 'hm/status/${name}'},
15
+ topicInputSysvar: {value: 'hm/set/${name}'},
16
16
 
17
- topicInputPutParam: {value: 'hm/paramset/${channelNameOrAddress}/${paramset}/${param}'}, // eslint-disable-line no-template-curly-in-string
18
- topicInputPutParamset: {value: 'hm/paramset/${channelNameOrAddress}/${paramset}'}, // eslint-disable-line no-template-curly-in-string
17
+ topicInputPutParam: {value: 'hm/paramset/${channelNameOrAddress}/${paramset}/${param}'},
18
+ topicInputPutParamset: {value: 'hm/paramset/${channelNameOrAddress}/${paramset}'},
19
19
 
20
- topicInputRpc: {value: 'hm/rpc/${iface}/${method}/${command}/${callid}'}, // eslint-disable-line no-template-curly-in-string
21
- topicOutputRpc: {value: 'hm/response/${callid}'}, // eslint-disable-line no-template-curly-in-string
20
+ topicInputRpc: {value: 'hm/rpc/${iface}/${method}/${command}/${callid}'},
21
+ topicOutputRpc: {value: 'hm/response/${callid}'},
22
22
 
23
- topicCounters: {value: 'hm/status/counter/${iface}/${rxtx}'}, // eslint-disable-line no-template-curly-in-string
23
+ topicCounters: {value: 'hm/status/counter/${iface}/${rxtx}'},
24
24
 
25
25
  payloadOutput: {value: 'mqsh-extended'}
26
26
  },
@@ -37,7 +37,6 @@
37
37
  return this.name ? 'node_label_italic' : '';
38
38
  },
39
39
  oneditsave() {
40
- console.log(this);
41
40
  }
42
41
  });
43
42
  </script>
package/nodes/ccu-mqtt.js CHANGED
@@ -33,19 +33,19 @@ module.exports = function (RED) {
33
33
 
34
34
  this.ccu.register(this);
35
35
 
36
- this.on('input', message => {
36
+ this.on('input', (message) => {
37
37
  this.input(message);
38
38
  });
39
39
 
40
- this.idEventSubscription = this.ccu.subscribe({cache: config.cache}, message => {
40
+ this.idEventSubscription = this.ccu.subscribe({cache: config.cache}, (message) => {
41
41
  this.event(message);
42
42
  });
43
43
 
44
- this.idSysvarSubscription = this.ccu.subscribeSysvar({cache: config.cache, change: true}, message => {
44
+ this.idSysvarSubscription = this.ccu.subscribeSysvar({cache: config.cache, change: true}, (message) => {
45
45
  this.sysvarOutput(message);
46
46
  });
47
47
 
48
- this.idProgramSubscription = this.ccu.subscribeProgram({}, message => {
48
+ this.idProgramSubscription = this.ccu.subscribeProgram({}, (message) => {
49
49
  this.programOutput(message);
50
50
  });
51
51
 
@@ -53,9 +53,17 @@ module.exports = function (RED) {
53
53
 
54
54
  if (this.topicCounters) {
55
55
  setTimeout(() => {
56
- this.ccu.enabledIfaces.forEach(iface => {
57
- this.send({topic: this.ccu.topicReplace(this.topicCounters, {iface, rxtx: 'rx'}), payload: '0', retain: true});
58
- this.send({topic: this.ccu.topicReplace(this.topicCounters, {iface, rxtx: 'tx'}), payload: '0', retain: true});
56
+ this.ccu.enabledIfaces.forEach((iface) => {
57
+ this.send({
58
+ topic: this.ccu.topicReplace(this.topicCounters, {iface, rxtx: 'rx'}),
59
+ payload: '0',
60
+ retain: true,
61
+ });
62
+ this.send({
63
+ topic: this.ccu.topicReplace(this.topicCounters, {iface, rxtx: 'tx'}),
64
+ payload: '0',
65
+ retain: true,
66
+ });
59
67
  });
60
68
  }, 25000);
61
69
  setInterval(() => {
@@ -75,7 +83,7 @@ module.exports = function (RED) {
75
83
  }
76
84
 
77
85
  checkCounters(c) {
78
- Object.keys(this.ccu[c]).forEach(iface => {
86
+ Object.keys(this.ccu[c]).forEach((iface) => {
79
87
  if (this.ccu[c][iface] !== this[c][iface]) {
80
88
  this[c][iface] = this.ccu[c][iface];
81
89
  const topic = this.ccu.topicReplace(this.topicCounters, {iface, rxtx: c.slice(0, 2)});
@@ -98,7 +106,11 @@ module.exports = function (RED) {
98
106
  const messageNotWorking = RED.util.cloneMessage(message);
99
107
  messageNotWorking.datapoint += '_NOTWORKING';
100
108
  messageNotWorking.datapointName += '_NOTWORKING';
101
- this.send({topic: this.ccu.topicReplace(this.topicOutputEvent, messageNotWorking), payload: this.output(messageNotWorking), retain: true});
109
+ this.send({
110
+ topic: this.ccu.topicReplace(this.topicOutputEvent, messageNotWorking),
111
+ payload: this.output(messageNotWorking),
112
+ retain: true,
113
+ });
102
114
  }
103
115
  }
104
116
 
@@ -119,7 +131,7 @@ module.exports = function (RED) {
119
131
  return {
120
132
  val: message.payload,
121
133
  ts: message.ts,
122
- lc: message.lc
134
+ lc: message.lc,
123
135
  };
124
136
  }
125
137
 
@@ -128,7 +140,7 @@ module.exports = function (RED) {
128
140
  val: message.payload,
129
141
  ts: message.ts,
130
142
  lc: message.lc,
131
- hm: message
143
+ hm: message,
132
144
  };
133
145
  delete payload.hm.topic;
134
146
  delete payload.hm.payload;
@@ -156,21 +168,21 @@ module.exports = function (RED) {
156
168
  sysvar: this.topicInputSysvar,
157
169
  putParam: this.topicInputPutParam,
158
170
  putParamset: this.topicInputPutParamset,
159
- rpc: this.topicInputRpc
171
+ rpc: this.topicInputRpc,
160
172
  };
161
173
 
162
174
  let command;
163
175
  let filter;
164
- Object.keys(topicList).forEach(key => {
176
+ Object.keys(topicList).forEach((key) => {
165
177
  if (!command) {
166
178
  const parts = topicList[key].split('/');
167
179
  const patternArray = [];
168
180
  const placeholders = [];
169
181
  for (let i = 0, {length} = parts; i < length; i++) {
170
182
  let match;
171
- if (match = parts[i].match(/^\${([\w-]+)}$/)) { // eslint-disable-line no-cond-assign
183
+ if ((match = parts[i].match(/^\${([\w-]+)}$/))) {
172
184
  placeholders.push(match[1]);
173
- patternArray[i] = (i + 1) < length ? '+' : '#';
185
+ patternArray[i] = i + 1 < length ? '+' : '#';
174
186
  } else {
175
187
  patternArray[i] = parts[i];
176
188
  }
@@ -180,7 +192,10 @@ module.exports = function (RED) {
180
192
  const match = mw(topic, pattern);
181
193
  if (match && match.length === placeholders.length) {
182
194
  command = key;
183
- filter = Object.assign.apply({}, placeholders.map((v, i) => ({[v]: match[i]})));
195
+ filter = Object.assign.apply(
196
+ {},
197
+ placeholders.map((v, i) => ({[v]: match[i]})),
198
+ );
184
199
  }
185
200
  }
186
201
  });
@@ -264,10 +279,14 @@ module.exports = function (RED) {
264
279
  return;
265
280
  }
266
281
 
267
- const psName = this.ccu.paramsetName(iface, this.ccu.metadata.devices[iface][filter.channel], filter.paramset);
282
+ const psName = this.ccu.paramsetName(
283
+ iface,
284
+ this.ccu.metadata.devices[iface][filter.channel],
285
+ filter.paramset,
286
+ );
268
287
  const paramsetDescription = this.ccu.paramsetDescriptions[psName];
269
288
  if (paramsetDescription && paramsetDescription[filter.param]) {
270
- if (!(paramsetDescription[filter.param].OPERATIONS) && 2) {
289
+ if (!paramsetDescription[filter.param].OPERATIONS && 2) {
271
290
  this.error('param ' + filter.param + ' not writeable');
272
291
  }
273
292
 
@@ -279,8 +298,9 @@ module.exports = function (RED) {
279
298
  const paramset = {};
280
299
  paramset[filter.param] = payload;
281
300
 
282
- this.ccu.methodCall(iface, 'putParamset', [filter.channel, filter.paramset, paramset])
283
- .catch(error => this.error(error.message));
301
+ this.ccu
302
+ .methodCall(iface, 'putParamset', [filter.channel, filter.paramset, paramset])
303
+ .catch((error) => this.error(error.message));
284
304
  }
285
305
 
286
306
  putParamset(filter, payload) {
@@ -314,14 +334,18 @@ module.exports = function (RED) {
314
334
  return;
315
335
  }
316
336
 
317
- const psName = this.ccu.paramsetName(iface, this.ccu.metadata.devices[iface][filter.channel], filter.paramset);
337
+ const psName = this.ccu.paramsetName(
338
+ iface,
339
+ this.ccu.metadata.devices[iface][filter.channel],
340
+ filter.paramset,
341
+ );
318
342
  const paramsetDescription = this.ccu.paramsetDescriptions[psName];
319
343
 
320
344
  const paramset = {};
321
345
 
322
- Object.keys(payload).forEach(parameter => {
346
+ Object.keys(payload).forEach((parameter) => {
323
347
  if (paramsetDescription && paramsetDescription[parameter]) {
324
- if (!(paramsetDescription[parameter].OPERATIONS) && 2) {
348
+ if (!paramsetDescription[parameter].OPERATIONS && 2) {
325
349
  this.error('param ' + parameter + ' not writeable');
326
350
  }
327
351
 
@@ -332,19 +356,21 @@ module.exports = function (RED) {
332
356
  }
333
357
  });
334
358
 
335
- this.ccu.methodCall(iface, 'putParamset', [filter.channel, filter.paramset, paramset])
336
- .catch(error => this.error(error.message));
359
+ this.ccu
360
+ .methodCall(iface, 'putParamset', [filter.channel, filter.paramset, paramset])
361
+ .catch((error) => this.error(error.message));
337
362
  }
338
363
 
339
364
  paramCast(value, paramset) {
340
365
  switch (paramset && paramset.TYPE) {
341
366
  case 'BOOL':
342
- // Fallthrough by intention
367
+ // Fallthrough by intention
343
368
  case 'ACTION':
344
369
  // OMG this is so ugly...
345
370
  if (value === 'false') {
346
371
  value = false;
347
- } else if (!isNaN(value)) { // Make sure that the string "0" gets casted to boolean false
372
+ } else if (!isNaN(value)) {
373
+ // Make sure that the string "0" gets casted to boolean false
348
374
  value = Number(value);
349
375
  }
350
376
 
@@ -362,12 +388,12 @@ module.exports = function (RED) {
362
388
  break;
363
389
  case 'ENUM':
364
390
  if (typeof value === 'string') {
365
- if (paramset.ENUM && (paramset.ENUM.includes(value))) {
391
+ if (paramset.ENUM && paramset.ENUM.includes(value)) {
366
392
  value = paramset.ENUM.indexOf(value);
367
393
  }
368
394
  }
369
395
 
370
- // Fallthrough by intention
396
+ // Fallthrough by intention
371
397
  case 'INTEGER':
372
398
  value = Number.parseInt(value, 10);
373
399
  if (value < paramset.MIN) {
@@ -5,7 +5,7 @@
5
5
  defaults: {
6
6
  name: {value: ''},
7
7
  ccuConfig: {value: 'localhost', type: 'ccu-connection', required: true},
8
- topic: {value: 'ReGaHSS/${Name}'} // eslint-disable-line no-template-curly-in-string
8
+ topic: {value: 'ReGaHSS/${Name}'}
9
9
  },
10
10
  inputs: 1,
11
11
  outputs: 1,
@@ -19,7 +19,7 @@ module.exports = function (RED) {
19
19
  this.name = config.name;
20
20
 
21
21
  if (this.name) {
22
- this.idSubscription = this.ccu.subscribeProgram(this.name, message => {
22
+ this.idSubscription = this.ccu.subscribeProgram(this.name, (message) => {
23
23
  message.topic = this.ccu.topicReplace(config.topic, message);
24
24
  this.send(message);
25
25
  });
@@ -32,27 +32,29 @@ module.exports = function (RED) {
32
32
  _input(message, send, done) {
33
33
  switch (typeof message.payload) {
34
34
  case 'boolean':
35
- this.ccu.programActive(this.name || message.topic, message.payload)
36
- .then(message_ => {
35
+ this.ccu
36
+ .programActive(this.name || message.topic, message.payload)
37
+ .then((message_) => {
37
38
  send(message_);
38
39
 
39
40
  this.status({fill: 'green', shape: 'dot', text: 'connected'});
40
41
  done();
41
42
  })
42
- .catch(error => {
43
+ .catch((error) => {
43
44
  this.status({fill: 'red', shape: 'dot', text: 'error'});
44
45
  done(error);
45
46
  });
46
47
  break;
47
48
  default:
48
- this.ccu.programExecute(this.name || message.topic)
49
- .then(message => {
49
+ this.ccu
50
+ .programExecute(this.name || message.topic)
51
+ .then((message) => {
50
52
  send(message);
51
53
 
52
54
  this.status({fill: 'green', shape: 'dot', text: 'connected'});
53
55
  done();
54
56
  })
55
- .catch(error => {
57
+ .catch((error) => {
56
58
  this.status({fill: 'red', shape: 'dot', text: 'error'});
57
59
  done(error);
58
60
  });