iobroker.lorawan 1.16.3 → 1.16.5

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.5 (2025-09-17)
27
+ * (BenAhrdt) Bugfix in notifications to Bridge (new device dicovered) => namespace not set
28
+
29
+ ### 1.16.4 (2025-09-17)
30
+ * (BenAhrdt) Bridge import foreign states till Adapter is running
31
+ * (BenAhrdt) Bridge delete foreign states till Adapter is running
32
+
26
33
  ### 1.16.3 (2025-09-16)
27
34
  * (BenAhrdt) nameing of foreign Devices in Bridge
28
35
 
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "lorawan",
4
- "version": "1.16.3",
4
+ "version": "1.16.5",
5
5
  "news": {
6
+ "1.16.5": {
7
+ "en": "Bugfix in notifications to Bridge (new device dicovered) => namespace not set",
8
+ "de": "Fehlerbehebung bei Benachrichtigungen an Bridge (neues Gerät erkannt) => Namespace nicht festgelegt",
9
+ "ru": "Исправлена ошибка в уведомлениях для моста (обнаружение нового устройства) => пространство имен не установлено",
10
+ "pt": "Correção de bug nas notificações para Bridge (novo dispositivo descoberto) => espaço de nomes não definido",
11
+ "nl": "Bugfix in meldingen naar Bridge (nieuw apparaat ontdekt) => namespace niet ingesteld",
12
+ "fr": "Correction de bug dans les notifications vers le pont (nouveau périphérique découvert) => espace de noms non défini",
13
+ "it": "Correzione di un bug nelle notifiche al Bridge (nuovo dispositivo scoperto) => namespace non impostato",
14
+ "es": "Corrección de error en las notificaciones al puente (nuevo dispositivo descubierto) => espacio de nombres no establecido",
15
+ "pl": "Poprawiono błąd w powiadomieniach do Bridge (nowe urządzenie zostało znalezione) => nie ustawiona przestrzeń nazw",
16
+ "uk": "Виправлено помилку у сповіщеннях до мосту (виявлено новий пристрій) => не встановлений простір імен",
17
+ "zh-cn": "修复了通知到桥接器的bug(发现新设备)=>命名空间未设置"
18
+ },
19
+ "1.16.4": {
20
+ "en": "Bridge import foreign states till Adapter is running\nBridge delete foreign states till Adapter is running",
21
+ "de": "Brücke importiert externe Zustände, solange der Adapter läuft.\nLösche Fremdzustände aus der Datenbank, solange der Adapter aktiv ist.",
22
+ "ru": "Импортируйте внешние состояния моста до запуска адаптера\nУдаление внешних состояний Bridge, пока работает адаптер.",
23
+ "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",
24
+ "nl": "Importeer externe toestanden van de brug totdat de adapter actief is\nBridge verwijdert externe statussen zolang de adapter actief is",
25
+ "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",
26
+ "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",
27
+ "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",
28
+ "pl": "Importuj stany mostu do momentu uruchomienia adaptera.\nUsunięto stany obce do momentu uruchomienia adaptera.",
29
+ "uk": "Міст імпортує зовнішні стани поки адаптер працює\nВидалення зовнішніх станів у мосту доки адаптер працює.",
30
+ "zh-cn": "桥接器在适配器运行之前导入外部状态\n桥删除外部状态直到适配器运行"
31
+ },
6
32
  "1.16.3": {
7
33
  "en": "nameing of foreign Devices in Bridge",
8
34
  "de": "Benennung von fremden Geräten in der Brücke",
@@ -67,32 +93,6 @@
67
93
  "pl": "Usuń oczekiwanie (await) z niektórych wywołań.",
68
94
  "uk": "видаліть await із деяких викликів",
69
95
  "zh-cn": "从部分调用中删除 await"
70
- },
71
- "1.15.7": {
72
- "en": "solve publishing intern",
73
- "de": "Löse das Problem mit der Veröffentlichung des Praktikanten.",
74
- "ru": "решить вопрос с публикацией стажера",
75
- "pt": "Resolver publicação de estagiário",
76
- "nl": "Oplossen van het publiceren van stages",
77
- "fr": "résoudre le stage en édition",
78
- "it": "risolto l'internato che pubblica",
79
- "es": "Resolver publicación de interno.",
80
- "pl": "rozwiązać problem stażysty ds. publikacji",
81
- "uk": "вирішення питань практиканта з розміщення текстів",
82
- "zh-cn": "解决发布实习生"
83
- },
84
- "1.15.6": {
85
- "en": "improve handling of state device in case of subfolders",
86
- "de": "Verbessere die Handhabung des Gerätestatus bei Unterordnern.",
87
- "ru": "Улучшено управление устройствами состояний в случае подпапок.",
88
- "pt": "Melhorar o tratamento do dispositivo de estado no caso de subpastas",
89
- "nl": "Verbeter de verwerking van apparaatstaten in geval van submappen.",
90
- "fr": "Améliorer la gestion de l'appareil d'état en cas de sous-dossiers",
91
- "it": "Migliorare la gestione del dispositivo di stato nel caso di sottocartelle",
92
- "es": "Mejora en el manejo del dispositivo de estado en caso de subcarpetas",
93
- "pl": "Poprawiono obsługę urządzenia stanu w przypadku podfolderó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';
@@ -232,14 +234,16 @@ class bridgeClass {
232
234
  this.adapter.log.debug(`Function ${activeFunction} started.`);
233
235
  try {
234
236
  if (this.bridgeMqttClient.internalConnectionstate) {
235
- const countBefore = Object.keys(this.DiscoveredIds).length;
237
+ const countBefore = Object.keys(this.Notifications).length;
236
238
  await this.discovery(id, options);
237
- // only publish new discovered Ids
238
- if (countBefore !== Object.keys(this.DiscoveredIds).length) {
239
+ // notify new discovered Devices (Notification count changed)
240
+ // On startup this ist mostly true, but the genereal notification id will set later.
241
+ // So there is no notificaton published to Bridge
242
+ if (countBefore !== Object.keys(this.Notifications).length) {
239
243
  const device = this.DiscoveredIds[id].informations.usedDeviceId;
240
244
  const application = this.DiscoveredIds[id].informations.usedApplicationName;
241
245
  const message = `${this.adapter.i18nTranslation['new device discovered']}.\n${this.adapter.i18nTranslation['Device']}: ${device}\n${this.adapter.i18nTranslation['Application']}: ${application}`;
242
- const notificationId = `${this.adapter.bridge.Words.notification}${this.adapter.bridge.GeneralId}`;
246
+ const notificationId = `${this.adapter.namespace}.${this.adapter.bridge.Words.notification}${this.adapter.bridge.GeneralId}`;
243
247
  await this.adapter.bridge?.publishNotification(
244
248
  notificationId,
245
249
  message,
@@ -306,17 +310,29 @@ class bridgeClass {
306
310
  };
307
311
  let discoveryobject = this.getNotificationDiscoveryObject(deviceIdentifier, this.Words.general);
308
312
  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;
313
+ this.assignIdStructure(
314
+ this.PublishedIds,
315
+ general.notificationId,
316
+ {
317
+ applicationName: changeInfo.applicationName,
318
+ usedApplicationName: changeInfo.usedApplicationName,
319
+ deviceId: changeInfo.deviceId,
320
+ usedDeviceId: changeInfo.usedDeviceId,
321
+ },
322
+ discoveryobject?.topic,
323
+ discoveryobject?.payload,
324
+ discoveryobject?.payload.topic,
325
+ );
326
+
317
327
  await this.publishDiscovery(general.notificationId, {
318
328
  topic: discoveryobject?.topic,
319
329
  payload: structuredClone(discoveryobject?.payload),
330
+ informations: {
331
+ applicationName: changeInfo.applicationName,
332
+ usedApplicationName: changeInfo.usedApplicationName,
333
+ deviceId: changeInfo.deviceId,
334
+ usedDeviceId: changeInfo.usedDeviceId,
335
+ },
320
336
  });
321
337
 
322
338
  // offline
@@ -326,17 +342,29 @@ class bridgeClass {
326
342
  };
327
343
  discoveryobject = this.getNotificationDiscoveryObject(deviceIdentifier, this.Words.offline);
328
344
  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;
345
+ this.assignIdStructure(
346
+ this.PublishedIds,
347
+ offline.notificationId,
348
+ {
349
+ applicationName: changeInfo.applicationName,
350
+ usedApplicationName: changeInfo.usedApplicationName,
351
+ deviceId: changeInfo.deviceId,
352
+ usedDeviceId: changeInfo.usedDeviceId,
353
+ },
354
+ discoveryobject?.topic,
355
+ discoveryobject?.payload,
356
+ discoveryobject?.payload.topic,
357
+ );
358
+
337
359
  await this.publishDiscovery(offline.notificationId, {
338
360
  topic: discoveryobject?.topic,
339
361
  payload: structuredClone(discoveryobject?.payload),
362
+ informations: {
363
+ applicationName: changeInfo.applicationName,
364
+ usedApplicationName: changeInfo.usedApplicationName,
365
+ deviceId: changeInfo.deviceId,
366
+ usedDeviceId: changeInfo.usedDeviceId,
367
+ },
340
368
  });
341
369
 
342
370
  // online
@@ -346,17 +374,29 @@ class bridgeClass {
346
374
  };
347
375
  discoveryobject = this.getNotificationDiscoveryObject(deviceIdentifier, this.Words.online);
348
376
  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;
377
+ this.assignIdStructure(
378
+ this.PublishedIds,
379
+ online.notificationId,
380
+ {
381
+ applicationName: changeInfo.applicationName,
382
+ usedApplicationName: changeInfo.usedApplicationName,
383
+ deviceId: changeInfo.deviceId,
384
+ usedDeviceId: changeInfo.usedDeviceId,
385
+ },
386
+ discoveryobject?.topic,
387
+ discoveryobject?.payload,
388
+ discoveryobject?.payload.topic,
389
+ );
390
+
357
391
  await this.publishDiscovery(online.notificationId, {
358
392
  topic: discoveryobject?.topic,
359
393
  payload: structuredClone(discoveryobject?.payload),
394
+ informations: {
395
+ applicationName: changeInfo.applicationName,
396
+ usedApplicationName: changeInfo.usedApplicationName,
397
+ deviceId: changeInfo.deviceId,
398
+ usedDeviceId: changeInfo.usedDeviceId,
399
+ },
360
400
  });
361
401
  }
362
402
  } catch (error) {
@@ -379,17 +419,23 @@ class bridgeClass {
379
419
  if (!this.Notifications[notificationId]) {
380
420
  const discoveryobject = this.getNotificationDiscoveryObject(this.adapter.namespace, this.Words.general);
381
421
  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;
422
+ this.assignIdStructure(
423
+ this.PublishedIds,
424
+ notificationId,
425
+ {
426
+ usedDeviceId: this.adapter.namespace,
427
+ },
428
+ discoveryobject?.topic,
429
+ discoveryobject?.payload,
430
+ discoveryobject?.payload.topic,
431
+ );
432
+
390
433
  await this.publishDiscovery(notificationId, {
391
434
  topic: discoveryobject?.topic,
392
435
  payload: structuredClone(discoveryobject?.payload),
436
+ informations: {
437
+ usedDeviceId: this.adapter.namespace,
438
+ },
393
439
  });
394
440
  }
395
441
  } catch (error) {
@@ -510,84 +556,81 @@ class bridgeClass {
510
556
  };
511
557
 
512
558
  // 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
- };
559
+ // Target
560
+ this.assignTopicStructure(
561
+ this.SubscribedTopics,
562
+ `${target.Topic}${this.EndingSet}`,
563
+ {
564
+ applicationName: target.changeInfo.applicationName,
565
+ usedApplicationName: target.changeInfo.usedApplicationName,
566
+ deviceId: target.changeInfo.deviceId,
567
+ usedDeviceId: target.changeInfo.usedDeviceId,
568
+ },
569
+ DiscoveryTopic,
570
+ DiscoveryPayload,
571
+ config.climateIds.target,
572
+ );
527
573
 
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
- };
574
+ // Mode
575
+ this.assignTopicStructure(
576
+ this.SubscribedTopics,
577
+ `${mode.Topic}${this.EndingSet}`,
578
+ {
579
+ applicationName: mode.changeInfo.applicationName,
580
+ usedApplicationName: mode.changeInfo.usedApplicationName,
581
+ deviceId: mode.changeInfo.deviceId,
582
+ usedDeviceId: mode.changeInfo.usedDeviceId,
583
+ },
584
+ DiscoveryTopic,
585
+ DiscoveryPayload,
586
+ config.climateIds.mode,
587
+ );
542
588
 
543
589
  // Assign published Topics
544
590
  // 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
- };
591
+ this.assignIdStructure(
592
+ this.PublishedIds,
593
+ config.climateIds.target,
594
+ {
595
+ applicationName: target.changeInfo.applicationName,
596
+ usedApplicationName: target.changeInfo.usedApplicationName,
597
+ deviceId: target.changeInfo.deviceId,
598
+ usedDeviceId: target.changeInfo.usedDeviceId,
599
+ },
600
+ DiscoveryTopic,
601
+ DiscoveryPayload,
602
+ `${target.Topic}${this.EndingState}`,
603
+ );
559
604
 
560
605
  // 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
- };
606
+ this.assignIdStructure(
607
+ this.PublishedIds,
608
+ config.climateIds.act,
609
+ {
610
+ applicationName: act.changeInfo.applicationName,
611
+ usedApplicationName: act.changeInfo.usedApplicationName,
612
+ deviceId: act.changeInfo.deviceId,
613
+ usedDeviceId: act.changeInfo.usedDeviceId,
614
+ },
615
+ DiscoveryTopic,
616
+ DiscoveryPayload,
617
+ `${act.Topic}${this.EndingState}`,
618
+ );
575
619
 
576
620
  // 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
- };
621
+ this.assignIdStructure(
622
+ this.PublishedIds,
623
+ config.climateIds.mode,
624
+ {
625
+ applicationName: mode.changeInfo.applicationName,
626
+ usedApplicationName: mode.changeInfo.usedApplicationName,
627
+ deviceId: mode.changeInfo.deviceId,
628
+ usedDeviceId: mode.changeInfo.usedDeviceId,
629
+ },
630
+ DiscoveryTopic,
631
+ DiscoveryPayload,
632
+ `${mode.Topic}${this.EndingState}`,
633
+ );
591
634
 
592
635
  // State to publish for Mode
593
636
  let modeval = undefined;
@@ -809,20 +852,19 @@ class bridgeClass {
809
852
  options.Bridgestate = Bridgestate;
810
853
  const DiscoveryObject = await this.getDiscoveryObject(changeInfo, options);
811
854
  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
- };
855
+ this.assignIdStructure(
856
+ this.PublishedIds,
857
+ id,
858
+ {
859
+ applicationName: changeInfo.applicationName,
860
+ usedApplicationName: changeInfo.usedApplicationName,
861
+ deviceId: changeInfo.deviceId,
862
+ usedDeviceId: changeInfo.usedDeviceId,
863
+ },
864
+ DiscoveryObject?.topic,
865
+ DiscoveryObject?.payload,
866
+ DiscoveryObject?.payload.state_topic,
867
+ );
826
868
  }
827
869
  await this.publishDiscovery(id, {
828
870
  topic: DiscoveryObject?.topic,
@@ -869,36 +911,34 @@ class bridgeClass {
869
911
  options.Bridgestate = Bridgestate;
870
912
  const DiscoveryObject = await this.getDiscoveryObject(changeInfo, options);
871
913
  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
- };
914
+ this.assignIdStructure(
915
+ this.PublishedIds,
916
+ id,
917
+ {
918
+ applicationName: changeInfo.applicationName,
919
+ usedApplicationName: changeInfo.usedApplicationName,
920
+ deviceId: changeInfo.deviceId,
921
+ usedDeviceId: changeInfo.usedDeviceId,
922
+ },
923
+ DiscoveryObject?.topic,
924
+ DiscoveryObject?.payload,
925
+ DiscoveryObject?.payload.state_topic,
926
+ );
886
927
  }
887
928
  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
- };
929
+ this.assignTopicStructure(
930
+ this.SubscribedTopics,
931
+ DiscoveryObject?.payload.command_topic,
932
+ {
933
+ applicationName: changeInfo.applicationName,
934
+ usedApplicationName: changeInfo.usedApplicationName,
935
+ deviceId: changeInfo.deviceId,
936
+ usedDeviceId: changeInfo.usedDeviceId,
937
+ },
938
+ DiscoveryObject?.topic,
939
+ DiscoveryObject?.payload,
940
+ id,
941
+ );
902
942
  }
903
943
  await this.publishDiscovery(id, {
904
944
  topic: DiscoveryObject?.topic,
@@ -919,6 +959,52 @@ class bridgeClass {
919
959
  }
920
960
  }
921
961
 
962
+ /*********************************************************************
963
+ * **************** assign Structur of internal memory ***************
964
+ * ******************************************************************/
965
+ /**
966
+ * @param assignObject object to assign
967
+ * @param indexId index of the assignable object
968
+ * @param informations informations about the assign
969
+ * @param topic dicoverytopic of the assign
970
+ * @param payload payload of the assign
971
+ * @param state_topic topic for the of the assigned state
972
+ */
973
+ assignIdStructure(assignObject, indexId, informations, topic, payload, state_topic) {
974
+ if (!assignObject[indexId]) {
975
+ assignObject[indexId] = { discovery: [] };
976
+ }
977
+ assignObject[indexId].discovery.push({
978
+ topic: topic,
979
+ payload: structuredClone(payload),
980
+ });
981
+ assignObject[indexId].state_topic = state_topic;
982
+ assignObject[indexId].informations = structuredClone(informations);
983
+ }
984
+
985
+ /*********************************************************************
986
+ * **************** assign Structur of internal memory ***************
987
+ * ******************************************************************/
988
+ /**
989
+ * @param assignObject object to assign
990
+ * @param indexTopic index of the assignable object
991
+ * @param informations informations about the assign
992
+ * @param topic dicoverytopic of the assign
993
+ * @param payload payload of the assign
994
+ * @param id id for the assign to the foreign state
995
+ */
996
+ assignTopicStructure(assignObject, indexTopic, informations, topic, payload, id) {
997
+ if (!assignObject[indexTopic]) {
998
+ assignObject[indexTopic] = { discovery: [] };
999
+ }
1000
+ assignObject[indexTopic].discovery.push({
1001
+ topic: topic,
1002
+ payload: structuredClone(payload),
1003
+ });
1004
+ this.SubscribedTopics[indexTopic].id = id;
1005
+ this.SubscribedTopics[indexTopic].informations = structuredClone(informations);
1006
+ }
1007
+
922
1008
  /*********************************************************************
923
1009
  * ******************** Discovery Objekt bilden **********************
924
1010
  * ******************************************************************/
@@ -1370,6 +1456,9 @@ class bridgeClass {
1370
1456
  const activeFunction = 'bridge.js - checkAllStatesForBridgeWork';
1371
1457
  this.adapter.log.debug(`Function ${activeFunction} started.`);
1372
1458
  try {
1459
+ // get old Discovered ids
1460
+ this.OldDiscoveredIds = JSON.parse((await this.adapter.getStateAsync('info.discoveredIds')).val);
1461
+
1373
1462
  // Get all ids in adapterfolder
1374
1463
  // Generate Infos of all devices and decoded folders
1375
1464
  const adapterObjects = await this.adapter.getAdapterObjectsAsync();
@@ -1394,11 +1483,27 @@ class bridgeClass {
1394
1483
  await this.discoverClimate();
1395
1484
  await this.discoverGeneralNotification();
1396
1485
  await this.getForeignStatesForStandardEntities();
1486
+ await this.checkDiscoveries();
1397
1487
  } catch (error) {
1398
1488
  this.adapter.log.error(`error at ${activeFunction}: ${error}`);
1399
1489
  }
1400
1490
  }
1401
1491
 
1492
+ /**
1493
+ * check discovery for old entries
1494
+ */
1495
+ async checkDiscoveries() {
1496
+ for (const id in this.OldDiscoveredIds) {
1497
+ if (!this.DiscoveredIds[id]) {
1498
+ this.adapter.log.debug(`The discovered id: ${id} will be removed`);
1499
+ this.DiscoveredIds[id] = this.OldDiscoveredIds[id];
1500
+ this.DiscoveredIds[id].payload = {};
1501
+ await this.publishDiscovery(id, this.DiscoveredIds[id]);
1502
+ delete this.DiscoveredIds[id];
1503
+ await this.adapter.setState('info.discoveredIds', JSON.stringify(this.DiscoveredIds), true);
1504
+ }
1505
+ }
1506
+ }
1402
1507
  // create schedule Jobs for online and historic values
1403
1508
  /**
1404
1509
  * Build the cronJob
@@ -1456,18 +1561,12 @@ class bridgeClass {
1456
1561
  const activeFunction = 'bridge.js - getForeignStatesForStandardEntities';
1457
1562
  this.adapter.log.debug(`Function ${activeFunction} started.`);
1458
1563
  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
- }
1564
+ const idBridgefunction = 'enum.functions.bridge';
1565
+ await this.adapter.subscribeForeignObjectsAsync('enum.functions.bridge');
1566
+ const bridgeElements = await this.adapter.getForeignObjectAsync(idBridgefunction);
1567
+ if (bridgeElements) {
1568
+ for (const member of bridgeElements.common.members) {
1569
+ await this.discoverForeignRange(member);
1471
1570
  }
1472
1571
  }
1473
1572
  } catch (error) {
@@ -1475,6 +1574,43 @@ class bridgeClass {
1475
1574
  }
1476
1575
  }
1477
1576
 
1577
+ /**
1578
+ * @param id id to discover foreign state
1579
+ * @param clear clear the ids from internal memory
1580
+ */
1581
+ async discoverForeignRange(id, clear = false) {
1582
+ const params = {
1583
+ startkey: id,
1584
+ endkey: `${id}.\u9999`,
1585
+ };
1586
+ if (!clear) {
1587
+ this.ForeignBridgeMembers[id] = id;
1588
+ } else {
1589
+ delete this.ForeignBridgeMembers[id];
1590
+ }
1591
+ const states = await this.adapter.getObjectViewAsync('system', 'state', params);
1592
+ for (const state of states.rows) {
1593
+ if (!clear) {
1594
+ const common = state.value.common;
1595
+ await this.discoverForeignStandardEntity(state.id, { common: common });
1596
+ } else {
1597
+ if (
1598
+ this.DiscoveredIds[id] &&
1599
+ this.DiscoveredIds[id].payload &&
1600
+ this.DiscoveredIds[id].payload.command_topic
1601
+ ) {
1602
+ delete this.SubscribedTopics[this.DiscoveredIds[id].payload.command_topic];
1603
+ }
1604
+ delete this.PublishedIds[id];
1605
+ this.DiscoveredIds[id].payload = {};
1606
+ await this.adapter.unsubscribeForeignStatesAsync(id);
1607
+ await this.publishDiscovery(id, this.DiscoveredIds[id]);
1608
+ delete this.DiscoveredIds[id];
1609
+ await this.adapter.setState('info.discoveredIds', JSON.stringify(this.DiscoveredIds), true);
1610
+ }
1611
+ }
1612
+ }
1613
+
1478
1614
  /**
1479
1615
  * @param id id to discover foreign state
1480
1616
  * @param options options of foreign state
@@ -1533,35 +1669,60 @@ class bridgeClass {
1533
1669
  }
1534
1670
 
1535
1671
  if (options.Bridgestate.publish) {
1536
- if (!this.PublishedIds[id]) {
1672
+ this.assignIdStructure(
1673
+ this.PublishedIds,
1674
+ id,
1675
+ {
1676
+ usedDeviceId: deviceIdentifier,
1677
+ },
1678
+ discoveryTopic,
1679
+ discoveryPayload,
1680
+ discoveryPayload.state_topic,
1681
+ );
1682
+
1683
+ /*if (!this.PublishedIds[id]) {
1537
1684
  this.PublishedIds[id] = { discovery: [] };
1538
1685
  }
1539
1686
  this.PublishedIds[id].discovery.push({
1540
1687
  topic: discoveryTopic,
1541
1688
  payload: structuredClone(discoveryPayload),
1542
1689
  });
1543
- this.PublishedIds[id].state_topic = discoveryPayload.state_topic;
1690
+ this.PublishedIds[id].state_topic = discoveryPayload.state_topic;*/
1544
1691
  }
1545
1692
  if (options.Bridgestate.subscribe) {
1546
- if (!this.SubscribedTopics[discoveryPayload.command_topic]) {
1693
+ this.assignTopicStructure(
1694
+ this.SubscribedTopics,
1695
+ discoveryPayload.command_topic,
1696
+ {
1697
+ usedDeviceId: deviceIdentifier,
1698
+ },
1699
+ discoveryTopic,
1700
+ discoveryPayload,
1701
+ id,
1702
+ );
1703
+
1704
+ /*if (!this.SubscribedTopics[discoveryPayload.command_topic]) {
1547
1705
  this.SubscribedTopics[discoveryPayload.command_topic] = { discovery: [] };
1548
1706
  }
1549
1707
  this.SubscribedTopics[discoveryPayload.command_topic].discovery.push({
1550
1708
  topic: discoveryTopic,
1551
1709
  payload: structuredClone(discoveryPayload),
1552
1710
  });
1553
- this.SubscribedTopics[discoveryPayload.command_topic].id = id;
1711
+ this.SubscribedTopics[discoveryPayload.command_topic].id = id;*/
1554
1712
  }
1555
1713
  await this.publishDiscovery(id, {
1556
1714
  topic: discoveryTopic,
1557
1715
  payload: structuredClone(discoveryPayload),
1716
+ informations: {
1717
+ usedDeviceId: deviceIdentifier,
1718
+ },
1558
1719
  });
1559
1720
  // Delay for publish new entity
1560
1721
  setTimeout(async () => {
1561
1722
  await this.publishId(id, state.val, {});
1562
1723
  }, 1000);
1563
1724
  // Subscribe state for onStatechange mathode
1564
- this.adapter.subscribeForeignStatesAsync(id);
1725
+ await this.adapter.subscribeForeignStatesAsync(id);
1565
1726
  } catch (error) {
1566
1727
  this.adapter.log.error(`error at ${activeFunction}: ${error}`);
1567
1728
  }
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.3",
3
+ "version": "1.16.5",
4
4
  "description": "converts the desired lora gateway data to a ioBroker structure",
5
5
  "author": {
6
6
  "name": "BenAhrdt",