iobroker.lorawan 1.16.2 → 1.16.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -23,6 +23,13 @@ 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.16.4 (2025-09-17)
27
+ * (BenAhrdt) Bridge import foreign states till Adapter is running
28
+ * (BenAhrdt) Bridge delete foreign states till Adapter is running
29
+
30
+ ### 1.16.3 (2025-09-16)
31
+ * (BenAhrdt) nameing of foreign Devices in Bridge
32
+
26
33
  ### 1.16.2 (2025-09-16)
27
34
  * (BenAhrdt) bugfix namespace also by calling work from directoryhandler
28
35
 
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "lorawan",
4
- "version": "1.16.2",
4
+ "version": "1.16.4",
5
5
  "news": {
6
+ "1.16.4": {
7
+ "en": "Bridge import foreign states till Adapter is running\nBridge delete foreign states till Adapter is running",
8
+ "de": "Brücke importiert externe Zustände, solange der Adapter läuft.\nLösche Fremdzustände aus der Datenbank, solange der Adapter aktiv ist.",
9
+ "ru": "Импортируйте внешние состояния моста до запуска адаптера\nУдаление внешних состояний Bridge, пока работает адаптер.",
10
+ "pt": "Importar estados externos da ponte até que o adaptador esteja em execução\nExcluir estados estrangeiros da ponte até que o adaptador esteja em execução",
11
+ "nl": "Importeer externe toestanden van de brug totdat de adapter actief is\nBridge verwijdert externe statussen zolang de adapter actief is",
12
+ "fr": "Importer les états étrangers du pont tant que l'adaptateur est en cours d'exécution.\nSupprimer les états étrangers du pont tant que l'adaptateur est en cours d'exécution",
13
+ "it": "Importa gli stati esterni del bridge finché l'adattatore è in esecuzione\nEliminazione dello stato estero del bridge fino a quando l'adattatore è in esecuzione",
14
+ "es": "Importar estados extranjeros del puente hasta que el adaptador esté en funcionamiento.\nEliminar estados extranjeros del puente hasta que el adaptador esté en funcionamiento",
15
+ "pl": "Importuj stany mostu do momentu uruchomienia adaptera.\nUsunięto stany obce do momentu uruchomienia adaptera.",
16
+ "uk": "Міст імпортує зовнішні стани поки адаптер працює\nВидалення зовнішніх станів у мосту доки адаптер працює.",
17
+ "zh-cn": "桥接器在适配器运行之前导入外部状态\n桥删除外部状态直到适配器运行"
18
+ },
19
+ "1.16.3": {
20
+ "en": "nameing of foreign Devices in Bridge",
21
+ "de": "Benennung von fremden Geräten in der Brücke",
22
+ "ru": "Наименование иностранных устройств в мосту",
23
+ "pt": "Nomenclatura de Dispositivos Estrangeiros na Ponte",
24
+ "nl": "Benaming van externe apparaten in de bridge",
25
+ "fr": "Renommage des appareils étrangers dans le pont",
26
+ "it": "Nominativo dei dispositivi stranieri nel Bridge",
27
+ "es": "Renombrar dispositivos extranjeros en el puente",
28
+ "pl": "Nadanie nazw obcym urządzeniom w mostku",
29
+ "uk": "Перейменування зовнішніх пристроїв у мосту",
30
+ "zh-cn": "在网桥中给外部设备命名"
31
+ },
6
32
  "1.16.2": {
7
33
  "en": "bugfix namespace also by calling work from directoryhandler",
8
34
  "de": "Bug behoben: Namensraum auch durch Aufruf von \"Arbeit\" von DirectoryHandler.",
@@ -67,32 +93,6 @@
67
93
  "pl": "rozwiązać problem stażysty ds. publikacji",
68
94
  "uk": "вирішення питань практиканта з розміщення текстів",
69
95
  "zh-cn": "解决发布实习生"
70
- },
71
- "1.15.6": {
72
- "en": "improve handling of state device in case of subfolders",
73
- "de": "Verbessere die Handhabung des Gerätestatus bei Unterordnern.",
74
- "ru": "Улучшено управление устройствами состояний в случае подпапок.",
75
- "pt": "Melhorar o tratamento do dispositivo de estado no caso de subpastas",
76
- "nl": "Verbeter de verwerking van apparaatstaten in geval van submappen.",
77
- "fr": "Améliorer la gestion de l'appareil d'état en cas de sous-dossiers",
78
- "it": "Migliorare la gestione del dispositivo di stato nel caso di sottocartelle",
79
- "es": "Mejora en el manejo del dispositivo de estado en caso de subcarpetas",
80
- "pl": "Poprawiono obsługę urządzenia stanu w przypadku podfolderów.",
81
- "uk": "Поліпшено обробку пристрою стану у випадку підпапок.",
82
- "zh-cn": "改进对子文件夹中状态设备的处理"
83
- },
84
- "1.15.5": {
85
- "en": "Bugfix logging removed",
86
- "de": "Fehlerbehebung beim Protokollieren entfernt",
87
- "ru": "Исправлена ошибка с удалением журнала.",
88
- "pt": "Correção de bug: log removido",
89
- "nl": "Bugfix logging verwijderd",
90
- "fr": "Correctif de bug: suppression du journalisation",
91
- "it": "Rimossa la registrazione dei bugfix",
92
- "es": "Corregido el registro de errores.",
93
- "pl": "Usunięto logowanie błędów",
94
- "uk": "Виправлено запис журналів про помилки",
95
- "zh-cn": "修复了日志记录问题"
96
96
  }
97
97
  },
98
98
  "titleLang": {
@@ -21,6 +21,7 @@ class bridgeClass {
21
21
 
22
22
  // Structure of actual vaulues in Bridge (till las start of Adapter)
23
23
  this.CheckedIds = {};
24
+ this.OldDiscoveredIds = {};
24
25
  this.DiscoveredIds = {};
25
26
  this.SubscribedTopics = {};
26
27
  this.PublishedIds = {};
@@ -29,6 +30,7 @@ class bridgeClass {
29
30
  this.BridgeDiscoveryPrefix = {
30
31
  HA: 'homeassistant/',
31
32
  };
33
+ this.ForeignBridgeMembers = {};
32
34
  this.MinTime = 100; // ms between publish and subscribe same value
33
35
  this.DiscoveryCronjob = {};
34
36
  this.EndingSet = '/set';
@@ -306,17 +308,29 @@ class bridgeClass {
306
308
  };
307
309
  let discoveryobject = this.getNotificationDiscoveryObject(deviceIdentifier, this.Words.general);
308
310
  this.Notifications[general.notificationId] = {};
309
- if (!this.PublishedIds[general.notificationId]) {
310
- this.PublishedIds[general.notificationId] = { discovery: [] };
311
- }
312
- this.PublishedIds[general.notificationId].discovery.push({
313
- topic: discoveryobject?.topic,
314
- payload: structuredClone(discoveryobject?.payload),
315
- });
316
- this.PublishedIds[general.notificationId].state_topic = discoveryobject?.payload.topic;
311
+ this.assignIdStructure(
312
+ this.PublishedIds,
313
+ general.notificationId,
314
+ {
315
+ applicationName: changeInfo.applicationName,
316
+ usedApplicationName: changeInfo.usedApplicationName,
317
+ deviceId: changeInfo.deviceId,
318
+ usedDeviceId: changeInfo.usedDeviceId,
319
+ },
320
+ discoveryobject?.topic,
321
+ discoveryobject?.payload,
322
+ discoveryobject?.payload.topic,
323
+ );
324
+
317
325
  await this.publishDiscovery(general.notificationId, {
318
326
  topic: discoveryobject?.topic,
319
327
  payload: structuredClone(discoveryobject?.payload),
328
+ informations: {
329
+ applicationName: changeInfo.applicationName,
330
+ usedApplicationName: changeInfo.usedApplicationName,
331
+ deviceId: changeInfo.deviceId,
332
+ usedDeviceId: changeInfo.usedDeviceId,
333
+ },
320
334
  });
321
335
 
322
336
  // offline
@@ -326,17 +340,29 @@ class bridgeClass {
326
340
  };
327
341
  discoveryobject = this.getNotificationDiscoveryObject(deviceIdentifier, this.Words.offline);
328
342
  this.Notifications[offline.notificationId] = {};
329
- if (!this.PublishedIds[offline.notificationId]) {
330
- this.PublishedIds[offline.notificationId] = { discovery: [] };
331
- }
332
- this.PublishedIds[offline.notificationId].discovery.push({
333
- topic: discoveryobject?.topic,
334
- payload: structuredClone(discoveryobject?.payload),
335
- });
336
- this.PublishedIds[offline.notificationId].state_topic = discoveryobject?.payload.topic;
343
+ this.assignIdStructure(
344
+ this.PublishedIds,
345
+ offline.notificationId,
346
+ {
347
+ applicationName: changeInfo.applicationName,
348
+ usedApplicationName: changeInfo.usedApplicationName,
349
+ deviceId: changeInfo.deviceId,
350
+ usedDeviceId: changeInfo.usedDeviceId,
351
+ },
352
+ discoveryobject?.topic,
353
+ discoveryobject?.payload,
354
+ discoveryobject?.payload.topic,
355
+ );
356
+
337
357
  await this.publishDiscovery(offline.notificationId, {
338
358
  topic: discoveryobject?.topic,
339
359
  payload: structuredClone(discoveryobject?.payload),
360
+ informations: {
361
+ applicationName: changeInfo.applicationName,
362
+ usedApplicationName: changeInfo.usedApplicationName,
363
+ deviceId: changeInfo.deviceId,
364
+ usedDeviceId: changeInfo.usedDeviceId,
365
+ },
340
366
  });
341
367
 
342
368
  // online
@@ -346,17 +372,29 @@ class bridgeClass {
346
372
  };
347
373
  discoveryobject = this.getNotificationDiscoveryObject(deviceIdentifier, this.Words.online);
348
374
  this.Notifications[online.notificationId] = {};
349
- if (!this.PublishedIds[online.notificationId]) {
350
- this.PublishedIds[online.notificationId] = { discovery: [] };
351
- }
352
- this.PublishedIds[online.notificationId].discovery.push({
353
- topic: discoveryobject?.topic,
354
- payload: structuredClone(discoveryobject?.payload),
355
- });
356
- this.PublishedIds[online.notificationId].state_topic = discoveryobject?.payload.topic;
375
+ this.assignIdStructure(
376
+ this.PublishedIds,
377
+ online.notificationId,
378
+ {
379
+ applicationName: changeInfo.applicationName,
380
+ usedApplicationName: changeInfo.usedApplicationName,
381
+ deviceId: changeInfo.deviceId,
382
+ usedDeviceId: changeInfo.usedDeviceId,
383
+ },
384
+ discoveryobject?.topic,
385
+ discoveryobject?.payload,
386
+ discoveryobject?.payload.topic,
387
+ );
388
+
357
389
  await this.publishDiscovery(online.notificationId, {
358
390
  topic: discoveryobject?.topic,
359
391
  payload: structuredClone(discoveryobject?.payload),
392
+ informations: {
393
+ applicationName: changeInfo.applicationName,
394
+ usedApplicationName: changeInfo.usedApplicationName,
395
+ deviceId: changeInfo.deviceId,
396
+ usedDeviceId: changeInfo.usedDeviceId,
397
+ },
360
398
  });
361
399
  }
362
400
  } catch (error) {
@@ -379,17 +417,23 @@ class bridgeClass {
379
417
  if (!this.Notifications[notificationId]) {
380
418
  const discoveryobject = this.getNotificationDiscoveryObject(this.adapter.namespace, this.Words.general);
381
419
  this.Notifications[notificationId] = {};
382
- if (!this.PublishedIds[notificationId]) {
383
- this.PublishedIds[notificationId] = { discovery: [] };
384
- }
385
- this.PublishedIds[notificationId].discovery.push({
386
- topic: discoveryobject?.topic,
387
- payload: structuredClone(discoveryobject?.payload),
388
- });
389
- this.PublishedIds[notificationId].state_topic = discoveryobject?.payload.topic;
420
+ this.assignIdStructure(
421
+ this.PublishedIds,
422
+ notificationId,
423
+ {
424
+ usedDeviceId: this.adapter.namespace,
425
+ },
426
+ discoveryobject?.topic,
427
+ discoveryobject?.payload,
428
+ discoveryobject?.payload.topic,
429
+ );
430
+
390
431
  await this.publishDiscovery(notificationId, {
391
432
  topic: discoveryobject?.topic,
392
433
  payload: structuredClone(discoveryobject?.payload),
434
+ informations: {
435
+ usedDeviceId: this.adapter.namespace,
436
+ },
393
437
  });
394
438
  }
395
439
  } catch (error) {
@@ -510,84 +554,81 @@ class bridgeClass {
510
554
  };
511
555
 
512
556
  // Assign Subscribed Topics
513
- if (!this.SubscribedTopics[`${target.Topic}${this.EndingSet}`]) {
514
- this.SubscribedTopics[`${target.Topic}${this.EndingSet}`] = { discovery: [] };
515
- }
516
- this.SubscribedTopics[`${target.Topic}${this.EndingSet}`].discovery.push({
517
- topic: DiscoveryTopic,
518
- payload: structuredClone(DiscoveryPayload),
519
- });
520
- this.SubscribedTopics[`${target.Topic}${this.EndingSet}`].id = config.climateIds.target;
521
- this.SubscribedTopics[`${target.Topic}${this.EndingSet}`].informations = {
522
- applicationName: target.changeInfo.applicationName,
523
- usedApplicationName: target.changeInfo.usedApplicationName,
524
- deviceId: target.changeInfo.deviceId,
525
- usedDeviceId: target.changeInfo.usedDeviceId,
526
- };
557
+ // Target
558
+ this.assignTopicStructure(
559
+ this.SubscribedTopics,
560
+ `${target.Topic}${this.EndingSet}`,
561
+ {
562
+ applicationName: target.changeInfo.applicationName,
563
+ usedApplicationName: target.changeInfo.usedApplicationName,
564
+ deviceId: target.changeInfo.deviceId,
565
+ usedDeviceId: target.changeInfo.usedDeviceId,
566
+ },
567
+ DiscoveryTopic,
568
+ DiscoveryPayload,
569
+ config.climateIds.target,
570
+ );
527
571
 
528
- if (!this.SubscribedTopics[`${mode.Topic}${this.EndingSet}`]) {
529
- this.SubscribedTopics[`${mode.Topic}${this.EndingSet}`] = { discovery: [] };
530
- }
531
- this.SubscribedTopics[`${mode.Topic}${this.EndingSet}`].discovery.push({
532
- topic: DiscoveryTopic,
533
- payload: structuredClone(DiscoveryPayload),
534
- });
535
- this.SubscribedTopics[`${mode.Topic}${this.EndingSet}`].id = config.climateIds.mode;
536
- this.SubscribedTopics[`${mode.Topic}${this.EndingSet}`].informations = {
537
- applicationName: mode.changeInfo.applicationName,
538
- usedApplicationName: mode.changeInfo.usedApplicationName,
539
- deviceId: mode.changeInfo.deviceId,
540
- usedDeviceId: mode.changeInfo.usedDeviceId,
541
- };
572
+ // Mode
573
+ this.assignTopicStructure(
574
+ this.SubscribedTopics,
575
+ `${mode.Topic}${this.EndingSet}`,
576
+ {
577
+ applicationName: mode.changeInfo.applicationName,
578
+ usedApplicationName: mode.changeInfo.usedApplicationName,
579
+ deviceId: mode.changeInfo.deviceId,
580
+ usedDeviceId: mode.changeInfo.usedDeviceId,
581
+ },
582
+ DiscoveryTopic,
583
+ DiscoveryPayload,
584
+ config.climateIds.mode,
585
+ );
542
586
 
543
587
  // Assign published Topics
544
588
  // Target
545
- if (!this.PublishedIds[config.climateIds.target]) {
546
- this.PublishedIds[config.climateIds.target] = { discovery: [] };
547
- }
548
- this.PublishedIds[config.climateIds.target].discovery.push({
549
- topic: DiscoveryTopic,
550
- payload: structuredClone(DiscoveryPayload),
551
- });
552
- this.PublishedIds[config.climateIds.target].state_topic = `${target.Topic}${this.EndingState}`;
553
- this.PublishedIds[config.climateIds.target].informations = {
554
- applicationName: target.changeInfo.applicationName,
555
- usedApplicationName: target.changeInfo.usedApplicationName,
556
- deviceId: target.changeInfo.deviceId,
557
- usedDeviceId: target.changeInfo.usedDeviceId,
558
- };
589
+ this.assignIdStructure(
590
+ this.PublishedIds,
591
+ config.climateIds.target,
592
+ {
593
+ applicationName: target.changeInfo.applicationName,
594
+ usedApplicationName: target.changeInfo.usedApplicationName,
595
+ deviceId: target.changeInfo.deviceId,
596
+ usedDeviceId: target.changeInfo.usedDeviceId,
597
+ },
598
+ DiscoveryTopic,
599
+ DiscoveryPayload,
600
+ `${target.Topic}${this.EndingState}`,
601
+ );
559
602
 
560
603
  // Act
561
- if (!this.PublishedIds[config.climateIds.act]) {
562
- this.PublishedIds[config.climateIds.act] = { discovery: [] };
563
- }
564
- this.PublishedIds[config.climateIds.act].discovery.push({
565
- topic: DiscoveryTopic,
566
- payload: structuredClone(DiscoveryPayload),
567
- });
568
- this.PublishedIds[config.climateIds.act].state_topic = `${act.Topic}${this.EndingState}`;
569
- this.PublishedIds[config.climateIds.act].informations = {
570
- applicationName: act.changeInfo.applicationName,
571
- usedApplicationName: act.changeInfo.usedApplicationName,
572
- deviceId: act.changeInfo.deviceId,
573
- usedDeviceId: act.changeInfo.usedDeviceId,
574
- };
604
+ this.assignIdStructure(
605
+ this.PublishedIds,
606
+ config.climateIds.act,
607
+ {
608
+ applicationName: act.changeInfo.applicationName,
609
+ usedApplicationName: act.changeInfo.usedApplicationName,
610
+ deviceId: act.changeInfo.deviceId,
611
+ usedDeviceId: act.changeInfo.usedDeviceId,
612
+ },
613
+ DiscoveryTopic,
614
+ DiscoveryPayload,
615
+ `${act.Topic}${this.EndingState}`,
616
+ );
575
617
 
576
618
  // Mode
577
- if (!this.PublishedIds[config.climateIds.mode]) {
578
- this.PublishedIds[config.climateIds.mode] = { discovery: [] };
579
- }
580
- this.PublishedIds[config.climateIds.mode].discovery.push({
581
- topic: DiscoveryTopic,
582
- payload: structuredClone(DiscoveryPayload),
583
- });
584
- this.PublishedIds[config.climateIds.mode].state_topic = `${mode.Topic}${this.EndingState}`;
585
- this.PublishedIds[config.climateIds.mode].informations = {
586
- applicationName: mode.changeInfo.applicationName,
587
- usedApplicationName: mode.changeInfo.usedApplicationName,
588
- deviceId: mode.changeInfo.deviceId,
589
- usedDeviceId: mode.changeInfo.usedDeviceId,
590
- };
619
+ this.assignIdStructure(
620
+ this.PublishedIds,
621
+ config.climateIds.mode,
622
+ {
623
+ applicationName: mode.changeInfo.applicationName,
624
+ usedApplicationName: mode.changeInfo.usedApplicationName,
625
+ deviceId: mode.changeInfo.deviceId,
626
+ usedDeviceId: mode.changeInfo.usedDeviceId,
627
+ },
628
+ DiscoveryTopic,
629
+ DiscoveryPayload,
630
+ `${mode.Topic}${this.EndingState}`,
631
+ );
591
632
 
592
633
  // State to publish for Mode
593
634
  let modeval = undefined;
@@ -809,20 +850,19 @@ class bridgeClass {
809
850
  options.Bridgestate = Bridgestate;
810
851
  const DiscoveryObject = await this.getDiscoveryObject(changeInfo, options);
811
852
  if (Bridgestate.publish) {
812
- if (!this.PublishedIds[id]) {
813
- this.PublishedIds[id] = { discovery: [] };
814
- }
815
- this.PublishedIds[id].discovery.push({
816
- topic: DiscoveryObject?.topic,
817
- payload: structuredClone(DiscoveryObject?.payload),
818
- });
819
- this.PublishedIds[id].state_topic = DiscoveryObject?.payload.state_topic;
820
- this.PublishedIds[id].informations = {
821
- applicationName: changeInfo.applicationName,
822
- usedApplicationName: changeInfo.usedApplicationName,
823
- deviceId: changeInfo.deviceId,
824
- usedDeviceId: changeInfo.usedDeviceId,
825
- };
853
+ this.assignIdStructure(
854
+ this.PublishedIds,
855
+ id,
856
+ {
857
+ applicationName: changeInfo.applicationName,
858
+ usedApplicationName: changeInfo.usedApplicationName,
859
+ deviceId: changeInfo.deviceId,
860
+ usedDeviceId: changeInfo.usedDeviceId,
861
+ },
862
+ DiscoveryObject?.topic,
863
+ DiscoveryObject?.payload,
864
+ DiscoveryObject?.payload.state_topic,
865
+ );
826
866
  }
827
867
  await this.publishDiscovery(id, {
828
868
  topic: DiscoveryObject?.topic,
@@ -869,36 +909,34 @@ class bridgeClass {
869
909
  options.Bridgestate = Bridgestate;
870
910
  const DiscoveryObject = await this.getDiscoveryObject(changeInfo, options);
871
911
  if (Bridgestate.publish) {
872
- if (!this.PublishedIds[id]) {
873
- this.PublishedIds[id] = { discovery: [] };
874
- }
875
- this.PublishedIds[id].discovery.push({
876
- topic: DiscoveryObject?.topic,
877
- payload: structuredClone(DiscoveryObject?.payload),
878
- });
879
- this.PublishedIds[id].state_topic = DiscoveryObject?.payload.state_topic;
880
- this.PublishedIds[id].informations = {
881
- applicationName: changeInfo.applicationName,
882
- usedApplicationName: changeInfo.usedApplicationName,
883
- deviceId: changeInfo.deviceId,
884
- usedDeviceId: changeInfo.usedDeviceId,
885
- };
912
+ this.assignIdStructure(
913
+ this.PublishedIds,
914
+ id,
915
+ {
916
+ applicationName: changeInfo.applicationName,
917
+ usedApplicationName: changeInfo.usedApplicationName,
918
+ deviceId: changeInfo.deviceId,
919
+ usedDeviceId: changeInfo.usedDeviceId,
920
+ },
921
+ DiscoveryObject?.topic,
922
+ DiscoveryObject?.payload,
923
+ DiscoveryObject?.payload.state_topic,
924
+ );
886
925
  }
887
926
  if (Bridgestate.subscribe) {
888
- if (!this.SubscribedTopics[DiscoveryObject?.payload.command_topic]) {
889
- this.SubscribedTopics[DiscoveryObject?.payload.command_topic] = { discovery: [] };
890
- }
891
- this.SubscribedTopics[DiscoveryObject?.payload.command_topic].discovery.push({
892
- topic: DiscoveryObject?.topic,
893
- payload: structuredClone(DiscoveryObject?.payload),
894
- });
895
- this.SubscribedTopics[DiscoveryObject?.payload.command_topic].id = id;
896
- this.SubscribedTopics[DiscoveryObject?.payload.command_topic].informations = {
897
- applicationName: changeInfo.applicationName,
898
- usedApplicationName: changeInfo.usedApplicationName,
899
- deviceId: changeInfo.deviceId,
900
- usedDeviceId: changeInfo.usedDeviceId,
901
- };
927
+ this.assignTopicStructure(
928
+ this.SubscribedTopics,
929
+ DiscoveryObject?.payload.command_topic,
930
+ {
931
+ applicationName: changeInfo.applicationName,
932
+ usedApplicationName: changeInfo.usedApplicationName,
933
+ deviceId: changeInfo.deviceId,
934
+ usedDeviceId: changeInfo.usedDeviceId,
935
+ },
936
+ DiscoveryObject?.topic,
937
+ DiscoveryObject?.payload,
938
+ id,
939
+ );
902
940
  }
903
941
  await this.publishDiscovery(id, {
904
942
  topic: DiscoveryObject?.topic,
@@ -919,6 +957,52 @@ class bridgeClass {
919
957
  }
920
958
  }
921
959
 
960
+ /*********************************************************************
961
+ * **************** assign Structur of internal memory ***************
962
+ * ******************************************************************/
963
+ /**
964
+ * @param assignObject object to assign
965
+ * @param indexId index of the assignable object
966
+ * @param informations informations about the assign
967
+ * @param topic dicoverytopic of the assign
968
+ * @param payload payload of the assign
969
+ * @param state_topic topic for the of the assigned state
970
+ */
971
+ assignIdStructure(assignObject, indexId, informations, topic, payload, state_topic) {
972
+ if (!assignObject[indexId]) {
973
+ assignObject[indexId] = { discovery: [] };
974
+ }
975
+ assignObject[indexId].discovery.push({
976
+ topic: topic,
977
+ payload: structuredClone(payload),
978
+ });
979
+ assignObject[indexId].state_topic = state_topic;
980
+ assignObject[indexId].informations = structuredClone(informations);
981
+ }
982
+
983
+ /*********************************************************************
984
+ * **************** assign Structur of internal memory ***************
985
+ * ******************************************************************/
986
+ /**
987
+ * @param assignObject object to assign
988
+ * @param indexTopic index of the assignable object
989
+ * @param informations informations about the assign
990
+ * @param topic dicoverytopic of the assign
991
+ * @param payload payload of the assign
992
+ * @param id id for the assign to the foreign state
993
+ */
994
+ assignTopicStructure(assignObject, indexTopic, informations, topic, payload, id) {
995
+ if (!assignObject[indexTopic]) {
996
+ assignObject[indexTopic] = { discovery: [] };
997
+ }
998
+ assignObject[indexTopic].discovery.push({
999
+ topic: topic,
1000
+ payload: structuredClone(payload),
1001
+ });
1002
+ this.SubscribedTopics[indexTopic].id = id;
1003
+ this.SubscribedTopics[indexTopic].informations = structuredClone(informations);
1004
+ }
1005
+
922
1006
  /*********************************************************************
923
1007
  * ******************** Discovery Objekt bilden **********************
924
1008
  * ******************************************************************/
@@ -1370,6 +1454,9 @@ class bridgeClass {
1370
1454
  const activeFunction = 'bridge.js - checkAllStatesForBridgeWork';
1371
1455
  this.adapter.log.debug(`Function ${activeFunction} started.`);
1372
1456
  try {
1457
+ // get old Discovered ids
1458
+ this.OldDiscoveredIds = JSON.parse((await this.adapter.getStateAsync('info.discoveredIds')).val);
1459
+
1373
1460
  // Get all ids in adapterfolder
1374
1461
  // Generate Infos of all devices and decoded folders
1375
1462
  const adapterObjects = await this.adapter.getAdapterObjectsAsync();
@@ -1394,11 +1481,27 @@ class bridgeClass {
1394
1481
  await this.discoverClimate();
1395
1482
  await this.discoverGeneralNotification();
1396
1483
  await this.getForeignStatesForStandardEntities();
1484
+ await this.checkDiscoveries();
1397
1485
  } catch (error) {
1398
1486
  this.adapter.log.error(`error at ${activeFunction}: ${error}`);
1399
1487
  }
1400
1488
  }
1401
1489
 
1490
+ /**
1491
+ * check discovery for old entries
1492
+ */
1493
+ async checkDiscoveries() {
1494
+ for (const id in this.OldDiscoveredIds) {
1495
+ if (!this.DiscoveredIds[id]) {
1496
+ this.adapter.log.debug(`The discovered id: ${id} will be removed`);
1497
+ this.DiscoveredIds[id] = this.OldDiscoveredIds[id];
1498
+ this.DiscoveredIds[id].payload = {};
1499
+ await this.publishDiscovery(id, this.DiscoveredIds[id]);
1500
+ delete this.DiscoveredIds[id];
1501
+ await this.adapter.setState('info.discoveredIds', JSON.stringify(this.DiscoveredIds), true);
1502
+ }
1503
+ }
1504
+ }
1402
1505
  // create schedule Jobs for online and historic values
1403
1506
  /**
1404
1507
  * Build the cronJob
@@ -1456,18 +1559,12 @@ class bridgeClass {
1456
1559
  const activeFunction = 'bridge.js - getForeignStatesForStandardEntities';
1457
1560
  this.adapter.log.debug(`Function ${activeFunction} started.`);
1458
1561
  try {
1459
- const functions = await this.adapter.getEnums('functions');
1460
- if (functions['enum.functions']['enum.functions.bridge']) {
1461
- for (const member of functions['enum.functions']['enum.functions.bridge'].common.members) {
1462
- const params = {
1463
- startkey: member,
1464
- endkey: `${member}.\u9999`,
1465
- };
1466
- const states = await this.adapter.getObjectViewAsync('system', 'state', params);
1467
- for (const state of states.rows) {
1468
- const common = state.value.common;
1469
- await this.discoverForeignStandardEntity(state.id, { common: common });
1470
- }
1562
+ const idBridgefunction = 'enum.functions.bridge';
1563
+ await this.adapter.subscribeForeignObjectsAsync('enum.functions.bridge');
1564
+ const bridgeElements = await this.adapter.getForeignObjectAsync(idBridgefunction);
1565
+ if (bridgeElements) {
1566
+ for (const member of bridgeElements.common.members) {
1567
+ await this.discoverForeignRange(member);
1471
1568
  }
1472
1569
  }
1473
1570
  } catch (error) {
@@ -1475,6 +1572,43 @@ class bridgeClass {
1475
1572
  }
1476
1573
  }
1477
1574
 
1575
+ /**
1576
+ * @param id id to discover foreign state
1577
+ * @param clear clear the ids from internal memory
1578
+ */
1579
+ async discoverForeignRange(id, clear = false) {
1580
+ const params = {
1581
+ startkey: id,
1582
+ endkey: `${id}.\u9999`,
1583
+ };
1584
+ if (!clear) {
1585
+ this.ForeignBridgeMembers[id] = id;
1586
+ } else {
1587
+ delete this.ForeignBridgeMembers[id];
1588
+ }
1589
+ const states = await this.adapter.getObjectViewAsync('system', 'state', params);
1590
+ for (const state of states.rows) {
1591
+ if (!clear) {
1592
+ const common = state.value.common;
1593
+ await this.discoverForeignStandardEntity(state.id, { common: common });
1594
+ } else {
1595
+ if (
1596
+ this.DiscoveredIds[id] &&
1597
+ this.DiscoveredIds[id].payload &&
1598
+ this.DiscoveredIds[id].payload.command_topic
1599
+ ) {
1600
+ delete this.SubscribedTopics[this.DiscoveredIds[id].payload.command_topic];
1601
+ }
1602
+ delete this.PublishedIds[id];
1603
+ this.DiscoveredIds[id].payload = {};
1604
+ await this.adapter.unsubscribeForeignStatesAsync(id);
1605
+ await this.publishDiscovery(id, this.DiscoveredIds[id]);
1606
+ delete this.DiscoveredIds[id];
1607
+ await this.adapter.setState('info.discoveredIds', JSON.stringify(this.DiscoveredIds), true);
1608
+ }
1609
+ }
1610
+ }
1611
+
1478
1612
  /**
1479
1613
  * @param id id to discover foreign state
1480
1614
  * @param options options of foreign state
@@ -1484,15 +1618,21 @@ class bridgeClass {
1484
1618
  this.adapter.log.debug(`Function ${activeFunction} started.`);
1485
1619
  try {
1486
1620
  const state = await this.adapter.getForeignStateAsync(id);
1487
- const parentObject = await this.getParentObject(id);
1488
1621
  let partentId = '';
1489
1622
  let parentName = '';
1490
- if (typeof parentObject === 'object') {
1491
- partentId = parentObject._id;
1492
- parentName = parentObject.common.name;
1623
+ const parentDevice = await this.getParentDevice(id);
1624
+ if (typeof parentDevice === 'string') {
1625
+ const parentChannel = await this.getParentChannel(id);
1626
+ if (typeof parentChannel === 'string') {
1627
+ partentId = parentChannel;
1628
+ parentName = partentId;
1629
+ } else {
1630
+ partentId = parentChannel._id;
1631
+ parentName = parentChannel.common.name;
1632
+ }
1493
1633
  } else {
1494
- partentId = parentObject;
1495
- parentName = partentId;
1634
+ partentId = parentDevice._id;
1635
+ parentName = parentDevice.common.name;
1496
1636
  }
1497
1637
  const deviceIdentifier = parentName;
1498
1638
  const statename = id.substring(partentId.length + 1, id.length);
@@ -1527,66 +1667,110 @@ class bridgeClass {
1527
1667
  }
1528
1668
 
1529
1669
  if (options.Bridgestate.publish) {
1530
- if (!this.PublishedIds[id]) {
1670
+ this.assignIdStructure(
1671
+ this.PublishedIds,
1672
+ id,
1673
+ {
1674
+ usedDeviceId: deviceIdentifier,
1675
+ },
1676
+ discoveryTopic,
1677
+ discoveryPayload,
1678
+ discoveryPayload.state_topic,
1679
+ );
1680
+
1681
+ /*if (!this.PublishedIds[id]) {
1531
1682
  this.PublishedIds[id] = { discovery: [] };
1532
1683
  }
1533
1684
  this.PublishedIds[id].discovery.push({
1534
1685
  topic: discoveryTopic,
1535
1686
  payload: structuredClone(discoveryPayload),
1536
1687
  });
1537
- this.PublishedIds[id].state_topic = discoveryPayload.state_topic;
1688
+ this.PublishedIds[id].state_topic = discoveryPayload.state_topic;*/
1538
1689
  }
1539
1690
  if (options.Bridgestate.subscribe) {
1540
- if (!this.SubscribedTopics[discoveryPayload.command_topic]) {
1691
+ this.assignTopicStructure(
1692
+ this.SubscribedTopics,
1693
+ discoveryPayload.command_topic,
1694
+ {
1695
+ usedDeviceId: deviceIdentifier,
1696
+ },
1697
+ discoveryTopic,
1698
+ discoveryPayload,
1699
+ id,
1700
+ );
1701
+
1702
+ /*if (!this.SubscribedTopics[discoveryPayload.command_topic]) {
1541
1703
  this.SubscribedTopics[discoveryPayload.command_topic] = { discovery: [] };
1542
1704
  }
1543
1705
  this.SubscribedTopics[discoveryPayload.command_topic].discovery.push({
1544
1706
  topic: discoveryTopic,
1545
1707
  payload: structuredClone(discoveryPayload),
1546
1708
  });
1547
- this.SubscribedTopics[discoveryPayload.command_topic].id = id;
1709
+ this.SubscribedTopics[discoveryPayload.command_topic].id = id;*/
1548
1710
  }
1549
1711
  await this.publishDiscovery(id, {
1550
1712
  topic: discoveryTopic,
1551
1713
  payload: structuredClone(discoveryPayload),
1714
+ informations: {
1715
+ usedDeviceId: deviceIdentifier,
1716
+ },
1552
1717
  });
1553
1718
  // Delay for publish new entity
1554
1719
  setTimeout(async () => {
1555
1720
  await this.publishId(id, state.val, {});
1556
1721
  }, 1000);
1557
1722
  // Subscribe state for onStatechange mathode
1558
- this.adapter.subscribeForeignStatesAsync(id);
1723
+ await this.adapter.subscribeForeignStatesAsync(id);
1559
1724
  } catch (error) {
1560
1725
  this.adapter.log.error(`error at ${activeFunction}: ${error}`);
1561
1726
  }
1562
1727
  }
1563
1728
 
1564
1729
  /**
1565
- * @param id id to get parent Object
1730
+ * @param id id to get parent Channel
1566
1731
  */
1567
- async getParentObject(id) {
1568
- const activeFunction = 'bridge.js - getParentObject';
1732
+ async getParentDevice(id) {
1733
+ const activeFunction = 'bridge.js - getParentDevice';
1569
1734
  this.adapter.log.debug(`Function ${activeFunction} started.`);
1570
1735
  try {
1571
1736
  const firstIdexOfDot = id.indexOf('.');
1572
1737
  const lastIdexOfDot = id.lastIndexOf('.');
1573
1738
  if (lastIdexOfDot > firstIdexOfDot + 3) {
1574
1739
  id = id.substring(0, lastIdexOfDot);
1575
- const firstObj = await this.adapter.getForeignObjectAsync(id);
1576
- if (!firstObj) {
1740
+ const obj = await this.adapter.getForeignObjectAsync(id);
1741
+ if (!obj) {
1577
1742
  return undefined;
1578
1743
  }
1579
- if (firstObj?.type === 'device') {
1580
- return firstObj;
1744
+ if (obj?.type === 'device') {
1745
+ return obj;
1581
1746
  }
1582
- if (firstObj.type === 'channel') {
1583
- const secondObj = await this.getParentObject(id);
1584
- if (secondObj !== undefined) {
1585
- return secondObj;
1586
- }
1587
- return firstObj;
1747
+ return await this.getParentDevice(id);
1748
+ }
1749
+ return id.substring(0, lastIdexOfDot);
1750
+ } catch (error) {
1751
+ this.adapter.log.error(`error at ${activeFunction}: ${error}`);
1752
+ }
1753
+ }
1754
+
1755
+ /**
1756
+ * @param id id to get parent Channel
1757
+ */
1758
+ async getParentChannel(id) {
1759
+ const activeFunction = 'bridge.js - getParentChannel';
1760
+ this.adapter.log.debug(`Function ${activeFunction} started.`);
1761
+ try {
1762
+ const firstIdexOfDot = id.indexOf('.');
1763
+ const lastIdexOfDot = id.lastIndexOf('.');
1764
+ if (lastIdexOfDot > firstIdexOfDot + 3) {
1765
+ id = id.substring(0, lastIdexOfDot);
1766
+ const obj = await this.adapter.getForeignObjectAsync(id);
1767
+ if (!obj) {
1768
+ return undefined;
1769
+ }
1770
+ if (obj?.type === 'channel') {
1771
+ return obj;
1588
1772
  }
1589
- return await this.getParentObject(id);
1773
+ return await this.getParentChannel(id);
1590
1774
  }
1591
1775
  return id.substring(0, lastIdexOfDot);
1592
1776
  } catch (error) {
package/main.js CHANGED
@@ -23,7 +23,7 @@ class Lorawan extends utils.Adapter {
23
23
  });
24
24
  this.on('ready', this.onReady.bind(this));
25
25
  this.on('stateChange', this.onStateChange.bind(this));
26
- //this.on('objectChange', this.onObjectChange.bind(this));
26
+ this.on('objectChange', this.onObjectChange.bind(this));
27
27
  this.on('message', this.onMessage.bind(this));
28
28
  this.on('unload', this.onUnload.bind(this));
29
29
  this.on('fileChange', this.onFileChange.bind(this));
@@ -77,7 +77,7 @@ class Lorawan extends utils.Adapter {
77
77
  await this.messagehandler.setCustomObjectAtStartup();
78
78
 
79
79
  //Subscribe all configuration and control states
80
- this.subscribeStatesAsync('*');
80
+ await this.subscribeStatesAsync('*');
81
81
  //this.subscribeObjectsAsync('*.uplink.decoded.*');
82
82
  //this.subscribeObjectsAsync('*.downlink.control.*');
83
83
  this.log.debug(`the adapter starts with downlinkconfigs: ${JSON.stringify(this.config.downlinkConfig)}.`);
@@ -420,11 +420,30 @@ class Lorawan extends utils.Adapter {
420
420
  * @param id id of the changed object
421
421
  * @param obj value and ack of the changed object
422
422
  */
423
- /*async onObjectChange(id, obj) {
423
+ async onObjectChange(id, obj) {
424
424
  this.log.debug(`${id} is changed into ${JSON.stringify(obj.common)}`);
425
- // Erzeugen der HA Bridged für Control
426
- await this.messagehandler?.directoryhandler.setCustomForHaBridge(id, obj.common);
427
- }*/
425
+
426
+ // Only work, if bridge is activ
427
+ if (this.bridge) {
428
+ // Erzeugen der HA Bridged für Control
429
+ // check for new Entry
430
+ const members = obj.common.members;
431
+ for (const member of members) {
432
+ if (!this.bridge.ForeignBridgeMembers[member]) {
433
+ await this.bridge?.discoverForeignRange(member);
434
+ return;
435
+ }
436
+ }
437
+
438
+ // check for Entry removed
439
+ for (const member of Object.values(this.bridge.ForeignBridgeMembers)) {
440
+ if (!members.includes(member)) {
441
+ await this.bridge.discoverForeignRange(member, true);
442
+ return;
443
+ }
444
+ }
445
+ }
446
+ }
428
447
 
429
448
  /**
430
449
  * Is called if a subscribed state changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.lorawan",
3
- "version": "1.16.2",
3
+ "version": "1.16.4",
4
4
  "description": "converts the desired lora gateway data to a ioBroker structure",
5
5
  "author": {
6
6
  "name": "BenAhrdt",