iobroker.zwavews 0.0.18 → 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.
package/README.md CHANGED
@@ -35,6 +35,12 @@ Activate WS Server Settings in `zwave-js-ui` we use the Home Assistant Settings
35
35
 
36
36
 
37
37
  ## Changelog
38
+ ### 0.1.0 (2026-03-08)
39
+ * (arteck) BREAKING CHANGE - dp name is now with underline
40
+ * (arteck) add deviceManager
41
+ * (arteck) fix dp's with a space
42
+ * (arteck) fix dp's with special chars
43
+
38
44
  ### 0.0.18 (2026-02-28)
39
45
  * (arteck) add info.sendMessageAllowed object to allow sending the message to zwave-ui-js
40
46
  * (arteck) add new checkbox to set info.sendMessageAllowed immediately after starting the adapter
@@ -5,6 +5,31 @@
5
5
  "width": "calc(100% - 100px)"
6
6
  },
7
7
  "items": {
8
+ "_deviceManager": {
9
+ "type": "panel",
10
+ "label": "devices",
11
+ "items": {
12
+ "_devMng": {
13
+ "type": "deviceManager",
14
+ "sm": 12,
15
+ "style": {
16
+ "width": "100%",
17
+ "height": "100%",
18
+ "overflow": "hidden"
19
+ }
20
+ }
21
+ },
22
+ "style": {
23
+ "width": "100%",
24
+ "height": "100%",
25
+ "overflow": "hidden"
26
+ },
27
+ "innerStyle": {
28
+ "width": "100%",
29
+ "height": "100%",
30
+ "overflow": "hidden"
31
+ }
32
+ },
8
33
  "_tab_Start": {
9
34
  "type": "panel",
10
35
  "label": "Main Settings",
package/io-package.json CHANGED
@@ -1,8 +1,21 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "zwavews",
4
- "version": "0.0.18",
4
+ "version": "0.1.0",
5
5
  "news": {
6
+ "0.1.0": {
7
+ "en": "BREAKING CHANGE - dp name is now with underline\nadd deviceManager\nfix dp's with a space\nfix dp's with special chars",
8
+ "de": "BREAKING CHANGE - dp name ist jetzt mit unterstreichen\nadd-Gerät Manager\ndp's mit einem raum reparieren\nfix dp's with special chars",
9
+ "ru": "BREAKING CHANGE - название dp теперь с подчеркиванием\nдобавить устройство Менеджер\nустановить dp в пространстве\nобсуждение dp's with special chars",
10
+ "pt": "MUDANÇA DE INÍCIO - nome dp está agora com sublinhado\nadicionar dispositivo Gestor\ncorrigir dp's com um espaço\ncorrigir dp's com caracteres especiais",
11
+ "nl": "BREAKING VERANDERING - dp naam is nu met benadrukken\napparaat toevoegen Beheerder\nfix dp's met een spatie\nfix dp's met speciale tekens",
12
+ "fr": "CHANGEMENT DE BREAKING - DP nom est maintenant avec le soulignement\najouter un périphérique Gestionnaire\nréparer dp's avec un espace\nfixer dp's avec des caractères spéciaux",
13
+ "it": "BREAKING CHANGE - il nome dp è ora in linea\naggiungere dispositivo Manager\nfix dp's con uno spazio\nsistemare dp's con beneficenza speciali",
14
+ "es": "CAMBIO DE BREAKING - nombre dp ahora es con subrayado\nañadir dispositivo Manager\narreglar dp con un espacio\narreglar dp con chars especiales",
15
+ "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",
16
+ "uk": "BREAKING CHANGE - ім'я dp тепер з онлайн\nдодати пристрій Менеджер\nзакріпити dp's з космосом\nфіксувати dp з особливими chars",
17
+ "zh-cn": "断裂变换 - dp 名称现在是下划线\n添加设备 经理\n修补 dp 的空格\n修复 dp 与特殊字符"
18
+ },
6
19
  "0.0.18": {
7
20
  "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",
8
21
  "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",
@@ -80,22 +93,8 @@
80
93
  "pl": "dodaj typ zdarzenia \"powiadomienie o wartości\"",
81
94
  "uk": "додати тип події \"значення повідомлення\"",
82
95
  "zh-cn": "添加事件类型“ 值通知”"
83
- },
84
- "0.0.12": {
85
- "en": "typo\nfix dp channel name\nadd endpoint > 0 to value if exists",
86
- "de": "typo\ndp kanal name\nendpunkt hinzufügen > 0 auf wert, falls vorhanden",
87
- "ru": "опечатка\nустановить имя канала dp\nдобавить конечную точку 0, если существует",
88
- "pt": "erro de digitação\ncorrigir o nome do canal dp\nadicionar endpoint > 0 a valor se existir",
89
- "nl": "type\nfix dp kanaalnaam\neindpunt toevoegen > 0 naar waarde indien aanwezig",
90
- "fr": "typo\ncorriger le nom du canal dp\najouter le paramètre > 0 à valeur s'il existe",
91
- "it": "tipo\ncorretto nome del canale dp\naggiungere il punto finale 0 a valore se esiste",
92
- "es": "typo\nfijar nombre del canal dp\nañadir endpoint √ 0 a valor si existe",
93
- "pl": "typo\nfix dp nazwa kanału\ndodać punkt końcowy > 0 do wartości, jeśli istnieje",
94
- "uk": "типи\nзафіксувати ім'я каналів dp\nдодати кінцеву точку > 0 до значення, якщо існує",
95
- "zh-cn": "类型\n修复 dp 频道名称\n添加终点 > 0 到数值( 如果存在)"
96
96
  }
97
97
  },
98
- "messages": [],
99
98
  "titleLang": {
100
99
  "en": "Z-Wave WS",
101
100
  "de": "Z-Wave WS",
@@ -184,7 +183,60 @@
184
183
  "admin": ">=7.6.17"
185
184
  }
186
185
  ],
187
- "installedFrom": "arteck/ioBroker.zwavews#notrigger"
186
+ "messages": [
187
+ {
188
+ "condition": {
189
+ "operand": "and",
190
+ "rules": [
191
+ "oldVersion<0.0.18",
192
+ "newVersion>=0.1.0"
193
+ ]
194
+ },
195
+ "title": {
196
+ "en": "Important notice!",
197
+ "de": "Wichtiger Hinweis!",
198
+ "ru": "Важное замечание!",
199
+ "pt": "Notícia importante!",
200
+ "nl": "Belangrijke mededeling!",
201
+ "fr": "Avis important!",
202
+ "it": "Avviso IMPORTANTE!",
203
+ "es": "Noticia importante!",
204
+ "pl": "Ważna uwaga!",
205
+ "zh-cn": "重要通知!"
206
+ },
207
+ "text": {
208
+ "en": "\"BREAKING CHANGE. <br> Adapter version 0.1.0 use now a underline on Object. check you alias or visu and corr this mistake. example: Manufacturer Specific is now Manufacturer_Specific",
209
+ "de": "\"BREAKING CHANGE. <br> Die Adapterversion 0.1.0 verwendet jetzt eine Unterstreichung bei Objekten. Überprüfe deinen Alias oder Visu und korrigiere es. Beispiel: Manufacturer Specific lautet jetzt Manufacturer_Specific.",
210
+ "ru": "\"BREAKING CHANGE. <br> В версии адаптера 0.1.0 теперь используется подчеркивание объекта. Проверьте свой псевдоним или визуализацию и исправьте эту ошибку. Например: Manufacturer Specific теперь Manufacturer_Specific",
211
+ "pt": "\"BREAKING CHANGE. <br> A versão 0.1.0 do adaptador agora usa um sublinhado em Objetos. Verifique seu alias ou visualizador e corrija esse erro. Exemplo: Manufacturer Specific agora é Manufacturer_Specific.",
212
+ "nl": "\"BREAKING CHANGE. <br> Adapterversie 0.1.0 gebruikt nu een onderstreping bij Object. Controleer je alias of visualisatie en corrigeer deze fout. Bijvoorbeeld: Manufacturer Specific is nu Manufacturer_Specific.",
213
+ "fr": "\"BREAKING CHANGE. <br> L'adaptateur version 0.1.0 utilise désormais un trait de soulignement sur les objets. Vérifiez votre alias ou visualisez l'interface et corrigez cette erreur. Exemple : Manufacturer Specific devient Manufacturer_Specific.",
214
+ "it": "\"BREAKING CHANGE. <br> La versione 0.1.0 dell'adattatore ora utilizza una sottolineatura sull'oggetto. Controlla il tuo alias o visu e correggi questo errore. Esempio: Manufacturer Specific ora è Manufacturer_Specific",
215
+ "es": "\"BREAKING CHANGE. <br> La versión 0.1.0 del adaptador ahora usa un subrayado en el objeto. Verifique su alias o visu y corrija este error. Ejemplo: Manufacturer Specific ahora es Manufacturer_Specific",
216
+ "pl": "\"BREAKING CHANGE. <br> Wersja adaptera 0.1.0 używa teraz podkreślenia na obiekcie. Sprawdź alias lub wizualizację i popraw ten błąd. Przykład: Manufacturer Specific to teraz Manufacturer_Specific",
217
+ "uk": "\"BREAKING CHANGE. <br> Версія адаптера 0.1.0 тепер використовує підкреслення на об'єкті. Перевірте свій псевдонім або візуалізацію та виправте цю помилку. Приклад: Manufacturer Specific тепер Manufacturer_Specific.",
218
+ "zh-cn": "\"BREAKING CHANGE. <br> 适配器版本 0.1.0 现在在对象名称前使用下划线。请检查您的别名或视觉设置,并更正此错误。例如:Manufacturer Specific 现在是 Manufacturer_Specific。"
219
+ },
220
+ "link": "https://github.com/arteck/ioBroker.zwavews/wiki/DP's-with-space-blank-in-Name",
221
+ "level": "warn",
222
+ "linkText": {
223
+ "en": "Readme",
224
+ "de": "Liesmich",
225
+ "ru": "Прочти меня",
226
+ "pt": "Leia-me",
227
+ "nl": "Leesmij",
228
+ "fr": "Lisez-moi",
229
+ "it": "Leggimi",
230
+ "es": "Léame",
231
+ "pl": "Readme",
232
+ "zh-cn": "自述文件"
233
+ },
234
+ "buttons": [
235
+ "agree",
236
+ "cancel"
237
+ ]
238
+ }
239
+ ]
188
240
  },
189
241
  "native": {
190
242
  "connectionType": "ws",
@@ -0,0 +1,404 @@
1
+ 'use strict';
2
+ const dmUtils = require('@iobroker/dm-utils');
3
+ const humanizeDuration = require('humanize-duration');
4
+
5
+ /**
6
+ *
7
+ */
8
+ class dmZwave extends dmUtils.DeviceManagement {
9
+ /**
10
+ *
11
+ * @param adapter
12
+ */
13
+ constructor(adapter) {
14
+ super(adapter);
15
+ this.adapter = adapter;
16
+ }
17
+
18
+ /**
19
+ *
20
+ */
21
+ async listDevices() {
22
+ const devices = await this.adapter.getDevicesAsync();
23
+ const arrDevices = [];
24
+ for (const i in devices) {
25
+ const status = {};
26
+
27
+ const nodeId = this.stripIobPrefix(devices[i]._id);
28
+
29
+ const device = this.adapter.nodeCache[nodeId].nodeData;
30
+
31
+ if (device.ready) {
32
+ status.connection = device.ready ? 'connected' : 'disconnected';
33
+ }
34
+
35
+ //const link_quality = await this.adapter.getStateAsync(`${theDevice._id}.status`);
36
+ //status.rssi = link_quality.val == 'alive' ? '100' : '0';
37
+
38
+ const battery = await this.adapter.getStateAsync(`${devices[i]._id}.Battery.level`);
39
+ if (battery) {
40
+ status.battery = battery.val;
41
+ }
42
+
43
+ let devStatus;
44
+
45
+ switch (device.status) {
46
+ case 1:
47
+ devStatus = 'data:image/png;base64,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';
48
+ break;
49
+ case 2:
50
+ devStatus = 'data:image/png;base64,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';
51
+ break;
52
+ case 3:
53
+ devStatus = 'data:image/png;base64,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';
54
+ break;
55
+ case 4:
56
+ devStatus = 'data:image/png;base64,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';
57
+ break;
58
+ default:
59
+ devStatus = 'unknown';
60
+ }
61
+
62
+ const res = {
63
+ id: nodeId,
64
+ name: device.name || device.label,
65
+ icon: devStatus,
66
+ manufacturer: device.deviceConfig.manufacturer,
67
+ model: `${device.deviceConfig.label } ${ device.deviceConfig.description}`,
68
+ status: status,
69
+ hasDetails: true,
70
+ actions: [
71
+ {
72
+ id: 'doc',
73
+ icon: 'lines',
74
+ description: 'Documentation',
75
+ handler: async (_id, context) => this.openPDF(context, device),
76
+ },
77
+ ],
78
+ };
79
+
80
+
81
+ arrDevices.push(res);
82
+ }
83
+
84
+ // nach id sortieren (z.B. nodeID_2 vor nodeID_10)
85
+ arrDevices.sort((a, b) => String(a?.id ?? '').localeCompare(String(b?.id ?? ''), undefined, {
86
+ numeric: true,
87
+ sensitivity: 'base',
88
+ }));
89
+
90
+ return arrDevices;
91
+ }
92
+
93
+ /**
94
+ *
95
+ * @param context
96
+ * @param device
97
+ */
98
+ async openPDF(context, device) {
99
+ const manual = device?.deviceConfig?.metadata?.manual;
100
+ const urls = Array.isArray(manual)
101
+ ? manual
102
+ : (typeof manual === 'string' && manual.trim())
103
+ ? [manual]
104
+ : [];
105
+
106
+ const items = {};
107
+
108
+ if (!urls.length) {
109
+ items._no_manual = {
110
+ type: 'staticText',
111
+ text: this.adapter.i18nTranslation?.['No documentation link found'] || 'No documentation link found',
112
+ newLine: true,
113
+ };
114
+ } else {
115
+ urls
116
+ .filter(u => typeof u === 'string' && u.trim())
117
+ .forEach((u, idx) => {
118
+ const href = /^https?:\/\//i.test(u) ? u : `https://${u}`;
119
+ items[`_manual_${idx}`] = {
120
+ type: 'staticLink',
121
+ label: urls.length === 1 ? 'Dokumentation' : `Dokumentation ${idx + 1}`,
122
+ href,
123
+ button: true,
124
+ newLine: true,
125
+ };
126
+ });
127
+ }
128
+
129
+ await context.showForm(
130
+ {
131
+ type: 'panel',
132
+ items,
133
+ },
134
+ {
135
+ title: this.adapter.i18nTranslation?.['DeviceDocumentation'] || 'Device documentation',
136
+ },
137
+ );
138
+
139
+ return { refresh: true };
140
+ }
141
+
142
+ /**
143
+ *
144
+ * @param id
145
+ * @param action
146
+ * @param context
147
+ */
148
+ async getDeviceDetails(id, action, context) {
149
+ this.adapter.log.debug('getDeviceDetails');
150
+
151
+ const device = this.adapter.nodeCache[id]?.nodeData;
152
+
153
+ if (!device) {
154
+ return null;
155
+ }
156
+
157
+ const items = {
158
+ nodeId: {
159
+ type: 'staticText',
160
+ text: `Node ID: ${device.nodeId ?? '—'}`,
161
+ newLine: true,
162
+ },
163
+ manufacturerId: {
164
+ type: 'staticText',
165
+ text: `Manufacturer ID: ${device.manufacturerId ?? device.deviceConfig?.manufacturerId ?? '—'}`,
166
+ newLine: true,
167
+ },
168
+ productId: {
169
+ type: 'staticText',
170
+ text: `Product ID: ${device.productId ?? '—'}`,
171
+ newLine: true,
172
+ },
173
+ productType: {
174
+ type: 'staticText',
175
+ text: `Product Type: ${device.productType ?? '—'}`,
176
+ newLine: true,
177
+ },
178
+ protocolVersion: {
179
+ type: 'staticText',
180
+ text: `Protocol Version: ${device.protocolVersion ?? '—'}`,
181
+ newLine: true,
182
+ },
183
+ sdkVersion: {
184
+ type: 'staticText',
185
+ text: `SDK Version: ${device.sdkVersion ?? '—'}`,
186
+ newLine: true,
187
+ },
188
+ interviewStage: {
189
+ type: 'staticText',
190
+ text: `Interview Stage: ${device.interviewStage ?? '—'}`,
191
+ newLine: true,
192
+ },
193
+ lastActive: {
194
+ type: 'staticText',
195
+ text: `Last Active: ${device.lastActive ?? '—'}`,
196
+ newLine: true,
197
+ },
198
+ endpointsCount: {
199
+ type: 'staticText',
200
+ text: `Endpoints Count: ${device.endpointsCount ?? '—'}`,
201
+ newLine: true,
202
+ },
203
+ deviceClassBasic: {
204
+ type: 'staticText',
205
+ text: `Device Class Basic: ${device.deviceClass?.basic ?? '—'}`,
206
+ newLine: true,
207
+ },
208
+ deviceClassGeneric: {
209
+ type: 'staticText',
210
+ text: `Device Class Generic: ${device.deviceClass?.generic ?? '—'}`,
211
+ newLine: true,
212
+ },
213
+ deviceClassSpecific: {
214
+ type: 'staticText',
215
+ text: `Device Class Specific: ${device.deviceClass?.specific ?? '—'}`,
216
+ newLine: true,
217
+ },
218
+ supportsSecurity: {
219
+ type: 'checkbox',
220
+ label: 'Supports Security',
221
+ readOnly: true,
222
+ checked: !!device.supportsSecurity,
223
+ newLine: true,
224
+ },
225
+ supportsBeaming: {
226
+ type: 'checkbox',
227
+ label: 'Supports Beaming',
228
+ readOnly: true,
229
+ checked: !!device.supportsBeaming,
230
+ },
231
+ isFrequentListening: {
232
+ type: 'checkbox',
233
+ label: 'Frequent Listening',
234
+ readOnly: true,
235
+ checked: !!device.isFrequentListening,
236
+ },
237
+ isControllerNode: {
238
+ type: 'checkbox',
239
+ label: 'Controller Node',
240
+ readOnly: true,
241
+ checked: !!device.isControllerNode,
242
+ },
243
+ keepAwake: {
244
+ type: 'checkbox',
245
+ label: 'Keep Awake',
246
+ readOnly: true,
247
+ checked: !!device.keepAwake,
248
+ },
249
+ };
250
+
251
+ let devStatus;
252
+ switch (device.status) {
253
+ case 1:
254
+ devStatus = 'asleep';
255
+ break;
256
+ case 2:
257
+ devStatus = 'awake';
258
+ break;
259
+ case 3:
260
+ devStatus = 'dead';
261
+ break;
262
+ case 4:
263
+ devStatus = 'alive';
264
+ break;
265
+ default:
266
+ devStatus = 'unknown';
267
+ }
268
+
269
+ return {
270
+ id: String(device.nodeId),
271
+ schema: {
272
+ type: 'tabs',
273
+ items: {
274
+ _tab_Start: {
275
+ type: 'panel',
276
+ label: 'Main',
277
+ items: {
278
+ header_Start: {
279
+ type: 'header',
280
+ text: `${id} - ${device.label} ${device?.deviceClass?.basic || ''}`.trim(),
281
+ size: 3,
282
+ },
283
+ nameDevice: {
284
+ type: 'text',
285
+ label: 'Device Name',
286
+ readOnly: true,
287
+ },
288
+ manufacturer: {
289
+ type: 'text',
290
+ label: 'Manufacturer',
291
+ readOnly: true,
292
+ },
293
+ firmwareVersion: {
294
+ type: 'text',
295
+ label: 'Firmware Version',
296
+ readOnly: true,
297
+ },
298
+ statusText: {
299
+ type: 'text',
300
+ label: 'Status',
301
+ readOnly: true,
302
+ },
303
+ zwavePlusVersion: {
304
+ type: 'text',
305
+ label: 'Zwave Plus Version',
306
+ readOnly: true,
307
+ },
308
+ _divider2: {
309
+ type: 'divider',
310
+ color: 'primary',
311
+ },
312
+ ready: {
313
+ type: 'checkbox',
314
+ label: 'is Ready',
315
+ readOnly: true,
316
+ },
317
+ isListening: {
318
+ type: 'checkbox',
319
+ label: 'is Listening',
320
+ readOnly: true,
321
+ },
322
+ isRouting: {
323
+ type: 'checkbox',
324
+ label: 'is Routing',
325
+ readOnly: true,
326
+ },
327
+ isSecure: {
328
+ type: 'checkbox',
329
+ label: 'is Secure',
330
+ readOnly: true,
331
+ newLine: true,
332
+ },
333
+ maxBaudRate: {
334
+ type: 'text',
335
+ label: 'Max Baud Rate',
336
+ readOnly: true,
337
+ },
338
+ },
339
+ },
340
+ _tab_Details: {
341
+ type: 'panel',
342
+ label: 'Details',
343
+ items,
344
+ },
345
+ },
346
+ },
347
+ data: {
348
+ nameDevice: device.name || '',
349
+ manufacturer: device.deviceConfig?.manufacturer || '',
350
+ firmwareVersion: device.firmwareVersion || '',
351
+ statusText: devStatus,
352
+ zwavePlusVersion: device.zwavePlusVersion || '',
353
+ ready: !!device.ready,
354
+ isListening: !!device.isListening,
355
+ isRouting: !!device.isRouting,
356
+ isSecure: !!device.isSecure,
357
+ maxBaudRate: device.maxBaudRate ? `${device.maxBaudRate} kBaud/s` : '',
358
+ },
359
+ };
360
+ }
361
+
362
+
363
+
364
+ /**
365
+ *
366
+ * @param time
367
+ * @param type
368
+ */
369
+ async formatDate(time, type) { //'ISO_8601' | 'ISO_8601_local' | 'epoch' | 'relative'
370
+ if (type === 'ISO_8601') {
371
+ return new Date(time).toISOString();
372
+ } else if (type === 'ISO_8601_local') {
373
+ return this.toLocalISOString(new Date(time));
374
+ } else if (type === 'epoch') {
375
+ return time;
376
+ }
377
+ // relative
378
+ const ago = `${humanizeDuration(Date.now() - time, {language: 'en', largest: 2, round: true}) } ago`;
379
+ return ago;
380
+
381
+ }
382
+
383
+ /**
384
+ *
385
+ * @param d
386
+ */
387
+ toLocalISOString(d) {
388
+ const off = d.getTimezoneOffset();
389
+ return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes() - off, d.getSeconds(), d.getMilliseconds()).toISOString();
390
+ }
391
+ // Entfernt den ioBroker-Prefix am Anfang, z.B.
392
+ // "zwavews.0.nodeID_1.info.name" -> "nodeID_1.info.name"
393
+ /**
394
+ *
395
+ * @param id
396
+ */
397
+ stripIobPrefix(id) {
398
+ const s = String(id ?? '');
399
+ return s.replace(/^[^.]+\.[^.]+\./, '');
400
+ }
401
+
402
+ }
403
+
404
+ module.exports = dmZwave;
package/lib/helper.js CHANGED
@@ -68,7 +68,7 @@ class Helper {
68
68
 
69
69
  if (valuesOnly != null && typeof valuesOnly === "object" && valuesOnly.length > 0) {
70
70
  for (const v of valuesOnly) {
71
- let parsePath = `${nodeId}.${v.commandClassName}`;
71
+ let parsePath = utils.formatObject(`${nodeId}.${v.commandClassName}`);
72
72
  let metadata = v.metadata || {};
73
73
 
74
74
  if (constant.noInfoDP.includes(v.commandClassName)) {
@@ -115,6 +115,8 @@ class Helper {
115
115
  parsePath = `${parsePath}_${v.endpoint}`;
116
116
  }
117
117
 
118
+ parsePath = utils.formatObject(parsePath); // entferne sonderzeichen und blanke aus dem namen
119
+
118
120
  const nam_id = v.label ?? v.propertyName;
119
121
 
120
122
  metadata.value = v.value; // add value for resolution
@@ -181,7 +183,7 @@ class Helper {
181
183
  * @param options
182
184
  */
183
185
  async parse(path, element, options = { write: false }) {
184
- let parsePath = path;
186
+ let parsePath = utils.formatObject(path);
185
187
 
186
188
  if (element == null) {
187
189
  this.adapter.log.debug(`Cannot extract empty: ${parsePath}`);
@@ -257,7 +259,7 @@ class Helper {
257
259
  }
258
260
 
259
261
  for (const key of Object.keys(element)) {
260
- let fullPath = `${parsePath}.${key}`;
262
+ let fullPath = utils.formatObject(`${parsePath}.${key}`);
261
263
  let valDP = element[key];
262
264
 
263
265
  if (Array.isArray(valDP)) {
package/lib/utils.js CHANGED
@@ -137,6 +137,18 @@ function replaceLastDot(str) {
137
137
  const idx = str.lastIndexOf(".");
138
138
  return idx >= 0 ? `${str.slice(0, idx)}_${str.slice(idx + 1)}` : str;
139
139
  }
140
+
141
+ /**
142
+ *
143
+ * @param str
144
+ */
145
+ function formatObject(str) {
146
+ if (typeof str !== "string") {
147
+ return "";
148
+ }
149
+ return str.trim().replace(/₂/g, "2").replace(/\s+/g, "_");
150
+ }
151
+
140
152
  /**
141
153
  *
142
154
  * @param input
@@ -202,4 +214,5 @@ module.exports = {
202
214
  formatMQTT,
203
215
  padNodeId,
204
216
  getStatusText,
217
+ formatObject,
205
218
  };
@@ -69,7 +69,7 @@ class WebsocketController {
69
69
  */
70
70
  send(message) {
71
71
  if (wsClient.readyState !== WebSocket.OPEN) {
72
- this.adapter.log.warn('Cannot set State, no websocket connection to Zigbee2MQTT!');
72
+ this.adapter.log.warn('Cannot set State, no websocket connection to zwave-js-ui');
73
73
  return;
74
74
  }
75
75
  wsClient.send(message);
package/main.js CHANGED
@@ -4,6 +4,7 @@ const core = require("@iobroker/adapter-core");
4
4
  const mqtt = require("mqtt");
5
5
  const utils = require("./lib/utils");
6
6
  const constant = require("./lib/constants");
7
+ const dmZwave = require('./lib/devicemgmt.js');
7
8
 
8
9
  const adapterInfo = require("./lib/messages").adapterInfo;
9
10
  const StatesController = require("./lib/statesController").StatesController;
@@ -60,6 +61,8 @@ class zwavews extends core.Adapter {
60
61
  );
61
62
  }
62
63
 
64
+ this.deviceManagement = new dmZwave(this);
65
+
63
66
  if (this.config.wsOnStart) {
64
67
  this.setStateChanged("info.sendMessageAllowed", true, true);
65
68
  }
@@ -67,6 +70,7 @@ class zwavews extends core.Adapter {
67
70
  this.nodeCache = {};
68
71
  this.setStateChanged("info.debugmessages", "", true);
69
72
 
73
+
70
74
  // MQTT
71
75
  if (["exmqtt", "intmqtt"].includes(this.config.connectionType)) {
72
76
  // External MQTT-Server
@@ -264,6 +268,8 @@ class zwavews extends core.Adapter {
264
268
  }
265
269
  }
266
270
 
271
+ parsePath = utils.formatObject(parsePath);
272
+
267
273
  if (nodeArg.commandClass === 119) { // sonderlocke für node naming
268
274
  switch (nodeArg.property) {
269
275
  case 'name':
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.zwavews",
3
- "version": "0.0.18",
3
+ "version": "0.1.0",
4
4
  "description": "zwavews adapter for ioBroker",
5
5
  "author": {
6
6
  "name": "Dennis Rathjen and Arthur Rupp",
@@ -27,6 +27,7 @@
27
27
  "dependencies": {
28
28
  "@iobroker/adapter-core": "^3.3.2",
29
29
  "@iobroker/dm-utils": "^2.0.1",
30
+ "humanize-duration": "^3.33.2",
30
31
  "aedes": "^0.51.3",
31
32
  "aedes-persistence-nedb": "^2.0.3",
32
33
  "mqtt": "^5.15.0",