iobroker.zigbee 3.3.1-alpha.0 → 3.3.2
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/LICENSE +1 -1
- package/README.md +49 -50
- package/admin/admin.js +39 -7
- package/admin/tab_m.html +19 -0
- package/io-package.json +26 -26
- package/lib/colors.js +182 -421
- package/lib/exposes.js +126 -202
- package/lib/groups.js +2 -5
- package/lib/legacy/devices.js +8 -5
- package/lib/models.js +101 -12
- package/lib/statescontroller.js +147 -134
- package/lib/zigbeecontroller.js +59 -10
- package/main.js +15 -20
- package/package.json +5 -5
package/lib/zigbeecontroller.js
CHANGED
|
@@ -1230,6 +1230,20 @@ class ZigbeeController extends EventEmitter {
|
|
|
1230
1230
|
*/
|
|
1231
1231
|
}
|
|
1232
1232
|
|
|
1233
|
+
|
|
1234
|
+
async getConverterValue(converter, target, key, preparedValue, preparedObject, meta) {
|
|
1235
|
+
if (preparedObject) {
|
|
1236
|
+
// try {
|
|
1237
|
+
return { result:await converter.convertSet(target, key, preparedObject, meta), fromObject:true };
|
|
1238
|
+
// }
|
|
1239
|
+
// catch (error)
|
|
1240
|
+
// {
|
|
1241
|
+
// return { result:await converter.convertSet(target, key, preparedValue, meta), fromObject:false };
|
|
1242
|
+
// }
|
|
1243
|
+
}
|
|
1244
|
+
else return { result:await converter.convertSet(target, key, preparedValue, meta), fromObject:false };
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1233
1247
|
// publish via converter
|
|
1234
1248
|
//
|
|
1235
1249
|
async publishFromState(deviceId, model, stateModel, stateList, options, debugID, has_elevated_debug) {
|
|
@@ -1284,6 +1298,12 @@ class ZigbeeController extends EventEmitter {
|
|
|
1284
1298
|
|
|
1285
1299
|
return;
|
|
1286
1300
|
}
|
|
1301
|
+
// force read for brightness
|
|
1302
|
+
const skey = stateDesc.setattr || stateDesc.prop || stateDesc.id;
|
|
1303
|
+
const readKey = { key: undefined, converter: undefined };
|
|
1304
|
+
if (skey === 'brightness') readKey.key = 'state';
|
|
1305
|
+
if (skey === 'state') readKey.key = 'brightness';
|
|
1306
|
+
|
|
1287
1307
|
for (const c of mappedModel.toZigbee) {
|
|
1288
1308
|
|
|
1289
1309
|
if (!c.hasOwnProperty('convertSet')) continue;
|
|
@@ -1292,6 +1312,8 @@ class ZigbeeController extends EventEmitter {
|
|
|
1292
1312
|
{
|
|
1293
1313
|
if (converter === undefined)
|
|
1294
1314
|
{
|
|
1315
|
+
if (readKey.key && readKey.converter === undefined && c.hasOwnProperty('convertGet'))
|
|
1316
|
+
readKey.converter = c;
|
|
1295
1317
|
converter = c;
|
|
1296
1318
|
if (has_elevated_debug) {
|
|
1297
1319
|
const message = `Setting converter to keyless converter for ${deviceId} of type ${model}`;
|
|
@@ -1326,8 +1348,14 @@ class ZigbeeController extends EventEmitter {
|
|
|
1326
1348
|
converter = c;
|
|
1327
1349
|
msg_counter++;
|
|
1328
1350
|
}
|
|
1351
|
+
if (readKey.key && c.key.includes(readKey.key) && c.hasOwnProperty('convertGet'))
|
|
1352
|
+
readKey.converter = c;
|
|
1329
1353
|
}
|
|
1330
1354
|
if (converter === undefined) {
|
|
1355
|
+
if (stateDesc.isInternalState) {
|
|
1356
|
+
this.emit('acknowledge_state', deviceId, undefined, stateDesc , undefined );
|
|
1357
|
+
return;
|
|
1358
|
+
}
|
|
1331
1359
|
const message = `No converter available for '${model}' with key '${stateDesc.id}' `;
|
|
1332
1360
|
if (has_elevated_debug) {
|
|
1333
1361
|
this.emit('device_debug', { ID:debugID, data: { error: 'NOCONV',states:[{id:stateDesc.id, value:value, payload:'no converter'}] , IO:false }, message:message});
|
|
@@ -1353,7 +1381,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
1353
1381
|
|
|
1354
1382
|
const epName = stateDesc.epname !== undefined ? stateDesc.epname : (stateDesc.prop || stateDesc.id);
|
|
1355
1383
|
const key = stateDesc.setattr || stateDesc.prop || stateDesc.id;
|
|
1356
|
-
const message = `convert ${key} with value ${safeJsonStringify(preparedValue)} and options ${safeJsonStringify(preparedOptions)} for device ${deviceId} with Endpoint ${epName}`;
|
|
1384
|
+
const message = `convert ${key} with value ${safeJsonStringify(preparedValue)} and options ${safeJsonStringify(preparedOptions)} for device ${deviceId} ${stateDesc.epname ? `with Endpoint ${epName}` : 'without Endpoint'}`;
|
|
1357
1385
|
if (has_elevated_debug) {
|
|
1358
1386
|
this.emit('device_debug', { ID:debugID, data: { flag: '04', payload: {key:key, ep: stateDesc.epname, value:preparedValue, options:preparedOptions}, IO:false }, message:message});
|
|
1359
1387
|
}
|
|
@@ -1371,7 +1399,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
1371
1399
|
if (this.debugActive) this.debug(`target: ${safeJsonStringify(target)}`);
|
|
1372
1400
|
|
|
1373
1401
|
const meta = {
|
|
1374
|
-
endpoint_name:
|
|
1402
|
+
endpoint_name: stateDesc.epname,
|
|
1375
1403
|
options: preparedOptions,
|
|
1376
1404
|
device: entity.device,
|
|
1377
1405
|
mapped: model === 'group' ? [] : mappedModel,
|
|
@@ -1398,10 +1426,22 @@ class ZigbeeController extends EventEmitter {
|
|
|
1398
1426
|
}
|
|
1399
1427
|
}
|
|
1400
1428
|
let retry = 2;
|
|
1429
|
+
/*
|
|
1430
|
+
let preparedObject = null;
|
|
1431
|
+
try {
|
|
1432
|
+
preparedObject = JSON.parse(preparedValue);
|
|
1433
|
+
}
|
|
1434
|
+
catch (error)
|
|
1435
|
+
{ }
|
|
1436
|
+
*/
|
|
1437
|
+
|
|
1401
1438
|
do
|
|
1402
1439
|
{
|
|
1403
1440
|
try {
|
|
1404
1441
|
const result = await converter.convertSet(target, key, preparedValue, meta);
|
|
1442
|
+
const fromObject = false;
|
|
1443
|
+
const preparedObject = null;
|
|
1444
|
+
//const { result, fromObject } = await this.getConverterValue(converter, target, key, preparedValue, preparedObject, meta);
|
|
1405
1445
|
const message = `convert result ${safeJsonStringify(result)} for device ${deviceId}`;
|
|
1406
1446
|
if (isGroup)
|
|
1407
1447
|
this.emit('published', deviceId, model, stateModel, stateList, options, debugID, has_elevated_debug );
|
|
@@ -1411,7 +1451,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
1411
1451
|
else
|
|
1412
1452
|
if (this.debugActive) this.debug(message);
|
|
1413
1453
|
if (result !== undefined) {
|
|
1414
|
-
if (
|
|
1454
|
+
if (!stateDesc.noack) {
|
|
1415
1455
|
this.emit('acknowledge_state', deviceId, model, stateDesc, value );
|
|
1416
1456
|
}
|
|
1417
1457
|
// process sync state list
|
|
@@ -1419,7 +1459,8 @@ class ZigbeeController extends EventEmitter {
|
|
|
1419
1459
|
}
|
|
1420
1460
|
else {
|
|
1421
1461
|
if (has_elevated_debug) {
|
|
1422
|
-
const
|
|
1462
|
+
const stringvalue = fromObject ? safeJsonStringify(preparedObject) : typeof preparedValue == 'object' ? safeJsonStringify(preparedValue) : preparedValue;
|
|
1463
|
+
const message = `Convert does not return a result result for ${key} with ${stringvalue} on device ${deviceId}.`;
|
|
1423
1464
|
this.emit('device_debug', { ID:debugID, data: { flag: '06' , IO:false }, message:message});
|
|
1424
1465
|
}
|
|
1425
1466
|
}
|
|
@@ -1440,7 +1481,13 @@ class ZigbeeController extends EventEmitter {
|
|
|
1440
1481
|
` Error: ${error.message}`, `Send command to ${deviceId} failed with`, error);
|
|
1441
1482
|
}
|
|
1442
1483
|
}
|
|
1443
|
-
} while (retry > 0)
|
|
1484
|
+
} while (retry > 0);
|
|
1485
|
+
|
|
1486
|
+
if (readKey.converter) {
|
|
1487
|
+
const tt = preparedOptions.transition || preparedOptions.transition_time;
|
|
1488
|
+
setTimeout(async () => { await readKey.converter.convertGet(target, readKey.key, {device:entity.device})}, tt ? tt * 1000 : 100)
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1444
1491
|
});
|
|
1445
1492
|
} catch (err) {
|
|
1446
1493
|
const message = `No entity for ${deviceId} : ${err && err.message ? err.message : 'no error message'}`;
|
|
@@ -1574,14 +1621,16 @@ class ZigbeeController extends EventEmitter {
|
|
|
1574
1621
|
for (const converter of mappedModel.toZigbee) {
|
|
1575
1622
|
if (converter.hasOwnProperty('convertGet')) {
|
|
1576
1623
|
cCount++;
|
|
1577
|
-
const sources =
|
|
1578
|
-
if (converter.endpoints
|
|
1579
|
-
|
|
1624
|
+
const sources = new Set();
|
|
1625
|
+
if (!converter.endpoints) sources.add(entity.device.endpoints[0]);
|
|
1626
|
+
const epCandidates = converter.endpoints ? converter.endpoints : epmap ? Object.keys(epmap) : undefined;
|
|
1627
|
+
if (epCandidates) {
|
|
1628
|
+
for (const epname of epCandidates) {
|
|
1580
1629
|
const source = entity.device.endpoints.find((id) => id.ID == epmap[epname]);
|
|
1581
|
-
if (source) sources.
|
|
1630
|
+
if (source) sources.add(source);
|
|
1582
1631
|
}
|
|
1583
1632
|
}
|
|
1584
|
-
if (sources.
|
|
1633
|
+
if (sources.size == 0) sources.add(entity.device.endpoints[0]);
|
|
1585
1634
|
for (const source of sources) {
|
|
1586
1635
|
for (const k of converter.key)
|
|
1587
1636
|
try {
|
package/main.js
CHANGED
|
@@ -130,15 +130,13 @@ class Zigbee extends utils.Adapter {
|
|
|
130
130
|
const Sentry = sentryInstance.getSentryObject();
|
|
131
131
|
if (Sentry) {
|
|
132
132
|
if (message) {
|
|
133
|
-
Sentry.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}));
|
|
133
|
+
Sentry && Sentry.withScope(scope => scope.addBreadcrumb({
|
|
134
|
+
type: 'error', // predefined types
|
|
135
|
+
category: 'error message',
|
|
136
|
+
level: 'error',
|
|
137
|
+
message
|
|
138
|
+
}));
|
|
140
139
|
}
|
|
141
|
-
|
|
142
140
|
if (typeof error == 'string') {
|
|
143
141
|
Sentry.captureException(new Error(error));
|
|
144
142
|
} else {
|
|
@@ -641,13 +639,13 @@ class Zigbee extends utils.Adapter {
|
|
|
641
639
|
await this.callPluginMethod('start', [this.zbController, this.stController]);
|
|
642
640
|
}
|
|
643
641
|
|
|
644
|
-
async syncAllDeviceStates(
|
|
642
|
+
async syncAllDeviceStates(rebuildStates) {
|
|
645
643
|
this.stController.CleanupRequired(false);
|
|
646
|
-
if (
|
|
644
|
+
if (rebuildStates) this.stController.clearModelDefinitions();
|
|
647
645
|
const devicesFromObjects = (await this.getDevicesAsync()).filter(item => item.native.id.length ==16).map((item) => `0x${item.native.id}`);
|
|
648
646
|
const devicesFromDB = this.zbController.getClientIterator(false);
|
|
649
647
|
for (const device of devicesFromDB) {
|
|
650
|
-
if (
|
|
648
|
+
if (rebuildStates) {
|
|
651
649
|
const hM = await zigbeeHerdsmanConverters.findByDevice(device);
|
|
652
650
|
await this.stController.AddModelFromHerdsman(device, hM ? hM.model : device.modelID);
|
|
653
651
|
}
|
|
@@ -660,7 +658,7 @@ class Zigbee extends utils.Adapter {
|
|
|
660
658
|
if (entity) {
|
|
661
659
|
const model = entity.mapped ? entity.mapped.model : entity.device.modelID;
|
|
662
660
|
this.stController.updateDev(zbIdorIeeetoAdId(this, device.ieeeAddr, false), model, model, () =>
|
|
663
|
-
this.stController.syncDevStates(device, model
|
|
661
|
+
this.stController.syncDevStates(device, model));
|
|
664
662
|
}
|
|
665
663
|
else (this.log.debug('resolveEntity returned no entity'));
|
|
666
664
|
}
|
|
@@ -705,15 +703,12 @@ class Zigbee extends utils.Adapter {
|
|
|
705
703
|
await this.stController.AddModelFromHerdsman(entity.device, model)
|
|
706
704
|
if (device) {
|
|
707
705
|
this.getObject(zbIdorIeeetoAdId(this, device.ieeeAddr, false), (err, obj) => {
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
if (this.debugActive) this.log.debug(`new device ${device.ieeeAddr} ${device.networkAddress} ${model} `);
|
|
706
|
+
const model = (entity.mapped) ? entity.mapped.model : entity.device.modelID;
|
|
707
|
+
if (this.debugActive) this.log.debug(`new device ${device.ieeeAddr} ${device.networkAddress} ${model} `);
|
|
711
708
|
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
}
|
|
716
|
-
else if (this.debugActive) this.log.debug(`Device ${safeJsonStringify(entity)} rejoined, no new device`);
|
|
709
|
+
if (!obj) this.logToPairing(`New device joined '${device.ieeeAddr}' model ${model}`, true);
|
|
710
|
+
this.stController.updateDev(zbIdorIeeetoAdId(this, device.ieeeAddr, false), model, model, () =>
|
|
711
|
+
this.stController.syncDevStates(device, model));
|
|
717
712
|
});
|
|
718
713
|
}
|
|
719
714
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.zigbee",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.2",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "Kirov Ilya",
|
|
6
6
|
"email": "kirovilya@gmail.com"
|
|
@@ -23,13 +23,13 @@
|
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@iobroker/adapter-core": "^3.3.2",
|
|
25
25
|
"@iobroker/dm-utils": "^1.0.13",
|
|
26
|
-
"humanize-duration": "^3.33.
|
|
26
|
+
"humanize-duration": "^3.33.2",
|
|
27
27
|
"tar": "^7.5.2",
|
|
28
28
|
"ajv": "^8.17.1",
|
|
29
29
|
"uri-js": "^4.4.1",
|
|
30
30
|
"typescript": "^5.9.3",
|
|
31
|
-
"zigbee-herdsman": "^
|
|
32
|
-
"zigbee-herdsman-converters": "25.
|
|
31
|
+
"zigbee-herdsman": "^8.0.1",
|
|
32
|
+
"zigbee-herdsman-converters": "^25.99.0"
|
|
33
33
|
},
|
|
34
34
|
"description": "Zigbee devices",
|
|
35
35
|
"devDependencies": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"@alcalzone/release-script-plugin-license": "^4.0.0",
|
|
39
39
|
"@alcalzone/release-script-plugin-manual-review": "^4.0.0",
|
|
40
40
|
"@iobroker/testing": "^5.2.2",
|
|
41
|
-
"eslint": "^9.39.
|
|
41
|
+
"eslint": "^9.39.2",
|
|
42
42
|
"eslint-config-prettier": "^9.1.0",
|
|
43
43
|
"eslint-plugin-prettier": "^5.5.4",
|
|
44
44
|
"mixin-deep": "^2.0.1",
|