iobroker.lorawan 1.13.3 → 1.13.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -23,6 +23,15 @@ 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.13.5 (2025-09-06)
27
+ * (BenAhrdt) Show discovery topic(s) & messag(es) ind array
28
+ * (BenAhrdt) Add Tab to see Discovered, Published and Subscribed Ids.
29
+ * (BenAhrdt) Add Posibility to discover climate Entity
30
+ * (BenAhrdt) Retaining Discovery
31
+
32
+ ### 1.13.4 (2025-09-04)
33
+ * (BenAhrdt) Bugfixing crc in Vicki Profile => ChildLock
34
+
26
35
  ### 1.13.3 (2025-09-04)
27
36
  * (BenAhrdt) Add images to the new States
28
37
 
@@ -117,7 +117,7 @@
117
117
  "_NoLoRaWAN": "Der State ist nicht in der richtigen Lorawan - Instanz",
118
118
  "publishTooltip": "Veröffentlichen Sie den State zur der Bridge",
119
119
  "subscribeTooltip": "Abonnieren Sie den State von der Bridge",
120
- "BridgeStateHeader": "Definieren Sie ZustäStates für das HA Discovery",
120
+ "BridgeStateHeader": "Definieren Sie Zustände für das HA Discovery",
121
121
  "BridgeStateInformation": "Hier können Sie ein Array von States definieren, die ein Topic für Discovery festlegen. (Wildcards sind auch möglich)",
122
122
  "Application": "Anwendung",
123
123
  "Device": "Gerät",
@@ -126,7 +126,15 @@
126
126
  "BridgeType": "Bridge Typ",
127
127
  "BridgeTypeTooltip": "Wählen Sie den Typ des Fremdsystems aus",
128
128
  "BridgeTypeOff": "aus",
129
- "BridgeTypeHA": "Voldemort",
129
+ "BridgeTypeHA": "Home Assistant",
130
130
  "RefreshDiscoveryCronJob": "Discovery Zyklus",
131
- "RefreshDiscoveryCronJobTooltip": "Stellen Sie den Cronjob für das Discovery ein"
131
+ "RefreshDiscoveryCronJobTooltip": "Stellen Sie den Cronjob für das Discovery ein",
132
+ "ClimateHeader": "Definieren Sie Zustände für eine Klima ENtität",
133
+ "ClimateInformation": "Hier können Sie ein Array von Klimaentitäten definieren",
134
+ "ClimateTargetTemperatureText": "Solltemperatur",
135
+ "ClimateActTemperatureText": "Isttemperatur",
136
+ "ClimateActModeText": "Mode",
137
+ "_DiscoveredIds": "Discoverd Ids",
138
+ "_PublishedIds": "Published Ids",
139
+ "_SubscribedTopics": "Subscribed Topics"
132
140
  }
@@ -128,5 +128,13 @@
128
128
  "BridgeTypeOff": "off",
129
129
  "BridgeTypeHA": "Home Assistant",
130
130
  "RefreshDiscoveryCronJob": "Discover Cycle",
131
- "RefreshDiscoveryCronJobTooltip": "insert the cronjob for refreshing the discovery"
131
+ "RefreshDiscoveryCronJobTooltip": "insert the cronjob for refreshing the discovery",
132
+ "ClimateHeader": "Define States for Climate Entity",
133
+ "ClimateInformation": "Here you can define an array of Climate definitions",
134
+ "ClimateTargetTemperatureText": "Target Temperature",
135
+ "ClimateActTemperatureText": "Target Temperature",
136
+ "ClimateActModeText": "Target Temperature",
137
+ "_DiscoveredIds": "Discoverd Ids",
138
+ "_PublishedIds": "Published Ids",
139
+ "_SubscribedTopics": "Subscribed Topics"
132
140
  }
@@ -1112,7 +1112,7 @@
1112
1112
  "attr": "subscribe",
1113
1113
  "label": "subscribe",
1114
1114
  "hidden": "data.Folder !== 'downlink.control'",
1115
- "default": false,
1115
+ "default": true,
1116
1116
  "width": "5%"
1117
1117
  },
1118
1118
  {
@@ -1123,6 +1123,273 @@
1123
1123
  "width": "5%"
1124
1124
  }
1125
1125
  ]
1126
+ },
1127
+ "_ClimateHeader":{
1128
+ "newLine": true,
1129
+ "hidden": "data.BridgeType === 'off'",
1130
+ "type": "header",
1131
+ "text": "ClimateHeader",
1132
+ "size": 3,
1133
+ "xs": 12,
1134
+ "sm": 12,
1135
+ "md": 12,
1136
+ "lg": 12,
1137
+ "xl": 12
1138
+ },
1139
+ "_ClimateInformation":{
1140
+ "newLine":true,
1141
+ "hidden": "data.BridgeType === 'off'",
1142
+ "type": "staticText",
1143
+ "label": "ClimateInformation",
1144
+ "xs": 12,
1145
+ "sm": 12,
1146
+ "md": 12,
1147
+ "lg": 12,
1148
+ "xl": 12
1149
+ },
1150
+ "ClimateConfig":{
1151
+ "newLine": true,
1152
+ "hidden": "data.BridgeType === 'off'",
1153
+ "type":"accordion",
1154
+ "titleAttr": "ClimateName",
1155
+ "clone": true,
1156
+ "xs": 12,
1157
+ "sm": 12,
1158
+ "md": 12,
1159
+ "lg": 12,
1160
+ "xl": 12,
1161
+ "items":[
1162
+ {
1163
+ "type": "text",
1164
+ "attr": "ClimateName",
1165
+ "label": "ClimateNameText",
1166
+ "xs": 12,
1167
+ "sm": 4,
1168
+ "md": 4,
1169
+ "lg": 4,
1170
+ "xl": 4
1171
+ },
1172
+ {
1173
+ "newLine": true,
1174
+ "type": "staticText",
1175
+ "attr": "_statciTextTarget",
1176
+ "label": "ClimateTargetTemperatureText",
1177
+ "xs": 12,
1178
+ "sm": 12,
1179
+ "md": 12,
1180
+ "lg": 12,
1181
+ "xl": 12
1182
+ },
1183
+ {
1184
+ "newLine": true,
1185
+ "type": "selectSendTo",
1186
+ "attr": "TargetApplication",
1187
+ "label": "Application",
1188
+ "default": "No Application selected",
1189
+ "jsonData": "{}",
1190
+ "command": "getApplicationsForClimateConfig",
1191
+ "xs": 12,
1192
+ "sm": 3,
1193
+ "md": 3,
1194
+ "lg": 3,
1195
+ "xl": 3
1196
+ },
1197
+ {
1198
+ "type": "selectSendTo",
1199
+ "attr": "TargetDevice",
1200
+ "label": "Device",
1201
+ "default": "No Device selected",
1202
+ "jsonData": "{\"application\":\"${data.TargetApplication}\"}",
1203
+ "command": "getDevicesForClimateConfig",
1204
+ "alsoDependsOn":[
1205
+ "TargetApplication"
1206
+ ],
1207
+ "xs": 12,
1208
+ "sm": 3,
1209
+ "md": 3,
1210
+ "lg": 3,
1211
+ "xl": 3
1212
+ },
1213
+ {
1214
+ "type": "select",
1215
+ "attr": "TargetFolder",
1216
+ "label": "Folder",
1217
+ "default": "downlink.control",
1218
+ "options": [
1219
+ {"label":"downlink.control","value":"downlink.control"}
1220
+ ],
1221
+ "xs": 12,
1222
+ "sm": 2,
1223
+ "md": 2,
1224
+ "lg": 2,
1225
+ "xl": 2
1226
+ },
1227
+ {
1228
+ "type": "selectSendTo",
1229
+ "attr": "TargetState",
1230
+ "label": "State",
1231
+ "default": "No State selected",
1232
+ "jsonData": "{\"application\":\"${data.TargetApplication}\",\"device\":\"${data.TargetDevice}\",\"folder\":\"${data.TargetFolder}\"}",
1233
+ "command": "getStatesForClimateConfig",
1234
+ "alsoDependsOn":[
1235
+ "TargetApplication",
1236
+ "TargetDevice",
1237
+ "TargetFolder"
1238
+ ],
1239
+ "xs": 12,
1240
+ "sm": 4,
1241
+ "md": 4,
1242
+ "lg": 4,
1243
+ "xl": 4
1244
+ },
1245
+ {
1246
+ "type": "staticText",
1247
+ "attr": "_statciTextAct",
1248
+ "label": "ClimateActTemperatureText",
1249
+ "xs": 12,
1250
+ "sm": 12,
1251
+ "md": 12,
1252
+ "lg": 12,
1253
+ "xl": 12
1254
+ },
1255
+ {
1256
+ "newLine": true,
1257
+ "type": "selectSendTo",
1258
+ "attr": "ActApplication",
1259
+ "label": "Application",
1260
+ "default": "No Application selected",
1261
+ "jsonData": "{}",
1262
+ "command": "getApplicationsForClimateConfig",
1263
+ "xs": 12,
1264
+ "sm": 3,
1265
+ "md": 3,
1266
+ "lg": 3,
1267
+ "xl": 3
1268
+ },
1269
+ {
1270
+ "type": "selectSendTo",
1271
+ "attr": "ActDevice",
1272
+ "label": "Device",
1273
+ "default": "No Device selected",
1274
+ "jsonData": "{\"application\":\"${data.ActApplication}\"}",
1275
+ "command": "getDevicesForClimateConfig",
1276
+ "alsoDependsOn":[
1277
+ "ActApplication"
1278
+ ],
1279
+ "xs": 12,
1280
+ "sm": 3,
1281
+ "md": 3,
1282
+ "lg": 3,
1283
+ "xl": 3
1284
+ },
1285
+ {
1286
+ "type": "select",
1287
+ "attr": "ActFolder",
1288
+ "label": "Folder",
1289
+ "default": "uplink.decoded",
1290
+ "options": [
1291
+ {"label":"uplink.decoded","value":"uplink.decoded"}
1292
+ ],
1293
+ "xs": 12,
1294
+ "sm": 2,
1295
+ "md": 2,
1296
+ "lg": 2,
1297
+ "xl": 2
1298
+ },
1299
+ {
1300
+ "type": "selectSendTo",
1301
+ "attr": "ActState",
1302
+ "label": "State",
1303
+ "default": "No State selected",
1304
+ "jsonData": "{\"application\":\"${data.ActApplication}\",\"device\":\"${data.ActDevice}\",\"folder\":\"${data.ActFolder}\"}",
1305
+ "command": "getStatesForClimateConfig",
1306
+ "alsoDependsOn":[
1307
+ "ActApplication",
1308
+ "ActDevice",
1309
+ "ActFolder"
1310
+ ],
1311
+ "xs": 12,
1312
+ "sm": 4,
1313
+ "md": 4,
1314
+ "lg": 4,
1315
+ "xl": 4
1316
+ },
1317
+ {
1318
+ "type": "staticText",
1319
+ "attr": "_statciTextMode",
1320
+ "label": "ClimateModeTemperatureText",
1321
+ "xs": 12,
1322
+ "sm": 12,
1323
+ "md": 12,
1324
+ "lg": 12,
1325
+ "xl": 12
1326
+ },
1327
+ {
1328
+ "newLine": true,
1329
+ "type": "selectSendTo",
1330
+ "attr": "ModeApplication",
1331
+ "label": "Application",
1332
+ "default": "NotPresent",
1333
+ "jsonData": "{}",
1334
+ "command": "getApplicationsForClimateModeConfig",
1335
+ "xs": 12,
1336
+ "sm": 3,
1337
+ "md": 3,
1338
+ "lg": 3,
1339
+ "xl": 3
1340
+ },
1341
+ {
1342
+ "type": "selectSendTo",
1343
+ "attr": "ModeDevice",
1344
+ "label": "Device",
1345
+ "default": "*",
1346
+ "jsonData": "{\"application\":\"${data.ModeApplication}\"}",
1347
+ "command": "getDevicesForClimateConfig",
1348
+ "hidden": "data.ModeApplication === 'NotPresent'",
1349
+ "alsoDependsOn":[
1350
+ "ModeApplication"
1351
+ ],
1352
+ "xs": 12,
1353
+ "sm": 3,
1354
+ "md": 3,
1355
+ "lg": 3,
1356
+ "xl": 3
1357
+ },
1358
+ {
1359
+ "type": "select",
1360
+ "attr": "ModeFolder",
1361
+ "label": "Folder",
1362
+ "default": "uplink.decoded",
1363
+ "options": [
1364
+ {"label":"uplink.decoded","value":"uplink.decoded"}
1365
+ ],
1366
+ "hidden": "data.ModeApplication === 'NotPresent'",
1367
+ "xs": 12,
1368
+ "sm": 2,
1369
+ "md": 2,
1370
+ "lg": 2,
1371
+ "xl": 2
1372
+ },
1373
+ {
1374
+ "type": "selectSendTo",
1375
+ "attr": "ModeState",
1376
+ "label": "State",
1377
+ "default": "No State selected",
1378
+ "jsonData": "{\"application\":\"${data.ModeApplication}\",\"device\":\"${data.ActDevice}\",\"folder\":\"${data.ActFolder}\"}",
1379
+ "command": "getStatesForClimateConfig",
1380
+ "alsoDependsOn":[
1381
+ "ModeApplication",
1382
+ "ModeDevice",
1383
+ "ModeFolder"
1384
+ ],
1385
+ "hidden": "data.ModeApplication === 'NotPresent'",
1386
+ "xs": 12,
1387
+ "sm": 4,
1388
+ "md": 4,
1389
+ "lg": 4,
1390
+ "xl": 4
1391
+ }
1392
+ ]
1126
1393
  }
1127
1394
  }
1128
1395
  }
@@ -0,0 +1,69 @@
1
+ {
2
+ "i18n": true,
3
+ "type": "tabs",
4
+ "tabsStyle": {
5
+ "width": "calc(100% - 100px)"
6
+ },
7
+ "items":{
8
+ "_DiscoveredIds":{
9
+ "type": "panel",
10
+ "label": "_DiscoveredIds",
11
+ "items": {
12
+ "_DiscoveredIds":{
13
+ "type": "text",
14
+ "label": "_DiscoveredIds",
15
+ "defaultSendTo": "getDiscoveredIds",
16
+ "minRows": 10,
17
+ "readOnly": true,
18
+ "trim": false,
19
+ "noClearButton": true,
20
+ "xs": 12,
21
+ "sm": 12,
22
+ "md": 12,
23
+ "lg": 12,
24
+ "xl": 12
25
+ }
26
+ }
27
+ },
28
+ "_PublishedIds":{
29
+ "type": "panel",
30
+ "label": "_PublishedIds",
31
+ "items": {
32
+ "_PublishedIds":{
33
+ "type": "text",
34
+ "label": "_PublishedIds",
35
+ "defaultSendTo": "getPublishedIds",
36
+ "minRows": 10,
37
+ "readOnly": true,
38
+ "trim": false,
39
+ "noClearButton": true,
40
+ "xs": 12,
41
+ "sm": 12,
42
+ "md": 12,
43
+ "lg": 12,
44
+ "xl": 12
45
+ }
46
+ }
47
+ },
48
+ "_SubscribedTopics":{
49
+ "type": "panel",
50
+ "label": "_SubscribedTopics",
51
+ "items": {
52
+ "_SubscribedTopics":{
53
+ "type": "text",
54
+ "label": "_SubscribedTopics",
55
+ "defaultSendTo": "getSubscribedTopics",
56
+ "minRows": 10,
57
+ "readOnly": true,
58
+ "trim": false,
59
+ "noClearButton": true,
60
+ "xs": 12,
61
+ "sm": 12,
62
+ "md": 12,
63
+ "lg": 12,
64
+ "xl": 12
65
+ }
66
+ }
67
+ }
68
+ }
69
+ }
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "lorawan",
4
- "version": "1.13.3",
4
+ "version": "1.13.5",
5
5
  "news": {
6
+ "1.13.5": {
7
+ "en": "Show discovery topic(s) & messag(es) ind array\nAdd Tab to see Discovered, Published and Subscribed Ids.\nAdd Posibility to discover climate Entity\nRetaining Discovery",
8
+ "de": "Zeige Entdeckungsthemen & Messag(en) ind array\nFügen Sie Tab hinzu, um entdeckte, veröffentlichte und abgemeldete Ids zu sehen.\nMöglichkeit, das Klima zu entdecken\nRetaining Discovery",
9
+ "ru": "Показать тему(ы) обнаружения и мессенджер(ы) ind array\nДобавьте вкладку, чтобы увидеть обнаруженные, опубликованные и подписанные идентификаторы.\nДобавить возможность открыть климатическую организацию\nСохранение Discovery",
10
+ "pt": "Mostrar o( s) tópico( s) de descoberta & messag( es) ind array\nAdicionar aba para ver IDs descobertos, publicados e assinados.\nAdicionar Possibilidade de descobrir o clima Entidade\nManter a Descoberta",
11
+ "nl": "Ontdekkingsonderwerp(s) & messag(es) ind-array tonen\nTabblad toevoegen om Ontdekt, Gepubliceerd en Geabonneerd Ids te zien.\nMogelijkheid toevoegen om klimaat te ontdekken Entity\nOntdekking behouden",
12
+ "fr": "Afficher le(s) sujet(s) de découverte et le(s) tableau(s) ind\nAjouter un onglet pour voir les idées découvertes, publiées et enregistrées.\nAjouter la possibilité de découvrir le climat Entité\nConserver la découverte",
13
+ "it": "Mostra argomento(i) & messag(es) ind array\nAggiungi scheda per vedere Scoperto, Pubblicato e Abbonato Ids.\nAggiungi Posibilità per scoprire il clima\nRecuperare Discovery",
14
+ "es": "Mostrar el tema de descubrimiento(s) & messag(es) end array\nAñadir Tab para ver Ids descubiertos, publicados y suscritos.\nAñadir Posibilidad de descubrir la Entidad climática\nRetaining Discovery",
15
+ "pl": "Pokaż temat (y) & messag (y) ind array\nDodaj kartę, aby zobaczyć odkryte, opublikowane i subskrybowane identyfikatory.\nDodaj możliwość odkrywania podmiotu klimatu\nZachowanie Odkrycia",
16
+ "uk": "Показати тему відкриття (s) & mesag(es) ind array\nДодати вкладку, щоб побачити Discovered, Опубліковано та підписувати Ids.\nДодати можливість відкрити клімат\nПідтримка Discovery",
17
+ "zh-cn": "显示发现主题 & messag( es) ind 数组\n添加 Tab 以查看发现、 发布和订阅的 Ids .\n添加发现气候实体的可能性\n保留发现"
18
+ },
19
+ "1.13.4": {
20
+ "en": "Bugfixing crc in Vicki Profile => ChildLock",
21
+ "de": "Bugfixing crc in Vicki Profil => ChildLock",
22
+ "ru": "Bugfixing crc в профиле Вики => ChildLock",
23
+ "pt": "Bugfixing crc in Vicki Profile => ChildLock",
24
+ "nl": "Bugfixing crc in Vicki-profiel => ChildLock",
25
+ "fr": "Correction de bugs dans le profil Vicki => ChildLock",
26
+ "it": "Bugfixing crc in Vicki Profilo => ChildLock",
27
+ "es": "Crc de Bugfixing en Vicki Perfil = 75%Lock",
28
+ "pl": "Bugfining crc w profilu Vicki = > ChildLock",
29
+ "uk": "Виправлення кришки в Vicki Profile => Дитячий замок",
30
+ "zh-cn": "Vicki 配置中的错误修复 crc QQ ChildLock"
31
+ },
6
32
  "1.13.3": {
7
33
  "en": "Add images to the new States",
8
34
  "de": "Bild hinzugefügt für die neuen Staaten",
@@ -67,32 +93,6 @@
67
93
  "pl": "usunąć Błąd z obsługą folderu / stanu",
68
94
  "uk": "видалення Помилки з папкою / державною обробкою",
69
95
  "zh-cn": "删除 有文件夹/ 状态处理的错误"
70
- },
71
- "1.12.0": {
72
- "en": "Custom Table for Config HA Bridge",
73
- "de": "Benutzerdefinierte Tisch für Config HA Bridge",
74
- "ru": "Настольный стол для моста Config HA",
75
- "pt": "Mesa personalizada para configuração HA Bridge",
76
- "nl": "Aangepaste tabel voor Config HA Bridge",
77
- "fr": "Table personnalisée pour Config HA Bridge",
78
- "it": "Tabella personalizzata per Config HA Bridge",
79
- "es": "Tabla personalizada para el puente Config HA",
80
- "pl": "Niestandardowa tabela dla Config HA Bridge",
81
- "uk": "Спеціальна таблиця для Config HA Bridge",
82
- "zh-cn": "配置 HA 桥的自定义表格"
83
- },
84
- "1.11.10": {
85
- "en": "insert logging to object change",
86
- "de": "einfügen von protokollierung zur objektänderung",
87
- "ru": "вставить журналирование для изменения объекта",
88
- "pt": "inserir o registro à mudança de objeto",
89
- "nl": "loggen toevoegen aan objectverandering",
90
- "fr": "insérer l'enregistrement dans le changement d'objet",
91
- "it": "inserire logging per cambiare oggetto",
92
- "es": "insertar logging to object change",
93
- "pl": "wpisz logowanie do zmiany obiektu",
94
- "uk": "вставити заголовок до зміни об'єкта",
95
- "zh-cn": "插入日志到对象更改"
96
96
  }
97
97
  },
98
98
  "titleLang": {
@@ -146,7 +146,16 @@
146
146
  "dataSource": "push",
147
147
  "blockly": true,
148
148
  "adminUI": {
149
- "config": "json"
149
+ "config": "json",
150
+ "tab": "json"
151
+ },
152
+ "adminTab": {
153
+ "link": "jsonTab.json",
154
+ "singleton": false,
155
+ "name": {
156
+ "en": "LoRaWAN",
157
+ "de": "LoRaWAN"
158
+ }
150
159
  },
151
160
  "dependencies": [
152
161
  {
@@ -376,7 +385,8 @@
376
385
  "subscribe": false,
377
386
  "exclude": false
378
387
  }
379
- ]
388
+ ],
389
+ "ClimateConfig": []
380
390
  },
381
391
  "objects": [],
382
392
  "instanceObjects": [
@@ -1,6 +1,8 @@
1
1
  const bridgeMqttClientClass = require('./bridgeMqttclient');
2
2
  const schedule = require('node-schedule');
3
-
3
+ /*
4
+ Also er published irgendwie nicht den Mode => und es kommt virtual_Mode nicht subcribed....
5
+ */
4
6
  /**
5
7
  * this class handles the bridge to foreign system
6
8
  */
@@ -10,7 +12,7 @@ class bridgeClass {
10
12
  */
11
13
  constructor(adapter) {
12
14
  this.adapter = adapter;
13
-
15
+ this.InitDone = false; // Activates work
14
16
  /*********************************************************************
15
17
  * ************** Definition Assigns (externel Module) ***************
16
18
  * ******************************************************************/
@@ -21,12 +23,16 @@ class bridgeClass {
21
23
  this.CheckedIds = {};
22
24
  this.DiscoveredIds = {};
23
25
  this.SubscribedTopics = {};
24
- this.PulishedIds = {};
26
+ this.PublishedIds = {};
27
+ this.VitualIds = {};
25
28
  this.BridgeDiscoveryPrefix = {
26
29
  HA: 'homeassistant/',
27
30
  };
28
31
  this.MinTime = 100; // ms between publish and subscribe same value
29
32
  this.DiscoveryCronjob = {};
33
+ this.EndingVirtualClimate = '.virtual_climate';
34
+ this.EndingVirtualMode = '.virtual_mode';
35
+ this.ClimateEntityType = 'climate';
30
36
  }
31
37
 
32
38
  /*********************************************************************
@@ -42,15 +48,25 @@ class bridgeClass {
42
48
  this.adapter.log.debug(`Function ${activeFunction} started.`);
43
49
  try {
44
50
  if (this.SubscribedTopics[topic]) {
45
- this.SubscribedTopics[topic].val = message;
46
- this.SubscribedTopics[topic].ts = Date.now();
47
51
  if (
48
- !this.PulishedIds[this.SubscribedTopics[topic].id] ||
49
- this.PulishedIds[this.SubscribedTopics[topic].id].val !== message ||
50
- Date.now() - this.PulishedIds[this.SubscribedTopics[topic].id].ts > this.MinTime
52
+ !this.PublishedIds[this.SubscribedTopics[topic].id] ||
53
+ this.PublishedIds[this.SubscribedTopics[topic].id].val !== message ||
54
+ Date.now() - this.PublishedIds[this.SubscribedTopics[topic].id].ts >= this.MinTime
51
55
  ) {
56
+ this.SubscribedTopics[topic].val = message;
57
+ this.SubscribedTopics[topic].ts = Date.now();
58
+ if (this.SubscribedTopics[topic].id.endsWith(this.EndingVirtualMode)) {
59
+ this.adapter.log.debug(
60
+ `The value ${message} is assigned to virtual id: ${this.SubscribedTopics[topic].id}`,
61
+ );
62
+ this.VitualIds[this.SubscribedTopics[topic].id] = message;
63
+ this.adapter.log.warn(`aaa${JSON.stringify(this.VitualIds)}`);
64
+ return;
65
+ }
52
66
  await this.adapter.setState(this.SubscribedTopics[topic].id, message);
53
67
  }
68
+ } else {
69
+ this.adapter.log.debug(`The received Topic ${topic} is not subscribed`);
54
70
  }
55
71
  } catch (error) {
56
72
  this.adapter.log.error(`error at ${activeFunction}: ${error}`);
@@ -66,9 +82,13 @@ class bridgeClass {
66
82
  const activeFunction = 'bridge.js - work';
67
83
  this.adapter.log.debug(`Function ${activeFunction} started.`);
68
84
  try {
85
+ // First remove namespace from id
86
+ id = this.adapter.removeNamespace(id);
69
87
  if (this.bridgeMqttClient.internalConnectionstate) {
70
88
  await this.discovery(id, options);
71
89
  await this.publishId(id, Stateval);
90
+ } else {
91
+ this.adapter.log.debug(`work called with id ${id}, but Bridge is not connected yet.`);
72
92
  }
73
93
  } catch (error) {
74
94
  this.adapter.log.error(`error at ${activeFunction}: ${error}`);
@@ -88,7 +108,11 @@ class bridgeClass {
88
108
  this.adapter.log.debug(`Function ${activeFunction} started.`);
89
109
  try {
90
110
  if (!this.CheckedIds[id] || (options && options.forceDiscovery)) {
111
+ this.CheckedIds[id] = {};
112
+ this.adapter.log.debug(`discover the id ${id}`);
91
113
  await this.buildDiscovery(id, options);
114
+ } else {
115
+ this.adapter.log.debug(`${id} allready checked for discovery`);
92
116
  }
93
117
  } catch (error) {
94
118
  this.adapter.log.error(`error at ${activeFunction}: ${error}`);
@@ -96,7 +120,205 @@ class bridgeClass {
96
120
  }
97
121
 
98
122
  /*********************************************************************
99
- * ********************* Publish zur Bridge **************=***********
123
+ * ********************** Discover Climate ***************************
124
+ * ******************************************************************/
125
+
126
+ /**
127
+ * Discover Configed Climate Entities
128
+ */
129
+ async discoverClimate() {
130
+ const activeFunction = 'discoverClimate';
131
+ this.adapter.log.debug(`Function ${activeFunction} started.`);
132
+ try {
133
+ if (this.adapter.config.ClimateConfig) {
134
+ for (const config of this.adapter.config.ClimateConfig) {
135
+ if (!(await this.generateClimateIds(config))) {
136
+ continue;
137
+ }
138
+ // All Ids ok
139
+ // Target
140
+ const target = {};
141
+ target.changeInfo = await this.adapter.getChangeInfo(config.climateIds.target);
142
+ target.DeviceIdentifier = this.getDeviceIdentifier(
143
+ target.changeInfo,
144
+ this.adapter.config.DeviceIdentifiers,
145
+ );
146
+ target.ReplacedDeviceIdentifier = await this.replaceGermanSpecific(target.DeviceIdentifier);
147
+ target.ReplacedWithoutSpace = await this.replaceSpace(target.ReplacedDeviceIdentifier);
148
+ target.ReplaceWithoutSlash = await this.replaceSlash(target.ReplacedWithoutSpace);
149
+ target.Topic = `${this.bridgeMqttClient.BridgePrefix}${target.ReplacedDeviceIdentifier}/${target.changeInfo.changedState}`;
150
+
151
+ //Min und Max holen
152
+ const targetObject = await this.adapter.getObjectAsync(config.climateIds.target);
153
+ if (targetObject.common.min) {
154
+ target.min = targetObject.common.min;
155
+ }
156
+ if (targetObject.common.max) {
157
+ target.max = targetObject.common.max;
158
+ }
159
+
160
+ // Act
161
+ const act = {};
162
+ act.changeInfo = await this.adapter.getChangeInfo(config.climateIds.act);
163
+ act.DeviceIdentifier = this.getDeviceIdentifier(
164
+ act.changeInfo,
165
+ this.adapter.config.DeviceIdentifiers,
166
+ );
167
+ act.ReplacedDeviceIdentifier = await this.replaceGermanSpecific(act.DeviceIdentifier);
168
+ act.ReplacedWithoutSpace = await this.replaceSpace(act.ReplacedDeviceIdentifier);
169
+ act.ReplaceWithoutSlash = await this.replaceSlash(act.ReplacedWithoutSpace);
170
+ act.Topic = `${this.bridgeMqttClient.BridgePrefix}${act.ReplacedDeviceIdentifier}/${act.changeInfo.changedState}`;
171
+
172
+ // Mode
173
+ const mode = {};
174
+ mode.changeInfo = await this.adapter.getChangeInfo(config.climateIds.mode);
175
+ mode.DeviceIdentifier = this.getDeviceIdentifier(
176
+ mode.changeInfo,
177
+ this.adapter.config.DeviceIdentifiers,
178
+ );
179
+ mode.ReplacedDeviceIdentifier = await this.replaceGermanSpecific(mode.DeviceIdentifier);
180
+ mode.ReplacedWithoutSpace = await this.replaceSpace(mode.ReplacedDeviceIdentifier);
181
+ mode.ReplaceWithoutSlash = await this.replaceSlash(mode.ReplacedWithoutSpace);
182
+ mode.Topic = `${this.bridgeMqttClient.BridgePrefix}${mode.ReplacedDeviceIdentifier}/${mode.changeInfo.changedState}`;
183
+
184
+ const indexLastSlashTarget = target.Topic.lastIndexOf('/');
185
+ const Topic = target.Topic.substring(0, indexLastSlashTarget) + this.EndingVirtualClimate;
186
+ const DiscoveryTopic = `${this.BridgeDiscoveryPrefix[this.adapter.config.BridgeType]}${this.ClimateEntityType}/${target.ReplaceWithoutSlash}/${config.ClimateName}/config`;
187
+ const indexLastDotTarget = config.climateIds.target.lastIndexOf('.');
188
+ const Id = config.climateIds.target.substring(0, indexLastDotTarget) + this.EndingVirtualClimate;
189
+ const DiscoveryPayload = {
190
+ name: config.ClimateName,
191
+ unique_id: `${target.ReplaceWithoutSlash}_${config.ClimateName}`.toLowerCase(),
192
+ device: {
193
+ identifiers: [target.ReplaceWithoutSlash.toLowerCase()],
194
+ name: target.DeviceIdentifier,
195
+ },
196
+ mode_state_topic: mode.Topic,
197
+ mode_command_topic: mode.Topic,
198
+ temperature_state_topic: target.Topic,
199
+ temperature_command_topic: target.Topic,
200
+ current_temperature_topic: act.Topic,
201
+ min_temp: target.min ? target.min : 0,
202
+ max_temp: target.max ? target.max : 40,
203
+ modes: ['auto', 'heat', 'off'],
204
+ precision: 0.5,
205
+ temp_step: 0.5,
206
+ };
207
+
208
+ // Assign Subscribed Topics
209
+ this.SubscribedTopics[target.Topic] = {};
210
+ this.SubscribedTopics[target.Topic].id = config.climateIds.target;
211
+ this.SubscribedTopics[target.Topic].val = await this.adapter.getState(config.climateIds.target).val;
212
+ this.SubscribedTopics[target.Topic].ts = Date.now() - this.MinTime;
213
+
214
+ this.SubscribedTopics[mode.Topic] = {};
215
+ this.SubscribedTopics[mode.Topic].id = config.climateIds.mode;
216
+ if (config.climateIds.mode.endsWith(this.EndingVirtualMode)) {
217
+ this.SubscribedTopics[mode.Topic].val = 'auto';
218
+ this.VitualIds[config.climateIds.mode] = this.SubscribedTopics[mode.Topic].val;
219
+ } else {
220
+ this.SubscribedTopics[mode.Topic].val = await this.adapter.getState(config.climateIds.mode).val;
221
+ }
222
+ this.SubscribedTopics[mode.Topic].ts = Date.now() - this.MinTime;
223
+
224
+ const DiscoveryObject = {
225
+ Topic: Topic,
226
+ topic: DiscoveryTopic,
227
+ payload: structuredClone(DiscoveryPayload),
228
+ };
229
+
230
+ // Assign published Topics
231
+ // Target
232
+ if (!this.PublishedIds[config.climateIds.target]) {
233
+ this.PublishedIds[config.climateIds.target] = { discovery: [] };
234
+ }
235
+ this.PublishedIds[config.climateIds.target].Topic = target.Topic;
236
+ this.PublishedIds[config.climateIds.target].discovery.push({
237
+ topic: DiscoveryTopic,
238
+ payload: structuredClone(DiscoveryPayload),
239
+ });
240
+ this.PublishedIds[config.climateIds.target].val = 0;
241
+ this.PublishedIds[config.climateIds.target].ts = Date.now();
242
+
243
+ // Act
244
+ if (!this.PublishedIds[config.climateIds.act]) {
245
+ this.PublishedIds[config.climateIds.act] = { discovery: [] };
246
+ }
247
+ this.PublishedIds[config.climateIds.act].Topic = act.Topic;
248
+ this.PublishedIds[config.climateIds.act].discovery.push({
249
+ topic: DiscoveryTopic,
250
+ payload: structuredClone(DiscoveryPayload),
251
+ });
252
+ this.PublishedIds[config.climateIds.act].val = 0;
253
+ this.PublishedIds[config.climateIds.act].ts = Date.now();
254
+
255
+ // Mode
256
+ if (!this.PublishedIds[config.climateIds.mode]) {
257
+ this.PublishedIds[config.climateIds.mode] = { discovery: [] };
258
+ }
259
+ this.PublishedIds[config.climateIds.mode].Topic = mode.Topic;
260
+ this.PublishedIds[config.climateIds.mode].discovery.push({
261
+ topic: DiscoveryTopic,
262
+ payload: structuredClone(DiscoveryPayload),
263
+ });
264
+ this.PublishedIds[config.climateIds.mode].val = 0;
265
+ this.PublishedIds[config.climateIds.mode].ts = Date.now();
266
+
267
+ // Publishing the discover message
268
+ await this.publishDiscovery(Id, {
269
+ topic: DiscoveryObject?.topic,
270
+ payload: structuredClone(DiscoveryObject.payload),
271
+ });
272
+ await this.publishId(config.climateIds.target, this.SubscribedTopics[target.Topic].val);
273
+ await this.publishId(config.climateIds.act, await this.adapter.getState(config.climateIds.act).val);
274
+ await this.publishId(config.climateIds.mode, this.SubscribedTopics[mode.Topic].val);
275
+ }
276
+ }
277
+ } catch (error) {
278
+ this.adapter.log.error(`error at ${activeFunction}: ${error}`);
279
+ }
280
+ }
281
+
282
+ /*********************************************************************
283
+ * ****************** generate Climate Ids ***************************
284
+ * ******************************************************************/
285
+
286
+ /**
287
+ * @param config Configuration of the climate entity, wich is to genereate
288
+ */
289
+ async generateClimateIds(config) {
290
+ const activeFunction = 'generateClimateIds';
291
+ this.adapter.log.debug(`Function ${activeFunction} started.`);
292
+ try {
293
+ const climateIds = { target: '', act: '', mode: '' };
294
+ climateIds.target = `${config.TargetApplication}.devices.${config.TargetDevice}.${config.TargetFolder}.${config.TargetState}`;
295
+ climateIds.act = `${config.ActApplication}.devices.${config.ActDevice}.${config.ActFolder}.${config.ActState}`;
296
+ if (config.ModeApplication === 'NotPresent') {
297
+ climateIds.mode = `${climateIds.target}${this.EndingVirtualMode}`;
298
+ } else {
299
+ climateIds.mode = `${config.ModeApplication}.devices.${config.ModeDevice}.${config.ModeFolder}.${config.ModeState}`;
300
+ }
301
+ for (const id of Object.values(climateIds)) {
302
+ if (!(await this.adapter.objectExists(id)) && !id.endsWith(this.EndingVirtualMode)) {
303
+ return false;
304
+ }
305
+ }
306
+ if (config.ClimateName === '') {
307
+ return false;
308
+ }
309
+ const indexOfSpace = config.ClimateName.indexOf(' ');
310
+ if (indexOfSpace > 0) {
311
+ config.ClimateName = config.ClimateName.substring(0, indexOfSpace);
312
+ }
313
+ config.climateIds = climateIds;
314
+ return true;
315
+ } catch (error) {
316
+ this.adapter.log.error(`error at ${activeFunction}: ${error}`);
317
+ }
318
+ }
319
+
320
+ /*********************************************************************
321
+ * ********************* Publish zur Bridge **************************
100
322
  * ******************************************************************/
101
323
 
102
324
  /**
@@ -104,10 +326,10 @@ class bridgeClass {
104
326
  * @param val Value of the used Id
105
327
  */
106
328
  async publishId(id, val) {
107
- const activeFunction = 'bridge.js - publish';
329
+ const activeFunction = 'bridge.js - publishId';
108
330
  this.adapter.log.debug(`Function ${activeFunction} started.`);
109
331
  try {
110
- if (this.PulishedIds[id]) {
332
+ if (this.PublishedIds[id]) {
111
333
  if (val === undefined) {
112
334
  const State = await this.adapter.getState(id);
113
335
  if (State) {
@@ -115,16 +337,21 @@ class bridgeClass {
115
337
  }
116
338
  }
117
339
  if (
118
- !this.SubscribedTopics[this.PulishedIds[id].Topic] ||
119
- this.SubscribedTopics[this.PulishedIds[id].Topic].val !== val ||
120
- Date.now() - this.SubscribedTopics[this.PulishedIds[id].Topic].ts > this.MinTime
340
+ !this.SubscribedTopics[this.PublishedIds[id].Topic] ||
341
+ this.SubscribedTopics[this.PublishedIds[id].Topic].val !== val ||
342
+ Date.now() - this.SubscribedTopics[this.PublishedIds[id].Topic].ts >= this.MinTime
121
343
  ) {
122
- this.PulishedIds[id].ts = Date.now();
123
- this.PulishedIds[id].val = val;
124
- await this.bridgeMqttClient.publish(this.PulishedIds[id].Topic, JSON.stringify(val), {
344
+ this.PublishedIds[id].ts = Date.now();
345
+ this.PublishedIds[id].val = val;
346
+ if (typeof val !== 'string') {
347
+ val = JSON.stringify(val);
348
+ }
349
+ await this.bridgeMqttClient.publish(this.PublishedIds[id].Topic, val, {
125
350
  retain: true,
126
351
  });
127
352
  }
353
+ } else {
354
+ this.adapter.log.debug(`Id not for publish used.`);
128
355
  }
129
356
  } catch (error) {
130
357
  this.adapter.log.error(`error at ${activeFunction}: ${error}`);
@@ -136,7 +363,7 @@ class bridgeClass {
136
363
  * @param options Options for using spezial fuctions
137
364
  */
138
365
  async buildDiscovery(id, options) {
139
- const activeFunction = 'bridge.js - publbuildDiscoveryish';
366
+ const activeFunction = 'bridge.js - buildDiscovery';
140
367
  this.adapter.log.debug(`Function ${activeFunction} started.`);
141
368
  try {
142
369
  // Query for decoded Folder
@@ -170,17 +397,27 @@ class bridgeClass {
170
397
  options.Bridgestate = Bridgestate;
171
398
  const DiscoveryObject = await this.getDiscoveryObject(changeInfo, options);
172
399
  if (Bridgestate.publish) {
173
- this.PulishedIds[id] = DiscoveryObject;
174
- this.PulishedIds[id].val = 0;
175
- this.PulishedIds[id].ts = Date.now();
400
+ if (!this.PublishedIds[id]) {
401
+ this.PublishedIds[id] = { discovery: [] };
402
+ }
403
+ this.PublishedIds[id].Topic = DiscoveryObject?.Topic;
404
+ this.PublishedIds[id].discovery.push({
405
+ topic: DiscoveryObject?.topic,
406
+ payload: structuredClone(DiscoveryObject?.payload),
407
+ });
408
+ this.PublishedIds[id].val = 0;
409
+ this.PublishedIds[id].ts = Date.now();
176
410
  }
177
411
  if (Bridgestate.subscribe) {
178
412
  this.SubscribedTopics[DiscoveryObject?.Topic] = {};
179
413
  this.SubscribedTopics[DiscoveryObject?.Topic].id = id;
180
414
  this.SubscribedTopics[DiscoveryObject?.Topic].val = 0;
181
- this.SubscribedTopics[DiscoveryObject?.Topic].ts = Date.now();
415
+ this.SubscribedTopics[DiscoveryObject?.Topic].ts = Date.now() - this.MinTime;
182
416
  }
183
- await this.publishDiscovery(id, DiscoveryObject);
417
+ await this.publishDiscovery(id, {
418
+ topic: DiscoveryObject?.topic,
419
+ payload: structuredClone(DiscoveryObject?.payload),
420
+ });
184
421
  }
185
422
  }
186
423
 
@@ -218,19 +455,30 @@ class bridgeClass {
218
455
  options.Bridgestate = Bridgestate;
219
456
  const DiscoveryObject = await this.getDiscoveryObject(changeInfo, options);
220
457
  if (Bridgestate.publish) {
221
- this.PulishedIds[id] = DiscoveryObject;
458
+ if (!this.PublishedIds[id]) {
459
+ this.PublishedIds[id] = { discovery: [] };
460
+ }
461
+ this.PublishedIds[id].Topic = DiscoveryObject?.Topic;
462
+ this.PublishedIds[id].discovery.push({
463
+ topic: DiscoveryObject?.topic,
464
+ payload: structuredClone(DiscoveryObject?.payload),
465
+ });
466
+ this.PublishedIds[id].val = 0;
467
+ this.PublishedIds[id].ts = Date.now();
222
468
  }
223
469
  if (Bridgestate.subscribe) {
224
470
  this.SubscribedTopics[DiscoveryObject?.Topic] = {};
225
471
  this.SubscribedTopics[DiscoveryObject?.Topic].id = id;
226
472
  this.SubscribedTopics[DiscoveryObject?.Topic].val = 0;
227
- this.SubscribedTopics[DiscoveryObject?.Topic].ts = Date.now();
473
+ this.SubscribedTopics[DiscoveryObject?.Topic].ts = Date.now() - this.MinTime;
228
474
  }
229
- await this.publishDiscovery(id, DiscoveryObject);
475
+ await this.publishDiscovery(id, {
476
+ topic: DiscoveryObject?.topic,
477
+ payload: structuredClone(DiscoveryObject?.payload),
478
+ });
230
479
  }
231
480
  }
232
481
  }
233
- this.CheckedIds[id] = {};
234
482
  } catch (error) {
235
483
  this.adapter.log.error(`error at ${activeFunction}: ${error}`);
236
484
  }
@@ -275,7 +523,7 @@ class bridgeClass {
275
523
  for (const Attribute in AdditionalAttributes) {
276
524
  DiscoveryPayload[Attribute] = AdditionalAttributes[Attribute];
277
525
  }
278
- return { Topic: Topic, DiscoveryTopic: DiscoveryTopic, DiscoveryPayload: DiscoveryPayload };
526
+ return { Topic: Topic, topic: DiscoveryTopic, payload: DiscoveryPayload };
279
527
  } catch (error) {
280
528
  this.adapter.log.error(`error at ${activeFunction}: ${error}`);
281
529
  }
@@ -294,11 +542,9 @@ class bridgeClass {
294
542
  this.adapter.log.debug(`Function ${activeFunction} started.`);
295
543
  try {
296
544
  this.DiscoveredIds[id] = DiscoveryObject;
297
- await this.bridgeMqttClient.publish(
298
- DiscoveryObject.DiscoveryTopic,
299
- JSON.stringify(DiscoveryObject.DiscoveryPayload),
300
- {},
301
- );
545
+ await this.bridgeMqttClient.publish(DiscoveryObject.topic, JSON.stringify(DiscoveryObject.payload), {
546
+ retain: true,
547
+ });
302
548
  await this.adapter.setState('info.discoveredIds', JSON.stringify(this.DiscoveredIds), true);
303
549
  } catch (error) {
304
550
  this.adapter.log.error(`error at ${activeFunction}: ${error}`);
@@ -617,6 +863,7 @@ class bridgeClass {
617
863
  }
618
864
  }
619
865
  }
866
+ await this.discoverClimate();
620
867
  } catch (error) {
621
868
  this.adapter.log.error(`error at ${activeFunction}: ${error}`);
622
869
  }
@@ -72,10 +72,17 @@ class bridgeMqttClientClass {
72
72
  this.client.on('message', async (topic, message) => {
73
73
  this.adapter.log.debug(`incomming bridge topic: ${topic}`);
74
74
  this.adapter.log.debug(`incomming bridge message: ${message}`);
75
- // @ts-expect-error assignmessage in JSON.parse
76
- message = JSON.parse(message);
77
- //topic = topic.substring(this.BridgePrefix.length, topic.length);
78
- await this.adapter.bridge.handleMessage(topic, message);
75
+
76
+ let payload = message.toString('utf8');
77
+ // Message Parsen => Wenn nicht pasebar, dann string weitergeben
78
+ try {
79
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
80
+ // @ts-expect-error
81
+ payload = JSON.parse(message);
82
+ } catch {
83
+ this.adapter.log.debug(`The Message ${message} is not parsabele. Work with string`);
84
+ }
85
+ await this.adapter.bridge.handleMessage(topic, payload);
79
86
  });
80
87
  }
81
88
  /**
@@ -187,7 +187,7 @@
187
187
  "deviceType": "Vicki",
188
188
  "decimalPlaces": "1",
189
189
  "lengthInByte": 2,
190
- "crc": "off",
190
+ "crc": "noCrc",
191
191
  "swap": false,
192
192
  "limitMax": false,
193
193
  "limitMaxValue": 0,
@@ -480,7 +480,7 @@ class directorieshandlerClass {
480
480
  });
481
481
  // Add Bridged Funktion (MQTT auto discovery)
482
482
  // Add for new state
483
- await this.adapter.bridge.work(objectId, stateVal, { common: common });
483
+ await this.adapter.bridge?.work(objectId, stateVal, { common: common });
484
484
  if (typeof stateVal === 'object') {
485
485
  stateVal = JSON.stringify(stateVal);
486
486
  }
@@ -136,7 +136,9 @@ class messagehandlerClass {
136
136
  const adapterObjectsAtStart = await this.adapter.getAdapterObjectsAsync();
137
137
  for (const adapterObject of Object.values(adapterObjectsAtStart)) {
138
138
  if (adapterObject.type === 'device') {
139
- await this.fillWithDownlinkConfig(this.adapter.removeNamespace(adapterObject._id), {});
139
+ await this.fillWithDownlinkConfig(this.adapter.removeNamespace(adapterObject._id), {
140
+ startup: true,
141
+ });
140
142
  //await this.addDirectoriesToPresentDirectory(`${stateId}`); Not used yet (Maybe for thefuture with more folders)
141
143
  }
142
144
  }
@@ -524,6 +526,11 @@ class messagehandlerClass {
524
526
  if (downlinkDevice !== this.adapter.downlinkConfighandler.internalDevices.baseDevice) {
525
527
  foundLength[downlinkParameter.name] = downlinkDevice.length;
526
528
  }
529
+ // Add Bridged Funktion (MQTT auto discovery) only in Message
530
+ if (!options?.startup) {
531
+ await this.adapter.bridge.work(stateId, undefined, { common: common });
532
+ }
533
+
527
534
  //check for right type of data (after a possible change)
528
535
  if (!options || !options.inMessage) {
529
536
  const state = await this.adapter.getStateAsync(stateId);
package/main.js CHANGED
@@ -77,8 +77,8 @@ class Lorawan extends utils.Adapter {
77
77
  this.subscribeStatesAsync('*');
78
78
  //this.subscribeObjectsAsync('*.uplink.decoded.*');
79
79
  //this.subscribeObjectsAsync('*.downlink.control.*');
80
- this.log.silly(`the adapter starts with downlinkconfigs: ${JSON.stringify(this.config.downlinkConfig)}.`);
81
- this.log.silly(
80
+ this.log.debug(`the adapter starts with downlinkconfigs: ${JSON.stringify(this.config.downlinkConfig)}.`);
81
+ this.log.debug(
82
82
  `the active downlinkconfigs are: ${JSON.stringify(this.downlinkConfighandler.activeDownlinkConfigs)}`,
83
83
  );
84
84
  /*
@@ -409,12 +409,12 @@ class Lorawan extends utils.Adapter {
409
409
  const activeFunction = 'onStateChange';
410
410
  try {
411
411
  if (state) {
412
- //this.log.silly(`state ${id} changed: val: ${state.val} - ack: ${state.ack}`);
412
+ //this.log.debug(`state ${id} changed: val: ${state.val} - ack: ${state.ack}`);
413
413
  // The state was changed => only states with ack = false will be processed, others will be ignored
414
414
  if (!state.ack) {
415
415
  // Check for downlink in id
416
416
  if (id.indexOf('.downlink.control.') !== -1) {
417
- this.log.silly(`the state ${id} has changed to ${state.val}.`);
417
+ this.log.debug(`the state ${id} has changed to ${state.val}.`);
418
418
  // get information of the changing state
419
419
  const changeInfo = await this.getChangeInfo(id, { withBestMatch: true });
420
420
  const suffix = this.downlinkConfighandler?.getDownlinkTopicSuffix(changeInfo?.changedState);
@@ -538,7 +538,7 @@ class Lorawan extends utils.Adapter {
538
538
  async checkSendDownlinkWithUplink(id) {
539
539
  const activeFunction = 'checkSendDownlinkWithUplink';
540
540
  try {
541
- this.log.silly(`Check for send downlink with uplink.`);
541
+ this.log.debug(`Check for send downlink with uplink.`);
542
542
  const changeInfo = await this.getChangeInfo(id, { withBestMatch: true });
543
543
  if (
544
544
  changeInfo &&
@@ -637,7 +637,7 @@ class Lorawan extends utils.Adapter {
637
637
  async getChangeInfo(id, options) {
638
638
  const activeFunction = 'getChangeInfo';
639
639
  try {
640
- this.log.silly(`changeinfo of id ${id}, will be generated.`);
640
+ this.log.debug(`changeinfo of id ${id}, will be generated.`);
641
641
  const changeInfo = this.getBaseDeviceInfo(id);
642
642
  const myId = `${changeInfo?.objectStartDirectory}.${this.messagehandler?.directoryhandler.reachableSubfolders.configuration}.devicetype`;
643
643
  // Check for changeInfo
@@ -672,7 +672,7 @@ class Lorawan extends utils.Adapter {
672
672
  }
673
673
  }
674
674
  }
675
- this.log.silly(`changeinfo is ${JSON.stringify(changeInfo)}.`);
675
+ this.log.debug(`changeinfo is ${JSON.stringify(changeInfo)}.`);
676
676
  return changeInfo;
677
677
  } catch (error) {
678
678
  this.log.error(`error at ${activeFunction}: ${error}`);
@@ -681,7 +681,7 @@ class Lorawan extends utils.Adapter {
681
681
 
682
682
  removeNamespace(id) {
683
683
  if (id.indexOf(this.namespace) !== -1) {
684
- this.log.silly(`namespace will be removed from id ${id}.`);
684
+ this.log.debug(`namespace will be removed from id ${id}.`);
685
685
  id = id.substring(this.namespace.length + 1, id.length);
686
686
  }
687
687
  return id;
@@ -931,10 +931,21 @@ class Lorawan extends utils.Adapter {
931
931
  }
932
932
 
933
933
  // send application to config
934
- } else if (obj.command === 'getApplicationsForConfig') {
934
+ } else if (
935
+ obj.command === 'getApplicationsForConfig' ||
936
+ obj.command === 'getApplicationsForClimateConfig' ||
937
+ obj.command === 'getApplicationsForClimateModeConfig'
938
+ ) {
935
939
  try {
936
- let myCount = 1;
937
- const applications = [{ label: '* (Wildcard)', value: '*' }];
940
+ let myCount = 0;
941
+ const applications = [];
942
+ if (obj.command === 'getApplicationsForConfig') {
943
+ applications[myCount] = { label: '* (Wildcard)', value: '*' };
944
+ myCount++;
945
+ } else if (obj.command === 'getApplicationsForClimateModeConfig') {
946
+ applications[myCount] = { label: '* Not Present (Virtual)', value: 'NotPresent' };
947
+ myCount++;
948
+ }
938
949
  const currentApplications = {};
939
950
  const adapterObjects = await this.getAdapterObjectsAsync();
940
951
  for (const adapterObject of Object.values(adapterObjects)) {
@@ -955,10 +966,14 @@ class Lorawan extends utils.Adapter {
955
966
  } catch (error) {
956
967
  this.log.error(error);
957
968
  }
958
- } else if (obj.command === 'getDevicesForConfig') {
969
+ } else if (obj.command === 'getDevicesForConfig' || obj.command === 'getDevicesForClimateConfig') {
959
970
  try {
960
- let myCount = 1;
961
- const devices = [{ label: '* (Wildcard)', value: '*' }];
971
+ let myCount = 0;
972
+ const devices = [];
973
+ if (obj.command === 'getDevicesForConfig') {
974
+ devices[myCount] = { label: '* (Wildcard)', value: '*' };
975
+ myCount++;
976
+ }
962
977
  const adapterObjects = await this.getAdapterObjectsAsync();
963
978
  for (const adapterObject of Object.values(adapterObjects)) {
964
979
  if (
@@ -991,10 +1006,14 @@ class Lorawan extends utils.Adapter {
991
1006
  } catch (error) {
992
1007
  this.log.error(error);
993
1008
  }
994
- } else if (obj.command === 'getStatesForConfig') {
1009
+ } else if (obj.command === 'getStatesForConfig' || obj.command === 'getStatesForClimateConfig') {
995
1010
  try {
996
- let myCount = 1;
997
- const states = [{ label: '* (Wildcard)', value: '*' }];
1011
+ let myCount = 0;
1012
+ const states = [];
1013
+ if (obj.command === 'getDevicesForConfig') {
1014
+ states[myCount] = { label: '* (Wildcard)', value: '*' };
1015
+ myCount++;
1016
+ }
998
1017
  const currentStates = {};
999
1018
  const adapterObjects = await this.getAdapterObjectsAsync();
1000
1019
  for (const adapterObject of Object.values(adapterObjects)) {
@@ -1035,6 +1054,39 @@ class Lorawan extends utils.Adapter {
1035
1054
  } catch (error) {
1036
1055
  this.log.error(error);
1037
1056
  }
1057
+ } else if (obj.command === 'getDiscoveredIds') {
1058
+ try {
1059
+ this.sendTo(
1060
+ obj.from,
1061
+ obj.command,
1062
+ JSON.stringify(this.bridge?.DiscoveredIds, null, 2),
1063
+ obj.callback,
1064
+ );
1065
+ } catch (error) {
1066
+ this.log.error(error);
1067
+ }
1068
+ } else if (obj.command === 'getPublishedIds') {
1069
+ try {
1070
+ this.sendTo(
1071
+ obj.from,
1072
+ obj.command,
1073
+ JSON.stringify(this.bridge?.PublishedIds, null, 2),
1074
+ obj.callback,
1075
+ );
1076
+ } catch (error) {
1077
+ this.log.error(error);
1078
+ }
1079
+ } else if (obj.command === 'getSubscribedTopics') {
1080
+ try {
1081
+ this.sendTo(
1082
+ obj.from,
1083
+ obj.command,
1084
+ JSON.stringify(this.bridge?.SubscribedTopics, null, 2),
1085
+ obj.callback,
1086
+ );
1087
+ } catch (error) {
1088
+ this.log.error(error);
1089
+ }
1038
1090
  } else {
1039
1091
  const result = { error: true, message: 'No message matched', received: obj.message };
1040
1092
  if (obj.callback) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.lorawan",
3
- "version": "1.13.3",
3
+ "version": "1.13.5",
4
4
  "description": "converts the desired lora gateway data to a ioBroker structure",
5
5
  "author": {
6
6
  "name": "BenAhrdt",