iobroker.sonoff 2.4.6 → 2.5.1
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/.github/workflows/dependabot-automerge.yml +1 -1
- package/.github/workflows/test-and-release.yml +6 -6
- package/.mocharc.json +5 -0
- package/LICENSE +1 -1
- package/README.md +22 -1
- package/admin/words.js +1 -1
- package/io-package.json +37 -37
- package/lib/server.js +96 -88
- package/package.json +9 -9
|
@@ -28,9 +28,9 @@ jobs:
|
|
|
28
28
|
node-version: [12.x]
|
|
29
29
|
|
|
30
30
|
steps:
|
|
31
|
-
- uses: actions/checkout@
|
|
31
|
+
- uses: actions/checkout@v3
|
|
32
32
|
- name: Use Node.js ${{ matrix.node-version }}
|
|
33
|
-
uses: actions/setup-node@
|
|
33
|
+
uses: actions/setup-node@v3
|
|
34
34
|
with:
|
|
35
35
|
node-version: ${{ matrix.node-version }}
|
|
36
36
|
|
|
@@ -60,9 +60,9 @@ jobs:
|
|
|
60
60
|
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
61
61
|
|
|
62
62
|
steps:
|
|
63
|
-
- uses: actions/checkout@
|
|
63
|
+
- uses: actions/checkout@v3
|
|
64
64
|
- name: Use Node.js ${{ matrix.node-version }}
|
|
65
|
-
uses: actions/setup-node@
|
|
65
|
+
uses: actions/setup-node@v3
|
|
66
66
|
with:
|
|
67
67
|
node-version: ${{ matrix.node-version }}
|
|
68
68
|
|
|
@@ -96,10 +96,10 @@ jobs:
|
|
|
96
96
|
|
|
97
97
|
steps:
|
|
98
98
|
- name: Checkout code
|
|
99
|
-
uses: actions/checkout@
|
|
99
|
+
uses: actions/checkout@v3
|
|
100
100
|
|
|
101
101
|
- name: Use Node.js ${{ matrix.node-version }}
|
|
102
|
-
uses: actions/setup-node@
|
|
102
|
+
uses: actions/setup-node@v3
|
|
103
103
|
with:
|
|
104
104
|
node-version: ${{ matrix.node-version }}
|
|
105
105
|
|
package/.mocharc.json
ADDED
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
The MIT License (MIT)
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2014-
|
|
3
|
+
Copyright (c) 2014-2022 bluefox <dogafox@gmail.com>
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -11,6 +11,17 @@
|
|
|
11
11
|
|
|
12
12
|
**This adapter uses Sentry libraries to automatically report exceptions and code errors to the developers.** For more details and for information how to disable the error reporting see [Sentry-Plugin Documentation](https://github.com/ioBroker/plugin-sentry#plugin-sentry)! Sentry reporting is used starting with js-controller 3.0.
|
|
13
13
|
|
|
14
|
+
## Comparison of ioBroker adapters using MQTT protocol
|
|
15
|
+
If you only have Tasmotas speaking MQTT protocol go for ioBroker.sonoff. For other scenarios consider the different options:
|
|
16
|
+
||ioBroker.sonoff|[ioBroker.mqtt](https://github.com/ioBroker/ioBroker.mqtt/) (in broker mode)|[ioBroker.mqtt](https://github.com/ioBroker/ioBroker.mqtt/) (in client mode)|[ioBroker.mqtt-client](https://github.com/Pmant/ioBroker.mqtt-client/)|
|
|
17
|
+
|---|---|---|---|---|
|
|
18
|
+
|Has a built-in MQTT broker|yes|yes|no|no|
|
|
19
|
+
|Relays messages to other MQTT subscribers|NO!!!|yes|not aplicable|not aplicable|
|
|
20
|
+
|External MQTT broker|unsupported|unsupported|required|required|
|
|
21
|
+
|Tasmota MQTT messages to ioBroker Objects|smart processing|1:1 processing of all messages|1:1 processing of subscribed messages|1:1 processing of subscribed messages|
|
|
22
|
+
|non-Tasmota MQTT messages to ioBroker Objects|no processing|1:1 processing of all messages|1:1 processing of subscribed messages|1:1 processing of subscribed messages|
|
|
23
|
+
|publish ioBroker values as MQTT messages|none|configured subtrees|configured subtrees|individually configured values|
|
|
24
|
+
|
|
14
25
|
## Usage
|
|
15
26
|
|
|
16
27
|
This adapter communicates with Sonoff devices with Tasmota firmware or ESP devices via MQTT.
|
|
@@ -109,6 +120,16 @@ States:
|
|
|
109
120
|
### __WORK IN PROGRESS__
|
|
110
121
|
-->
|
|
111
122
|
## Changelog
|
|
123
|
+
### 2.5.1 (2022-04-23)
|
|
124
|
+
* (Apollon77) Fix crash case reported by Sentry
|
|
125
|
+
|
|
126
|
+
### 2.5.0 (2022-03-21)
|
|
127
|
+
* (GreatSUN) Implement writing of NSPanel Widget changes
|
|
128
|
+
* (Apollon77) Fix crash case reported by Sentry
|
|
129
|
+
|
|
130
|
+
### 2.4.7 (2021-11-14)
|
|
131
|
+
* (Apollon77) Fix crash case (Sentry IOBROKER-SONOFF-1S)
|
|
132
|
+
|
|
112
133
|
### 2.4.6 (2021-11-13)
|
|
113
134
|
* (Apollon77) Fix some crash cases reported by Sentry (IOBROKER-SONOFF-B, IOBROKER-SONOFF-R, IOBROKER-SONOFF-4, IOBROKER-SONOFF-1, IOBROKER-SONOFF-13, IOBROKER-SONOFF-1J, IOBROKER-SONOFF-16, IOBROKER-SONOFF-3, IOBROKER-SONOFF-H)
|
|
114
135
|
* (Apollon77) Adjust Uptime to mixed because it seems that it can be number or string
|
|
@@ -223,7 +244,7 @@ States:
|
|
|
223
244
|
|
|
224
245
|
The MIT License (MIT)
|
|
225
246
|
|
|
226
|
-
Copyright (c) 2017-
|
|
247
|
+
Copyright (c) 2017-2022, bluefox <dogafox@gmail.com>
|
|
227
248
|
|
|
228
249
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
229
250
|
of this software and associated documentation files (the "Software"), to deal
|
package/admin/words.js
CHANGED
|
@@ -48,7 +48,7 @@ systemDictionary = {
|
|
|
48
48
|
"Use WebSockets:": { "en": "Use WebSockets too", "de": "Benutze auch WebSockets", "ru": "Сервер WebSockets тоже", "pt": "Use também WebSockets", "nl": "Use também WebSockets", "fr": "Utilisez aussi WebSockets", "it": "Utilizza anche WebSockets", "es": "Use WebSockets también", "pl": "Użyj także WebSockets", "zh-cn": "也使用WebSockets"},
|
|
49
49
|
"Use chunk patch:": { "en": "Use chunk patch", "de": "Benutze Patch für Chunking", "ru": "Использовать заплатку для Chunking", "pt": "Use patch de pedaços", "nl": "Use patch de pedaços", "fr": "Utiliser un patch de morceau", "it": "Usa patch pezzo", "es": "Use el fragmento de fragmento", "pl": "Użyj poprawki kawałka", "zh-cn": "使用大块补丁"},
|
|
50
50
|
"Use different topic names for set and get:": { "en": "Use different topic names for set and get", "de": "Unterschiedliche Namen für setzten und lesen", "ru": "Использовать разные имена для чтения и записи", "pt": "Use nomes de tópicos diferentes para definir e obter", "nl": "Use nomes de tópicos diferentes para definir e obter", "fr": "Utilisez différents noms de sujet pour définir et obtenir", "it": "Usa diversi nomi di argomenti per impostare e ottenere", "es": "Use diferentes nombres de tema para establecer y obtener", "pl": "Używaj różnych nazw tematów do ustawiania i pobierania", "zh-cn": "使用不同的主题名称进行设置和获取"},
|
|
51
|
-
"User:": { "en": "User", "de": "Benutzer", "ru": "Имя пользователя", "pt": "
|
|
51
|
+
"User:": { "en": "User", "de": "Benutzer", "ru": "Имя пользователя", "pt": "Utilizador", "nl": "Do utilizador", "fr": "Utilisateur", "it": "Utente", "es": "Usuario", "pl": "Użytkownik", "zh-cn": "用户"},
|
|
52
52
|
"chars": { "en": "chars", "de": "Symbolen", "ru": "символов", "pt": "caracteres", "nl": "caracteres", "fr": "chars", "it": "caratteri", "es": "caracteres", "pl": "znaki", "zh-cn": "字符"},
|
|
53
53
|
"connected": { "en": "connected", "de": "verbunden", "ru": "успешно", "pt": "conectado", "nl": "conectado", "fr": "connecté", "it": "collegato", "es": "conectado", "pl": "połączony", "zh-cn": "连接的"},
|
|
54
54
|
"ms": { "en": "ms", "de": "ms", "ru": "мс", "pt": "Senhora", "nl": "Senhora", "fr": "Mme", "it": "Signorina", "es": "Sra", "pl": "ms", "zh-cn": "女士"},
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,44 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "sonoff",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.5.1",
|
|
5
5
|
"news": {
|
|
6
|
+
"2.5.1": {
|
|
7
|
+
"en": "Fix crash case reported by Sentry",
|
|
8
|
+
"de": "Absturzfall behoben, der von Sentry gemeldet wurde",
|
|
9
|
+
"ru": "Исправить случай сбоя, о котором сообщил Sentry",
|
|
10
|
+
"pt": "Corrigir caso de falha relatado pelo Sentinela",
|
|
11
|
+
"nl": "Herstel crashgeval gemeld door Sentry",
|
|
12
|
+
"fr": "Correction d'un cas de crash signalé par Sentry",
|
|
13
|
+
"it": "Risolto il caso di crash segnalato da Sentry",
|
|
14
|
+
"es": "Solucionar caso de bloqueo informado por Sentry",
|
|
15
|
+
"pl": "Napraw przypadek awarii zgłoszony przez Sentry",
|
|
16
|
+
"zh-cn": "修复 Sentry 报告的崩溃案例"
|
|
17
|
+
},
|
|
18
|
+
"2.5.0": {
|
|
19
|
+
"en": "Implement writing of NSPanel Widget changes\nFix crash case reported by Sentry",
|
|
20
|
+
"de": "Implementieren Sie das Schreiben von NSPanel-Widget-Änderungen\nAbsturzfall behoben, der von Sentry gemeldet wurde",
|
|
21
|
+
"ru": "Реализовать запись изменений виджета NSPanel\nИсправить случай сбоя, о котором сообщил Sentry",
|
|
22
|
+
"pt": "Implemente a gravação de alterações do Widget NSPanel\nCorrigir caso de falha relatado pelo Sentinela",
|
|
23
|
+
"nl": "Implementeren van het schrijven van NSPanel Widget-wijzigingen\nHerstel crashgeval gemeld door Sentry",
|
|
24
|
+
"fr": "Mettre en œuvre l'écriture des modifications du Widget NSPanel\nCorrection d'un cas de crash signalé par Sentry",
|
|
25
|
+
"it": "Implementare la scrittura delle modifiche al Widget NSPanel\nRisolto il caso di crash segnalato da Sentry",
|
|
26
|
+
"es": "Implementar la escritura de cambios de NSPanel Widget\nSolucionar caso de bloqueo informado por Sentry",
|
|
27
|
+
"pl": "Zaimplementuj pisanie zmian NSPanel Widget\nNapraw przypadek awarii zgłoszony przez Sentry",
|
|
28
|
+
"zh-cn": "实现编写 NSPanel Widget 更改\n修复 Sentry 报告的崩溃案例"
|
|
29
|
+
},
|
|
30
|
+
"2.4.7": {
|
|
31
|
+
"en": "Fix crash case (Sentry IOBROKER-SONOFF-1S)",
|
|
32
|
+
"de": "Crashfall beheben (Sentry IOBROKER-SONOFF-1S)",
|
|
33
|
+
"ru": "Исправить сбой (Sentry IOBROKER-SONOFF-1S)",
|
|
34
|
+
"pt": "Corrigir caso de falha (Sentry IOBROKER-SONOFF-1S)",
|
|
35
|
+
"nl": "Crashgeval repareren (Sentry IOBROKER-SONOFF-1S)",
|
|
36
|
+
"fr": "Correction du crash (Sentry IOBROKER-SONOFF-1S)",
|
|
37
|
+
"it": "Risolto il crash case (Sentry IOBROKER-SONOFF-1S)",
|
|
38
|
+
"es": "Reparar caso de bloqueo (Sentry IOBROKER-SONOFF-1S)",
|
|
39
|
+
"pl": "Napraw przypadek awarii (Sentry IOBROKER-SONOFF-1S)",
|
|
40
|
+
"zh-cn": "修复崩溃案例(Sentry IOBROKER-SONOFF-1S)"
|
|
41
|
+
},
|
|
6
42
|
"2.4.6": {
|
|
7
43
|
"en": "Fix some crash cases reported by Sentry (IOBROKER-SONOFF-B, IOBROKER-SONOFF-R, IOBROKER-SONOFF-4, IOBROKER-SONOFF-1, IOBROKER-SONOFF-13, IOBROKER-SONOFF-1J, IOBROKER-SONOFF-16, IOBROKER-SONOFF-3, IOBROKER-SONOFF-H)\nAdjust Uptime to mixed because it seems that it can be number or string",
|
|
8
44
|
"de": "Behebung einiger von Sentry gemeldeter Absturzfälle (IOBROKER-SONOFF-B, IOBROKER-SONOFF-R, IOBROKER-SONOFF-4, IOBROKER-SONOFF-1, IOBROKER-SONOFF-13, IOBROKER-SONOFF-1J, IOBROKER-SONOFF-16, IOBROKER-SONOFF-3, IOBROKER-SONOFF-H)\nStellen Sie die Betriebszeit auf gemischt ein, da es sich anscheinend um eine Zahl oder eine Zeichenfolge handeln kann",
|
|
@@ -50,42 +86,6 @@
|
|
|
50
86
|
"es": "Mejor detección de tipos para estados no descritos",
|
|
51
87
|
"pl": "Lepsze wykrywanie typów dla stanów nieopisanych",
|
|
52
88
|
"zh-cn": "更好的未描述状态的类型检测"
|
|
53
|
-
},
|
|
54
|
-
"2.4.2": {
|
|
55
|
-
"en": "Optimize for js-controller 3.3",
|
|
56
|
-
"de": "Optimieren Sie für js-Controller 3.3",
|
|
57
|
-
"ru": "Оптимизировать под js-controller 3.3",
|
|
58
|
-
"pt": "Otimize para js-controller 3.3",
|
|
59
|
-
"nl": "Optimaliseren voor js-controller 3.3",
|
|
60
|
-
"fr": "Optimiser pour js-controller 3.3",
|
|
61
|
-
"it": "Ottimizza per js-controller 3.3",
|
|
62
|
-
"es": "Optimizar para js-controller 3.3",
|
|
63
|
-
"pl": "Optymalizacja dla kontrolera js 3.3",
|
|
64
|
-
"zh-cn": "针对 js-controller 3.3 优化"
|
|
65
|
-
},
|
|
66
|
-
"2.4.1": {
|
|
67
|
-
"en": "(Apollon77/bluefox) Optimize for js-controller 3.3\nAdd Sentry for error reporting with js-controller 3.x+",
|
|
68
|
-
"de": "(Apollon77/bluefox) Optimieren für js-Controller 3.3\nSentry für Fehlerberichte mit js-controller 3.x+ hinzufügen Add",
|
|
69
|
-
"ru": "(Apollon77 / bluefox) Оптимизация под js-controller 3.3\nДобавить Sentry для отчетов об ошибках с js-controller 3.x +",
|
|
70
|
-
"pt": "(Apollon77 / bluefox) Otimize para js-controller 3.3\nAdicionar Sentry para relatório de erros com js-controller 3.x +",
|
|
71
|
-
"nl": "(Apollon77/bluefox) Optimaliseren voor js-controller 3.3\nAdd Sentry voor foutrapportage met js-controller 3.x+",
|
|
72
|
-
"fr": "(Apollon77/bluefox) Optimiser pour js-controller 3.3\nAjouter Sentry pour le rapport d'erreurs avec js-controller 3.x+",
|
|
73
|
-
"it": "(Apollon77/bluefox) Ottimizza per js-controller 3.3\nAggiungi Sentry per la segnalazione degli errori con js-controller 3.x+",
|
|
74
|
-
"es": "(Apollon77 / bluefox) Optimizar para js-controller 3.3\nAgregue Sentry para informes de errores con js-controller 3.x +",
|
|
75
|
-
"pl": "(Apollon77/bluefox) Optymalizacja dla kontrolera js 3.3\nDodaj Sentry do raportowania błędów z js-controller 3.x+",
|
|
76
|
-
"zh-cn": "(Apollon77/bluefox) 针对 js-controller 3.3 优化\n使用 js-controller 3.x+ 添加 Sentry 用于错误报告"
|
|
77
|
-
},
|
|
78
|
-
"2.4.0": {
|
|
79
|
-
"en": "add several datapoints\nFix tranlation for 'ignorePings'\nFix wrong unit for humidity\nConfig option to create a complete object tree instead of a flat structure\nChange Action type to string\njs-controller 2.0 is required at least",
|
|
80
|
-
"de": "Fügen Sie mehrere Datenpunkte hinzu\nKorrektur der Übersetzung für 'ignorePings'\nKorrigieren Sie das falsche Gerät für die Luftfeuchtigkeit\nKonfigurationsoption zum Erstellen eines vollständigen Objektbaums anstelle einer flachen Struktur\nÄndern Sie den Aktionstyp in Zeichenfolge\nmindestens js-controller 2.0 ist erforderlich",
|
|
81
|
-
"ru": "добавить несколько точек данных\nИсправить перевод для ignorePings\nИсправьте неправильную единицу измерения влажности\nВозможность конфигурации для создания полного дерева объектов вместо плоской структуры\nИзмените тип действия на строку\njs-controller 2.0 требуется как минимум",
|
|
82
|
-
"pt": "adicionar vários pontos de dados\nCorrigir tradução para 'ignorePings'\nConsertar unidade errada para umidade\nOpção de configuração para criar uma árvore de objetos completa em vez de uma estrutura plana\nAlterar o tipo de ação para string\njs-controller 2.0 é necessário pelo menos",
|
|
83
|
-
"nl": "voeg meerdere datapunten toe\nHerstel vertaling voor 'ignorePings'\nBevestig verkeerde eenheid voor vochtigheid\nConfiguratie-optie om een complete objectenboom te maken in plaats van een platte structuur\nWijzig het actietype in string\njs-controller 2.0 is minimaal vereist",
|
|
84
|
-
"fr": "ajouter plusieurs points de données\nCorrection de la traduction pour 'ignorePings'\nCorrection d'une mauvaise unité pour l'humidité\nOption de configuration pour créer une arborescence d'objets complète au lieu d'une structure plate\nChanger le type d'action en chaîne\njs-controller 2.0 est requis au moins",
|
|
85
|
-
"it": "aggiungere diversi datapoint\nCorrezione della traduzione per \"ignorePings\"\nCorreggi l'unità sbagliata per l'umidità\nOpzione di configurazione per creare un albero di oggetti completo invece di una struttura piatta\nCambia il tipo di azione in stringa\nÈ richiesto almeno js-controller 2.0",
|
|
86
|
-
"es": "agregar varios puntos de datos\nCorregir traducción para 'ignorePings'\nArregle la unidad incorrecta para la humedad\nOpción de configuración para crear un árbol de objetos completo en lugar de una estructura plana\nCambiar el tipo de acción a cadena\njs-controller 2.0 se requiere al menos",
|
|
87
|
-
"pl": "dodaj kilka punktów danych\nNapraw tłumaczenie dla „ignorePings”\nNapraw niewłaściwą jednostkę ze względu na wilgotność\nOpcja konfiguracji, aby utworzyć pełne drzewo obiektów zamiast płaskiej struktury\nZmień typ akcji na ciąg\njs-controller 2.0 jest wymagany przynajmniej",
|
|
88
|
-
"zh-cn": "添加几个数据点\n修复“ ignorePings”的翻译\n固定错误的湿度单元\nConfig选项创建完整的对象树而不是平面结构\n将动作类型更改为字符串\n至少需要js-controller 2.0"
|
|
89
89
|
}
|
|
90
90
|
},
|
|
91
91
|
"title": "Sonoff",
|
package/lib/server.js
CHANGED
|
@@ -103,7 +103,7 @@ function hsvToRgb(h, s, v) {
|
|
|
103
103
|
|
|
104
104
|
function componentToHex(c) {
|
|
105
105
|
const hex = c.toString(16);
|
|
106
|
-
return hex.length === 1 ?
|
|
106
|
+
return hex.length === 1 ? `0${hex}` : hex;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
function toPaddedHexString(num, len) {
|
|
@@ -113,7 +113,7 @@ function toPaddedHexString(num, len) {
|
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
const str = num.toString(16);
|
|
116
|
-
if (str.length
|
|
116
|
+
if (str.length >= len) return str;
|
|
117
117
|
return '0'.repeat(len - str.length) + str;
|
|
118
118
|
}
|
|
119
119
|
|
|
@@ -191,7 +191,7 @@ function MQTTServer(adapter) {
|
|
|
191
191
|
if (clients[channelId] && clients[channelId]._map && clients[channelId]._map[stateId]) {
|
|
192
192
|
setImmediate(sendState2Client, clients[channelId], clients[channelId]._map[stateId] || 'cmnd/sonoff/Color', val, adapter.config.defaultQoS);
|
|
193
193
|
} else if (clients[channelId] && clients[channelId]._fallBackName) {
|
|
194
|
-
setImmediate(sendState2Client, clients[channelId],
|
|
194
|
+
setImmediate(sendState2Client, clients[channelId], `cmnd/${clients[channelId]._fallBackName}/${stateId}`, val, adapter.config.defaultQoS);
|
|
195
195
|
} else {
|
|
196
196
|
adapter.log.warn(`Unknown mapping for "${stateId}"`);
|
|
197
197
|
}
|
|
@@ -205,7 +205,7 @@ function MQTTServer(adapter) {
|
|
|
205
205
|
if (clients[channelId]._map && clients[channelId]._map[stateId]) {
|
|
206
206
|
setImmediate(sendState2Client, clients[channelId], clients[channelId]._map[stateId] || 'cmnd/sonoff/POWER', val ? 'ON' : 'OFF', adapter.config.defaultQoS);
|
|
207
207
|
} else if (clients[channelId]._fallBackName) {
|
|
208
|
-
setImmediate(sendState2Client, clients[channelId],
|
|
208
|
+
setImmediate(sendState2Client, clients[channelId], `cmnd/${clients[channelId]._fallBackName}/${stateId}`, val, adapter.config.defaultQoS);
|
|
209
209
|
} else {
|
|
210
210
|
adapter.log.warn(`Unknown mapping for "${stateId}"`);
|
|
211
211
|
}
|
|
@@ -213,7 +213,7 @@ function MQTTServer(adapter) {
|
|
|
213
213
|
|
|
214
214
|
function setStateImmediate(channelId, stateId, val) {
|
|
215
215
|
if (clients[channelId] && clients[channelId]._map && clients[channelId]._map[stateId]) {
|
|
216
|
-
setImmediate(sendState2Client, clients[channelId], clients[channelId]._map[stateId] || (
|
|
216
|
+
setImmediate(sendState2Client, clients[channelId], clients[channelId]._map[stateId] || (`cmnd/sonoff/${stateId}`), val, adapter.config.defaultQoS);
|
|
217
217
|
} else if (clients[channelId] && clients[channelId]._fallBackName) {
|
|
218
218
|
setImmediate(sendState2Client, clients[channelId], `cmnd/${clients[channelId]._fallBackName}/${stateId}`, val, adapter.config.defaultQoS);
|
|
219
219
|
} else {
|
|
@@ -253,12 +253,12 @@ function MQTTServer(adapter) {
|
|
|
253
253
|
stateId = parts.pop();
|
|
254
254
|
|
|
255
255
|
if (stateId === 'level' || stateId === 'state' || stateId === 'red' || stateId === 'blue' || stateId === 'green') {
|
|
256
|
-
stateId = parts.pop()
|
|
256
|
+
stateId = `${parts.pop()}.${stateId}`;
|
|
257
257
|
}
|
|
258
258
|
|
|
259
259
|
channelId = parts.splice(2, parts.length).join('.');
|
|
260
260
|
}
|
|
261
|
-
const ledModeIdExor = adapter.namespace
|
|
261
|
+
const ledModeIdExor = `${adapter.namespace}.${channelId}.modeLedExor`;
|
|
262
262
|
if (cachedModeExor[ledModeIdExor] === undefined) {
|
|
263
263
|
return adapter.getForeignState(ledModeIdExor, (err, _state) => {
|
|
264
264
|
cachedModeExor[ledModeIdExor] = _state ? _state.val || false : true;
|
|
@@ -280,7 +280,9 @@ function MQTTServer(adapter) {
|
|
|
280
280
|
// set white to rgb or rgbww
|
|
281
281
|
adapter.getObject(id, (err, obj) => {
|
|
282
282
|
if (!obj) {
|
|
283
|
-
adapter.log.warn(
|
|
283
|
+
adapter.log.warn(`invalid rgbww obj for ${id}`);
|
|
284
|
+
} else if (typeof state.val !== 'string') {
|
|
285
|
+
adapter.log.warn(`invalid rgbww state value for ${id} : ${JSON.stringify(state.val)} needs to be a string`);
|
|
284
286
|
} else {
|
|
285
287
|
const role = obj.common.role;
|
|
286
288
|
let color;
|
|
@@ -291,13 +293,13 @@ function MQTTServer(adapter) {
|
|
|
291
293
|
if (state.val.toUpperCase() === '#FFFFFF') {
|
|
292
294
|
// transform white to WW
|
|
293
295
|
//color='000000FF';
|
|
294
|
-
color = state.val.substring(1)
|
|
296
|
+
color = `${state.val.substring(1)}00`;
|
|
295
297
|
} else {
|
|
296
298
|
// strip # char and add ww
|
|
297
|
-
color = state.val.substring(1)
|
|
299
|
+
color = `${state.val.substring(1)}00`;
|
|
298
300
|
}
|
|
299
301
|
} else if (role === 'level.color.rgbcwww') {
|
|
300
|
-
color = state.val.substring(1)
|
|
302
|
+
color = `${state.val.substring(1)}0000`;
|
|
301
303
|
} else {
|
|
302
304
|
// rgb, strip # char
|
|
303
305
|
color = state.val.substring(1);
|
|
@@ -311,25 +313,25 @@ function MQTTServer(adapter) {
|
|
|
311
313
|
|
|
312
314
|
// set rgb too
|
|
313
315
|
const hidE = id.split('.');
|
|
314
|
-
const deviceDesc = hidE[0]
|
|
315
|
-
let idAlive = deviceDesc
|
|
316
|
+
const deviceDesc = `${hidE[0]}.${hidE[1]}.${hidE[2]}`;
|
|
317
|
+
let idAlive = `${deviceDesc}.Red`;
|
|
316
318
|
adapter.setState(idAlive, 100 * parseInt(color.substring(0, 2), 16) / 255, true);
|
|
317
319
|
|
|
318
|
-
idAlive = deviceDesc
|
|
320
|
+
idAlive = `${deviceDesc}.Green`;
|
|
319
321
|
adapter.setState(idAlive, 100 * parseInt(color.substring(2, 4), 16) / 255, true);
|
|
320
322
|
|
|
321
|
-
idAlive = deviceDesc
|
|
323
|
+
idAlive = `${deviceDesc}.Blue`;
|
|
322
324
|
adapter.setState(idAlive, 100 * parseInt(color.substring(4, 6), 16) / 255, true);
|
|
323
325
|
}
|
|
324
326
|
});
|
|
325
327
|
} else {
|
|
326
328
|
const hidE = id.split('.');
|
|
327
|
-
const deviceDesc = hidE[0]
|
|
329
|
+
const deviceDesc = `${hidE[0]}.${hidE[1]}.${hidE[2]}`;
|
|
328
330
|
if (stateId.match(/Red\d?/)) {
|
|
329
331
|
// set red component
|
|
330
332
|
if (state.val > 100) state.val = 100;
|
|
331
333
|
const red = toPaddedHexString(Math.floor(255 * state.val / 100), 2);
|
|
332
|
-
const idAlive = deviceDesc
|
|
334
|
+
const idAlive = `${deviceDesc}.Color`;
|
|
333
335
|
adapter.getForeignState(idAlive, (err, state) => {
|
|
334
336
|
if (!state) {
|
|
335
337
|
adapter.setState(idAlive, '#000000', false);
|
|
@@ -338,7 +340,7 @@ function MQTTServer(adapter) {
|
|
|
338
340
|
const color = state.val.substring(1);
|
|
339
341
|
// replace red component
|
|
340
342
|
const out = red + color.substring(2, 10);
|
|
341
|
-
adapter.setState(idAlive,
|
|
343
|
+
adapter.setState(idAlive, `#${out}`, false);
|
|
342
344
|
setColor(channelId, out);
|
|
343
345
|
});
|
|
344
346
|
} else
|
|
@@ -346,7 +348,7 @@ function MQTTServer(adapter) {
|
|
|
346
348
|
// set green component
|
|
347
349
|
if (state.val > 100) state.val = 100;
|
|
348
350
|
const green = toPaddedHexString(Math.floor(255 * state.val / 100), 2);
|
|
349
|
-
const idAlive = deviceDesc
|
|
351
|
+
const idAlive = `${deviceDesc}.Color`;
|
|
350
352
|
adapter.getForeignState(idAlive, (err, state) => {
|
|
351
353
|
if (!state) {
|
|
352
354
|
adapter.setState(idAlive, '#000000', false);
|
|
@@ -355,7 +357,7 @@ function MQTTServer(adapter) {
|
|
|
355
357
|
const color = state.val.substring(1);
|
|
356
358
|
// replace green component
|
|
357
359
|
const out = color.substring(0, 2) + green + color.substring(4, 10);
|
|
358
|
-
adapter.setState(idAlive,
|
|
360
|
+
adapter.setState(idAlive, `#${out}`, false);
|
|
359
361
|
setColor(channelId, out);
|
|
360
362
|
});
|
|
361
363
|
} else
|
|
@@ -363,7 +365,7 @@ function MQTTServer(adapter) {
|
|
|
363
365
|
// set blue component
|
|
364
366
|
if (state.val > 100) state.val = 100;
|
|
365
367
|
const blue = toPaddedHexString(Math.floor(255 * state.val / 100), 2);
|
|
366
|
-
const idAlive = deviceDesc
|
|
368
|
+
const idAlive = `${deviceDesc}.Color`;
|
|
367
369
|
adapter.getForeignState(idAlive, (err, state) => {
|
|
368
370
|
if (!state) {
|
|
369
371
|
adapter.setState(idAlive, '#000000', false);
|
|
@@ -372,17 +374,17 @@ function MQTTServer(adapter) {
|
|
|
372
374
|
const color = state.val.substring(1);
|
|
373
375
|
// replace blue component
|
|
374
376
|
const out = color.substring(0, 4) + blue + color.substring(6, 10);
|
|
375
|
-
adapter.setState(idAlive,
|
|
377
|
+
adapter.setState(idAlive, `#${out}`, false);
|
|
376
378
|
setColor(channelId, out);
|
|
377
379
|
});
|
|
378
380
|
} else
|
|
379
381
|
if (stateId.match(/RGB_POWER\d?/)) {
|
|
380
382
|
// set ww component
|
|
381
383
|
const rgbpow = state.val === 'true' || state.val === true || state.val === 1 || state.val === '1';
|
|
382
|
-
const idAlive = deviceDesc
|
|
384
|
+
const idAlive = `${deviceDesc}.Color`;
|
|
383
385
|
adapter.getForeignState(idAlive, (err, state) => {
|
|
384
|
-
if (!state) {
|
|
385
|
-
|
|
386
|
+
if (!state || typeof state.val !== 'string') {
|
|
387
|
+
adapter.log.info(`invalid state Color for ${idAlive}, correcting value to #000000`);
|
|
386
388
|
adapter.setState(idAlive, '#000000', false);
|
|
387
389
|
return;
|
|
388
390
|
}
|
|
@@ -396,18 +398,18 @@ function MQTTServer(adapter) {
|
|
|
396
398
|
|
|
397
399
|
if (rgbpow && exorWhiteLeds) {
|
|
398
400
|
//adapter.log.info('reset white');
|
|
399
|
-
out = rgb
|
|
400
|
-
let idAlive = deviceDesc
|
|
401
|
+
out = `${rgb}0000`;
|
|
402
|
+
let idAlive = `${deviceDesc}.WW_POWER`;
|
|
401
403
|
adapter.setState(idAlive, false, false);
|
|
402
|
-
idAlive = deviceDesc
|
|
404
|
+
idAlive = `${deviceDesc}.WW`;
|
|
403
405
|
adapter.setState(idAlive, 0, false);
|
|
404
|
-
idAlive = deviceDesc
|
|
406
|
+
idAlive = `${deviceDesc}.CW_POWER`;
|
|
405
407
|
adapter.setState(idAlive, false, false);
|
|
406
|
-
idAlive = deviceDesc
|
|
408
|
+
idAlive = `${deviceDesc}.CW`;
|
|
407
409
|
adapter.setState(idAlive, 0, false);
|
|
408
410
|
}
|
|
409
411
|
setColor(channelId, out);
|
|
410
|
-
adapter.setState(idAlive,
|
|
412
|
+
adapter.setState(idAlive, `#${out}`, false);
|
|
411
413
|
if (rgbpow) {
|
|
412
414
|
setPower(channelId, true)
|
|
413
415
|
}
|
|
@@ -420,7 +422,7 @@ function MQTTServer(adapter) {
|
|
|
420
422
|
let hue = state.val;
|
|
421
423
|
if (hue > 359) hue = 359;
|
|
422
424
|
// recalc color by hue
|
|
423
|
-
const idAlive = deviceDesc
|
|
425
|
+
const idAlive = `${deviceDesc}.Dimmer`;
|
|
424
426
|
adapter.getForeignState(idAlive, (err, state) => {
|
|
425
427
|
if (!state) {
|
|
426
428
|
const dim = 100;
|
|
@@ -428,7 +430,7 @@ function MQTTServer(adapter) {
|
|
|
428
430
|
//adapter.log.warn('ill state Dimmer');
|
|
429
431
|
} else {
|
|
430
432
|
const dim = state.val;
|
|
431
|
-
let idAlive = deviceDesc
|
|
433
|
+
let idAlive = `${deviceDesc}.Saturation`;
|
|
432
434
|
adapter.getForeignState(idAlive, (err, state) => {
|
|
433
435
|
if (!state) {
|
|
434
436
|
const sat = 100;
|
|
@@ -437,8 +439,8 @@ function MQTTServer(adapter) {
|
|
|
437
439
|
const sat = state.val;
|
|
438
440
|
const rgb = hsvToRgb(hue, sat, dim);
|
|
439
441
|
const hexVal = componentToHex(rgb[0]) + componentToHex(rgb[1]) + componentToHex(rgb[2]);
|
|
440
|
-
let idAlive = deviceDesc
|
|
441
|
-
adapter.setState(idAlive,
|
|
442
|
+
let idAlive = `${deviceDesc}.Color`;
|
|
443
|
+
adapter.setState(idAlive, `#${hexVal}`, false);
|
|
442
444
|
}
|
|
443
445
|
});
|
|
444
446
|
}
|
|
@@ -448,7 +450,7 @@ function MQTTServer(adapter) {
|
|
|
448
450
|
let sat = state.val;
|
|
449
451
|
if (sat > 100) sat = 100;
|
|
450
452
|
// recalc color by saturation
|
|
451
|
-
const idAlive = deviceDesc
|
|
453
|
+
const idAlive = `${deviceDesc}.Dimmer`;
|
|
452
454
|
adapter.getForeignState(idAlive, (err, state) => {
|
|
453
455
|
if (!state) {
|
|
454
456
|
const dim = 100;
|
|
@@ -456,7 +458,7 @@ function MQTTServer(adapter) {
|
|
|
456
458
|
//adapter.log.warn('ill state Dimmer');
|
|
457
459
|
} else {
|
|
458
460
|
const dim = state.val;
|
|
459
|
-
const idAlive = deviceDesc
|
|
461
|
+
const idAlive = `${deviceDesc}.Hue`;
|
|
460
462
|
adapter.getForeignState(idAlive, (err, state) => {
|
|
461
463
|
if (!state) {
|
|
462
464
|
const hue = 100;
|
|
@@ -465,15 +467,15 @@ function MQTTServer(adapter) {
|
|
|
465
467
|
const hue = state.val;
|
|
466
468
|
const rgb = hsvToRgb(hue, sat, dim);
|
|
467
469
|
const hexVal = componentToHex(rgb[0]) + componentToHex(rgb[1]) + componentToHex(rgb[2]);
|
|
468
|
-
const idAlive = deviceDesc
|
|
469
|
-
adapter.setState(idAlive,
|
|
470
|
+
const idAlive = `${deviceDesc}.Color`;
|
|
471
|
+
adapter.setState(idAlive, `#${hexVal}`, false);
|
|
470
472
|
}
|
|
471
473
|
});
|
|
472
474
|
}
|
|
473
475
|
});
|
|
474
476
|
} else {
|
|
475
477
|
// get color attributes to check other ledstripe vars
|
|
476
|
-
const idAlive = deviceDesc
|
|
478
|
+
const idAlive = `${deviceDesc}.Color`;
|
|
477
479
|
adapter.getForeignObject(idAlive, (err, obj) => {
|
|
478
480
|
if (!obj) {
|
|
479
481
|
// no color object
|
|
@@ -491,7 +493,7 @@ function MQTTServer(adapter) {
|
|
|
491
493
|
if (stateId.match(/WW_POWER\d?/)) {
|
|
492
494
|
// set ww component
|
|
493
495
|
const wwpow = state.val === 'true' || state.val === true || state.val === 1 || state.val === '1';
|
|
494
|
-
const idAlive = deviceDesc
|
|
496
|
+
const idAlive = `${deviceDesc}.Color`;
|
|
495
497
|
adapter.getForeignState(idAlive, (err, state) => {
|
|
496
498
|
if (!state) {
|
|
497
499
|
adapter.log.warn('ill state Color');
|
|
@@ -506,17 +508,17 @@ function MQTTServer(adapter) {
|
|
|
506
508
|
let out = color.substring(0, wwindex) + ww;
|
|
507
509
|
if (wwpow && exorWhiteLeds) {
|
|
508
510
|
//adapter.log.info('reset white');
|
|
509
|
-
out =
|
|
510
|
-
let idAlive = deviceDesc
|
|
511
|
+
out = `000000${ww}`;
|
|
512
|
+
let idAlive = `${deviceDesc}.RGB_POWER`;
|
|
511
513
|
adapter.setState(idAlive,false, false);
|
|
512
514
|
}
|
|
513
515
|
|
|
514
|
-
let idAlive = deviceDesc
|
|
515
|
-
adapter.setState(idAlive
|
|
516
|
+
let idAlive = `${deviceDesc}.Color`;
|
|
517
|
+
adapter.setState(idAlive,`#${out}`, false);
|
|
516
518
|
setColor(channelId, out);
|
|
517
519
|
|
|
518
520
|
// set ww channel
|
|
519
|
-
idAlive = deviceDesc
|
|
521
|
+
idAlive = `${deviceDesc}.WW`;
|
|
520
522
|
adapter.setState(idAlive, 100 * parseInt(out.substring(6, 8), 16) / 255, true);
|
|
521
523
|
|
|
522
524
|
// in case POWER is off, switch it on
|
|
@@ -526,7 +528,7 @@ function MQTTServer(adapter) {
|
|
|
526
528
|
if (stateId.match(/CW_POWER\d?/)) {
|
|
527
529
|
// set ww component
|
|
528
530
|
const cwpow = state.val === 'true' || state.val === true || state.val === 1 || state.val === '1';
|
|
529
|
-
const idAlive = deviceDesc
|
|
531
|
+
const idAlive = `${deviceDesc}.Color`;
|
|
530
532
|
adapter.getForeignState(idAlive, (err, state) => {
|
|
531
533
|
if (!state) {
|
|
532
534
|
adapter.log.warn('ill state Color');
|
|
@@ -541,22 +543,22 @@ function MQTTServer(adapter) {
|
|
|
541
543
|
let out = color.substring(0, 6) + cw + color.substring(8, 10);
|
|
542
544
|
if (cwpow && exorWhiteLeds) {
|
|
543
545
|
//adapter.log.info('reset white');
|
|
544
|
-
out =
|
|
545
|
-
let idAlive = deviceDesc
|
|
546
|
+
out = `000000${cw}${color.substring(8, 10)}`;
|
|
547
|
+
let idAlive = `${deviceDesc}.RGB_POWER`;
|
|
546
548
|
adapter.setState(idAlive, false, false);
|
|
547
549
|
}
|
|
548
550
|
|
|
549
|
-
let idAlive = deviceDesc
|
|
550
|
-
adapter.setState(idAlive,
|
|
551
|
+
let idAlive = `${deviceDesc}.Color`;
|
|
552
|
+
adapter.setState(idAlive, `#${out}`, false);
|
|
551
553
|
setColor(channelId, out);
|
|
552
554
|
|
|
553
555
|
// set cw channel
|
|
554
|
-
idAlive = deviceDesc
|
|
556
|
+
idAlive = `${deviceDesc}.CW`;
|
|
555
557
|
adapter.setState(idAlive, 100 * parseInt(out.substring(6, 8), 16) / 255, true);
|
|
556
558
|
|
|
557
559
|
// in case POWER is off, switch it on
|
|
558
560
|
if (cwpow) {
|
|
559
|
-
let idAlive = deviceDesc
|
|
561
|
+
let idAlive = `${deviceDesc}.POWER`;
|
|
560
562
|
adapter.setState(idAlive, true, false);
|
|
561
563
|
}
|
|
562
564
|
});
|
|
@@ -564,7 +566,7 @@ function MQTTServer(adapter) {
|
|
|
564
566
|
if (stateId.match(/WW\d?/)) {
|
|
565
567
|
// set ww component
|
|
566
568
|
const ww = toPaddedHexString(Math.floor(255 * state.val / 100), 2);
|
|
567
|
-
const idAlive = deviceDesc
|
|
569
|
+
const idAlive = `${deviceDesc}.Color`;
|
|
568
570
|
adapter.getForeignState(idAlive, (err, state) => {
|
|
569
571
|
if (!state) {
|
|
570
572
|
adapter.setState(idAlive, '#000000', false);
|
|
@@ -579,7 +581,7 @@ function MQTTServer(adapter) {
|
|
|
579
581
|
if (stateId.match(/CW\d?/)) {
|
|
580
582
|
// set ww component
|
|
581
583
|
const cw = toPaddedHexString(Math.floor(255 * state.val / 100), 2);
|
|
582
|
-
const idAlive = deviceDesc
|
|
584
|
+
const idAlive = `${deviceDesc}.Color`;
|
|
583
585
|
adapter.getForeignState(idAlive, (err, state) => {
|
|
584
586
|
if (!state) {
|
|
585
587
|
adapter.setState(idAlive, '#000000', false);
|
|
@@ -671,7 +673,7 @@ function MQTTServer(adapter) {
|
|
|
671
673
|
return;
|
|
672
674
|
}
|
|
673
675
|
let task = tasks[0];
|
|
674
|
-
adapter.log.debug(
|
|
676
|
+
adapter.log.debug(`process task: ${JSON.stringify(task)}`);
|
|
675
677
|
if (task.type === 'addObject') {
|
|
676
678
|
if (!cacheAddedObjects[task.id]) {
|
|
677
679
|
cacheAddedObjects[task.id] = true;
|
|
@@ -679,9 +681,9 @@ function MQTTServer(adapter) {
|
|
|
679
681
|
if (!obj || !obj.common) {
|
|
680
682
|
adapter.setForeignObject(task.id, task.data, (err) => {
|
|
681
683
|
if (err) {
|
|
682
|
-
adapter.log.warn(
|
|
684
|
+
adapter.log.warn(`New Object creation error: ${err.message}`)
|
|
683
685
|
} else {
|
|
684
|
-
adapter.log.info(
|
|
686
|
+
adapter.log.info(`new object created: ${task.id}`);
|
|
685
687
|
}
|
|
686
688
|
if (task.cb) {
|
|
687
689
|
task.cb(task.id, task.cbArg, () => {
|
|
@@ -696,9 +698,9 @@ function MQTTServer(adapter) {
|
|
|
696
698
|
} else if (obj.common.type !== task.data.common.type) {
|
|
697
699
|
adapter.extendObject(task.id, {common: {type: task.data.common.type}}, err => {
|
|
698
700
|
if (err) {
|
|
699
|
-
adapter.log.warn(
|
|
701
|
+
adapter.log.warn(`Object update error: ${err.message}`)
|
|
700
702
|
} else {
|
|
701
|
-
adapter.log.info(
|
|
703
|
+
adapter.log.info(`Object updated: ${task.id}`);
|
|
702
704
|
}
|
|
703
705
|
if (task.cb) {
|
|
704
706
|
task.cb(task.id, task.cbArg, () => {
|
|
@@ -758,7 +760,7 @@ function MQTTServer(adapter) {
|
|
|
758
760
|
}
|
|
759
761
|
});
|
|
760
762
|
} else {
|
|
761
|
-
adapter.log.error(
|
|
763
|
+
adapter.log.error(`Unknown task name: ${JSON.stringify(task)}`);
|
|
762
764
|
if (task.cb) {
|
|
763
765
|
task.cb(task.id, task.cbArg, () => {
|
|
764
766
|
tasks.shift();
|
|
@@ -776,7 +778,7 @@ function MQTTServer(adapter) {
|
|
|
776
778
|
// mqtt.0.stat.sonoff.POWER
|
|
777
779
|
let isStart = !tasks.length;
|
|
778
780
|
|
|
779
|
-
let id = adapter.namespace
|
|
781
|
+
let id = `${adapter.namespace}.${client.iobId}`;
|
|
780
782
|
let obj = {
|
|
781
783
|
_id: id,
|
|
782
784
|
common: {
|
|
@@ -791,13 +793,13 @@ function MQTTServer(adapter) {
|
|
|
791
793
|
tasks.push({type: 'addObject', id: obj._id, data: obj});
|
|
792
794
|
|
|
793
795
|
obj = {
|
|
794
|
-
_id: id
|
|
796
|
+
_id: `${id}.alive`,
|
|
795
797
|
common: {
|
|
796
798
|
type: 'boolean',
|
|
797
799
|
role: 'indicator.reachable',
|
|
798
800
|
read: true,
|
|
799
801
|
write: false,
|
|
800
|
-
name: client.id
|
|
802
|
+
name: `${client.id} alive`
|
|
801
803
|
},
|
|
802
804
|
type: 'state'
|
|
803
805
|
};
|
|
@@ -813,7 +815,7 @@ function MQTTServer(adapter) {
|
|
|
813
815
|
let text = '';
|
|
814
816
|
if (clients) {
|
|
815
817
|
for (let id in clients) {
|
|
816
|
-
text +=
|
|
818
|
+
text += `${text ? ',' : ''}${id}`;
|
|
817
819
|
}
|
|
818
820
|
}
|
|
819
821
|
|
|
@@ -821,7 +823,7 @@ function MQTTServer(adapter) {
|
|
|
821
823
|
}
|
|
822
824
|
|
|
823
825
|
function updateAlive(client, alive) {
|
|
824
|
-
let idAlive = adapter.namespace
|
|
826
|
+
let idAlive = `${adapter.namespace}.${client.iobId}.alive`;
|
|
825
827
|
|
|
826
828
|
adapter.getForeignState(idAlive, (err, state) => {
|
|
827
829
|
if (!state || state.val !== alive) {
|
|
@@ -870,7 +872,7 @@ function MQTTServer(adapter) {
|
|
|
870
872
|
|
|
871
873
|
function addObject(attr, client, prefix, path) {
|
|
872
874
|
let replaceAttr = types[attr].replace || attr;
|
|
873
|
-
let id = `${adapter.namespace}.${client.iobId}.${prefix ? prefix
|
|
875
|
+
let id = `${adapter.namespace}.${client.iobId}.${prefix ? `${prefix}.` : ''}${path.length ? `${path.join('_')}_` : ''}${replaceAttr.replace(FORBIDDEN_CHARS, '_')}`;
|
|
874
876
|
let obj = {
|
|
875
877
|
type: 'addObject',
|
|
876
878
|
id: id,
|
|
@@ -881,7 +883,7 @@ function MQTTServer(adapter) {
|
|
|
881
883
|
type: 'state'
|
|
882
884
|
}
|
|
883
885
|
};
|
|
884
|
-
obj.data.common.name = `${client.id} ${prefix ? prefix
|
|
886
|
+
obj.data.common.name = `${client.id} ${prefix ? `${prefix} ` : ''}${path.length ? `${path.join(' ')} ` : ''} ${replaceAttr}`;
|
|
885
887
|
return obj;
|
|
886
888
|
}
|
|
887
889
|
|
|
@@ -890,7 +892,7 @@ function MQTTServer(adapter) {
|
|
|
890
892
|
return;
|
|
891
893
|
}
|
|
892
894
|
|
|
893
|
-
const ledModeReadColorsID = adapter.namespace
|
|
895
|
+
const ledModeReadColorsID = `${adapter.namespace}.${client.iobId}.modeReadColors`;
|
|
894
896
|
|
|
895
897
|
if (cachedReadColors[ledModeReadColorsID] === undefined) {
|
|
896
898
|
return adapter.getForeignState(ledModeReadColorsID, (err, state) => {
|
|
@@ -920,7 +922,7 @@ function MQTTServer(adapter) {
|
|
|
920
922
|
}
|
|
921
923
|
// define new object
|
|
922
924
|
let replaceAttr = attr.replace(FORBIDDEN_CHARS, '_') + i.toString();
|
|
923
|
-
let id = `${adapter.namespace}.${client.iobId}.${prefix ? prefix
|
|
925
|
+
let id = `${adapter.namespace}.${client.iobId}.${prefix ? `${prefix}.` : ''}${path.length ? `${path.join('_')}_` : ''}${replaceAttr}`;
|
|
924
926
|
let obj = {
|
|
925
927
|
type: 'addObject',
|
|
926
928
|
id: id,
|
|
@@ -931,7 +933,7 @@ function MQTTServer(adapter) {
|
|
|
931
933
|
type: 'state'
|
|
932
934
|
}
|
|
933
935
|
};
|
|
934
|
-
obj.data.common.name = `${client.id} ${prefix ? prefix
|
|
936
|
+
obj.data.common.name = `${client.id} ${prefix ? `${prefix} ` : ''}${path.length ? `${path.join(' ')} ` : ''} ${replaceAttr}`;
|
|
935
937
|
obj.data.common.type = typeof val;
|
|
936
938
|
if (!['number', 'string', 'boolean'].includes(obj.data.common.type)) {
|
|
937
939
|
obj.data.common.type = 'string';
|
|
@@ -948,7 +950,7 @@ function MQTTServer(adapter) {
|
|
|
948
950
|
let nPath = Object.assign([], path);
|
|
949
951
|
nPath.push(attr.replace(FORBIDDEN_CHARS, '_'));
|
|
950
952
|
if (adapter.config.OBJ_TREE) {
|
|
951
|
-
checkData(client, topic, prefix
|
|
953
|
+
checkData(client, topic, `${prefix}.${nPath}`, data[attr], unit);
|
|
952
954
|
} else {
|
|
953
955
|
checkData(client, topic, prefix, data[attr], unit, nPath);
|
|
954
956
|
}
|
|
@@ -963,7 +965,7 @@ function MQTTServer(adapter) {
|
|
|
963
965
|
|
|
964
966
|
if (obj.data.common.storeMap) {
|
|
965
967
|
delete obj.data.common.storeMap;
|
|
966
|
-
client._map[replaceAttr] = topic.replace(/$\w+\//, 'cmnd/').replace(/\/\w+$/,
|
|
968
|
+
client._map[replaceAttr] = topic.replace(/$\w+\//, 'cmnd/').replace(/\/\w+$/, `/${replaceAttr}`);
|
|
967
969
|
}
|
|
968
970
|
|
|
969
971
|
// adaptions for magichome tasmota
|
|
@@ -1053,7 +1055,7 @@ function MQTTServer(adapter) {
|
|
|
1053
1055
|
if (attr === 'Color') {
|
|
1054
1056
|
// add # char
|
|
1055
1057
|
if (allowReadColors) {
|
|
1056
|
-
val =
|
|
1058
|
+
val = `#${data[attr]}`;
|
|
1057
1059
|
}
|
|
1058
1060
|
} else {
|
|
1059
1061
|
val = data[attr];
|
|
@@ -1072,6 +1074,7 @@ function MQTTServer(adapter) {
|
|
|
1072
1074
|
// auto generate objects
|
|
1073
1075
|
if ((parts[0] === 'tele' && (
|
|
1074
1076
|
(adapter.config.TELE_SENSOR && parts[2] === 'SENSOR') ||
|
|
1077
|
+
(adapter.config.STAT_RESULT && parts[2] === 'RESULT') ||
|
|
1075
1078
|
(adapter.config.TELE_STATE && parts[2] === 'STATE'))) ||
|
|
1076
1079
|
(parts[0] === 'stat' &&
|
|
1077
1080
|
(adapter.config.STAT_RESULT && parts[2] === 'RESULT'))
|
|
@@ -1091,7 +1094,7 @@ function MQTTServer(adapter) {
|
|
|
1091
1094
|
}
|
|
1092
1095
|
|
|
1093
1096
|
let replaceAttr = attr ;
|
|
1094
|
-
let id = `${adapter.namespace}.${client.iobId}.${prefix ? prefix
|
|
1097
|
+
let id = `${adapter.namespace}.${client.iobId}.${prefix ? `${prefix}.` : ''}${path.length ? `${path.join('_')}_` : ''}${replaceAttr}`;
|
|
1095
1098
|
let obj = {
|
|
1096
1099
|
type: 'addObject',
|
|
1097
1100
|
id: id,
|
|
@@ -1102,7 +1105,7 @@ function MQTTServer(adapter) {
|
|
|
1102
1105
|
type: 'state'
|
|
1103
1106
|
}
|
|
1104
1107
|
};
|
|
1105
|
-
obj.data.common.name = `${client.id} ${prefix ? prefix
|
|
1108
|
+
obj.data.common.name = `${client.id} ${prefix ? `${prefix} ` : ''}${path.length ? `${path.join(' ')} ` : ''} ${replaceAttr}`;
|
|
1106
1109
|
updateState(obj, val);
|
|
1107
1110
|
}
|
|
1108
1111
|
}
|
|
@@ -1111,7 +1114,7 @@ function MQTTServer(adapter) {
|
|
|
1111
1114
|
|
|
1112
1115
|
function receivedTopic(packet, client) {
|
|
1113
1116
|
if (!packet) {
|
|
1114
|
-
return adapter.log.warn(
|
|
1117
|
+
return adapter.log.warn(`Empty packet received: ${JSON.stringify(packet)}`);
|
|
1115
1118
|
}
|
|
1116
1119
|
|
|
1117
1120
|
client.states = client.states || {};
|
|
@@ -1206,7 +1209,7 @@ function MQTTServer(adapter) {
|
|
|
1206
1209
|
checkData(client, packet.topic, NO_PREFIX, JSON.parse(val));
|
|
1207
1210
|
}
|
|
1208
1211
|
} catch (e) {
|
|
1209
|
-
adapter.log.warn(
|
|
1212
|
+
adapter.log.warn(`Cannot parse data "${stateId}": _${val}_ - ${e}`);
|
|
1210
1213
|
}
|
|
1211
1214
|
}
|
|
1212
1215
|
return;
|
|
@@ -1216,7 +1219,7 @@ function MQTTServer(adapter) {
|
|
|
1216
1219
|
// tele/sonoff/SENSOR = {"Time":"2017-10-05T17:43:19", "DS18x20":{"DS1":{"Type":"DS18B20", "Address":"28FF9A9876815022A", "Temperature":12.2}}, "TempUnit":"C"}
|
|
1217
1220
|
// tele/sonoff5/SENSOR = {"Time":"2017-10-03T14:02:25", "AM2301-14":{"Temperature":21.6, "Humidity":54.7}, "TempUnit":"C"}
|
|
1218
1221
|
// tele/sonoff/SENSOR = {"Time":"2018-02-23T17:36:59", "Analog0":298}
|
|
1219
|
-
if (parts[0] === 'tele' && stateId.match(/^(STATE|SENSOR|WAKEUP)\d?$/)) {
|
|
1222
|
+
if (parts[0] === 'tele' && stateId.match(/^(RESULT|STATE|SENSOR|WAKEUP)\d?$/)) {
|
|
1220
1223
|
try {
|
|
1221
1224
|
if (adapter.config.OBJ_TREE) {
|
|
1222
1225
|
if (stateId.match(/^(STATE)\d?$/)) {
|
|
@@ -1225,13 +1228,15 @@ function MQTTServer(adapter) {
|
|
|
1225
1228
|
checkData(client, packet.topic, 'SENSOR', JSON.parse(val));
|
|
1226
1229
|
} else if (stateId.match(/^(WAKEUP)\d?$/)) {
|
|
1227
1230
|
checkData(client, packet.topic, 'WAKEUP', JSON.parse(val));
|
|
1231
|
+
} else if (stateId.match(/^(RESULT)\d?$/)) {
|
|
1232
|
+
checkData(client, packet.topic, 'WAKEUP', JSON.parse(val));
|
|
1228
1233
|
}
|
|
1229
1234
|
} else {
|
|
1230
1235
|
checkData(client, packet.topic, NO_PREFIX, JSON.parse(val));
|
|
1231
1236
|
//adapter.log.warn('log sensor parse"' + stateId + '": _' + val);
|
|
1232
1237
|
}
|
|
1233
1238
|
} catch (e) {
|
|
1234
|
-
adapter.log.warn(
|
|
1239
|
+
adapter.log.warn(`Cannot parse data "${stateId}": _${val}_ - ${e}`);
|
|
1235
1240
|
}
|
|
1236
1241
|
} else if (parts[0] === 'tele' && stateId.match(/^INFO\d?$/)) {
|
|
1237
1242
|
// tele/SonoffPOW/INFO1 = {"Module":"Sonoff Pow", "Version":"5.8.0", "FallbackTopic":"SonoffPOW", "GroupTopic":"sonoffs"}
|
|
@@ -1240,14 +1245,14 @@ function MQTTServer(adapter) {
|
|
|
1240
1245
|
try {
|
|
1241
1246
|
checkData(client, packet.topic, 'INFO', JSON.parse(val));
|
|
1242
1247
|
} catch (e) {
|
|
1243
|
-
adapter.log.warn(
|
|
1248
|
+
adapter.log.warn(`Cannot parse data"${stateId}": _${val}_ - ${e}`);
|
|
1244
1249
|
}
|
|
1245
1250
|
} else if (parts[0] === 'tele' && stateId.match(/^(ENERGY)\d?$/)) {
|
|
1246
1251
|
// tele/sonoff_4ch/ENERGY = {"Time":"2017-10-02T19:24:32", "Total":1.753, "Yesterday":0.308, "Today":0.205, "Period":0, "Power":3, "Factor":0.12, "Voltage":221, "Current":0.097}
|
|
1247
1252
|
try {
|
|
1248
1253
|
checkData(client, packet.topic, 'ENERGY', JSON.parse(val));
|
|
1249
1254
|
} catch (e) {
|
|
1250
|
-
adapter.log.warn(
|
|
1255
|
+
adapter.log.warn(`Cannot parse data"${stateId}": _${val}_ - ${e}`);
|
|
1251
1256
|
}
|
|
1252
1257
|
} else if (types[stateId]) {
|
|
1253
1258
|
// /ESP_BOX/BM280/Pressure = 1010.09
|
|
@@ -1259,7 +1264,7 @@ function MQTTServer(adapter) {
|
|
|
1259
1264
|
// stat/sonoff/POWER
|
|
1260
1265
|
|
|
1261
1266
|
if (types[stateId]) {
|
|
1262
|
-
let id = adapter.namespace
|
|
1267
|
+
let id = `${adapter.namespace}.${client.iobId}.${stateId.replace(/[-.+\s]+/g, '_')}`;
|
|
1263
1268
|
let obj = {
|
|
1264
1269
|
type: 'addObject',
|
|
1265
1270
|
id: id,
|
|
@@ -1270,7 +1275,7 @@ function MQTTServer(adapter) {
|
|
|
1270
1275
|
type: 'state'
|
|
1271
1276
|
}
|
|
1272
1277
|
};
|
|
1273
|
-
obj.data.common.name = client.id
|
|
1278
|
+
obj.data.common.name = `${client.id} ${stateId}`;
|
|
1274
1279
|
|
|
1275
1280
|
// push only new objects
|
|
1276
1281
|
updateState(obj, () => {
|
|
@@ -1306,7 +1311,7 @@ function MQTTServer(adapter) {
|
|
|
1306
1311
|
}
|
|
1307
1312
|
});
|
|
1308
1313
|
} else {
|
|
1309
|
-
adapter.log.debug(
|
|
1314
|
+
adapter.log.debug(`Cannot process: ${packet.topic}`);
|
|
1310
1315
|
}
|
|
1311
1316
|
}
|
|
1312
1317
|
}
|
|
@@ -1403,7 +1408,7 @@ function MQTTServer(adapter) {
|
|
|
1403
1408
|
server.on('connection', stream => {
|
|
1404
1409
|
let client = mqtt(stream);
|
|
1405
1410
|
// Store unique connection identifier
|
|
1406
|
-
client.__secret = Date.now()
|
|
1411
|
+
client.__secret = `${Date.now()}_${Math.round(Math.random() * 10000)}`;
|
|
1407
1412
|
|
|
1408
1413
|
// client connected
|
|
1409
1414
|
client.on('connect', options => {
|
|
@@ -1558,7 +1563,7 @@ function MQTTServer(adapter) {
|
|
|
1558
1563
|
return false;
|
|
1559
1564
|
}
|
|
1560
1565
|
});
|
|
1561
|
-
if (pos !==
|
|
1566
|
+
if (pos !== null) {
|
|
1562
1567
|
client.pubrel({messageId: packet.messageId});
|
|
1563
1568
|
} else {
|
|
1564
1569
|
adapter.log.warn(`Client [${client.id}] Received pubrec on ${client.id} for unknown messageId ${packet.messageId}`);
|
|
@@ -1593,6 +1598,9 @@ function MQTTServer(adapter) {
|
|
|
1593
1598
|
|
|
1594
1599
|
// response for QoS2
|
|
1595
1600
|
client.on('pubrel', packet => {
|
|
1601
|
+
if (!client._messages) {
|
|
1602
|
+
return;
|
|
1603
|
+
}
|
|
1596
1604
|
if (clients[client.id] && client.__secret !== clients[client.id].__secret) {
|
|
1597
1605
|
!adapter.config.ignorePings && adapter.log.warn(`Old client ${client.id} with secret ${client.__secret} sends pubrel. Ignore! Actual secret is ${clients[client.id].__secret}`);
|
|
1598
1606
|
return;
|
|
@@ -1611,7 +1619,7 @@ function MQTTServer(adapter) {
|
|
|
1611
1619
|
}
|
|
1612
1620
|
});
|
|
1613
1621
|
|
|
1614
|
-
if (pos !==
|
|
1622
|
+
if (pos !== null) {
|
|
1615
1623
|
client.pubcomp({messageId: packet.messageId});
|
|
1616
1624
|
|
|
1617
1625
|
receivedTopic(client._messages[pos], client);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.sonoff",
|
|
3
3
|
"description": "The adapter allows to send and receive MQTT messages from ioBroker and to be a broker.",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.5.1",
|
|
5
5
|
"author": "bluefox <dogafox@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/ioBroker/ioBroker.sonoff",
|
|
7
7
|
"repository": {
|
|
@@ -17,17 +17,17 @@
|
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"mqtt-connection": "^4.1.0",
|
|
20
|
-
"@iobroker/adapter-core": "^2.
|
|
20
|
+
"@iobroker/adapter-core": "^2.6.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@alcalzone/release-script": "^3.
|
|
24
|
-
"@alcalzone/release-script-plugin-iobroker": "^3.
|
|
25
|
-
"@alcalzone/release-script-plugin-license": "^3.
|
|
26
|
-
"axios": "^0.
|
|
27
|
-
"mqtt": "^4.
|
|
23
|
+
"@alcalzone/release-script": "^3.5.6",
|
|
24
|
+
"@alcalzone/release-script-plugin-iobroker": "^3.5.7",
|
|
25
|
+
"@alcalzone/release-script-plugin-license": "^3.5.3",
|
|
26
|
+
"axios": "^0.26.1",
|
|
27
|
+
"mqtt": "^4.3.7",
|
|
28
28
|
"gulp": "^4.0.2",
|
|
29
|
-
"mocha": "^9.
|
|
30
|
-
"chai": "^4.3.
|
|
29
|
+
"mocha": "^9.2.2",
|
|
30
|
+
"chai": "^4.3.6"
|
|
31
31
|
},
|
|
32
32
|
"bugs": {
|
|
33
33
|
"url": "https://github.com/ioBroker/ioBroker.sonoff/issues"
|