iobroker.lorawan 0.1.2 → 0.1.4
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 +6 -0
- package/admin/i18n/de/translations.json +2 -2
- package/admin/i18n/en/translations.json +2 -2
- package/admin/i18n/es/translations.json +2 -2
- package/admin/i18n/fr/translations.json +2 -2
- package/admin/i18n/it/translations.json +2 -2
- package/admin/i18n/nl/translations.json +2 -2
- package/admin/i18n/pl/translations.json +2 -2
- package/admin/i18n/pt/translations.json +2 -2
- package/admin/i18n/ru/translations.json +3 -3
- package/admin/i18n/uk/translations.json +2 -2
- package/admin/i18n/zh-cn/translations.json +3 -3
- package/admin/jsonConfig.json +13 -9
- package/io-package.json +27 -27
- package/lib/modules/directorieshandler.js +6 -6
- package/lib/modules/downlinkConfighandler.js +90 -43
- package/lib/modules/downlinks/Dragino LT22222.json +8 -8
- package/lib/modules/downlinks/Dragino.json +2 -2
- package/lib/modules/downlinks/LBR-BSM-0404.json +117 -0
- package/lib/modules/downlinks/Vicki.json +139 -0
- package/lib/modules/downlinks/{all.json → baseDevices/internalBaseDevice.json} +4 -3
- package/lib/modules/messagehandler.js +12 -11
- package/lib/modules/mqttclient.js +2 -2
- package/main.js +35 -68
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -19,6 +19,12 @@ Adapter was created in collaboration with Joerg Froehner LoraWan@hafenmeister.co
|
|
|
19
19
|
Placeholder for the next version (at the beginning of the line):
|
|
20
20
|
### **WORK IN PROGRESS**
|
|
21
21
|
-->
|
|
22
|
+
### 0.1.4 (2024-02-01)
|
|
23
|
+
* (BenAhrdt) change input of length and validate hex inputs
|
|
24
|
+
|
|
25
|
+
### 0.1.3 (2024-02-01)
|
|
26
|
+
* (BenAhrdt) change internal Base devices
|
|
27
|
+
|
|
22
28
|
### 0.1.2 (2024-01-31)
|
|
23
29
|
* (BenAhrdt) concept of config changed
|
|
24
30
|
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"frontTooltip": "Geben Sie den Frontwert im Hex-Format ein, der heruntergeladen werden soll",
|
|
35
35
|
"end": "Folgend (hex)",
|
|
36
36
|
"endTooltip": "Geben Sie den Endwert im Hex-Format ein, der heruntergeladen werden soll",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
37
|
+
"lengthInByte": "Statelänge (Byte)",
|
|
38
|
+
"lengthInByteTooltip": "Geben Sie die Länge des States in Bytes an",
|
|
39
39
|
"on": "An",
|
|
40
40
|
"onTooltip": "Geben Sie den Wert ein, den Sie senden möchten, wenn Sie den Status auf „true“ setzen",
|
|
41
41
|
"off": "aus",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"frontTooltip": "insert the front-value in hex format, wich will be downloaded",
|
|
35
35
|
"end": "end value (hex)",
|
|
36
36
|
"endTooltip": "insert the end-value in hex format, wich will be downloaded",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
37
|
+
"lengthInByte": "length of state (byte)",
|
|
38
|
+
"lengthInByteTooltip": "insert the length of the state in bytes",
|
|
39
39
|
"on": "on",
|
|
40
40
|
"onTooltip": "insert the value you want to send if you set the state to true",
|
|
41
41
|
"off": "off",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"frontTooltip": "inserte el valor frontal en formato hexadecimal, que se descargará",
|
|
35
35
|
"end": "valor final (hexadecimal)",
|
|
36
36
|
"endTooltip": "inserte el valor final en formato hexadecimal, que se descargará",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
37
|
+
"lengthInByte": "longitud del estado (byte)",
|
|
38
|
+
"lengthInByteTooltip": "insertar la longitud del estado en bytes",
|
|
39
39
|
"on": "en",
|
|
40
40
|
"onTooltip": "inserte el valor que desea enviar si establece el estado en verdadero",
|
|
41
41
|
"off": "apagado",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"frontTooltip": "insérez la valeur frontale au format hexadécimal, qui sera téléchargée",
|
|
35
35
|
"end": "valeur finale (hex)",
|
|
36
36
|
"endTooltip": "insérez la valeur finale au format hexadécimal, qui sera téléchargée",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
37
|
+
"lengthInByte": "longueur de l'état (octet)",
|
|
38
|
+
"lengthInByteTooltip": "insérer la longueur de l'état en octets",
|
|
39
39
|
"on": "sur",
|
|
40
40
|
"onTooltip": "insérez la valeur que vous souhaitez envoyer si vous définissez l'état sur true",
|
|
41
41
|
"off": "désactivé",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"frontTooltip": "inserire il valore frontale in formato esadecimale, che verrà scaricato",
|
|
35
35
|
"end": "valore finale (esadecimale)",
|
|
36
36
|
"endTooltip": "inserire il valore finale in formato esadecimale, che verrà scaricato",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
37
|
+
"lengthInByte": "lunghezza dello stato (byte)",
|
|
38
|
+
"lengthInByteTooltip": "inserire la lunghezza dello stato in byte",
|
|
39
39
|
"on": "SU",
|
|
40
40
|
"onTooltip": "inserisci il valore che vuoi inviare se imposti lo stato su true",
|
|
41
41
|
"off": "spento",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"frontTooltip": "voeg de voorwaarde in hexadecimaal formaat in, die zal worden gedownload",
|
|
35
35
|
"end": "eindwaarde (hexadecimaal)",
|
|
36
36
|
"endTooltip": "voer de eindwaarde in hexadecimaal formaat in, die zal worden gedownload",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
37
|
+
"lengthInByte": "lengte van staat (byte)",
|
|
38
|
+
"lengthInByteTooltip": "voer de lengte van de status in bytes in",
|
|
39
39
|
"on": "op",
|
|
40
40
|
"onTooltip": "voer de waarde in die u wilt verzenden als u de status op true instelt",
|
|
41
41
|
"off": "uit",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"frontTooltip": "wstaw wartość przednią w formacie szesnastkowym, która zostanie pobrana",
|
|
35
35
|
"end": "wartość końcowa (szesnastkowo)",
|
|
36
36
|
"endTooltip": "wstaw wartość końcową w formacie szesnastkowym, która zostanie pobrana",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
37
|
+
"lengthInByte": "długość stanu (bajt)",
|
|
38
|
+
"lengthInByteTooltip": "wstaw długość stanu w bajtach",
|
|
39
39
|
"on": "NA",
|
|
40
40
|
"onTooltip": "wstaw wartość, którą chcesz wysłać, jeśli ustawisz stan na true",
|
|
41
41
|
"off": "wyłączony",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"frontTooltip": "insira o valor frontal em formato hexadecimal, que será baixado",
|
|
35
35
|
"end": "valor final (hex)",
|
|
36
36
|
"endTooltip": "insira o valor final em formato hexadecimal, que será baixado",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
37
|
+
"lengthInByte": "comprimento do estado (byte)",
|
|
38
|
+
"lengthInByteTooltip": "insira o comprimento do estado em bytes",
|
|
39
39
|
"on": "sobre",
|
|
40
40
|
"onTooltip": "insira o valor que deseja enviar se definir o estado como verdadeiro",
|
|
41
41
|
"off": "desligado",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"frontTooltip": "вставьте переднее значение в шестнадцатеричном формате, которое будет загружено",
|
|
35
35
|
"end": "конечное значение (шестнадцатеричное)",
|
|
36
36
|
"endTooltip": "вставьте конечное значение в шестнадцатеричном формате, которое будет загружено",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
37
|
+
"lengthInByte": "длина состояния (байт)",
|
|
38
|
+
"lengthInByteTooltip": "вставьте длину состояния в байтах",
|
|
39
39
|
"on": "на",
|
|
40
40
|
"onTooltip": "вставьте значение, которое вы хотите отправить, если вы установили состояние true",
|
|
41
41
|
"off": "выключенный",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"unitTooltip": "вставьте единицу измерения вашего значения",
|
|
49
49
|
"deviceType": "тип устройства",
|
|
50
50
|
"expertSettings": "Эксперт-Настройки",
|
|
51
|
-
"enabled & collect": "включить и
|
|
51
|
+
"enabled & collect": "включить и собрать",
|
|
52
52
|
"deviceTypeTooltip": "вставьте название типа устройства, этот конфиг действителен. (например, Dragino XY также соответствует Dragino)",
|
|
53
53
|
"sendWithUplink": "отправить по восходящей линии связи",
|
|
54
54
|
"sendWithUplinkTooltip": "выберите режим отправки для конфигов с нужным типом устройства",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"frontTooltip": "вставте переднє значення в шістнадцятковому форматі, яке буде завантажено",
|
|
35
35
|
"end": "кінцеве значення (шістнадцяткове)",
|
|
36
36
|
"endTooltip": "вставте кінцеве значення в шістнадцятковому форматі, яке буде завантажено",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
37
|
+
"lengthInByte": "довжина стану (байт)",
|
|
38
|
+
"lengthInByteTooltip": "вставити довжину стану в байтах",
|
|
39
39
|
"on": "на",
|
|
40
40
|
"onTooltip": "вставте значення, яке ви хочете надіслати, якщо ви встановили стан як true",
|
|
41
41
|
"off": "вимкнено",
|
|
@@ -34,15 +34,15 @@
|
|
|
34
34
|
"frontTooltip": "以十六进制格式插入前面的值,它将被下载",
|
|
35
35
|
"end": "最终值(十六进制)",
|
|
36
36
|
"endTooltip": "插入十六进制格式的最终值,它将被下载",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
37
|
+
"lengthInByte": "状态长度(字节)",
|
|
38
|
+
"lengthInByteTooltip": "插入状态的长度(以字节为单位)",
|
|
39
39
|
"on": "在",
|
|
40
40
|
"onTooltip": "如果将状态设置为 true,则插入要发送的值",
|
|
41
41
|
"off": "离开",
|
|
42
42
|
"offTooltip": "如果将状态设置为 false,则插入要发送的值",
|
|
43
43
|
"onClick": "点击时",
|
|
44
44
|
"onClickTooltip": "如果将状态设置为 true(单击按钮),则插入要发送的值",
|
|
45
|
-
"multiplyfaktor": "
|
|
45
|
+
"multiplyfaktor": "多重因子",
|
|
46
46
|
"multiplyfaktorTooltip": "插入您想要与数据相乘的因子(例如,输入 1(min) => 60s 为 60)",
|
|
47
47
|
"unit": "单元",
|
|
48
48
|
"unitTooltip": "插入您的值的单位",
|
package/admin/jsonConfig.json
CHANGED
|
@@ -102,7 +102,6 @@
|
|
|
102
102
|
"items":[
|
|
103
103
|
{
|
|
104
104
|
"newLine": true,
|
|
105
|
-
"attr": "downlinkConfigMain",
|
|
106
105
|
"type": "header",
|
|
107
106
|
"text": "downlinkConfigMainHeader",
|
|
108
107
|
"size": 3
|
|
@@ -115,6 +114,8 @@
|
|
|
115
114
|
"options": [
|
|
116
115
|
{"label":"all","value":"all"}
|
|
117
116
|
],
|
|
117
|
+
"validator": "if(data.deviceType === '' || data.deviceType === null){return false;}else{return true;}",
|
|
118
|
+
"validatorNoSaveOnError": true,
|
|
118
119
|
"default": "all",
|
|
119
120
|
"freeSolo": true,
|
|
120
121
|
"sm":2
|
|
@@ -179,8 +180,7 @@
|
|
|
179
180
|
"label": "name",
|
|
180
181
|
"tooltip": "nameTooltip",
|
|
181
182
|
"default": "",
|
|
182
|
-
"validator": "if(data.name === '' || data.name === null)
|
|
183
|
-
"validatorNoSaveOnError": true,
|
|
183
|
+
"validator": "if(data.name === '' || data.name === null){return false;}else{return true;}",
|
|
184
184
|
"sm":2
|
|
185
185
|
},
|
|
186
186
|
{
|
|
@@ -229,6 +229,7 @@
|
|
|
229
229
|
"label": "front",
|
|
230
230
|
"tooltip": "frontTooltip",
|
|
231
231
|
"default": "03",
|
|
232
|
+
"validator": "const myRegEx = /^([0-9a-f]{2})*$/i; return myRegEx.test(data.front);",
|
|
232
233
|
"hidden": "data.type === 'boolean' || data.type === 'button'",
|
|
233
234
|
"sm":2
|
|
234
235
|
},
|
|
@@ -237,17 +238,17 @@
|
|
|
237
238
|
"attr": "end",
|
|
238
239
|
"label": "end",
|
|
239
240
|
"tooltip": "endTooltip",
|
|
240
|
-
"default": "11",
|
|
241
|
+
"default": "11","validator": "const myRegEx = /^([0-9a-f]{2})*$/i; return myRegEx.test(data.end);",
|
|
241
242
|
"hidden": "data.type === 'boolean' || data.type === 'button'",
|
|
242
243
|
"sm":2
|
|
243
244
|
},
|
|
244
245
|
{
|
|
245
246
|
"type": "number",
|
|
246
|
-
"attr": "
|
|
247
|
-
"label": "
|
|
248
|
-
"tooltip": "
|
|
249
|
-
"default":
|
|
250
|
-
"min":
|
|
247
|
+
"attr": "lengthInByte",
|
|
248
|
+
"label": "lengthInByte",
|
|
249
|
+
"tooltip": "lengthInByteTooltip",
|
|
250
|
+
"default": 2,
|
|
251
|
+
"min":1,
|
|
251
252
|
"max": 20,
|
|
252
253
|
"hidden": "data.type === 'boolean' || data.type === 'button' || data.type === 'string'",
|
|
253
254
|
"sm":2
|
|
@@ -259,6 +260,7 @@
|
|
|
259
260
|
"label": "on",
|
|
260
261
|
"tooltip": "onTooltip",
|
|
261
262
|
"default": "01",
|
|
263
|
+
"validator": "const myRegEx = /^([0-9a-f]{2})*$/i; return myRegEx.test(data.on);",
|
|
262
264
|
"hidden": "data.type !== 'boolean'",
|
|
263
265
|
"sm":2
|
|
264
266
|
},
|
|
@@ -268,6 +270,7 @@
|
|
|
268
270
|
"label": "off",
|
|
269
271
|
"tooltip": "offTooltip",
|
|
270
272
|
"default": "11",
|
|
273
|
+
"validator": "const myRegEx = /^([0-9a-f]{2})*$/i; return myRegEx.test(data.off);",
|
|
271
274
|
"hidden": "data.type !== 'boolean'",
|
|
272
275
|
"sm":2
|
|
273
276
|
},
|
|
@@ -278,6 +281,7 @@
|
|
|
278
281
|
"label": "onClick",
|
|
279
282
|
"tooltip": "onClickTooltip",
|
|
280
283
|
"default": "030111",
|
|
284
|
+
"validator": "const myRegEx = /^([0-9a-f]{2})*$/i; return myRegEx.test(data.onClick);",
|
|
281
285
|
"hidden": "data.type !== 'button'",
|
|
282
286
|
"sm":2
|
|
283
287
|
},
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "lorawan",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.4",
|
|
5
5
|
"news": {
|
|
6
|
+
"0.1.4": {
|
|
7
|
+
"en": "change input of length and validate hex inputs",
|
|
8
|
+
"de": "längeneingabe ändern und hexeneingänge validieren",
|
|
9
|
+
"ru": "изменение вводимых значений длины и валидированных",
|
|
10
|
+
"pt": "alterar a entrada de comprimento e validar entradas de hex",
|
|
11
|
+
"nl": "de input van lengte wijzigen en hex-inputs valideren",
|
|
12
|
+
"fr": "modifier l'entrée de longueur et valider les entrées de hexagone",
|
|
13
|
+
"it": "modificare l'ingresso della lunghezza e convalidare gli input esadecimali",
|
|
14
|
+
"es": "cambio de entrada de longitud y validar entradas de hex",
|
|
15
|
+
"pl": "zmiana wejścia długości i walidacja wejść heksu",
|
|
16
|
+
"uk": "зміна введення довжини і валідації шестигранних входів",
|
|
17
|
+
"zh-cn": "修改长度输入并验证十六进制输入"
|
|
18
|
+
},
|
|
19
|
+
"0.1.3": {
|
|
20
|
+
"en": "change internal Base devices",
|
|
21
|
+
"de": "änderung intern Basisgeräte",
|
|
22
|
+
"ru": "изменения Базовые устройства",
|
|
23
|
+
"pt": "mudança interna Dispositivos base",
|
|
24
|
+
"nl": "intern wijzigen Basisvoorzieningen",
|
|
25
|
+
"fr": "changement interne Dispositifs de base",
|
|
26
|
+
"it": "cambiamento interno Dispositivi di base",
|
|
27
|
+
"es": "cambio interno Dispositivos de base",
|
|
28
|
+
"pl": "zmiana wewnętrzna Urządzenia bazowe",
|
|
29
|
+
"uk": "змінити внутрішню Пристрої бази",
|
|
30
|
+
"zh-cn": "内部变化 基本设备"
|
|
31
|
+
},
|
|
6
32
|
"0.1.2": {
|
|
7
33
|
"en": "concept of config changed",
|
|
8
34
|
"de": "konzept von config geändert",
|
|
@@ -67,32 +93,6 @@
|
|
|
67
93
|
"pl": "zmiana obsługi konfiguracji standardowych",
|
|
68
94
|
"uk": "змінено Обробка стандартних конфігурацій",
|
|
69
95
|
"zh-cn": "更改标准配置的处理"
|
|
70
|
-
},
|
|
71
|
-
"0.0.16": {
|
|
72
|
-
"en": "romeve reacheble object directory / improoved object === NULL",
|
|
73
|
-
"de": "romeve toucheble Objektverzeichnis / improoviertes Objekt == NULL",
|
|
74
|
-
"ru": "romeve reacheble object Directory / improoved object === NULL",
|
|
75
|
-
"pt": "romeve reacheble object diretório / objeto improoved - Sim",
|
|
76
|
-
"nl": "roeve bereikbare object directory / improoved object === NULL",
|
|
77
|
-
"fr": "romeve attele object directory / objet improvisé === NULL",
|
|
78
|
-
"it": "romeve catcheble object directory / oggetto improvato Traduzione:",
|
|
79
|
-
"es": "romeve reacheble objeto directorio / objeto improvisado === NULL",
|
|
80
|
-
"pl": "romeve Reacheble katalog obiektów / obiekt nieprofaworyzowany = = = NULL",
|
|
81
|
-
"uk": "romeve досягає каталогу об'єктів / об'єкт об'єкта ==== NULL",
|
|
82
|
-
"zh-cn": "romeve 达到对象目录/ 无法对象 QQ NULL 语言"
|
|
83
|
-
},
|
|
84
|
-
"0.0.15": {
|
|
85
|
-
"en": "bugfix chirpstack directory at downlink queued",
|
|
86
|
-
"de": "bugfix chirpstack verzeichnis bei downlink queued",
|
|
87
|
-
"ru": "bugfix chirpstack directory в очертаниях",
|
|
88
|
-
"pt": "bugfix chirpstack diretório no downlink queued",
|
|
89
|
-
"nl": "bugfix chirpstack directory bij downlink wachtrij",
|
|
90
|
-
"fr": "bugfix répertoire chirpstack au lien descendant en file d'attente",
|
|
91
|
-
"it": "bugfix chirpstack directory in downlink in coda",
|
|
92
|
-
"es": "bugfix chirpstack directorio en downlink queued",
|
|
93
|
-
"pl": "katalog chirpstock bugfix na downlink w kolejce",
|
|
94
|
-
"uk": "javascript licenses api веб-сайт go1.13.8",
|
|
95
|
-
"zh-cn": "下行链路队列时的 bugfix kirpstack 目录"
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
98
|
"title": "LoRaWAN",
|
|
@@ -212,9 +212,9 @@ class directorieshandlerClass {
|
|
|
212
212
|
try{
|
|
213
213
|
// Select search in case of origin
|
|
214
214
|
switch(this.adapter.config.origin){
|
|
215
|
-
case
|
|
215
|
+
case this.adapter.origin.ttn:
|
|
216
216
|
return await this.getTtnAttributValue(topic,message,resolvetype);
|
|
217
|
-
case
|
|
217
|
+
case this.adapter.origin.chirpstack:
|
|
218
218
|
return await this.getChirpstackAttributValue(topic,message,resolvetype);
|
|
219
219
|
}
|
|
220
220
|
}
|
|
@@ -232,9 +232,9 @@ class directorieshandlerClass {
|
|
|
232
232
|
try{
|
|
233
233
|
// Select search in case of origin
|
|
234
234
|
switch(this.adapter.config.origin){
|
|
235
|
-
case
|
|
235
|
+
case this.adapter.origin.ttn:
|
|
236
236
|
return await this.getTtnObjectDirectory(topic,message,resolvetype);
|
|
237
|
-
case
|
|
237
|
+
case this.adapter.origin.chirpstack:
|
|
238
238
|
return await this.getChirpstackObjectDirectory(topic,message,resolvetype);
|
|
239
239
|
}
|
|
240
240
|
}
|
|
@@ -252,9 +252,9 @@ class directorieshandlerClass {
|
|
|
252
252
|
this.adapter.log.silly(`topic ${topic} is requested for resolveing`);
|
|
253
253
|
// Select in case of origin
|
|
254
254
|
switch(this.adapter.config.origin){
|
|
255
|
-
case
|
|
255
|
+
case this.adapter.origin.ttn:
|
|
256
256
|
return this.getTtnTopicResolved(topic);
|
|
257
|
-
case
|
|
257
|
+
case this.adapter.origin.chirpstack:
|
|
258
258
|
return this.getChirpstackTopicResolved(topic);
|
|
259
259
|
}
|
|
260
260
|
}
|
|
@@ -4,7 +4,10 @@ const { isDeepStrictEqual } = require("util");
|
|
|
4
4
|
class downlinkConfighandlerClass {
|
|
5
5
|
constructor(adapter) {
|
|
6
6
|
this.adapter = adapter;
|
|
7
|
-
this.
|
|
7
|
+
this.activeDownlinkConfigs = {};
|
|
8
|
+
this.internalDevices = {
|
|
9
|
+
baseDevice: "internalBaseDevice"
|
|
10
|
+
};
|
|
8
11
|
}
|
|
9
12
|
|
|
10
13
|
/*********************************************************************
|
|
@@ -18,13 +21,13 @@ class downlinkConfighandlerClass {
|
|
|
18
21
|
// Add standard downlink config
|
|
19
22
|
const internalDownlinks = this.getJsonArrayFromDirectoryfiles(`${this.adapter.adapterDir}/lib/modules/downlinks`);
|
|
20
23
|
if(Array.isArray(internalDownlinks)){
|
|
21
|
-
for(const
|
|
22
|
-
this.addDownlinkConfigByType(
|
|
24
|
+
for(const downlinkConfig of Object.values(internalDownlinks)){
|
|
25
|
+
this.addDownlinkConfigByType(downlinkConfig,this.activeDownlinkConfigs);
|
|
23
26
|
}
|
|
24
27
|
}
|
|
25
28
|
// Add user downlink config
|
|
26
|
-
for(const
|
|
27
|
-
this.addDownlinkConfigByType(
|
|
29
|
+
for(const downlinkConfig of Object.values(this.adapter.config.downlinkConfig)){
|
|
30
|
+
this.addDownlinkConfigByType(downlinkConfig,this.activeDownlinkConfigs);
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
// Check active userconfig
|
|
@@ -32,10 +35,29 @@ class downlinkConfighandlerClass {
|
|
|
32
35
|
const obj = await this.adapter.getForeignObjectAsync(adapterId);
|
|
33
36
|
// generate the Config without own objects
|
|
34
37
|
const ownConfig = [];
|
|
35
|
-
for(const
|
|
36
|
-
ownConfig.push(JSON.parse(JSON.stringify(
|
|
38
|
+
for(const downlinkConfig of Object.values(this.activeDownlinkConfigs)){
|
|
39
|
+
ownConfig.push(JSON.parse(JSON.stringify(downlinkConfig)));
|
|
37
40
|
delete ownConfig[ownConfig.length - 1].downlinkState;
|
|
41
|
+
/*for(const downlinkParameter of Object.values(ownConfig[ownConfig.length - 1].downlinkParameter)){
|
|
42
|
+
//delete elements out of downlinkParameter Array
|
|
43
|
+
let parameterIndex = 0;
|
|
44
|
+
while(parameterIndex !== -1){
|
|
45
|
+
parameterIndex = downlinkParameter.findIndex((parameter) => {return parameter.notInConfig;});
|
|
46
|
+
if(parameterIndex !== -1){
|
|
47
|
+
downlinkParameter.splice(parameterIndex,1);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}*/
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Add internal base downlinks
|
|
54
|
+
const internalBaseDownlinks = this.getJsonArrayFromDirectoryfiles(`${this.adapter.adapterDir}/lib/modules/downlinks/baseDevices`);
|
|
55
|
+
if(Array.isArray(internalBaseDownlinks)){
|
|
56
|
+
for(const downlinkConfig of Object.values(internalBaseDownlinks)){
|
|
57
|
+
this.addDownlinkConfigByType(downlinkConfig,this.activeDownlinkConfigs);
|
|
58
|
+
}
|
|
38
59
|
}
|
|
60
|
+
|
|
39
61
|
// Sort Array by Alphabet
|
|
40
62
|
ownConfig.sort((a, b) => a.deviceType.toLowerCase() > b.deviceType.toLowerCase()?1:-1);
|
|
41
63
|
if(!isDeepStrictEqual(obj.native.downlinkConfig,ownConfig)){
|
|
@@ -50,14 +72,14 @@ class downlinkConfighandlerClass {
|
|
|
50
72
|
}
|
|
51
73
|
}
|
|
52
74
|
|
|
53
|
-
addDownlinkConfigByType(
|
|
75
|
+
addDownlinkConfigByType(downlinkConfig,config){
|
|
54
76
|
const activeFunction = "addDownlinkConfigByType";
|
|
55
77
|
try{
|
|
56
78
|
// override standard with userconfig
|
|
57
|
-
config[
|
|
58
|
-
config[
|
|
59
|
-
for(const downlinkParameter of Object.values(
|
|
60
|
-
config[
|
|
79
|
+
config[downlinkConfig.deviceType] = downlinkConfig;
|
|
80
|
+
config[downlinkConfig.deviceType].downlinkState = {};
|
|
81
|
+
for(const downlinkParameter of Object.values(downlinkConfig.downlinkParameter)){
|
|
82
|
+
config[downlinkConfig.deviceType].downlinkState[downlinkParameter.name] = downlinkParameter;
|
|
61
83
|
}
|
|
62
84
|
}
|
|
63
85
|
catch(error){
|
|
@@ -89,15 +111,14 @@ class downlinkConfighandlerClass {
|
|
|
89
111
|
try{
|
|
90
112
|
let foundMatch = "";
|
|
91
113
|
let foundLength = 0;
|
|
92
|
-
for(const deviceType in this.
|
|
93
|
-
if((deviceType === "all" || changeInfo.deviceType.indexOf(deviceType) === 0) && deviceType.length > foundLength){
|
|
114
|
+
for(const deviceType in this.activeDownlinkConfigs){
|
|
115
|
+
if((deviceType === "all" || deviceType === this.internalDevices.baseDevice || changeInfo.deviceType.indexOf(deviceType) === 0) && deviceType.length > foundLength){
|
|
94
116
|
foundMatch = deviceType;
|
|
95
|
-
if(deviceType !== "all"){
|
|
117
|
+
if(deviceType !== "all" && deviceType !== this.internalDevices.baseDevice){
|
|
96
118
|
foundLength = deviceType.length;
|
|
97
119
|
}
|
|
98
120
|
}
|
|
99
121
|
}
|
|
100
|
-
|
|
101
122
|
if(foundMatch !== ""){
|
|
102
123
|
return foundMatch;
|
|
103
124
|
}
|
|
@@ -110,17 +131,17 @@ class downlinkConfighandlerClass {
|
|
|
110
131
|
}
|
|
111
132
|
}
|
|
112
133
|
|
|
113
|
-
|
|
114
|
-
const activeFunction = "
|
|
134
|
+
getDownlinkParameter(changeInfo,options){
|
|
135
|
+
const activeFunction = "getDownlinkParameter";
|
|
115
136
|
this.adapter.log.silly(`the downlinkconfig is requested for the following changeinfo: ${JSON.stringify(changeInfo)}`);
|
|
116
137
|
try{
|
|
117
138
|
let downlinkConfig = undefined;
|
|
118
139
|
let foundLength = 0;
|
|
119
|
-
for(const deviceType in this.
|
|
120
|
-
if((deviceType === "all" || changeInfo.deviceType.indexOf(deviceType) === 0) && deviceType.length > foundLength){
|
|
121
|
-
if(this.
|
|
122
|
-
downlinkConfig = this.
|
|
123
|
-
if(deviceType !== "all"){
|
|
140
|
+
for(const deviceType in this.activeDownlinkConfigs){
|
|
141
|
+
if((deviceType === "all" || deviceType === this.internalDevices.baseDevice || changeInfo.deviceType.indexOf(deviceType) === 0) && deviceType.length > foundLength){
|
|
142
|
+
if(this.activeDownlinkConfigs[deviceType].downlinkState[changeInfo.changedState]){
|
|
143
|
+
downlinkConfig = this.activeDownlinkConfigs[deviceType].downlinkState[changeInfo.changedState];
|
|
144
|
+
if(deviceType !== "all" && deviceType !== this.internalDevices.baseDevice){
|
|
124
145
|
foundLength = deviceType.length;
|
|
125
146
|
}
|
|
126
147
|
}
|
|
@@ -140,7 +161,7 @@ class downlinkConfighandlerClass {
|
|
|
140
161
|
}
|
|
141
162
|
}
|
|
142
163
|
else{
|
|
143
|
-
this.adapter.log.warn(`${activeFunction}: no
|
|
164
|
+
this.adapter.log.warn(`${activeFunction}: no downlinkParameter found: deviceType: ${changeInfo.deviceType} - changed state: ${changeInfo.changedState}`);
|
|
144
165
|
}
|
|
145
166
|
}
|
|
146
167
|
}
|
|
@@ -156,13 +177,39 @@ class downlinkConfighandlerClass {
|
|
|
156
177
|
getDownlinkTopic(changeInfo,suffix){
|
|
157
178
|
// Select downlinktopic in case of origin
|
|
158
179
|
switch(this.adapter.config.origin){
|
|
159
|
-
case
|
|
180
|
+
case this.adapter.origin.ttn:
|
|
160
181
|
return this.getTtnDownlinkTopicFromDirektory(changeInfo,suffix);
|
|
161
|
-
case
|
|
182
|
+
case this.adapter.origin.chirpstack:
|
|
162
183
|
return this.getChirpstackDownlinkTopicFromDirektory(changeInfo,suffix);
|
|
163
184
|
}
|
|
164
185
|
}
|
|
165
186
|
|
|
187
|
+
/*********************************************************************
|
|
188
|
+
* *********************** Topicsuffix *****************************
|
|
189
|
+
* ******************************************************************/
|
|
190
|
+
|
|
191
|
+
getDownlinkTopicSuffix(state){
|
|
192
|
+
const activeFunction = "getDownlinkTopicSuffix";
|
|
193
|
+
try{
|
|
194
|
+
const replace = "replace";
|
|
195
|
+
switch(this.adapter.config.origin){
|
|
196
|
+
case this.adapter.origin.ttn:
|
|
197
|
+
switch(state){
|
|
198
|
+
case replace:
|
|
199
|
+
return "/down/replace";
|
|
200
|
+
|
|
201
|
+
default:
|
|
202
|
+
return "/down/push";
|
|
203
|
+
}
|
|
204
|
+
case this.adapter.origin.chirpstack:
|
|
205
|
+
return "/down";
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
catch(error){
|
|
209
|
+
this.adapter.log.error(`error at ${activeFunction}: ` + error);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
166
213
|
/*********************************************************************
|
|
167
214
|
* ************************** Downlink *******************************
|
|
168
215
|
* ******************************************************************/
|
|
@@ -171,9 +218,9 @@ class downlinkConfighandlerClass {
|
|
|
171
218
|
// Select downlink in case of origin
|
|
172
219
|
this.adapter.log.silly(`the downlink for the changeinfo ${JSON.stringify(changeInfo)} is requested`);
|
|
173
220
|
switch(this.adapter.config.origin){
|
|
174
|
-
case
|
|
221
|
+
case this.adapter.origin.ttn:
|
|
175
222
|
return this.getTtnDownlink(downlinkConfig,payloadInHex);
|
|
176
|
-
case
|
|
223
|
+
case this.adapter.origin.chirpstack:
|
|
177
224
|
return this.getChirpstackDownlink(downlinkConfig,payloadInHex,changeInfo);
|
|
178
225
|
}
|
|
179
226
|
}
|
|
@@ -182,59 +229,59 @@ class downlinkConfighandlerClass {
|
|
|
182
229
|
* ******************* Calculation of payload ************************
|
|
183
230
|
* ******************************************************************/
|
|
184
231
|
|
|
185
|
-
calculatePayloadInHex(
|
|
232
|
+
calculatePayloadInHex(downlinkParameter,state){
|
|
186
233
|
// declare pyaload variable
|
|
187
234
|
this.adapter.log.silly(`the payload will be calculated`);
|
|
188
235
|
let payloadInHex = "";
|
|
189
236
|
let multipliedVal = 0;
|
|
190
237
|
//Check type
|
|
191
|
-
if(
|
|
192
|
-
payloadInHex =
|
|
238
|
+
if(downlinkParameter.type === "button"){
|
|
239
|
+
payloadInHex = downlinkParameter.onClick;
|
|
193
240
|
}
|
|
194
|
-
else if(
|
|
241
|
+
else if(downlinkParameter.type === "boolean"){
|
|
195
242
|
if(state.val){
|
|
196
|
-
payloadInHex =
|
|
243
|
+
payloadInHex = downlinkParameter.on;
|
|
197
244
|
}
|
|
198
245
|
else{
|
|
199
|
-
payloadInHex =
|
|
246
|
+
payloadInHex = downlinkParameter.off;
|
|
200
247
|
}
|
|
201
248
|
}
|
|
202
249
|
else{
|
|
203
250
|
let numberOfDiggits = 0;
|
|
204
251
|
let zeroDiggits = "";
|
|
205
252
|
let resultAfterdecimalPlaces = 0;
|
|
206
|
-
switch(
|
|
253
|
+
switch(downlinkParameter.type){
|
|
207
254
|
case "number":
|
|
208
|
-
if(
|
|
209
|
-
const expotentialFactor = Math.pow(10,
|
|
255
|
+
if(downlinkParameter.decimalPlaces){
|
|
256
|
+
const expotentialFactor = Math.pow(10,downlinkParameter.decimalPlaces);
|
|
210
257
|
const StateWithExotetialFactor = Math.trunc(state.val * expotentialFactor);
|
|
211
258
|
resultAfterdecimalPlaces = StateWithExotetialFactor / expotentialFactor;
|
|
212
259
|
}
|
|
213
260
|
else{
|
|
214
261
|
resultAfterdecimalPlaces = Math.trunc(state.val);
|
|
215
262
|
}
|
|
216
|
-
multipliedVal = resultAfterdecimalPlaces *
|
|
263
|
+
multipliedVal = resultAfterdecimalPlaces * downlinkParameter.multiplyfaktor;
|
|
217
264
|
payloadInHex = multipliedVal.toString(16).toUpperCase();
|
|
218
|
-
numberOfDiggits =
|
|
265
|
+
numberOfDiggits = downlinkParameter.lengthInByte * 2;
|
|
219
266
|
for(let index = 1; index <= numberOfDiggits; index++){
|
|
220
267
|
zeroDiggits += "0";
|
|
221
268
|
}
|
|
222
269
|
payloadInHex = (zeroDiggits + payloadInHex).slice(-numberOfDiggits);
|
|
223
|
-
payloadInHex =
|
|
270
|
+
payloadInHex = downlinkParameter.front + payloadInHex + downlinkParameter.end;
|
|
224
271
|
break;
|
|
225
272
|
|
|
226
273
|
case "ascii":
|
|
227
274
|
payloadInHex = Buffer.from(state.val).toString("hex").toUpperCase();
|
|
228
|
-
numberOfDiggits =
|
|
275
|
+
numberOfDiggits = downlinkParameter.lengthInByte * 2;
|
|
229
276
|
for(let index = 1; index <= numberOfDiggits; index++){
|
|
230
277
|
zeroDiggits += "0";
|
|
231
278
|
}
|
|
232
279
|
payloadInHex = (zeroDiggits + payloadInHex).slice(-numberOfDiggits);
|
|
233
|
-
payloadInHex =
|
|
280
|
+
payloadInHex = downlinkParameter.front + payloadInHex + downlinkParameter.end;
|
|
234
281
|
break;
|
|
235
282
|
|
|
236
283
|
case "string":
|
|
237
|
-
payloadInHex =
|
|
284
|
+
payloadInHex = downlinkParameter.front + state.val + downlinkParameter.end;
|
|
238
285
|
payloadInHex = Buffer.from(payloadInHex).toString("hex").toUpperCase();
|
|
239
286
|
break;
|
|
240
287
|
}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"confirmed": true,
|
|
15
15
|
"front": "030111",
|
|
16
16
|
"end": "11",
|
|
17
|
-
"
|
|
17
|
+
"lengthInByte": 1,
|
|
18
18
|
"on": "030111",
|
|
19
19
|
"off": "030011",
|
|
20
20
|
"multiplyfaktor": "1",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"confirmed": false,
|
|
30
30
|
"front": "01",
|
|
31
31
|
"end": "",
|
|
32
|
-
"
|
|
32
|
+
"lengthInByte": 3,
|
|
33
33
|
"on": "11",
|
|
34
34
|
"off": "11",
|
|
35
35
|
"multiplyfaktor": 60,
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"confirmed": true,
|
|
45
45
|
"front": "03",
|
|
46
46
|
"end": "11",
|
|
47
|
-
"
|
|
47
|
+
"lengthInByte": 1,
|
|
48
48
|
"on": "031101",
|
|
49
49
|
"off": "031100",
|
|
50
50
|
"multiplyfaktor": "1",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"confirmed": false,
|
|
60
60
|
"front": "03",
|
|
61
61
|
"end": "11",
|
|
62
|
-
"
|
|
62
|
+
"lengthInByte": 1,
|
|
63
63
|
"on": "2104",
|
|
64
64
|
"off": "2100",
|
|
65
65
|
"multiplyfaktor": "1",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"confirmed": true,
|
|
75
75
|
"front": "03",
|
|
76
76
|
"end": "11",
|
|
77
|
-
"
|
|
77
|
+
"lengthInByte": 1,
|
|
78
78
|
"on": "02011111",
|
|
79
79
|
"off": "02001111",
|
|
80
80
|
"multiplyfaktor": "1",
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"confirmed": true,
|
|
90
90
|
"front": "03",
|
|
91
91
|
"end": "11",
|
|
92
|
-
"
|
|
92
|
+
"lengthInByte": 1,
|
|
93
93
|
"on": "02110111",
|
|
94
94
|
"off": "02110011",
|
|
95
95
|
"multiplyfaktor": "1",
|
|
@@ -104,7 +104,7 @@
|
|
|
104
104
|
"confirmed": false,
|
|
105
105
|
"front": "03",
|
|
106
106
|
"end": "11",
|
|
107
|
-
"
|
|
107
|
+
"lengthInByte": 1,
|
|
108
108
|
"on": "A90001111107D0",
|
|
109
109
|
"off": "",
|
|
110
110
|
"multiplyfaktor": "1",
|
|
@@ -119,7 +119,7 @@
|
|
|
119
119
|
"confirmed": true,
|
|
120
120
|
"front": "03",
|
|
121
121
|
"end": "11",
|
|
122
|
-
"
|
|
122
|
+
"lengthInByte": 1,
|
|
123
123
|
"on": "050021EA60",
|
|
124
124
|
"off": "",
|
|
125
125
|
"multiplyfaktor": "1",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"confirmed": false,
|
|
15
15
|
"front": "01",
|
|
16
16
|
"end": "",
|
|
17
|
-
"
|
|
17
|
+
"lengthInByte": 3,
|
|
18
18
|
"on": "",
|
|
19
19
|
"off": "",
|
|
20
20
|
"multiplyfaktor": 60,
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"confirmed": false,
|
|
29
29
|
"front": "",
|
|
30
30
|
"end": "",
|
|
31
|
-
"
|
|
31
|
+
"lengthInByte": 2,
|
|
32
32
|
"on": "",
|
|
33
33
|
"off": "",
|
|
34
34
|
"onClick": "04FF",
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"deviceType":"LBR-BSM-0404",
|
|
4
|
+
"sendWithUplink":"disabled",
|
|
5
|
+
"port":2,
|
|
6
|
+
"priority":"NORMAL",
|
|
7
|
+
"confirmed":false,
|
|
8
|
+
"downlinkParameter":[
|
|
9
|
+
{
|
|
10
|
+
"name": "Cron",
|
|
11
|
+
"port": 128,
|
|
12
|
+
"priority": "NORMAL",
|
|
13
|
+
"type": "string",
|
|
14
|
+
"confirmed": true,
|
|
15
|
+
"front": "SMeasureCron=",
|
|
16
|
+
"end": "",
|
|
17
|
+
"lengthInByte": 2,
|
|
18
|
+
"on": "01",
|
|
19
|
+
"off": "11",
|
|
20
|
+
"onClick": "030111",
|
|
21
|
+
"multiplyfaktor": "1",
|
|
22
|
+
"unit": ""
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"name": "Get config parameter",
|
|
26
|
+
"port": 128,
|
|
27
|
+
"priority": "NORMAL",
|
|
28
|
+
"type": "string",
|
|
29
|
+
"confirmed": false,
|
|
30
|
+
"front": "g",
|
|
31
|
+
"end": "",
|
|
32
|
+
"lengthInByte": 2,
|
|
33
|
+
"on": "01",
|
|
34
|
+
"off": "11",
|
|
35
|
+
"onClick": "g",
|
|
36
|
+
"multiplyfaktor": "1",
|
|
37
|
+
"unit": ""
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "Request firmware and version",
|
|
41
|
+
"port": 128,
|
|
42
|
+
"priority": "NORMAL",
|
|
43
|
+
"type": "button",
|
|
44
|
+
"confirmed": true,
|
|
45
|
+
"front": "03",
|
|
46
|
+
"end": "11",
|
|
47
|
+
"lengthInByte": 2,
|
|
48
|
+
"on": "01",
|
|
49
|
+
"off": "11",
|
|
50
|
+
"onClick": "3F",
|
|
51
|
+
"multiplyfaktor": "1",
|
|
52
|
+
"unit": ""
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"name": "BSM_Relais1",
|
|
56
|
+
"port": 4,
|
|
57
|
+
"priority": "NORMAL",
|
|
58
|
+
"type": "boolean",
|
|
59
|
+
"confirmed": true,
|
|
60
|
+
"front": "03",
|
|
61
|
+
"end": "11",
|
|
62
|
+
"lengthInByte": 2,
|
|
63
|
+
"on": "0601050000FF00",
|
|
64
|
+
"off": "06010500000000",
|
|
65
|
+
"onClick": "030111",
|
|
66
|
+
"multiplyfaktor": "1",
|
|
67
|
+
"unit": ""
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"name": "BSM_Relais2",
|
|
71
|
+
"port": 4,
|
|
72
|
+
"priority": "NORMAL",
|
|
73
|
+
"type": "boolean",
|
|
74
|
+
"confirmed": true,
|
|
75
|
+
"front": "03",
|
|
76
|
+
"end": "11",
|
|
77
|
+
"lengthInByte": 2,
|
|
78
|
+
"on": "0601050001FF00",
|
|
79
|
+
"off": "06010500010000",
|
|
80
|
+
"onClick": "030111",
|
|
81
|
+
"multiplyfaktor": "1",
|
|
82
|
+
"unit": ""
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"name": "BSM_Relais3",
|
|
86
|
+
"port": 4,
|
|
87
|
+
"priority": "NORMAL",
|
|
88
|
+
"type": "boolean",
|
|
89
|
+
"confirmed": true,
|
|
90
|
+
"front": "03",
|
|
91
|
+
"end": "11",
|
|
92
|
+
"lengthInByte": 2,
|
|
93
|
+
"on": "0601050002FF00",
|
|
94
|
+
"off": "06010500020000",
|
|
95
|
+
"onClick": "030111",
|
|
96
|
+
"multiplyfaktor": "1",
|
|
97
|
+
"unit": ""
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"name": "BSM_Relais4",
|
|
101
|
+
"port": 4,
|
|
102
|
+
"priority": "NORMAL",
|
|
103
|
+
"type": "boolean",
|
|
104
|
+
"confirmed": true,
|
|
105
|
+
"front": "03",
|
|
106
|
+
"end": "11",
|
|
107
|
+
"lengthInByte": 2,
|
|
108
|
+
"on": "0601050003FF00",
|
|
109
|
+
"off": "06010500030000",
|
|
110
|
+
"onClick": "030111",
|
|
111
|
+
"multiplyfaktor": "1",
|
|
112
|
+
"unit": "",
|
|
113
|
+
"decimalPlaces": "1"
|
|
114
|
+
}
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
]
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"deviceType":"Vicki",
|
|
4
|
+
"sendWithUplink":"disabled",
|
|
5
|
+
"port":2,
|
|
6
|
+
"priority":"NORMAL",
|
|
7
|
+
"confirmed":false,
|
|
8
|
+
"downlinkParameter":[
|
|
9
|
+
{
|
|
10
|
+
"name": "Vicki_ext_Temperatur",
|
|
11
|
+
"port": 1,
|
|
12
|
+
"priority": "NORMAL",
|
|
13
|
+
"type": "number",
|
|
14
|
+
"confirmed": false,
|
|
15
|
+
"front": "3C",
|
|
16
|
+
"end": "0D0218",
|
|
17
|
+
"lengthInByte": 2,
|
|
18
|
+
"on": "01",
|
|
19
|
+
"off": "11",
|
|
20
|
+
"onClick": "030111",
|
|
21
|
+
"multiplyfaktor": 10,
|
|
22
|
+
"unit": "Grad",
|
|
23
|
+
"decimalPlaces": 1
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"name": "Vicki_Interval",
|
|
27
|
+
"port": 1,
|
|
28
|
+
"priority": "NORMAL",
|
|
29
|
+
"type": "number",
|
|
30
|
+
"confirmed": false,
|
|
31
|
+
"front": "02",
|
|
32
|
+
"end": "12",
|
|
33
|
+
"lengthInByte": 2,
|
|
34
|
+
"on": "01",
|
|
35
|
+
"off": "11",
|
|
36
|
+
"onClick": "030111",
|
|
37
|
+
"multiplyfaktor": "1",
|
|
38
|
+
"unit": "Minuten",
|
|
39
|
+
"deviceType": "Vicki"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"name": "Vicki_Target_Temperature",
|
|
43
|
+
"port": 1,
|
|
44
|
+
"priority": "NORMAL",
|
|
45
|
+
"type": "number",
|
|
46
|
+
"confirmed": false,
|
|
47
|
+
"front": "0E",
|
|
48
|
+
"end": "",
|
|
49
|
+
"lengthInByte": 1,
|
|
50
|
+
"on": "01",
|
|
51
|
+
"off": "11",
|
|
52
|
+
"onClick": "030111",
|
|
53
|
+
"multiplyfaktor": "1",
|
|
54
|
+
"unit": "Grad",
|
|
55
|
+
"decimalPlaces": 0
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"name": "Vicki_Max_Temperature",
|
|
59
|
+
"port": 1,
|
|
60
|
+
"priority": "NORMAL",
|
|
61
|
+
"type": "number",
|
|
62
|
+
"confirmed": false,
|
|
63
|
+
"front": "0805",
|
|
64
|
+
"end": "15",
|
|
65
|
+
"lengthInByte": 1,
|
|
66
|
+
"on": "01",
|
|
67
|
+
"off": "11",
|
|
68
|
+
"onClick": "030111",
|
|
69
|
+
"multiplyfaktor": "1",
|
|
70
|
+
"unit": "Grad",
|
|
71
|
+
"deviceType": "Vicki"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"name": "Vicki_Get_Infos",
|
|
75
|
+
"port": 1,
|
|
76
|
+
"priority": "NORMAL",
|
|
77
|
+
"type": "button",
|
|
78
|
+
"confirmed": false,
|
|
79
|
+
"front": "03",
|
|
80
|
+
"end": "11",
|
|
81
|
+
"lengthInByte": 2,
|
|
82
|
+
"on": "01",
|
|
83
|
+
"off": "11",
|
|
84
|
+
"onClick": "041215184634",
|
|
85
|
+
"multiplyfaktor": "1",
|
|
86
|
+
"unit": "",
|
|
87
|
+
"deviceType": "Vicki"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"name": "Vicki_Motor_Callibration",
|
|
91
|
+
"port": 1,
|
|
92
|
+
"priority": "NORMAL",
|
|
93
|
+
"type": "button",
|
|
94
|
+
"confirmed": false,
|
|
95
|
+
"front": "03",
|
|
96
|
+
"end": "11",
|
|
97
|
+
"lengthInByte": 2,
|
|
98
|
+
"on": "01",
|
|
99
|
+
"off": "11",
|
|
100
|
+
"onClick": "03",
|
|
101
|
+
"multiplyfaktor": "1",
|
|
102
|
+
"unit": "",
|
|
103
|
+
"deviceType": "Vicki"
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"name": "Vicki_Child_Lock",
|
|
107
|
+
"port": 1,
|
|
108
|
+
"priority": "NORMAL",
|
|
109
|
+
"type": "boolean",
|
|
110
|
+
"confirmed": false,
|
|
111
|
+
"front": "03",
|
|
112
|
+
"end": "11",
|
|
113
|
+
"lengthInByte": 2,
|
|
114
|
+
"on": "070114",
|
|
115
|
+
"off": "070014",
|
|
116
|
+
"onClick": "030111",
|
|
117
|
+
"multiplyfaktor": "1",
|
|
118
|
+
"unit": "",
|
|
119
|
+
"deviceType": "Vicki"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"name": "Vicki_Mode_2",
|
|
123
|
+
"port": 1,
|
|
124
|
+
"priority": "NORMAL",
|
|
125
|
+
"type": "boolean",
|
|
126
|
+
"confirmed": false,
|
|
127
|
+
"front": "03",
|
|
128
|
+
"end": "11",
|
|
129
|
+
"lengthInByte": 2,
|
|
130
|
+
"on": "0D02",
|
|
131
|
+
"off": "0D01",
|
|
132
|
+
"onClick": "030111",
|
|
133
|
+
"multiplyfaktor": "1",
|
|
134
|
+
"unit": "",
|
|
135
|
+
"decimalPlaces": "1"
|
|
136
|
+
}
|
|
137
|
+
]
|
|
138
|
+
}
|
|
139
|
+
]
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
[
|
|
2
2
|
{
|
|
3
|
-
"deviceType":"
|
|
3
|
+
"deviceType":"internalBaseDevice",
|
|
4
4
|
"sendWithUplink":"disabled",
|
|
5
5
|
"downlinkParameter":[
|
|
6
6
|
{
|
|
7
|
+
"notInConfig": true,
|
|
7
8
|
"name": "push",
|
|
8
9
|
"type": "json",
|
|
9
10
|
"deviceType": "all"
|
|
10
11
|
},
|
|
11
12
|
{
|
|
13
|
+
"notInConfig": true,
|
|
12
14
|
"name": "replace",
|
|
13
15
|
"type": "json",
|
|
14
16
|
"deviceType": "all"
|
|
15
17
|
}
|
|
16
18
|
]
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
+
}
|
|
19
20
|
]
|
|
@@ -14,10 +14,10 @@ class messagehandlerClass {
|
|
|
14
14
|
async handleMessage(topic,message){
|
|
15
15
|
// Select datahandling in case of origin
|
|
16
16
|
switch(this.adapter.config.origin){
|
|
17
|
-
case
|
|
17
|
+
case this.adapter.origin.ttn:
|
|
18
18
|
await this.handleTtnMessage(topic,message);
|
|
19
19
|
break;
|
|
20
|
-
case
|
|
20
|
+
case this.adapter.origin.chirpstack:
|
|
21
21
|
await this.handleChirpstackMessage(topic,message);
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -38,9 +38,10 @@ class messagehandlerClass {
|
|
|
38
38
|
for(const adapterObject of Object.values(adapterObjectsAtStart)){
|
|
39
39
|
if(adapterObject.type === "state" && (adapterObject._id.indexOf("downlink.control") !== -1)){
|
|
40
40
|
const changeInfo = await this.adapter.getChangeInfo(adapterObject._id);
|
|
41
|
-
const
|
|
42
|
-
if(!
|
|
41
|
+
const downlinkParameter = this.adapter.downlinkConfighandler.getDownlinkParameter(changeInfo,{startupCheck:true});
|
|
42
|
+
if(!downlinkParameter || this.stateForbidden(changeInfo.changedState)){
|
|
43
43
|
await this.adapter.delObjectAsync(this.adapter.removeNamespace(adapterObject._id));
|
|
44
|
+
this.adapter.log.debug(`${activeFunction}: the state ${changeInfo.changedState} was deleted out of ${changeInfo.objectStartDirectory}`);
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
}
|
|
@@ -62,14 +63,14 @@ class messagehandlerClass {
|
|
|
62
63
|
const changeInfo = await this.adapter.getChangeInfo(`${deviceStartdirectory}.fillDownlinkFolder`);
|
|
63
64
|
const foundLength = {};
|
|
64
65
|
//iterate downlinkDevice
|
|
65
|
-
for(const downlinkDevice in this.adapter.downlinkConfighandler.
|
|
66
|
+
for(const downlinkDevice in this.adapter.downlinkConfighandler.activeDownlinkConfigs){
|
|
66
67
|
// query for match deviceType
|
|
67
|
-
if((downlinkDevice === "all" || changeInfo.deviceType.indexOf(downlinkDevice) === 0)){
|
|
68
|
+
if((downlinkDevice === "all" || downlinkDevice === this.adapter.downlinkConfighandler.internalDevices.baseDevice || changeInfo.deviceType.indexOf(downlinkDevice) === 0)){
|
|
68
69
|
// iterate downlinkConfig
|
|
69
|
-
for(const downlinkConfig of Object.values(this.adapter.downlinkConfighandler.
|
|
70
|
+
for(const downlinkConfig of Object.values(this.adapter.downlinkConfighandler.activeDownlinkConfigs[downlinkDevice].downlinkState)){
|
|
70
71
|
this.adapter.log.silly(`the downlinkconfig ${JSON.stringify(downlinkConfig)}, will checked.`);
|
|
71
72
|
// check for forbidden states
|
|
72
|
-
if(this.stateForbidden(
|
|
73
|
+
if(this.stateForbidden(downlinkConfig.name)){
|
|
73
74
|
continue;
|
|
74
75
|
}
|
|
75
76
|
// Create found length if not defined
|
|
@@ -100,7 +101,7 @@ class messagehandlerClass {
|
|
|
100
101
|
},
|
|
101
102
|
native: {},
|
|
102
103
|
});
|
|
103
|
-
if(downlinkDevice !=="all"){
|
|
104
|
+
if(downlinkDevice !=="all" && downlinkDevice === this.adapter.downlinkConfighandler.internalDevices.baseDevice){
|
|
104
105
|
foundLength[downlinkConfig.name] = downlinkDevice.length;
|
|
105
106
|
}
|
|
106
107
|
}
|
|
@@ -115,9 +116,9 @@ class messagehandlerClass {
|
|
|
115
116
|
|
|
116
117
|
stateForbidden(stateName){
|
|
117
118
|
switch(this.adapter.config.origin){
|
|
118
|
-
case
|
|
119
|
+
case this.adapter.origin.ttn:
|
|
119
120
|
return false;
|
|
120
|
-
case
|
|
121
|
+
case this.adapter.origin.chirpstack:
|
|
121
122
|
return stateName === "replace";
|
|
122
123
|
}
|
|
123
124
|
}
|
|
@@ -53,9 +53,9 @@ class mqttClientClass {
|
|
|
53
53
|
|
|
54
54
|
getSubscribtionArray(){
|
|
55
55
|
switch(this.adapter.config.origin){
|
|
56
|
-
case
|
|
56
|
+
case this.adapter.origin.ttn:
|
|
57
57
|
return ["v3/+/devices/+/up","v3/+/devices/+/down/#"];
|
|
58
|
-
case
|
|
58
|
+
case this.adapter.origin.chirpstack:
|
|
59
59
|
return ["application/+/device/+/event/up","application/+/device/+/command/down"];
|
|
60
60
|
}
|
|
61
61
|
}
|
package/main.js
CHANGED
|
@@ -26,6 +26,11 @@ class Lorawan extends utils.Adapter {
|
|
|
26
26
|
// this.on("objectChange", this.onObjectChange.bind(this));
|
|
27
27
|
// this.on("message", this.onMessage.bind(this));
|
|
28
28
|
this.on("unload", this.onUnload.bind(this));
|
|
29
|
+
|
|
30
|
+
this.origin = {
|
|
31
|
+
ttn: "ttn",
|
|
32
|
+
chirpstack: "chirpstack"
|
|
33
|
+
};
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
/**
|
|
@@ -34,7 +39,6 @@ class Lorawan extends utils.Adapter {
|
|
|
34
39
|
async onReady() {
|
|
35
40
|
const activeFunction = "onReady";
|
|
36
41
|
try{
|
|
37
|
-
this.log.warn("START");
|
|
38
42
|
// create downlinkConfigs
|
|
39
43
|
this.downlinkConfighandler = new downlinkConfighandlerClass(this);
|
|
40
44
|
|
|
@@ -56,7 +60,7 @@ class Lorawan extends utils.Adapter {
|
|
|
56
60
|
this.subscribeStatesAsync("*downlink.control.*");
|
|
57
61
|
this.subscribeStatesAsync("*.logAvailableConfignames");
|
|
58
62
|
this.log.debug(`the adapter start with the config: ${JSON.stringify(this.config)}.`);
|
|
59
|
-
this.log.silly(`the whole reacable downlinkconfigs are: ${JSON.stringify(this.downlinkConfighandler.
|
|
63
|
+
this.log.silly(`the whole reacable downlinkconfigs are: ${JSON.stringify(this.downlinkConfighandler.activeDownlinkConfigs)}`);
|
|
60
64
|
|
|
61
65
|
/*setTimeout(async () => {
|
|
62
66
|
await this.startSimulation();
|
|
@@ -139,55 +143,25 @@ class Lorawan extends utils.Adapter {
|
|
|
139
143
|
this.log.silly(`the state ${id} has changed to ${state.val}.`);
|
|
140
144
|
// get information of the changing state
|
|
141
145
|
const changeInfo = await this.getChangeInfo(id,{withBestMatch:true});
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
this.setStateAsync(id,state.val,true);
|
|
148
|
-
}
|
|
149
|
-
else if(changeInfo?.changedState === "replace"){
|
|
150
|
-
appending = "replace";
|
|
151
|
-
const downlinkTopic = this.downlinkConfighandler?.getDownlinkTopic(changeInfo,`/down/${appending}`);
|
|
152
|
-
await this.sendDownlink(downlinkTopic,state.val,changeInfo);
|
|
153
|
-
this.setStateAsync(id,state.val,true);
|
|
154
|
-
}
|
|
155
|
-
else{
|
|
156
|
-
const downlinkTopic = this.downlinkConfighandler?.getDownlinkTopic(changeInfo,`/down/${appending}`);
|
|
157
|
-
const downlinkConfig = this.downlinkConfighandler?.getDownlinkConfig(changeInfo);
|
|
158
|
-
if(downlinkConfig !== undefined){
|
|
159
|
-
const payloadInHex = this.downlinkConfighandler?.calculatePayloadInHex(downlinkConfig,state);
|
|
160
|
-
await this.writeNextSend(changeInfo,payloadInHex);
|
|
161
|
-
if(!changeInfo?.bestMatchForDeviceType || this.downlinkConfighandler?.activeDownlinkDeviceConfigs[changeInfo.bestMatchForDeviceType].sendWithUplink === "disabled"){
|
|
162
|
-
const downlink = this.downlinkConfighandler?.getDownlink(downlinkConfig,payloadInHex,changeInfo);
|
|
163
|
-
if(downlink !== undefined){
|
|
164
|
-
await this.sendDownlink(downlinkTopic,JSON.stringify(downlink),changeInfo);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
this.setStateAsync(id,state.val,true);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
146
|
+
const suffix = this.downlinkConfighandler?.getDownlinkTopicSuffix(changeInfo?.changedState);
|
|
147
|
+
if(changeInfo?.changedState === "push" || changeInfo?.changedState === "replace"){
|
|
148
|
+
const downlinkTopic = this.downlinkConfighandler?.getDownlinkTopic(changeInfo,suffix);
|
|
149
|
+
await this.sendDownlink(downlinkTopic,state.val);
|
|
150
|
+
this.setStateAsync(id,state.val,true);
|
|
170
151
|
}
|
|
171
|
-
else
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
this.
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
const payloadInHex = this.downlinkConfighandler?.calculatePayloadInHex(downlinkConfig,state);
|
|
182
|
-
await this.writeNextSend(changeInfo,payloadInHex);
|
|
183
|
-
if(!changeInfo?.bestMatchForDeviceType || this.downlinkConfighandler?.activeDownlinkDeviceConfigs[changeInfo.bestMatchForDeviceType].sendWithUplink === "disabled"){
|
|
184
|
-
const downlink = this.downlinkConfighandler?.getDownlink(downlinkConfig,payloadInHex,changeInfo);
|
|
185
|
-
if(downlink !== undefined){
|
|
186
|
-
await this.sendDownlink(downlinkTopic,JSON.stringify(downlink),changeInfo);
|
|
187
|
-
}
|
|
152
|
+
else{
|
|
153
|
+
const downlinkTopic = this.downlinkConfighandler?.getDownlinkTopic(changeInfo,suffix);
|
|
154
|
+
const downlinkParameter = this.downlinkConfighandler?.getDownlinkParameter(changeInfo);
|
|
155
|
+
if(downlinkParameter !== undefined){
|
|
156
|
+
const payloadInHex = this.downlinkConfighandler?.calculatePayloadInHex(downlinkParameter,state);
|
|
157
|
+
await this.writeNextSend(changeInfo,payloadInHex);
|
|
158
|
+
if(!changeInfo?.bestMatchForDeviceType || this.downlinkConfighandler?.activeDownlinkConfigs[changeInfo.bestMatchForDeviceType].sendWithUplink === "disabled"){
|
|
159
|
+
const downlink = this.downlinkConfighandler?.getDownlink(downlinkParameter,payloadInHex,changeInfo);
|
|
160
|
+
if(downlink !== undefined){
|
|
161
|
+
await this.sendDownlink(downlinkTopic,JSON.stringify(downlink),changeInfo);
|
|
188
162
|
}
|
|
189
|
-
this.setStateAsync(id,state.val,true);
|
|
190
163
|
}
|
|
164
|
+
this.setStateAsync(id,state.val,true);
|
|
191
165
|
}
|
|
192
166
|
}
|
|
193
167
|
}
|
|
@@ -201,8 +175,8 @@ class Lorawan extends utils.Adapter {
|
|
|
201
175
|
for(const adapterObject of Object.values(adapterObjects)){
|
|
202
176
|
if(adapterObject.type === "state" && (adapterObject._id.indexOf(`${changeInfo?.objectStartDirectory}.downlink.control`) !== -1)){
|
|
203
177
|
const changeInfo = await this.getChangeInfo(adapterObject._id);
|
|
204
|
-
const
|
|
205
|
-
if(!
|
|
178
|
+
const downlinkParameter = this.downlinkConfighandler?.getDownlinkParameter(changeInfo,{startupCheck:true});
|
|
179
|
+
if(!downlinkParameter){
|
|
206
180
|
await this.delObjectAsync(this.removeNamespace(adapterObject._id));
|
|
207
181
|
}
|
|
208
182
|
}
|
|
@@ -213,9 +187,11 @@ class Lorawan extends utils.Adapter {
|
|
|
213
187
|
else if(id.indexOf("logAvailableConfignames") !== -1){
|
|
214
188
|
this.log.info(`The following devicenames has an existing downlink-config`);
|
|
215
189
|
let index = 0;
|
|
216
|
-
for(const devicename in this.downlinkConfighandler?.
|
|
190
|
+
for(const devicename in this.downlinkConfighandler?.activeDownlinkConfigs){
|
|
217
191
|
index++;
|
|
218
|
-
this.
|
|
192
|
+
if(devicename !== this.downlinkConfighandler.internalDevices.baseDevice){
|
|
193
|
+
this.log.info(`Device ${index}: ${devicename}`);
|
|
194
|
+
}
|
|
219
195
|
}
|
|
220
196
|
this.setStateAsync(id,state.val,true);
|
|
221
197
|
}
|
|
@@ -235,21 +211,12 @@ class Lorawan extends utils.Adapter {
|
|
|
235
211
|
try{
|
|
236
212
|
this.log.silly(`Check for send downlink with uplink.`);
|
|
237
213
|
const changeInfo = await this.getChangeInfo(id,{withBestMatch:true});
|
|
238
|
-
if(changeInfo && changeInfo.bestMatchForDeviceType && this.downlinkConfighandler?.
|
|
214
|
+
if(changeInfo && changeInfo.bestMatchForDeviceType && this.downlinkConfighandler?.activeDownlinkConfigs[changeInfo.bestMatchForDeviceType].sendWithUplink !== "disabled"){
|
|
239
215
|
const nextSend = await this.getNextSend(changeInfo?.objectStartDirectory);
|
|
240
216
|
if(nextSend?.val !== "0"){
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
appending = `/down/push`;
|
|
245
|
-
break;
|
|
246
|
-
|
|
247
|
-
case "chirpstack":
|
|
248
|
-
appending = `/down`;
|
|
249
|
-
break;
|
|
250
|
-
}
|
|
251
|
-
const downlinkTopic = this.downlinkConfighandler?.getDownlinkTopic(changeInfo,appending);
|
|
252
|
-
const downlinkConfig = this.downlinkConfighandler?.activeDownlinkDeviceConfigs[changeInfo.bestMatchForDeviceType];
|
|
217
|
+
const suffix = this.downlinkConfighandler?.getDownlinkTopicSuffix("push");
|
|
218
|
+
const downlinkTopic = this.downlinkConfighandler?.getDownlinkTopic(changeInfo,suffix);
|
|
219
|
+
const downlinkConfig = this.downlinkConfighandler?.activeDownlinkConfigs[changeInfo.bestMatchForDeviceType];
|
|
253
220
|
const downlink = this.downlinkConfighandler?.getDownlink(downlinkConfig,nextSend?.val,changeInfo);
|
|
254
221
|
if(downlink !== undefined){
|
|
255
222
|
await this.sendDownlink(downlinkTopic,JSON.stringify(downlink),changeInfo);
|
|
@@ -269,7 +236,7 @@ class Lorawan extends utils.Adapter {
|
|
|
269
236
|
|
|
270
237
|
async writeNextSend(changeInfo,payloadInHex){
|
|
271
238
|
const idFolderNextSend = `${changeInfo.objectStartDirectory}.${this.messagehandler?.directoryhandler.reachableSubfolders.downlinkNextSend}`;
|
|
272
|
-
if(changeInfo.bestMatchForDeviceType && this.downlinkConfighandler?.
|
|
239
|
+
if(changeInfo.bestMatchForDeviceType && this.downlinkConfighandler?.activeDownlinkConfigs[changeInfo.bestMatchForDeviceType].sendWithUplink === "enabled & collect"){
|
|
273
240
|
const nextSend = await this.getStateAsync(`${idFolderNextSend}.hex`);
|
|
274
241
|
if(nextSend?.val !== "0"){
|
|
275
242
|
payloadInHex = nextSend?.val + payloadInHex;
|
|
@@ -300,11 +267,11 @@ class Lorawan extends utils.Adapter {
|
|
|
300
267
|
}
|
|
301
268
|
let payload = "";
|
|
302
269
|
switch(this.config.origin){
|
|
303
|
-
case
|
|
270
|
+
case this.origin.ttn:
|
|
304
271
|
payload = downlink.downlinks[0].frm_payload;
|
|
305
272
|
break;
|
|
306
273
|
|
|
307
|
-
case
|
|
274
|
+
case this.origin.chirpstack:
|
|
308
275
|
payload = downlink.data;
|
|
309
276
|
break;
|
|
310
277
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.lorawan",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "converts the desired lora gateway data to a ioBroker structure",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "BenAhrdt",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@iobroker/adapter-core": "^3.0.4",
|
|
28
|
-
"mqtt": "^5.3.
|
|
28
|
+
"mqtt": "^5.3.5"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@alcalzone/release-script": "^3.7.0",
|
|
@@ -38,12 +38,12 @@
|
|
|
38
38
|
"@types/chai": "^4.3.11",
|
|
39
39
|
"@types/chai-as-promised": "^7.1.8",
|
|
40
40
|
"@types/mocha": "^10.0.6",
|
|
41
|
-
"@types/node": "^20.
|
|
41
|
+
"@types/node": "^20.11.14",
|
|
42
42
|
"@types/proxyquire": "^1.3.31",
|
|
43
|
-
"@types/sinon": "^17.0.
|
|
43
|
+
"@types/sinon": "^17.0.3",
|
|
44
44
|
"@types/sinon-chai": "^3.2.12",
|
|
45
45
|
"chai-as-promised": "^7.1.1",
|
|
46
|
-
"chai": "^4.4.
|
|
46
|
+
"chai": "^4.4.1",
|
|
47
47
|
"eslint": "^8.56.0",
|
|
48
48
|
"mocha": "^10.2.0",
|
|
49
49
|
"proxyquire": "^2.1.3",
|