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 +7 -0
- package/io-package.json +27 -27
- package/lib/modules/bridge.js +326 -165
- 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.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.
|
|
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": {
|
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';
|
|
@@ -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.
|
|
237
|
+
const countBefore = Object.keys(this.Notifications).length;
|
|
236
238
|
await this.discovery(id, options);
|
|
237
|
-
//
|
|
238
|
-
|
|
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
|
-
|
|
310
|
-
this.PublishedIds
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
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
|
-
|
|
330
|
-
this.PublishedIds
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
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
|
-
|
|
350
|
-
this.PublishedIds
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
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
|
-
|
|
383
|
-
this.PublishedIds
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
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
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
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
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
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
|
-
|
|
546
|
-
this.PublishedIds
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
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
|
-
|
|
562
|
-
this.PublishedIds
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
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
|
-
|
|
578
|
-
this.PublishedIds
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
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
|
-
|
|
813
|
-
this.PublishedIds
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
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
|
-
|
|
873
|
-
this.PublishedIds
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
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
|
-
|
|
889
|
-
this.SubscribedTopics
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
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
|
|
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
|
-
}
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|