iobroker.lorawan 1.18.63 → 1.19.1
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/admin/jsonConfig.json +1 -2
- package/io-package.json +27 -27
- package/lib/modules/assignhandler.js +1 -1
- package/lib/modules/bridge.js +52 -48
- package/lib/modules/bridgeDeviceHandler.js +373 -0
- package/lib/modules/directorieshandler.js +14 -14
- package/lib/modules/messagehandler.js +8 -5
- package/main.js +10 -7
- package/package.json +2 -2
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.19.1 (2026-01-03)
|
|
27
|
+
* (BenAhrdt) bugfix device and replace debug logs for silly
|
|
28
|
+
|
|
29
|
+
### 1.19.0 (2026-01-03)
|
|
30
|
+
* (BenAhrdt) remove Bridgetype Smarthome
|
|
31
|
+
* (BenAhrdt) add firt possibility to generate devices from Bridge to Iob
|
|
32
|
+
|
|
26
33
|
### 1.18.63 (2026-01-01)
|
|
27
34
|
* (BenAhrdt) return to await calls in checkAll (bridge)
|
|
28
35
|
|
package/admin/jsonConfig.json
CHANGED
|
@@ -751,8 +751,7 @@
|
|
|
751
751
|
"tooltip": "BridgeTypeTooltip",
|
|
752
752
|
"options": [
|
|
753
753
|
{"label":"BridgeTypeOff","value":"off"},
|
|
754
|
-
{"label":"BridgeTypeHA","value":"HA"}
|
|
755
|
-
{"label":"BridgeTypeSH","value":"SH"}
|
|
754
|
+
{"label":"BridgeTypeHA","value":"HA"}
|
|
756
755
|
],
|
|
757
756
|
"default": "off",
|
|
758
757
|
"xs": 12,
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "lorawan",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.19.1",
|
|
5
5
|
"news": {
|
|
6
|
+
"1.19.1": {
|
|
7
|
+
"en": "bugfix device and replace debug logs for silly",
|
|
8
|
+
"de": "bugfix gerät und ersetzen debug protokolle für albern",
|
|
9
|
+
"ru": "bugfix-устройство и замена отладочных журналов на глупые",
|
|
10
|
+
"pt": "dispositivo de correção de bugs e registros de depuração de substituição para bobo",
|
|
11
|
+
"nl": "bugfix-apparaat en debug-logs vervangen voor domheid",
|
|
12
|
+
"fr": "bugfix périphérique et remplacer les journaux de débogage pour idiot",
|
|
13
|
+
"it": "dispositivo bugfix e sostituire i log di debug per sciocco",
|
|
14
|
+
"es": "dispositivo bugfix y reemplazar los registros de depuración para tontos",
|
|
15
|
+
"pl": "bugfix urządzenia i zastąpić logi debug dla głupi",
|
|
16
|
+
"uk": "пристрій для виправлення помилок і заміни журналів для silly",
|
|
17
|
+
"zh-cn": "错误修正设备并替换愚昧的调试日志"
|
|
18
|
+
},
|
|
19
|
+
"1.19.0": {
|
|
20
|
+
"en": "remove Bridgetype Smarthome\nadd firt possibility to generate devices from Bridge to Iob",
|
|
21
|
+
"de": "bridgetype Smarthome entfernen\nfügen Sie firt Möglichkeit, Geräte von Bridge zu Iob zu generieren",
|
|
22
|
+
"ru": "скачать Bridgetype Smarthome\nдобавьте возможность создания устройств от Bridge до Iob",
|
|
23
|
+
"pt": "remover o tipo de ponte Smarthome\nadicionar a possibilidade inicial de gerar dispositivos de Bridge para Iob",
|
|
24
|
+
"nl": "verwijderen Bridgetype Smarthome\nfirt mogelijkheid toevoegen om apparaten van brug aan Iob te genereren",
|
|
25
|
+
"fr": "supprimer Bridgetype Smarthome\najouter la possibilité de firt pour générer des appareils de Bridge à Iob",
|
|
26
|
+
"it": "rimuovere Bridgetype Smarthome\naggiungere firt possibilità di generare dispositivi da Bridge a Iob",
|
|
27
|
+
"es": "eliminar Bridgetype Smarthome\nañadir firt posibilidad de generar dispositivos desde Bridge a Iob",
|
|
28
|
+
"pl": "usuń Bridgetype Smarthome\ndodać firt możliwość generowania urządzeń z Bridge do Iob",
|
|
29
|
+
"uk": "видалити Bridgetype Smarthome\nдо Iob",
|
|
30
|
+
"zh-cn": "删除桥型 Smarthome\n从 Bridge 添加 firt 生成设备的可能性"
|
|
31
|
+
},
|
|
6
32
|
"1.18.63": {
|
|
7
33
|
"en": "return to await calls in checkAll (bridge)",
|
|
8
34
|
"de": "zurück zu warten Anrufe im Check Alle (Brücke)",
|
|
@@ -67,32 +93,6 @@
|
|
|
67
93
|
"pl": "Chuck sprawdził Wszystkie państwa dla BridgeWork dla lepszej wydajności",
|
|
68
94
|
"uk": "Перевірка качки AllStatesForBridgeWork для кращої продуктивності",
|
|
69
95
|
"zh-cn": "查克检查 为更好的业绩而努力"
|
|
70
|
-
},
|
|
71
|
-
"1.18.58": {
|
|
72
|
-
"en": "serialize and cache the config messagens",
|
|
73
|
-
"de": "serialisieren und kache die config messagens",
|
|
74
|
-
"ru": "сериализировать и кэшировать config messagens",
|
|
75
|
-
"pt": "serialize e cache as mensagens de configuração",
|
|
76
|
-
"nl": "serialiseren en cache de config messages",
|
|
77
|
-
"fr": "sérialisez et cachez les messages de configuration",
|
|
78
|
-
"it": "serializzare e memorizzare i messaggi di configurazione",
|
|
79
|
-
"es": "serialize y cache los mensajes de config",
|
|
80
|
-
"pl": "serializuj i buforuj wiadomości konfiguracyjne",
|
|
81
|
-
"uk": "послідовність і кешування конфігураційних повідомлень",
|
|
82
|
-
"zh-cn": "序列化和缓存配置信件"
|
|
83
|
-
},
|
|
84
|
-
"1.18.57": {
|
|
85
|
-
"en": "cache Infos in config for more performance",
|
|
86
|
-
"de": "cache Infos in config für mehr Leistung",
|
|
87
|
-
"ru": "cache Infos in Config для повышения производительности",
|
|
88
|
-
"pt": "informações de cache em configuração para mais desempenho",
|
|
89
|
-
"nl": "cache-informatie in configuratie voor meer prestaties",
|
|
90
|
-
"fr": "cache Infos en configuration pour plus de performances",
|
|
91
|
-
"it": "cache Infos in config per maggiori prestazioni",
|
|
92
|
-
"es": "cache Infos en config para más rendimiento",
|
|
93
|
-
"pl": "cache Infos w konfiguracji dla większej wydajności",
|
|
94
|
-
"uk": "cache Infos в конфігурації для більшої продуктивності",
|
|
95
|
-
"zh-cn": "为更多性能在配置中缓存信息"
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
98
|
"titleLang": {
|
|
@@ -719,7 +719,7 @@ class assignhandlerClass {
|
|
|
719
719
|
*/
|
|
720
720
|
executeAssign(id, value, assigndata, options) {
|
|
721
721
|
const activeFunction = 'executeAssign';
|
|
722
|
-
this.adapter.log.
|
|
722
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
723
723
|
try {
|
|
724
724
|
// check folder
|
|
725
725
|
const baseInfo = this.adapter.getBaseDeviceInfo(id);
|
package/lib/modules/bridge.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const bridgeMqttClientClass = require('./bridgeMqttclient');
|
|
2
|
+
const bridgeDeviceHandlerClass = require('./bridgeDeviceHandler');
|
|
2
3
|
const schedule = require('node-schedule');
|
|
3
4
|
/*
|
|
4
5
|
Also er published irgendwie nicht den Mode => und es kommt virtual_Mode nicht subcribed....
|
|
@@ -18,6 +19,7 @@ class bridgeClass {
|
|
|
18
19
|
* ******************************************************************/
|
|
19
20
|
|
|
20
21
|
this.bridgeMqttClient = new bridgeMqttClientClass(this.adapter, this.adapter.config);
|
|
22
|
+
this.bridgeDeviceHandler = new bridgeDeviceHandlerClass(this.adapter);
|
|
21
23
|
|
|
22
24
|
// Structure of actual vaulues in Bridge (till las start of Adapter)
|
|
23
25
|
this.CheckedIds = {};
|
|
@@ -29,7 +31,6 @@ class bridgeClass {
|
|
|
29
31
|
this.Notifications = {};
|
|
30
32
|
this.BridgeDiscoveryPrefix = {
|
|
31
33
|
HA: 'homeassistant/',
|
|
32
|
-
SH: 'smarthome/',
|
|
33
34
|
};
|
|
34
35
|
this.ForeignBridgeMembers = {};
|
|
35
36
|
this.MinTime = 100; // ms between publish and subscribe same value
|
|
@@ -186,7 +187,7 @@ class bridgeClass {
|
|
|
186
187
|
*/
|
|
187
188
|
async handleMessage(topic, message) {
|
|
188
189
|
const activeFunction = 'bridge.js - handleMessage';
|
|
189
|
-
this.adapter.log.
|
|
190
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
190
191
|
try {
|
|
191
192
|
if (this.SubscribedTopics[topic]) {
|
|
192
193
|
// safe old values (10 last values)
|
|
@@ -289,6 +290,9 @@ class bridgeClass {
|
|
|
289
290
|
// Special DataExchange
|
|
290
291
|
if (this.SubscribedTopics[topic].dataExchange) {
|
|
291
292
|
if (typeof message === 'object') {
|
|
293
|
+
// Call the BridgeDeviceHandler
|
|
294
|
+
await this.bridgeDeviceHandler.generateDeviceStructure(message);
|
|
295
|
+
// Stringify for set State
|
|
292
296
|
message = JSON.stringify(message);
|
|
293
297
|
}
|
|
294
298
|
await this.adapter.setState(
|
|
@@ -334,7 +338,7 @@ class bridgeClass {
|
|
|
334
338
|
*/
|
|
335
339
|
hexToRgb(hex) {
|
|
336
340
|
const activeFunction = 'bridge.js - hexToRgb';
|
|
337
|
-
this.adapter.log.
|
|
341
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
338
342
|
try {
|
|
339
343
|
hex = hex.replace('#', '').trim();
|
|
340
344
|
|
|
@@ -372,7 +376,7 @@ class bridgeClass {
|
|
|
372
376
|
*/
|
|
373
377
|
rgbToHex(colorObject) {
|
|
374
378
|
const activeFunction = 'bridge.js - rgbToHex';
|
|
375
|
-
this.adapter.log.
|
|
379
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
376
380
|
try {
|
|
377
381
|
const { r, g, b } = colorObject;
|
|
378
382
|
|
|
@@ -397,7 +401,7 @@ class bridgeClass {
|
|
|
397
401
|
*/
|
|
398
402
|
async work(id, Stateval, options) {
|
|
399
403
|
const activeFunction = 'bridge.js - work';
|
|
400
|
-
this.adapter.log.
|
|
404
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
401
405
|
try {
|
|
402
406
|
if (this.bridgeMqttClient.internalConnectionstate) {
|
|
403
407
|
const discovered = await this.discovery(id, options);
|
|
@@ -423,7 +427,7 @@ class bridgeClass {
|
|
|
423
427
|
*/
|
|
424
428
|
async discovery(id, options) {
|
|
425
429
|
const activeFunction = 'bridge.js - discovery';
|
|
426
|
-
this.adapter.log.
|
|
430
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
427
431
|
try {
|
|
428
432
|
if (!this.CheckedIds[id] || (options && options.forceDiscovery)) {
|
|
429
433
|
this.CheckedIds[id] = {};
|
|
@@ -446,7 +450,7 @@ class bridgeClass {
|
|
|
446
450
|
*/
|
|
447
451
|
async discoverGeneralNotification() {
|
|
448
452
|
const activeFunction = 'discoverGeneralNotification';
|
|
449
|
-
this.adapter.log.
|
|
453
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
450
454
|
try {
|
|
451
455
|
const notificationId = `${this.adapter.namespace}.${this.Words.notification}${this.GeneralId}`;
|
|
452
456
|
if (!this.Notifications[notificationId]) {
|
|
@@ -487,7 +491,7 @@ class bridgeClass {
|
|
|
487
491
|
*/
|
|
488
492
|
getNotificationDiscoveryObject(deviceIdentifier, notificationType) {
|
|
489
493
|
const activeFunction = 'getNotificationDiscoveryObject';
|
|
490
|
-
this.adapter.log.
|
|
494
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
491
495
|
try {
|
|
492
496
|
const normalizedDeviceIdentifier = this.normalizeString(deviceIdentifier);
|
|
493
497
|
const discoveryobject = {
|
|
@@ -515,7 +519,7 @@ class bridgeClass {
|
|
|
515
519
|
*/
|
|
516
520
|
async discoverClimate() {
|
|
517
521
|
const activeFunction = 'discoverClimate';
|
|
518
|
-
this.adapter.log.
|
|
522
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
519
523
|
try {
|
|
520
524
|
if (this.adapter.config.ClimateConfig) {
|
|
521
525
|
for (const config of this.adapter.config.ClimateConfig) {
|
|
@@ -726,7 +730,7 @@ class bridgeClass {
|
|
|
726
730
|
*/
|
|
727
731
|
async generateClimateIds(config) {
|
|
728
732
|
const activeFunction = 'generateClimateIds';
|
|
729
|
-
this.adapter.log.
|
|
733
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
730
734
|
try {
|
|
731
735
|
const climateIds = { target: '', act: '', mode: '' };
|
|
732
736
|
climateIds.target = `${this.adapter.namespace}.${config.TargetApplication}.devices.${config.TargetDevice}.${config.TargetFolder}.${config.TargetState}`;
|
|
@@ -766,7 +770,7 @@ class bridgeClass {
|
|
|
766
770
|
*/
|
|
767
771
|
async publishNotification(id, message, level) {
|
|
768
772
|
const activeFunction = 'bridge.js - publishNotification';
|
|
769
|
-
this.adapter.log.
|
|
773
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
770
774
|
try {
|
|
771
775
|
if (this.adapter.bridge.Notifications[id]) {
|
|
772
776
|
if (this.adapter.config.BridgenotificationActivation.includes(level)) {
|
|
@@ -795,7 +799,7 @@ class bridgeClass {
|
|
|
795
799
|
*/
|
|
796
800
|
async publishId(id, val, options) {
|
|
797
801
|
const activeFunction = 'bridge.js - publishId';
|
|
798
|
-
this.adapter.log.
|
|
802
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
799
803
|
try {
|
|
800
804
|
if (this.PublishedIds[id]) {
|
|
801
805
|
if (val === undefined) {
|
|
@@ -971,7 +975,7 @@ class bridgeClass {
|
|
|
971
975
|
*/
|
|
972
976
|
async buildDiscovery(id, options) {
|
|
973
977
|
const activeFunction = 'bridge.js - buildDiscovery';
|
|
974
|
-
this.adapter.log.
|
|
978
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
975
979
|
try {
|
|
976
980
|
// Defaultvalue for discover
|
|
977
981
|
let returnValue = { newDevice: undefined, newId: undefined };
|
|
@@ -1218,7 +1222,7 @@ class bridgeClass {
|
|
|
1218
1222
|
*/
|
|
1219
1223
|
async getDiscoveryObject(changeInfo, options) {
|
|
1220
1224
|
const activeFunction = 'bridge.js - getDiscoveryObject';
|
|
1221
|
-
this.adapter.log.
|
|
1225
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
1222
1226
|
try {
|
|
1223
1227
|
let indexOfStatebegin = -1;
|
|
1224
1228
|
// Check for state discover outsid the applications
|
|
@@ -1298,7 +1302,7 @@ class bridgeClass {
|
|
|
1298
1302
|
*/
|
|
1299
1303
|
async publishDiscovery(id, DiscoveryObject) {
|
|
1300
1304
|
const activeFunction = 'bridge.js - publishDiscovery';
|
|
1301
|
-
this.adapter.log.
|
|
1305
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
1302
1306
|
const returnValue = { newDevice: undefined, newId: undefined };
|
|
1303
1307
|
try {
|
|
1304
1308
|
if (!DiscoveryObject.lastDiscover) {
|
|
@@ -1384,7 +1388,7 @@ class bridgeClass {
|
|
|
1384
1388
|
*/
|
|
1385
1389
|
async getEntityType(options) {
|
|
1386
1390
|
const activeFunction = 'bridge.js - getEntityType';
|
|
1387
|
-
this.adapter.log.
|
|
1391
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
1388
1392
|
try {
|
|
1389
1393
|
const common = options.common;
|
|
1390
1394
|
const isWritable = options.Bridgestate.subscribe;
|
|
@@ -1434,7 +1438,7 @@ class bridgeClass {
|
|
|
1434
1438
|
*/
|
|
1435
1439
|
async getStateAttributes(common, entityType) {
|
|
1436
1440
|
const activeFunction = 'bridge.js - getStateAttributes';
|
|
1437
|
-
this.adapter.log.
|
|
1441
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
1438
1442
|
try {
|
|
1439
1443
|
const role = (common?.role || '').toLowerCase();
|
|
1440
1444
|
const unit = common?.unit || '';
|
|
@@ -1660,7 +1664,7 @@ class bridgeClass {
|
|
|
1660
1664
|
*/
|
|
1661
1665
|
getDeviceIdentifier(changeInfo, DeviceIdentifiers) {
|
|
1662
1666
|
const activeFunction = 'bridge.js - getDeviceIdentifier';
|
|
1663
|
-
this.adapter.log.
|
|
1667
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
1664
1668
|
try {
|
|
1665
1669
|
let DeviceIdentifier = '';
|
|
1666
1670
|
let Separator = '';
|
|
@@ -1719,7 +1723,7 @@ class bridgeClass {
|
|
|
1719
1723
|
*/
|
|
1720
1724
|
normalizeString(Inputstring) {
|
|
1721
1725
|
const activeFunction = 'bridge.js - normalizeString';
|
|
1722
|
-
this.adapter.log.
|
|
1726
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
1723
1727
|
try {
|
|
1724
1728
|
return Inputstring.replace(/ä/g, 'ae')
|
|
1725
1729
|
.replace(/ö/g, 'oe')
|
|
@@ -1751,7 +1755,7 @@ class bridgeClass {
|
|
|
1751
1755
|
*/
|
|
1752
1756
|
async checkAllStatesForBridgeWork(options) {
|
|
1753
1757
|
const activeFunction = 'bridge.js - checkAllStatesForBridgeWork';
|
|
1754
|
-
this.adapter.log.
|
|
1758
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
1755
1759
|
try {
|
|
1756
1760
|
// get old Discovered ids
|
|
1757
1761
|
this.OldDiscoveredIds = JSON.parse((await this.adapter.getStateAsync('info.discoveredIds')).val);
|
|
@@ -1804,7 +1808,7 @@ class bridgeClass {
|
|
|
1804
1808
|
/*
|
|
1805
1809
|
async checkAllStatesForBridgeWork(options) {
|
|
1806
1810
|
const activeFunction = 'bridge.js - checkAllStatesForBridgeWork';
|
|
1807
|
-
this.adapter.log.
|
|
1811
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
1808
1812
|
|
|
1809
1813
|
try {
|
|
1810
1814
|
// get old Discovered ids
|
|
@@ -1879,7 +1883,7 @@ class bridgeClass {
|
|
|
1879
1883
|
*/
|
|
1880
1884
|
generateOldDevices(oldDiscoveredIds) {
|
|
1881
1885
|
const activeFunction = 'bridge.js - generateOldDevices';
|
|
1882
|
-
this.adapter.log.
|
|
1886
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
1883
1887
|
try {
|
|
1884
1888
|
const oldDevices = {};
|
|
1885
1889
|
for (const id of Object.values(oldDiscoveredIds)) {
|
|
@@ -1976,7 +1980,7 @@ class bridgeClass {
|
|
|
1976
1980
|
*/
|
|
1977
1981
|
async checkDiscoveries() {
|
|
1978
1982
|
const activeFunction = 'bridge.js - checkDiscoveries';
|
|
1979
|
-
this.adapter.log.
|
|
1983
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
1980
1984
|
try {
|
|
1981
1985
|
for (const id in this.OldDiscoveredIds) {
|
|
1982
1986
|
if (!this.DiscoveredIds[id]) {
|
|
@@ -2013,7 +2017,7 @@ class bridgeClass {
|
|
|
2013
2017
|
*/
|
|
2014
2018
|
createScheduleJobs() {
|
|
2015
2019
|
const activeFunction = 'bridge.js - createScheduleJobs';
|
|
2016
|
-
this.adapter.log.
|
|
2020
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
2017
2021
|
try {
|
|
2018
2022
|
if (this.adapter.config.EnableRefresh) {
|
|
2019
2023
|
this.DiscoveryCronjob = schedule.scheduleJob(
|
|
@@ -2031,7 +2035,7 @@ class bridgeClass {
|
|
|
2031
2035
|
*/
|
|
2032
2036
|
async startScheduledDiscovery() {
|
|
2033
2037
|
const activeFunction = 'bridge.js - startScheduledDiscovery';
|
|
2034
|
-
this.adapter.log.
|
|
2038
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
2035
2039
|
try {
|
|
2036
2040
|
for (const DiscoveredId in this.DiscoveredIds) {
|
|
2037
2041
|
await this.publishDiscovery(DiscoveredId, this.DiscoveredIds[DiscoveredId]);
|
|
@@ -2046,7 +2050,7 @@ class bridgeClass {
|
|
|
2046
2050
|
*/
|
|
2047
2051
|
clearAllSchedules() {
|
|
2048
2052
|
const activeFunction = 'bridge.js - clearAllSchedules';
|
|
2049
|
-
this.adapter.log.
|
|
2053
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
2050
2054
|
try {
|
|
2051
2055
|
schedule.cancelJob(this.DiscoveryCronjob);
|
|
2052
2056
|
} catch (error) {
|
|
@@ -2062,7 +2066,7 @@ class bridgeClass {
|
|
|
2062
2066
|
*/
|
|
2063
2067
|
async getForeignClimateConfig() {
|
|
2064
2068
|
const activeFunction = 'bridge.js - getForeignClimateEntities';
|
|
2065
|
-
this.adapter.log.
|
|
2069
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
2066
2070
|
try {
|
|
2067
2071
|
for (const config of this.adapter.config.ClimateForeignConfig) {
|
|
2068
2072
|
await this.discoverForeignClimate(config);
|
|
@@ -2079,7 +2083,7 @@ class bridgeClass {
|
|
|
2079
2083
|
*/
|
|
2080
2084
|
async discoverForeignClimate(config) {
|
|
2081
2085
|
const activeFunction = 'bridge.js - discoverForeignClimateEntities';
|
|
2082
|
-
this.adapter.log.
|
|
2086
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
2083
2087
|
try {
|
|
2084
2088
|
// Assign the Ids (use the codenameing of discoverClimate)
|
|
2085
2089
|
if (!(await this.generateForeignClimateIds(config))) {
|
|
@@ -2256,7 +2260,7 @@ class bridgeClass {
|
|
|
2256
2260
|
*/
|
|
2257
2261
|
async generateForeignClimateIds(config) {
|
|
2258
2262
|
const activeFunction = 'generateForeignClimateIds';
|
|
2259
|
-
this.adapter.log.
|
|
2263
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
2260
2264
|
try {
|
|
2261
2265
|
const climateIds = { target: '', act: '', mode: '' };
|
|
2262
2266
|
climateIds.target = config.TargetId;
|
|
@@ -2295,7 +2299,7 @@ class bridgeClass {
|
|
|
2295
2299
|
*/
|
|
2296
2300
|
async getForeignHumidifierConfig() {
|
|
2297
2301
|
const activeFunction = 'bridge.js - getForeignHumidifierConfig';
|
|
2298
|
-
this.adapter.log.
|
|
2302
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
2299
2303
|
try {
|
|
2300
2304
|
for (const config of this.adapter.config.HumidifierForeignConfig) {
|
|
2301
2305
|
await this.discoverForeignHumidifier(config);
|
|
@@ -2312,7 +2316,7 @@ class bridgeClass {
|
|
|
2312
2316
|
*/
|
|
2313
2317
|
async discoverForeignHumidifier(config) {
|
|
2314
2318
|
const activeFunction = 'bridge.js - discoverForeignHumidifier';
|
|
2315
|
-
this.adapter.log.
|
|
2319
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
2316
2320
|
try {
|
|
2317
2321
|
// Assign the Ids (use the codenameing of discoverClimate)
|
|
2318
2322
|
if (!(await this.generateForeignHumidifierIds(config))) {
|
|
@@ -2492,7 +2496,7 @@ class bridgeClass {
|
|
|
2492
2496
|
*/
|
|
2493
2497
|
async generateForeignHumidifierIds(config) {
|
|
2494
2498
|
const activeFunction = 'generateForeignHumidifierIds';
|
|
2495
|
-
this.adapter.log.
|
|
2499
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
2496
2500
|
try {
|
|
2497
2501
|
const HumidifierIds = { onOff: '', target: '', act: '' };
|
|
2498
2502
|
HumidifierIds.onOff = config.OnOffId;
|
|
@@ -2524,7 +2528,7 @@ class bridgeClass {
|
|
|
2524
2528
|
*/
|
|
2525
2529
|
async getForeignLightConfig() {
|
|
2526
2530
|
const activeFunction = 'bridge.js - getForeignLightConfig';
|
|
2527
|
-
this.adapter.log.
|
|
2531
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
2528
2532
|
try {
|
|
2529
2533
|
for (const config of this.adapter.config.LightForeignConfig) {
|
|
2530
2534
|
await this.discoverForeignLight(config);
|
|
@@ -2541,7 +2545,7 @@ class bridgeClass {
|
|
|
2541
2545
|
*/
|
|
2542
2546
|
async discoverForeignLight(config) {
|
|
2543
2547
|
const activeFunction = 'bridge.js - discoverForeignLight';
|
|
2544
|
-
this.adapter.log.
|
|
2548
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
2545
2549
|
try {
|
|
2546
2550
|
// Assign the Ids (use the codenameing of discoverClimate)
|
|
2547
2551
|
if (!(await this.generateForeignLightIds(config))) {
|
|
@@ -2736,7 +2740,7 @@ class bridgeClass {
|
|
|
2736
2740
|
*/
|
|
2737
2741
|
async generateForeignLightIds(config) {
|
|
2738
2742
|
const activeFunction = 'generateForeignLightIds';
|
|
2739
|
-
this.adapter.log.
|
|
2743
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
2740
2744
|
try {
|
|
2741
2745
|
const LightIds = { onOff: '' };
|
|
2742
2746
|
LightIds.onOff = config.OnOffId;
|
|
@@ -2775,7 +2779,7 @@ class bridgeClass {
|
|
|
2775
2779
|
*/
|
|
2776
2780
|
async getForeignStatesForStandardEntities() {
|
|
2777
2781
|
const activeFunction = 'bridge.js - getForeignStatesForStandardEntities';
|
|
2778
|
-
this.adapter.log.
|
|
2782
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
2779
2783
|
try {
|
|
2780
2784
|
const idBridgefunction = this.adapter.config.BridgeEnum;
|
|
2781
2785
|
if (idBridgefunction !== '' && idBridgefunction !== '*') {
|
|
@@ -2803,7 +2807,7 @@ class bridgeClass {
|
|
|
2803
2807
|
*/
|
|
2804
2808
|
async getForeignCoverConfig() {
|
|
2805
2809
|
const activeFunction = 'bridge.js - getForeignCoverConfig';
|
|
2806
|
-
this.adapter.log.
|
|
2810
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
2807
2811
|
try {
|
|
2808
2812
|
for (const config of this.adapter.config.CoverForeignConfig) {
|
|
2809
2813
|
await this.discoverForeignCover(config);
|
|
@@ -2820,7 +2824,7 @@ class bridgeClass {
|
|
|
2820
2824
|
*/
|
|
2821
2825
|
async discoverForeignCover(config) {
|
|
2822
2826
|
const activeFunction = 'bridge.js - discoverForeignCover';
|
|
2823
|
-
this.adapter.log.
|
|
2827
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
2824
2828
|
try {
|
|
2825
2829
|
// Assign the Ids (use the codenameing of discoverClimate)
|
|
2826
2830
|
if (!(await this.generateForeignCoverIds(config))) {
|
|
@@ -3120,7 +3124,7 @@ class bridgeClass {
|
|
|
3120
3124
|
*/
|
|
3121
3125
|
async generateForeignCoverIds(config) {
|
|
3122
3126
|
const activeFunction = 'generateForeignCoverIds';
|
|
3123
|
-
this.adapter.log.
|
|
3127
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
3124
3128
|
try {
|
|
3125
3129
|
const CoverIds = {};
|
|
3126
3130
|
if (config.CoverSeparate === 'string') {
|
|
@@ -3171,7 +3175,7 @@ class bridgeClass {
|
|
|
3171
3175
|
*/
|
|
3172
3176
|
async getForeignLockConfig() {
|
|
3173
3177
|
const activeFunction = 'bridge.js - getForeignLockConfig';
|
|
3174
|
-
this.adapter.log.
|
|
3178
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
3175
3179
|
try {
|
|
3176
3180
|
for (const config of this.adapter.config.LockForeignConfig) {
|
|
3177
3181
|
await this.discoverForeignLock(config);
|
|
@@ -3188,7 +3192,7 @@ class bridgeClass {
|
|
|
3188
3192
|
*/
|
|
3189
3193
|
async discoverForeignLock(config) {
|
|
3190
3194
|
const activeFunction = 'bridge.js - discoverForeignLock';
|
|
3191
|
-
this.adapter.log.
|
|
3195
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
3192
3196
|
try {
|
|
3193
3197
|
// Assign the Ids (use the codenameing of discoverClimate)
|
|
3194
3198
|
if (!(await this.generateForeignLockIds(config))) {
|
|
@@ -3334,7 +3338,7 @@ class bridgeClass {
|
|
|
3334
3338
|
*/
|
|
3335
3339
|
async generateForeignLockIds(config) {
|
|
3336
3340
|
const activeFunction = 'generateForeignLockIds';
|
|
3337
|
-
this.adapter.log.
|
|
3341
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
3338
3342
|
try {
|
|
3339
3343
|
const LockIds = {};
|
|
3340
3344
|
if (config.LockSeparate === 'string') {
|
|
@@ -3377,7 +3381,7 @@ class bridgeClass {
|
|
|
3377
3381
|
*/
|
|
3378
3382
|
async discoverForeignRange(id, clear = false) {
|
|
3379
3383
|
const activeFunction = 'bridge.js - discoverForeignRange';
|
|
3380
|
-
this.adapter.log.
|
|
3384
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
3381
3385
|
try {
|
|
3382
3386
|
const params = {
|
|
3383
3387
|
startkey: id,
|
|
@@ -3419,7 +3423,7 @@ class bridgeClass {
|
|
|
3419
3423
|
*/
|
|
3420
3424
|
async getParentNameing(id) {
|
|
3421
3425
|
const activeFunction = 'bridge.js - getParentNameing';
|
|
3422
|
-
this.adapter.log.
|
|
3426
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
3423
3427
|
try {
|
|
3424
3428
|
let parentId = '';
|
|
3425
3429
|
let parentName = '';
|
|
@@ -3472,7 +3476,7 @@ class bridgeClass {
|
|
|
3472
3476
|
*/
|
|
3473
3477
|
async discoverForeignStandardEntity(id, options) {
|
|
3474
3478
|
const activeFunction = 'bridge.js - discoverForeignStandardEntity';
|
|
3475
|
-
this.adapter.log.
|
|
3479
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
3476
3480
|
try {
|
|
3477
3481
|
const state = await this.adapter.getForeignStateAsync(id);
|
|
3478
3482
|
|
|
@@ -3562,7 +3566,7 @@ class bridgeClass {
|
|
|
3562
3566
|
*/
|
|
3563
3567
|
async getUniqueString(id, deviceidentifier) {
|
|
3564
3568
|
const activeFunction = 'bridge.js - getUniqueString';
|
|
3565
|
-
this.adapter.log.
|
|
3569
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
3566
3570
|
try {
|
|
3567
3571
|
const unique = {
|
|
3568
3572
|
flat: `${this.normalizeString(deviceidentifier)}_${this.normalizeString(id)}`,
|
|
@@ -3579,7 +3583,7 @@ class bridgeClass {
|
|
|
3579
3583
|
*/
|
|
3580
3584
|
async getParentDevice(id) {
|
|
3581
3585
|
const activeFunction = 'bridge.js - getParentDevice';
|
|
3582
|
-
this.adapter.log.
|
|
3586
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
3583
3587
|
try {
|
|
3584
3588
|
const firstIdexOfDot = id.indexOf('.');
|
|
3585
3589
|
const lastIdexOfDot = id.lastIndexOf('.');
|
|
@@ -3605,7 +3609,7 @@ class bridgeClass {
|
|
|
3605
3609
|
*/
|
|
3606
3610
|
async getParentChannel(id) {
|
|
3607
3611
|
const activeFunction = 'bridge.js - getParentChannel';
|
|
3608
|
-
this.adapter.log.
|
|
3612
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
3609
3613
|
try {
|
|
3610
3614
|
const firstIdexOfDot = id.indexOf('.');
|
|
3611
3615
|
const lastIdexOfDot = id.lastIndexOf('.');
|
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* class to handle incomming messages from Bridge
|
|
3
|
+
*/
|
|
4
|
+
class bridgeDeviceHandlerClass {
|
|
5
|
+
/**
|
|
6
|
+
* @param adapter data of the adapter (eg. for logging)
|
|
7
|
+
*/
|
|
8
|
+
constructor(adapter) {
|
|
9
|
+
this.adapter = adapter;
|
|
10
|
+
this.basefolder = 'bridge.devices';
|
|
11
|
+
this.adapter.extendObject(this.basefolder, {
|
|
12
|
+
type: 'folder',
|
|
13
|
+
common: { name: 'Devices recieved from Bridge' },
|
|
14
|
+
native: {},
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Generate Structure of incomming Data
|
|
19
|
+
/**
|
|
20
|
+
* @param message message from bridge to generate devices (eg.)
|
|
21
|
+
*/
|
|
22
|
+
async generateDeviceStructure(message) {
|
|
23
|
+
const activeFunction = 'bridgeDeviceHandler.js - generateDeviceStructure';
|
|
24
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
25
|
+
try {
|
|
26
|
+
// Query for Entity
|
|
27
|
+
if (message.entities) {
|
|
28
|
+
for (const entity of Object.values(message.entities)) {
|
|
29
|
+
const entityInfo = this.generateStructure(entity);
|
|
30
|
+
await this.adapter.extendObject(entityInfo?.device.id, {
|
|
31
|
+
type: 'device',
|
|
32
|
+
common: { name: entity.device.name },
|
|
33
|
+
native: entity.device,
|
|
34
|
+
});
|
|
35
|
+
const channel = entity.entity_id.substring(0, entity.entity_id.indexOf('.'));
|
|
36
|
+
await this.adapter.extendObject(entityInfo?.channel.id, {
|
|
37
|
+
type: 'channel',
|
|
38
|
+
common: { name: 'Channel of Entity' },
|
|
39
|
+
native: {},
|
|
40
|
+
});
|
|
41
|
+
let unique_id = entity.unique_id;
|
|
42
|
+
if (entity.unique_id.startsWith(channel)) {
|
|
43
|
+
unique_id = unique_id.substring(channel.length + 1, unique_id.length);
|
|
44
|
+
}
|
|
45
|
+
unique_id.replace('.', '_');
|
|
46
|
+
await this.adapter.extendObject(entityInfo?.state.id, {
|
|
47
|
+
type: 'state',
|
|
48
|
+
common: {
|
|
49
|
+
name: entityInfo?.state.name,
|
|
50
|
+
type: entityInfo?.state.type,
|
|
51
|
+
role: entityInfo?.state.role,
|
|
52
|
+
read: entityInfo?.state.read,
|
|
53
|
+
write: entityInfo?.state.write,
|
|
54
|
+
unit: entityInfo?.state.unit,
|
|
55
|
+
},
|
|
56
|
+
native: { entity: entity, entityInfo: entityInfo },
|
|
57
|
+
});
|
|
58
|
+
let state = entity.state;
|
|
59
|
+
if (entityInfo?.state.type === 'boolean') {
|
|
60
|
+
state = entity.state === 'on';
|
|
61
|
+
} else if (entityInfo?.state.type === 'number') {
|
|
62
|
+
state = Number(entity.state);
|
|
63
|
+
}
|
|
64
|
+
await this.adapter.setState(entityInfo?.state.id, state, true);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Periodic discovery
|
|
68
|
+
if (message.discovery) {
|
|
69
|
+
const id = `${this.basefolder}.discoveredEntities`;
|
|
70
|
+
await this.adapter.extendObject(id, {
|
|
71
|
+
type: 'state',
|
|
72
|
+
common: {
|
|
73
|
+
name: 'Discovered Entities',
|
|
74
|
+
type: 'string',
|
|
75
|
+
role: 'json',
|
|
76
|
+
read: true,
|
|
77
|
+
write: false,
|
|
78
|
+
def: '',
|
|
79
|
+
},
|
|
80
|
+
native: {},
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Read current data
|
|
84
|
+
const discoveredEntities = await this.adapter.getStateAsync(id);
|
|
85
|
+
const checkDevices = {};
|
|
86
|
+
if (discoveredEntities.val) {
|
|
87
|
+
const entities = JSON.parse(discoveredEntities.val);
|
|
88
|
+
for (const entityId of Object.keys(entities)) {
|
|
89
|
+
if (!Object.keys(message.entities).includes(entityId)) {
|
|
90
|
+
const entityInfo = this.generateStructure(entities[entityId]);
|
|
91
|
+
await this.adapter.delObjectAsync(entityInfo?.state.id);
|
|
92
|
+
checkDevices[entityInfo?.device.id] = {};
|
|
93
|
+
if (entityInfo?.channel.id) {
|
|
94
|
+
checkDevices[entityInfo?.device.id][entityInfo?.channel.id] = {};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Check for delete channels and devices
|
|
100
|
+
for (const deviceId of Object.keys(checkDevices)) {
|
|
101
|
+
let foundStateInAnyChannel = false;
|
|
102
|
+
|
|
103
|
+
// Check channel
|
|
104
|
+
for (const channelId of Object.keys(checkDevices[deviceId])) {
|
|
105
|
+
const channelParams = {
|
|
106
|
+
startkey: `${channelId}.`,
|
|
107
|
+
endkey: `${channelId}.\u9999`,
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const channelStates = await this.adapter.getObjectViewAsync(
|
|
111
|
+
'system',
|
|
112
|
+
'state',
|
|
113
|
+
channelParams,
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
if (channelStates.rows.length > 0) {
|
|
117
|
+
// State found
|
|
118
|
+
foundStateInAnyChannel = true;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// No state
|
|
123
|
+
await this.adapter.delObjectAsync(channelId, { recursive: true });
|
|
124
|
+
this.adapter.log.debug(`Deleted empty channel: ${channelId}`);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Check device
|
|
128
|
+
if (!foundStateInAnyChannel) {
|
|
129
|
+
const deviceParams = {
|
|
130
|
+
startkey: `${deviceId}.`,
|
|
131
|
+
endkey: `${deviceId}.\u9999`,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const deviceStates = await this.adapter.getObjectViewAsync('system', 'state', deviceParams);
|
|
135
|
+
|
|
136
|
+
if (deviceStates.rows.length === 0) {
|
|
137
|
+
await this.adapter.delObjectAsync(deviceId, { recursive: true });
|
|
138
|
+
this.adapter.log.debug(`Deleted empty device: ${deviceId}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
await this.adapter.setState(id, JSON.stringify(message.entities), true);
|
|
144
|
+
}
|
|
145
|
+
} catch (error) {
|
|
146
|
+
this.adapter.log.error(`error at ${activeFunction}: ${error}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* @param entity entity wich contains the desired informations
|
|
152
|
+
*/
|
|
153
|
+
generateStructure(entity) {
|
|
154
|
+
const activeFunction = 'bridgeDeviceHandler.js - generateStructure';
|
|
155
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
156
|
+
try {
|
|
157
|
+
if (!entity || !entity.entity_id) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const [domain] = entity.entity_id.split('.');
|
|
162
|
+
|
|
163
|
+
const stateId = this.buildSafeStateId(entity);
|
|
164
|
+
if (!stateId) {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
const type = this.detectType(entity);
|
|
168
|
+
const assign = this.detectAssign(entity);
|
|
169
|
+
|
|
170
|
+
const device = {
|
|
171
|
+
id: `${this.basefolder}.${entity.device?.id ?? 'unknown_device'}`,
|
|
172
|
+
name: entity.device?.name || 'Unknown Device',
|
|
173
|
+
manufacturer: entity.device?.manufacturer || '',
|
|
174
|
+
model: entity.device?.model || '',
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const channel = {
|
|
178
|
+
id: `${this.basefolder}.${entity.device?.id}.${domain}`,
|
|
179
|
+
name: domain,
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const state = {
|
|
183
|
+
id: `${this.basefolder}.${entity.device?.id}.${domain}.${stateId}`,
|
|
184
|
+
name: entity.friendly_name || stateId,
|
|
185
|
+
type: type,
|
|
186
|
+
role: this.detectRole(entity, domain, type),
|
|
187
|
+
unit: entity.unit_of_measurement || undefined,
|
|
188
|
+
read: true,
|
|
189
|
+
write: this.isWritable(domain),
|
|
190
|
+
};
|
|
191
|
+
if (assign) {
|
|
192
|
+
state.assign = assign;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const meta = {
|
|
196
|
+
entity_id: entity.entity_id,
|
|
197
|
+
unique_id: entity.unique_id,
|
|
198
|
+
device_class: entity.device_class,
|
|
199
|
+
state_class: entity.state_class,
|
|
200
|
+
};
|
|
201
|
+
return {
|
|
202
|
+
device: device,
|
|
203
|
+
channel: channel,
|
|
204
|
+
state: state,
|
|
205
|
+
meta: meta,
|
|
206
|
+
};
|
|
207
|
+
} catch (error) {
|
|
208
|
+
this.adapter.log.error(`error at ${activeFunction}: ${error}`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* @param entity entity wich contains the deired informations
|
|
214
|
+
*/
|
|
215
|
+
detectType(entity) {
|
|
216
|
+
const activeFunction = 'bridgeDeviceHandler.js - detectType';
|
|
217
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
218
|
+
try {
|
|
219
|
+
const s = entity.state;
|
|
220
|
+
|
|
221
|
+
if (['on', 'off', 'true', 'false'].includes(s)) {
|
|
222
|
+
return 'boolean';
|
|
223
|
+
}
|
|
224
|
+
if (!isNaN(s) && s !== '') {
|
|
225
|
+
return 'number';
|
|
226
|
+
}
|
|
227
|
+
return 'string';
|
|
228
|
+
} catch (error) {
|
|
229
|
+
this.adapter.log.error(`error at ${activeFunction}: ${error}`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* @param entity entity wich contains the deired informations
|
|
235
|
+
*/
|
|
236
|
+
detectAssign(entity) {
|
|
237
|
+
const activeFunction = 'bridgeDeviceHandler.js - detectAssign';
|
|
238
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
239
|
+
try {
|
|
240
|
+
const s = entity.state;
|
|
241
|
+
if (['on', 'off'].includes(s)) {
|
|
242
|
+
return { true: 'on', false: 'off' };
|
|
243
|
+
}
|
|
244
|
+
if (['true', 'false'].includes(s)) {
|
|
245
|
+
return { true: 'true', false: 'false' };
|
|
246
|
+
}
|
|
247
|
+
return null;
|
|
248
|
+
} catch (error) {
|
|
249
|
+
this.adapter.log.error(`error at ${activeFunction}: ${error}`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* @param domain domain, wich contains the type of entity
|
|
255
|
+
*/
|
|
256
|
+
isWritable(domain) {
|
|
257
|
+
const activeFunction = 'bridgeDeviceHandler.js - isWritable';
|
|
258
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
259
|
+
try {
|
|
260
|
+
return [
|
|
261
|
+
'switch',
|
|
262
|
+
'light',
|
|
263
|
+
'input_boolean',
|
|
264
|
+
'input_number',
|
|
265
|
+
'input_select',
|
|
266
|
+
'climate',
|
|
267
|
+
'cover',
|
|
268
|
+
'lock',
|
|
269
|
+
].includes(domain);
|
|
270
|
+
} catch (error) {
|
|
271
|
+
this.adapter.log.error(`error at ${activeFunction}: ${error}`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* @param entity entity wich contains the desired informations
|
|
277
|
+
* @param domain domain wich contains the type of the entity
|
|
278
|
+
* @param type type wich contains the type of ioBroker state
|
|
279
|
+
*/
|
|
280
|
+
detectRole(entity, domain, type) {
|
|
281
|
+
const activeFunction = 'bridgeDeviceHandler.js - detectRole';
|
|
282
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
283
|
+
try {
|
|
284
|
+
if (domain === 'switch') {
|
|
285
|
+
return 'switch';
|
|
286
|
+
}
|
|
287
|
+
if (domain === 'light') {
|
|
288
|
+
return 'light';
|
|
289
|
+
}
|
|
290
|
+
if (domain === 'binary_sensor') {
|
|
291
|
+
return 'indicator';
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (entity.device_class) {
|
|
295
|
+
const map = {
|
|
296
|
+
temperature: 'value.temperature',
|
|
297
|
+
humidity: 'value.humidity',
|
|
298
|
+
power: 'value.power',
|
|
299
|
+
energy: 'value.energy',
|
|
300
|
+
window: 'sensor.window',
|
|
301
|
+
door: 'sensor.door',
|
|
302
|
+
};
|
|
303
|
+
if (map[entity.device_class]) {
|
|
304
|
+
return map[entity.device_class];
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (type === 'number') {
|
|
309
|
+
return 'value';
|
|
310
|
+
}
|
|
311
|
+
if (type === 'boolean') {
|
|
312
|
+
return 'indicator';
|
|
313
|
+
}
|
|
314
|
+
return 'state';
|
|
315
|
+
} catch (error) {
|
|
316
|
+
this.adapter.log.error(`error at ${activeFunction}: ${error}`);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* @param entity entity wich contains the deired informations
|
|
322
|
+
*/
|
|
323
|
+
buildSafeStateId(entity) {
|
|
324
|
+
const activeFunction = 'bridgeDeviceHandler.js - buildSafeStateId';
|
|
325
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
326
|
+
try {
|
|
327
|
+
// 1. Basis: unique_id oder entity_id
|
|
328
|
+
const baseId = entity.unique_id || entity.entity_id;
|
|
329
|
+
|
|
330
|
+
if (!baseId) {
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// if eg. switch in front => remove
|
|
335
|
+
const parts = baseId.split('.');
|
|
336
|
+
const raw =
|
|
337
|
+
parts.length > 1 && parts[0] === entity.entity_id?.split('.')[0] ? parts.slice(1).join('.') : baseId;
|
|
338
|
+
|
|
339
|
+
// 3. remove ".
|
|
340
|
+
return raw.replace(/\./g, '_');
|
|
341
|
+
} catch (error) {
|
|
342
|
+
this.adapter.log.error(`error at ${activeFunction}: ${error}`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/************************************************************************************
|
|
347
|
+
*
|
|
348
|
+
************************************************************************************/
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* @param id id wich is to send
|
|
352
|
+
* @param state state of the id
|
|
353
|
+
*/
|
|
354
|
+
async sendData(id, state) {
|
|
355
|
+
const activeFunction = 'bridgeDeviceHandler.js - sendData';
|
|
356
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
357
|
+
try {
|
|
358
|
+
const idObject = await this.adapter.getObjectAsync(id);
|
|
359
|
+
const sendInfo = {};
|
|
360
|
+
if (idObject.native.entityInfo.state.assign) {
|
|
361
|
+
sendInfo[idObject.native.entity.entity_id] = idObject.native.entityInfo.state.assign[state.val];
|
|
362
|
+
} else {
|
|
363
|
+
sendInfo[idObject.native.entity.entity_id] = state.val;
|
|
364
|
+
}
|
|
365
|
+
await this.adapter.bridge.publishId(`${this.adapter.namespace}.bridge.dataFromIob`, sendInfo, {});
|
|
366
|
+
await this.adapter.setState(`${this.adapter.namespace}.bridge.dataFromIob`, JSON.stringify(sendInfo), true);
|
|
367
|
+
} catch (error) {
|
|
368
|
+
this.adapter.log.error(`error at ${activeFunction}: ${error}`);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
module.exports = bridgeDeviceHandlerClass;
|
|
@@ -86,7 +86,7 @@ class directorieshandlerClass {
|
|
|
86
86
|
//general function for writecommands
|
|
87
87
|
this.executeWritecommand = async (writecommand, elementName, sourceId, value) => {
|
|
88
88
|
const activeFunction = 'executeWritecommand';
|
|
89
|
-
this.adapter.log.
|
|
89
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
90
90
|
try {
|
|
91
91
|
// Check, if there is a writetrigger and the stateval is not euqal its releaseVal(still present)
|
|
92
92
|
if (writecommand.releaseValue !== value) {
|
|
@@ -114,7 +114,7 @@ class directorieshandlerClass {
|
|
|
114
114
|
// Define settings for writecommand devicetype
|
|
115
115
|
this.writeCommandDeviceType = async (elementName, sourceId, value) => {
|
|
116
116
|
const activeFunction = 'writeCommandDeviceType';
|
|
117
|
-
this.adapter.log.
|
|
117
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
118
118
|
try {
|
|
119
119
|
const writecommand = {
|
|
120
120
|
destination: 'configuration.devicetype',
|
|
@@ -248,7 +248,7 @@ class directorieshandlerClass {
|
|
|
248
248
|
*/
|
|
249
249
|
async generateRekursivObjects(obj, startDirectory, topic, message, options) {
|
|
250
250
|
const activeFunction = 'generateRekursivObjects';
|
|
251
|
-
this.adapter.log.
|
|
251
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
252
252
|
try {
|
|
253
253
|
// just proceed with ojects
|
|
254
254
|
if (typeof obj === 'object') {
|
|
@@ -531,7 +531,7 @@ class directorieshandlerClass {
|
|
|
531
531
|
*/
|
|
532
532
|
getAttributValue(topic, message, resolvetype) {
|
|
533
533
|
const activeFunction = 'getAttributValue';
|
|
534
|
-
this.adapter.log.
|
|
534
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
535
535
|
try {
|
|
536
536
|
// Select search in case of origin
|
|
537
537
|
switch (this.adapter.config.origin) {
|
|
@@ -556,7 +556,7 @@ class directorieshandlerClass {
|
|
|
556
556
|
*/
|
|
557
557
|
getIconPath(topic, message, icontype) {
|
|
558
558
|
const activeFunction = 'getIconPath';
|
|
559
|
-
this.adapter.log.
|
|
559
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
560
560
|
try {
|
|
561
561
|
// Select search in case of origin
|
|
562
562
|
switch (this.adapter.config.origin) {
|
|
@@ -576,7 +576,7 @@ class directorieshandlerClass {
|
|
|
576
576
|
*/
|
|
577
577
|
analyseConnection(sf, rssi) {
|
|
578
578
|
const activeFunction = 'getIcon';
|
|
579
|
-
this.adapter.log.
|
|
579
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
580
580
|
try {
|
|
581
581
|
this.adapter.log.silly(`icon for device with sf: ${sf} and rssi: ${rssi} requested`);
|
|
582
582
|
let iconPath = `icons/wifiSf`;
|
|
@@ -615,7 +615,7 @@ class directorieshandlerClass {
|
|
|
615
615
|
*/
|
|
616
616
|
getDeviceStartDirectory(topic, message) {
|
|
617
617
|
const activeFunction = 'getDeviceStartDirectory';
|
|
618
|
-
this.adapter.log.
|
|
618
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
619
619
|
try {
|
|
620
620
|
const applicationId = `${this.getAttributValue(topic, message, this.searchableAttributeNames.applicationId)}`;
|
|
621
621
|
const deviceEUI = `${this.getAttributValue(topic, message, this.searchableAttributeNames.deviceEUI)}`;
|
|
@@ -633,7 +633,7 @@ class directorieshandlerClass {
|
|
|
633
633
|
*/
|
|
634
634
|
getTopicResolved(topic) {
|
|
635
635
|
const activeFunction = 'getTopicResolved';
|
|
636
|
-
this.adapter.log.
|
|
636
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
637
637
|
try {
|
|
638
638
|
this.adapter.log.silly(`topic ${topic} is requested for resolveing`);
|
|
639
639
|
// Select in case of origin
|
|
@@ -663,7 +663,7 @@ class directorieshandlerClass {
|
|
|
663
663
|
*/
|
|
664
664
|
getTtnAttributValue(topic, message, resolvetype) {
|
|
665
665
|
const activeFunction = 'getTtnAttributValue';
|
|
666
|
-
this.adapter.log.
|
|
666
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
667
667
|
try {
|
|
668
668
|
this.adapter.log.silly(`attribute ${resolvetype} is requested for ttn`);
|
|
669
669
|
const topicResolved = this.getTopicResolved(topic);
|
|
@@ -700,7 +700,7 @@ class directorieshandlerClass {
|
|
|
700
700
|
*/
|
|
701
701
|
getTtnIconPath(topic, message, icontype) {
|
|
702
702
|
const activeFunction = 'getTtnIconPath';
|
|
703
|
-
this.adapter.log.
|
|
703
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
704
704
|
try {
|
|
705
705
|
this.adapter.log.silly(`icontype ${icontype} is requested for ttn`);
|
|
706
706
|
switch (icontype) {
|
|
@@ -734,7 +734,7 @@ class directorieshandlerClass {
|
|
|
734
734
|
*/
|
|
735
735
|
getTtnTopicResolved(topic) {
|
|
736
736
|
const activeFunction = 'getTtnTopicResolved';
|
|
737
|
-
this.adapter.log.
|
|
737
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
738
738
|
try {
|
|
739
739
|
const topicElements = topic.split('/');
|
|
740
740
|
const topicResolved = {
|
|
@@ -771,7 +771,7 @@ class directorieshandlerClass {
|
|
|
771
771
|
*/
|
|
772
772
|
getChirpstackAttributValue(topic, message, resolvetype) {
|
|
773
773
|
const activeFunction = 'getChirpstackAttributValue';
|
|
774
|
-
this.adapter.log.
|
|
774
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
775
775
|
try {
|
|
776
776
|
this.adapter.log.silly(`attribute ${resolvetype} is requested for chirpstack`);
|
|
777
777
|
const topicResolved = this.getTopicResolved(topic);
|
|
@@ -808,7 +808,7 @@ class directorieshandlerClass {
|
|
|
808
808
|
*/
|
|
809
809
|
getChirpstackIconPath(topic, message, icontype) {
|
|
810
810
|
const activeFunction = 'getChirpstackIconPath';
|
|
811
|
-
this.adapter.log.
|
|
811
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
812
812
|
try {
|
|
813
813
|
this.adapter.log.silly(`icontype ${icontype} is requested for Chirpstack`);
|
|
814
814
|
switch (icontype) {
|
|
@@ -839,7 +839,7 @@ class directorieshandlerClass {
|
|
|
839
839
|
*/
|
|
840
840
|
getChirpstackTopicResolved(topic) {
|
|
841
841
|
const activeFunction = 'getChirpstackTopicResolved';
|
|
842
|
-
this.adapter.log.
|
|
842
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
843
843
|
try {
|
|
844
844
|
const topicElements = topic.split('/');
|
|
845
845
|
const topicResolved = {
|
|
@@ -60,7 +60,7 @@ class messagehandlerClass {
|
|
|
60
60
|
async checkTimestamps() {
|
|
61
61
|
const activeFunction = 'checkTimestamps';
|
|
62
62
|
try {
|
|
63
|
-
this.adapter.log.
|
|
63
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
64
64
|
const adapterObjects = await this.adapter.getAdapterObjectsAsync();
|
|
65
65
|
// Generate Infos of all defices and decoded folders
|
|
66
66
|
for (const adapterObject of Object.values(adapterObjects)) {
|
|
@@ -146,7 +146,10 @@ class messagehandlerClass {
|
|
|
146
146
|
try {
|
|
147
147
|
const adapterObjectsAtStart = await this.adapter.getAdapterObjectsAsync();
|
|
148
148
|
for (const adapterObject of Object.values(adapterObjectsAtStart)) {
|
|
149
|
-
if (
|
|
149
|
+
if (
|
|
150
|
+
adapterObject.type === 'device' &&
|
|
151
|
+
!adapterObject.id.startsWith(`${this.adapter.namespace}.bridge`)
|
|
152
|
+
) {
|
|
150
153
|
await this.fillWithDownlinkConfig(this.adapter.removeNamespace(adapterObject._id), {
|
|
151
154
|
startup: true,
|
|
152
155
|
});
|
|
@@ -179,7 +182,7 @@ class messagehandlerClass {
|
|
|
179
182
|
*/
|
|
180
183
|
async generateDeviceinfosAtStartup() {
|
|
181
184
|
const activeFunction = 'generateDeviceinfosAtStartup';
|
|
182
|
-
this.adapter.log.
|
|
185
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
183
186
|
try {
|
|
184
187
|
const adapterObjectsAtStart = await this.adapter.getAdapterObjectsAsync();
|
|
185
188
|
this.adapter.log.debug(`Adapter objects at start: ${JSON.stringify(adapterObjectsAtStart)}`);
|
|
@@ -284,7 +287,7 @@ class messagehandlerClass {
|
|
|
284
287
|
*/
|
|
285
288
|
async assignDeviceInformation(id, message) {
|
|
286
289
|
const activeFunction = 'assignDeviceInformation';
|
|
287
|
-
this.adapter.log.
|
|
290
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
288
291
|
try {
|
|
289
292
|
const changeInfo = await this.adapter.getChangeInfo(id);
|
|
290
293
|
// Create Attribute for application id
|
|
@@ -411,7 +414,7 @@ class messagehandlerClass {
|
|
|
411
414
|
async fillWithDownlinkConfig(deviceStartdirectory, options) {
|
|
412
415
|
const activeFunction = 'fillWithDownlinkConfig';
|
|
413
416
|
try {
|
|
414
|
-
this.adapter.log.
|
|
417
|
+
this.adapter.log.silly(`Function ${activeFunction} started.`);
|
|
415
418
|
const changeInfo = await this.adapter.getChangeInfo(`${deviceStartdirectory}.fillDownlinkFolder`, {
|
|
416
419
|
withBestMatch: true,
|
|
417
420
|
});
|
package/main.js
CHANGED
|
@@ -460,7 +460,7 @@ class Lorawan extends utils.Adapter {
|
|
|
460
460
|
async onObjectChange(id, obj) {
|
|
461
461
|
this.log.debug(`${id} is changed into ${JSON.stringify(obj.common)}`);
|
|
462
462
|
const activeFunction = 'main.js - onObjectChange';
|
|
463
|
-
this.log.
|
|
463
|
+
this.log.silly(`Function ${activeFunction} started.`);
|
|
464
464
|
try {
|
|
465
465
|
// Only work, if bridge is activ
|
|
466
466
|
if (this.bridge) {
|
|
@@ -876,6 +876,9 @@ class Lorawan extends utils.Adapter {
|
|
|
876
876
|
await this.setState(id, state.val, true);
|
|
877
877
|
await this.bridge.publishId(id, state.val, {});
|
|
878
878
|
}
|
|
879
|
+
} else if (id.startsWith(`${this.namespace}.bridge.devices.`)) {
|
|
880
|
+
await this.bridge?.bridgeDeviceHandler.sendData(id, state);
|
|
881
|
+
await this.setState(id, state.val, true);
|
|
879
882
|
}
|
|
880
883
|
} else {
|
|
881
884
|
// Query for 0_userdata or alias => states also publish with ack = false
|
|
@@ -900,7 +903,7 @@ class Lorawan extends utils.Adapter {
|
|
|
900
903
|
|
|
901
904
|
async checkSendDownlinkWithUplink(id, options) {
|
|
902
905
|
const activeFunction = 'main.js - checkSendDownlinkWithUplink';
|
|
903
|
-
this.log.
|
|
906
|
+
this.log.silly(`Function ${activeFunction} started.`);
|
|
904
907
|
try {
|
|
905
908
|
this.log.debug(`Check for send downlink with uplink.`);
|
|
906
909
|
const changeInfo = await this.getChangeInfo(id, { withBestMatch: true });
|
|
@@ -930,7 +933,7 @@ class Lorawan extends utils.Adapter {
|
|
|
930
933
|
|
|
931
934
|
async getNextSend(deviceDirectory) {
|
|
932
935
|
const activeFunction = 'main.js - getNextSend';
|
|
933
|
-
this.log.
|
|
936
|
+
this.log.silly(`Function ${activeFunction} started.`);
|
|
934
937
|
try {
|
|
935
938
|
const idFolder = `${deviceDirectory}.${this.messagehandler?.directoryhandler.reachableSubfolders.downlinkNextSend}`;
|
|
936
939
|
return await this.getStateAsync(`${idFolder}.hex`);
|
|
@@ -941,7 +944,7 @@ class Lorawan extends utils.Adapter {
|
|
|
941
944
|
|
|
942
945
|
async writeNextSend(changeInfo, payloadInHex) {
|
|
943
946
|
const activeFunction = 'main.js - writeNextSend';
|
|
944
|
-
this.log.
|
|
947
|
+
this.log.silly(`Function ${activeFunction} started.`);
|
|
945
948
|
try {
|
|
946
949
|
const idFolderNextSend = `${changeInfo.objectStartDirectory}.${this.messagehandler?.directoryhandler.reachableSubfolders.downlinkNextSend}`;
|
|
947
950
|
const stateId = `${idFolderNextSend}.hex`;
|
|
@@ -969,7 +972,7 @@ class Lorawan extends utils.Adapter {
|
|
|
969
972
|
// Serialize functions
|
|
970
973
|
async withLock(locksMap, key, fn) {
|
|
971
974
|
const activeFunction = 'main.js - withLock';
|
|
972
|
-
this.log.
|
|
975
|
+
this.log.silly(`Function ${activeFunction} started.`);
|
|
973
976
|
const prev = locksMap.get(key) || Promise.resolve();
|
|
974
977
|
|
|
975
978
|
// fn erst starten, wenn prev fertig ist (egal ob ok oder Fehler)
|
|
@@ -995,7 +998,7 @@ class Lorawan extends utils.Adapter {
|
|
|
995
998
|
|
|
996
999
|
async sendDownlink(topic, message, changeInfo) {
|
|
997
1000
|
const activeFunction = 'main.js - sendDownlink';
|
|
998
|
-
this.log.
|
|
1001
|
+
this.log.silly(`Function ${activeFunction} started.`);
|
|
999
1002
|
try {
|
|
1000
1003
|
await this.mqttClient?.publish(topic, message, {});
|
|
1001
1004
|
const idFolderNextSend = `${changeInfo.objectStartDirectory}.${this.messagehandler?.directoryhandler.reachableSubfolders.downlinkNextSend}`;
|
|
@@ -1015,7 +1018,7 @@ class Lorawan extends utils.Adapter {
|
|
|
1015
1018
|
|
|
1016
1019
|
getHexpayloadFromDownlink(downlinkmessage) {
|
|
1017
1020
|
const activeFunction = 'main.js - getHexpayloadFromDownlink';
|
|
1018
|
-
this.log.
|
|
1021
|
+
this.log.silly(`Function ${activeFunction} started.`);
|
|
1019
1022
|
try {
|
|
1020
1023
|
let downlink = downlinkmessage;
|
|
1021
1024
|
if (typeof downlink === 'string') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.lorawan",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.1",
|
|
4
4
|
"description": "converts the desired lora gateway data to a ioBroker structure",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "BenAhrdt",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"@iobroker/testing": "^5.2.2",
|
|
42
42
|
"@tsconfig/node20": "^20.1.8",
|
|
43
43
|
"@types/lodash": "^4.17.21",
|
|
44
|
-
"@types/node": "^
|
|
44
|
+
"@types/node": "^25.0.3",
|
|
45
45
|
"typescript": "~5.9.3"
|
|
46
46
|
},
|
|
47
47
|
"main": "main.js",
|