iobroker.lorawan 1.15.8 → 1.16.0
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 +3 -0
- package/io-package.json +14 -14
- package/lib/modules/bridge.js +167 -15
- package/main.js +129 -96
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,6 +23,9 @@ 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.0 (2025-09-16)
|
|
27
|
+
* (BenAhrdt) possibility to insert foreign states to bridge by using enum.functions.bridge
|
|
28
|
+
|
|
26
29
|
### 1.15.8 (2025-09-16)
|
|
27
30
|
* (BenAhrdt) remove await from some callings
|
|
28
31
|
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "lorawan",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.16.0",
|
|
5
5
|
"news": {
|
|
6
|
+
"1.16.0": {
|
|
7
|
+
"en": "possibility to insert foreign states to bridge by using enum.functions.bridge",
|
|
8
|
+
"de": "Möglichkeit, externe Zustände über enum.functions.bridge in die Bridge einzufügen.",
|
|
9
|
+
"ru": "Возможность вставки внешних состояний в мост путем использования enum.functions.bridge",
|
|
10
|
+
"pt": "possibilidade de inserir estados estrangeiros na ponte usando enum.functions.bridge",
|
|
11
|
+
"nl": "Mogelijkheid om externe toestanden in de brug in te voegen door gebruik te maken van enum.functions.bridge.",
|
|
12
|
+
"fr": "possibilité d'insérer des états étrangers dans le pont en utilisant enum.functions.bridge",
|
|
13
|
+
"it": "Possibilità di inserire stati esterni al bridge utilizzando enum.functions.bridge",
|
|
14
|
+
"es": "Posibilidad de insertar estados extranjeros en el puente utilizando enum.functions.bridge",
|
|
15
|
+
"pl": "możliwość wstawienia stanów zewnętrznych do mostka za pomocą enum.functions.bridge",
|
|
16
|
+
"uk": "Можливість додавання зовнішніх станів до моста за допомогою enum.functions.bridge",
|
|
17
|
+
"zh-cn": "通过使用enum.functions.bridge功能,可以将外部状态插入到桥接器中。"
|
|
18
|
+
},
|
|
6
19
|
"1.15.8": {
|
|
7
20
|
"en": "remove await from some callings",
|
|
8
21
|
"de": "Entferne das „await“ aus einigen Aufrufen.",
|
|
@@ -80,19 +93,6 @@
|
|
|
80
93
|
"pl": "nie tłumacz stanu \"selected\" w konfiguracji mostu",
|
|
81
94
|
"uk": "не перекладайте обраний стан в конфігурації моста",
|
|
82
95
|
"zh-cn": "不要将“selected state”翻译成桥接配置"
|
|
83
|
-
},
|
|
84
|
-
"1.15.2": {
|
|
85
|
-
"en": "change wording of notifications\nimport diagnostic and config fpr entity_type\nchange extSernsorTemperature in ExtSernsorTemperature",
|
|
86
|
-
"de": "Änderung der Benachrichtigungen\nDiagnose und konfiguriere entity_type\nÄndern von extSernsorTemperature in ExtSernsorTemperature",
|
|
87
|
-
"ru": "изменить формулировку уведомлений\nИсправление диагностики и конфигурации для типа entity\nИзменено extSernsorTemperature на ExtSernsorTemperature",
|
|
88
|
-
"pt": "alterar a redação das notificações\nimportação de diagnóstico e configuração para o tipo de entidade\nAlterar extSernsorTemperature para ExtSernsorTemperature",
|
|
89
|
-
"nl": "wijziging van meldingen\nimport diagnose en configuratie voor entity_type\nVerander extSernsorTemperature in ExtSernsorTemperature",
|
|
90
|
-
"fr": "modifier le libellé des notifications\nImporter le diagnostic et la configuration pour le type d'entité\nChanger extSernsorTemperature en ExtSernsorTemperature",
|
|
91
|
-
"it": "modificare i testi delle notifiche\nimport diagnostiche e configurazioni per il tipo di entità\nModifica extSernsorTemperature in ExtSernsorTemperature",
|
|
92
|
-
"es": "cambiar la redacción de las notificaciones\nimportar diagnóstico y configuración para el tipo de entidad\nCambiar extSensorTemperature a ExtSensorTemperature",
|
|
93
|
-
"pl": "zmień sformułowanie powiadomień\nimport diagnostyka i konfiguracja dla entity_type\nzmień extSensorTemperature na ExtSensorTemperature",
|
|
94
|
-
"uk": "змінити формулювання сповіщень\nімпорт діагнострики та конфігурації для типу entity\nЗміна extSensorTemperature на ExtSensorTemperature",
|
|
95
|
-
"zh-cn": "更改通知内容\n为entity_type添加诊断和配置\n将\"extSensorTemperature\"更改为\"ExtSensorTemperature\""
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
98
|
"titleLang": {
|
package/lib/modules/bridge.js
CHANGED
|
@@ -70,7 +70,7 @@ class bridgeClass {
|
|
|
70
70
|
second: '2-digit',
|
|
71
71
|
},
|
|
72
72
|
};
|
|
73
|
-
|
|
73
|
+
this.ids = {};
|
|
74
74
|
// Unitmapping zur Zuweisung der passenden Unit, wenn diese falsch geschrieben ist
|
|
75
75
|
this.unitMap = {
|
|
76
76
|
'°C': { device_class: 'temperature' },
|
|
@@ -207,7 +207,12 @@ class bridgeClass {
|
|
|
207
207
|
await this.publishId(this.SubscribedTopics[topic].id, message, {});
|
|
208
208
|
return;
|
|
209
209
|
}
|
|
210
|
-
|
|
210
|
+
// Check for namespace and write own, oder foreign state
|
|
211
|
+
if (this.SubscribedTopics[topic].id.startsWith(this.adapter.namespace)) {
|
|
212
|
+
await this.adapter.setState(this.SubscribedTopics[topic].id, message);
|
|
213
|
+
} else {
|
|
214
|
+
await this.adapter.setForeignStateAsync(this.SubscribedTopics[topic].id, message);
|
|
215
|
+
}
|
|
211
216
|
await this.adapter.setState('info.subscribedTopics', JSON.stringify(this.DiscoveredIds), true);
|
|
212
217
|
} else {
|
|
213
218
|
this.adapter.log.debug(`The received Topic ${topic} is not subscribed`);
|
|
@@ -226,8 +231,6 @@ class bridgeClass {
|
|
|
226
231
|
const activeFunction = 'bridge.js - work';
|
|
227
232
|
this.adapter.log.debug(`Function ${activeFunction} started.`);
|
|
228
233
|
try {
|
|
229
|
-
// First remove namespace from id
|
|
230
|
-
id = this.adapter.removeNamespace(id);
|
|
231
234
|
if (this.bridgeMqttClient.internalConnectionstate) {
|
|
232
235
|
const countBefore = Object.keys(this.DiscoveredIds).length;
|
|
233
236
|
await this.discovery(id, options);
|
|
@@ -293,7 +296,7 @@ class bridgeClass {
|
|
|
293
296
|
const activeFunction = 'discoverDeviceNotifications';
|
|
294
297
|
this.adapter.log.debug(`Function ${activeFunction} started.`);
|
|
295
298
|
try {
|
|
296
|
-
const notificationId = `${changeInfo.objectStartDirectory}${this.NotificationId}${this.GeneralId}`;
|
|
299
|
+
const notificationId = `${this.adapter.namespace}.${changeInfo.objectStartDirectory}${this.NotificationId}${this.GeneralId}`;
|
|
297
300
|
if (!this.Notifications[notificationId]) {
|
|
298
301
|
const deviceIdentifier = this.getDeviceIdentifier(changeInfo, this.adapter.config.DeviceIdentifiers);
|
|
299
302
|
const normalizedDeviceIdentifier = this.normalizeString(deviceIdentifier);
|
|
@@ -319,7 +322,7 @@ class bridgeClass {
|
|
|
319
322
|
// offline
|
|
320
323
|
const offline = {
|
|
321
324
|
topic: `${this.bridgeMqttClient.BridgePrefix}${normalizedDeviceIdentifier}/${this.Words.notification}_${this.Words.offline}${this.EndingState}`.toLowerCase(),
|
|
322
|
-
notificationId: `${changeInfo.objectStartDirectory}${this.NotificationId}${this.OfflineId}`,
|
|
325
|
+
notificationId: `${this.adapter.namespace}.${changeInfo.objectStartDirectory}${this.NotificationId}${this.OfflineId}`,
|
|
323
326
|
};
|
|
324
327
|
discoveryobject = this.getNotificationDiscoveryObject(deviceIdentifier, this.Words.offline);
|
|
325
328
|
this.Notifications[offline.notificationId] = {};
|
|
@@ -339,7 +342,7 @@ class bridgeClass {
|
|
|
339
342
|
// online
|
|
340
343
|
const online = {
|
|
341
344
|
topic: `${this.bridgeMqttClient.BridgePrefix}${normalizedDeviceIdentifier}/${this.Words.notification}_${this.Words.online}${this.EndingState}`.toLowerCase(),
|
|
342
|
-
notificationId: `${changeInfo.objectStartDirectory}${this.NotificationId}${this.OnlineId}`,
|
|
345
|
+
notificationId: `${this.adapter.namespace}.${changeInfo.objectStartDirectory}${this.NotificationId}${this.OnlineId}`,
|
|
343
346
|
};
|
|
344
347
|
discoveryobject = this.getNotificationDiscoveryObject(deviceIdentifier, this.Words.online);
|
|
345
348
|
this.Notifications[online.notificationId] = {};
|
|
@@ -372,7 +375,7 @@ class bridgeClass {
|
|
|
372
375
|
const activeFunction = 'discoverGeneralNotification';
|
|
373
376
|
this.adapter.log.debug(`Function ${activeFunction} started.`);
|
|
374
377
|
try {
|
|
375
|
-
const notificationId = `${this.Words.notification}${this.GeneralId}`;
|
|
378
|
+
const notificationId = `${this.adapter.namespace}.${this.Words.notification}${this.GeneralId}`;
|
|
376
379
|
if (!this.Notifications[notificationId]) {
|
|
377
380
|
const discoveryobject = this.getNotificationDiscoveryObject(this.adapter.namespace, this.Words.general);
|
|
378
381
|
this.Notifications[notificationId] = {};
|
|
@@ -638,12 +641,12 @@ class bridgeClass {
|
|
|
638
641
|
this.adapter.log.debug(`Function ${activeFunction} started.`);
|
|
639
642
|
try {
|
|
640
643
|
const climateIds = { target: '', act: '', mode: '' };
|
|
641
|
-
climateIds.target = `${config.TargetApplication}.devices.${config.TargetDevice}.${config.TargetFolder}.${config.TargetState}`;
|
|
642
|
-
climateIds.act = `${config.ActApplication}.devices.${config.ActDevice}.${config.ActFolder}.${config.ActState}`;
|
|
644
|
+
climateIds.target = `${this.adapter.namespace}.${config.TargetApplication}.devices.${config.TargetDevice}.${config.TargetFolder}.${config.TargetState}`;
|
|
645
|
+
climateIds.act = `${this.adapter.namespace}.${config.ActApplication}.devices.${config.ActDevice}.${config.ActFolder}.${config.ActState}`;
|
|
643
646
|
if (config.ModeApplication === 'NotPresent') {
|
|
644
|
-
climateIds.mode = `${config.TargetApplication}.devices.${config.TargetDevice}.${config.TargetFolder}${this.EndingVirtualMode}`;
|
|
647
|
+
climateIds.mode = `${this.adapter.namespace}.${config.TargetApplication}.devices.${config.TargetDevice}.${config.TargetFolder}${this.EndingVirtualMode}`;
|
|
645
648
|
} else {
|
|
646
|
-
climateIds.mode = `${config.ModeApplication}.devices.${config.ModeDevice}.${config.ModeFolder}.${config.ModeState}`;
|
|
649
|
+
climateIds.mode = `${this.adapter.namespace}.${config.ModeApplication}.devices.${config.ModeDevice}.${config.ModeFolder}.${config.ModeState}`;
|
|
647
650
|
}
|
|
648
651
|
for (const id of Object.values(climateIds)) {
|
|
649
652
|
if (!(await this.adapter.objectExists(id)) && !id.endsWith(this.EndingVirtualMode)) {
|
|
@@ -724,7 +727,7 @@ class bridgeClass {
|
|
|
724
727
|
val = State.val;
|
|
725
728
|
}
|
|
726
729
|
}
|
|
727
|
-
// safe old values (
|
|
730
|
+
// safe old values (5 last values)
|
|
728
731
|
if (this.PublishedIds[id].values) {
|
|
729
732
|
if (!this.PublishedIds[id].oldValues) {
|
|
730
733
|
this.PublishedIds[id].oldValues = [];
|
|
@@ -786,7 +789,7 @@ class bridgeClass {
|
|
|
786
789
|
(changeInfo.applicationId === config.Application || config.Application === '*') &&
|
|
787
790
|
(changeInfo.deviceEUI === config.Device || config.Device === '*') &&
|
|
788
791
|
(id.includes(`.${config.Folder}.`) || config.Folder === '*') &&
|
|
789
|
-
(id.endsWith(
|
|
792
|
+
(id.endsWith(`.decoded.${config.State}`) || config.State === '*')
|
|
790
793
|
) {
|
|
791
794
|
Bridgestate.discover = !config.exclude;
|
|
792
795
|
Bridgestate.publish = config.publish;
|
|
@@ -852,7 +855,7 @@ class bridgeClass {
|
|
|
852
855
|
(changeInfo.applicationId === config.Application || config.Application === '*') &&
|
|
853
856
|
(changeInfo.deviceEUI === config.Device || config.Device === '*') &&
|
|
854
857
|
(id.includes(`.${config.Folder}.`) || config.Folder === '*') &&
|
|
855
|
-
(id.endsWith(
|
|
858
|
+
(id.endsWith(`.control.${config.State}`) || config.State === '*')
|
|
856
859
|
) {
|
|
857
860
|
Bridgestate.discover = !config.exclude;
|
|
858
861
|
Bridgestate.publish = config.publish;
|
|
@@ -1390,6 +1393,7 @@ class bridgeClass {
|
|
|
1390
1393
|
}
|
|
1391
1394
|
await this.discoverClimate();
|
|
1392
1395
|
await this.discoverGeneralNotification();
|
|
1396
|
+
await this.getForeignStatesForStandardEntities();
|
|
1393
1397
|
} catch (error) {
|
|
1394
1398
|
this.adapter.log.error(`error at ${activeFunction}: ${error}`);
|
|
1395
1399
|
}
|
|
@@ -1441,5 +1445,153 @@ class bridgeClass {
|
|
|
1441
1445
|
this.adapter.log.error(`error at ${activeFunction}: ${error}`);
|
|
1442
1446
|
}
|
|
1443
1447
|
}
|
|
1448
|
+
|
|
1449
|
+
/*****************************************************************
|
|
1450
|
+
* *********************** Foreign functions *********************
|
|
1451
|
+
* **************************************************************/
|
|
1452
|
+
/**
|
|
1453
|
+
* get Foreign states for Bridge
|
|
1454
|
+
*/
|
|
1455
|
+
async getForeignStatesForStandardEntities() {
|
|
1456
|
+
const activeFunction = 'bridge.js - getForeignStatesForStandardEntities';
|
|
1457
|
+
this.adapter.log.debug(`Function ${activeFunction} started.`);
|
|
1458
|
+
try {
|
|
1459
|
+
const functions = await this.adapter.getEnums('functions');
|
|
1460
|
+
if (functions['enum.functions']['enum.functions.bridge']) {
|
|
1461
|
+
for (const member of functions['enum.functions']['enum.functions.bridge'].common.members) {
|
|
1462
|
+
const params = {
|
|
1463
|
+
startkey: member,
|
|
1464
|
+
endkey: `${member}.\u9999`,
|
|
1465
|
+
};
|
|
1466
|
+
const states = await this.adapter.getObjectViewAsync('system', 'state', params);
|
|
1467
|
+
for (const state of states.rows) {
|
|
1468
|
+
const common = state.value.common;
|
|
1469
|
+
await this.discoverForeignStandardEntity(state.id, { common: common });
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
} catch (error) {
|
|
1474
|
+
this.adapter.log.error(`error at ${activeFunction}: ${error}`);
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
/**
|
|
1479
|
+
* @param id id to discover foreign state
|
|
1480
|
+
* @param options options of foreign state
|
|
1481
|
+
*/
|
|
1482
|
+
async discoverForeignStandardEntity(id, options) {
|
|
1483
|
+
const activeFunction = 'bridge.js - discoverForeignStandardEntity';
|
|
1484
|
+
this.adapter.log.debug(`Function ${activeFunction} started.`);
|
|
1485
|
+
try {
|
|
1486
|
+
const state = await this.adapter.getForeignStateAsync(id);
|
|
1487
|
+
const parentObject = await this.getParentObject(id);
|
|
1488
|
+
let partentId = '';
|
|
1489
|
+
let parentName = '';
|
|
1490
|
+
if (typeof parentObject === 'object') {
|
|
1491
|
+
partentId = parentObject._id;
|
|
1492
|
+
parentName = parentObject.common.name;
|
|
1493
|
+
} else {
|
|
1494
|
+
partentId = parentObject;
|
|
1495
|
+
parentName = partentId;
|
|
1496
|
+
}
|
|
1497
|
+
const deviceIdentifier = parentName;
|
|
1498
|
+
const statename = id.substring(partentId.length + 1, id.length);
|
|
1499
|
+
options.Bridgestate = {
|
|
1500
|
+
publish: options.common.read,
|
|
1501
|
+
subscribe: options.common.write,
|
|
1502
|
+
};
|
|
1503
|
+
const normalizedStateName = this.normalizeString(statename);
|
|
1504
|
+
const normalizedDeviceIdentifier = this.normalizeString(deviceIdentifier);
|
|
1505
|
+
const topic =
|
|
1506
|
+
`${this.bridgeMqttClient.BridgePrefix}${normalizedDeviceIdentifier}/${normalizedStateName}`.toLowerCase();
|
|
1507
|
+
const EntityType = await this.getEntityType(options);
|
|
1508
|
+
const AdditionalAttributes = await this.getStateAttributes(options.common, EntityType);
|
|
1509
|
+
const discoveryTopic =
|
|
1510
|
+
`${this.BridgeDiscoveryPrefix[this.adapter.config.BridgeType]}${EntityType}/${normalizedDeviceIdentifier}/${normalizedStateName}/config`.toLowerCase();
|
|
1511
|
+
const discoveryPayload = {
|
|
1512
|
+
name: statename,
|
|
1513
|
+
unique_id: `${normalizedDeviceIdentifier}_${normalizedStateName}`.toLowerCase(),
|
|
1514
|
+
device: { identifiers: [normalizedDeviceIdentifier.toLowerCase()], name: deviceIdentifier },
|
|
1515
|
+
};
|
|
1516
|
+
// Add Topics
|
|
1517
|
+
if (options.Bridgestate.publish) {
|
|
1518
|
+
discoveryPayload.state_topic = `${topic}${this.EndingState}`;
|
|
1519
|
+
}
|
|
1520
|
+
if (options.Bridgestate.subscribe) {
|
|
1521
|
+
discoveryPayload.command_topic = `${topic}${this.EndingSet}`;
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
// Assign Attibute to Payload
|
|
1525
|
+
for (const Attribute in AdditionalAttributes) {
|
|
1526
|
+
discoveryPayload[Attribute] = AdditionalAttributes[Attribute];
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
if (options.Bridgestate.publish) {
|
|
1530
|
+
if (!this.PublishedIds[id]) {
|
|
1531
|
+
this.PublishedIds[id] = { discovery: [] };
|
|
1532
|
+
}
|
|
1533
|
+
this.PublishedIds[id].discovery.push({
|
|
1534
|
+
topic: discoveryTopic,
|
|
1535
|
+
payload: structuredClone(discoveryPayload),
|
|
1536
|
+
});
|
|
1537
|
+
this.PublishedIds[id].state_topic = discoveryPayload.state_topic;
|
|
1538
|
+
}
|
|
1539
|
+
if (options.Bridgestate.subscribe) {
|
|
1540
|
+
if (!this.SubscribedTopics[discoveryPayload.command_topic]) {
|
|
1541
|
+
this.SubscribedTopics[discoveryPayload.command_topic] = { discovery: [] };
|
|
1542
|
+
}
|
|
1543
|
+
this.SubscribedTopics[discoveryPayload.command_topic].discovery.push({
|
|
1544
|
+
topic: discoveryTopic,
|
|
1545
|
+
payload: structuredClone(discoveryPayload),
|
|
1546
|
+
});
|
|
1547
|
+
this.SubscribedTopics[discoveryPayload.command_topic].id = id;
|
|
1548
|
+
}
|
|
1549
|
+
await this.publishDiscovery(id, {
|
|
1550
|
+
topic: discoveryTopic,
|
|
1551
|
+
payload: structuredClone(discoveryPayload),
|
|
1552
|
+
});
|
|
1553
|
+
// Delay for publish new entity
|
|
1554
|
+
setTimeout(async () => {
|
|
1555
|
+
await this.publishId(id, state.val, {});
|
|
1556
|
+
}, 1000);
|
|
1557
|
+
// Subscribe state for onStatechange mathode
|
|
1558
|
+
this.adapter.subscribeForeignStatesAsync(id);
|
|
1559
|
+
} catch (error) {
|
|
1560
|
+
this.adapter.log.error(`error at ${activeFunction}: ${error}`);
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
/**
|
|
1565
|
+
* @param id id to get parent Object
|
|
1566
|
+
*/
|
|
1567
|
+
async getParentObject(id) {
|
|
1568
|
+
const activeFunction = 'bridge.js - getParentObject';
|
|
1569
|
+
this.adapter.log.debug(`Function ${activeFunction} started.`);
|
|
1570
|
+
try {
|
|
1571
|
+
const firstIdexOfDot = id.indexOf('.');
|
|
1572
|
+
const lastIdexOfDot = id.lastIndexOf('.');
|
|
1573
|
+
if (lastIdexOfDot > firstIdexOfDot + 3) {
|
|
1574
|
+
id = id.substring(0, lastIdexOfDot);
|
|
1575
|
+
const firstObj = await this.adapter.getForeignObjectAsync(id);
|
|
1576
|
+
if (!firstObj) {
|
|
1577
|
+
return undefined;
|
|
1578
|
+
}
|
|
1579
|
+
if (firstObj?.type === 'device') {
|
|
1580
|
+
return firstObj;
|
|
1581
|
+
}
|
|
1582
|
+
if (firstObj.type === 'channel') {
|
|
1583
|
+
const secondObj = await this.getParentObject(id);
|
|
1584
|
+
if (secondObj !== undefined) {
|
|
1585
|
+
return secondObj;
|
|
1586
|
+
}
|
|
1587
|
+
return firstObj;
|
|
1588
|
+
}
|
|
1589
|
+
return await this.getParentObject(id);
|
|
1590
|
+
}
|
|
1591
|
+
return id.substring(0, lastIdexOfDot);
|
|
1592
|
+
} catch (error) {
|
|
1593
|
+
this.adapter.log.error(`error at ${activeFunction}: ${error}`);
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1444
1596
|
}
|
|
1445
1597
|
module.exports = bridgeClass;
|
package/main.js
CHANGED
|
@@ -448,118 +448,151 @@ class Lorawan extends utils.Adapter {
|
|
|
448
448
|
);
|
|
449
449
|
}
|
|
450
450
|
if (!state.ack) {
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
try {
|
|
459
|
-
if (JSON.parse(state.val)) {
|
|
460
|
-
await this.sendDownlink(downlinkTopic, state.val, changeInfo);
|
|
461
|
-
await this.bridge?.publishId(this.removeNamespace(id), state.val, {});
|
|
462
|
-
await this.setState(id, state.val, true);
|
|
463
|
-
}
|
|
464
|
-
} catch (error) {
|
|
465
|
-
this.log.warn(`Cant send invalid downlinks. Error: ${error}`);
|
|
466
|
-
}
|
|
467
|
-
} else if (changeInfo?.changedState === 'CustomSend') {
|
|
468
|
-
if (state.val !== '') {
|
|
451
|
+
if (id.startsWith(this.namespace)) {
|
|
452
|
+
// Check for downlink in id
|
|
453
|
+
if (id.indexOf('.downlink.control.') !== -1) {
|
|
454
|
+
// get information of the changing state
|
|
455
|
+
const changeInfo = await this.getChangeInfo(id, { withBestMatch: true });
|
|
456
|
+
const suffix = this.downlinkConfighandler?.getDownlinkTopicSuffix(changeInfo?.changedState);
|
|
457
|
+
if (changeInfo?.changedState === 'push' || changeInfo?.changedState === 'replace') {
|
|
469
458
|
const downlinkTopic = this.downlinkConfighandler?.getDownlinkTopic(changeInfo, suffix);
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
changeInfo
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
Confirmed: Statevalues[2]
|
|
479
|
-
? Statevalues[2] === 'true'
|
|
480
|
-
? true
|
|
481
|
-
: false
|
|
482
|
-
: downlinkConfig.confirmed,
|
|
483
|
-
Priority: Statevalues[3] ? Statevalues[3] : downlinkConfig.priority,
|
|
484
|
-
};
|
|
485
|
-
// Query for righte type
|
|
486
|
-
this.log.debug('The following values are detected at input of custom send state');
|
|
487
|
-
for (const element of Object.values(StateElements)) {
|
|
488
|
-
this.log.debug(typeof element);
|
|
489
|
-
this.log.debug(element);
|
|
459
|
+
try {
|
|
460
|
+
if (JSON.parse(state.val)) {
|
|
461
|
+
await this.sendDownlink(downlinkTopic, state.val, changeInfo);
|
|
462
|
+
await this.bridge?.publishId(id, state.val, {});
|
|
463
|
+
await this.setState(id, state.val, true);
|
|
464
|
+
}
|
|
465
|
+
} catch (error) {
|
|
466
|
+
this.log.warn(`Cant send invalid downlinks. Error: ${error}`);
|
|
490
467
|
}
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
!changeInfo?.bestMatchForDeviceType ||
|
|
495
|
-
this.downlinkConfighandler?.activeDownlinkConfigs[changeInfo.bestMatchForDeviceType]
|
|
496
|
-
.sendWithUplink === 'disabled'
|
|
497
|
-
) {
|
|
498
|
-
const downlink = this.downlinkConfighandler?.getDownlink(
|
|
499
|
-
{
|
|
500
|
-
port: StateElements.Port,
|
|
501
|
-
confirmed: StateElements.Confirmed,
|
|
502
|
-
priority: StateElements.Priority,
|
|
503
|
-
},
|
|
504
|
-
StateElements.PayloadInHex,
|
|
468
|
+
} else if (changeInfo?.changedState === 'CustomSend') {
|
|
469
|
+
if (state.val !== '') {
|
|
470
|
+
const downlinkTopic = this.downlinkConfighandler?.getDownlinkTopic(
|
|
505
471
|
changeInfo,
|
|
472
|
+
suffix,
|
|
506
473
|
);
|
|
507
|
-
|
|
508
|
-
|
|
474
|
+
const downlinkConfig =
|
|
475
|
+
this.downlinkConfighandler?.activeDownlinkConfigs[
|
|
476
|
+
changeInfo.bestMatchForDeviceType
|
|
477
|
+
];
|
|
478
|
+
const Statevalues = state.val.split(',');
|
|
479
|
+
const StateElements = {
|
|
480
|
+
PayloadInHex: Statevalues[0].toUpperCase(),
|
|
481
|
+
Port: Statevalues[1] ? parseInt(Statevalues[1]) : downlinkConfig.port,
|
|
482
|
+
Confirmed: Statevalues[2]
|
|
483
|
+
? Statevalues[2] === 'true'
|
|
484
|
+
? true
|
|
485
|
+
: false
|
|
486
|
+
: downlinkConfig.confirmed,
|
|
487
|
+
Priority: Statevalues[3] ? Statevalues[3] : downlinkConfig.priority,
|
|
488
|
+
};
|
|
489
|
+
// Query for righte type
|
|
490
|
+
this.log.debug('The following values are detected at input of custom send state');
|
|
491
|
+
for (const element of Object.values(StateElements)) {
|
|
492
|
+
this.log.debug(typeof element);
|
|
493
|
+
this.log.debug(element);
|
|
494
|
+
}
|
|
495
|
+
// Write into nextSend
|
|
496
|
+
await this.writeNextSend(changeInfo, StateElements.PayloadInHex);
|
|
497
|
+
if (
|
|
498
|
+
!changeInfo?.bestMatchForDeviceType ||
|
|
499
|
+
this.downlinkConfighandler?.activeDownlinkConfigs[
|
|
500
|
+
changeInfo.bestMatchForDeviceType
|
|
501
|
+
].sendWithUplink === 'disabled'
|
|
502
|
+
) {
|
|
503
|
+
const downlink = this.downlinkConfighandler?.getDownlink(
|
|
504
|
+
{
|
|
505
|
+
port: StateElements.Port,
|
|
506
|
+
confirmed: StateElements.Confirmed,
|
|
507
|
+
priority: StateElements.Priority,
|
|
508
|
+
},
|
|
509
|
+
StateElements.PayloadInHex,
|
|
510
|
+
changeInfo,
|
|
511
|
+
);
|
|
512
|
+
if (downlink !== undefined) {
|
|
513
|
+
await this.sendDownlink(
|
|
514
|
+
downlinkTopic,
|
|
515
|
+
JSON.stringify(downlink),
|
|
516
|
+
changeInfo,
|
|
517
|
+
);
|
|
518
|
+
}
|
|
509
519
|
}
|
|
510
520
|
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
const payloadInHex = this.downlinkConfighandler?.calculatePayloadInHex(
|
|
519
|
-
downlinkParameter,
|
|
520
|
-
state,
|
|
521
|
+
await this.bridge?.publishId(id, state.val, {});
|
|
522
|
+
await this.setState(id, state.val, true);
|
|
523
|
+
} else {
|
|
524
|
+
const downlinkTopic = this.downlinkConfighandler?.getDownlinkTopic(changeInfo, suffix);
|
|
525
|
+
const downlinkParameter = this.downlinkConfighandler?.getDownlinkParameter(
|
|
526
|
+
changeInfo,
|
|
527
|
+
{},
|
|
521
528
|
);
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
!changeInfo?.bestMatchForDeviceType ||
|
|
525
|
-
this.downlinkConfighandler?.activeDownlinkConfigs[changeInfo.bestMatchForDeviceType]
|
|
526
|
-
.sendWithUplink === 'disabled'
|
|
527
|
-
) {
|
|
528
|
-
const downlink = this.downlinkConfighandler?.getDownlink(
|
|
529
|
+
if (downlinkParameter !== undefined) {
|
|
530
|
+
const payloadInHex = this.downlinkConfighandler?.calculatePayloadInHex(
|
|
529
531
|
downlinkParameter,
|
|
530
|
-
|
|
531
|
-
changeInfo,
|
|
532
|
+
state,
|
|
532
533
|
);
|
|
533
|
-
|
|
534
|
-
|
|
534
|
+
await this.writeNextSend(changeInfo, payloadInHex);
|
|
535
|
+
if (
|
|
536
|
+
!changeInfo?.bestMatchForDeviceType ||
|
|
537
|
+
this.downlinkConfighandler?.activeDownlinkConfigs[
|
|
538
|
+
changeInfo.bestMatchForDeviceType
|
|
539
|
+
].sendWithUplink === 'disabled'
|
|
540
|
+
) {
|
|
541
|
+
const downlink = this.downlinkConfighandler?.getDownlink(
|
|
542
|
+
downlinkParameter,
|
|
543
|
+
payloadInHex,
|
|
544
|
+
changeInfo,
|
|
545
|
+
);
|
|
546
|
+
if (downlink !== undefined) {
|
|
547
|
+
await this.sendDownlink(
|
|
548
|
+
downlinkTopic,
|
|
549
|
+
JSON.stringify(downlink),
|
|
550
|
+
changeInfo,
|
|
551
|
+
);
|
|
552
|
+
}
|
|
535
553
|
}
|
|
554
|
+
await this.bridge?.publishId(id, state.val, {});
|
|
555
|
+
await this.setState(id, state.val, true);
|
|
536
556
|
}
|
|
537
|
-
await this.bridge?.publishId(this.removeNamespace(id), state.val, {});
|
|
538
|
-
await this.setState(id, state.val, true);
|
|
539
557
|
}
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
this.messagehandler?.fillWithDownlinkConfig(changeInfo?.objectStartDirectory, {});
|
|
558
|
+
} else if (id.indexOf('.configuration.') !== -1) {
|
|
559
|
+
// State is from configuration path
|
|
560
|
+
const changeInfo = await this.getChangeInfo(id, { withBestMatch: true });
|
|
561
|
+
this.messagehandler?.fillWithDownlinkConfig(changeInfo?.objectStartDirectory, {});
|
|
545
562
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
563
|
+
// remove not configed states
|
|
564
|
+
const adapterObjects = await this.getAdapterObjectsAsync();
|
|
565
|
+
for (const adapterObject of Object.values(adapterObjects)) {
|
|
566
|
+
if (
|
|
567
|
+
adapterObject.type === 'state' &&
|
|
568
|
+
adapterObject._id.indexOf(
|
|
569
|
+
`${changeInfo?.objectStartDirectory}.downlink.control`,
|
|
570
|
+
) !== -1
|
|
571
|
+
) {
|
|
572
|
+
const changeInfo = await this.getChangeInfo(adapterObject._id);
|
|
573
|
+
const downlinkParameter = this.downlinkConfighandler?.getDownlinkParameter(
|
|
574
|
+
changeInfo,
|
|
575
|
+
{
|
|
576
|
+
startupCheck: true,
|
|
577
|
+
},
|
|
578
|
+
);
|
|
579
|
+
if (!downlinkParameter) {
|
|
580
|
+
await this.delObjectAsync(this.removeNamespace(adapterObject._id));
|
|
581
|
+
}
|
|
559
582
|
}
|
|
560
583
|
}
|
|
584
|
+
await this.setState(id, state.val, true);
|
|
585
|
+
}
|
|
586
|
+
} else {
|
|
587
|
+
// Query for 0_userdata or alias => states also publish with ack = false
|
|
588
|
+
if (id.startsWith('0_userdata') || id.startsWith('alias')) {
|
|
589
|
+
await this.bridge?.publishId(id, state.val, {});
|
|
561
590
|
}
|
|
562
|
-
|
|
591
|
+
}
|
|
592
|
+
} else {
|
|
593
|
+
// Query for Namespace => Just publish foreign States with ack = true
|
|
594
|
+
if (!id.startsWith(this.namespace)) {
|
|
595
|
+
await this.bridge?.publishId(id, state.val, {});
|
|
563
596
|
}
|
|
564
597
|
}
|
|
565
598
|
} else {
|