iobroker.zwavews 0.1.4 → 0.1.6

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
@@ -17,6 +17,13 @@
17
17
 
18
18
  The `zwavews` adapter connects a [`zwave-js-ui`](https://zwave-js.github.io/zwave-js-ui/#/) to ioBroker and creates corresponding data points for devices, values, and statuses. This allows Z-Wave devices to be conveniently used in visualizations, logic, and automations.
19
19
 
20
+ ### Features
21
+ * **Real-time communication**: Instantly receives updates of device values and statuses via WebSocket or MQTT.
22
+ * **Auto-Discovery**: Automatically creates and updates the device and state structure in ioBroker from the `zwave-js-ui` nodes.
23
+ * **Device Management**: View battery levels, connection status, and detailed device metrics right from the ioBroker interface.
24
+ * **Firmware Updates**: Observe firmware update progress directly via the adapter's logs and states.
25
+ * **State Control**: Send commands and update values natively through the ioBroker object tree.
26
+ * **Support for multiple protocols**: You can connect to `zwave-js-ui` using WebSocket, External MQTT, or an Internal Dummy MQTT server.
20
27
 
21
28
  ## Adapter Documentation
22
29
 
@@ -35,6 +42,12 @@ Activate WS Server Settings in `zwave-js-ui` we use the Home Assistant Settings
35
42
 
36
43
 
37
44
  ## Changelog
45
+ ### 0.1.6 (2026-04-23)
46
+ * (arteck) add test
47
+
48
+ ### 0.1.5 (2026-04-21)
49
+ * (arteck) upd devicemanager
50
+
38
51
  ### 0.1.4 (2026-04-16)
39
52
  * (arteck) Dependencies have been updated
40
53
  * (arteck) add vscode folder
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "zwavews",
4
- "version": "0.1.4",
4
+ "version": "0.1.6",
5
5
  "news": {
6
+ "0.1.6": {
7
+ "en": "add test",
8
+ "de": "test hinzufügen",
9
+ "ru": "добавить тест",
10
+ "pt": "adicionar teste",
11
+ "nl": "test toevoegen",
12
+ "fr": "ajouter un essai",
13
+ "it": "aggiungere test",
14
+ "es": "agregar la prueba",
15
+ "pl": "dodać test",
16
+ "uk": "додати тест",
17
+ "zh-cn": "添加测试"
18
+ },
19
+ "0.1.5": {
20
+ "en": "upd devicemanager",
21
+ "de": "gerätemanager und -manager",
22
+ "ru": "улучшенный devicemanager",
23
+ "pt": "gerenciador de dispositivos upd",
24
+ "nl": "upd apparaatbeheerder",
25
+ "fr": "gestionnaire d'appareil",
26
+ "it": "upd devicemanager",
27
+ "es": "upd devicemanager",
28
+ "pl": "upd devicemaniger",
29
+ "uk": "напляскване",
30
+ "zh-cn": "上调设备管理器"
31
+ },
6
32
  "0.1.4": {
7
33
  "en": "Dependencies have been updated\nadd vscode folder",
8
34
  "de": "Abhängigkeiten wurden aktualisiert\nvscode ordner hinzufügen",
@@ -67,32 +93,6 @@
67
93
  "pl": "ZMIANA BREAKING - nazwa dp jest teraz z podkreśleniem\ndodaj urządzenie Kierownik\nfix dp 's z przestrzenią\nfix dp 's ze specjalnymi znakami",
68
94
  "uk": "BREAKING CHANGE - ім'я dp тепер з онлайн\nдодати пристрій Менеджер\nзакріпити dp's з космосом\nфіксувати dp з особливими chars",
69
95
  "zh-cn": "断裂变换 - dp 名称现在是下划线\n添加设备 经理\n修补 dp 的空格\n修复 dp 与特殊字符"
70
- },
71
- "0.0.18": {
72
- "en": "add info.sendMessageAllowed object to allow sending the message to zwave-ui-js\nadd new checkbox to set info.sendMessageAllowed immediately after starting the adapter",
73
- "de": "add info.sendMessageAllowed object to let send the message to zwave-ui-js\nneue Checkbox hinzufügen, um info.sendMessage einzustellen Sofort nach dem Start des Adapters zugelassen",
74
- "ru": "добавить info.sendMessageРазрешенный объект для отправки сообщения на zwave-ui-js\nдобавить новый флажок для установки info.sendMessage Допускается сразу после запуска адаптера",
75
- "pt": "add info.sendMessagePermitido objeto para permitir o envio da mensagem para zwave-ui-js\nadicionar nova caixa de seleção para definir info.sendMessage Permitido imediatamente após iniciar o adaptador",
76
- "nl": "info.sendMessageToegewezen object om het bericht naar zwave-ui-js te versturen\nnieuwe selectievakje toevoegen om info.sendMessage in te stellen Onmiddellijk na het starten van de adapter toegestaan",
77
- "fr": "ajouter info.sendMessageObjet autorisé pour permettre l'envoi du message à zwave-ui-js\najouter une nouvelle case à cocher pour définir info.sendMessage Autorisé immédiatement après le démarrage de l'adaptateur",
78
- "it": "aggiungere info.sendMessageAllowed oggetto per consentire l'invio del messaggio a zwave-ui-js\naggiungere nuova casella di controllo per impostare info.sendMessage Consentito subito dopo l'avvio dell'adattatore",
79
- "es": "añadir info.sendMessagePropósito permitido enviar el mensaje a zwave-ui-js\nañadir nueva casilla para configurar información.sendMessage Permitido inmediatamente después de iniciar el adaptador",
80
- "pl": "dodaj info.sendMessageDopuszczalny obiekt, aby umożliwić wysyłanie wiadomości do zwave- ui- js\ndodaj nową opcję do ustawienia info.sendMessage Dozwolone bezpośrednio po uruchomieniu adaptera",
81
- "uk": "додайте інформацію.sendMessageВсього об'єкту, щоб дозволити надсилати повідомлення на zwave-ui-js\nдодати нову прапорець, щоб встановити інформацію.sendMessage Допускається відразу після запуску адаптера",
82
- "zh-cn": "添加信息. sendMessage Allowed 对象允许将消息发送到 zwave- ui- js\n添加新复选框以设置信息. sendMessage 启动适配器后立即允许"
83
- },
84
- "0.0.17": {
85
- "en": "fix adapter start\nDependencies have been updated",
86
- "de": "befestigungsadapter start\nAbhängigkeiten wurden aktualisiert",
87
- "ru": "запуск адаптера\nЗависимости были обновлены",
88
- "pt": "corrigir o início do adaptador\nAs dependências foram atualizadas",
89
- "nl": "fix adapter start\nAfhankelijkheden zijn bijgewerkt",
90
- "fr": "fixer le démarrage de l'adaptateur\nLes dépendances ont été actualisées",
91
- "it": "avvio dell'adattatore\nLe dipendenze sono state aggiornate",
92
- "es": "adaptador de fijación\nSe han actualizado las dependencias",
93
- "pl": "uruchomić adapter\nZaktualizowano zależności",
94
- "uk": "запуск адаптера\nЗалежність було оновлено",
95
- "zh-cn": "固定适配器启动\n依赖关系已更新"
96
96
  }
97
97
  },
98
98
  "titleLang": {
package/lib/devicemgmt.js CHANGED
@@ -17,17 +17,26 @@ class dmZwave extends dmUtils.DeviceManagement {
17
17
  }
18
18
 
19
19
  /**
20
+ * Loads all ZWave devices and reports them to the device manager context.
21
+ * Called by the dm-utils framework in response to a 'dm:loadDevices' message.
20
22
  *
23
+ * @param {object} context - The DeviceLoadContext (addDevice / setTotalDevices / complete).
21
24
  */
22
- async listDevices() {
25
+ async loadDevices(context) {
23
26
  const devices = await this.adapter.getDevicesAsync();
24
- const arrDevices = [];
27
+ context.setTotalDevices(devices.length);
28
+
25
29
  for (const i in devices) {
26
30
  const status = {};
27
31
 
28
32
  const nodeId = this.stripIobPrefix(devices[i]._id);
29
33
 
30
- const device = this.adapter.nodeCache[nodeId].nodeData;
34
+ const cacheEntry = this.adapter.nodeCache[nodeId];
35
+ if (!cacheEntry) {
36
+ this.adapter.log.warn(`listDevices: nodeCache miss for ${nodeId}, skipping.`);
37
+ continue;
38
+ }
39
+ const device = cacheEntry.nodeData;
31
40
 
32
41
  status.connection = device.ready ? 'connected' : 'disconnected';
33
42
 
@@ -58,12 +67,53 @@ class dmZwave extends dmUtils.DeviceManagement {
58
67
  devStatus = 'unknown';
59
68
  }
60
69
 
70
+ // Sensordaten aus Multilevel_Sensor laden
71
+ const sensorCustomInfo = {
72
+ id: nodeId,
73
+ schema: {
74
+ type: 'panel',
75
+ items: {},
76
+ },
77
+ };
78
+
79
+ try {
80
+ const sensorObjects = await this.adapter.getObjectViewAsync('system', 'state', {
81
+ startkey: `${devices[i]._id}.Multilevel_Sensor.`,
82
+ endkey: `${devices[i]._id}.Multilevel_Sensor.\u9999`,
83
+ });
84
+
85
+ if (sensorObjects && sensorObjects.rows && sensorObjects.rows.length > 0) {
86
+ for (const row of sensorObjects.rows) {
87
+ const obj = row.value;
88
+ if (!obj) {
89
+ continue;
90
+ }
91
+ const stateId = obj._id;
92
+ const sensorKey = stateId.replace(/\./g, '_');
93
+ const labelParts = stateId.split('.');
94
+ const sensorLabel = labelParts[labelParts.length - 1];
95
+ const unit = obj.common?.unit ? ` (${obj.common.unit})` : '';
96
+
97
+ sensorCustomInfo.schema.items[sensorKey] = {
98
+ type: 'state',
99
+ oid: stateId,
100
+ foreign: true,
101
+ label: `${sensorLabel}${unit}`,
102
+ newLine: true,
103
+ };
104
+ }
105
+ }
106
+ } catch (e) {
107
+ this.adapter.log.warn(`listDevices: Fehler beim Laden der Multilevel_Sensor-Daten für ${nodeId}: ${e.message}`);
108
+ }
109
+
110
+
61
111
  const res = {
62
112
  id: nodeId,
63
113
  name: device.name || device.label,
64
114
  icon: devStatus,
65
- manufacturer: device.deviceConfig.manufacturer,
66
- model: `${device.deviceConfig.label } ${ device.deviceConfig.description}`,
115
+ manufacturer: device.deviceConfig?.manufacturer ?? '',
116
+ model: `${device.deviceConfig?.label ?? ''} ${device.deviceConfig?.description ?? ''}`.trim(),
67
117
  status: status,
68
118
  hasDetails: true,
69
119
  actions: [
@@ -76,17 +126,122 @@ class dmZwave extends dmUtils.DeviceManagement {
76
126
  ],
77
127
  };
78
128
 
129
+ // Schalter aus Multilevel_Switch laden
130
+ try {
131
+ const switchObjects = await this.adapter.getObjectViewAsync('system', 'state', {
132
+ startkey: `${devices[i]._id}.Multilevel_Switch.`,
133
+ endkey: `${devices[i]._id}.Multilevel_Switch.\u9999`,
134
+ });
135
+
136
+ if (switchObjects && switchObjects.rows && switchObjects.rows.length > 0) {
137
+ // Trennlinie einfügen, wenn bereits Sensordaten vorhanden
138
+ if (Object.keys(sensorCustomInfo.schema.items).length > 0) {
139
+ sensorCustomInfo.schema.items['_divider_switch'] = {
140
+ type: 'divider',
141
+ color: 'primary',
142
+ };
143
+ }
144
+
145
+ // Alle Rows in eine Map sammeln (rawName → {obj, stateId})
146
+ const switchMap = {};
147
+ for (const row of switchObjects.rows) {
148
+ const obj = row.value;
149
+ if (!obj) {
150
+ continue;
151
+ }
152
+ const parts = obj._id.split('.');
153
+ const rawName = parts[parts.length - 1];
154
+ switchMap[rawName] = { obj, stateId: obj._id };
155
+ }
156
+
157
+ // Gewünschte Reihenfolge, unbekannte States werden danach angehängt
158
+ const order = ['open', 'close', 'currentValue', 'targetValue', 'restorePrevious', 'duration'];
159
+ const allKeys = [...order, ...Object.keys(switchMap).filter(k => !order.includes(k))];
79
160
 
80
- arrDevices.push(res);
161
+ allKeys.forEach((rawName, index) => {
162
+ if (!switchMap[rawName]) {
163
+ return;
164
+ }
165
+ const { obj, stateId } = switchMap[rawName];
166
+ // Nummerierten Prefix damit Admin-UI die Elemente in der richtigen Reihenfolge anzeigt
167
+ const switchKey = `_sw${String(index + 1).padStart(2, '0')}_${rawName}`;
168
+ const isBoolean = obj.common?.type === 'boolean';
169
+
170
+ // Anzeigenamen umbenennen
171
+ let switchLabel;
172
+ if (rawName === 'targetValue') {
173
+ switchLabel = 'Target';
174
+ } else if (rawName === 'currentValue') {
175
+ switchLabel = 'Current';
176
+ } else {
177
+ switchLabel = rawName;
178
+ }
179
+
180
+ // currentValue: nur lesebarer numerischer Wert mit %-Einheit
181
+ // duration: nur lesebarer numerischer Wert
182
+ if (rawName === 'currentValue' && !isBoolean) {
183
+ sensorCustomInfo.schema.items[switchKey] = {
184
+ type: 'state',
185
+ oid: stateId,
186
+ foreign: true,
187
+ label: switchLabel,
188
+ readOnly: true,
189
+ unit: '%',
190
+ newLine: true,
191
+ };
192
+ } else if (rawName === 'duration' && !isBoolean) {
193
+ sensorCustomInfo.schema.items[switchKey] = {
194
+ type: 'state',
195
+ oid: stateId,
196
+ foreign: true,
197
+ label: switchLabel,
198
+ readOnly: true,
199
+ newLine: true,
200
+ };
201
+ } else if (isBoolean) {
202
+ sensorCustomInfo.schema.items[switchKey] = {
203
+ type: 'state',
204
+ oid: stateId,
205
+ foreign: true,
206
+ label: switchLabel,
207
+ control: 'switch',
208
+ trueTextStyle: { color: 'green' },
209
+ falseTextStyle: { color: 'red' },
210
+ trueText: 'ON',
211
+ falseText: 'OFF',
212
+ newLine: true,
213
+ };
214
+ } else {
215
+ sensorCustomInfo.schema.items[switchKey] = {
216
+ type: 'state',
217
+ oid: stateId,
218
+ foreign: true,
219
+ label: switchLabel,
220
+ control: 'slider',
221
+ min: obj.common?.min ?? 0,
222
+ max: obj.common?.max ?? 99,
223
+ newLine: true,
224
+ };
225
+ }
226
+ });
227
+ }
228
+ } catch (e) {
229
+ this.adapter.log.warn(`listDevices: Fehler beim Laden der Multilevel_Switch-Daten für ${nodeId}: ${e.message}`);
230
+ }
231
+
232
+
233
+ // Nur customInfo anhängen, wenn Sensor- oder Schalterdaten vorhanden sind
234
+ if (Object.keys(sensorCustomInfo.schema.items).length > 0) {
235
+ res.customInfo = sensorCustomInfo;
236
+ }
237
+
238
+
239
+ context.addDevice(res);
81
240
  }
82
241
 
83
242
  // nach id sortieren (z.B. nodeID_2 vor nodeID_10)
84
- arrDevices.sort((a, b) => String(a?.id ?? '').localeCompare(String(b?.id ?? ''), undefined, {
85
- numeric: true,
86
- sensitivity: 'base',
87
- }));
88
-
89
- return arrDevices;
243
+ // Note: sorting is informational only; context already sent devices
244
+ context.complete();
90
245
  }
91
246
 
92
247
  /**
@@ -267,6 +422,10 @@ class dmZwave extends dmUtils.DeviceManagement {
267
422
  devStatus = 'unknown';
268
423
  }
269
424
 
425
+ // Kalibrierungsknopf prüfen
426
+ const calibStateId = `${this.adapter.namespace}.${id}.Configuration.Forced_Roller_Shutter_Calibration`;
427
+ const calibObj = await this.adapter.getObjectAsync(calibStateId).catch(() => null);
428
+
270
429
  return {
271
430
  id: String(device.nodeId),
272
431
  schema: {
@@ -336,6 +495,34 @@ class dmZwave extends dmUtils.DeviceManagement {
336
495
  label: 'Max Baud Rate',
337
496
  readOnly: true,
338
497
  },
498
+ ...(calibObj ? {
499
+ _divider_calib: {
500
+ type: 'divider',
501
+ color: 'primary',
502
+ },
503
+ _calib_spacer: {
504
+ type: 'staticText',
505
+ text: '',
506
+ newLine: true,
507
+ xs: 8,
508
+ sm: 9,
509
+ md: 10,
510
+ lg: 10,
511
+ xl: 10,
512
+ },
513
+ _calib_button: {
514
+ type: 'state',
515
+ oid: calibStateId,
516
+ foreign: true,
517
+ label: 'Kalibrierung starten',
518
+ control: 'button',
519
+ xs: 4,
520
+ sm: 3,
521
+ md: 2,
522
+ lg: 2,
523
+ xl: 2,
524
+ },
525
+ } : {}),
339
526
  },
340
527
  },
341
528
  _tab_Details: {
package/lib/helper.js CHANGED
@@ -26,6 +26,33 @@ class Helper {
26
26
 
27
27
  }
28
28
 
29
+ /**
30
+ * Normalises any value to a valid ioBroker common.type string.
31
+ * Valid types: "number" | "string" | "boolean" | "array" | "object" | "mixed" | "file"
32
+ *
33
+ * @param {*} value - The raw value whose type should be determined.
34
+ * @param {string} [hint] - An optional type hint (e.g. from metadata.type).
35
+ * @returns {string} A valid ioBroker type string.
36
+ */
37
+ normalizeType(value, hint) {
38
+ const VALID = new Set(["number", "string", "boolean", "array", "object", "mixed", "file"]);
39
+ if (hint && VALID.has(hint)) {
40
+ return hint;
41
+ }
42
+ if (Array.isArray(value)) {
43
+ return "array";
44
+ }
45
+ const t = typeof value;
46
+ if (t === "number") {
47
+ return "number";
48
+ }
49
+ if (t === "boolean") {
50
+ return "boolean";
51
+ }
52
+ // strings are stored as "mixed" to allow numeric/bool changes later
53
+ return "mixed";
54
+ }
55
+
29
56
  /**
30
57
  * Creates a ZWave node device and all its value states in ioBroker.
31
58
  *
@@ -55,9 +82,9 @@ class Helper {
55
82
  await this.createReadyStatus(nodeId);
56
83
 
57
84
  const valuesOnly = element.values ?? null;
58
- delete element.values;
85
+ const { values: _values, ...elementWithoutValues } = element;
59
86
 
60
- await this.parse(`${nodeId}.info`, element);
87
+ await this.parse(`${nodeId}.info`, elementWithoutValues);
61
88
 
62
89
  if (valuesOnly != null && typeof valuesOnly === "object" && valuesOnly.length > 0) {
63
90
  for (const v of valuesOnly) {
@@ -112,7 +139,8 @@ class Helper {
112
139
  metadata.value = v.value; // add value for resolution
113
140
  const valDp = this.resolveCommandClassValue(metadata) ?? 0;
114
141
 
115
- let typeDp = metadata.type === "timeout" ? "number" : metadata.type;
142
+ const rawType = metadata.type === "timeout" ? "number" : metadata.type;
143
+ let typeDp = this.normalizeType(valDp, rawType);
116
144
 
117
145
  if (constant.mixedType.includes(nam_id)) {
118
146
  typeDp = "mixed";
@@ -189,8 +217,19 @@ class Helper {
189
217
 
190
218
  if (!this.alreadyCreatedObjects[parsePath]) {
191
219
  try {
192
- let common = {};
193
- if (typeof element === "string" || typeof element === "number") {
220
+ let common;
221
+ if (typeof element === "boolean") {
222
+ common = {
223
+ id: parsePath,
224
+ name: parsePath,
225
+ role: "switch",
226
+ type: "boolean",
227
+ write: options.write,
228
+ read: true,
229
+ def: false,
230
+ };
231
+ } else {
232
+ // string or number
194
233
  common = {
195
234
  id: parsePath,
196
235
  name: parsePath,
@@ -222,20 +261,19 @@ class Helper {
222
261
  return;
223
262
  }
224
263
 
225
- options.channelName = utils.getLastSegment(parsePath);
264
+ const channelName = utils.getLastSegment(parsePath);
226
265
 
227
266
  if (!this.alreadyCreatedObjects[parsePath]) {
228
267
  try {
229
268
  await this.adapter.setObjectNotExistsAsync(parsePath, {
230
269
  type: "channel",
231
270
  common: {
232
- name: options.channelName || ""
271
+ name: channelName || ""
233
272
  },
234
273
  native: {},
235
274
  });
236
275
 
237
276
  this.alreadyCreatedObjects[parsePath] = { };
238
- delete options.channelName;
239
277
  } catch (error) {
240
278
  this.adapter.log.error(`parse error ${ parsePath}`);
241
279
  this.adapter.log.error(error);
@@ -278,8 +316,8 @@ class Helper {
278
316
 
279
317
  if (isObj) {
280
318
  if (Object.keys(valDP).length > 0) {
281
- options.write = false;
282
- await this.parse(fullPath, valDP, options);
319
+ // FIX: options-Objekt nicht mutieren – Spread-Kopie verwenden
320
+ await this.parse(fullPath, valDP, { ...options, write: false });
283
321
  }
284
322
  continue;
285
323
  }
@@ -300,7 +338,7 @@ class Helper {
300
338
 
301
339
  if (!this.alreadyCreatedObjects[fullPath]) {
302
340
  const objectName = options.descriptions?.[key] || key;
303
- let typeDp = typeof valDP === "string" ? "mixed" : (valDP != null ? typeof valDP : "mixed");
341
+ let typeDp = this.normalizeType(valDP);
304
342
 
305
343
  if (constant.mixedType.includes(key)) {
306
344
  typeDp = "mixed";
@@ -335,10 +373,9 @@ class Helper {
335
373
  await this.changeState(fullPath, valDP, change);
336
374
 
337
375
  if (valDP !== undefined) {
338
- if (fullPath.endsWith('ready') ) {
339
- valDP = element['status'];
340
- if (utils.isNumeric(valDP) && valDP === 3) {
341
- fullPath = fullPath.replace(".status", ".ready");
376
+ if (fullPath.endsWith('ready')) {
377
+ const statusVal = element['status'];
378
+ if (utils.isNumeric(statusVal) && statusVal === 3) {
342
379
  await this.changeState(fullPath, false);
343
380
  }
344
381
  }
@@ -375,15 +412,11 @@ class Helper {
375
412
 
376
413
  for (let i = 0; i < array.length; i++) {
377
414
  const arrayElement = array[i];
378
- // const index = (i + 1).toString().padStart(2, "0");
379
415
 
380
416
  if (typeof arrayElement === "string") {
381
- if (key === undefined || key === "") {
382
- key = arrayElement;
383
- }
384
-
417
+ const segKey = (key === undefined || key === "") ? arrayElement : key;
385
418
  await this.parse(
386
- `${path}.${key}.${arrayElement}`,
419
+ `${path}.${segKey}`,
387
420
  arrayElement,
388
421
  options,
389
422
  );
@@ -443,6 +476,10 @@ class Helper {
443
476
  resolveCommandClassValue(element) {
444
477
  const type = element.type;
445
478
 
479
+ if (!type) {
480
+ return element.value ?? 0;
481
+ }
482
+
446
483
  if (type === "any" || type === "color") {
447
484
  element.type = "mixed";
448
485
  return typeof element.value === "object"
@@ -487,10 +524,10 @@ class Helper {
487
524
  }
488
525
 
489
526
  if (type === "number") {
490
- if (element?.value) {
527
+ if (element.value != null) {
491
528
  return utils.isNumeric(element.value) ? element.value : 0;
492
529
  }
493
- return element.value ?? element.min;
530
+ return element.min ?? 0;
494
531
  }
495
532
 
496
533
  return element.readable === false
@@ -545,18 +582,22 @@ class Helper {
545
582
  */
546
583
  async updateDevice(nodeId, element, nameChange = true) {
547
584
  const obj = await this.adapter.getObjectAsync(nodeId);
548
- if (obj) {
549
- if (nameChange) {
550
- const newName = element.name || element.productLabel || element.manufacturer || element.newValue;
551
-
552
- if (obj.common?.name !== newName) {
553
- obj.common = obj.common ?? {};
554
- obj.common.name = newName;
555
- } else {
556
- const newDesc = element.desc;
557
- obj.common = obj.common ?? {};
558
- obj.common.desc = newDesc;
559
- }
585
+ if (!obj) {
586
+ return;
587
+ }
588
+
589
+ obj.common = obj.common ?? {};
590
+
591
+ if (nameChange) {
592
+ const newName = element.name || element.productLabel || element.manufacturer || element.newValue;
593
+ if (newName !== undefined && obj.common.name !== newName) {
594
+ obj.common.name = newName;
595
+ await this.adapter.setObjectAsync(nodeId, obj);
596
+ }
597
+ } else {
598
+ const newDesc = element.desc;
599
+ if (newDesc !== undefined) {
600
+ obj.common.desc = newDesc;
560
601
  await this.adapter.setObjectAsync(nodeId, obj);
561
602
  }
562
603
  }
@@ -571,9 +612,9 @@ class Helper {
571
612
  */
572
613
  async changeState(path, value, change = false) {
573
614
  if (change) {
574
- this.adapter.setState(path, value, true);
615
+ await this.adapter.setStateAsync(path, value, true);
575
616
  } else {
576
- this.adapter.setStateChanged(path, value, true);
617
+ await this.adapter.setStateChangedAsync(path, value, true);
577
618
  }
578
619
  }
579
620
 
package/lib/messages.js CHANGED
@@ -11,7 +11,7 @@ async function adapterInfo(config, log) {
11
11
  log.info(`|| zwaveWS Frontend Server: ${config.webUIServer}`);
12
12
  log.info(`|| zwaveWS Frontend Port: ${config.webUIPort}`);
13
13
  log.info(`|| zwaveWS Connection Type: ${config.connectionType}`);
14
- if (config.connectionType == "ws") {
14
+ if (config.connectionType === "ws") {
15
15
  log.info(`|| zwaveWS Websocket Scheme: ${config.wsScheme}`);
16
16
  log.info(`|| zwaveWS Websocket Server: ${config.wsServerIP}`);
17
17
  log.info(`|| zwaveWS Websocket Port: ${config.wsServerPort}`);
@@ -21,11 +21,11 @@ async function adapterInfo(config, log) {
21
21
  log.info(
22
22
  `|| zwaveWS Websocket Dummy MQTT-Server: ${config.dummyMqtt ? "activated" : "deactivated"}`,
23
23
  );
24
- if (config.dummyMqtt == true) {
24
+ if (config.dummyMqtt === true) {
25
25
  log.info(`|| zwaveWS Dummy MQTT IP-Bind: ${config.mqttServerIPBind}`);
26
26
  log.info(`|| zwaveWS Dummy MQTT Port: ${config.mqttServerPort}`);
27
27
  }
28
- } else if (config.connectionType == "exmqtt") {
28
+ } else if (config.connectionType === "exmqtt") {
29
29
  log.info(
30
30
  `|| zwaveWS Externanl MQTT Server: ${config.externalMqttServerIP}`,
31
31
  );
@@ -35,7 +35,7 @@ async function adapterInfo(config, log) {
35
35
  log.info(
36
36
  `|| zwaveWS Externanl MQTT Credentials: ${config.externalMqttServerCredentials ? "use" : "unused"}`,
37
37
  );
38
- } else if (config.connectionType == "intmqtt") {
38
+ } else if (config.connectionType === "intmqtt") {
39
39
  log.info(`|| zwaveWS Internal MQTT IP-Bind: ${config.mqttServerIPBind}`);
40
40
  log.info(`|| zwaveWS Internal MQTT Port: ${config.mqttServerPort}`);
41
41
  }
@@ -33,7 +33,7 @@ class MqttServerController {
33
33
  this.adapter.config.mqttServerIPBind,
34
34
  () => {
35
35
  this.adapter.log.info(
36
- `Statring MQTT-Server on IP ${this.adapter.config.mqttServerIPBind} and Port ${this.adapter.config.mqttServerPort}`,
36
+ `Starting MQTT-Server on IP ${this.adapter.config.mqttServerIPBind} and Port ${this.adapter.config.mqttServerPort}`,
37
37
  );
38
38
  },
39
39
  );
@@ -54,7 +54,7 @@ class MqttServerController {
54
54
  this.adapter.config.mqttServerIPBind,
55
55
  () => {
56
56
  this.adapter.log.info(
57
- `Statring DummyMQTT-Server on IP ${this.adapter.config.mqttServerIPBind} and Port ${this.adapter.config.mqttServerPort}`,
57
+ `Starting DummyMQTT-Server on IP ${this.adapter.config.mqttServerIPBind} and Port ${this.adapter.config.mqttServerPort}`,
58
58
  );
59
59
  },
60
60
  );
@@ -67,7 +67,7 @@ class MqttServerController {
67
67
  *
68
68
  */
69
69
  closeServer() {
70
- if (mqttServer && !mqttServer.closed()) {
70
+ if (mqttServer && mqttServer.listening) {
71
71
  mqttServer.close();
72
72
  }
73
73
  }
@@ -45,9 +45,10 @@ class StatesController {
45
45
  async subscribeAllWritableExistsStates() {
46
46
  const writableStates = {};
47
47
 
48
+ const ns = `${this.adapter.namespace}.`;
48
49
  const res = await this.adapter.getObjectViewAsync("system", "state", {
49
- startkey: "zwaveWS.",
50
- endkey: "zwaveWS.\u9999",
50
+ startkey: ns,
51
+ endkey: `${ns}\u9999`,
51
52
  });
52
53
 
53
54
  for (const row of res.rows) {