iobroker.zwavews 0.0.17 → 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 +10 -0
- package/admin/i18n/de/translations.json +4 -1
- package/admin/i18n/en/translations.json +3 -1
- package/admin/i18n/es/translations.json +3 -1
- package/admin/i18n/fr/translations.json +3 -1
- package/admin/i18n/it/translations.json +3 -1
- package/admin/i18n/nl/translations.json +3 -1
- package/admin/i18n/pl/translations.json +3 -1
- package/admin/i18n/pt/translations.json +3 -1
- package/admin/i18n/ru/translations.json +3 -1
- package/admin/i18n/uk/translations.json +3 -1
- package/admin/i18n/zh-cn/translations.json +3 -1
- package/admin/jsonConfig.json +37 -0
- package/io-package.json +96 -29
- package/lib/constants.js +1 -0
- package/lib/devicemgmt.js +404 -0
- package/lib/helper.js +17 -10
- package/lib/utils.js +13 -0
- package/lib/websocketController.js +1 -1
- package/main.js +37 -18
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -35,6 +35,16 @@ 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
|
+
|
|
44
|
+
### 0.0.18 (2026-02-28)
|
|
45
|
+
* (arteck) add info.sendMessageAllowed object to allow sending the message to zwave-ui-js
|
|
46
|
+
* (arteck) add new checkbox to set info.sendMessageAllowed immediately after starting the adapter
|
|
47
|
+
|
|
38
48
|
### 0.0.17 (2026-02-20)
|
|
39
49
|
* (arteck) fix adapter start
|
|
40
50
|
* (arteck) Dependencies have been updated
|
|
@@ -31,5 +31,8 @@
|
|
|
31
31
|
"Always refresh node infos": "Node-Informationen immer aktualisieren",
|
|
32
32
|
"The events such as 'Device removed' or 'Disabled' are displayed in the description instead of in the name": "Die Ereignisse wie 'Gerät entfernt' oder 'Deaktiviert' werden in der Beschreibung anstelle des Namens angezeigt",
|
|
33
33
|
"Inform about wake up and sleep of battery devices in the log": "Über das Aufwachen und Schlafen von batteriebetriebenen Geräten im Protokoll informieren",
|
|
34
|
-
"new Type event Warning in log": "neue Typ-Ereigniswarnung im Protokoll"
|
|
34
|
+
"new Type event Warning in log": "neue Typ-Ereigniswarnung im Protokoll",
|
|
35
|
+
"allow start send WS message directly after adapter start": "Erlaube das Senden von WS-Nachrichten direkt nach dem Adapterstart",
|
|
36
|
+
"This allows you to decide whether messages are sent immediately after the adapter starts. If the checkbox is false, the last status is taken from the info.sendMessageAllowed DP.": "damit kann man entscheiden ob die Nachrichten direkt nach adapter Start gesendet werden. Ist die checkbox false wird der letzte Status aus dem info.sendMessageAllowed DP genommen."
|
|
37
|
+
|
|
35
38
|
}
|
|
@@ -31,6 +31,8 @@
|
|
|
31
31
|
"Always refresh node infos": "Always refresh node infos",
|
|
32
32
|
"The events such as 'Device removed' or 'Disabled' are displayed in the description instead of in the name": "The events such as 'Device removed' or 'Disabled' are displayed in the description instead of in the name",
|
|
33
33
|
"Inform about wake up and sleep of battery devices in the log": "Inform about wake up and sleep of battery devices in the log",
|
|
34
|
-
"new Type event Warning in log": "new Type event Warning in log"
|
|
34
|
+
"new Type event Warning in log": "new Type event Warning in log",
|
|
35
|
+
"allow start send WS message directly after adapter start": "allow start send WS message directly after adapter start",
|
|
36
|
+
"This allows you to decide whether messages are sent immediately after the adapter starts. If the checkbox is false, the last status is taken from the info.sendMessageAllowed DP.": "This allows you to decide whether messages are sent immediately after the adapter starts. If the checkbox is false, the last status is taken from the info.sendMessageAllowed DP."
|
|
35
37
|
|
|
36
38
|
}
|
|
@@ -31,5 +31,7 @@
|
|
|
31
31
|
"Always refresh node infos": "Actualizar siempre la información del nodo",
|
|
32
32
|
"The events such as 'Device removed' or 'Disabled' are displayed in the description instead of in the name": "Los eventos como 'Dispositivo eliminado' o 'Deshabilitado' se muestran en la descripción en lugar de en el nombre",
|
|
33
33
|
"Inform about wake up and sleep of battery devices in the log": "Informar sobre el despertar y el sueño de los dispositivos de batería en el registro",
|
|
34
|
-
"new Type event Warning in log": "nuevo evento de tipo Advertencia en el registro"
|
|
34
|
+
"new Type event Warning in log": "nuevo evento de tipo Advertencia en el registro",
|
|
35
|
+
"allow start send WS message directly after adapter start": "permitir el envío de mensajes WS directamente después del inicio del adaptador",
|
|
36
|
+
"This allows you to decide whether messages are sent immediately after the adapter starts. If the checkbox is false, the last status is taken from the info.sendMessageAllowed DP.": "Esto te permite decidir si los mensajes se envían inmediatamente después de que el adaptador se inicie. Si la casilla de verificación es falsa, el último estado se toma del DP info.sendMessageAllowed."
|
|
35
37
|
}
|
|
@@ -31,5 +31,7 @@
|
|
|
31
31
|
"Always refresh node infos": "Toujours actualiser les informations sur le nœud",
|
|
32
32
|
"The events such as 'Device removed' or 'Disabled' are displayed in the description instead of in the name": "Les événements tels que 'Appareil supprimé' ou 'Désactivé' sont affichés dans la description au lieu du nom",
|
|
33
33
|
"Inform about wake up and sleep of battery devices in the log": "Informer sur le réveil et le sommeil des appareils alimentés par batterie dans le journal",
|
|
34
|
-
"new Type event Warning in log": "nouvel avertissement d'événement de type dans le journal"
|
|
34
|
+
"new Type event Warning in log": "nouvel avertissement d'événement de type dans le journal",
|
|
35
|
+
"allow start send WS message directly after adapter start": "permettre l'envoi de messages WS directement après le démarrage de l'adaptateur",
|
|
36
|
+
"This allows you to decide whether messages are sent immediately after the adapter starts. If the checkbox is false, the last status is taken from the info.sendMessageAllowed DP.": "Cela vous permet de décider si les messages sont envoyés immédiatement après le démarrage de l'adaptateur. Si la case à cocher est fausse, le dernier statut est pris du DP info.sendMessageAllowed."
|
|
35
37
|
}
|
|
@@ -31,5 +31,7 @@
|
|
|
31
31
|
"Always refresh node infos": "Aggiorna sempre le informazioni sui nodi",
|
|
32
32
|
"The events such as 'Device removed' or 'Disabled' are displayed in the description instead of in the name": "Gli eventi come 'Dispositivo rimosso' o 'Disabilitato' vengono visualizzati nella descrizione anziché nel nome",
|
|
33
33
|
"Inform about wake up and sleep of battery devices in the log": "Informazioni sul risveglio e sul sonno dei dispositivi a batteria nel registro",
|
|
34
|
-
"new Type event Warning in log": "nuovo avviso di evento di tipo nel registro"
|
|
34
|
+
"new Type event Warning in log": "nuovo avviso di evento di tipo nel registro",
|
|
35
|
+
"allow start send WS message directly after adapter start": "consentire l'invio di messaggi WS direttamente dopo l'avvio dell'adattatore",
|
|
36
|
+
"This allows you to decide whether messages are sent immediately after the adapter starts. If the checkbox is false, the last status is taken from the info.sendMessageAllowed DP.": "Questo ti permette di decidere se i messaggi vengono inviati immediatamente dopo l'avvio dell'adattatore. Se la casella di controllo è falsa, l'ultimo stato viene preso dal DP info.sendMessageAllowed."
|
|
35
37
|
}
|
|
@@ -31,5 +31,7 @@
|
|
|
31
31
|
"Always refresh node infos": "Ververs node-informatie altijd",
|
|
32
32
|
"The events such as 'Device removed' or 'Disabled' are displayed in the description instead of in the name": "Evenementen zoals 'Apparaat verwijderd' of 'Uitgeschakeld' worden weergegeven in de beschrijving in plaats van in de naam",
|
|
33
33
|
"Inform about wake up and sleep of battery devices in the log": "Informeer over het wakker worden en slapen van batterijapparaten in het logboek",
|
|
34
|
-
"new Type event Warning in log": "nieuw Type gebeurtenis Waarschuwing in log"
|
|
34
|
+
"new Type event Warning in log": "nieuw Type gebeurtenis Waarschuwing in log",
|
|
35
|
+
"allow start send WS message directly after adapter start": "toestaan dat WS-berichten direct na het starten van de adapter worden verzonden",
|
|
36
|
+
"This allows you to decide whether messages are sent immediately after the adapter starts. If the checkbox is false, the last status is taken from the info.sendMessageAllowed DP.": "Hiermee kunt u beslissen of berichten onmiddellijk na het starten van de adapter worden verzonden. Als het selectievakje niet is geselecteerd, wordt de laatste status genomen van de info.sendMessageAllowed DP."
|
|
35
37
|
}
|
|
@@ -31,6 +31,8 @@
|
|
|
31
31
|
"Always refresh node infos": "Zawsze odświeżaj informacje o Node",
|
|
32
32
|
"The events such as 'Device removed' or 'Disabled' are displayed in the description instead of in the name": "Zdarzenia takie jak 'Urządzenie usunięte' lub 'Wyłączone' są wyświetlane w opisie zamiast w nazwie",
|
|
33
33
|
"Inform about wake up and sleep of battery devices in the log": "Informuj o wybudzaniu i usypianiu urządzeń bateryjnych w Logu",
|
|
34
|
-
"new Type event Warning in log": "nowe ostrzeżenie zdarzenia typu w Logu"
|
|
34
|
+
"new Type event Warning in log": "nowe ostrzeżenie zdarzenia typu w Logu",
|
|
35
|
+
"allow start send WS message directly after adapter start": "zezwól na wysyłanie wiadomości WS bezpośrednio po uruchomieniu adaptera",
|
|
36
|
+
"This allows you to decide whether messages are sent immediately after the adapter starts. If the checkbox is false, the last status is taken from the info.sendMessageAllowed DP.": "Dzięki temu możesz zdecydować, czy wiadomości są wysyłane bezpośrednio po uruchomieniu adaptera. Jeśli pole wyboru jest fałszywe, ostatni status jest pobierany z info.sendMessageAllowed DP."
|
|
35
37
|
|
|
36
38
|
}
|
|
@@ -31,5 +31,7 @@
|
|
|
31
31
|
"Always refresh node infos": "Sempre atualizar informações do nó",
|
|
32
32
|
"The events such as 'Device removed' or 'Disabled' are displayed in the description instead of in the name": "Os eventos como 'Dispositivo removido' ou 'Desativado' são exibidos na descrição em vez do nome",
|
|
33
33
|
"Inform about wake up and sleep of battery devices in the log": "Informar sobre o despertar e o sono dos dispositivos de bateria no log",
|
|
34
|
-
"new Type event Warning in log": "novo aviso de evento de tipo no log"
|
|
34
|
+
"new Type event Warning in log": "novo aviso de evento de tipo no log",
|
|
35
|
+
"allow start send WS message directly after adapter start": "permitir o envio de mensagens WS diretamente após o início do adaptador",
|
|
36
|
+
"This allows you to decide whether messages are sent immediately after the adapter starts. If the checkbox is false, the last status is taken from the info.sendMessageAllowed DP.": "Isso permite que você decida se as mensagens são enviadas imediatamente após o início do adaptador. Se a caixa de seleção for falsa, o último status é retirado do DP info.sendMessageAllowed."
|
|
35
37
|
}
|
|
@@ -31,5 +31,7 @@
|
|
|
31
31
|
"Always refresh node infos": "Всегда обновлять информацию о узлах",
|
|
32
32
|
"The events such as 'Device removed' or 'Disabled' are displayed in the description instead of in the name": "События, такие как 'Устройство удалено' или 'Отключено', отображаются в описании, а не в имени",
|
|
33
33
|
"Inform about wake up and sleep of battery devices in the log": "Информация о пробуждении и сне устройств на батарейках в журнале",
|
|
34
|
-
"new Type event Warning in log": "новое предупреждение о событии типа в журнале"
|
|
34
|
+
"new Type event Warning in log": "новое предупреждение о событии типа в журнале",
|
|
35
|
+
"allow start send WS message directly after adapter start": "разрешить отправку WS-сообщения непосредственно после запуска адаптера",
|
|
36
|
+
"This allows you to decide whether messages are sent immediately after the adapter starts. If the checkbox is false, the last status is taken from the info.sendMessageAllowed DP.": "Это позволяет вам решить, отправляются ли сообщения сразу после запуска адаптера. Если флажок не установлен, последний статус берется из info.sendMessageAllowed DP."
|
|
35
37
|
}
|
|
@@ -31,5 +31,7 @@
|
|
|
31
31
|
"Always refresh node infos": "Завжди оновлювати інформацію про вузли",
|
|
32
32
|
"The events such as 'Device removed' or 'Disabled' are displayed in the description instead of in the name": "Події, такі як 'Пристрій видалено' або 'Вимкнено', відображаються в описі, а не в імені",
|
|
33
33
|
"Inform about wake up and sleep of battery devices in the log": "Інформація про пробудження та сон пристроїв на батарейках у журналі",
|
|
34
|
-
"new Type event Warning in log": "нове попередження про подію типу в журналі"
|
|
34
|
+
"new Type event Warning in log": "нове попередження про подію типу в журналі",
|
|
35
|
+
"allow start send WS message directly after adapter start": "дозволить отправлять WS-сообщение непосредственно после запуска адаптера",
|
|
36
|
+
"This allows you to decide whether messages are sent immediately after the adapter starts. If the checkbox is false, the last status is taken from the info.sendMessageAllowed DP.": "Это позволяет вам решить, отправляются ли сообщения сразу после запуска адаптера. Если флажок не установлен, последний статус берется из info.sendMessageAllowed DP."
|
|
35
37
|
}
|
|
@@ -31,5 +31,7 @@
|
|
|
31
31
|
"Always refresh node infos": "始终刷新节点信息",
|
|
32
32
|
"The events such as 'Device removed' or 'Disabled' are displayed in the description instead of in the name": "诸如“设备已移除”或“已禁用”等事件显示在描述中,而不是名称中",
|
|
33
33
|
"Inform about wake up and sleep of battery devices in the log": "在日志中通知电池设备的唤醒和休眠情况",
|
|
34
|
-
"new Type event Warning in log": "日志中新类型事件警告"
|
|
34
|
+
"new Type event Warning in log": "日志中新类型事件警告",
|
|
35
|
+
"allow start send WS message directly after adapter start": "允许在适配器启动后直接发送 WS 消息",
|
|
36
|
+
"This allows you to decide whether messages are sent immediately after the adapter starts. If the checkbox is false, the last status is taken from the info.sendMessageAllowed DP.": "这允许您决定是否在适配器启动后立即发送消息。如果复选框为 false,则最后的状态将从 info.sendMessageAllowed DP 中获取。"
|
|
35
37
|
}
|
package/admin/jsonConfig.json
CHANGED
|
@@ -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",
|
|
@@ -305,6 +330,18 @@
|
|
|
305
330
|
"type": "panel",
|
|
306
331
|
"label": "Other configurations",
|
|
307
332
|
"items": {
|
|
333
|
+
"wsOnStart": {
|
|
334
|
+
"type": "checkbox",
|
|
335
|
+
"label": "allow start send WS message directly after adapter start",
|
|
336
|
+
"default": true,
|
|
337
|
+
"help": "This allows you to decide whether messages are sent immediately after the adapter starts. If the checkbox is false, the last status is taken from the info.sendMessageAllowed DP.",
|
|
338
|
+
"xs": 12,
|
|
339
|
+
"sm": 12,
|
|
340
|
+
"md": 12,
|
|
341
|
+
"lg": 12,
|
|
342
|
+
"xl": 12,
|
|
343
|
+
"newLine": true
|
|
344
|
+
},
|
|
308
345
|
"showNodeInfoMessage": {
|
|
309
346
|
"type": "checkbox",
|
|
310
347
|
"label": "Show Node Info messages to ioBroker log",
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "zwavews",
|
|
4
|
-
"version": "0.0
|
|
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
|
+
},
|
|
19
|
+
"0.0.18": {
|
|
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",
|
|
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",
|
|
22
|
+
"ru": "добавить info.sendMessageРазрешенный объект для отправки сообщения на zwave-ui-js\nдобавить новый флажок для установки info.sendMessage Допускается сразу после запуска адаптера",
|
|
23
|
+
"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",
|
|
24
|
+
"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",
|
|
25
|
+
"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",
|
|
26
|
+
"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",
|
|
27
|
+
"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",
|
|
28
|
+
"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",
|
|
29
|
+
"uk": "додайте інформацію.sendMessageВсього об'єкту, щоб дозволити надсилати повідомлення на zwave-ui-js\nдодати нову прапорець, щоб встановити інформацію.sendMessage Допускається відразу після запуску адаптера",
|
|
30
|
+
"zh-cn": "添加信息. sendMessage Allowed 对象允许将消息发送到 zwave- ui- js\n添加新复选框以设置信息. sendMessage 启动适配器后立即允许"
|
|
31
|
+
},
|
|
6
32
|
"0.0.17": {
|
|
7
33
|
"en": "fix adapter start\nDependencies have been updated",
|
|
8
34
|
"de": "befestigungsadapter start\nAbhängigkeiten wurden aktualisiert",
|
|
@@ -67,35 +93,8 @@
|
|
|
67
93
|
"pl": "dodaj typ zdarzenia \"powiadomienie o wartości\"",
|
|
68
94
|
"uk": "додати тип події \"значення повідомлення\"",
|
|
69
95
|
"zh-cn": "添加事件类型“ 值通知”"
|
|
70
|
-
},
|
|
71
|
-
"0.0.12": {
|
|
72
|
-
"en": "typo\nfix dp channel name\nadd endpoint > 0 to value if exists",
|
|
73
|
-
"de": "typo\ndp kanal name\nendpunkt hinzufügen > 0 auf wert, falls vorhanden",
|
|
74
|
-
"ru": "опечатка\nустановить имя канала dp\nдобавить конечную точку 0, если существует",
|
|
75
|
-
"pt": "erro de digitação\ncorrigir o nome do canal dp\nadicionar endpoint > 0 a valor se existir",
|
|
76
|
-
"nl": "type\nfix dp kanaalnaam\neindpunt toevoegen > 0 naar waarde indien aanwezig",
|
|
77
|
-
"fr": "typo\ncorriger le nom du canal dp\najouter le paramètre > 0 à valeur s'il existe",
|
|
78
|
-
"it": "tipo\ncorretto nome del canale dp\naggiungere il punto finale 0 a valore se esiste",
|
|
79
|
-
"es": "typo\nfijar nombre del canal dp\nañadir endpoint √ 0 a valor si existe",
|
|
80
|
-
"pl": "typo\nfix dp nazwa kanału\ndodać punkt końcowy > 0 do wartości, jeśli istnieje",
|
|
81
|
-
"uk": "типи\nзафіксувати ім'я каналів dp\nдодати кінцеву точку > 0 до значення, якщо існує",
|
|
82
|
-
"zh-cn": "类型\n修复 dp 频道名称\n添加终点 > 0 到数值( 如果存在)"
|
|
83
|
-
},
|
|
84
|
-
"0.0.11": {
|
|
85
|
-
"en": "fix dp types",
|
|
86
|
-
"de": "dp-typen",
|
|
87
|
-
"ru": "фиксировать типы dp",
|
|
88
|
-
"pt": "corrigir tipos dp",
|
|
89
|
-
"nl": "fix dp types",
|
|
90
|
-
"fr": "correction des types dp",
|
|
91
|
-
"it": "corretti i tipi dp",
|
|
92
|
-
"es": "arreglos tipo dp",
|
|
93
|
-
"pl": "fix dp types",
|
|
94
|
-
"uk": "фіксувати типи dp",
|
|
95
|
-
"zh-cn": "固定 dp 类型"
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
|
-
"messages": [],
|
|
99
98
|
"titleLang": {
|
|
100
99
|
"en": "Z-Wave WS",
|
|
101
100
|
"de": "Z-Wave WS",
|
|
@@ -183,6 +182,60 @@
|
|
|
183
182
|
{
|
|
184
183
|
"admin": ">=7.6.17"
|
|
185
184
|
}
|
|
185
|
+
],
|
|
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
|
+
}
|
|
186
239
|
]
|
|
187
240
|
},
|
|
188
241
|
"native": {
|
|
@@ -207,7 +260,8 @@
|
|
|
207
260
|
"showNodeInfoMessage": true,
|
|
208
261
|
"useEventInDesc": false,
|
|
209
262
|
"wakeUpInfo": false,
|
|
210
|
-
"newTypeEvent": true
|
|
263
|
+
"newTypeEvent": true,
|
|
264
|
+
"wsOnStart": true
|
|
211
265
|
},
|
|
212
266
|
"protectedNative": [
|
|
213
267
|
"externalMqttServerPassword",
|
|
@@ -291,6 +345,19 @@
|
|
|
291
345
|
"def": ""
|
|
292
346
|
},
|
|
293
347
|
"native": {}
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
"_id": "info.sendMessageAllowed",
|
|
351
|
+
"type": "state",
|
|
352
|
+
"common": {
|
|
353
|
+
"role": "state",
|
|
354
|
+
"name": "send message is allowed",
|
|
355
|
+
"type": "boolean",
|
|
356
|
+
"read": true,
|
|
357
|
+
"write": true,
|
|
358
|
+
"def": true
|
|
359
|
+
},
|
|
360
|
+
"native": {}
|
|
294
361
|
}
|
|
295
362
|
]
|
|
296
363
|
}
|
package/lib/constants.js
CHANGED
|
@@ -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
|
@@ -63,11 +63,12 @@ class Helper {
|
|
|
63
63
|
|
|
64
64
|
const valuesOnly = element.values ?? null;
|
|
65
65
|
delete element.values;
|
|
66
|
+
|
|
66
67
|
await this.parse(`${nodeId}.info`, element);
|
|
67
68
|
|
|
68
69
|
if (valuesOnly != null && typeof valuesOnly === "object" && valuesOnly.length > 0) {
|
|
69
70
|
for (const v of valuesOnly) {
|
|
70
|
-
let parsePath = `${nodeId}.${v.commandClassName}
|
|
71
|
+
let parsePath = utils.formatObject(`${nodeId}.${v.commandClassName}`);
|
|
71
72
|
let metadata = v.metadata || {};
|
|
72
73
|
|
|
73
74
|
if (constant.noInfoDP.includes(v.commandClassName)) {
|
|
@@ -114,6 +115,8 @@ class Helper {
|
|
|
114
115
|
parsePath = `${parsePath}_${v.endpoint}`;
|
|
115
116
|
}
|
|
116
117
|
|
|
118
|
+
parsePath = utils.formatObject(parsePath); // entferne sonderzeichen und blanke aus dem namen
|
|
119
|
+
|
|
117
120
|
const nam_id = v.label ?? v.propertyName;
|
|
118
121
|
|
|
119
122
|
metadata.value = v.value; // add value for resolution
|
|
@@ -158,15 +161,14 @@ class Helper {
|
|
|
158
161
|
common,
|
|
159
162
|
native,
|
|
160
163
|
});
|
|
161
|
-
|
|
164
|
+
|
|
162
165
|
if (common.write === true) {
|
|
163
166
|
this.adapter.subscribeStates(parsePath);
|
|
164
167
|
}
|
|
165
168
|
|
|
166
|
-
this.
|
|
167
|
-
|
|
168
|
-
this.adapter.setState(parsePath, valDp, true);
|
|
169
|
+
this.adapter.setStateChanged(parsePath, valDp, true);
|
|
169
170
|
|
|
171
|
+
this.alreadyCreatedObjects[parsePath] = {};
|
|
170
172
|
}
|
|
171
173
|
}
|
|
172
174
|
} catch (error) {
|
|
@@ -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}`);
|
|
@@ -222,7 +224,7 @@ class Helper {
|
|
|
222
224
|
}
|
|
223
225
|
}
|
|
224
226
|
|
|
225
|
-
this.adapter.
|
|
227
|
+
this.adapter.setStateChanged(parsePath, valDp, true);
|
|
226
228
|
return;
|
|
227
229
|
}
|
|
228
230
|
options.channelName = utils.getLastSegment(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)) {
|
|
@@ -271,6 +273,11 @@ class Helper {
|
|
|
271
273
|
continue;
|
|
272
274
|
}
|
|
273
275
|
|
|
276
|
+
// überspringe bestimmte DP Namen
|
|
277
|
+
if (constant.noInfoDP.includes(key)) {
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
|
|
274
281
|
const isObj = this.isObject(valDP);
|
|
275
282
|
|
|
276
283
|
if (isObj) {
|
|
@@ -327,13 +334,13 @@ class Helper {
|
|
|
327
334
|
|
|
328
335
|
try {
|
|
329
336
|
if (valDP !== undefined) {
|
|
330
|
-
this.adapter.
|
|
337
|
+
this.adapter.setStateChanged(fullPath, valDP, true);
|
|
331
338
|
|
|
332
339
|
if (fullPath.endsWith('ready') ) {
|
|
333
340
|
valDP = element['status'];
|
|
334
341
|
if (utils.isNumeric(valDP) && valDP == 3) {
|
|
335
342
|
fullPath = fullPath.replace(".status", ".ready");
|
|
336
|
-
this.adapter.
|
|
343
|
+
this.adapter.setStateChanged(fullPath, false, true);
|
|
337
344
|
}
|
|
338
345
|
}
|
|
339
346
|
}
|
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
|
|
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
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
2
|
|
|
3
3
|
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;
|
|
@@ -14,7 +15,6 @@ const MqttServerController = require("./lib/mqttServerController").MqttServerCon
|
|
|
14
15
|
|
|
15
16
|
let mqttClient;
|
|
16
17
|
let deviceCache = {};
|
|
17
|
-
let nodeCache = {};
|
|
18
18
|
const logCustomizations = { debugDevices: "", logfilter: [] };
|
|
19
19
|
|
|
20
20
|
let websocketController;
|
|
@@ -49,7 +49,7 @@ class zwavews extends core.Adapter {
|
|
|
49
49
|
// Initialize your adapter here
|
|
50
50
|
adapterInfo(this.config, this.log);
|
|
51
51
|
|
|
52
|
-
this.
|
|
52
|
+
this.setStateChanged("info.connection", false, true);
|
|
53
53
|
await statesController.setAllAvailableToFalse();
|
|
54
54
|
|
|
55
55
|
helper = new Helper(this, deviceCache);
|
|
@@ -60,7 +60,16 @@ class zwavews extends core.Adapter {
|
|
|
60
60
|
debugDevicesState.val.toLowerCase(),
|
|
61
61
|
);
|
|
62
62
|
}
|
|
63
|
-
|
|
63
|
+
|
|
64
|
+
this.deviceManagement = new dmZwave(this);
|
|
65
|
+
|
|
66
|
+
if (this.config.wsOnStart) {
|
|
67
|
+
this.setStateChanged("info.sendMessageAllowed", true, true);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
this.nodeCache = {};
|
|
71
|
+
this.setStateChanged("info.debugmessages", "", true);
|
|
72
|
+
|
|
64
73
|
|
|
65
74
|
// MQTT
|
|
66
75
|
if (["exmqtt", "intmqtt"].includes(this.config.connectionType)) {
|
|
@@ -113,7 +122,7 @@ class zwavews extends core.Adapter {
|
|
|
113
122
|
// MQTT Client
|
|
114
123
|
mqttClient.on("connect", () => {
|
|
115
124
|
this.log.info(`Connect to zwavews over ${this.config.connectionType == "exmqtt" ? "external mqtt" : "internal mqtt"} connection.`);
|
|
116
|
-
this.
|
|
125
|
+
this.setStateChanged("info.connection", true, true);
|
|
117
126
|
});
|
|
118
127
|
|
|
119
128
|
mqttClient.subscribe(`${this.config.baseTopic}/#`);
|
|
@@ -133,7 +142,7 @@ class zwavews extends core.Adapter {
|
|
|
133
142
|
if (this.config.dummyMqtt == true) {
|
|
134
143
|
mqttServerController = new MqttServerController(this);
|
|
135
144
|
await mqttServerController.createDummyMQTTServer();
|
|
136
|
-
this.
|
|
145
|
+
this.setStateChanged("info.connection", true, true);
|
|
137
146
|
await this.delay(1500);
|
|
138
147
|
}
|
|
139
148
|
|
|
@@ -161,7 +170,7 @@ class zwavews extends core.Adapter {
|
|
|
161
170
|
await statesController.setAllAvailableToFalse();
|
|
162
171
|
startListening = false;
|
|
163
172
|
deviceCache = [];
|
|
164
|
-
nodeCache = [];
|
|
173
|
+
this.nodeCache = [];
|
|
165
174
|
this.log.info('Websocket connection closed. Attempting to reconnect...');
|
|
166
175
|
});
|
|
167
176
|
}
|
|
@@ -198,6 +207,10 @@ class zwavews extends core.Adapter {
|
|
|
198
207
|
break;
|
|
199
208
|
}
|
|
200
209
|
|
|
210
|
+
if (allNodesCreated) { // wird manchmal doppelt geschickt
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
|
|
201
214
|
driver = messageObj.result.state.driver;
|
|
202
215
|
controller = messageObj.result.state.controller;
|
|
203
216
|
allNodes = messageObj.result.state.nodes;
|
|
@@ -209,13 +222,13 @@ class zwavews extends core.Adapter {
|
|
|
209
222
|
this.log.warn(`--->>> fromZ2W_RAW2-> ${JSON.stringify(nodeData)}` );
|
|
210
223
|
}
|
|
211
224
|
|
|
212
|
-
if (!nodeCache[nodeId]) {
|
|
225
|
+
if (!this.nodeCache[nodeId]) {
|
|
213
226
|
if (this.config.showNodeInfoMessage) {
|
|
214
227
|
this.log.info(`Node Info Update for ${nodeId}`);
|
|
215
228
|
}
|
|
216
|
-
nodeCache[nodeId] = {
|
|
229
|
+
this.nodeCache[nodeId] = {nodeData};
|
|
217
230
|
}
|
|
218
|
-
await helper.createNode(
|
|
231
|
+
await helper.createNode(nodeId, nodeData, options);
|
|
219
232
|
}
|
|
220
233
|
|
|
221
234
|
allNodesCreated = true;
|
|
@@ -255,6 +268,8 @@ class zwavews extends core.Adapter {
|
|
|
255
268
|
}
|
|
256
269
|
}
|
|
257
270
|
|
|
271
|
+
parsePath = utils.formatObject(parsePath);
|
|
272
|
+
|
|
258
273
|
if (nodeArg.commandClass === 119) { // sonderlocke für node naming
|
|
259
274
|
switch (nodeArg.property) {
|
|
260
275
|
case 'name':
|
|
@@ -398,7 +413,7 @@ class zwavews extends core.Adapter {
|
|
|
398
413
|
this.log.error(e);
|
|
399
414
|
}
|
|
400
415
|
|
|
401
|
-
this.
|
|
416
|
+
this.setStateChanged("info.connection", false, true);
|
|
402
417
|
|
|
403
418
|
callback();
|
|
404
419
|
}
|
|
@@ -407,11 +422,11 @@ class zwavews extends core.Adapter {
|
|
|
407
422
|
if (!allNodesCreated) { // wenn alle nodes angelegt sind, erst dann horchen auf target
|
|
408
423
|
return;
|
|
409
424
|
}
|
|
410
|
-
|
|
425
|
+
|
|
411
426
|
if (state && state.ack == false) {
|
|
412
427
|
if (id.endsWith("info.debugId")) {
|
|
413
428
|
logCustomizations.debugDevices = state.val.toLowerCase();
|
|
414
|
-
this.
|
|
429
|
+
this.setStateChanged(id, state.val, true);
|
|
415
430
|
return;
|
|
416
431
|
}
|
|
417
432
|
|
|
@@ -429,13 +444,17 @@ class zwavews extends core.Adapter {
|
|
|
429
444
|
nodeId: nodeId,
|
|
430
445
|
valueId: nativeObj.valueId,
|
|
431
446
|
value: state.val
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
const sendMessageAllowed = await this.getStateAsync("info.sendMessageAllowed");
|
|
435
450
|
|
|
436
|
-
|
|
451
|
+
if (sendMessageAllowed.val) {
|
|
452
|
+
websocketController.send(JSON.stringify(message));
|
|
453
|
+
}
|
|
437
454
|
|
|
438
|
-
|
|
455
|
+
this.setStateChanged('info.debugmessages', JSON.stringify(message), true);
|
|
456
|
+
this.log.debug(`<zwavews> message onStateChange ${message}`);
|
|
457
|
+
}
|
|
439
458
|
}
|
|
440
459
|
}
|
|
441
460
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.zwavews",
|
|
3
|
-
"version": "0.0
|
|
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",
|