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 +7 -0
- package/io-package.json +27 -27
- package/lib/modules/bridge.js +365 -181
- package/main.js +25 -6
- package/package.json +1 -1
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.
|
|
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": {
|
package/lib/modules/bridge.js
CHANGED
|
@@ -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
|
-
|
|
310
|
-
this.PublishedIds
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
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
|
-
|
|
330
|
-
this.PublishedIds
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
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
|
-
|
|
350
|
-
this.PublishedIds
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
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
|
-
|
|
383
|
-
this.PublishedIds
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
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
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
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
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
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
|
-
|
|
546
|
-
this.PublishedIds
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
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
|
-
|
|
562
|
-
this.PublishedIds
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
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
|
-
|
|
578
|
-
this.PublishedIds
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
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
|
-
|
|
813
|
-
this.PublishedIds
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
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
|
-
|
|
873
|
-
this.PublishedIds
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
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
|
-
|
|
889
|
-
this.SubscribedTopics
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
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
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
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
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
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 =
|
|
1495
|
-
parentName =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
1730
|
+
* @param id id to get parent Channel
|
|
1566
1731
|
*/
|
|
1567
|
-
async
|
|
1568
|
-
const activeFunction = 'bridge.js -
|
|
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
|
|
1576
|
-
if (!
|
|
1740
|
+
const obj = await this.adapter.getForeignObjectAsync(id);
|
|
1741
|
+
if (!obj) {
|
|
1577
1742
|
return undefined;
|
|
1578
1743
|
}
|
|
1579
|
-
if (
|
|
1580
|
-
return
|
|
1744
|
+
if (obj?.type === 'device') {
|
|
1745
|
+
return obj;
|
|
1581
1746
|
}
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
423
|
+
async onObjectChange(id, obj) {
|
|
424
424
|
this.log.debug(`${id} is changed into ${JSON.stringify(obj.common)}`);
|
|
425
|
-
|
|
426
|
-
|
|
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
|