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 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
- "length": "Gesamtlänge",
38
- "lengthTooltip": "Geben Sie den Wert der gesamten Downlink-Nutzlast ein",
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
- "length": "overall length",
38
- "lengthTooltip": "insert the value of the whole downlink payload",
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
- "length": "longitud total",
38
- "lengthTooltip": "inserte el valor de toda la carga útil del enlace descendente",
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
- "length": "longueur totale",
38
- "lengthTooltip": "insérer la valeur de toute la charge utile de la liaison descendante",
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
- "length": "lunghezza complessiva",
38
- "lengthTooltip": "inserire il valore dell'intero payload del downlink",
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
- "length": "totale lengte",
38
- "lengthTooltip": "voer de waarde van de gehele downlink-payload in",
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
- "length": "całkowita długość",
38
- "lengthTooltip": "wstaw wartość całego ładunku łącza pobierającego",
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
- "length": "comprimento total",
38
- "lengthTooltip": "insira o valor de toda a carga útil do downlink",
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
- "length": "полная длина",
38
- "lengthTooltip": "вставьте значение всей полезной нагрузки нисходящей линии связи",
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
- "length": "Загальна довжина",
38
- "lengthTooltip": "вставте значення всього корисного навантаження низхідного каналу",
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
- "length": "总体长度",
38
- "lengthTooltip": "插入整个下行链路有效负载的值",
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": "插入您的值的单位",
@@ -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) return false; return true",
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": "length",
247
- "label": "length",
248
- "tooltip": "lengthTooltip",
249
- "default": 8,
250
- "min":2,
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.2",
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 "ttn":
215
+ case this.adapter.origin.ttn:
216
216
  return await this.getTtnAttributValue(topic,message,resolvetype);
217
- case "chirpstack":
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 "ttn":
235
+ case this.adapter.origin.ttn:
236
236
  return await this.getTtnObjectDirectory(topic,message,resolvetype);
237
- case "chirpstack":
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 "ttn":
255
+ case this.adapter.origin.ttn:
256
256
  return this.getTtnTopicResolved(topic);
257
- case "chirpstack":
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.activeDownlinkDeviceConfigs = {};
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 downlinkDeviceConfig of Object.values(internalDownlinks)){
22
- this.addDownlinkConfigByType(downlinkDeviceConfig,this.activeDownlinkDeviceConfigs);
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 downlinkDeviceConfig of Object.values(this.adapter.config.downlinkConfig)){
27
- this.addDownlinkConfigByType(downlinkDeviceConfig,this.activeDownlinkDeviceConfigs);
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 downlinkDeviceConfig of Object.values(this.activeDownlinkDeviceConfigs)){
36
- ownConfig.push(JSON.parse(JSON.stringify(downlinkDeviceConfig)));
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(downlinkDeviceConfig,config){
75
+ addDownlinkConfigByType(downlinkConfig,config){
54
76
  const activeFunction = "addDownlinkConfigByType";
55
77
  try{
56
78
  // override standard with userconfig
57
- config[downlinkDeviceConfig.deviceType] = downlinkDeviceConfig;
58
- config[downlinkDeviceConfig.deviceType].downlinkState = {};
59
- for(const downlinkParameter of Object.values(downlinkDeviceConfig.downlinkParameter)){
60
- config[downlinkDeviceConfig.deviceType].downlinkState[downlinkParameter.name] = downlinkParameter;
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.activeDownlinkDeviceConfigs){
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
- getDownlinkConfig(changeInfo,options){
114
- const activeFunction = "getDownlinkConfig";
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.activeDownlinkDeviceConfigs){
120
- if((deviceType === "all" || changeInfo.deviceType.indexOf(deviceType) === 0) && deviceType.length > foundLength){
121
- if(this.activeDownlinkDeviceConfigs[deviceType].downlinkState[changeInfo.changedState]){
122
- downlinkConfig = this.activeDownlinkDeviceConfigs[deviceType].downlinkState[changeInfo.changedState];
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 downlinkConfig found: deviceType: ${changeInfo.deviceType} - changed state: ${changeInfo.changedState}`);
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 "ttn":
180
+ case this.adapter.origin.ttn:
160
181
  return this.getTtnDownlinkTopicFromDirektory(changeInfo,suffix);
161
- case "chirpstack":
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 "ttn":
221
+ case this.adapter.origin.ttn:
175
222
  return this.getTtnDownlink(downlinkConfig,payloadInHex);
176
- case "chirpstack":
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(downlinkConfig,state){
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(downlinkConfig.type === "button"){
192
- payloadInHex = downlinkConfig.onClick;
238
+ if(downlinkParameter.type === "button"){
239
+ payloadInHex = downlinkParameter.onClick;
193
240
  }
194
- else if(downlinkConfig.type === "boolean"){
241
+ else if(downlinkParameter.type === "boolean"){
195
242
  if(state.val){
196
- payloadInHex = downlinkConfig.on;
243
+ payloadInHex = downlinkParameter.on;
197
244
  }
198
245
  else{
199
- payloadInHex = downlinkConfig.off;
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(downlinkConfig.type){
253
+ switch(downlinkParameter.type){
207
254
  case "number":
208
- if(downlinkConfig.decimalPlaces){
209
- const expotentialFactor = Math.pow(10,downlinkConfig.decimalPlaces);
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 * downlinkConfig.multiplyfaktor;
263
+ multipliedVal = resultAfterdecimalPlaces * downlinkParameter.multiplyfaktor;
217
264
  payloadInHex = multipliedVal.toString(16).toUpperCase();
218
- numberOfDiggits = downlinkConfig.length - downlinkConfig.front.length - downlinkConfig.end.length;
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 = downlinkConfig.front + payloadInHex + downlinkConfig.end;
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 = downlinkConfig.length - downlinkConfig.front.length - downlinkConfig.end.length;
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 = downlinkConfig.front + payloadInHex + downlinkConfig.end;
280
+ payloadInHex = downlinkParameter.front + payloadInHex + downlinkParameter.end;
234
281
  break;
235
282
 
236
283
  case "string":
237
- payloadInHex = downlinkConfig.front + state.val + downlinkConfig.end;
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
- "length": 8,
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
- "length": 8,
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
- "length": 2,
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
- "length": 2,
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
- "length": 2,
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
- "length": 2,
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
- "length": 2,
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
- "length": 2,
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
- "length": 8,
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
- "length": 4,
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":"all",
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 "ttn":
17
+ case this.adapter.origin.ttn:
18
18
  await this.handleTtnMessage(topic,message);
19
19
  break;
20
- case "chirpstack":
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 downlinkConfig = this.adapter.downlinkConfighandler.getDownlinkConfig(changeInfo,{startupCheck:true});
42
- if(!downlinkConfig || this.stateForbidden(changeInfo.changedState)){
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.activeDownlinkDeviceConfigs){
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.activeDownlinkDeviceConfigs[downlinkDevice].downlinkState)){
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(changeInfo.changedState)){
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 "ttn":
119
+ case this.adapter.origin.ttn:
119
120
  return false;
120
- case "chirpstack":
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 "ttn":
56
+ case this.adapter.origin.ttn:
57
57
  return ["v3/+/devices/+/up","v3/+/devices/+/down/#"];
58
- case "chirpstack":
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.activeDownlinkDeviceConfigs)}`);
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
- if(this.config.origin === "ttn"){
143
- let appending = "push";
144
- if(changeInfo?.changedState === "push"){
145
- const downlinkTopic = this.downlinkConfighandler?.getDownlinkTopic(changeInfo,`/down/${appending}`);
146
- await this.sendDownlink(downlinkTopic,state.val);
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 if(this.config.origin === "chirpstack"){
172
- if(changeInfo?.changedState === "push"){
173
- const downlinkTopic = this.downlinkConfighandler?.getDownlinkTopic(changeInfo,`/down`);
174
- await this.sendDownlink(downlinkTopic,state.val,changeInfo);
175
- this.setStateAsync(id,state.val,true);
176
- }
177
- else{
178
- const downlinkTopic = this.downlinkConfighandler?.getDownlinkTopic(changeInfo,`/down`);
179
- const downlinkConfig = this.downlinkConfighandler?.getDownlinkConfig(changeInfo);
180
- if(downlinkConfig !== undefined){
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 downlinkConfig = this.downlinkConfighandler?.getDownlinkConfig(changeInfo,{startupCheck:true});
205
- if(!downlinkConfig){
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?.activeDownlinkDeviceConfigs){
190
+ for(const devicename in this.downlinkConfighandler?.activeDownlinkConfigs){
217
191
  index++;
218
- this.log.info(`Device ${index}: ${devicename}`);
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?.activeDownlinkDeviceConfigs[changeInfo.bestMatchForDeviceType].sendWithUplink !== "disabled"){
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
- let appending = "";
242
- switch(this.config.origin){
243
- case "ttn":
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?.activeDownlinkDeviceConfigs[changeInfo.bestMatchForDeviceType].sendWithUplink === "enabled & collect"){
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 "ttn":
270
+ case this.origin.ttn:
304
271
  payload = downlink.downlinks[0].frm_payload;
305
272
  break;
306
273
 
307
- case "chirpstack":
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.2",
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.4"
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.10.6",
41
+ "@types/node": "^20.11.14",
42
42
  "@types/proxyquire": "^1.3.31",
43
- "@types/sinon": "^17.0.2",
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.0",
46
+ "chai": "^4.4.1",
47
47
  "eslint": "^8.56.0",
48
48
  "mocha": "^10.2.0",
49
49
  "proxyquire": "^2.1.3",