iobroker.lorawan 1.17.10 → 1.17.12

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,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.17.12 (2025-09-24)
27
+ * (BenAhrdt) Virtual Mode in default selected for Climate Entities
28
+ * (BenAhrdt) improve hidden attribute for climate entitie in LoRaWAN
29
+ * (BenAhrdt) change discovery delete {} => ''
30
+
31
+ ### 1.17.11 (2025-09-23)
32
+ * (BenAhrdt) dont fillDownlinks in case of not implemented messagetype
33
+ * (BenAhrdt) type of json ids changed to string
34
+
26
35
  ### 1.17.10 (2025-09-23)
27
36
  * (BenAhrdt) Update topics und qnique ids
28
37
 
@@ -1409,6 +1409,7 @@
1409
1409
  "label": "Device",
1410
1410
  "default": "*",
1411
1411
  "jsonData": "{\"application\":\"${data.ModeApplication}\"}",
1412
+ "hidden": "data.ModeApplication === 'NotPresent'",
1412
1413
  "command": "getDevicesForClimateConfig",
1413
1414
  "alsoDependsOn":[
1414
1415
  "ModeApplication"
@@ -1424,6 +1425,7 @@
1424
1425
  "attr": "ModeFolder",
1425
1426
  "label": "Folder",
1426
1427
  "default": "uplink.decoded",
1428
+ "hidden": "data.ModeApplication === 'NotPresent'",
1427
1429
  "options": [
1428
1430
  {"label":"uplink.decoded","value":"uplink.decoded"}
1429
1431
  ],
@@ -1440,6 +1442,7 @@
1440
1442
  "default": "No State selected",
1441
1443
  "jsonData": "{\"application\":\"${data.ModeApplication}\",\"device\":\"${data.ModeDevice}\",\"folder\":\"${data.ModeFolder}\"}",
1442
1444
  "command": "getStatesForClimateConfig",
1445
+ "hidden": "data.ModeApplication === 'NotPresent'",
1443
1446
  "noTranslation": true,
1444
1447
  "alsoDependsOn":[
1445
1448
  "ModeApplication",
@@ -1546,7 +1549,7 @@
1546
1549
  "attr": "VirtualMode",
1547
1550
  "label": "VirtualMode",
1548
1551
  "tooltip": "VirtualModeTooltip",
1549
- "default": false,
1552
+ "default": true,
1550
1553
  "xs": 12,
1551
1554
  "sm": 2,
1552
1555
  "md": 2,
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "lorawan",
4
- "version": "1.17.10",
4
+ "version": "1.17.12",
5
5
  "news": {
6
+ "1.17.12": {
7
+ "en": "Virtual Mode in default selected for Climate Entities\nimprove hidden attribute for climate entitie in LoRaWAN\nchange discovery delete {} => ''",
8
+ "de": "Virtueller Modus in Standardeinstellung für Climate Entities\nverbessern Sie das versteckte Attribut für den Klimaschutz in LoRaWAN\nänderung der entdeckung löschen {} => ' '",
9
+ "ru": "Виртуальный режим по умолчанию выбран для климатических объектов\nулучшение скрытого атрибута для климатического объекта в LoRaWAN\nобнаружение изменений удалить {} => \"",
10
+ "pt": "Modo Virtual por omissão seleccionado para Entidades Climáticas\nmelhorar o atributo oculto para o clima em LoRaWAN\nalterar a descoberta apagar {} => ' '",
11
+ "nl": "Virtuele modus in standaard geselecteerd voor klimaatentiteiten\nverbeteren verborgen attribuut voor klimaat entitie in LoRaWAN\nde ontdekking wijzigen delete {} => ' '",
12
+ "fr": "Mode virtuel par défaut sélectionné pour les entités climatiques\naméliorer l'attribut caché pour entitie climatique dans LoRaWAN\nmodifier découverte supprimer {} => ' '",
13
+ "it": "Modalità virtuale in default selezionata per le Entità Climatiche\nmigliorare l'attributo nascosto per il clima in LoRaWAN\ncambiamento scoperta eliminare {} = > ' '",
14
+ "es": "Modo virtual por defecto seleccionado para Entidades climáticas\nmejorar el atributo oculto para el aislamiento climático en LoRaWAN\ncambio de descubrimiento eliminar {} = confianza ' '",
15
+ "pl": "Tryb wirtualny domyślnie wybrany dla podmiotów klimatycznych\npoprawić ukryte atrybuty dla klimatu w LoRaWAN\nzmień odkrycie usuń {} = > ''",
16
+ "uk": "Віртуальний режим за замовчуванням, вибраний для кліматичних обов'язків\nпокращуйте прихований атрибут для ентіту клімату в LoRaWAN\nвидалити зміни {} => ' р",
17
+ "zh-cn": "为气候实体选择默认的虚拟模式\n改善LoRaWAN中气候内涵的隐藏属性\n更改发现删除 {}} '"
18
+ },
19
+ "1.17.11": {
20
+ "en": "dont fillDownlinks in case of not implemented messagetype\ntype of json ids changed to string",
21
+ "de": "nicht ausfüllen Downlinks bei nicht implementiertem Nachrichtentyp\nart der json ids geändert in string",
22
+ "ru": "не заполнять Downlinks в случае нереализованного типа сообщения\nтип json ids изменили на строку",
23
+ "pt": "não preencher Links para baixo em caso de tipo de mensagem não implementado\no tipo de ids json mudou para string",
24
+ "nl": "vullen Downlinks in geval van niet geïmplementeerd berichttype\ntype json-id's veranderd in string",
25
+ "fr": "ne pas remplir Liens vers le bas en cas de type de message non mis en œuvre\ntype d'ids de json changé en chaîne",
26
+ "it": "non riempire Downlinks in caso di messaggio non implementato\ntipo di json ids cambiato in stringa",
27
+ "es": "no te llenes Enlaces descendentes en caso de no aplicar el tipo de mensaje\ntipo json ids cambiados a cadena",
28
+ "pl": "nie wypełniaj Downlinks w przypadku niewdrożonego rodzaju wiadomości\nrodzaj idów json zmienionych na ciąg",
29
+ "uk": "не заповнити Попередження у разі невиконання типу повідомлення\nтип json ids змінився на рядок",
30
+ "zh-cn": "不填满 未执行消息类型时的下行链接\n更改为字符串的 json id 类型"
31
+ },
6
32
  "1.17.10": {
7
33
  "en": "Update topics und qnique ids",
8
34
  "de": "Update-Themen und qnique ids",
@@ -67,32 +93,6 @@
67
93
  "pl": "Sprawdź poprawność identyfikatora stanu zagranicznego w ulepszonym module klimatyzacji",
68
94
  "uk": "Перевірено зовнішній ідентифікатор стану в кліматі покращений",
69
95
  "zh-cn": "改进了气候模块中检查外部状态id"
70
- },
71
- "1.17.5": {
72
- "en": "Improve quere for foreign states in discover foreign climate",
73
- "de": "Verbessern Sie die Abfrage für ausländische Staaten in der Entdecken-Fremdes-Klima-Funktion.",
74
- "ru": "Улучшена обработка запросов для иностранных стран при обнаружении климата в других странах.",
75
- "pt": "Melhorada a consulta para estados estrangeiros no descobrimento do clima estrangeiro.",
76
- "nl": "Verbeter query voor buitenlandse staten in het ontdekken van het buitenlandse klimaat",
77
- "fr": "Amélioration de la requête pour les états étrangers dans la découverte du climat étranger",
78
- "it": "Migliorata la richiesta per gli stati esteri nella scoperta del clima estero",
79
- "es": "Mejorar la consulta para estados extranjeros en descubrir clima extranjero",
80
- "pl": "Popraw zapytanie o stany zagraniczne w odkrywaniu zagranicznego klimatu",
81
- "uk": "Покращено запит для іноземних держав у відкритті зовнішнього клімату",
82
- "zh-cn": "改进了外国气候的查询。"
83
- },
84
- "1.17.4": {
85
- "en": "More debuglogging for Foreign Climate error",
86
- "de": "Mehr Debug-Logging für Fehler bei Fremdklima.",
87
- "ru": "Больше отладочного журналирования для ошибки внешнего климата",
88
- "pt": "Mais debuglogging para erro de Clima Estrangeiro",
89
- "nl": "Meer debuglogging voor fouten in het buitenlandse klimaatsysteem",
90
- "fr": "Plus de debuglogging pour l'erreur Foreign Climate",
91
- "it": "Maggiori dettagli di debug per gli errori relativi al sistema di climatizzazione esterno",
92
- "es": "Más depuración para el error de Clima Externo",
93
- "pl": "Więcej debugowania dla błędu Foreign Climate",
94
- "uk": "Більше відладки для помилки зовнішнього клімату",
95
- "zh-cn": "为外部气候错误添加更多的调试日志记录"
96
96
  }
97
97
  },
98
98
  "titleLang": {
@@ -507,7 +507,7 @@
507
507
  "common": {
508
508
  "role": "json",
509
509
  "name": "Information of all discovered States",
510
- "type": "json",
510
+ "type": "string",
511
511
  "icon": "icons/discover.png",
512
512
  "read": true,
513
513
  "write": false,
@@ -521,7 +521,7 @@
521
521
  "common": {
522
522
  "role": "json",
523
523
  "name": "Information of all Published States",
524
- "type": "json",
524
+ "type": "string",
525
525
  "icon": "icons/discover.png",
526
526
  "read": true,
527
527
  "write": false,
@@ -535,7 +535,7 @@
535
535
  "common": {
536
536
  "role": "json",
537
537
  "name": "Information of all Subscribed Topics",
538
- "type": "json",
538
+ "type": "string",
539
539
  "icon": "icons/discover.png",
540
540
  "read": true,
541
541
  "write": false,
@@ -549,7 +549,7 @@
549
549
  "common": {
550
550
  "role": "json",
551
551
  "name": "Information of all devices",
552
- "type": "json",
552
+ "type": "string",
553
553
  "icon": "icons/deviceinfo.png",
554
554
  "read": true,
555
555
  "write": false,
@@ -235,24 +235,9 @@ class bridgeClass {
235
235
  this.adapter.log.debug(`Function ${activeFunction} started.`);
236
236
  try {
237
237
  if (this.bridgeMqttClient.internalConnectionstate) {
238
- const newDeviceDiscovered = await this.discovery(id, options);
239
- // notify new discovered Devices (new deviceidentifier)
240
- if (newDeviceDiscovered) {
241
- const device = this.DiscoveredIds[id].informations.usedDeviceId;
242
- const application = this.DiscoveredIds[id].informations.usedApplicationName;
243
- const message = `${this.adapter.i18nTranslation['new device discovered']}.\n${this.adapter.i18nTranslation['Device']}: ${device}\n${this.adapter.i18nTranslation['Application']}: ${application}`;
244
- const notificationId = `${this.adapter.namespace}.${this.adapter.bridge.Words.notification}${this.adapter.bridge.GeneralId}`;
245
- await this.adapter.bridge?.publishNotification(
246
- notificationId,
247
- message,
248
- this.adapter.bridge?.Notificationlevel.deviceState,
249
- false,
250
- );
251
- // Delay for publish new entitys
252
- setTimeout(async () => {
253
- await this.publishId(id, Stateval, {});
254
- }, 1000);
255
- } else {
238
+ const discovered = await this.discovery(id, options);
239
+ // only publish if no new id is discovered, because the newId will be published 1s later
240
+ if (!discovered || !discovered.newId) {
256
241
  await this.publishId(id, Stateval, {});
257
242
  }
258
243
  } else {
@@ -717,7 +702,8 @@ class bridgeClass {
717
702
  this.adapter.log.debug(`Function ${activeFunction} started.`);
718
703
  try {
719
704
  // Defaultvalue for discover
720
- let newDeviceDiscovered = false;
705
+ let returnValue = { newDevice: undefined, newId: undefined };
706
+
721
707
  // Query for decoded Folder
722
708
  if (id.includes(`${this.adapter.messagehandler.directoryhandler.reachableSubfolders.uplinkDecoded}.`)) {
723
709
  const changeInfo = await this.adapter.getChangeInfo(id);
@@ -767,7 +753,7 @@ class bridgeClass {
767
753
  DiscoveryObject?.payload.state_topic,
768
754
  );
769
755
  }
770
- await this.publishDiscovery(id, {
756
+ returnValue = await this.publishDiscovery(id, {
771
757
  topic: DiscoveryObject?.topic,
772
758
  payload: structuredClone(DiscoveryObject?.payload),
773
759
  informations: {
@@ -777,11 +763,10 @@ class bridgeClass {
777
763
  usedDeviceId: changeInfo.usedDeviceId,
778
764
  },
779
765
  });
780
- if (await this.checkNewDeviceDiscovered(DiscoveryObject?.payload.device.identifiers[0])) {
781
- newDeviceDiscovered = true;
782
- } else {
783
- newDeviceDiscovered = false;
784
- }
766
+ // Delay for publish new entity
767
+ setTimeout(async () => {
768
+ await this.publishId(id, undefined, {});
769
+ }, 1000);
785
770
  }
786
771
  }
787
772
 
@@ -845,7 +830,7 @@ class bridgeClass {
845
830
  id,
846
831
  );
847
832
  }
848
- await this.publishDiscovery(id, {
833
+ returnValue = await this.publishDiscovery(id, {
849
834
  topic: DiscoveryObject?.topic,
850
835
  payload: structuredClone(DiscoveryObject?.payload),
851
836
  informations: {
@@ -855,15 +840,14 @@ class bridgeClass {
855
840
  usedDeviceId: changeInfo.usedDeviceId,
856
841
  },
857
842
  });
858
- if (await this.checkNewDeviceDiscovered(DiscoveryObject?.payload.device.identifiers[0])) {
859
- newDeviceDiscovered = true;
860
- } else {
861
- newDeviceDiscovered = false;
862
- }
843
+ // Delay for publish new entity
844
+ setTimeout(async () => {
845
+ await this.publishId(id, undefined, {});
846
+ }, 1000);
863
847
  }
864
848
  }
865
849
  }
866
- return newDeviceDiscovered;
850
+ return returnValue;
867
851
  } catch (error) {
868
852
  this.adapter.log.error(`error at ${activeFunction}: ${error}`);
869
853
  }
@@ -986,6 +970,7 @@ class bridgeClass {
986
970
  async publishDiscovery(id, DiscoveryObject) {
987
971
  const activeFunction = 'bridge.js - publishDiscovery';
988
972
  this.adapter.log.debug(`Function ${activeFunction} started.`);
973
+ const returnValue = { newDevice: undefined, newId: undefined };
989
974
  try {
990
975
  if (!DiscoveryObject.lastDiscover) {
991
976
  DiscoveryObject.lastDiscover = {};
@@ -997,13 +982,56 @@ class bridgeClass {
997
982
  // @ts-expect-error
998
983
  this.Timeoutput.Format,
999
984
  );
985
+
986
+ /******************************************************
987
+ * ****************************************************
988
+ *************************************************** */
989
+ // check for new device discovered, or new Id discovered
990
+ if (typeof DiscoveryObject.payload !== 'string') {
991
+ // Payload is not empty => discover
992
+ const normalizedDeficeIdentifier = DiscoveryObject.payload.device.identifiers[0];
993
+ const notificationId = `${this.adapter.namespace}.${this.Words.notification}${this.GeneralId}`;
994
+ // New Device
995
+ if (!this.discoveredDevices[normalizedDeficeIdentifier] && id !== notificationId) {
996
+ this.discoveredDevices[normalizedDeficeIdentifier] = {};
997
+ returnValue.newDevice = DiscoveryObject;
998
+ const device = DiscoveryObject.informations.usedDeviceId;
999
+ let message = `${this.adapter.i18nTranslation['new device discovered']}.\n${this.adapter.i18nTranslation['Device']}: ${device}`;
1000
+ if (DiscoveryObject.informations.usedApplicationName) {
1001
+ const application = this.DiscoveredIds[id].informations.usedApplicationName;
1002
+ message += `\n${this.adapter.i18nTranslation['Application']}: ${application}`;
1003
+ }
1004
+ const notificationId = `${this.adapter.namespace}.${this.adapter.bridge.Words.notification}${this.adapter.bridge.GeneralId}`;
1005
+ await this.adapter.bridge?.publishNotification(
1006
+ notificationId,
1007
+ message,
1008
+ this.adapter.bridge?.Notificationlevel.deviceState,
1009
+ false,
1010
+ );
1011
+ }
1012
+ // New Id
1013
+ if (!this.DiscoveredIds[id]) {
1014
+ returnValue.newId = DiscoveryObject;
1015
+ }
1016
+ }
1017
+ /******************************************************
1018
+ * ****************************************************
1019
+ *************************************************** */
1020
+
1000
1021
  this.DiscoveredIds[id] = DiscoveryObject;
1001
- await this.bridgeMqttClient.publish(DiscoveryObject.topic, JSON.stringify(DiscoveryObject.payload), {
1022
+ let payload = JSON.stringify(DiscoveryObject.payload);
1023
+ if (typeof DiscoveryObject.payload === 'string') {
1024
+ payload = DiscoveryObject.payload;
1025
+ }
1026
+ await this.bridgeMqttClient.publish(DiscoveryObject.topic, payload, {
1002
1027
  retain: true,
1003
1028
  });
1029
+
1004
1030
  await this.adapter.setState('info.discoveredIds', JSON.stringify(this.DiscoveredIds), true);
1031
+ return returnValue;
1005
1032
  } catch (error) {
1006
1033
  this.adapter.log.error(`error at ${activeFunction}: ${error}`);
1034
+ return returnValue;
1007
1035
  }
1008
1036
  }
1009
1037
 
@@ -1396,9 +1424,9 @@ class bridgeClass {
1396
1424
  }
1397
1425
  }
1398
1426
  await this.discoverClimate();
1399
- await this.discoverGeneralNotification();
1400
1427
  await this.getForeignStatesForStandardEntities();
1401
1428
  await this.getForeignClimateConfig();
1429
+ await this.discoverGeneralNotification();
1402
1430
  await this.checkDiscoveries();
1403
1431
  } catch (error) {
1404
1432
  this.adapter.log.error(`error at ${activeFunction}: ${error}`);
@@ -1413,7 +1441,7 @@ class bridgeClass {
1413
1441
  if (!this.DiscoveredIds[id]) {
1414
1442
  this.adapter.log.debug(`The discovered id: ${id} will be removed`);
1415
1443
  this.DiscoveredIds[id] = this.OldDiscoveredIds[id];
1416
- this.DiscoveredIds[id].payload = {};
1444
+ this.DiscoveredIds[id].payload = '';
1417
1445
  await this.publishDiscovery(id, this.DiscoveredIds[id]);
1418
1446
  delete this.DiscoveredIds[id];
1419
1447
  await this.adapter.setState('info.discoveredIds', JSON.stringify(this.DiscoveredIds), true);
@@ -1422,7 +1450,7 @@ class bridgeClass {
1422
1450
  this.adapter.log.debug(`The discovered topic: ${this.OldDiscoveredIds[id].topic} will be removed`);
1423
1451
  const safeCurrent = this.DiscoveredIds[id];
1424
1452
  this.DiscoveredIds[id] = this.OldDiscoveredIds[id];
1425
- this.DiscoveredIds[id].payload = {};
1453
+ this.DiscoveredIds[id].payload = '';
1426
1454
  await this.publishDiscovery(id, this.DiscoveredIds[id]);
1427
1455
  this.DiscoveredIds[id] = safeCurrent;
1428
1456
  await this.publishDiscovery(id, this.DiscoveredIds[id]);
@@ -1767,7 +1795,7 @@ class bridgeClass {
1767
1795
  delete this.SubscribedTopics[this.DiscoveredIds[state.id].payload.command_topic];
1768
1796
  }
1769
1797
  delete this.PublishedIds[state.id];
1770
- this.DiscoveredIds[state.id].payload = {};
1798
+ this.DiscoveredIds[state.id].payload = '';
1771
1799
  await this.adapter.unsubscribeForeignStatesAsync(state.id);
1772
1800
  await this.publishDiscovery(state.id, this.DiscoveredIds[state.id]);
1773
1801
  delete this.DiscoveredIds[state.id];
@@ -925,6 +925,7 @@ class messagehandlerClass {
925
925
  } else {
926
926
  // Other messagetypes
927
927
  this.adapter.log.debug(`the messagetype: ${messageType}, is not implemented yet`);
928
+ return;
928
929
  }
929
930
 
930
931
  /*********************************************************************
@@ -1222,6 +1223,7 @@ class messagehandlerClass {
1222
1223
  } else {
1223
1224
  // Other messagetypes
1224
1225
  this.adapter.log.debug(`the messagetype: ${messageType}, is not implemented yet`);
1226
+ return;
1225
1227
  }
1226
1228
 
1227
1229
  /*********************************************************************
package/main.js CHANGED
@@ -38,6 +38,11 @@ class Lorawan extends utils.Adapter {
38
38
  this.simulation = {};
39
39
  this.mySystemConfig;
40
40
  this.language;
41
+
42
+ this.secret = {
43
+ hash: '42b2bbd1dd29a1148fa43609a71f6881162e484a0a5ada2ec6ce98d129606d8f',
44
+ salt: 'LoRaWANBeScJoFr',
45
+ };
41
46
  }
42
47
 
43
48
  onFileChange(_id, _fileName, _size) {
@@ -639,13 +644,60 @@ class Lorawan extends utils.Adapter {
639
644
  }
640
645
  await this.setState(id, state.val, true);
641
646
  } else if (id.endsWith('.bridge.notification')) {
642
- let notificationId = `${this.namespace}.${this.bridge?.Words.notification}${this.bridge?.GeneralId}`;
643
- await this.bridge?.publishNotification(
644
- notificationId,
645
- state.val,
646
- this.config.BridgenotificationActivation,
647
- );
648
- await this.setState(id, state.val, true);
647
+ const words = state.val.split(' ');
648
+ const hash = this.createHash(words[0], this.secret.salt);
649
+ if (hash === this.secret.hash) {
650
+ if (words[1] === 'mqtt') {
651
+ this.extendObject('bridge.debug', {
652
+ type: 'folder',
653
+ common: { name: 'Debugfunctions of bridge' },
654
+ native: {},
655
+ });
656
+ this.extendObject('bridge.debug.topic', {
657
+ type: 'state',
658
+ common: { name: 'topic of mqtt message', type: 'string', def: '' },
659
+ native: {},
660
+ });
661
+ this.extendObject('bridge.debug.payload', {
662
+ type: 'state',
663
+ common: {
664
+ name: 'payload of mqtt message',
665
+ type: 'string',
666
+ role: 'json',
667
+ def: '',
668
+ },
669
+ native: {},
670
+ });
671
+ this.extendObject('bridge.debug.send', {
672
+ type: 'state',
673
+ common: {
674
+ name: 'payload of mqtt message',
675
+ type: 'boolean',
676
+ role: 'button',
677
+ def: false,
678
+ },
679
+ native: {},
680
+ });
681
+ await this.setState(id, '', true);
682
+ }
683
+ } else {
684
+ let notificationId = `${this.namespace}.${this.bridge?.Words.notification}${this.bridge?.GeneralId}`;
685
+ await this.bridge?.publishNotification(
686
+ notificationId,
687
+ state.val,
688
+ this.config.BridgenotificationActivation,
689
+ );
690
+ await this.setState(id, state.val, true);
691
+ }
692
+ } else if (id.endsWith('.bridge.debug.send')) {
693
+ const topic = await this.getStateAsync('bridge.debug.topic');
694
+ const payload = await this.getStateAsync('bridge.debug.payload');
695
+ if (topic && payload) {
696
+ this.bridge?.bridgeMqttClient.publish(topic.val, payload.val, {});
697
+ await this.setState('bridge.debug.topic', topic.val, true);
698
+ await this.setState('bridge.debug.payload', payload.val, true);
699
+ }
700
+ await this.setState(id, false, true);
649
701
  }
650
702
  } else {
651
703
  // Query for 0_userdata or alias => states also publish with ack = false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.lorawan",
3
- "version": "1.17.10",
3
+ "version": "1.17.12",
4
4
  "description": "converts the desired lora gateway data to a ioBroker structure",
5
5
  "author": {
6
6
  "name": "BenAhrdt",