iobroker.lorawan 1.20.10 → 1.20.13
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 +9 -0
- package/admin/i18n/de/translations.json +2 -0
- package/admin/i18n/en/translations.json +3 -1
- package/admin/i18n/es/translations.json +2 -0
- package/admin/i18n/fr/translations.json +2 -0
- package/admin/i18n/it/translations.json +2 -0
- package/admin/i18n/nl/translations.json +2 -0
- package/admin/i18n/pl/translations.json +2 -0
- package/admin/i18n/pt/translations.json +2 -0
- package/admin/i18n/ru/translations.json +2 -0
- package/admin/i18n/uk/translations.json +2 -0
- package/admin/i18n/zh-cn/translations.json +2 -0
- package/io-package.json +42 -42
- package/lib/modules/bridge.js +6 -6
- package/lib/modules/bridgeMqttclient.js +10 -10
- package/lib/modules/deviceManager.js +98 -43
- package/lib/modules/mqttclient.js +2 -2
- package/main.js +105 -98
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,6 +23,15 @@ 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.13 (2026-01-26)
|
|
27
|
+
* (BenAhrdt) remove nod from crypto
|
|
28
|
+
|
|
29
|
+
### 1.20.12 (2026-01-26)
|
|
30
|
+
* (BenAhrdt) check for update
|
|
31
|
+
|
|
32
|
+
### 1.20.11 (2026-01-26)
|
|
33
|
+
* (BenAhrdt) improve device Manager icons and Buttons
|
|
34
|
+
|
|
26
35
|
### 1.20.10 (2026-01-26)
|
|
27
36
|
* (BenAhrdt) return to root getCnageInfo
|
|
28
37
|
|
|
@@ -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": "Фактична вологість",
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,47 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "lorawan",
|
|
4
|
-
"version": "1.20.
|
|
4
|
+
"version": "1.20.13",
|
|
5
5
|
"news": {
|
|
6
|
+
"1.20.13": {
|
|
7
|
+
"en": "remove nod from crypto",
|
|
8
|
+
"de": "nod from crypto entfernen",
|
|
9
|
+
"ru": "удалить nod из crypto",
|
|
10
|
+
"pt": "remover aceno do cripto",
|
|
11
|
+
"nl": "verwijderen knik uit crypto",
|
|
12
|
+
"fr": "enlever le noeud de crypto",
|
|
13
|
+
"it": "rimuovere il nodo da crypto",
|
|
14
|
+
"es": "quitar el fideo de cripto",
|
|
15
|
+
"pl": "usunąć skinienie z krypto",
|
|
16
|
+
"uk": "видалити nod з крипто",
|
|
17
|
+
"zh-cn": "从加密中删除点头"
|
|
18
|
+
},
|
|
19
|
+
"1.20.12": {
|
|
20
|
+
"en": "check for update",
|
|
21
|
+
"de": "überprüfung der aktualisierung",
|
|
22
|
+
"ru": "проверьте обновление",
|
|
23
|
+
"pt": "verificar a actualização",
|
|
24
|
+
"nl": "controleren op update",
|
|
25
|
+
"fr": "vérifier la mise à jour",
|
|
26
|
+
"it": "controllare per l'aggiornamento",
|
|
27
|
+
"es": "check for update",
|
|
28
|
+
"pl": "sprawdzanie aktualizacji",
|
|
29
|
+
"uk": "реєстрація на оновлення",
|
|
30
|
+
"zh-cn": "检查更新"
|
|
31
|
+
},
|
|
32
|
+
"1.20.11": {
|
|
33
|
+
"en": "improve device Manager icons and Buttons",
|
|
34
|
+
"de": "verbesserung der Vorrichtung Icons und Buttons verwalten",
|
|
35
|
+
"ru": "улучшить устройство Иконки менеджера и кнопки",
|
|
36
|
+
"pt": "melhorar o dispositivo Gerir ícones e botões",
|
|
37
|
+
"nl": "apparaat verbeteren Pictogrammen en knoppen voor de manager",
|
|
38
|
+
"fr": "améliorer l'appareil Icônes de gestionnaire et boutons",
|
|
39
|
+
"it": "migliorare il dispositivo Icone Manager e pulsanti",
|
|
40
|
+
"es": "mejorar el dispositivo Gestor de iconos y botones",
|
|
41
|
+
"pl": "ulepszenie urządzenia Ikony menedżera i przyciski",
|
|
42
|
+
"uk": "поліпшення пристрою Ім'я користувача",
|
|
43
|
+
"zh-cn": "改进设备 管理器图标和按钮"
|
|
44
|
+
},
|
|
6
45
|
"1.20.10": {
|
|
7
46
|
"en": "return to root getCnageInfo",
|
|
8
47
|
"de": "zurück zu root getCnageInfo",
|
|
@@ -54,45 +93,6 @@
|
|
|
54
93
|
"pl": "bugfix prawidłowe pisanie wskaźników",
|
|
55
94
|
"uk": "виправлення правильних показників",
|
|
56
95
|
"zh-cn": "错误修正正确的指标写法"
|
|
57
|
-
},
|
|
58
|
-
"1.20.6": {
|
|
59
|
-
"en": "updateing assignhandler und modifying indicators and informations",
|
|
60
|
-
"de": "aktualisierung von assignhandler und änderung von indikatoren und informationen",
|
|
61
|
-
"ru": "обновление цессионера и изменение показателей и информации",
|
|
62
|
-
"pt": "atualização de indicadores e informações de atribuição e modificação",
|
|
63
|
-
"nl": "actualisering van indicatoren en informatie",
|
|
64
|
-
"fr": "mettre à jour les indicateurs et les informations d'attribution et de modification",
|
|
65
|
-
"it": "aggiornamento assegnatore und modifica degli indicatori e delle informazioni",
|
|
66
|
-
"es": "actualización del cedente nod modificando indicadores e informaciones",
|
|
67
|
-
"pl": "aktualizowanie identyfikatorów i modyfikowanie wskaźników i informacji",
|
|
68
|
-
"uk": "оновлення вивіски унд модифікації індикаторів та інформації",
|
|
69
|
-
"zh-cn": "更新指定手控器未修改指标和信息"
|
|
70
|
-
},
|
|
71
|
-
"1.20.5": {
|
|
72
|
-
"en": "bugfixing updating object Store with not alowed id",
|
|
73
|
-
"de": "bugfixing update object Store with not alowed id",
|
|
74
|
-
"ru": "bugfixing Update Object Store с невысоким идентификатором",
|
|
75
|
-
"pt": "correcção de erros para actualizar o objecto Armazenar sem ID abaixado",
|
|
76
|
-
"nl": "bugfixing update object Store with not alowed id",
|
|
77
|
-
"fr": "bugfixing update object Store avec id non alowed",
|
|
78
|
-
"it": "bugfixing aggiornamento oggetti Store con non alowed id",
|
|
79
|
-
"es": "bugfixing actualización objeto Store with not alowed id",
|
|
80
|
-
"pl": "bugfitting aktualizacja obiektu Przechowuj bez przypisanego id",
|
|
81
|
-
"uk": "виправлення помилок оновлення об'єкту Store з не потовщеним id",
|
|
82
|
-
"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": "
|
|
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
|
},
|
package/lib/modules/bridge.js
CHANGED
|
@@ -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] ||
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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 = {
|
|
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.
|
|
33
|
-
this.filter.
|
|
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(
|
|
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(`
|
|
109
|
-
this.adapter.log.debug(`
|
|
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.
|
|
116
|
-
if (topic.includes(this.filter.
|
|
117
|
-
await this.adapter.setState('bridge.debug.
|
|
118
|
-
await this.adapter.setState('bridge.debug.
|
|
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:
|
|
29
|
+
id: key,
|
|
31
30
|
name: value.object.common.name,
|
|
32
|
-
icon:
|
|
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
|
|
100
|
+
* @param deviceValue values of device
|
|
104
101
|
*/
|
|
105
|
-
async getIcon(
|
|
106
|
-
if (
|
|
107
|
-
if (
|
|
102
|
+
async getIcon(deviceValue) {
|
|
103
|
+
if (deviceValue.indicators) {
|
|
104
|
+
if (deviceValue.indicators.isThermostat) {
|
|
108
105
|
return 'thermostat';
|
|
109
|
-
} else if (
|
|
106
|
+
} else if (deviceValue.indicators.isDoor) {
|
|
110
107
|
return 'door';
|
|
111
|
-
} else if (
|
|
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
|
|
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
|
|
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.
|
|
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
|
-
|
|
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(`
|
|
81
|
-
this.adapter.log.debug(`
|
|
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
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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(`
|
|
461
|
-
this.log.debug(`
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
611
|
+
const stateValues = state.val.split(',');
|
|
612
612
|
const StateElements = {
|
|
613
|
-
payloadInHex:
|
|
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
|
|
621
|
-
if (
|
|
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(
|
|
626
|
+
StateElements.port = Number(stateValues [element]);
|
|
627
627
|
} else if (element === '2') {
|
|
628
|
-
StateElements.confirmed =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
//
|
|
830
|
-
this.extendObject('bridge.debug.
|
|
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.
|
|
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.
|
|
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.
|
|
924
|
-
this.bridge?.bridgeMqttClient.setFilter('
|
|
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
|
-
|
|
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
|
|
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 -
|
|
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
|
|
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
|
-
|
|
1151
|
-
const
|
|
1152
|
-
//const
|
|
1153
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
1556
|
+
let fullStateName = changeInfo?.changedState;
|
|
1550
1557
|
if (changeInfo?.allElements.length > 6) {
|
|
1551
|
-
|
|
1558
|
+
fullStateName = '';
|
|
1552
1559
|
for (let i = 5; i < changeInfo?.allElements.length; i++) {
|
|
1553
|
-
if (
|
|
1554
|
-
|
|
1560
|
+
if (fullStateName !== '') {
|
|
1561
|
+
fullStateName += '.';
|
|
1555
1562
|
}
|
|
1556
|
-
|
|
1563
|
+
fullStateName += changeInfo?.allElements[i];
|
|
1557
1564
|
}
|
|
1558
1565
|
}
|
|
1559
1566
|
if (adapterObject.type === 'folder') {
|
|
1560
|
-
|
|
1567
|
+
fullStateName += '.';
|
|
1561
1568
|
}
|
|
1562
|
-
const label =
|
|
1563
|
-
const value =
|
|
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
|
|
1632
|
-
for (const myEnum of Object.values(
|
|
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
|
|
1652
|
-
const testclient = mqtt.connect(`${
|
|
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 };
|