iobroker.lorawan 1.13.4 → 1.13.6
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 +9 -0
- package/admin/i18n/de/translations.json +11 -3
- package/admin/i18n/en/translations.json +9 -1
- package/admin/jsonConfig.json +268 -1
- package/admin/jsonTab.json +69 -0
- package/io-package.json +39 -29
- package/lib/modules/bridge.js +278 -33
- package/lib/modules/directorieshandler.js +1 -1
- package/lib/modules/messagehandler.js +8 -1
- package/main.js +61 -9
- package/package.json +1 -1
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.6 (2025-09-06)
|
|
27
|
+
* (BenAhrdt) Bugfix handling in fillDownlink
|
|
28
|
+
|
|
29
|
+
### 1.13.5 (2025-09-06)
|
|
30
|
+
* (BenAhrdt) Show discovery topic(s) & messag(es) ind array
|
|
31
|
+
* (BenAhrdt) Add Tab to see Discovered, Published and Subscribed Ids.
|
|
32
|
+
* (BenAhrdt) Add Posibility to discover climate Entity
|
|
33
|
+
* (BenAhrdt) Retaining Discovery
|
|
34
|
+
|
|
26
35
|
### 1.13.4 (2025-09-04)
|
|
27
36
|
* (BenAhrdt) Bugfixing crc in Vicki Profile => ChildLock
|
|
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
|
|
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": "
|
|
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
|
}
|
package/admin/jsonConfig.json
CHANGED
|
@@ -1112,7 +1112,7 @@
|
|
|
1112
1112
|
"attr": "subscribe",
|
|
1113
1113
|
"label": "subscribe",
|
|
1114
1114
|
"hidden": "data.Folder !== 'downlink.control'",
|
|
1115
|
-
"default":
|
|
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.
|
|
4
|
+
"version": "1.13.6",
|
|
5
5
|
"news": {
|
|
6
|
+
"1.13.6": {
|
|
7
|
+
"en": "Bugfix handling in fillDownlink",
|
|
8
|
+
"de": "Bugfix Handhabung in fillDownlink",
|
|
9
|
+
"ru": "Обработка Bugfix в fillDownlink",
|
|
10
|
+
"pt": "Tratamento de erros em fillDownlink",
|
|
11
|
+
"nl": "Bugfix-verwerking in fillDownlink",
|
|
12
|
+
"fr": "Gestion du bugfix dans fillDownlink",
|
|
13
|
+
"it": "Gestione bugfix in fillDownlink",
|
|
14
|
+
"es": "Manejo de bugfix en rellenoDownlink",
|
|
15
|
+
"pl": "Obsługa Bugfix w FuelDownlink",
|
|
16
|
+
"uk": "Обробка помилок в накладціДоне посилання",
|
|
17
|
+
"zh-cn": "在 fillDownlink 中处理错误"
|
|
18
|
+
},
|
|
19
|
+
"1.13.5": {
|
|
20
|
+
"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",
|
|
21
|
+
"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",
|
|
22
|
+
"ru": "Показать тему(ы) обнаружения и мессенджер(ы) ind array\nДобавьте вкладку, чтобы увидеть обнаруженные, опубликованные и подписанные идентификаторы.\nДобавить возможность открыть климатическую организацию\nСохранение Discovery",
|
|
23
|
+
"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",
|
|
24
|
+
"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",
|
|
25
|
+
"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",
|
|
26
|
+
"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",
|
|
27
|
+
"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",
|
|
28
|
+
"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",
|
|
29
|
+
"uk": "Показати тему відкриття (s) & mesag(es) ind array\nДодати вкладку, щоб побачити Discovered, Опубліковано та підписувати Ids.\nДодати можливість відкрити клімат\nПідтримка Discovery",
|
|
30
|
+
"zh-cn": "显示发现主题 & messag( es) ind 数组\n添加 Tab 以查看发现、 发布和订阅的 Ids .\n添加发现气候实体的可能性\n保留发现"
|
|
31
|
+
},
|
|
6
32
|
"1.13.4": {
|
|
7
33
|
"en": "Bugfixing crc in Vicki Profile => ChildLock",
|
|
8
34
|
"de": "Bugfixing crc in Vicki Profil => ChildLock",
|
|
@@ -67,32 +93,6 @@
|
|
|
67
93
|
"pl": "Zbuduj pięść wersja własnego klienta Bridge MQTT",
|
|
68
94
|
"uk": "Створення fist версії власного Bridge MQTT Клієнт",
|
|
69
95
|
"zh-cn": "构建自有桥 MQTT 客户端的拳头版本"
|
|
70
|
-
},
|
|
71
|
-
"1.12.1": {
|
|
72
|
-
"en": "remove Bug with folder / state handling",
|
|
73
|
-
"de": "entfernen Bug mit Ordner / State Handling",
|
|
74
|
-
"ru": "удалять Баг с папкой / обработка состояния",
|
|
75
|
-
"pt": "remover Erro com manipulação de pasta / estado",
|
|
76
|
-
"nl": "verwijderen Bug met map / status behandeling",
|
|
77
|
-
"fr": "supprimer Bogue avec gestion de dossier / état",
|
|
78
|
-
"it": "rimuovere Bug con cartella / gestione dello stato",
|
|
79
|
-
"es": "retirar Error con carpeta / manejo del estado",
|
|
80
|
-
"pl": "usunąć Błąd z obsługą folderu / stanu",
|
|
81
|
-
"uk": "видалення Помилки з папкою / державною обробкою",
|
|
82
|
-
"zh-cn": "删除 有文件夹/ 状态处理的错误"
|
|
83
|
-
},
|
|
84
|
-
"1.12.0": {
|
|
85
|
-
"en": "Custom Table for Config HA Bridge",
|
|
86
|
-
"de": "Benutzerdefinierte Tisch für Config HA Bridge",
|
|
87
|
-
"ru": "Настольный стол для моста Config HA",
|
|
88
|
-
"pt": "Mesa personalizada para configuração HA Bridge",
|
|
89
|
-
"nl": "Aangepaste tabel voor Config HA Bridge",
|
|
90
|
-
"fr": "Table personnalisée pour Config HA Bridge",
|
|
91
|
-
"it": "Tabella personalizzata per Config HA Bridge",
|
|
92
|
-
"es": "Tabla personalizada para el puente Config HA",
|
|
93
|
-
"pl": "Niestandardowa tabela dla Config HA Bridge",
|
|
94
|
-
"uk": "Спеціальна таблиця для Config HA Bridge",
|
|
95
|
-
"zh-cn": "配置 HA 桥的自定义表格"
|
|
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": [
|
package/lib/modules/bridge.js
CHANGED
|
@@ -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.
|
|
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,13 +48,21 @@ 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.
|
|
49
|
-
this.
|
|
50
|
-
Date.now() - this.
|
|
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
|
}
|
|
54
68
|
} else {
|
|
@@ -68,9 +82,13 @@ class bridgeClass {
|
|
|
68
82
|
const activeFunction = 'bridge.js - work';
|
|
69
83
|
this.adapter.log.debug(`Function ${activeFunction} started.`);
|
|
70
84
|
try {
|
|
85
|
+
// First remove namespace from id
|
|
86
|
+
id = this.adapter.removeNamespace(id);
|
|
71
87
|
if (this.bridgeMqttClient.internalConnectionstate) {
|
|
72
88
|
await this.discovery(id, options);
|
|
73
89
|
await this.publishId(id, Stateval);
|
|
90
|
+
} else {
|
|
91
|
+
this.adapter.log.debug(`work called with id ${id}, but Bridge is not connected yet.`);
|
|
74
92
|
}
|
|
75
93
|
} catch (error) {
|
|
76
94
|
this.adapter.log.error(`error at ${activeFunction}: ${error}`);
|
|
@@ -90,7 +108,11 @@ class bridgeClass {
|
|
|
90
108
|
this.adapter.log.debug(`Function ${activeFunction} started.`);
|
|
91
109
|
try {
|
|
92
110
|
if (!this.CheckedIds[id] || (options && options.forceDiscovery)) {
|
|
111
|
+
this.CheckedIds[id] = {};
|
|
112
|
+
this.adapter.log.debug(`discover the id ${id}`);
|
|
93
113
|
await this.buildDiscovery(id, options);
|
|
114
|
+
} else {
|
|
115
|
+
this.adapter.log.debug(`${id} allready checked for discovery`);
|
|
94
116
|
}
|
|
95
117
|
} catch (error) {
|
|
96
118
|
this.adapter.log.error(`error at ${activeFunction}: ${error}`);
|
|
@@ -98,7 +120,205 @@ class bridgeClass {
|
|
|
98
120
|
}
|
|
99
121
|
|
|
100
122
|
/*********************************************************************
|
|
101
|
-
*
|
|
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 **************************
|
|
102
322
|
* ******************************************************************/
|
|
103
323
|
|
|
104
324
|
/**
|
|
@@ -106,10 +326,10 @@ class bridgeClass {
|
|
|
106
326
|
* @param val Value of the used Id
|
|
107
327
|
*/
|
|
108
328
|
async publishId(id, val) {
|
|
109
|
-
const activeFunction = 'bridge.js -
|
|
329
|
+
const activeFunction = 'bridge.js - publishId';
|
|
110
330
|
this.adapter.log.debug(`Function ${activeFunction} started.`);
|
|
111
331
|
try {
|
|
112
|
-
if (this.
|
|
332
|
+
if (this.PublishedIds[id]) {
|
|
113
333
|
if (val === undefined) {
|
|
114
334
|
const State = await this.adapter.getState(id);
|
|
115
335
|
if (State) {
|
|
@@ -117,16 +337,21 @@ class bridgeClass {
|
|
|
117
337
|
}
|
|
118
338
|
}
|
|
119
339
|
if (
|
|
120
|
-
!this.SubscribedTopics[this.
|
|
121
|
-
this.SubscribedTopics[this.
|
|
122
|
-
Date.now() - this.SubscribedTopics[this.
|
|
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
|
|
123
343
|
) {
|
|
124
|
-
this.
|
|
125
|
-
this.
|
|
126
|
-
|
|
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, {
|
|
127
350
|
retain: true,
|
|
128
351
|
});
|
|
129
352
|
}
|
|
353
|
+
} else {
|
|
354
|
+
this.adapter.log.debug(`Id not for publish used.`);
|
|
130
355
|
}
|
|
131
356
|
} catch (error) {
|
|
132
357
|
this.adapter.log.error(`error at ${activeFunction}: ${error}`);
|
|
@@ -138,7 +363,7 @@ class bridgeClass {
|
|
|
138
363
|
* @param options Options for using spezial fuctions
|
|
139
364
|
*/
|
|
140
365
|
async buildDiscovery(id, options) {
|
|
141
|
-
const activeFunction = 'bridge.js -
|
|
366
|
+
const activeFunction = 'bridge.js - buildDiscovery';
|
|
142
367
|
this.adapter.log.debug(`Function ${activeFunction} started.`);
|
|
143
368
|
try {
|
|
144
369
|
// Query for decoded Folder
|
|
@@ -172,17 +397,27 @@ class bridgeClass {
|
|
|
172
397
|
options.Bridgestate = Bridgestate;
|
|
173
398
|
const DiscoveryObject = await this.getDiscoveryObject(changeInfo, options);
|
|
174
399
|
if (Bridgestate.publish) {
|
|
175
|
-
this.
|
|
176
|
-
|
|
177
|
-
|
|
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();
|
|
178
410
|
}
|
|
179
411
|
if (Bridgestate.subscribe) {
|
|
180
412
|
this.SubscribedTopics[DiscoveryObject?.Topic] = {};
|
|
181
413
|
this.SubscribedTopics[DiscoveryObject?.Topic].id = id;
|
|
182
414
|
this.SubscribedTopics[DiscoveryObject?.Topic].val = 0;
|
|
183
|
-
this.SubscribedTopics[DiscoveryObject?.Topic].ts = Date.now();
|
|
415
|
+
this.SubscribedTopics[DiscoveryObject?.Topic].ts = Date.now() - this.MinTime;
|
|
184
416
|
}
|
|
185
|
-
await this.publishDiscovery(id,
|
|
417
|
+
await this.publishDiscovery(id, {
|
|
418
|
+
topic: DiscoveryObject?.topic,
|
|
419
|
+
payload: structuredClone(DiscoveryObject?.payload),
|
|
420
|
+
});
|
|
186
421
|
}
|
|
187
422
|
}
|
|
188
423
|
|
|
@@ -220,19 +455,30 @@ class bridgeClass {
|
|
|
220
455
|
options.Bridgestate = Bridgestate;
|
|
221
456
|
const DiscoveryObject = await this.getDiscoveryObject(changeInfo, options);
|
|
222
457
|
if (Bridgestate.publish) {
|
|
223
|
-
this.
|
|
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();
|
|
224
468
|
}
|
|
225
469
|
if (Bridgestate.subscribe) {
|
|
226
470
|
this.SubscribedTopics[DiscoveryObject?.Topic] = {};
|
|
227
471
|
this.SubscribedTopics[DiscoveryObject?.Topic].id = id;
|
|
228
472
|
this.SubscribedTopics[DiscoveryObject?.Topic].val = 0;
|
|
229
|
-
this.SubscribedTopics[DiscoveryObject?.Topic].ts = Date.now();
|
|
473
|
+
this.SubscribedTopics[DiscoveryObject?.Topic].ts = Date.now() - this.MinTime;
|
|
230
474
|
}
|
|
231
|
-
await this.publishDiscovery(id,
|
|
475
|
+
await this.publishDiscovery(id, {
|
|
476
|
+
topic: DiscoveryObject?.topic,
|
|
477
|
+
payload: structuredClone(DiscoveryObject?.payload),
|
|
478
|
+
});
|
|
232
479
|
}
|
|
233
480
|
}
|
|
234
481
|
}
|
|
235
|
-
this.CheckedIds[id] = {};
|
|
236
482
|
} catch (error) {
|
|
237
483
|
this.adapter.log.error(`error at ${activeFunction}: ${error}`);
|
|
238
484
|
}
|
|
@@ -277,7 +523,7 @@ class bridgeClass {
|
|
|
277
523
|
for (const Attribute in AdditionalAttributes) {
|
|
278
524
|
DiscoveryPayload[Attribute] = AdditionalAttributes[Attribute];
|
|
279
525
|
}
|
|
280
|
-
return { Topic: Topic,
|
|
526
|
+
return { Topic: Topic, topic: DiscoveryTopic, payload: DiscoveryPayload };
|
|
281
527
|
} catch (error) {
|
|
282
528
|
this.adapter.log.error(`error at ${activeFunction}: ${error}`);
|
|
283
529
|
}
|
|
@@ -296,11 +542,9 @@ class bridgeClass {
|
|
|
296
542
|
this.adapter.log.debug(`Function ${activeFunction} started.`);
|
|
297
543
|
try {
|
|
298
544
|
this.DiscoveredIds[id] = DiscoveryObject;
|
|
299
|
-
await this.bridgeMqttClient.publish(
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
{},
|
|
303
|
-
);
|
|
545
|
+
await this.bridgeMqttClient.publish(DiscoveryObject.topic, JSON.stringify(DiscoveryObject.payload), {
|
|
546
|
+
retain: true,
|
|
547
|
+
});
|
|
304
548
|
await this.adapter.setState('info.discoveredIds', JSON.stringify(this.DiscoveredIds), true);
|
|
305
549
|
} catch (error) {
|
|
306
550
|
this.adapter.log.error(`error at ${activeFunction}: ${error}`);
|
|
@@ -619,6 +863,7 @@ class bridgeClass {
|
|
|
619
863
|
}
|
|
620
864
|
}
|
|
621
865
|
}
|
|
866
|
+
await this.discoverClimate();
|
|
622
867
|
} catch (error) {
|
|
623
868
|
this.adapter.log.error(`error at ${activeFunction}: ${error}`);
|
|
624
869
|
}
|
|
@@ -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
|
|
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
|
@@ -931,10 +931,21 @@ class Lorawan extends utils.Adapter {
|
|
|
931
931
|
}
|
|
932
932
|
|
|
933
933
|
// send application to config
|
|
934
|
-
} else if (
|
|
934
|
+
} else if (
|
|
935
|
+
obj.command === 'getApplicationsForConfig' ||
|
|
936
|
+
obj.command === 'getApplicationsForClimateConfig' ||
|
|
937
|
+
obj.command === 'getApplicationsForClimateModeConfig'
|
|
938
|
+
) {
|
|
935
939
|
try {
|
|
936
|
-
let myCount =
|
|
937
|
-
const applications = [
|
|
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 =
|
|
961
|
-
const devices = [
|
|
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 =
|
|
997
|
-
const states = [
|
|
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) {
|