iobroker.openknx 0.4.4 → 0.5.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 +29 -12
- package/admin/index_m.html +7 -1
- package/io-package.json +29 -15
- package/lib/knx/src/Connection.js +27 -2
- package/lib/knx/src/FSM.js +7 -0
- package/lib/knx/src/dptlib/dpt1.js +50 -8
- package/lib/knx/src/dptlib/dpt12.js +2 -1
- package/lib/knx/src/dptlib/dpt17.js +2 -1
- package/lib/knx/src/dptlib/dpt2.js +12 -0
- package/lib/knx/src/dptlib/dpt21.js +9 -9
- package/lib/knx/src/dptlib/dpt232.js +1 -1
- package/lib/knx/src/dptlib/dpt3.js +2 -0
- package/lib/knx/src/dptlib/dpt4.js +1 -0
- package/lib/knx/src/dptlib/dpt5.js +4 -2
- package/lib/knx/src/dptlib/dpt7.js +2 -1
- package/lib/projectImport.js +13 -4
- package/lib/tools.js +6 -1
- package/main.js +43 -36
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -50,14 +50,22 @@ This settings protects the KNX bus from data flooding by limiting data frames to
|
|
|
50
50
|
Not sent frames are delay until the delay time since last send on bus is elapsed. If more send requests are waiting, send order is random.
|
|
51
51
|
If you experience disconnects from your KNX IP Gateway in the log then increase this number.
|
|
52
52
|
|
|
53
|
+
### use common.type boolean for 1 bit enum instead of number
|
|
54
|
+
|
|
55
|
+
Use in IOB Object common.type boolean for 1 bit enum instead of number.
|
|
56
|
+
|
|
53
57
|
### readout values of autoread iob objects on startup
|
|
54
58
|
|
|
55
59
|
All IOB objects that are configured with the autoread flag are requested on the bus to be synchronized with IOB.
|
|
56
60
|
|
|
57
|
-
###
|
|
61
|
+
### import only GAs that do not exist in IOB objects
|
|
58
62
|
|
|
59
63
|
If checked, the import will skip overwriting existing communication objects.
|
|
60
64
|
|
|
65
|
+
### remove existing IOB objects thtat are not in import file
|
|
66
|
+
|
|
67
|
+
To clean up object tree
|
|
68
|
+
|
|
61
69
|
### Import XML from ETS
|
|
62
70
|
|
|
63
71
|

|
|
@@ -162,12 +170,14 @@ The whole name including path is used to check for similarity.
|
|
|
162
170
|
|
|
163
171
|
# howto use the adapter & basic concept
|
|
164
172
|
|
|
165
|
-
### ACK flags
|
|
173
|
+
### ACK flags with tunneling connections
|
|
166
174
|
|
|
167
|
-
Applications shall
|
|
175
|
+
Applications shall not set the ack flag, application is notified from this adapter by the ack flag if data is updated.
|
|
168
176
|
KNX Stack sets the ack flag of the corresponding IoBroker object on receiption of a group address if another knx host writes to the bus.
|
|
169
|
-
|
|
170
|
-
|
|
177
|
+
|
|
178
|
+
|GA is | connected to device with a R flag | connected to devices with no R flag | unconnected
|
|
179
|
+
|Application issues GroupValue_Write | ack | ack | no ack
|
|
180
|
+
|Application issues GroupValue_Read | ack | no ack | no ack
|
|
171
181
|
|
|
172
182
|
### Node Red complex datatype example
|
|
173
183
|
|
|
@@ -211,7 +221,7 @@ Autoread is set to false where it is clear from the DPT that this is a trigger s
|
|
|
211
221
|
"bitlength": 1, // size ob knx data, derived from dpt
|
|
212
222
|
"dpt": "DPT1.001", // DPT
|
|
213
223
|
"encoding": {
|
|
214
|
-
//
|
|
224
|
+
// values of the interface if it is an enum DPT type
|
|
215
225
|
"0": "Off",
|
|
216
226
|
"1": "On"
|
|
217
227
|
},
|
|
@@ -267,7 +277,7 @@ GroupValue_Read comment does not work for javascript adapter. Use qualityAsNumbe
|
|
|
267
277
|
|
|
268
278
|
| KNX DPT | javascript datatype | special values | value range | remark |
|
|
269
279
|
| --------- | ---------------------- | ---------------------------------------------------------------------------------------------------- | ----------------------------------------- | ----------------------------------------------------- |
|
|
270
|
-
| DPT-1 |
|
|
280
|
+
| DPT-1 | number enum | | false, true | |
|
|
271
281
|
| DPT-2 | object | {"priority":1 bit,"data":1 bit} | - | |
|
|
272
282
|
| DPT-3 | object | {"decr_incr":1 bit,"data":2 bit} | - | |
|
|
273
283
|
| DPT-18 | object | {"save_recall":0,"scenenumber":0} | - | Datapoint Type DPT_SceneControl removed from autoread |
|
|
@@ -359,16 +369,17 @@ Data is sent to Iobroker Sentry server hosted in Germany. If you have allowed io
|
|
|
359
369
|
- create joint alias objects that react on status inputs
|
|
360
370
|
- supports project of all possible group address styles
|
|
361
371
|
|
|
362
|
-
# Known Problems
|
|
363
|
-
|
|
364
|
-
- none
|
|
365
|
-
|
|
366
372
|
# Limitations
|
|
367
373
|
|
|
368
374
|
- ETS 4 export file format is not supported
|
|
369
375
|
- KNX secure is not supported
|
|
370
376
|
- only IPv4 supported
|
|
371
377
|
|
|
378
|
+
# FAQ
|
|
379
|
+
|
|
380
|
+
- Autoread trigger actors on the bus to react
|
|
381
|
+
Check in ETS if group objects of certain devices that are connected to the suspicious GA have the R/L flag configured. This should not be the case if te device is a consumer of the signal. If the signal has an event character, a groupValueRead would trigger that event. Change configuration in ETS or disable autoread for this object.
|
|
382
|
+
|
|
372
383
|
## Changelog
|
|
373
384
|
|
|
374
385
|
<!--
|
|
@@ -377,7 +388,13 @@ Data is sent to Iobroker Sentry server hosted in Germany. If you have allowed io
|
|
|
377
388
|
* .... -> this is used by script to generate a new entry, copy after a new release
|
|
378
389
|
* npm run release major/minor/patch major.minor.patch
|
|
379
390
|
-->
|
|
380
|
-
### 0.
|
|
391
|
+
### 0.5.0 (2022-12-30)
|
|
392
|
+
|
|
393
|
+
- feature: use common.type boolean for 1 bit enum instead of number
|
|
394
|
+
import enum with one bit as common.type mixed and not strict as number
|
|
395
|
+
- handling of iob ack improved for tunneling connections, see description
|
|
396
|
+
|
|
397
|
+
### 0.4.5 (2022-12-19)
|
|
381
398
|
|
|
382
399
|
- bugfix in knx lib: make dpt2 not an enum datatype
|
|
383
400
|
|
package/admin/index_m.html
CHANGED
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
if (isAlive && !window.isProcessingRequest) {
|
|
67
67
|
$("#onlyAddNewObjects").removeClass("disabled");
|
|
68
68
|
$("#autoreadEnabled").removeClass("disabled");
|
|
69
|
+
$("#useBoolean").removeClass("disabled");
|
|
69
70
|
$("#removeUnusedObjects").removeClass("disabled");
|
|
70
71
|
$("#setAckOnWrite").removeClass("disabled");
|
|
71
72
|
$(".file-field .btn").removeClass("disabled");
|
|
@@ -83,6 +84,7 @@
|
|
|
83
84
|
if (settings.minimumDelay === undefined) settings.minimumDelay = 50;
|
|
84
85
|
if (settings.onlyAddNewObjects === undefined) settings.onlyAddNewObjects = false;
|
|
85
86
|
if (settings.autoreadEnabled === undefined) settings.autoreadEnabled = false;
|
|
87
|
+
if (settings.useBoolean === undefined) settings.useBoolean = false;
|
|
86
88
|
if (settings.removeUnusedObjects === undefined) settings.removeUnusedObjects = false;
|
|
87
89
|
if (settings.localInterface === undefined) settings.localInterface = "";
|
|
88
90
|
if (settings.setAckOnWrite === undefined) settings.setAckOnWrite = false;
|
|
@@ -382,12 +384,16 @@
|
|
|
382
384
|
<div class="row">
|
|
383
385
|
<div class="col s12 input-field">
|
|
384
386
|
<input class="value" id="onlyAddNewObjects" type="checkbox" />
|
|
385
|
-
<label class="translate" for="onlyAddNewObjects">import only GAs that do not exist
|
|
387
|
+
<label class="translate" for="onlyAddNewObjects">import only GAs that do not exist in IOB objects</label>
|
|
386
388
|
</div>
|
|
387
389
|
<div class="col s12 input-field">
|
|
388
390
|
<input class="value" id="removeUnusedObjects" type="checkbox" />
|
|
389
391
|
<label class="translate" for="removeUnusedObjects">remove existing IOB objects that are not in import file</label>
|
|
390
392
|
</div>
|
|
393
|
+
<div class="col s12 input-field">
|
|
394
|
+
<input class="value" id="useBoolean" type="checkbox" />
|
|
395
|
+
<label class="translate" for="useBoolean">use common.type boolean for 1 bit enum instead of number</label>
|
|
396
|
+
</div>
|
|
391
397
|
|
|
392
398
|
<div class="col s12 m12 l6 file-field input-field">
|
|
393
399
|
<div class="btn" id="fileUploadButton"><i class="material-icons right">input</i>
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "openknx",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.0",
|
|
5
5
|
"news": {
|
|
6
|
+
"0.5.0": {
|
|
7
|
+
"en": "- feature: use common.type boolean for 1 bit enum instead of number\n import enum with one bit as common.type mixed and not strict as number\n- handling of iob ack improved for tunneling connections, see description",
|
|
8
|
+
"de": "- feature: verwenden sie gemeinsam. typ boolean für 1 bit enum statt anzahl\nimport enum mit ein bisschen wie üblich. typ gemischt und nicht streng als zahl\n- handhabung von iob ack verbessert für tunnelverbindungen, siehe beschreibung",
|
|
9
|
+
"ru": "- функция: использовать общий. тип boolean для 1 бит enum вместо номера\nимпорт enum с одним битом как общий. тип смешанный и не строгий как номер\n- обработка iob ack улучшена для туннелирования соединения, см. описание",
|
|
10
|
+
"pt": "- recurso: use comum. tipo booleano para 1 bit enum em vez de número\nimportação enum com um pouco como comum. tipo misturado e não estrito como número\n- manipulação de iob ack melhorado para conexões de túnel, ver descrição",
|
|
11
|
+
"nl": "gebruik gewoon. typ boolean voor 1 cent in plaats van nummer\nimporteer met een beetje zoals gewoonlijk. gemengd en niet strikt als nummer\n- behandelen met iob ack verbeterd voor tunnelverbindingen",
|
|
12
|
+
"fr": "- caractéristique: utilisation commune. type booléen pour 1 bit enum au lieu du nombre\nimporter enum avec un peu comme commun. type mélangé et non strict\n- le traitement de l'iob ack amélioré pour les connexions de tunnel, voir la description",
|
|
13
|
+
"it": "- caratteristica: utilizzare comune. tipo boolean per 1 bit enum invece del numero\nimportare enum con un bit come comune. tipo misto e non rigoroso come numero\n- la gestione dell'attacco iob migliorata per i collegamenti di tunneling, vedi descrizione",
|
|
14
|
+
"es": "- función: usar común. tipo booleano por 1 bit enum en lugar de número\nimporta enum con un poco como común. tipo mixto y no estricto como número\n- manejo de iob ack mejorado para conexiones de túnel, ver descripción",
|
|
15
|
+
"pl": "wykorzystywanie: wspólne. bulean na 1 bit enum zamiast numeru\nzawartość z jednym bitem jako powszechna. mieszany i nie ścisły\n- obsługa iob udoskonalona dla połączeń tunelowych, zobacz opis iob",
|
|
16
|
+
"uk": "- функція: використання загального. тип булеан для 1 біт енму замість кількості\nімпортувати енму з одним бітом, як поширений. тип змішаних і не строгий як номер\n- обробка iob ack поліпшена для зв'язків з тунелями, див. опис",
|
|
17
|
+
"zh-cn": "- 特征:共同使用。 第1条的诱惑而不是数量\n进口有一处是普通的。 类型混杂不清\n- 对隧道的处理改良了碘包,见说明"
|
|
18
|
+
},
|
|
19
|
+
"0.4.5": {
|
|
20
|
+
"en": "bugfix in knx lib: make dpt2 not an enum datatype",
|
|
21
|
+
"de": "bugfix in knx lib: dpt2 nicht enum datatype",
|
|
22
|
+
"ru": "bugfix в knx lib: сделать dpt2 не enum datatype",
|
|
23
|
+
"pt": "bugfix em knx lib: fazer dpt2 não um tipo de dados enum",
|
|
24
|
+
"nl": "maak dpt2 geen enum datat",
|
|
25
|
+
"fr": "bugfix in knx lib: make dpt2 not an enum datatype",
|
|
26
|
+
"it": "bugfix in knx lib: make dpt2 not an enum datatype",
|
|
27
|
+
"es": "bugfix en knx lib: make dpt2 not an enum datatype",
|
|
28
|
+
"pl": "uszkodzenia w knx lib: czynić dpt2 nie enum datatype",
|
|
29
|
+
"uk": "виправлення помилок в knx lib: зробити dpt2 нетипові дані",
|
|
30
|
+
"zh-cn": "b knx lib的ugfix:d2不含一种全局数据。"
|
|
31
|
+
},
|
|
6
32
|
"0.4.4": {
|
|
7
33
|
"en": "bugfix in knx lib: make dpt2 not an enum datatype",
|
|
8
34
|
"de": "bugfix in knx lib: dpt2 nicht enum datatype",
|
|
@@ -67,19 +93,6 @@
|
|
|
67
93
|
"pl": "wygląd: wspieranie Free and Two Level Group Address Style, oprócz istniejącego Trzech poziomów, 320\ncechą charakterystyczną mapy knx jest konsekracja obiektu wspólnego. #313\ndebug message",
|
|
68
94
|
"uk": "функція: підтримка безкоштовного та дворівневого групового стилю, крім існуючої трирівневої підтримки #320\nфункція: кодування типу кнкс для об'єкта спільного. стани #313\ndebug повідомлення для відправки розміру черги",
|
|
69
95
|
"zh-cn": "特点:除了现有三级支助第320号行动之外,支持自由和二级组处理Style。\n特征:图千x数据点类型与目标一致。 第313号声明\nd. 发出呼吁规模的信息"
|
|
70
|
-
},
|
|
71
|
-
"0.3.2": {
|
|
72
|
-
"en": "feature: sync knx library\nfeature: sync with create adapter 0.2.3\nfeature: update to newer versions of dependant packages\nfeature: setting autoreadEnabled autoread\nbugfix: allow alias generation with missing gateway configuration\nbugfix in knx lib: keep correct order of send datagrams in case of burst write",
|
|
73
|
-
"de": "feature: sync knx bibliothek\nfeature: sync mit adapter erstellen 0.2.3\nfeature: update auf neuere versionen von abhängigen paketen\nfunktion: autoread einstellen Autoread aktivieren\nbugfix: alias-generation mit fehlender gateway-konfiguration erlauben\nbugfix in knx lib: korrekte reihenfolge des sendens von datengrammen bei burst-schreiben",
|
|
74
|
-
"ru": "функция: синхронизация knx библиотека\nособенность: синхронизация с созданием адаптера 0.2.3\nфункция: обновление до новых версий зависящих пакетов\nфункция: настройка autoread Включенный автопрочитан\nbugfix: позвольте псевдониму генерации с недостающей конфигурацией шлюза\nbugfix в knx lib: держите правильный порядок отправки данных в случае захоронения напишите",
|
|
75
|
-
"pt": "característica: biblioteca de sincronização knx\ncaracterística: sincronização com criar adaptador 0.2.3\nrecurso: atualização para versões mais recentes de pacotes dependentes\ncaracterística: definição de autoread Autoread habilitado\nbugfix: permitir a geração de alias com configuração de gateway ausente\nbugfix em knx lib: manter a ordem correta de enviar datagramas em caso de explosão escrever",
|
|
76
|
-
"nl": "vertaling:\nvertaling:\nvertaling:\nvertaling: Geautoread\nvertaling:\nbewaar de juiste volgorde van het versturen van gegevens in geval van ontploffing",
|
|
77
|
-
"fr": "fonction: bibliothèque sync knx\nfonction: synchronisation avec adaptateur de création 0.2.3\nfonction: mise à jour de nouvelles versions de paquets dépendants\nfonction: réglage automatique Autoread activé\nbugfix: permettre la génération d'alias avec la configuration de passerelle manquante\nbugfix in knx lib: garder l'ordre correct d'envoyer des datagrammes en cas d'éclatement écrire",
|
|
78
|
-
"it": "caratteristica: sync knx library\nfunzione: sincronizzare con creare adattatore 0.2.3\nfunzione: aggiornamento alle versioni più recenti dei pacchetti dipendenti\ncaratteristica: impostazione autoread Abilitato autoread\nbugfix: consentire la generazione di alias con la configurazione di gateway mancante\nbugfix in knx lib: mantenere l'ordine corretto di inviare i datagrams in caso di esplosione di scrittura",
|
|
79
|
-
"es": "función: biblioteca de knx de sincronización\nfunción: sincronización con el adaptador 0,2.3\nfunción: actualización a nuevas versiones de paquetes dependientes\nfunción: ajuste automático Autoread habilitado\nbugfix: permitir la generación de alias con configuración de entrada perdida\nbugfix en knx lib: mantener el orden correcto de enviar datagramas en caso de explosión escribir",
|
|
80
|
-
"pl": "funkcja: sync knx library\nfunkcja: synchronizacja z tworzeniem adaptatora 0.2.3\ndostępne są nowe wersje pakietów zależnych\nustawa Autoready\ntrąbka: pozwalać aliasowi pokolenie z brakami konfiguracji bramy\nuszkodzenia w knx lib: zachować poprawny porządek wysyłania danych w przypadku rozbłysku",
|
|
81
|
-
"uk": "русскийукраїнськабеларускаяoʻzbek tilienglish\nфункція: синхронізація з створення адаптера 0.2.3\nфункція: оновлення до нових версій пакетів залежностей\nфункція: налаштування автопродавця Увімкнути автоматичний\nвиправлення помилок: генерація псевдонімів з відсутністю конфігурації шлюзу\nвиправлення помилок в knx lib: зберегти правильний порядок відправки графіків у разі лопу писати",
|
|
82
|
-
"zh-cn": "特色:复合克日图书馆\n特征:与创造适应力的结合\n特点:更新依赖一揽子计划的新版本\n特征:建立汽车 便携式汽车\nb ugfix:允许产生离散的门户组合\nb knx lib的ugfix:在开火时保持正确的发送数据图。"
|
|
83
96
|
}
|
|
84
97
|
},
|
|
85
98
|
"title": "Open KNX",
|
|
@@ -153,11 +166,12 @@
|
|
|
153
166
|
},
|
|
154
167
|
"native": {
|
|
155
168
|
"autoreadEnabled": true,
|
|
169
|
+
"useBoolean": true,
|
|
156
170
|
"gwip": "",
|
|
157
171
|
"gwipport": "3671",
|
|
158
172
|
"localInterface": "",
|
|
159
173
|
"minimumDelay": 50,
|
|
160
|
-
"aliassRegexp": "stat(e|us)(\\.|$)|rm(\\.|$)|r(ü|ue)ckmeldung(\\.|$)
|
|
174
|
+
"aliassRegexp": "stat(e|us)(\\.|$)|rm(\\.|$)|r(ü|ue)ckmeldung(\\.|$)",
|
|
161
175
|
"aliasSimilarity": 0.9,
|
|
162
176
|
"aliasPath": "alias.0",
|
|
163
177
|
"aliasRange": false
|
|
@@ -195,6 +195,7 @@ FSM.prototype.write = function(grpaddr, value, dptid, callback) {
|
|
|
195
195
|
KnxLog.get().warn('write: You must supply both grpaddr and value!');
|
|
196
196
|
return;
|
|
197
197
|
}
|
|
198
|
+
sendConfNotification(callback, grpaddr, this);
|
|
198
199
|
try {
|
|
199
200
|
// outbound request onto the state machine
|
|
200
201
|
const serviceType = this.useTunneling ?
|
|
@@ -203,7 +204,7 @@ FSM.prototype.write = function(grpaddr, value, dptid, callback) {
|
|
|
203
204
|
this.Request(serviceType, function(datagram) {
|
|
204
205
|
DPTLib.populateAPDU(value, datagram.cemi.apdu, dptid);
|
|
205
206
|
datagram.cemi.dest_addr = grpaddr;
|
|
206
|
-
}
|
|
207
|
+
});
|
|
207
208
|
} catch (e) {
|
|
208
209
|
KnxLog.get().warn(e);
|
|
209
210
|
}
|
|
@@ -235,6 +236,7 @@ FSM.prototype.writeRaw = function(grpaddr, value, bitlength, callback) {
|
|
|
235
236
|
KnxLog.get().warn('Value must be a buffer!');
|
|
236
237
|
return;
|
|
237
238
|
}
|
|
239
|
+
sendConfNotification(callback, grpaddr, this);
|
|
238
240
|
// outbound request onto the state machine
|
|
239
241
|
const serviceType = this.useTunneling ?
|
|
240
242
|
KnxConstants.SERVICE_TYPE.TUNNELING_REQUEST :
|
|
@@ -243,7 +245,7 @@ FSM.prototype.writeRaw = function(grpaddr, value, bitlength, callback) {
|
|
|
243
245
|
datagram.cemi.apdu.data = value;
|
|
244
246
|
datagram.cemi.apdu.bitlength = bitlength ? bitlength : (value.byteLength * 8);
|
|
245
247
|
datagram.cemi.dest_addr = grpaddr;
|
|
246
|
-
}
|
|
248
|
+
});
|
|
247
249
|
}
|
|
248
250
|
|
|
249
251
|
// send a READ request to the bus
|
|
@@ -365,4 +367,27 @@ function Connection(options) {
|
|
|
365
367
|
return conn;
|
|
366
368
|
};
|
|
367
369
|
|
|
370
|
+
//notify sending application if timeout or if confirmation received
|
|
371
|
+
function sendConfNotification(callback, grpaddr, fsm) {
|
|
372
|
+
if (typeof callback == 'function') {
|
|
373
|
+
// when the confirmation arrives:
|
|
374
|
+
const responseEvent = 'GroupValue_Write_confirmed_' + grpaddr;
|
|
375
|
+
KnxLog.get().trace('Binding connection to ' + responseEvent);
|
|
376
|
+
const binding = (confirmed) => {
|
|
377
|
+
// unbind the event handler
|
|
378
|
+
fsm.off(responseEvent, binding);
|
|
379
|
+
// fire the callback
|
|
380
|
+
callback(grpaddr, confirmed);
|
|
381
|
+
clearTimeout(fsm.confirmtimer);
|
|
382
|
+
}
|
|
383
|
+
// prepare for the response
|
|
384
|
+
fsm.on(responseEvent, binding);
|
|
385
|
+
// clean up after 3 seconds just in case no one confirms
|
|
386
|
+
fsm.confirmtimer = setTimeout( () => {
|
|
387
|
+
fsm.off(responseEvent, binding);
|
|
388
|
+
callback(grpaddr, false);
|
|
389
|
+
}, 3000);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
368
393
|
module.exports = Connection;
|
package/lib/knx/src/FSM.js
CHANGED
|
@@ -377,10 +377,17 @@ module.exports = machina.Fsm.extend({
|
|
|
377
377
|
['inbound_TUNNELING_REQUEST_L_Data.con'](datagram) {
|
|
378
378
|
if (this.useTunneling) {
|
|
379
379
|
const confirmed = this.sentTunnRequests[datagram.cemi.dest_addr] && ! /*cofirmation error*/ datagram.cemi.ctrl.confirm;
|
|
380
|
+
const evtName = datagram.cemi.apdu.apci;
|
|
380
381
|
|
|
381
382
|
delete this.sentTunnRequests[datagram.cemi.dest_addr];
|
|
382
383
|
this.emit('confirmed', datagram.cemi.dest_addr, confirmed);
|
|
383
384
|
|
|
385
|
+
// event name for example GroupValue_Write_1/2/3
|
|
386
|
+
this.emit(
|
|
387
|
+
util.format('%s_confirmed_%s', evtName, datagram.cemi.dest_addr),
|
|
388
|
+
confirmed
|
|
389
|
+
);
|
|
390
|
+
|
|
384
391
|
KnxLog.get().trace(
|
|
385
392
|
'(%s): %s %s',
|
|
386
393
|
this.compositeState(),
|
|
@@ -8,7 +8,7 @@ const log = require('log-driver').logger;
|
|
|
8
8
|
const custom_truthiness = (value) => {
|
|
9
9
|
const f = parseFloat(value);
|
|
10
10
|
return !isNaN(f) && isFinite(f) ?
|
|
11
|
-
f
|
|
11
|
+
f != 0.0 : // numeric values (in native and string form) are truthy if NOT zero
|
|
12
12
|
value === true || value === 'true';// non-numeric value truthiness is Boolean true or the string 'true'.
|
|
13
13
|
};
|
|
14
14
|
|
|
@@ -36,6 +36,7 @@ exports.subtypes = {
|
|
|
36
36
|
use: 'G',
|
|
37
37
|
name: 'DPT_Switch',
|
|
38
38
|
desc: 'switch',
|
|
39
|
+
range: [0, 1],
|
|
39
40
|
enc: { 0: 'Off', 1: 'On' },
|
|
40
41
|
},
|
|
41
42
|
|
|
@@ -43,6 +44,7 @@ exports.subtypes = {
|
|
|
43
44
|
use: 'G',
|
|
44
45
|
name: 'DPT_Bool',
|
|
45
46
|
desc: 'bool',
|
|
47
|
+
range: [0, 1],
|
|
46
48
|
enc: { 0: 'False', 1: 'True' },
|
|
47
49
|
},
|
|
48
50
|
|
|
@@ -50,6 +52,7 @@ exports.subtypes = {
|
|
|
50
52
|
use: 'G',
|
|
51
53
|
name: 'DPT_Enable',
|
|
52
54
|
desc: 'enable',
|
|
55
|
+
range: [0, 1],
|
|
53
56
|
enc: { 0: 'Disable', 1: 'Enable' },
|
|
54
57
|
},
|
|
55
58
|
|
|
@@ -57,6 +60,7 @@ exports.subtypes = {
|
|
|
57
60
|
use: 'FB',
|
|
58
61
|
name: 'DPT_Ramp',
|
|
59
62
|
desc: 'ramp',
|
|
63
|
+
range: [0, 1],
|
|
60
64
|
enc: { 0: 'No ramp', 1: 'Ramp' },
|
|
61
65
|
},
|
|
62
66
|
|
|
@@ -64,6 +68,7 @@ exports.subtypes = {
|
|
|
64
68
|
use: 'FB',
|
|
65
69
|
name: 'DPT_Alarm',
|
|
66
70
|
desc: 'alarm',
|
|
71
|
+
range: [0, 1],
|
|
67
72
|
enc: { 0: 'No alarm', 1: 'Alarm' },
|
|
68
73
|
},
|
|
69
74
|
|
|
@@ -71,6 +76,7 @@ exports.subtypes = {
|
|
|
71
76
|
use: 'FB',
|
|
72
77
|
name: 'DPT_BinaryValue',
|
|
73
78
|
desc: 'binary value',
|
|
79
|
+
range: [0, 1],
|
|
74
80
|
enc: { 0: 'Low', 1: 'High' },
|
|
75
81
|
},
|
|
76
82
|
|
|
@@ -78,6 +84,7 @@ exports.subtypes = {
|
|
|
78
84
|
use: 'FB',
|
|
79
85
|
name: 'DPT_Step',
|
|
80
86
|
desc: 'step',
|
|
87
|
+
range: [0, 1],
|
|
81
88
|
enc: { 0: 'Decrease', 1: 'Increase' },
|
|
82
89
|
},
|
|
83
90
|
|
|
@@ -85,6 +92,7 @@ exports.subtypes = {
|
|
|
85
92
|
use: 'G',
|
|
86
93
|
name: 'DPT_UpDown',
|
|
87
94
|
desc: 'up/down',
|
|
95
|
+
range: [0, 1],
|
|
88
96
|
enc: { 0: 'Up', 1: 'Down' },
|
|
89
97
|
},
|
|
90
98
|
|
|
@@ -92,6 +100,7 @@ exports.subtypes = {
|
|
|
92
100
|
use: 'G',
|
|
93
101
|
name: 'DPT_OpenClose',
|
|
94
102
|
desc: 'open/close',
|
|
103
|
+
range: [0, 1],
|
|
95
104
|
enc: { 0: 'Open', 1: 'Close' },
|
|
96
105
|
},
|
|
97
106
|
|
|
@@ -99,6 +108,7 @@ exports.subtypes = {
|
|
|
99
108
|
use: 'G',
|
|
100
109
|
name: 'DPT_Start',
|
|
101
110
|
desc: 'start/stop',
|
|
111
|
+
range: [0, 1],
|
|
102
112
|
enc: { 0: 'Stop', 1: 'Start' },
|
|
103
113
|
},
|
|
104
114
|
|
|
@@ -113,6 +123,7 @@ exports.subtypes = {
|
|
|
113
123
|
use: 'FB',
|
|
114
124
|
name: 'DPT_Invert',
|
|
115
125
|
desc: 'invert',
|
|
126
|
+
range: [0, 1],
|
|
116
127
|
enc: { 0: 'Not inverted', 1: 'Inverted' },
|
|
117
128
|
},
|
|
118
129
|
|
|
@@ -120,6 +131,7 @@ exports.subtypes = {
|
|
|
120
131
|
use: 'FB',
|
|
121
132
|
name: 'DPT_DimSendStyle',
|
|
122
133
|
desc: 'dim send style',
|
|
134
|
+
range: [0, 1],
|
|
123
135
|
enc: { 0: 'Start/stop', 1: 'Cyclically' },
|
|
124
136
|
},
|
|
125
137
|
|
|
@@ -127,6 +139,7 @@ exports.subtypes = {
|
|
|
127
139
|
use: 'FB',
|
|
128
140
|
name: 'DPT_InputSource',
|
|
129
141
|
desc: 'input source',
|
|
142
|
+
range: [0, 1],
|
|
130
143
|
enc: { 0: 'Fixed', 1: 'Calculated' },
|
|
131
144
|
},
|
|
132
145
|
|
|
@@ -134,55 +147,83 @@ exports.subtypes = {
|
|
|
134
147
|
use: 'G',
|
|
135
148
|
name: 'DPT_Reset',
|
|
136
149
|
desc: 'reset',
|
|
137
|
-
|
|
150
|
+
range: [0, 1],
|
|
151
|
+
enc: {
|
|
152
|
+
0: 'no action(dummy)',
|
|
153
|
+
1: 'reset command(trigger)'
|
|
154
|
+
},
|
|
138
155
|
},
|
|
139
156
|
|
|
140
157
|
'016': {
|
|
141
158
|
use: 'G',
|
|
142
159
|
name: 'DPT_Ack',
|
|
143
160
|
desc: 'ack',
|
|
144
|
-
|
|
161
|
+
range: [0, 1],
|
|
162
|
+
enc: {
|
|
163
|
+
0: 'no action(dummy)',
|
|
164
|
+
1: 'acknowledge command(trigger)' },
|
|
145
165
|
},
|
|
146
166
|
|
|
147
167
|
'017': {
|
|
148
168
|
use: 'G',
|
|
149
169
|
name: 'DPT_Trigger',
|
|
150
170
|
desc: 'trigger',
|
|
151
|
-
|
|
171
|
+
range: [0, 1],
|
|
172
|
+
enc: {
|
|
173
|
+
0: 'trigger',
|
|
174
|
+
1: 'trigger'
|
|
175
|
+
},
|
|
152
176
|
},
|
|
153
177
|
|
|
154
178
|
'018': {
|
|
155
179
|
use: 'G',
|
|
156
180
|
name: 'DPT_Occupancy',
|
|
157
181
|
desc: 'occupancy',
|
|
158
|
-
|
|
182
|
+
range: [0, 1],
|
|
183
|
+
enc: {
|
|
184
|
+
0: 'not occupied',
|
|
185
|
+
1: 'occupied'
|
|
186
|
+
},
|
|
159
187
|
},
|
|
160
188
|
|
|
161
189
|
'019': {
|
|
162
190
|
use: 'G',
|
|
163
191
|
name: 'DPT_WindowDoor',
|
|
164
192
|
desc: 'open window/door',
|
|
165
|
-
|
|
193
|
+
range: [0, 1],
|
|
194
|
+
enc: {
|
|
195
|
+
0: 'closed',
|
|
196
|
+
1: 'open'
|
|
197
|
+
},
|
|
166
198
|
},
|
|
167
199
|
|
|
168
200
|
'021': {
|
|
169
201
|
use: 'FB',
|
|
170
202
|
name: 'DPT_LogicalFunction',
|
|
171
203
|
desc: 'and/or',
|
|
172
|
-
|
|
204
|
+
range: [0, 1],
|
|
205
|
+
enc: {
|
|
206
|
+
0: 'logical function OR',
|
|
207
|
+
1: 'logical function AND'
|
|
208
|
+
},
|
|
173
209
|
},
|
|
174
210
|
|
|
175
211
|
'022': {
|
|
176
212
|
use: 'FB',
|
|
177
213
|
name: 'DPT_Scene_AB',
|
|
178
214
|
desc: 'scene A/B',
|
|
179
|
-
|
|
215
|
+
range: [0, 1],
|
|
216
|
+
enc: {
|
|
217
|
+
0: 'scene A',
|
|
218
|
+
1: 'scene B'
|
|
219
|
+
},
|
|
180
220
|
},
|
|
181
221
|
|
|
182
222
|
'023': {
|
|
183
223
|
use: 'FB',
|
|
184
224
|
name: 'DPT_ShutterBlinds_Mode',
|
|
185
225
|
desc: 'shutter/blinds mode',
|
|
226
|
+
range: [0, 1],
|
|
186
227
|
enc: {
|
|
187
228
|
0: 'only move Up/Down mode (shutter)',
|
|
188
229
|
1: 'move Up/Down + StepStop mode (blind)',
|
|
@@ -193,6 +234,7 @@ exports.subtypes = {
|
|
|
193
234
|
use: 'G',
|
|
194
235
|
name: 'DPT_DayNight',
|
|
195
236
|
desc: 'Day Night',
|
|
237
|
+
range: [0, 1],
|
|
196
238
|
enc: {
|
|
197
239
|
0: 'Day',
|
|
198
240
|
1: 'Night',
|
|
@@ -47,6 +47,7 @@ exports.subtypes = {
|
|
|
47
47
|
use: 'G',
|
|
48
48
|
name: 'DPT_Switch_Control',
|
|
49
49
|
desc: 'switch with priority',
|
|
50
|
+
range: [0, 3],
|
|
50
51
|
//enc: { 0: 'Off', 1: 'On' }, binary datatype, not enum
|
|
51
52
|
},
|
|
52
53
|
// 2.002 boolean control
|
|
@@ -54,6 +55,7 @@ exports.subtypes = {
|
|
|
54
55
|
use: 'G',
|
|
55
56
|
name: 'DPT_Bool_Control',
|
|
56
57
|
desc: 'boolean with priority',
|
|
58
|
+
range: [0, 3],
|
|
57
59
|
//enc: { 0: 'false', 1: 'true' },
|
|
58
60
|
},
|
|
59
61
|
// 2.003 enable control
|
|
@@ -61,6 +63,7 @@ exports.subtypes = {
|
|
|
61
63
|
use: 'FB',
|
|
62
64
|
name: 'DPT_Emable_Control',
|
|
63
65
|
desc: 'enable with priority',
|
|
66
|
+
range: [0, 3],
|
|
64
67
|
//enc: { 0: 'Disabled', 1: 'Enabled' },
|
|
65
68
|
},
|
|
66
69
|
|
|
@@ -69,6 +72,7 @@ exports.subtypes = {
|
|
|
69
72
|
use: 'FB',
|
|
70
73
|
name: 'DPT_Ramp_Control',
|
|
71
74
|
desc: 'ramp with priority',
|
|
75
|
+
range: [0, 3],
|
|
72
76
|
//enc: { 0: 'No ramp', 1: 'Ramp' },
|
|
73
77
|
},
|
|
74
78
|
|
|
@@ -77,6 +81,7 @@ exports.subtypes = {
|
|
|
77
81
|
use: 'FB',
|
|
78
82
|
name: 'DPT_Alarm_Control',
|
|
79
83
|
desc: 'alarm with priority',
|
|
84
|
+
range: [0, 3],
|
|
80
85
|
//enc: { 0: 'No alarm', 1: 'Alarm' },
|
|
81
86
|
},
|
|
82
87
|
|
|
@@ -85,6 +90,7 @@ exports.subtypes = {
|
|
|
85
90
|
use: 'FB',
|
|
86
91
|
name: 'DPT_BinaryValue_Control',
|
|
87
92
|
desc: 'binary value with priority',
|
|
93
|
+
range: [0, 3],
|
|
88
94
|
//enc: { 0: 'Off', 1: 'On' },
|
|
89
95
|
},
|
|
90
96
|
|
|
@@ -93,6 +99,7 @@ exports.subtypes = {
|
|
|
93
99
|
use: 'FB',
|
|
94
100
|
name: 'DPT_Step_Control',
|
|
95
101
|
desc: 'step with priority',
|
|
102
|
+
range: [0, 3],
|
|
96
103
|
//enc: { 0: 'Off', 1: 'On' },
|
|
97
104
|
},
|
|
98
105
|
|
|
@@ -101,6 +108,7 @@ exports.subtypes = {
|
|
|
101
108
|
use: 'FB',
|
|
102
109
|
name: 'DPT_Direction1_Control',
|
|
103
110
|
desc: 'direction 1 with priority',
|
|
111
|
+
range: [0, 3],
|
|
104
112
|
//enc: { 0: 'Off', 1: 'On' },
|
|
105
113
|
},
|
|
106
114
|
|
|
@@ -109,6 +117,7 @@ exports.subtypes = {
|
|
|
109
117
|
use: 'FB',
|
|
110
118
|
name: 'DPT_Direction2_Control',
|
|
111
119
|
desc: 'direction 2 with priority',
|
|
120
|
+
range: [0, 3],
|
|
112
121
|
//enc: { 0: 'Off', 1: 'On' },
|
|
113
122
|
},
|
|
114
123
|
|
|
@@ -117,6 +126,7 @@ exports.subtypes = {
|
|
|
117
126
|
use: 'FB',
|
|
118
127
|
name: 'DPT_Start_Control',
|
|
119
128
|
desc: 'start with priority',
|
|
129
|
+
range: [0, 3],
|
|
120
130
|
//enc: { 0: 'Off', 1: 'On' },
|
|
121
131
|
},
|
|
122
132
|
|
|
@@ -125,6 +135,7 @@ exports.subtypes = {
|
|
|
125
135
|
use: 'FB',
|
|
126
136
|
name: 'DPT_State_Control',
|
|
127
137
|
desc: 'switch',
|
|
138
|
+
range: [0, 3],
|
|
128
139
|
//enc: { 0: 'Off', 1: 'On' },
|
|
129
140
|
},
|
|
130
141
|
|
|
@@ -133,6 +144,7 @@ exports.subtypes = {
|
|
|
133
144
|
use: 'FB',
|
|
134
145
|
name: 'DPT_Invert_Control',
|
|
135
146
|
desc: 'switch',
|
|
147
|
+
range: [0, 3],
|
|
136
148
|
//enc: { 0: 'Off', 1: 'On' },
|
|
137
149
|
},
|
|
138
150
|
};
|
|
@@ -63,18 +63,18 @@ exports.basetype = {
|
|
|
63
63
|
exports.subtypes = {
|
|
64
64
|
// 21.001 status - 5 bits
|
|
65
65
|
"001" : {
|
|
66
|
-
|
|
66
|
+
"name" : "DPT_StatusGen",
|
|
67
67
|
"desc" : "General Status",
|
|
68
|
-
|
|
68
|
+
"unit" : "",
|
|
69
69
|
"scalar_range" : [ , ],
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
"range" : [ , ]
|
|
71
|
+
},
|
|
72
72
|
// 21.002 control - 3 bits
|
|
73
73
|
"002" : {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
"name" : "DPT_Device_Control",
|
|
75
|
+
"desc" : "Device Control",
|
|
76
|
+
"unit" : "",
|
|
77
77
|
"scalar_range" : [ , ],
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
"range" : [ , ]
|
|
79
|
+
}
|
|
80
80
|
}
|
|
@@ -43,11 +43,13 @@ exports.subtypes = {
|
|
|
43
43
|
'007': {
|
|
44
44
|
name: 'DPT_Control_Dimming',
|
|
45
45
|
desc: 'dimming control',
|
|
46
|
+
range: [0, 15],
|
|
46
47
|
},
|
|
47
48
|
|
|
48
49
|
// 3.008 blind control
|
|
49
50
|
'008': {
|
|
50
51
|
name: 'DPT_Control_Blinds',
|
|
51
52
|
desc: 'blinds control',
|
|
53
|
+
range: [0, 15],
|
|
52
54
|
},
|
|
53
55
|
};
|
|
@@ -19,13 +19,15 @@ exports.subtypes = {
|
|
|
19
19
|
// 5.001 percentage (0=0..ff=100%)
|
|
20
20
|
"001" : {
|
|
21
21
|
"name" : "DPT_Scaling", "desc" : "percent",
|
|
22
|
-
"unit" : "%",
|
|
22
|
+
"unit" : "%",
|
|
23
|
+
"scalar_range" : [0, 100]
|
|
23
24
|
},
|
|
24
25
|
|
|
25
26
|
// 5.003 angle (degrees 0=0, ff=360)
|
|
26
27
|
"003" : {
|
|
27
28
|
"name" : "DPT_Angle", "desc" : "angle degrees",
|
|
28
|
-
"unit" : "°",
|
|
29
|
+
"unit" : "°",
|
|
30
|
+
"scalar_range" : [0, 360]
|
|
29
31
|
},
|
|
30
32
|
|
|
31
33
|
// 5.004 percentage (0..255%)
|
package/lib/projectImport.js
CHANGED
|
@@ -10,6 +10,7 @@ const select = require("xpath");
|
|
|
10
10
|
const dom = require("xmldom").DOMParser;
|
|
11
11
|
const tools = require("./tools.js");
|
|
12
12
|
const similarity = require("similarity");
|
|
13
|
+
const { basetype } = require("./knx/src/dptlib/dpt1.js");
|
|
13
14
|
|
|
14
15
|
module.exports = {
|
|
15
16
|
// get xml Files from index.html via adapter.on 'message' and put it into file Obj
|
|
@@ -82,7 +83,7 @@ module.exports = {
|
|
|
82
83
|
//allowed state, unresolveable dpt means raw interface
|
|
83
84
|
}
|
|
84
85
|
|
|
85
|
-
({ range, type, role } = identifyRangeRoleType(dptObj, range, dpt, type, role));
|
|
86
|
+
({ range, type, role } = identifyRangeRoleType(adapter, dptObj, range, dpt, type, role));
|
|
86
87
|
|
|
87
88
|
//if dpt is for sure not a status, remove from autoread
|
|
88
89
|
autoread = !tools.isTriggerDPT(dpt);
|
|
@@ -165,7 +166,7 @@ module.exports = {
|
|
|
165
166
|
return fullPath + tools.formatGaNameForIob(gaName);
|
|
166
167
|
}
|
|
167
168
|
|
|
168
|
-
function identifyRangeRoleType(dptObj, range, dpt, type, role) {
|
|
169
|
+
function identifyRangeRoleType(ad, dptObj, range, dpt, type, role) {
|
|
169
170
|
// is there a scalar range? eg. DPT5.003 angle degrees (0=0, ff=360)
|
|
170
171
|
if (dptObj?.subtype?.scalar_range) {
|
|
171
172
|
range = dptObj.subtype.scalar_range;
|
|
@@ -184,7 +185,15 @@ module.exports = {
|
|
|
184
185
|
//unknown dpt, range unknown
|
|
185
186
|
range = [];
|
|
186
187
|
}
|
|
187
|
-
|
|
188
|
+
|
|
189
|
+
if (dptObj?.subtype?.enc) {
|
|
190
|
+
if (basetype.bitlength == 1) {
|
|
191
|
+
//treat enum with one bit as mixed
|
|
192
|
+
if (ad.config.useBoolean) {
|
|
193
|
+
type = "boolean";
|
|
194
|
+
} else type = "mixed";
|
|
195
|
+
} else type = "number";
|
|
196
|
+
}
|
|
188
197
|
|
|
189
198
|
//correct range, set type and role based on dpt
|
|
190
199
|
//obj.common.min is only allowed on obj.common.type "number" or "mixed"
|
|
@@ -204,7 +213,7 @@ module.exports = {
|
|
|
204
213
|
console.assert(type == "", "object " + type);
|
|
205
214
|
type = "object";
|
|
206
215
|
} else if (!!dptObj && !tools.isEmptyObject(dptObj) && dptObj.basetype && dptObj.basetype.bitlength == 1) {
|
|
207
|
-
if (type != "
|
|
216
|
+
if (type != "number") type = "boolean";
|
|
208
217
|
role = "switch";
|
|
209
218
|
range[0] = false;
|
|
210
219
|
range[1] = true;
|
package/lib/tools.js
CHANGED
|
@@ -103,7 +103,7 @@ async function translateGoogle(text, targetLang) {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
/*
|
|
106
|
-
* convert dpt into DPT1 or DPT1.001
|
|
106
|
+
* convert dpt into DPT1 or DPT1.001 notation when input is like DPT-1 or DPST-1-001
|
|
107
107
|
*/
|
|
108
108
|
function formatDpt(dpt) {
|
|
109
109
|
if (dpt.indexOf("-") != -1) {
|
|
@@ -177,6 +177,10 @@ function isDateDPT(dpt) {
|
|
|
177
177
|
);
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
function isBitDPT(dpt) {
|
|
181
|
+
return dpt == "DPT1" || dpt.startsWith("DPT1.");
|
|
182
|
+
}
|
|
183
|
+
|
|
180
184
|
function isFloatDPT(dpt) {
|
|
181
185
|
return dpt == "DPT9" || dpt.startsWith("DPT9.") || dpt == "DPT14" || dpt.startsWith("DPT14.");
|
|
182
186
|
}
|
|
@@ -227,6 +231,7 @@ module.exports = {
|
|
|
227
231
|
formatGaNameForIob,
|
|
228
232
|
isStringDPT,
|
|
229
233
|
isDateDPT,
|
|
234
|
+
isBitDPT,
|
|
230
235
|
isUnknownDPT,
|
|
231
236
|
isFloatDPT,
|
|
232
237
|
isTriggerDPT,
|
package/main.js
CHANGED
|
@@ -19,6 +19,7 @@ const DoubleKeyedMap = require("./lib/doubleKeyedMap.js");
|
|
|
19
19
|
const detect = require("./lib/openknx.js");
|
|
20
20
|
const os = require("os");
|
|
21
21
|
const exitHook = require("async-exit-hook");
|
|
22
|
+
const { dpt1_control_ga } = require("./lib/knx/test/wiredtests/wiredtest-options.js");
|
|
22
23
|
|
|
23
24
|
class openknx extends utils.Adapter {
|
|
24
25
|
/**
|
|
@@ -336,6 +337,7 @@ class openknx extends utils.Adapter {
|
|
|
336
337
|
//keep string, boolean and number
|
|
337
338
|
ret = val;
|
|
338
339
|
}
|
|
340
|
+
|
|
339
341
|
return ret;
|
|
340
342
|
}
|
|
341
343
|
|
|
@@ -426,24 +428,39 @@ class openknx extends utils.Adapter {
|
|
|
426
428
|
|
|
427
429
|
// @ts-ignore
|
|
428
430
|
if (state.c == "GroupValue_Read" || state.q == 0x10) {
|
|
429
|
-
//interface to trigger GrouValue_Read is this comment or
|
|
430
|
-
this.log.debug("Outbound GroupValue_Read to " + ga);
|
|
431
|
-
this.knxConnection.read(ga)
|
|
431
|
+
//interface to trigger GrouValue_Read is this object comment or StateQuality 16
|
|
432
|
+
this.log.debug("Outbound GroupValue_Read to GA " + ga);
|
|
433
|
+
this.knxConnection.read(ga, () => {
|
|
434
|
+
//ack is generated with GroupValue_Response
|
|
435
|
+
});
|
|
432
436
|
return "read";
|
|
433
437
|
} else if (this.gaList.getDataById(id).common.write) {
|
|
434
438
|
this.log.debug(
|
|
435
|
-
|
|
436
|
-
ga +
|
|
437
|
-
" val: " +
|
|
438
|
-
(isRaw ? rawVal : JSON.stringify(knxVal)) +
|
|
439
|
-
" from " +
|
|
440
|
-
id,
|
|
439
|
+
`Outbound GroupValue_Write to " ${ga} val: ${isRaw ? rawVal : JSON.stringify(knxVal)} from ${id}`,
|
|
441
440
|
);
|
|
442
441
|
if (isRaw) {
|
|
443
|
-
this.knxConnection.writeRaw(ga, rawVal, () => {
|
|
442
|
+
this.knxConnection.writeRaw(ga, rawVal, (grpaddr, confirmed) => {
|
|
443
|
+
//l_data.con confirmation set by any receiver connected to the ga
|
|
444
|
+
if (confirmed) {
|
|
445
|
+
//set iob ack when value sent successful on the bus otherwise keep unset
|
|
446
|
+
this.setState(id, {
|
|
447
|
+
ack: true,
|
|
448
|
+
});
|
|
449
|
+
this.log.debug(`GroupValue_Write confirmation ${confirmed} received for ${grpaddr} ${id}`);
|
|
450
|
+
} else this.log.info(`GroupValue_Write confirmation ${confirmed} received for ${grpaddr} ${id}`);
|
|
451
|
+
});
|
|
444
452
|
return "write raw";
|
|
445
453
|
} else {
|
|
446
|
-
this.knxConnection.write(ga, knxVal, dpt, () => {
|
|
454
|
+
this.knxConnection.write(ga, knxVal, dpt, (grpaddr, confirmed) => {
|
|
455
|
+
//l_data.con confirmation set by any receiver connected to the ga
|
|
456
|
+
if (confirmed) {
|
|
457
|
+
//set iob ack when value sent successful on the bus otherwise keep unset
|
|
458
|
+
this.setState(id, {
|
|
459
|
+
ack: true,
|
|
460
|
+
});
|
|
461
|
+
this.log.debug(`GroupValue_Write confirmation ${confirmed} received for ${grpaddr} ${id}`);
|
|
462
|
+
} else this.log.info(`GroupValue_Write confirmation ${confirmed} received for ${grpaddr} ${id}`);
|
|
463
|
+
});
|
|
447
464
|
return "write";
|
|
448
465
|
}
|
|
449
466
|
} else {
|
|
@@ -493,11 +510,11 @@ class openknx extends utils.Adapter {
|
|
|
493
510
|
this.gaList.setDpById(key, datapoint);
|
|
494
511
|
cnt_withDPT++;
|
|
495
512
|
this.log.debug(
|
|
496
|
-
`Datapoint
|
|
497
|
-
this.gaList.getDataById(key).native.autoread
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
} ${key}`,
|
|
513
|
+
`Datapoint ${
|
|
514
|
+
this.gaList.getDataById(key).native.autoread
|
|
515
|
+
? "autoread created and GroupValueRead sent"
|
|
516
|
+
: "created"
|
|
517
|
+
} ${this.gaList.getDataById(key).native.address} ${key}`,
|
|
501
518
|
);
|
|
502
519
|
} catch (e) {
|
|
503
520
|
this.log.error("could not create KNX Datapoint for " + key + " with error: " + e);
|
|
@@ -522,21 +539,21 @@ class openknx extends utils.Adapter {
|
|
|
522
539
|
this.log.warn(connstatus);
|
|
523
540
|
},
|
|
524
541
|
|
|
525
|
-
//l_data.con, confirmation set receiver
|
|
542
|
+
//l_data.con, confirmation set by a receiver which has the sending flag
|
|
526
543
|
confirmed: (dest, confirmed) => {
|
|
527
544
|
for (const id of this.gaList.getIdsByGa(dest)) {
|
|
528
|
-
if (confirmed)
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
});
|
|
533
|
-
|
|
534
|
-
else this.log.info(`confirmation false received for ${dest} ${id}`);
|
|
545
|
+
if (confirmed) {
|
|
546
|
+
this.log.debug(`confirmation true received for ${dest} ${id}`);
|
|
547
|
+
} else {
|
|
548
|
+
//otherwise keep unset
|
|
549
|
+
this.log.info(`confirmation false received for ${dest} ${id}`);
|
|
550
|
+
}
|
|
535
551
|
}
|
|
536
552
|
},
|
|
537
553
|
|
|
538
554
|
//KNX Bus event received
|
|
539
|
-
//src: KnxDeviceAddress, dest: KnxGroupAddress,
|
|
555
|
+
//src: KnxDeviceAddress, dest: KnxGroupAddress,
|
|
556
|
+
//val: raw value not used, using dp interface instead
|
|
540
557
|
// @ts-ignore
|
|
541
558
|
event: (
|
|
542
559
|
/** @type {string} */ evt,
|
|
@@ -624,17 +641,7 @@ class openknx extends utils.Adapter {
|
|
|
624
641
|
break;
|
|
625
642
|
|
|
626
643
|
default:
|
|
627
|
-
this.log.debug(
|
|
628
|
-
"received unhandeled event " +
|
|
629
|
-
" " +
|
|
630
|
-
evt +
|
|
631
|
-
" " +
|
|
632
|
-
src +
|
|
633
|
-
" " +
|
|
634
|
-
dest +
|
|
635
|
-
" " +
|
|
636
|
-
convertedVal,
|
|
637
|
-
);
|
|
644
|
+
this.log.debug(`received unhandeled event " ${evt} ${src} ${dest} ${convertedVal}`);
|
|
638
645
|
ret = "unhandeled";
|
|
639
646
|
}
|
|
640
647
|
}
|