iobroker.lorawan 1.20.10 → 1.20.11

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
@@ -23,6 +23,9 @@ For now there is documentation in English here: https://wiki.hafenmeister.de
23
23
  Placeholder for the next version (at the beginning of the line):
24
24
  ### **WORK IN PROGRESS**
25
25
  -->
26
+ ### 1.20.11 (2026-01-26)
27
+ * (BenAhrdt) improve device Manager icons and Buttons
28
+
26
29
  ### 1.20.10 (2026-01-26)
27
30
  * (BenAhrdt) return to root getCnageInfo
28
31
 
@@ -85,6 +85,8 @@
85
85
  "DeviceIdentifiers": "Gerätekennung",
86
86
  "EnableRefresh": "zyklisches Discovery",
87
87
  "EnableRefreshTooltip": "aktivieren, um zyklisch mit einem cron zu discovern",
88
+ "Enter new devicetype": "Geben Sie einen neuen Gerätetyp ein",
89
+ "Enter new name": "Geben Sie einen neuen Gerätenamen ein",
88
90
  "Folder": "Ordner",
89
91
  "Humidifier": "Luftbefeuchter",
90
92
  "HumidifierActText": "Tatsächliche Luftfeuchtigkeit",
@@ -276,5 +276,7 @@
276
276
  "CoverSimulatePositionTooltip": "simulates the position depending on the limit switches (required for some systems)",
277
277
  "Rename this device": "Rename this device",
278
278
  "Config this device": "Config this device",
279
- "Info of this device": "Info of this device"
279
+ "Info of this device": "Info of this device",
280
+ "Enter new name": "Enter new name",
281
+ "Enter new devicetype": "Enter new devicetype"
280
282
  }
@@ -85,6 +85,8 @@
85
85
  "DeviceIdentifiers": "Identificadores de dispositivos",
86
86
  "EnableRefresh": "Descubrir cíclico",
87
87
  "EnableRefreshTooltip": "permitir descubrir en un cron cíclico",
88
+ "Enter new devicetype": "Ingrese el nuevo tipo de dispositivo",
89
+ "Enter new name": "Introduce un nuevo nombre",
88
90
  "Folder": "Carpeta",
89
91
  "Humidifier": "humidificador",
90
92
  "HumidifierActText": "Humedad real",
@@ -85,6 +85,8 @@
85
85
  "DeviceIdentifiers": "Identificateurs de périphérique",
86
86
  "EnableRefresh": "cyclique Découvrir",
87
87
  "EnableRefreshTooltip": "permettre de découvrir dans un cron cyclique",
88
+ "Enter new devicetype": "Entrez le nouveau type d'appareil",
89
+ "Enter new name": "Entrez un nouveau nom",
88
90
  "Folder": "Dossier",
89
91
  "Humidifier": "Humidificateur",
90
92
  "HumidifierActText": "Humidité réelle",
@@ -85,6 +85,8 @@
85
85
  "DeviceIdentifiers": "Identificatori del dispositivo",
86
86
  "EnableRefresh": "Scopri ciclico",
87
87
  "EnableRefreshTooltip": "consentire di scoprire in un cron ciclico",
88
+ "Enter new devicetype": "Inserisci il nuovo tipo di dispositivo",
89
+ "Enter new name": "Inserisci il nuovo nome",
88
90
  "Folder": "Cartella",
89
91
  "Humidifier": "Umidificatore",
90
92
  "HumidifierActText": "Umidità effettiva",
@@ -85,6 +85,8 @@
85
85
  "DeviceIdentifiers": "Apparaat-ID's",
86
86
  "EnableRefresh": "cyclisch Ontdek",
87
87
  "EnableRefreshTooltip": "maken het mogelijk om te ontdekken in een cyclische cron",
88
+ "Enter new devicetype": "Voer een nieuw apparaattype in",
89
+ "Enter new name": "Voer een nieuwe naam in",
88
90
  "Folder": "Map",
89
91
  "Humidifier": "Luchtbevochtiger",
90
92
  "HumidifierActText": "Werkelijke luchtvochtigheid",
@@ -85,6 +85,8 @@
85
85
  "DeviceIdentifiers": "Identyfikatory urządzeń",
86
86
  "EnableRefresh": "cykliczne Odkryj",
87
87
  "EnableRefreshTooltip": "włącz wykrywanie w cyklicznym cronie",
88
+ "Enter new devicetype": "Wprowadź nowy typ urządzenia",
89
+ "Enter new name": "Wprowadź nową nazwę",
88
90
  "Folder": "Falcówka",
89
91
  "Humidifier": "Nawilżacz",
90
92
  "HumidifierActText": "Rzeczywista wilgotność",
@@ -85,6 +85,8 @@
85
85
  "DeviceIdentifiers": "Identificadores de dispositivos",
86
86
  "EnableRefresh": "descoberta cíclica",
87
87
  "EnableRefreshTooltip": "permitir descobrir em um cron cíclico",
88
+ "Enter new devicetype": "Insira o novo tipo de dispositivo",
89
+ "Enter new name": "Digite o novo nome",
88
90
  "Folder": "Pasta",
89
91
  "Humidifier": "Umidificador",
90
92
  "HumidifierActText": "Umidade real",
@@ -85,6 +85,8 @@
85
85
  "DeviceIdentifiers": "Идентификаторы устройств",
86
86
  "EnableRefresh": "циклическое открытие",
87
87
  "EnableRefreshTooltip": "включить обнаружение в циклическом cron",
88
+ "Enter new devicetype": "Введите новый тип устройства",
89
+ "Enter new name": "Введите новое имя",
88
90
  "Folder": "Папка",
89
91
  "Humidifier": "Увлажнитель",
90
92
  "HumidifierActText": "Фактическая влажность",
@@ -85,6 +85,8 @@
85
85
  "DeviceIdentifiers": "Ідентифікатори пристроїв",
86
86
  "EnableRefresh": "циклічний Discover",
87
87
  "EnableRefreshTooltip": "дозволити виявити в циклічному кроні",
88
+ "Enter new devicetype": "Введіть новий тип пристрою",
89
+ "Enter new name": "Введіть нове ім'я",
88
90
  "Folder": "Папка",
89
91
  "Humidifier": "Зволожувач повітря",
90
92
  "HumidifierActText": "Фактична вологість",
@@ -85,6 +85,8 @@
85
85
  "DeviceIdentifiers": "设备标识符",
86
86
  "EnableRefresh": "循环发现",
87
87
  "EnableRefreshTooltip": "能够在循环 cron 中发现",
88
+ "Enter new devicetype": "输入新的设备类型",
89
+ "Enter new name": "输入新名称",
88
90
  "Folder": "文件夹",
89
91
  "Humidifier": "加湿器",
90
92
  "HumidifierActText": "实际湿度",
package/io-package.json CHANGED
@@ -1,8 +1,21 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "lorawan",
4
- "version": "1.20.10",
4
+ "version": "1.20.11",
5
5
  "news": {
6
+ "1.20.11": {
7
+ "en": "improve device Manager icons and Buttons",
8
+ "de": "verbesserung der Vorrichtung Icons und Buttons verwalten",
9
+ "ru": "улучшить устройство Иконки менеджера и кнопки",
10
+ "pt": "melhorar o dispositivo Gerir ícones e botões",
11
+ "nl": "apparaat verbeteren Pictogrammen en knoppen voor de manager",
12
+ "fr": "améliorer l'appareil Icônes de gestionnaire et boutons",
13
+ "it": "migliorare il dispositivo Icone Manager e pulsanti",
14
+ "es": "mejorar el dispositivo Gestor de iconos y botones",
15
+ "pl": "ulepszenie urządzenia Ikony menedżera i przyciski",
16
+ "uk": "поліпшення пристрою Ім'я користувача",
17
+ "zh-cn": "改进设备 管理器图标和按钮"
18
+ },
6
19
  "1.20.10": {
7
20
  "en": "return to root getCnageInfo",
8
21
  "de": "zurück zu root getCnageInfo",
@@ -80,19 +93,6 @@
80
93
  "pl": "bugfitting aktualizacja obiektu Przechowuj bez przypisanego id",
81
94
  "uk": "виправлення помилок оновлення об'єкту Store з не потовщеним id",
82
95
  "zh-cn": "正在更新对象 Store, 且未减少 ID"
83
- },
84
- "1.20.4": {
85
- "en": "experimental to debug in live system",
86
- "de": "experimentell zu debug im live-system",
87
- "ru": "экспериментальная отладка в живой системе",
88
- "pt": "experimental para depuração no sistema live",
89
- "nl": "experimenteel debuggen in live systeem",
90
- "fr": "expérimental pour déboguer dans le système vivant",
91
- "it": "sperimentale per debug nel sistema live",
92
- "es": "experimental para depurar en el sistema en vivo",
93
- "pl": "eksperymentalne debugowanie w systemie live",
94
- "uk": "експериментальна дебюга в живій системі",
95
- "zh-cn": "正在运行系统中调试的实验"
96
96
  }
97
97
  },
98
98
  "titleLang": {
@@ -576,7 +576,7 @@
576
576
  "_id": "bridge.debug",
577
577
  "type": "folder",
578
578
  "common": {
579
- "name": "Debugfunctions of bridge"
579
+ "name": "Debug functions of bridge"
580
580
  },
581
581
  "native": {}
582
582
  },
@@ -589,7 +589,7 @@
589
589
  "name": "internal logging types",
590
590
  "read": true,
591
591
  "write": true,
592
- "def": "{\"discovery\":false, \"assign\": false, \"messageTo\": false, \"listDevices\": false, \"getStatus\": false, \"deviceinformation\": false, \"downlinkconfig\": false, \"getChangeInfo\": false,}"
592
+ "def": "{\"discovery\":false, \"assign\": false, \"messageTo\": false, \"listDevices\": false, \"getStatus\": false, \"deviceinformation\": false, \"downlinkconfig\": false, \"getChangeInfo\": false}"
593
593
  },
594
594
  "native": {}
595
595
  },
@@ -447,7 +447,7 @@ class bridgeClass {
447
447
  const activeFunction = 'bridge.js - discovery';
448
448
  this.adapter.log.silly(`Function ${activeFunction} started.`);
449
449
  try {
450
- if (!this.CheckedIds[id] || (options && options.forceDiscovery)) {
450
+ if (!this.CheckedIds[id] || options?.forceDiscovery) {
451
451
  this.CheckedIds[id] = {};
452
452
  this.adapter.log.debug(`discover the id ${id}`);
453
453
  return await this.buildDiscovery(id, options);
@@ -1278,7 +1278,7 @@ class bridgeClass {
1278
1278
  try {
1279
1279
  let indexOfStatebegin = -1;
1280
1280
  // Check for state discover outsid the applications
1281
- if (options && options.internal) {
1281
+ if (options?.internal) {
1282
1282
  indexOfStatebegin = changeInfo.id.indexOf(options.internal.folder);
1283
1283
  indexOfStatebegin = options.internal.folder.length + 1;
1284
1284
  } else {
@@ -1299,13 +1299,13 @@ class bridgeClass {
1299
1299
  const StateName = changeInfo.id.substring(indexOfStatebegin, changeInfo.id.length);
1300
1300
  //const normalizedStateName = this.normalizeString(StateName); 08.11.2025 BeSc dont needed anymore with chenge below
1301
1301
  let DeviceIdentifier;
1302
- if (options && options.internal) {
1302
+ if (options?.internal) {
1303
1303
  DeviceIdentifier = options.internal.deviceidentifier;
1304
1304
  } else {
1305
1305
  DeviceIdentifier = this.getDeviceIdentifier(changeInfo, this.adapter.config.DeviceIdentifiers);
1306
1306
  }
1307
1307
  // Add Suffix, if present
1308
- if (options && options.deviceSuffix) {
1308
+ if (options?.deviceSuffix) {
1309
1309
  DeviceIdentifier += options.deviceSuffix;
1310
1310
  }
1311
1311
  const normalizedDeviceIdentifier = this.normalizeString(DeviceIdentifier);
@@ -1969,7 +1969,7 @@ class bridgeClass {
1969
1969
  let id = `${this.adapter.namespace}.bridge.dataFromIob`;
1970
1970
  let deviceObject = await this.adapter.getForeignObjectAsync(id);
1971
1971
  options.common = deviceObject.common;
1972
- let changeInfo = await this.adapter.getChangeInfo(id);
1972
+ let changeInfo = { id: `bridge.dataFromIob` }; // 26.01.2026 to unse getChangeInfo with objectstore
1973
1973
  options.Bridgestate = {
1974
1974
  discover: true,
1975
1975
  publish: true,
@@ -2004,7 +2004,7 @@ class bridgeClass {
2004
2004
  id = `${this.adapter.namespace}.bridge.dataToIob`;
2005
2005
  deviceObject = await this.adapter.getForeignObjectAsync(id);
2006
2006
  options.common = deviceObject.common;
2007
- changeInfo = await this.adapter.getChangeInfo(id);
2007
+ changeInfo = { id: `bridge.dataFromIob` }; // 26.01.2026 to unse getChangeInfo with objectstore
2008
2008
  options.Bridgestate = {
2009
2009
  discover: true,
2010
2010
  publish: false,
@@ -17,7 +17,7 @@ class bridgeMqttClientClass {
17
17
  clientId: `iobroker_${this.adapter.namespace}.bridge`,
18
18
  });
19
19
 
20
- this.filter = { incomming: '', outgoing: '' };
20
+ this.filter = { incoming: '', outgoing: '' };
21
21
 
22
22
  // Prefix for publish and subscribe
23
23
  this.BridgePrefix = `${this.adapter.namespace}/`.replace(/\./g, '_');
@@ -29,8 +29,8 @@ class bridgeMqttClientClass {
29
29
 
30
30
  this.client.on('connect', async () => {
31
31
  // Assign filter, if present
32
- if (await this.adapter.objectExists('bridge.debug.incommingTopicFilter')) {
33
- this.filter.incomming = (await this.adapter.getStateAsync('bridge.debug.incommingTopicFilter')).val;
32
+ if (await this.adapter.objectExists('bridge.debug.incomingTopicFilter')) {
33
+ this.filter.incoming = (await this.adapter.getStateAsync('bridge.debug.incomingTopicFilter')).val;
34
34
  }
35
35
  if (await this.adapter.objectExists('bridge.debug.outgoingTopicFilter')) {
36
36
  this.filter.outgoing = (await this.adapter.getStateAsync('bridge.debug.outgoingTopicFilter')).val;
@@ -80,7 +80,7 @@ class bridgeMqttClientClass {
80
80
  });
81
81
  this.client.on('error', err => {
82
82
  if (this.errorCountdown === 0) {
83
- this.adapter.log.error(`${err}`);
83
+ this.adapter.log.error(`bridgeMqttClientClass error: ${err}`);
84
84
  this.errorCountdown = this.numberOfErrorsToLog;
85
85
  } else {
86
86
  this.errorCountdown--;
@@ -105,17 +105,17 @@ class bridgeMqttClientClass {
105
105
  });
106
106
 
107
107
  this.client.on('message', async (topic, message) => {
108
- this.adapter.log.debug(`incomming bridge topic: ${topic}`);
109
- this.adapter.log.debug(`incomming bridge message: ${message}`);
108
+ this.adapter.log.debug(`incoming bridge topic: ${topic}`);
109
+ this.adapter.log.debug(`incoming bridge message: ${message}`);
110
110
 
111
111
  // String zuweisen, wenn JSON.parse ein Fehler auswirft.
112
112
  let payload = message.toString('utf8');
113
113
 
114
114
  // Write into debug
115
- if (await this.adapter.objectExists('bridge.debug.incommingTopic')) {
116
- if (topic.includes(this.filter.incomming)) {
117
- await this.adapter.setState('bridge.debug.incommingTopic', topic, true);
118
- await this.adapter.setState('bridge.debug.incommingPayload', payload, true);
115
+ if (await this.adapter.objectExists('bridge.debug.incomingTopic')) {
116
+ if (topic.includes(this.filter.incoming)) {
117
+ await this.adapter.setState('bridge.debug.incomingTopic', topic, true);
118
+ await this.adapter.setState('bridge.debug.incommngPayload', payload, true);
119
119
  }
120
120
  }
121
121
 
@@ -15,7 +15,6 @@ class LoRaWANDeviceManagement extends DeviceManagement {
15
15
  super(adapter);
16
16
  this.adapter = adapter;
17
17
  }
18
-
19
18
  /**
20
19
  * List all LoRaWAN devices
21
20
  */
@@ -27,9 +26,9 @@ class LoRaWANDeviceManagement extends DeviceManagement {
27
26
  // Check for logging
28
27
  this.adapter.log[this.adapter.logtypes.listDevices]?.(`List device started for device: ${key}`);
29
28
  const res = {
30
- id: value.object._id,
29
+ id: key,
31
30
  name: value.object.common.name,
32
- icon: 'cistern', //await this.getIcon(value),
31
+ icon: await this.getIcon(value),
33
32
  manufacturer: value.informations
34
33
  ? value.informations.lastUplink
35
34
  ? new Date(value.informations.lastUplink.state.ts).toLocaleString('de-DE', {
@@ -51,24 +50,22 @@ class LoRaWANDeviceManagement extends DeviceManagement {
51
50
  id: 'rename',
52
51
  icon: 'edit',
53
52
  description: this.adapter.i18nTranslation['Rename this device'],
54
- handler: async (_id, context) => await this.handleRenameDevice(_id, context),
53
+ handler: async (_id, context) => await this.handleRenameDevice(_id, context, value),
54
+ },
55
+ {
56
+ id: 'config',
57
+ icon: 'settings',
58
+ description: this.adapter.i18nTranslation['Config this device'],
59
+ handler: async (_id, context) => await this.handleConfigDevice(_id, context, value),
60
+ },
61
+ {
62
+ id: 'Info',
63
+ icon: 'lines',
64
+ description: this.adapter.i18nTranslation['Info of this device'],
65
+ handler: async (_id, context) => await this.handleInfo(_id, context),
55
66
  },
56
67
  ],
57
68
  };
58
- if (res.status.connection === 'connected') {
59
- res.actions.push({
60
- id: 'config',
61
- icon: 'settings',
62
- description: this.adapter.i18nTranslation['Config this device'],
63
- handler: async (_id, context) => await this.handleRenameDevice(_id, context),
64
- });
65
- res.actions.push({
66
- id: 'Info',
67
- icon: 'lines',
68
- description: this.adapter.i18nTranslation['Info of this device'],
69
- handler: async (_id, context) => await this.handleRenameDevice(_id, context),
70
- });
71
- }
72
69
  arrDevices.push(res);
73
70
  }
74
71
  return arrDevices;
@@ -100,15 +97,15 @@ class LoRaWANDeviceManagement extends DeviceManagement {
100
97
 
101
98
  /**
102
99
  *
103
- * @param devicevalue values of device
100
+ * @param deviceValue values of device
104
101
  */
105
- async getIcon(devicevalue) {
106
- if (devicevalue.indicators) {
107
- if (devicevalue.indicators.isThermostat) {
102
+ async getIcon(deviceValue) {
103
+ if (deviceValue.indicators) {
104
+ if (deviceValue.indicators.isThermostat) {
108
105
  return 'thermostat';
109
- } else if (devicevalue.indicators.isDoor) {
106
+ } else if (deviceValue.indicators.isDoor) {
110
107
  return 'door';
111
- } else if (devicevalue.indicators.isWindow) {
108
+ } else if (deviceValue.indicators.isWindow) {
112
109
  return 'window';
113
110
  }
114
111
  }
@@ -117,10 +114,11 @@ class LoRaWANDeviceManagement extends DeviceManagement {
117
114
 
118
115
  /**
119
116
  *
120
- * @param id id to rename
117
+ * @param id ID to rename
121
118
  * @param context context sendet from Backend
119
+ * @param objectValue value of the device object
122
120
  */
123
- async handleRenameDevice(id, context) {
121
+ async handleRenameDevice(id, context, objectValue) {
124
122
  const result = await context.showForm(
125
123
  {
126
124
  type: 'panel',
@@ -134,24 +132,12 @@ class LoRaWANDeviceManagement extends DeviceManagement {
134
132
  },
135
133
  {
136
134
  data: {
137
- newName: '',
138
- },
139
- title: {
140
- en: 'Enter new name',
141
- de: 'Neuen Namen eingeben',
142
- ru: 'Введите новое имя',
143
- pt: 'Digite um novo nome',
144
- nl: 'Voer een nieuwe naam in',
145
- fr: 'Entrez un nouveau nom',
146
- it: 'Inserisci un nuovo nome',
147
- es: 'Ingrese un nuevo nombre',
148
- pl: 'Wpisz nowe imię',
149
- 'zh-cn': '输入新名称',
150
- uk: "Введіть нове ім'я",
135
+ newName: objectValue.object.common.name,
151
136
  },
137
+ title: this.adapter.i18nTranslation['Enter new name'],
152
138
  },
153
139
  );
154
- if (result?.newName === undefined || result?.newName === '') {
140
+ if (result?.newName === undefined) {
155
141
  return { refresh: false };
156
142
  }
157
143
  const obj = {
@@ -159,7 +145,7 @@ class LoRaWANDeviceManagement extends DeviceManagement {
159
145
  name: result.newName,
160
146
  },
161
147
  };
162
- const res = await this.adapter.extendForeignObjectAsync(id, obj);
148
+ const res = await this.adapter.extendObjectAsync(objectValue.object._id, obj);
163
149
  if (res === null) {
164
150
  this.adapter.log.warn(`Can not rename device ${id}: ${JSON.stringify(res)}`);
165
151
  return { refresh: false };
@@ -167,7 +153,76 @@ class LoRaWANDeviceManagement extends DeviceManagement {
167
153
  return { refresh: true };
168
154
  }
169
155
 
170
- // Possible strings for icons
156
+ /**
157
+ *
158
+ * @param id ID to rename
159
+ * @param context context sendet from Backend
160
+ * @param objectValue value of the device object
161
+ */
162
+ async handleConfigDevice(id, context, objectValue) {
163
+ const result = await context.showForm(
164
+ {
165
+ type: 'panel',
166
+ items: {
167
+ devicetype: {
168
+ type: 'text',
169
+ trim: false,
170
+ placeholder: '',
171
+ },
172
+ },
173
+ },
174
+ {
175
+ data: {
176
+ devicetype: objectValue.configuration.devicetype.state.val,
177
+ },
178
+ title: this.adapter.i18nTranslation['Enter new devicetype'],
179
+ },
180
+ );
181
+ if (result?.devicetype === undefined) {
182
+ return { refresh: false };
183
+ }
184
+ const res = await this.adapter.setStateAsync(
185
+ objectValue.configuration.devicetype.object._id,
186
+ result.devicetype,
187
+ );
188
+ if (res === null) {
189
+ this.adapter.log.warn(`Can not set new devicetype ${id}: ${JSON.stringify(res)}`);
190
+ return { refresh: false };
191
+ }
192
+ return { refresh: true };
193
+ }
194
+
195
+ /**
196
+ *
197
+ * @param id ID to rename
198
+ * @param context context sendet from Backend
199
+ */
200
+ async handleInfo(id, context) {
201
+ let deviceInfo = await this.adapter.getStateAsync('info.deviceinformations');
202
+ deviceInfo = JSON.parse(deviceInfo.val);
203
+ await context.showForm(
204
+ {
205
+ type: 'panel',
206
+ items: {
207
+ deviceinfos: {
208
+ type: 'text',
209
+ readOnly: true,
210
+ noClearButton: true,
211
+ trim: false,
212
+ placeholder: '',
213
+ minRows: 10,
214
+ },
215
+ },
216
+ },
217
+ {
218
+ data: {
219
+ deviceinfos: JSON.stringify(deviceInfo[id].uplink.decoded, null, 2),
220
+ },
221
+ title: this.adapter.i18nTranslation['Info of this device'],
222
+ },
223
+ );
224
+ return { refresh: true };
225
+ }
171
226
  }
172
227
 
173
228
  module.exports = LoRaWANDeviceManagement;
@@ -77,8 +77,8 @@ class mqttClientClass {
77
77
  });
78
78
 
79
79
  this.client.on('message', async (topic, message) => {
80
- this.adapter.log.debug(`incomming topic: ${topic}`);
81
- this.adapter.log.debug(`incomming message: ${message}`);
80
+ this.adapter.log.debug(`incoming topic: ${topic}`);
81
+ this.adapter.log.debug(`incoming message: ${message}`);
82
82
  // @ts-expect-error assignmessage in JSON.parse
83
83
  message = JSON.parse(message);
84
84
 
package/main.js CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const mqtt = require('mqtt');
4
- const crypto = require('crypto');
4
+ const crypto = require('node:crypto');
5
5
 
6
6
  /*
7
7
  * Created with @iobroker/create-adapter v2.6.0
@@ -13,7 +13,7 @@ const utils = require('@iobroker/adapter-core');
13
13
  const bridgeClass = require('./lib/modules/bridge');
14
14
  const mqttClientClass = require('./lib/modules/mqttclient');
15
15
  const messagehandlerClass = require('./lib/modules/messagehandler');
16
- const downlinkConfighandlerClass = require('./lib/modules/downlinkConfighandler');
16
+ const downlinkConfigHandlerClass = require('./lib/modules/downlinkConfighandler');
17
17
  const LoRaWANDeviceManagement = require('./lib/modules/deviceManager');
18
18
  const objectStoreClass = require('./lib/modules/objectStore');
19
19
 
@@ -62,7 +62,7 @@ class Lorawan extends utils.Adapter {
62
62
 
63
63
  onFileChange(_id, _fileName, _size) {
64
64
  // restart adapter after upload
65
- //this.restart();
65
+ // this.restart();
66
66
  }
67
67
 
68
68
  /**
@@ -74,7 +74,7 @@ class Lorawan extends utils.Adapter {
74
74
  // Get Logtypes
75
75
  this.logtypes = JSON.parse(await this.setDefIfEmptyAndReturnVal('bridge.debug.logtypes'));
76
76
 
77
- // Generate Objectstore
77
+ // Generate Object Store
78
78
  this.objectStore = new objectStoreClass(this);
79
79
 
80
80
  await this.objectStore.generateDeviceObjects();
@@ -91,12 +91,12 @@ class Lorawan extends utils.Adapter {
91
91
  this.version = adapterinfos?.common.version;
92
92
 
93
93
  // create downlinkConfigs
94
- this.downlinkConfighandler = new downlinkConfighandlerClass(this);
94
+ this.downlinkConfighandler = new downlinkConfigHandlerClass(this);
95
95
 
96
96
  // Merge the configed and standard profile of downlinks
97
97
  await this.downlinkConfighandler.addAndMergeDownlinkConfigs();
98
98
 
99
- // create new messagehandler
99
+ // create new message handler
100
100
  this.messagehandler = new messagehandlerClass(this);
101
101
 
102
102
  // generate new configed downlinkstates on allready existing devices at adapter startup
@@ -110,12 +110,12 @@ class Lorawan extends utils.Adapter {
110
110
  // get history instances at Startup
111
111
  await this.messagehandler.setCustomObjectAtStartup();
112
112
 
113
- // Set mqtt client => just declare, if a url is set
113
+ // Set mqtt client => just declare, if a URL is set
114
114
  if (this.config.origin !== 'off') {
115
115
  this.mqttClient = new mqttClientClass(this, this.config);
116
116
  }
117
117
 
118
- // declare bridge if configed
118
+ // declare bridge if configured
119
119
  if (this.config.BridgeType !== 'off') {
120
120
  this.bridge = new bridgeClass(this);
121
121
  }
@@ -124,7 +124,7 @@ class Lorawan extends utils.Adapter {
124
124
  //Subscribe all configuration and control states
125
125
  await this.subscribeStatesAsync('*');
126
126
  await this.subscribeObjectsAsync('*');
127
- //this.subscribeObjectsAsync('*.downlink.control.*');
127
+ // this.subscribeObjectsAsync('*.downlink.control.*');
128
128
  // Check for logging
129
129
  this.log[this.logtypes.downlinkconfig]?.(
130
130
  `the adapter starts with downlinkconfigs: ${JSON.stringify(this.config.downlinkConfig)}.`,
@@ -132,14 +132,14 @@ class Lorawan extends utils.Adapter {
132
132
  this.log[this.logtypes.downlinkconfig]?.(
133
133
  `the active downlinkconfigs are: ${JSON.stringify(this.downlinkConfighandler.activeDownlinkConfigs)}`,
134
134
  );
135
- /*
135
+ /*
136
136
  setTimeout(async () => {
137
137
  this.log.debug('vor Simulation');
138
138
  await this.startSimulation();
139
139
  this.log.debug('nach Simulation');
140
140
  }, 5000);
141
141
  */
142
- /*this.simulation.timeout = setTimeout(async () => {
142
+ /* this.simulation.timeout = setTimeout(async () => {
143
143
  const topic = "application/d63c10b6-9263-4ab3-9299-4308fa19a2ad/device/f1c0ae0e-b4a2-4547-b360-7cfa15e85734/command/down";
144
144
  const message = {devEui:"f1c0ae0e-b4a2-4547-b360-7cfa15e85734",confirmed:false,fPort:1,data:"AAA"};
145
145
  await this.mqttClient?.publish(topic,JSON.stringify(message));
@@ -167,7 +167,7 @@ class Lorawan extends utils.Adapter {
167
167
  }
168
168
 
169
169
  /**
170
- * CHeck Id for '' and set to def, if preset
170
+ * CHeck ID for '' and set to def, if preset
171
171
  *
172
172
  * @param id id to check for empty
173
173
  */
@@ -420,56 +420,56 @@ class Lorawan extends utils.Adapter {
420
420
  regionConfigId: 'eu868',
421
421
  };
422
422
 
423
- //const topic = "application/d63c10b6-9263-4ab3-9299-4308fa19a2ad/device/a84041f621857cd2/command/down";
424
- //const message = {"devEui":"a84041f621857cd2","confirmed":false,"fPort":1,"data":"AQAqMA=="};
423
+ // const topic = "application/d63c10b6-9263-4ab3-9299-4308fa19a2ad/device/a84041f621857cd2/command/down";
424
+ // const message = {"devEui":"a84041f621857cd2","confirmed":false,"fPort":1,"data":"AQAqMA=="};
425
425
 
426
426
  // Chirpstack LT222222
427
- //const topic = "application/d63c10b6-9263-4ab3-9299-4308fa19a2ad/device/a8404127a188d826/event/up";
428
- //const message = {"deduplicationId":"bd3fdb3b-af86-4617-b9f2-da07075d2bc5","time":"2024-01-24T16:47:01.573381+00:00","deviceInfo":{"tenantId":"52f14cd4-c6f1-4fbd-8f87-4025e1d49242","tenantName":"ChirpStack","applicationId":"d63c10b6-9263-4ab3-9299-4308fa19a2ad","applicationName":"Benjamin Schmidt","deviceProfileId":"f1c0ae0e-b4a2-4547-b360-7cfa15e85734","deviceProfileName":"Dragino LT22222","deviceName":"Relaistestgerät","devEui":"a8404127a188d826","deviceClassEnabled":"CLASS_C","tags":{}},"devAddr":"01dfbaf2","adr":true,"dr":5,"fCnt":12,"fPort":2,"confirmed":false,"data":"AAAAAAAAAAA8/0E=","object":{"RO1_status":"OFF","DO2_status":"H","ACI2_mA":0.0,"DO1_status":"H","Hardware_mode":"LT22222","RO2_status":"OFF","AVI2_V":0.0,"ACI1_mA":0.0,"DI1_status":"H","DI2_status":"H","Work_mode":"2ACI+2AVI","AVI1_V":0.0},"rxInfo":[{"gatewayId":"50303541b0344750","uplinkId":57857,"gwTime":"2024-01-24T16:47:01.573381+00:00","nsTime":"2024-01-24T16:47:02.370171527+00:00","rssi":-54,"snr":8.5,"channel":6,"location":{"latitude":50.69344693065449,"longitude":8.476783633232118},"context":"2tr9BA==","metadata":{"region_config_id":"eu868","region_common_name":"EU868"},"crcStatus":"CRC_OK"}],"txInfo":{"frequency":867700000,"modulation":{"lora":{"bandwidth":125000,"spreadingFactor":7,"codeRate":"CR_4_5"}}}};
429
- //const topic = "application/d63c10b6-9263-4ab3-9299-4308fa19a2ad/device/a8404127a188d826/command/down";
430
- //const message = {"devEui":"a8404127a188d826","confirmed":false,"fPort":1,"data":"AQACWA=="};
427
+ // const topic = "application/d63c10b6-9263-4ab3-9299-4308fa19a2ad/device/a8404127a188d826/event/up";
428
+ // const message = {"deduplicationId":"bd3fdb3b-af86-4617-b9f2-da07075d2bc5","time":"2024-01-24T16:47:01.573381+00:00","deviceInfo":{"tenantId":"52f14cd4-c6f1-4fbd-8f87-4025e1d49242","tenantName":"ChirpStack","applicationId":"d63c10b6-9263-4ab3-9299-4308fa19a2ad","applicationName":"Benjamin Schmidt","deviceProfileId":"f1c0ae0e-b4a2-4547-b360-7cfa15e85734","deviceProfileName":"Dragino LT22222","deviceName":"Relaistestgerät","devEui":"a8404127a188d826","deviceClassEnabled":"CLASS_C","tags":{}},"devAddr":"01dfbaf2","adr":true,"dr":5,"fCnt":12,"fPort":2,"confirmed":false,"data":"AAAAAAAAAAA8/0E=","object":{"RO1_status":"OFF","DO2_status":"H","ACI2_mA":0.0,"DO1_status":"H","Hardware_mode":"LT22222","RO2_status":"OFF","AVI2_V":0.0,"ACI1_mA":0.0,"DI1_status":"H","DI2_status":"H","Work_mode":"2ACI+2AVI","AVI1_V":0.0},"rxInfo":[{"gatewayId":"50303541b0344750","uplinkId":57857,"gwTime":"2024-01-24T16:47:01.573381+00:00","nsTime":"2024-01-24T16:47:02.370171527+00:00","rssi":-54,"snr":8.5,"channel":6,"location":{"latitude":50.69344693065449,"longitude":8.476783633232118},"context":"2tr9BA==","metadata":{"region_config_id":"eu868","region_common_name":"EU868"},"crcStatus":"CRC_OK"}],"txInfo":{"frequency":867700000,"modulation":{"lora":{"bandwidth":125000,"spreadingFactor":7,"codeRate":"CR_4_5"}}}};
429
+ // const topic = "application/d63c10b6-9263-4ab3-9299-4308fa19a2ad/device/a8404127a188d826/command/down";
430
+ // const message = {"devEui":"a8404127a188d826","confirmed":false,"fPort":1,"data":"AQACWA=="};
431
431
 
432
432
  // ACK
433
- //const topic = "application/59bcc5a7-59e2-4481-9615-fc4e58791915/device/70b3d52dd300ed31/event/ack";
434
- //const message = {"deduplicationId":"b080c0d8-6151-4675-84b8-74ecf9e33bae","time":"2023-08-15T13:22:27.969901+00:00","deviceInfo":{"tenantId":"52f14cd4-c6f1-4fbd-8f87-4025e1d49242","tenantName":"ChirpStack","applicationId":"59bcc5a7-59e2-4481-9615-fc4e58791915","applicationName":"Mclimate_Vicki","deviceProfileId":"3a9bc28f-3664-4bdf-b3be-a20d1eb32dc8","deviceProfileName":"Mclimate_Vicki","deviceName":"MClimate_Vicki_Heizkoerperventil_001","devEui":"70b3d52dd300ed31","deviceClassEnabled":"CLASS_A","tags":{}},"queueItemId":"3434298f-2b89-49f8-885e-9fdd9f0892e6","acknowledged":true,"fCntDown":262};
433
+ // const topic = "application/59bcc5a7-59e2-4481-9615-fc4e58791915/device/70b3d52dd300ed31/event/ack";
434
+ // const message = {"deduplicationId":"b080c0d8-6151-4675-84b8-74ecf9e33bae","time":"2023-08-15T13:22:27.969901+00:00","deviceInfo":{"tenantId":"52f14cd4-c6f1-4fbd-8f87-4025e1d49242","tenantName":"ChirpStack","applicationId":"59bcc5a7-59e2-4481-9615-fc4e58791915","applicationName":"Mclimate_Vicki","deviceProfileId":"3a9bc28f-3664-4bdf-b3be-a20d1eb32dc8","deviceProfileName":"Mclimate_Vicki","deviceName":"MClimate_Vicki_Heizkoerperventil_001","devEui":"70b3d52dd300ed31","deviceClassEnabled":"CLASS_A","tags":{}},"queueItemId":"3434298f-2b89-49f8-885e-9fdd9f0892e6","acknowledged":true,"fCntDown":262};
435
435
 
436
436
  // TXACK
437
- //const topic = "application/59bcc5a7-59e2-4481-9615-fc4e58791915/device/70b3d52dd300ed31/event/txack";
438
- //const message = {"downlinkId":2478630510,"time":"2024-01-27T11:50:04.736655452+00:00","deviceInfo":{"tenantId":"52f14cd4-c6f1-4fbd-8f87-4025e1d49242","tenantName":"ChirpStack","applicationId":"59bcc5a7-59e2-4481-9615-fc4e58791915","applicationName":"Mclimate_Vicki","deviceProfileId":"3a9bc28f-3664-4bdf-b3be-a20d1eb32dc8","deviceProfileName":"Mclimate_Vicki","deviceName":"MClimate_Vicki_Heizkoerperventil_001","devEui":"70b3d52dd300ed31","deviceClassEnabled":"CLASS_A","tags":{}},"queueItemId":"efc2bacf-d5da-48d3-a6ef-2a77fda41bd0","fCntDown":4940,"gatewayId":"50313953530a4750","txInfo":{"frequency":868300000,"power":16,"modulation":{"lora":{"bandwidth":125000,"spreadingFactor":7,"codeRate":"CR_4_5","polarizationInversion":true}},"timing":{"delay":{"delay":"1s"}},"context":"eqFuiw=="}};
437
+ // const topic = "application/59bcc5a7-59e2-4481-9615-fc4e58791915/device/70b3d52dd300ed31/event/txack";
438
+ // const message = {"downlinkId":2478630510,"time":"2024-01-27T11:50:04.736655452+00:00","deviceInfo":{"tenantId":"52f14cd4-c6f1-4fbd-8f87-4025e1d49242","tenantName":"ChirpStack","applicationId":"59bcc5a7-59e2-4481-9615-fc4e58791915","applicationName":"Mclimate_Vicki","deviceProfileId":"3a9bc28f-3664-4bdf-b3be-a20d1eb32dc8","deviceProfileName":"Mclimate_Vicki","deviceName":"MClimate_Vicki_Heizkoerperventil_001","devEui":"70b3d52dd300ed31","deviceClassEnabled":"CLASS_A","tags":{}},"queueItemId":"efc2bacf-d5da-48d3-a6ef-2a77fda41bd0","fCntDown":4940,"gatewayId":"50313953530a4750","txInfo":{"frequency":868300000,"power":16,"modulation":{"lora":{"bandwidth":125000,"spreadingFactor":7,"codeRate":"CR_4_5","polarizationInversion":true}},"timing":{"delay":{"delay":"1s"}},"context":"eqFuiw=="}};
439
439
 
440
440
  // STATUS
441
- //const topic = "application/59bcc5a7-59e2-4481-9615-fc4e58791915/device/70b3d52dd300ed31/event/status";
442
- //const message = {"deduplicationId":"4a91b00d-b5e1-4955-b085-ba21b9318213","time":"2024-01-26T20:18:45.299871+00:00","deviceInfo":{"tenantId":"52f14cd4-c6f1-4fbd-8f87-4025e1d49242","tenantName":"ChirpStack","applicationId":"59bcc5a7-59e2-4481-9615-fc4e58791915","applicationName":"Mclimate_Vicki","deviceProfileId":"3a9bc28f-3664-4bdf-b3be-a20d1eb32dc8","deviceProfileName":"Mclimate_Vicki","deviceName":"MClimate_Vicki_Heizkoerperventil_001","devEui":"70b3d52dd300ed31","deviceClassEnabled":"CLASS_A","tags":{}},"margin":7,"externalPowerSource":false,"batteryLevelUnavailable":false,"batteryLevel":85.826775};
441
+ // const topic = "application/59bcc5a7-59e2-4481-9615-fc4e58791915/device/70b3d52dd300ed31/event/status";
442
+ // const message = {"deduplicationId":"4a91b00d-b5e1-4955-b085-ba21b9318213","time":"2024-01-26T20:18:45.299871+00:00","deviceInfo":{"tenantId":"52f14cd4-c6f1-4fbd-8f87-4025e1d49242","tenantName":"ChirpStack","applicationId":"59bcc5a7-59e2-4481-9615-fc4e58791915","applicationName":"Mclimate_Vicki","deviceProfileId":"3a9bc28f-3664-4bdf-b3be-a20d1eb32dc8","deviceProfileName":"Mclimate_Vicki","deviceName":"MClimate_Vicki_Heizkoerperventil_001","devEui":"70b3d52dd300ed31","deviceClassEnabled":"CLASS_A","tags":{}},"margin":7,"externalPowerSource":false,"batteryLevelUnavailable":false,"batteryLevel":85.826775};
443
443
 
444
444
  // UP
445
- //const topic = "application/e91e66ba-1aa7-4bdf-af88-f1246e0b8d75/device/a84041263188b787/event/up";
446
- //const message = {"deduplicationId":"ce1ca35d-35c7-4f60-844c-c2b2810fd74b","time":"2024-08-25T07:10:47.758298+00:00","deviceInfo":{"tenantId":"52f14cd4-c6f1-4fbd-8f87-4025e1d49242","tenantName":"ChirpStack","applicationId":"e91e66ba-1aa7-4bdf-af88-f1246e0b8d75","applicationName":"Türen","deviceProfileId":"431c5895-68e2-478d-945f-f0e9a6f5f9f5","deviceProfileName":"Dragino Türsensoren / Fenstersensoren","deviceName":"Flurtüre","devEui":"a84041263188b787","deviceClassEnabled":"CLASS_A","tags":{}},"devAddr":"0061ebd4","adr":true,"dr":5,"fCnt":8264,"fPort":10,"confirmed":false,"data":"DAYBAA+IAAAAAA==","object":{"ALARM":0.0,"BAT_V":3.078,"CONTACT":true,"OPEN_TIMES":3976.0,"MOD":1.0,"LAST_OPEN_DURATION":0.0,"OPEN":false,"devicetype":"Dragino"},"rxInfo":[{"gatewayId":"503035416e314750","uplinkId":64001,"gwTime":"2024-08-25T07:10:47.758298+00:00","nsTime":"2024-08-25T07:11:29.787667701+00:00","rssi":-68,"snr":9.25,"channel":6,"location":{"latitude":50.69350130173554,"longitude":8.476821184158327},"context":"fp1WbA==","metadata":{"region_common_name":"EU868","region_config_id":"eu868"},"crcStatus":"CRC_OK"}],"txInfo":{"frequency":867700000,"modulation":{"lora":{"bandwidth":125000,"spreadingFactor":7,"codeRate":"CR_4_5"}}}};
445
+ // const topic = "application/e91e66ba-1aa7-4bdf-af88-f1246e0b8d75/device/a84041263188b787/event/up";
446
+ // const message = {"deduplicationId":"ce1ca35d-35c7-4f60-844c-c2b2810fd74b","time":"2024-08-25T07:10:47.758298+00:00","deviceInfo":{"tenantId":"52f14cd4-c6f1-4fbd-8f87-4025e1d49242","tenantName":"ChirpStack","applicationId":"e91e66ba-1aa7-4bdf-af88-f1246e0b8d75","applicationName":"Türen","deviceProfileId":"431c5895-68e2-478d-945f-f0e9a6f5f9f5","deviceProfileName":"Dragino Türsensoren / Fenstersensoren","deviceName":"Flurtüre","devEui":"a84041263188b787","deviceClassEnabled":"CLASS_A","tags":{}},"devAddr":"0061ebd4","adr":true,"dr":5,"fCnt":8264,"fPort":10,"confirmed":false,"data":"DAYBAA+IAAAAAA==","object":{"ALARM":0.0,"BAT_V":3.078,"CONTACT":true,"OPEN_TIMES":3976.0,"MOD":1.0,"LAST_OPEN_DURATION":0.0,"OPEN":false,"devicetype":"Dragino"},"rxInfo":[{"gatewayId":"503035416e314750","uplinkId":64001,"gwTime":"2024-08-25T07:10:47.758298+00:00","nsTime":"2024-08-25T07:11:29.787667701+00:00","rssi":-68,"snr":9.25,"channel":6,"location":{"latitude":50.69350130173554,"longitude":8.476821184158327},"context":"fp1WbA==","metadata":{"region_common_name":"EU868","region_config_id":"eu868"},"crcStatus":"CRC_OK"}],"txInfo":{"frequency":867700000,"modulation":{"lora":{"bandwidth":125000,"spreadingFactor":7,"codeRate":"CR_4_5"}}}};
447
447
 
448
448
  // LOG
449
- //const topic = "application/59bcc5a7-59e2-4481-9615-fc4e58791915/device/70b3d52dd300ed31/event/up";
450
- //const message = {"time":"2024-01-27T10:29:58.221817559+00:00","deviceInfo":{"tenantId":"52f14cd4-c6f1-4fbd-8f87-4025e1d49242","tenantName":"ChirpStack","applicationId":"59bcc5a7-59e2-4481-9615-fc4e58791915","applicationName":"Mclimate_Vicki","deviceProfileId":"3a9bc28f-3664-4bdf-b3be-a20d1eb32dc8","deviceProfileName":"Mclimate_Vicki","deviceName":"MClimate_Vicki_Heizkoerperventil_001","devEui":"70b3d52dd300ed31","deviceClassEnabled":"CLASS_A","tags":{}},"level":"ERROR","code":"UPLINK_CODEC","description":"Exception generated by quickjs","context":{"deduplication_id":"c44e7e25-09ce-4c95-b96f-5a298c5c6440"}};
449
+ // const topic = "application/59bcc5a7-59e2-4481-9615-fc4e58791915/device/70b3d52dd300ed31/event/up";
450
+ // const message = {"time":"2024-01-27T10:29:58.221817559+00:00","deviceInfo":{"tenantId":"52f14cd4-c6f1-4fbd-8f87-4025e1d49242","tenantName":"ChirpStack","applicationId":"59bcc5a7-59e2-4481-9615-fc4e58791915","applicationName":"Mclimate_Vicki","deviceProfileId":"3a9bc28f-3664-4bdf-b3be-a20d1eb32dc8","deviceProfileName":"Mclimate_Vicki","deviceName":"MClimate_Vicki_Heizkoerperventil_001","devEui":"70b3d52dd300ed31","deviceClassEnabled":"CLASS_A","tags":{}},"level":"ERROR","code":"UPLINK_CODEC","description":"Exception generated by quickjs","context":{"deduplication_id":"c44e7e25-09ce-4c95-b96f-5a298c5c6440"}};
451
451
 
452
452
  // JOIN
453
- //const topic = "application/59bcc5a7-59e2-4481-9615-fc4e58791915/device/70b3d52dd300ed31/event/join";
454
- //const message = {"deduplicationId":"44cef56d-1b8d-45fc-a762-03b98b620db2","time":"2023-12-12T03:13:21.551178+00:00","deviceInfo":{"tenantId":"52f14cd4-c6f1-4fbd-8f87-4025e1d49242","tenantName":"ChirpStack","applicationId":"59bcc5a7-59e2-4481-9615-fc4e58791915","applicationName":"Mclimate_Vicki","deviceProfileId":"3a9bc28f-3664-4bdf-b3be-a20d1eb32dc8","deviceProfileName":"Mclimate_Vicki","deviceName":"MClimate_Vicki_Heizkoerperventil_001","devEui":"70b3d52dd300ed31","deviceClassEnabled":"CLASS_A","tags":{}},"devAddr":"01009400"};
453
+ // const topic = "application/59bcc5a7-59e2-4481-9615-fc4e58791915/device/70b3d52dd300ed31/event/join";
454
+ // const message = {"deduplicationId":"44cef56d-1b8d-45fc-a762-03b98b620db2","time":"2023-12-12T03:13:21.551178+00:00","deviceInfo":{"tenantId":"52f14cd4-c6f1-4fbd-8f87-4025e1d49242","tenantName":"ChirpStack","applicationId":"59bcc5a7-59e2-4481-9615-fc4e58791915","applicationName":"Mclimate_Vicki","deviceProfileId":"3a9bc28f-3664-4bdf-b3be-a20d1eb32dc8","deviceProfileName":"Mclimate_Vicki","deviceName":"MClimate_Vicki_Heizkoerperventil_001","devEui":"70b3d52dd300ed31","deviceClassEnabled":"CLASS_A","tags":{}},"devAddr":"01009400"};
455
455
 
456
456
  // DOWN
457
- //const topic = "application/59bcc5a7-59e2-4481-9615-fc4e58791915/device/70b3d52dd300ed31/command/down";
458
- //const message = {"devEui": "70b3d52dd300ed31", "confirmed": false,"fPort": 1,"data": "DQEYDQEY"};
457
+ // const topic = "application/59bcc5a7-59e2-4481-9615-fc4e58791915/device/70b3d52dd300ed31/command/down";
458
+ // const message = {"devEui": "70b3d52dd300ed31", "confirmed": false,"fPort": 1,"data": "DQEYDQEY"};
459
459
 
460
- this.log.debug(`incomming topic: ${topic}`);
461
- this.log.debug(`incomming message: ${JSON.stringify(message)}`);
460
+ this.log.debug(`incoming topic: ${topic}`);
461
+ this.log.debug(`incoming message: ${JSON.stringify(message)}`);
462
462
 
463
463
  await this.messagehandler?.handleMessage(topic, message);
464
464
  }
465
465
  /**
466
- * Is called when adapter shuts down - callback has to be called under any circumstances!
466
+ * Is called when the adapter shuts down - callback has to be called under any circumstances!
467
467
  *
468
468
  * @param callback function wich is called after shutdown adapter
469
469
  */
470
470
  async onUnload(callback) {
471
471
  try {
472
- // Ausgabe der Nachrichtg, dass der Adapter beendet wird
472
+ // Ausgabe der Nachricht, dass der Adapter beendet wird
473
473
  const notificationId = `${this.namespace}.${this.bridge?.Words.notification}${this.bridge?.GeneralId}`;
474
474
  await this.bridge?.publishNotification(
475
475
  notificationId,
@@ -482,7 +482,7 @@ class Lorawan extends utils.Adapter {
482
482
  delete this.simulation.timeout;
483
483
  }
484
484
 
485
- // Clear Schedules in directoriehandler
485
+ // Clear Schedules in the directory handler
486
486
  this.messagehandler?.clearAllSchedules();
487
487
 
488
488
  // Clear Schedules in Bridge
@@ -495,7 +495,7 @@ class Lorawan extends utils.Adapter {
495
495
  this.mqttClient?.destroy();
496
496
  callback();
497
497
  } catch (e) {
498
- this.log.error(e);
498
+ this.log.error(`error at onUnload: ${e}`);
499
499
  callback();
500
500
  }
501
501
  }
@@ -503,7 +503,7 @@ class Lorawan extends utils.Adapter {
503
503
  /**
504
504
  * Is called if a subscribed object changes
505
505
  *
506
- * @param id id of the changed object
506
+ * @param id ID of the changed object
507
507
  * @param obj value and ack of the changed object
508
508
  */
509
509
  async onObjectChange(id, obj) {
@@ -520,7 +520,7 @@ class Lorawan extends utils.Adapter {
520
520
 
521
521
  // External States
522
522
  } else {
523
- // Only work, if bridge is activ
523
+ // Only work if bridge is activ
524
524
  if (this.bridge) {
525
525
  // Erzeugen der HA Bridged für Control
526
526
  // check for new Entry
@@ -555,7 +555,7 @@ class Lorawan extends utils.Adapter {
555
555
  /**
556
556
  * Is called if a subscribed state changes
557
557
  *
558
- * @param id id of the changed state
558
+ * @param id ID of the changed state
559
559
  * @param state value and ack of the changed state
560
560
  */
561
561
  async onStateChange(id, state) {
@@ -608,31 +608,31 @@ class Lorawan extends utils.Adapter {
608
608
  changeInfo.bestMatchForDeviceType
609
609
  ];
610
610
  /* Alte Zuweisung
611
- const Statevalues = state.val.split(',');
611
+ const stateValues = state.val.split(',');
612
612
  const StateElements = {
613
- payloadInHex: Statevalues[0].toUpperCase(),
613
+ payloadInHex: stateValues [0].toUpperCase(),
614
614
  port: downlinkConfig.port,
615
615
  confirmed: downlinkConfig.confirmed,
616
616
  priority: downlinkConfig.priority,
617
617
  push: false,
618
618
  };
619
619
  // Assign writen values
620
- for (const element in Statevalues) {
621
- if (Statevalues[element] === 'push') {
620
+ for (const element in stateValues ) {
621
+ if (stateValues [element] === 'push') {
622
622
  StateElements.push = true;
623
623
  break;
624
624
  }
625
625
  if (element === '1') {
626
- StateElements.port = Number(Statevalues[element]);
626
+ StateElements.port = Number(stateValues [element]);
627
627
  } else if (element === '2') {
628
- StateElements.confirmed = Statevalues[element] === 'true' ? true : false;
628
+ StateElements.confirmed = stateValues [element] === 'true' ? true : false;
629
629
  } else if (element === '3') {
630
630
  StateElements.priority = Statevalues[element];
631
631
  }
632
632
  }
633
633
  */
634
634
  // Eingefügt am 09.12.2026
635
- const Statevalues = state.val.split(',');
635
+ const StateValues = state.val.split(',');
636
636
 
637
637
  const StateElements = {
638
638
  payloadInHex: null,
@@ -642,7 +642,7 @@ class Lorawan extends utils.Adapter {
642
642
  push: false,
643
643
  };
644
644
 
645
- for (const raw of Statevalues) {
645
+ for (const raw of StateValues) {
646
646
  const element = raw.trim();
647
647
 
648
648
  // --- push ---
@@ -676,7 +676,7 @@ class Lorawan extends utils.Adapter {
676
676
  }
677
677
  }
678
678
 
679
- // Query about th correct type
679
+ // Query about the correct type
680
680
  this.log.silly(
681
681
  'The following values are detected / used at input of custom send state',
682
682
  );
@@ -686,7 +686,7 @@ class Lorawan extends utils.Adapter {
686
686
  );
687
687
  }
688
688
 
689
- // write into NextSend, or push directly
689
+ // write into NextSend or push directly
690
690
  if (!StateElements.push) {
691
691
  // Write into nextSend
692
692
  await this.writeNextSend(changeInfo, StateElements.payloadInHex);
@@ -759,11 +759,11 @@ class Lorawan extends utils.Adapter {
759
759
  await this.setState(id, false, true);
760
760
  }
761
761
  } else if (id.indexOf('.configuration.') !== -1) {
762
- // State is from configuration path
762
+ // State is from the configuration path
763
763
  const changeInfo = await this.getChangeInfo(id, { withBestMatch: true });
764
764
  this.messagehandler?.fillWithDownlinkConfig(changeInfo?.objectStartDirectory, {});
765
765
 
766
- // remove not configed states
766
+ // remove not configured states
767
767
  const adapterObjects = await this.getAdapterObjectsAsync();
768
768
  for (const adapterObject of Object.values(adapterObjects)) {
769
769
  if (
@@ -826,8 +826,8 @@ class Lorawan extends utils.Adapter {
826
826
  },
827
827
  native: {},
828
828
  });
829
- // Incomming
830
- this.extendObject('bridge.debug.incommingTopic', {
829
+ // Incoming
830
+ this.extendObject('bridge.debug.incomingTopic', {
831
831
  type: 'state',
832
832
  common: {
833
833
  name: 'topic of mqtt message',
@@ -838,7 +838,7 @@ class Lorawan extends utils.Adapter {
838
838
  },
839
839
  native: {},
840
840
  });
841
- this.extendObject('bridge.debug.incommingTopicFilter', {
841
+ this.extendObject('bridge.debug.incomingTopicFilter', {
842
842
  type: 'state',
843
843
  common: {
844
844
  name: 'filter for topic of mqtt message',
@@ -849,7 +849,7 @@ class Lorawan extends utils.Adapter {
849
849
  },
850
850
  native: {},
851
851
  });
852
- this.extendObject('bridge.debug.incommingPayload', {
852
+ this.extendObject('bridge.debug.incomingPayload', {
853
853
  type: 'state',
854
854
  common: {
855
855
  name: 'payload of mqtt message',
@@ -910,6 +910,7 @@ class Lorawan extends utils.Adapter {
910
910
  },
911
911
  native: {},
912
912
  });
913
+ await this.setState(id, '', true);
913
914
  }
914
915
  } else {
915
916
  let notificationId = `${this.namespace}.${this.bridge?.Words.notification}${this.bridge?.GeneralId}`;
@@ -920,8 +921,8 @@ class Lorawan extends utils.Adapter {
920
921
  );
921
922
  await this.setState(id, state.val, true);
922
923
  }
923
- } else if (id.endsWith('bridge.debug.incommingTopicFilter')) {
924
- this.bridge?.bridgeMqttClient.setFilter('incomming', state.val);
924
+ } else if (id.endsWith('bridge.debug.incomingTopicFilter')) {
925
+ this.bridge?.bridgeMqttClient.setFilter('incoming', state.val);
925
926
  await this.setState(id, state.val, true);
926
927
  } else if (id.endsWith('bridge.debug.outgoingTopicFilter')) {
927
928
  this.bridge?.bridgeMqttClient.setFilter('outgoing', state.val);
@@ -931,7 +932,7 @@ class Lorawan extends utils.Adapter {
931
932
  const topic = await this.getStateAsync('bridge.debug.topic');
932
933
  const payload = await this.getStateAsync('bridge.debug.payload');
933
934
  if (topic && payload) {
934
- this.bridge?.bridgeMqttClient.publish(topic.val, payload.val, {});
935
+ await this.bridge?.bridgeMqttClient.publish(topic.val, payload.val, {});
935
936
  await this.setState('bridge.debug.topic', topic.val, true);
936
937
  await this.setState('bridge.debug.payload', payload.val, true);
937
938
  }
@@ -989,7 +990,7 @@ class Lorawan extends utils.Adapter {
989
990
  changeInfo.bestMatchForDeviceType &&
990
991
  (this.downlinkConfighandler?.activeDownlinkConfigs[changeInfo.bestMatchForDeviceType].sendWithUplink !==
991
992
  'disabled' ||
992
- (options && options.pushNextSend))
993
+ options?.pushNextSend)
993
994
  ) {
994
995
  const nextSend = await this.getNextSend(changeInfo?.objectStartDirectory);
995
996
  if (nextSend?.val !== '0') {
@@ -1026,7 +1027,7 @@ class Lorawan extends utils.Adapter {
1026
1027
  const idFolderNextSend = `${changeInfo.objectStartDirectory}.${this.messagehandler?.directoryhandler.reachableSubfolders.downlinkNextSend}`;
1027
1028
  const stateId = `${idFolderNextSend}.hex`;
1028
1029
 
1029
- // Serialize (also simple write without append)
1030
+ // Serialize (also simply write without appending)
1030
1031
  await this.withLock(this.NextSendLocks, stateId, async () => {
1031
1032
  let toWrite = payloadInHex;
1032
1033
  if (
@@ -1094,7 +1095,7 @@ class Lorawan extends utils.Adapter {
1094
1095
  }
1095
1096
 
1096
1097
  getHexpayloadFromDownlink(downlinkmessage) {
1097
- const activeFunction = 'main.js - getHexpayloadFromDownlink';
1098
+ const activeFunction = 'main.js - getHexPayloadFromDownlink';
1098
1099
  this.log.silly(`Function ${activeFunction} started.`);
1099
1100
  try {
1100
1101
  let downlink = downlinkmessage;
@@ -1125,7 +1126,7 @@ class Lorawan extends utils.Adapter {
1125
1126
  id = this.removeNamespace(id);
1126
1127
  const idElements = id.split('.');
1127
1128
  const deviceInfo = {
1128
- id: id,
1129
+ id,
1129
1130
  applicationId: idElements[0],
1130
1131
  deviceEUI: idElements[2],
1131
1132
  changedState: idElements[idElements.length - 1],
@@ -1144,13 +1145,14 @@ class Lorawan extends utils.Adapter {
1144
1145
  // Check for logging
1145
1146
  this.log[this.logtypes.getChangeInfo]?.(`changeinfo of id ${id}, will be generated.`);
1146
1147
  const changeInfo = this.getBaseDeviceInfo(id);
1147
- const myId = `${changeInfo?.objectStartDirectory}.${this.messagehandler?.directoryhandler.reachableSubfolders.configuration}.devicetype`; // commented out on: 26.01.2026 => Use objectStore
1148
+ // const myId = `${changeInfo?.objectStartDirectory}.${this.messagehandler?.directoryhandler.reachableSubfolders.configuration}.devicetype`; // commented out on: 26.01.2026 => Use objectStore
1148
1149
  // Check for changeInfo
1149
1150
  if (changeInfo) {
1150
- const applicationDirectoryObject = await this.getObjectAsync(changeInfo.applicationId); // commented out on: 26.01.2026 => Use objectStore
1151
- const startDirectoryObject = await this.getObjectAsync(changeInfo.objectStartDirectory); // commented out on: 26.01.2026 => Use objectStore
1152
- //const applicationDirectoryObject = this.objectStore?.applications[changeInfo.applicationId].object;
1153
- //const startDirectoryObject = this.objectStore?.devices[changeInfo.deviceEUI].object;
1151
+ // Get Object from start directory
1152
+ // const applicationDirectoryObject = await this.getObjectAsync(changeInfo.applicationId); // commented out on: 26.01.2026 => Use objectStore
1153
+ // const startDirectoryObject = await this.getObjectAsync(changeInfo.objectStartDirectory); // commented out on: 26.01.2026 => Use objectStore
1154
+ const applicationDirectoryObject = this.objectStore?.applications[changeInfo.applicationId].object;
1155
+ const startDirectoryObject = this.objectStore?.devices[changeInfo.deviceEUI].object;
1154
1156
  if (applicationDirectoryObject && startDirectoryObject) {
1155
1157
  changeInfo.applicationName = applicationDirectoryObject.native.applicationName;
1156
1158
  changeInfo.usedApplicationName = applicationDirectoryObject.common.name;
@@ -1158,12 +1160,12 @@ class Lorawan extends utils.Adapter {
1158
1160
  changeInfo.usedDeviceId = startDirectoryObject.common.name;
1159
1161
  }
1160
1162
  // Get deviceType
1161
- const deviceTypeIdState = await this.getStateAsync(myId); // commented out on: 26.01.2026 => Use objectStore
1162
- //const deviceTypeIdState = this.objectStore?.devices[changeInfo.deviceEUI].informations.devicetype.state;
1163
+ // const deviceTypeIdState = await this.getStateAsync(myId); // commented out on: 26.01.2026 => Use objectStore
1164
+ const deviceTypeIdState = this.objectStore?.devices[changeInfo.deviceEUI].informations.devicetype.state;
1163
1165
  if (deviceTypeIdState) {
1164
1166
  changeInfo.deviceType = deviceTypeIdState.val;
1165
1167
  if (options && options.withBestMatch) {
1166
- // Get best match of expert downlink
1168
+ // Get the best match of expert downlink
1167
1169
  const bestMatchForDeviceType =
1168
1170
  this.downlinkConfighandler?.getBestMatchForDeviceType(changeInfo);
1169
1171
  if (bestMatchForDeviceType) {
@@ -1195,13 +1197,14 @@ class Lorawan extends utils.Adapter {
1195
1197
  }
1196
1198
 
1197
1199
  // Get Changeinfo in case of device EUI (used more times in onMessage)
1198
- async getChangeInfoFromDeviceEUI(deviceUI, subId) {
1200
+ async getChangeInfoFromDeviceEUI(deviceUI, subId = '') {
1199
1201
  let changeInfo = undefined;
1200
1202
  const adapterObjects = await this.getAdapterObjectsAsync();
1201
1203
  for (const adapterObject of Object.values(adapterObjects)) {
1202
1204
  if (adapterObject.type === 'device') {
1203
1205
  if (adapterObject._id.indexOf(deviceUI) !== -1) {
1204
- changeInfo = await this.getChangeInfo(`${adapterObject._id}.${subId}`);
1206
+ const sufix = subId !== '' ? `.${subId}` : '';
1207
+ changeInfo = await this.getChangeInfo(`${adapterObject._id}${sufix}`);
1205
1208
  break;
1206
1209
  }
1207
1210
  }
@@ -1211,12 +1214,16 @@ class Lorawan extends utils.Adapter {
1211
1214
 
1212
1215
  // If you need to accept messages in your adapter, uncomment the following block and the corresponding line in the constructor.
1213
1216
  // /**
1214
- // * Some message was sent to this instance over message box. Used by email, pushover, text2speech, ...
1217
+ // * Some message was sent to this instance over the message box. Used by email, pushover, text2speech, ...
1215
1218
  // * Using this method requires "common.messagebox" property to be set to true in io-package.json
1216
1219
  // * @param {ioBroker.Message} obj
1217
1220
  // */
1218
1221
 
1219
1222
  async onMessage(obj) {
1223
+ if (obj.command?.startsWith('dm:')) {
1224
+ // Handled by Device Manager class itself, so ignored here
1225
+ return;
1226
+ }
1220
1227
  const activeFunction = 'onMessage';
1221
1228
  this.log.silly(`message received: command = ${obj.command} - message = ${JSON.stringify(obj.message)}`);
1222
1229
  try {
@@ -1473,7 +1480,7 @@ class Lorawan extends utils.Adapter {
1473
1480
  this.sendTo(obj.from, obj.command, applications, obj.callback);
1474
1481
  });
1475
1482
  } catch (error) {
1476
- this.log.error(error);
1483
+ this.log.error(`Error by command ${obj.command}: ${error}`);
1477
1484
  }
1478
1485
  } else if (obj.command === 'getDevicesForConfig' || obj.command === 'getDevicesForClimateConfig') {
1479
1486
  try {
@@ -1504,7 +1511,7 @@ class Lorawan extends utils.Adapter {
1504
1511
  this.sendTo(obj.from, obj.command, devices, obj.callback);
1505
1512
  });
1506
1513
  } catch (error) {
1507
- this.log.error(error);
1514
+ this.log.error(`Error by command ${obj.command}: ${error}`);
1508
1515
  }
1509
1516
  } else if (obj.command === 'getFoldersForConfig') {
1510
1517
  try {
@@ -1517,7 +1524,7 @@ class Lorawan extends utils.Adapter {
1517
1524
  this.sendTo(obj.from, obj.command, devices, obj.callback);
1518
1525
  });
1519
1526
  } catch (error) {
1520
- this.log.error(error);
1527
+ this.log.error(`Error by command ${obj.command}: ${error}`);
1521
1528
  }
1522
1529
  } else if (obj.command === 'getStatesForConfig' || obj.command === 'getStatesForClimateConfig') {
1523
1530
  try {
@@ -1546,21 +1553,21 @@ class Lorawan extends utils.Adapter {
1546
1553
  //adapterObject._id = this.removeNamespace(adapterObject._id); remooved 30.122025
1547
1554
  const changeInfo = await this.getChangeInfoCached(adapterObject._id);
1548
1555
  //if uplink decoded => changed State with folder
1549
- let fullStatename = changeInfo?.changedState;
1556
+ let fullStateName = changeInfo?.changedState;
1550
1557
  if (changeInfo?.allElements.length > 6) {
1551
- fullStatename = '';
1558
+ fullStateName = '';
1552
1559
  for (let i = 5; i < changeInfo?.allElements.length; i++) {
1553
- if (fullStatename !== '') {
1554
- fullStatename += '.';
1560
+ if (fullStateName !== '') {
1561
+ fullStateName += '.';
1555
1562
  }
1556
- fullStatename += changeInfo?.allElements[i];
1563
+ fullStateName += changeInfo?.allElements[i];
1557
1564
  }
1558
1565
  }
1559
1566
  if (adapterObject.type === 'folder') {
1560
- fullStatename += '.';
1567
+ fullStateName += '.';
1561
1568
  }
1562
- const label = fullStatename;
1563
- const value = fullStatename;
1569
+ const label = fullStateName;
1570
+ const value = fullStateName;
1564
1571
  if (!currentStates[value]) {
1565
1572
  currentStates[value] = value;
1566
1573
  states[myCount] = { label: label, value: value };
@@ -1572,7 +1579,7 @@ class Lorawan extends utils.Adapter {
1572
1579
  this.sendTo(obj.from, obj.command, states, obj.callback);
1573
1580
  });
1574
1581
  } catch (error) {
1575
- this.log.error(error);
1582
+ this.log.error(`Error by command ${obj.command}: ${error}`);
1576
1583
  }
1577
1584
  } else if (obj.command === 'getDiscoveredIds') {
1578
1585
  try {
@@ -1585,7 +1592,7 @@ class Lorawan extends utils.Adapter {
1585
1592
  obj.callback,
1586
1593
  );
1587
1594
  } catch (error) {
1588
- this.log.error(error);
1595
+ this.log.error(`Error by command ${obj.command}: ${error}`);
1589
1596
  }
1590
1597
  } else if (obj.command === 'getPublishedIds') {
1591
1598
  try {
@@ -1598,7 +1605,7 @@ class Lorawan extends utils.Adapter {
1598
1605
  obj.callback,
1599
1606
  );
1600
1607
  } catch (error) {
1601
- this.log.error(error);
1608
+ this.log.error(`Error by command ${obj.command}: ${error}`);
1602
1609
  }
1603
1610
  } else if (obj.command === 'getSubscribedTopics') {
1604
1611
  try {
@@ -1611,7 +1618,7 @@ class Lorawan extends utils.Adapter {
1611
1618
  obj.callback,
1612
1619
  );
1613
1620
  } catch (error) {
1614
- this.log.error(error);
1621
+ this.log.error(`Error by command ${obj.command}: ${error}`);
1615
1622
  }
1616
1623
  } else if (obj.command === 'getDeviceinformations') {
1617
1624
  try {
@@ -1622,14 +1629,14 @@ class Lorawan extends utils.Adapter {
1622
1629
  obj.callback,
1623
1630
  );
1624
1631
  } catch (error) {
1625
- this.log.error(error);
1632
+ this.log.error(`Error by command ${obj.command}: ${error}`);
1626
1633
  }
1627
1634
  } else if (obj.command === 'getEnums') {
1628
1635
  try {
1629
1636
  const enums = [{ label: 'No Enum selected', value: '*' }];
1630
1637
  const enumList = await this.getEnumsAsync();
1631
- for (const enumtyp of Object.values(enumList)) {
1632
- for (const myEnum of Object.values(enumtyp)) {
1638
+ for (const enumTyp of Object.values(enumList)) {
1639
+ for (const myEnum of Object.values(enumTyp)) {
1633
1640
  const value = myEnum._id;
1634
1641
  let label = myEnum.common.name;
1635
1642
  if (typeof label !== 'string') {
@@ -1643,13 +1650,13 @@ class Lorawan extends utils.Adapter {
1643
1650
  }
1644
1651
  this.sendTo(obj.from, obj.command, enums, obj.callback);
1645
1652
  } catch (error) {
1646
- this.log.error(error);
1653
+ this.log.error(`Error by command ${obj.command}: ${error}`);
1647
1654
  }
1648
1655
  } else if (obj.command === 'getBridgeConnection') {
1649
1656
  try {
1650
1657
  let connection = false;
1651
- const mqttprefix = obj.message.Bridgessl ? 'mqtts://' : 'mqtt://';
1652
- const testclient = mqtt.connect(`${mqttprefix}${obj.message.BridgeipUrl}`, {
1658
+ const mqttPrefix = obj.message.Bridgessl ? 'mqtts://' : 'mqtt://';
1659
+ const testclient = mqtt.connect(`${mqttPrefix}${obj.message.BridgeipUrl}`, {
1653
1660
  port: obj.message.Bridgeport,
1654
1661
  username: obj.message.Bridgeusername,
1655
1662
  password: obj.message.Bridgepassword,
@@ -1672,15 +1679,15 @@ class Lorawan extends utils.Adapter {
1672
1679
  );
1673
1680
  }, 100);
1674
1681
  } catch (error) {
1675
- this.log.error(error);
1682
+ this.log.error(`Error by command ${obj.command}: ${error}`);
1676
1683
  }
1677
1684
  } else if (obj.command === 'sendMQTTMessage') {
1678
1685
  try {
1679
- this.log.error(typeof obj.message.Topic);
1686
+ this.log.error(`Error by ${obj.command}: ${typeof obj.message.Topic}`);
1680
1687
  this.log.error(typeof obj.message.Message);
1681
1688
  this.sendTo(obj.from, obj.command, { result: 'OK' }, obj.callback);
1682
1689
  } catch (error) {
1683
- this.log.error(error);
1690
+ this.log.error(`Error by command ${obj.command}: ${error}`);
1684
1691
  }
1685
1692
  } else {
1686
1693
  const result = { error: true, message: 'No message matched', received: obj.message };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.lorawan",
3
- "version": "1.20.10",
3
+ "version": "1.20.11",
4
4
  "description": "converts the desired lora gateway data to a ioBroker structure",
5
5
  "author": {
6
6
  "name": "BenAhrdt",