matterbridge-zigbee2mqtt 2.4.7 → 2.5.0-dev.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/CHANGELOG.md +33 -0
- package/README.md +18 -3
- package/dist/entity.js +99 -85
- package/dist/platform.js +35 -9
- package/matterbridge-zigbee2mqtt.schema.json +26 -15
- package/npm-shrinkwrap.json +93 -77
- package/package.json +2 -2
- package/tsconfig.jest.json +8 -0
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,39 @@ If you like this project and find it useful, please consider giving it a star on
|
|
|
8
8
|
<img src="bmc-button.svg" alt="Buy me a coffee" width="120">
|
|
9
9
|
</a>
|
|
10
10
|
|
|
11
|
+
### Breaking Changes
|
|
12
|
+
|
|
13
|
+
New device types:
|
|
14
|
+
|
|
15
|
+
- extendedColorLight
|
|
16
|
+
- waterLeakDetector
|
|
17
|
+
- rainSensor
|
|
18
|
+
- smokeSensor
|
|
19
|
+
|
|
20
|
+
If your controller has issues detecting the new device type, blacklist these devices, restart, wait 5 minutes, remove the blacklist and restart again. This will create a new endpoint on the controller.
|
|
21
|
+
|
|
22
|
+
## [2.5.0] - 2025-05-21
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- [scenes]: Added scenes support for groups and devices. See the README.md for explanations.
|
|
27
|
+
- [waterLeak]: Added waterLeakDetector device type for zigbee property "water_leak". Default to false (i.e. no alarm) since is not possible to get the property.
|
|
28
|
+
- [rainSensor]: Added rainSensor device type for zigbee property "rain". Default to false (i.e. no alarm) since is not possible to get the property.
|
|
29
|
+
- [smokeSensor]: Added smokeSensor device type for zigbee property "smoke". Default to false (i.e. no alarm) since is not possible to get the property.
|
|
30
|
+
- [colorTemp]: Added conversion from color temperature to rgb for the devices that doesn't support color temperature.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- [package]: Updated package.
|
|
35
|
+
- [package]: Updated dependencies.
|
|
36
|
+
- [plugin]: Requires Matterbridge 3.0.3.
|
|
37
|
+
- [config]: As anticipated in the previous release, the parameter postfixHostname has been removed. Use postfix if needed.
|
|
38
|
+
- [colorRgb]: Changed the default device type from colorTemperatureLight to extendedColorLight to solve the SmartThings issue with colors.
|
|
39
|
+
|
|
40
|
+
<a href="https://www.buymeacoffee.com/luligugithub">
|
|
41
|
+
<img src="bmc-button.svg" alt="Buy me a coffee" width="80">
|
|
42
|
+
</a>
|
|
43
|
+
|
|
11
44
|
## [2.4.7] - 2025-03-19
|
|
12
45
|
|
|
13
46
|
### Added
|
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ Matterbridge zigbee2mqtt is a matterbridge production-level plugin that expose a
|
|
|
17
17
|
|
|
18
18
|
No hub or dedicated hardware needed.
|
|
19
19
|
|
|
20
|
-
Interested in super fast and autonomous automations for zigbee2mqtt
|
|
20
|
+
Interested in super fast and autonomous **[automations for zigbee2mqtt](https://github.com/Luligu/zigbee2mqtt-automations)**? Try this: https://github.com/Luligu/zigbee2mqtt-automations.
|
|
21
21
|
|
|
22
22
|
If you like this project and find it useful, please consider giving it a star on GitHub at https://github.com/Luligu/matterbridge-zigbee2mqtt and sponsoring it.
|
|
23
23
|
|
|
@@ -150,8 +150,9 @@ These are the default vules:
|
|
|
150
150
|
"outletList": [],
|
|
151
151
|
"featureBlackList": [],
|
|
152
152
|
"deviceFeatureBlackList": {},
|
|
153
|
-
"
|
|
154
|
-
"
|
|
153
|
+
"scenesType": "outlet",
|
|
154
|
+
"scenesPrefix: true,
|
|
155
|
+
"postfix": ""
|
|
155
156
|
}
|
|
156
157
|
```
|
|
157
158
|
|
|
@@ -250,6 +251,20 @@ If one of your devices is not supported out of the box, open an issue and we wil
|
|
|
250
251
|
|
|
251
252
|

|
|
252
253
|
|
|
254
|
+
## Scenes in groups and devices
|
|
255
|
+
|
|
256
|
+
With release 2.5.0 has been added support for scenes in groups and devices.
|
|
257
|
+
|
|
258
|
+
In the config select what device type you want to use to expose the command that runs the scene: 'light' | 'outlet' | 'switch' | 'mounted_switch'.
|
|
259
|
+
|
|
260
|
+
Switch is not supported by Alexa. Mounted Switch is not supported by Apple Home.
|
|
261
|
+
|
|
262
|
+
The virtual device takes the name of the group or device it belongs to, with added the name of scene. If scenesPrefix is disabled, it takes only the name of the scene. Consider that in Matter the node name is 32 characters long.
|
|
263
|
+
|
|
264
|
+
The state of the virtual device is always reverted to off in a few seconds.
|
|
265
|
+
|
|
266
|
+
It is possibile to disable the feature globally with featureBlackList and on a per device/group base with deviceFeatureBlackList.
|
|
267
|
+
|
|
253
268
|
# Known issues
|
|
254
269
|
|
|
255
270
|
For general controller issues check the Matterbridge Known issues section
|
package/dist/entity.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { airQualitySensor, colorTemperatureSwitch, dimmableSwitch, onOffSwitch, powerSource, bridgedNode, electricalSensor, onOffLight, dimmableLight, colorTemperatureLight, onOffOutlet, coverDevice, thermostatDevice, MatterbridgeEndpoint, dimmableOutlet, doorLockDevice, occupancySensor, lightSensor, contactSensor, temperatureSensor, humiditySensor, pressureSensor, genericSwitch, } from 'matterbridge';
|
|
1
|
+
import { airQualitySensor, colorTemperatureSwitch, dimmableSwitch, onOffSwitch, powerSource, bridgedNode, electricalSensor, onOffLight, dimmableLight, colorTemperatureLight, onOffOutlet, coverDevice, thermostatDevice, MatterbridgeEndpoint, dimmableOutlet, doorLockDevice, occupancySensor, lightSensor, contactSensor, temperatureSensor, humiditySensor, pressureSensor, genericSwitch, waterLeakDetector, rainSensor, smokeCoAlarm, extendedColorLight, } from 'matterbridge';
|
|
2
2
|
import { AnsiLogger, gn, dn, ign, idn, rs, db, debugStringify, hk, zb, or, nf, CYAN, er, YELLOW } from 'matterbridge/logger';
|
|
3
|
-
import { deepCopy, deepEqual, isValidNumber } from 'matterbridge/utils';
|
|
3
|
+
import { deepCopy, deepEqual, isValidNumber, kelvinToRGB, miredToKelvin } from 'matterbridge/utils';
|
|
4
4
|
import * as color from 'matterbridge/utils';
|
|
5
5
|
import { SwitchesTag, NumberTag } from 'matterbridge/matter';
|
|
6
6
|
import { getClusterNameById, ClusterId } from 'matterbridge/matter/types';
|
|
7
|
-
import { ElectricalEnergyMeasurement, ElectricalPowerMeasurement, OnOffCluster, LevelControlCluster, WindowCoveringCluster, DoorLockCluster, BridgedDeviceBasicInformation, OnOff, LevelControl, ColorControl, ColorControlCluster, TemperatureMeasurement, BooleanState, RelativeHumidityMeasurement, PressureMeasurement, OccupancySensing, IlluminanceMeasurement, PowerSource, WindowCovering, DoorLock, ThermostatCluster, Thermostat, AirQuality, TotalVolatileOrganicCompoundsConcentrationMeasurement, CarbonDioxideConcentrationMeasurement, CarbonMonoxideConcentrationMeasurement, FormaldehydeConcentrationMeasurement, Pm1ConcentrationMeasurement, Pm25ConcentrationMeasurement, Pm10ConcentrationMeasurement, } from 'matterbridge/matter/clusters';
|
|
7
|
+
import { ElectricalEnergyMeasurement, ElectricalPowerMeasurement, OnOffCluster, LevelControlCluster, WindowCoveringCluster, DoorLockCluster, BridgedDeviceBasicInformation, OnOff, LevelControl, ColorControl, ColorControlCluster, TemperatureMeasurement, BooleanState, RelativeHumidityMeasurement, PressureMeasurement, OccupancySensing, IlluminanceMeasurement, PowerSource, WindowCovering, DoorLock, ThermostatCluster, Thermostat, AirQuality, TotalVolatileOrganicCompoundsConcentrationMeasurement, CarbonDioxideConcentrationMeasurement, CarbonMonoxideConcentrationMeasurement, FormaldehydeConcentrationMeasurement, Pm1ConcentrationMeasurement, Pm25ConcentrationMeasurement, Pm10ConcentrationMeasurement, SmokeCoAlarm, } from 'matterbridge/matter/clusters';
|
|
8
8
|
import EventEmitter from 'node:events';
|
|
9
|
-
import { hostname } from 'node:os';
|
|
10
9
|
export class ZigbeeEntity extends EventEmitter {
|
|
11
10
|
log;
|
|
12
11
|
serial = '';
|
|
@@ -110,7 +109,7 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
110
109
|
const propertyMap = this.propertyMap.get(('action_' + value));
|
|
111
110
|
if (propertyMap) {
|
|
112
111
|
const child = this.bridgedDevice.getChildEndpointByName(propertyMap.endpoint);
|
|
113
|
-
if (child && child.
|
|
112
|
+
if (child && child.maybeNumber)
|
|
114
113
|
child.triggerSwitchEvent(propertyMap.action, this.log);
|
|
115
114
|
}
|
|
116
115
|
else
|
|
@@ -294,11 +293,11 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
294
293
|
}
|
|
295
294
|
const localValue = deviceEndpoint.getAttribute(ClusterId(clusterId), attributeName, undefined);
|
|
296
295
|
if (typeof value === 'object' ? deepEqual(value, localValue) : value === localValue) {
|
|
297
|
-
this.log.debug(`Skip update endpoint ${deviceEndpoint.name}:${deviceEndpoint.
|
|
296
|
+
this.log.debug(`Skip update endpoint ${deviceEndpoint.name}:${deviceEndpoint.maybeNumber}${childEndpointName ? ' (' + childEndpointName + ')' : ''} ` +
|
|
298
297
|
`attribute ${getClusterNameById(ClusterId(clusterId))}.${attributeName} already ${typeof value === 'object' ? debugStringify(value) : value}`);
|
|
299
298
|
return;
|
|
300
299
|
}
|
|
301
|
-
this.log.info(`${db}Update endpoint ${this.eidn}${deviceEndpoint.name}:${deviceEndpoint.
|
|
300
|
+
this.log.info(`${db}Update endpoint ${this.eidn}${deviceEndpoint.name}:${deviceEndpoint.maybeNumber}${db}${childEndpointName ? ' (' + zb + childEndpointName + db + ')' : ''} ` +
|
|
302
301
|
`attribute ${hk}${getClusterNameById(ClusterId(clusterId))}${db}.${hk}${attributeName}${db} from ${YELLOW}${typeof localValue === 'object' ? debugStringify(localValue) : localValue}${db} to ${YELLOW}${typeof value === 'object' ? debugStringify(value) : value}${db}`);
|
|
303
302
|
try {
|
|
304
303
|
deviceEndpoint.setAttribute(ClusterId(clusterId), attributeName, value);
|
|
@@ -330,10 +329,7 @@ export class ZigbeeGroup extends ZigbeeEntity {
|
|
|
330
329
|
}
|
|
331
330
|
static async create(platform, group) {
|
|
332
331
|
const zigbeeGroup = new ZigbeeGroup(platform, group);
|
|
333
|
-
if (zigbeeGroup.platform.
|
|
334
|
-
zigbeeGroup.serial = `group-${group.id}_${hostname}`.slice(0, 32);
|
|
335
|
-
}
|
|
336
|
-
else if (zigbeeGroup.platform.postfix !== '') {
|
|
332
|
+
if (zigbeeGroup.platform.postfix !== '') {
|
|
337
333
|
zigbeeGroup.serial = `group-${group.id}-${zigbeeGroup.platform.postfix}`.slice(0, 32);
|
|
338
334
|
}
|
|
339
335
|
else {
|
|
@@ -419,7 +415,7 @@ export class ZigbeeGroup extends ZigbeeEntity {
|
|
|
419
415
|
zigbeeGroup.propertyMap.set('color_temp', { name: 'color_temp', type: 'light', endpoint: '' });
|
|
420
416
|
}
|
|
421
417
|
if (useColor) {
|
|
422
|
-
deviceType =
|
|
418
|
+
deviceType = extendedColorLight;
|
|
423
419
|
zigbeeGroup.propertyMap.set('color', { name: 'color', type: 'light', endpoint: '' });
|
|
424
420
|
}
|
|
425
421
|
if (isCover) {
|
|
@@ -440,9 +436,14 @@ export class ZigbeeGroup extends ZigbeeEntity {
|
|
|
440
436
|
return zigbeeGroup;
|
|
441
437
|
zigbeeGroup.bridgedDevice = new MatterbridgeEndpoint([deviceType, bridgedNode, powerSource], { uniqueStorageKey: group.friendly_name }, zigbeeGroup.log.logLevel === "debug");
|
|
442
438
|
}
|
|
443
|
-
if (platform.
|
|
439
|
+
if (!platform.featureBlackList?.includes('scenes') && !platform.deviceFeatureBlackList[group.friendly_name]?.includes('scenes')) {
|
|
444
440
|
group.scenes.forEach((scene) => {
|
|
445
441
|
zigbeeGroup.log.debug(`***Group ${gn}${group.friendly_name}${rs}${db} scene ${CYAN}${scene.name}${db} id ${CYAN}${scene.id}${db}`);
|
|
442
|
+
platform.setSelectDeviceEntity(`group-${group.id}`, 'scenes', 'Scenes', 'component');
|
|
443
|
+
platform.registerVirtualDevice(`${platform.config.scenesPrefix ? group.friendly_name + ' ' : ''}${scene.name}`, async () => {
|
|
444
|
+
zigbeeGroup.log.info(`Triggered scene "${scene.name}" id ${scene.id} from group ${group.friendly_name}`);
|
|
445
|
+
zigbeeGroup.publishCommand('scene_recall', group.friendly_name, { 'scene_recall': scene.id });
|
|
446
|
+
});
|
|
446
447
|
});
|
|
447
448
|
}
|
|
448
449
|
zigbeeGroup.addBridgedDeviceBasicInformation();
|
|
@@ -458,7 +459,7 @@ export class ZigbeeGroup extends ZigbeeEntity {
|
|
|
458
459
|
if (isLight)
|
|
459
460
|
await zigbeeGroup.bridgedDevice.addFixedLabel('type', 'light');
|
|
460
461
|
zigbeeGroup.bridgedDevice.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
|
|
461
|
-
zigbeeGroup.log.
|
|
462
|
+
zigbeeGroup.log.debug(`Command identify called for ${zigbeeGroup.ien}${group.friendly_name}${rs}${db} identifyTime:${identifyTime}`);
|
|
462
463
|
});
|
|
463
464
|
zigbeeGroup.bridgedDevice.addCommandHandler('on', async () => {
|
|
464
465
|
zigbeeGroup.log.debug(`Command on called for ${zigbeeGroup.ien}${group.friendly_name}${rs}${db}`);
|
|
@@ -520,6 +521,14 @@ export class ZigbeeGroup extends ZigbeeEntity {
|
|
|
520
521
|
const rgb = color.hslColorToRgbColor((request.hue / 254) * 360, (request.saturation / 254) * 100, 50);
|
|
521
522
|
zigbeeGroup.publishCommand('moveToHueAndSaturation', group.friendly_name, { color: { r: rgb.r, g: rgb.g, b: rgb.b } });
|
|
522
523
|
});
|
|
524
|
+
zigbeeGroup.bridgedDevice.addCommandHandler('moveToColor', async ({ request }) => {
|
|
525
|
+
zigbeeGroup.log.debug(`Command moveToColor called for ${zigbeeGroup.ien}${group.friendly_name}${rs}${db} request: X: ${request.colorX} Y: ${request.colorY}`);
|
|
526
|
+
await zigbeeGroup.bridgedDevice?.setAttribute(ColorControlCluster.id, 'colorMode', ColorControl.ColorMode.CurrentXAndCurrentY, zigbeeGroup.log);
|
|
527
|
+
const payload = { color: { x: request.colorX / 65536, y: request.colorY / 65536 } };
|
|
528
|
+
if (zigbeeGroup.transition && request.transitionTime && request.transitionTime / 10 >= 1)
|
|
529
|
+
payload['transition'] = Math.round(request.transitionTime / 10);
|
|
530
|
+
zigbeeGroup.publishCommand('moveToColor', group.friendly_name, payload);
|
|
531
|
+
});
|
|
523
532
|
}
|
|
524
533
|
}
|
|
525
534
|
if (isCover) {
|
|
@@ -600,8 +609,8 @@ export const z2ms = [
|
|
|
600
609
|
{ type: 'outlet', name: 'brightness', property: 'brightness', deviceType: dimmableOutlet, cluster: LevelControl.Cluster.id, attribute: 'currentLevel', converter: (value) => { return Math.max(1, Math.min(254, value)); } },
|
|
601
610
|
{ type: 'light', name: 'state', property: 'state', deviceType: onOffLight, cluster: OnOff.Cluster.id, attribute: 'onOff', converter: (value) => { return value === 'ON' ? true : false; } },
|
|
602
611
|
{ type: 'light', name: 'brightness', property: 'brightness', deviceType: dimmableLight, cluster: LevelControl.Cluster.id, attribute: 'currentLevel', converter: (value) => { return Math.max(1, Math.min(254, value)); } },
|
|
603
|
-
{ type: 'light', name: 'color_hs', property: 'color_hs', deviceType:
|
|
604
|
-
{ type: 'light', name: 'color_xy', property: 'color_xy', deviceType:
|
|
612
|
+
{ type: 'light', name: 'color_hs', property: 'color_hs', deviceType: extendedColorLight, cluster: ColorControl.Cluster.id, attribute: 'colorMode' },
|
|
613
|
+
{ type: 'light', name: 'color_xy', property: 'color_xy', deviceType: extendedColorLight, cluster: ColorControl.Cluster.id, attribute: 'colorMode' },
|
|
605
614
|
{ type: 'light', name: 'color_temp', property: 'color_temp', deviceType: colorTemperatureLight, cluster: ColorControl.Cluster.id, attribute: 'colorMode' },
|
|
606
615
|
{ type: 'cover', name: 'state', property: 'state', deviceType: coverDevice, cluster: WindowCovering.Cluster.id, attribute: 'targetPositionLiftPercent100ths' },
|
|
607
616
|
{ type: 'cover', name: 'moving', property: 'moving', deviceType: coverDevice, cluster: WindowCovering.Cluster.id, attribute: 'operationalStatus' },
|
|
@@ -623,9 +632,10 @@ export const z2ms = [
|
|
|
623
632
|
{ type: '', name: 'occupancy', property: 'occupancy', deviceType: occupancySensor, cluster: OccupancySensing.Cluster.id, attribute: 'occupancy', converter: (value) => { return { occupied: value }; } },
|
|
624
633
|
{ type: '', name: 'illuminance', property: 'illuminance', deviceType: lightSensor, cluster: IlluminanceMeasurement.Cluster.id, attribute: 'measuredValue', converter: (value) => { return Math.round(Math.max(Math.min(10000 * Math.log10(value), 0xfffe), 0)); } },
|
|
625
634
|
{ type: '', name: 'contact', property: 'contact', deviceType: contactSensor, cluster: BooleanState.Cluster.id, attribute: 'stateValue', converter: (value) => { return value; } },
|
|
626
|
-
{ type: '', name: 'water_leak', property: 'water_leak', deviceType:
|
|
635
|
+
{ type: '', name: 'water_leak', property: 'water_leak', deviceType: waterLeakDetector, cluster: BooleanState.Cluster.id, attribute: 'stateValue', converter: (value) => { return value; } },
|
|
636
|
+
{ type: '', name: 'rain', property: 'rain', deviceType: rainSensor, cluster: BooleanState.Cluster.id, attribute: 'stateValue', converter: (value) => { return value; } },
|
|
627
637
|
{ type: '', name: 'vibration', property: 'vibration', deviceType: contactSensor, cluster: BooleanState.Cluster.id, attribute: 'stateValue', converter: (value) => { return !value; } },
|
|
628
|
-
{ type: '', name: 'smoke', property: 'smoke', deviceType:
|
|
638
|
+
{ type: '', name: 'smoke', property: 'smoke', deviceType: smokeCoAlarm, cluster: SmokeCoAlarm.Cluster.id, attribute: 'smokeState', converter: (value) => { return value ? SmokeCoAlarm.AlarmState.Critical : SmokeCoAlarm.AlarmState.Normal; } },
|
|
629
639
|
{ type: '', name: 'carbon_monoxide', property: 'carbon_monoxide', deviceType: contactSensor, cluster: BooleanState.Cluster.id, attribute: 'stateValue', converter: (value) => { return !value; } },
|
|
630
640
|
{ type: '', name: 'temperature', property: 'temperature', deviceType: temperatureSensor, cluster: TemperatureMeasurement.Cluster.id, attribute: 'measuredValue', converter: (value) => { return Math.round(value * 100); } },
|
|
631
641
|
{ type: '', name: 'humidity', property: 'humidity', deviceType: humiditySensor, cluster: RelativeHumidityMeasurement.Cluster.id, attribute: 'measuredValue', converter: (value) => { return Math.round(value * 100); } },
|
|
@@ -644,10 +654,10 @@ export const z2ms = [
|
|
|
644
654
|
{ type: '', name: '', property: 'battery', deviceType: powerSource, cluster: PowerSource.Cluster.id, attribute: 'batPercentRemaining', converter: (value) => { return Math.round(value * 2); } },
|
|
645
655
|
{ type: '', name: '', property: 'battery_low', deviceType: powerSource, cluster: PowerSource.Cluster.id, attribute: 'batChargeLevel', converter: (value) => { return value === true ? PowerSource.BatChargeLevel.Critical : PowerSource.BatChargeLevel.Ok; } },
|
|
646
656
|
{ type: '', name: '', property: 'battery_voltage', deviceType: powerSource, cluster: PowerSource.Cluster.id, attribute: 'batVoltage', converter: (value) => { return value; } },
|
|
647
|
-
{ type: '', name: 'energy', property: 'energy', deviceType: electricalSensor, cluster: ElectricalEnergyMeasurement.Cluster.id, attribute: 'cumulativeEnergyImported', converter: (value) => { return { energy: value * 1000000 }; } },
|
|
648
|
-
{ type: '', name: 'power', property: 'power', deviceType: electricalSensor, cluster: ElectricalPowerMeasurement.Cluster.id, attribute: 'activePower', converter: (value) => { return value * 1000; } },
|
|
649
|
-
{ type: '', name: 'voltage', property: 'voltage', deviceType: electricalSensor, cluster: ElectricalPowerMeasurement.Cluster.id, attribute: 'voltage', converter: (value) => { return value * 1000; } },
|
|
650
|
-
{ type: '', name: 'current', property: 'current', deviceType: electricalSensor, cluster: ElectricalPowerMeasurement.Cluster.id, attribute: 'activeCurrent', converter: (value) => { return value * 1000; } },
|
|
657
|
+
{ type: '', name: 'energy', property: 'energy', deviceType: electricalSensor, cluster: ElectricalEnergyMeasurement.Cluster.id, attribute: 'cumulativeEnergyImported', converter: (value) => { return { energy: Math.round(value * 1000000) }; } },
|
|
658
|
+
{ type: '', name: 'power', property: 'power', deviceType: electricalSensor, cluster: ElectricalPowerMeasurement.Cluster.id, attribute: 'activePower', converter: (value) => { return Math.round(value * 1000); } },
|
|
659
|
+
{ type: '', name: 'voltage', property: 'voltage', deviceType: electricalSensor, cluster: ElectricalPowerMeasurement.Cluster.id, attribute: 'voltage', converter: (value) => { return Math.round(value * 1000); } },
|
|
660
|
+
{ type: '', name: 'current', property: 'current', deviceType: electricalSensor, cluster: ElectricalPowerMeasurement.Cluster.id, attribute: 'activeCurrent', converter: (value) => { return Math.round(value * 1000); } },
|
|
651
661
|
];
|
|
652
662
|
export class ZigbeeDevice extends ZigbeeEntity {
|
|
653
663
|
constructor(platform, device) {
|
|
@@ -656,37 +666,42 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
656
666
|
static async create(platform, device) {
|
|
657
667
|
const zigbeeDevice = new ZigbeeDevice(platform, device);
|
|
658
668
|
zigbeeDevice.serial = `${device.ieee_address}`;
|
|
659
|
-
if (zigbeeDevice.platform.
|
|
660
|
-
zigbeeDevice.serial = `${zigbeeDevice.serial}_${hostname}`.slice(0, 32);
|
|
661
|
-
}
|
|
662
|
-
else if (zigbeeDevice.platform.postfix !== '') {
|
|
669
|
+
if (zigbeeDevice.platform.postfix !== '') {
|
|
663
670
|
zigbeeDevice.serial = `${zigbeeDevice.serial}-${zigbeeDevice.platform.postfix}`.slice(0, 32);
|
|
664
671
|
}
|
|
665
672
|
if (device.friendly_name === 'Coordinator' || (device.model_id === 'ti.router' && device.manufacturer === 'TexasInstruments') || (device.model_id.startsWith('SLZB-') && device.manufacturer === 'SMLIGHT')) {
|
|
666
673
|
zigbeeDevice.isRouter = true;
|
|
667
674
|
platform.setSelectDevice(device.ieee_address, device.friendly_name, 'wifi');
|
|
668
|
-
zigbeeDevice.bridgedDevice = new MatterbridgeEndpoint([doorLockDevice], { uniqueStorageKey: device.friendly_name }, zigbeeDevice.log.logLevel === "debug");
|
|
675
|
+
zigbeeDevice.bridgedDevice = new MatterbridgeEndpoint([doorLockDevice, bridgedNode, powerSource], { uniqueStorageKey: device.friendly_name }, zigbeeDevice.log.logLevel === "debug");
|
|
669
676
|
zigbeeDevice.addBridgedDeviceBasicInformation();
|
|
670
677
|
zigbeeDevice.addPowerSource();
|
|
671
678
|
zigbeeDevice.bridgedDevice.addRequiredClusterServers();
|
|
672
679
|
await zigbeeDevice.bridgedDevice.addFixedLabel('type', 'lock');
|
|
673
680
|
zigbeeDevice.verifyMutableDevice(zigbeeDevice.bridgedDevice);
|
|
681
|
+
zigbeeDevice.bridgedDevice.addCommandHandler('identify', async (data) => {
|
|
682
|
+
zigbeeDevice.log.debug(`Command identify called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} request identifyTime:${data.request.identifyTime} `);
|
|
683
|
+
});
|
|
674
684
|
zigbeeDevice.bridgedDevice.addCommandHandler('lockDoor', async () => {
|
|
675
|
-
zigbeeDevice.log.debug(`Command permit_join
|
|
685
|
+
zigbeeDevice.log.debug(`Command permit_join false called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db}`);
|
|
676
686
|
await zigbeeDevice.bridgedDevice?.setAttribute(DoorLockCluster.id, 'lockState', DoorLock.LockState.Locked, zigbeeDevice.log);
|
|
677
|
-
zigbeeDevice.publishCommand('permit_join
|
|
687
|
+
zigbeeDevice.publishCommand('permit_join false', 'bridge/request/permit_join', { value: false });
|
|
678
688
|
});
|
|
679
689
|
zigbeeDevice.bridgedDevice.addCommandHandler('unlockDoor', async () => {
|
|
680
|
-
zigbeeDevice.log.debug(`Command permit_join
|
|
690
|
+
zigbeeDevice.log.debug(`Command permit_join true called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db}`);
|
|
681
691
|
await zigbeeDevice.bridgedDevice?.setAttribute(DoorLockCluster.id, 'lockState', DoorLock.LockState.Unlocked, zigbeeDevice.log);
|
|
682
|
-
zigbeeDevice.publishCommand('permit_join
|
|
692
|
+
zigbeeDevice.publishCommand('permit_join true', 'bridge/request/permit_join', { value: true });
|
|
683
693
|
});
|
|
684
694
|
return zigbeeDevice;
|
|
685
695
|
}
|
|
686
|
-
if (platform.
|
|
696
|
+
if (!platform.featureBlackList?.includes('scenes') && !platform.deviceFeatureBlackList[device.friendly_name]?.includes('scenes')) {
|
|
687
697
|
Object.entries(device.endpoints).forEach(([key, endpoint]) => {
|
|
688
698
|
Object.values(endpoint.scenes).forEach((scene) => {
|
|
689
699
|
zigbeeDevice.log.debug(`***Device ${dn}${device.friendly_name}${rs}${db} endpoint ${CYAN}${key}${db} scene ${CYAN}${scene.name}${db} id ${CYAN}${scene.id}${db}`);
|
|
700
|
+
platform.setSelectDeviceEntity(device.ieee_address, 'scenes', 'Scenes', 'component');
|
|
701
|
+
platform.registerVirtualDevice(`${platform.config.scenesPrefix ? device.friendly_name + ' ' : ''}${scene.name}`, async () => {
|
|
702
|
+
zigbeeDevice.log.info(`Triggered scene "${scene.name}" id ${scene.id} from device ${device.friendly_name}`);
|
|
703
|
+
zigbeeDevice.publishCommand('scene_recall', device.friendly_name, { 'scene_recall': scene.id });
|
|
704
|
+
});
|
|
690
705
|
});
|
|
691
706
|
});
|
|
692
707
|
}
|
|
@@ -908,6 +923,11 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
908
923
|
deviceTypesMap.delete(onOffLight.code);
|
|
909
924
|
if (deviceTypesMap.has(dimmableLight.code) && deviceTypesMap.has(colorTemperatureLight.code))
|
|
910
925
|
deviceTypesMap.delete(dimmableLight.code);
|
|
926
|
+
if (deviceTypesMap.has(dimmableLight.code) && deviceTypesMap.has(extendedColorLight.code))
|
|
927
|
+
deviceTypesMap.delete(dimmableLight.code);
|
|
928
|
+
if (deviceTypesMap.has(colorTemperatureLight.code) && deviceTypesMap.has(extendedColorLight.code))
|
|
929
|
+
deviceTypesMap.delete(colorTemperatureLight.code);
|
|
930
|
+
deviceTypesMap.delete(bridgedNode.code);
|
|
911
931
|
deviceTypesMap.delete(powerSource.code);
|
|
912
932
|
device.deviceTypes = Array.from(deviceTypesMap.values());
|
|
913
933
|
}
|
|
@@ -943,12 +963,26 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
943
963
|
zigbeeDevice.log.debug(`Device ${zigbeeDevice.ien}${zigbeeDevice.device?.friendly_name}${rs}${db} endpoint: ${ign}${endpoint === '' ? 'main' : endpoint}${rs}${db} => ` +
|
|
944
964
|
`${nf}tagList: ${debugStringify(device.tagList)} deviceTypes: ${debugStringify(device.deviceTypes)} clusterServersIds: ${debugStringify(device.clusterServersIds)}`);
|
|
945
965
|
}
|
|
966
|
+
if ((mainEndpoint.deviceTypes.find((dt) => dt.code === waterLeakDetector.code) || mainEndpoint.deviceTypes.find((dt) => dt.code === rainSensor.code)) && mainEndpoint.clusterServersIds.includes(BooleanState.Cluster.id)) {
|
|
967
|
+
zigbeeDevice.log.debug(`Configuring device ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} BooleanStateCluster cluster with`);
|
|
968
|
+
zigbeeDevice.bridgedDevice.createDefaultBooleanStateClusterServer(false);
|
|
969
|
+
mainEndpoint.clusterServersIds.splice(mainEndpoint.clusterServersIds.indexOf(BooleanState.Cluster.id), 1);
|
|
970
|
+
}
|
|
971
|
+
if (mainEndpoint.deviceTypes.find((dt) => dt.code === smokeCoAlarm.code) && mainEndpoint.clusterServersIds.includes(SmokeCoAlarm.Cluster.id)) {
|
|
972
|
+
zigbeeDevice.log.debug(`Configuring device ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} SmokeCoAlarmCluster cluster with`);
|
|
973
|
+
zigbeeDevice.bridgedDevice.createSmokeOnlySmokeCOAlarmClusterServer(SmokeCoAlarm.AlarmState.Normal);
|
|
974
|
+
mainEndpoint.clusterServersIds.splice(mainEndpoint.clusterServersIds.indexOf(SmokeCoAlarm.Cluster.id), 1);
|
|
975
|
+
}
|
|
946
976
|
if (mainEndpoint.clusterServersIds.includes(ColorControl.Cluster.id)) {
|
|
947
|
-
zigbeeDevice.log.debug(`Configuring device ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} ColorControlCluster cluster with HS: ${names.includes('color_hs')} XY: ${names.includes('color_xy')} CT: ${names.includes('color_temp')}`);
|
|
948
977
|
if (!names.includes('color_hs') && !names.includes('color_xy')) {
|
|
949
|
-
zigbeeDevice.
|
|
950
|
-
|
|
978
|
+
zigbeeDevice.log.debug(`Configuring device ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} ColorControlCluster cluster with CT: ${names.includes('color_temp')} min: ${zigbeeDevice.propertyMap.get('color_temp')?.value_min} max: ${zigbeeDevice.propertyMap.get('color_temp')?.value_max}`);
|
|
979
|
+
zigbeeDevice.bridgedDevice.createCtColorControlClusterServer(zigbeeDevice.propertyMap.get('color_temp')?.value_max, zigbeeDevice.propertyMap.get('color_temp')?.value_min, zigbeeDevice.propertyMap.get('color_temp')?.value_max);
|
|
951
980
|
}
|
|
981
|
+
else {
|
|
982
|
+
zigbeeDevice.log.debug(`Configuring device ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} ColorControlCluster cluster with HS: ${names.includes('color_hs')} XY: ${names.includes('color_xy')} CT: ${names.includes('color_temp')} min: ${zigbeeDevice.propertyMap.get('color_temp')?.value_min} max: ${zigbeeDevice.propertyMap.get('color_temp')?.value_max}`);
|
|
983
|
+
zigbeeDevice.bridgedDevice.createDefaultColorControlClusterServer(undefined, undefined, undefined, undefined, zigbeeDevice.propertyMap.get('color_temp')?.value_max, zigbeeDevice.propertyMap.get('color_temp')?.value_min, zigbeeDevice.propertyMap.get('color_temp')?.value_max);
|
|
984
|
+
}
|
|
985
|
+
mainEndpoint.clusterServersIds.splice(mainEndpoint.clusterServersIds.indexOf(ColorControl.Cluster.id), 1);
|
|
952
986
|
}
|
|
953
987
|
if (mainEndpoint.clusterServersIds.includes(Thermostat.Cluster.id)) {
|
|
954
988
|
const system_mode = zigbeeDevice.propertyMap.get('system_mode');
|
|
@@ -991,25 +1025,25 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
991
1025
|
zigbeeDevice.mutableDevice.clear();
|
|
992
1026
|
zigbeeDevice.logPropertyMap();
|
|
993
1027
|
zigbeeDevice.bridgedDevice.addCommandHandler('identify', async (data) => {
|
|
994
|
-
zigbeeDevice.log.debug(`Command identify called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint
|
|
1028
|
+
zigbeeDevice.log.debug(`Command identify called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint?.maybeNumber} request identifyTime:${data.request.identifyTime} `);
|
|
995
1029
|
});
|
|
996
1030
|
if (zigbeeDevice.bridgedDevice.hasClusterServer(OnOffCluster.id) || zigbeeDevice.hasEndpoints) {
|
|
997
1031
|
for (const child of zigbeeDevice.bridgedDevice.getChildEndpoints()) {
|
|
998
1032
|
if (child.hasClusterServer(OnOffCluster)) {
|
|
999
1033
|
child.addCommandHandler('on', async (data) => {
|
|
1000
|
-
zigbeeDevice.log.debug(`Command on called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint
|
|
1034
|
+
zigbeeDevice.log.debug(`Command on called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint?.maybeNumber}`);
|
|
1001
1035
|
const payload = {};
|
|
1002
1036
|
payload['state_' + data.endpoint.uniqueStorageKey] = 'ON';
|
|
1003
1037
|
zigbeeDevice.publishCommand('on', device.friendly_name, payload);
|
|
1004
1038
|
});
|
|
1005
1039
|
child.addCommandHandler('off', async (data) => {
|
|
1006
|
-
zigbeeDevice.log.debug(`Command off called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint
|
|
1040
|
+
zigbeeDevice.log.debug(`Command off called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint?.maybeNumber}`);
|
|
1007
1041
|
const payload = {};
|
|
1008
1042
|
payload['state_' + data.endpoint.uniqueStorageKey] = 'OFF';
|
|
1009
1043
|
zigbeeDevice.publishCommand('off', device.friendly_name, payload);
|
|
1010
1044
|
});
|
|
1011
1045
|
child.addCommandHandler('toggle', async (data) => {
|
|
1012
|
-
zigbeeDevice.log.debug(`Command toggle called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint
|
|
1046
|
+
zigbeeDevice.log.debug(`Command toggle called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint?.maybeNumber}`);
|
|
1013
1047
|
const payload = {};
|
|
1014
1048
|
payload['state_' + data.endpoint.uniqueStorageKey] = 'TOGGLE';
|
|
1015
1049
|
zigbeeDevice.publishCommand('toggle', device.friendly_name, payload);
|
|
@@ -1017,41 +1051,23 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1017
1051
|
}
|
|
1018
1052
|
}
|
|
1019
1053
|
zigbeeDevice.bridgedDevice.addCommandHandler('on', async (data) => {
|
|
1020
|
-
zigbeeDevice.log.debug(`Command on called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint
|
|
1021
|
-
|
|
1022
|
-
const label = zigbeeDevice.platform.matterbridge.edge ? undefined : data.endpoint.uniqueStorageKey;
|
|
1023
|
-
if (label === undefined)
|
|
1024
|
-
payload['state'] = 'ON';
|
|
1025
|
-
else
|
|
1026
|
-
payload['state_' + label] = 'ON';
|
|
1027
|
-
zigbeeDevice.publishCommand('on', device.friendly_name, payload);
|
|
1054
|
+
zigbeeDevice.log.debug(`Command on called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint?.maybeNumber}`);
|
|
1055
|
+
zigbeeDevice.publishCommand('on', device.friendly_name, { state: 'ON' });
|
|
1028
1056
|
});
|
|
1029
1057
|
zigbeeDevice.bridgedDevice.addCommandHandler('off', async (data) => {
|
|
1030
|
-
zigbeeDevice.log.debug(`Command off called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint
|
|
1031
|
-
|
|
1032
|
-
const label = zigbeeDevice.platform.matterbridge.edge ? undefined : data.endpoint.uniqueStorageKey;
|
|
1033
|
-
if (label === undefined)
|
|
1034
|
-
payload['state'] = 'OFF';
|
|
1035
|
-
else
|
|
1036
|
-
payload['state_' + label] = 'OFF';
|
|
1037
|
-
zigbeeDevice.publishCommand('off', device.friendly_name, payload);
|
|
1058
|
+
zigbeeDevice.log.debug(`Command off called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint?.maybeNumber}`);
|
|
1059
|
+
zigbeeDevice.publishCommand('off', device.friendly_name, { state: 'OFF' });
|
|
1038
1060
|
});
|
|
1039
1061
|
zigbeeDevice.bridgedDevice.addCommandHandler('toggle', async (data) => {
|
|
1040
|
-
zigbeeDevice.log.debug(`Command toggle called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint
|
|
1041
|
-
|
|
1042
|
-
const label = zigbeeDevice.platform.matterbridge.edge ? undefined : data.endpoint.uniqueStorageKey;
|
|
1043
|
-
if (label === undefined)
|
|
1044
|
-
payload['state'] = 'TOGGLE';
|
|
1045
|
-
else
|
|
1046
|
-
payload['state_' + label] = 'TOGGLE';
|
|
1047
|
-
zigbeeDevice.publishCommand('toggle', device.friendly_name, payload);
|
|
1062
|
+
zigbeeDevice.log.debug(`Command toggle called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint?.maybeNumber}`);
|
|
1063
|
+
zigbeeDevice.publishCommand('toggle', device.friendly_name, { state: 'TOGGLE' });
|
|
1048
1064
|
});
|
|
1049
1065
|
}
|
|
1050
1066
|
if (zigbeeDevice.bridgedDevice.hasClusterServer(LevelControlCluster.id) || zigbeeDevice.hasEndpoints) {
|
|
1051
1067
|
for (const child of zigbeeDevice.bridgedDevice.getChildEndpoints()) {
|
|
1052
1068
|
if (child.hasClusterServer(LevelControlCluster)) {
|
|
1053
1069
|
child.addCommandHandler('moveToLevel', async (data) => {
|
|
1054
|
-
zigbeeDevice.log.debug(`Command moveToLevel called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint
|
|
1070
|
+
zigbeeDevice.log.debug(`Command moveToLevel called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint?.maybeNumber} request: ${data.request.level} transition: ${data.request.transitionTime}`);
|
|
1055
1071
|
const payload = {};
|
|
1056
1072
|
payload['brightness_' + data.endpoint.uniqueStorageKey] = data.request.level;
|
|
1057
1073
|
if (zigbeeDevice.transition && data.request.transitionTime && data.request.transitionTime / 10 >= 1)
|
|
@@ -1059,7 +1075,7 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1059
1075
|
zigbeeDevice.publishCommand('moveToLevel', device.friendly_name, payload);
|
|
1060
1076
|
});
|
|
1061
1077
|
child.addCommandHandler('moveToLevelWithOnOff', async (data) => {
|
|
1062
|
-
zigbeeDevice.log.debug(`Command moveToLevelWithOnOff called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint
|
|
1078
|
+
zigbeeDevice.log.debug(`Command moveToLevelWithOnOff called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint?.maybeNumber} request: ${data.request.level} transition: ${data.request.transitionTime}`);
|
|
1063
1079
|
const payload = {};
|
|
1064
1080
|
payload['brightness_' + data.endpoint.uniqueStorageKey] = data.request.level;
|
|
1065
1081
|
if (zigbeeDevice.transition && data.request.transitionTime && data.request.transitionTime / 10 >= 1)
|
|
@@ -1069,25 +1085,15 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1069
1085
|
}
|
|
1070
1086
|
}
|
|
1071
1087
|
zigbeeDevice.bridgedDevice.addCommandHandler('moveToLevel', async (data) => {
|
|
1072
|
-
zigbeeDevice.log.debug(`Command moveToLevel called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint
|
|
1073
|
-
const payload = {};
|
|
1074
|
-
const label = zigbeeDevice.platform.matterbridge.edge ? undefined : data.endpoint.uniqueStorageKey;
|
|
1075
|
-
if (label === undefined)
|
|
1076
|
-
payload['brightness'] = data.request.level;
|
|
1077
|
-
else
|
|
1078
|
-
payload['brightness_' + label] = data.request.level;
|
|
1088
|
+
zigbeeDevice.log.debug(`Command moveToLevel called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint?.maybeNumber} request: ${data.request.level} transition: ${data.request.transitionTime}`);
|
|
1089
|
+
const payload = { brightness: data.request.level };
|
|
1079
1090
|
if (zigbeeDevice.transition && data.request.transitionTime && data.request.transitionTime / 10 >= 1)
|
|
1080
1091
|
payload['transition'] = Math.round(data.request.transitionTime / 10);
|
|
1081
1092
|
zigbeeDevice.publishCommand('moveToLevel', device.friendly_name, payload);
|
|
1082
1093
|
});
|
|
1083
1094
|
zigbeeDevice.bridgedDevice.addCommandHandler('moveToLevelWithOnOff', async (data) => {
|
|
1084
|
-
zigbeeDevice.log.debug(`Command moveToLevelWithOnOff called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint
|
|
1085
|
-
const payload = {};
|
|
1086
|
-
const label = zigbeeDevice.platform.matterbridge.edge ? undefined : data.endpoint.uniqueStorageKey;
|
|
1087
|
-
if (label === undefined)
|
|
1088
|
-
payload['brightness'] = data.request.level;
|
|
1089
|
-
else
|
|
1090
|
-
payload['brightness_' + label] = data.request.level;
|
|
1095
|
+
zigbeeDevice.log.debug(`Command moveToLevelWithOnOff called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint?.maybeNumber} request: ${data.request.level} transition: ${data.request.transitionTime}`);
|
|
1096
|
+
const payload = { brightness: data.request.level };
|
|
1091
1097
|
if (zigbeeDevice.transition && data.request.transitionTime && data.request.transitionTime / 10 >= 1)
|
|
1092
1098
|
payload['transition'] = Math.round(data.request.transitionTime / 10);
|
|
1093
1099
|
zigbeeDevice.publishCommand('moveToLevelWithOnOff', device.friendly_name, payload);
|
|
@@ -1097,7 +1103,15 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1097
1103
|
zigbeeDevice.bridgedDevice.addCommandHandler('moveToColorTemperature', async ({ request }) => {
|
|
1098
1104
|
zigbeeDevice.log.debug(`Command moveToColorTemperature called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} request: ${request.colorTemperatureMireds}`);
|
|
1099
1105
|
await zigbeeDevice.bridgedDevice?.setAttribute(ColorControlCluster.id, 'colorMode', ColorControl.ColorMode.ColorTemperatureMireds, zigbeeDevice.log);
|
|
1100
|
-
const payload = {
|
|
1106
|
+
const payload = {};
|
|
1107
|
+
if (zigbeeDevice.propertyMap.get('color_temp')) {
|
|
1108
|
+
payload['color_temp'] = request.colorTemperatureMireds;
|
|
1109
|
+
}
|
|
1110
|
+
else {
|
|
1111
|
+
const rgb = kelvinToRGB(miredToKelvin(request.colorTemperatureMireds));
|
|
1112
|
+
payload['color'] = { r: rgb.r, g: rgb.g, b: rgb.b };
|
|
1113
|
+
zigbeeDevice.log.info(`Command moveToColorTemperature called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${nf} but color_temp property is not available. Converting ${request.colorTemperatureMireds} to RGB ${debugStringify(payload['color'])}.`);
|
|
1114
|
+
}
|
|
1101
1115
|
if (zigbeeDevice.transition && request.transitionTime && request.transitionTime / 10 >= 1)
|
|
1102
1116
|
payload['transition'] = Math.round(request.transitionTime / 10);
|
|
1103
1117
|
zigbeeDevice.publishCommand('moveToColorTemperature', device.friendly_name, payload);
|
|
@@ -1156,7 +1170,7 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1156
1170
|
zigbeeDevice.bridgedDevice.addCommandHandler('upOrOpen', async () => {
|
|
1157
1171
|
zigbeeDevice.log.debug(`Command upOrOpen called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db}`);
|
|
1158
1172
|
if (zigbeeDevice.isDevice && zigbeeDevice.propertyMap.has('position'))
|
|
1159
|
-
zigbeeDevice.bridgedDevice?.setAttribute(WindowCoveringCluster.id, 'targetPositionLiftPercent100ths', 0, zigbeeDevice.log);
|
|
1173
|
+
await zigbeeDevice.bridgedDevice?.setAttribute(WindowCoveringCluster.id, 'targetPositionLiftPercent100ths', 0, zigbeeDevice.log);
|
|
1160
1174
|
else
|
|
1161
1175
|
await zigbeeDevice.bridgedDevice?.setWindowCoveringTargetAndCurrentPosition(0);
|
|
1162
1176
|
zigbeeDevice.publishCommand('upOrOpen', device.friendly_name, { state: 'OPEN' });
|
|
@@ -1164,7 +1178,7 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1164
1178
|
zigbeeDevice.bridgedDevice.addCommandHandler('downOrClose', async () => {
|
|
1165
1179
|
zigbeeDevice.log.debug(`Command downOrClose called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db}`);
|
|
1166
1180
|
if (zigbeeDevice.isDevice && zigbeeDevice.propertyMap.has('position'))
|
|
1167
|
-
zigbeeDevice.bridgedDevice?.setAttribute(WindowCoveringCluster.id, 'targetPositionLiftPercent100ths', 10000, zigbeeDevice.log);
|
|
1181
|
+
await zigbeeDevice.bridgedDevice?.setAttribute(WindowCoveringCluster.id, 'targetPositionLiftPercent100ths', 10000, zigbeeDevice.log);
|
|
1168
1182
|
else
|
|
1169
1183
|
await zigbeeDevice.bridgedDevice?.setWindowCoveringTargetAndCurrentPosition(10000);
|
|
1170
1184
|
zigbeeDevice.publishCommand('downOrClose', device.friendly_name, { state: 'CLOSE' });
|
|
@@ -1177,7 +1191,7 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1177
1191
|
zigbeeDevice.bridgedDevice.addCommandHandler('goToLiftPercentage', async ({ request: { liftPercent100thsValue } }) => {
|
|
1178
1192
|
zigbeeDevice.log.debug(`Command goToLiftPercentage called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} request liftPercent100thsValue: ${liftPercent100thsValue}`);
|
|
1179
1193
|
if (zigbeeDevice.isDevice && zigbeeDevice.propertyMap.has('position'))
|
|
1180
|
-
zigbeeDevice.bridgedDevice?.setAttribute(WindowCoveringCluster.id, 'targetPositionLiftPercent100ths', liftPercent100thsValue, zigbeeDevice.log);
|
|
1194
|
+
await zigbeeDevice.bridgedDevice?.setAttribute(WindowCoveringCluster.id, 'targetPositionLiftPercent100ths', liftPercent100thsValue, zigbeeDevice.log);
|
|
1181
1195
|
else
|
|
1182
1196
|
await zigbeeDevice.bridgedDevice?.setWindowCoveringTargetAndCurrentPosition(liftPercent100thsValue);
|
|
1183
1197
|
zigbeeDevice.publishCommand('goToLiftPercentage', device.friendly_name, { position: liftPercent100thsValue / 100 });
|
|
@@ -1202,7 +1216,7 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1202
1216
|
const t = zigbeeDevice.bridgedDevice?.getAttribute(ThermostatCluster.id, 'occupiedHeatingSetpoint', zigbeeDevice.log);
|
|
1203
1217
|
const setpoint = Math.round(t / 100 + request.amount / 10);
|
|
1204
1218
|
if (zigbeeDevice.propertyMap.has('current_heating_setpoint')) {
|
|
1205
|
-
zigbeeDevice.publishCommand('
|
|
1219
|
+
zigbeeDevice.publishCommand('CurrentHeatingSetpoint', device.friendly_name, { current_heating_setpoint: setpoint });
|
|
1206
1220
|
}
|
|
1207
1221
|
else if (zigbeeDevice.propertyMap.has('occupied_heating_setpoint')) {
|
|
1208
1222
|
zigbeeDevice.publishCommand('OccupiedHeatingSetpoint', device.friendly_name, { occupied_heating_setpoint: setpoint });
|
|
@@ -1212,7 +1226,7 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1212
1226
|
const t = zigbeeDevice.bridgedDevice?.getAttribute(ThermostatCluster.id, 'occupiedCoolingSetpoint', zigbeeDevice.log);
|
|
1213
1227
|
const setpoint = Math.round(t / 100 + request.amount / 10);
|
|
1214
1228
|
if (zigbeeDevice.propertyMap.has('current_heating_setpoint')) {
|
|
1215
|
-
zigbeeDevice.publishCommand('
|
|
1229
|
+
zigbeeDevice.publishCommand('CurrentCoolingSetpoint', device.friendly_name, { current_heating_setpoint: setpoint });
|
|
1216
1230
|
}
|
|
1217
1231
|
else if (zigbeeDevice.propertyMap.has('occupied_cooling_setpoint')) {
|
|
1218
1232
|
zigbeeDevice.publishCommand('OccupiedCoolingSetpoint', device.friendly_name, { occupied_cooling_setpoint: setpoint });
|
package/dist/platform.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MatterbridgeDynamicPlatform } from 'matterbridge';
|
|
1
|
+
import { addVirtualDevice, MatterbridgeDynamicPlatform } from 'matterbridge';
|
|
2
2
|
import { dn, gn, db, wr, zb, payloadStringify, rs, debugStringify, CYAN, er, nf } from 'matterbridge/logger';
|
|
3
3
|
import { isValidNumber, isValidString, waiter } from 'matterbridge/utils';
|
|
4
4
|
import { BridgedDeviceBasicInformation, DoorLock } from 'matterbridge/matter/clusters';
|
|
@@ -11,6 +11,7 @@ export class ZigbeePlatform extends MatterbridgeDynamicPlatform {
|
|
|
11
11
|
bridgedDevices = [];
|
|
12
12
|
zigbeeEntities = [];
|
|
13
13
|
injectTimer;
|
|
14
|
+
namePostfix = 1;
|
|
14
15
|
mqttHost = 'localhost';
|
|
15
16
|
mqttPort = 1883;
|
|
16
17
|
mqttTopic = 'zigbee2mqtt';
|
|
@@ -23,7 +24,6 @@ export class ZigbeePlatform extends MatterbridgeDynamicPlatform {
|
|
|
23
24
|
featureBlackList = [];
|
|
24
25
|
deviceFeatureBlackList = {};
|
|
25
26
|
postfix = '';
|
|
26
|
-
postfixHostname = true;
|
|
27
27
|
debugEnabled;
|
|
28
28
|
shouldStart;
|
|
29
29
|
shouldConfigure;
|
|
@@ -38,8 +38,8 @@ export class ZigbeePlatform extends MatterbridgeDynamicPlatform {
|
|
|
38
38
|
availabilityTimer;
|
|
39
39
|
constructor(matterbridge, log, config) {
|
|
40
40
|
super(matterbridge, log, config);
|
|
41
|
-
if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('
|
|
42
|
-
throw new Error(`This plugin requires Matterbridge version >= "
|
|
41
|
+
if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('3.0.3')) {
|
|
42
|
+
throw new Error(`This plugin requires Matterbridge version >= "3.0.3". Please update Matterbridge from ${this.matterbridge.matterbridgeVersion} to the latest version in the frontend."`);
|
|
43
43
|
}
|
|
44
44
|
this.debugEnabled = config.debug;
|
|
45
45
|
this.shouldStart = false;
|
|
@@ -69,7 +69,6 @@ export class ZigbeePlatform extends MatterbridgeDynamicPlatform {
|
|
|
69
69
|
if (config.postfix)
|
|
70
70
|
this.postfix = config.postfix;
|
|
71
71
|
this.postfix = this.postfix.trim().slice(0, 3);
|
|
72
|
-
this.postfixHostname = config.postfixHostname ?? true;
|
|
73
72
|
config.host = this.mqttHost;
|
|
74
73
|
config.port = this.mqttPort;
|
|
75
74
|
config.protocolVersion = this.mqttProtocol;
|
|
@@ -77,7 +76,16 @@ export class ZigbeePlatform extends MatterbridgeDynamicPlatform {
|
|
|
77
76
|
config.username = this.mqttUsername;
|
|
78
77
|
config.password = this.mqttPassword;
|
|
79
78
|
config.postfix = this.postfix;
|
|
80
|
-
config.postfixHostname
|
|
79
|
+
if (config.postfixHostname !== undefined)
|
|
80
|
+
delete config.postfixHostname;
|
|
81
|
+
if (config.deviceScenes !== undefined)
|
|
82
|
+
delete config.deviceScenes;
|
|
83
|
+
if (config.groupScenes !== undefined)
|
|
84
|
+
delete config.groupScenes;
|
|
85
|
+
if (config.scenesType === undefined)
|
|
86
|
+
config.scenesType = 'outlet';
|
|
87
|
+
if (config.scenesPrefix === undefined)
|
|
88
|
+
config.scenesPrefix = true;
|
|
81
89
|
if (config.type === 'MatterbridgeExtension') {
|
|
82
90
|
this.z2m = new Zigbee2MQTT(this.mqttHost, this.mqttPort, this.mqttTopic, this.mqttUsername, this.mqttPassword, this.mqttProtocol, this.debugEnabled);
|
|
83
91
|
this.z2m.setLogDebug(this.debugEnabled);
|
|
@@ -86,7 +94,6 @@ export class ZigbeePlatform extends MatterbridgeDynamicPlatform {
|
|
|
86
94
|
}
|
|
87
95
|
this.log.info(`Initializing platform: ${CYAN}${this.config.name}${nf} version: ${CYAN}${this.config.version}${rs}`);
|
|
88
96
|
this.log.info(`Loaded zigbee2mqtt parameters from ${CYAN}${path.join(matterbridge.matterbridgeDirectory, 'matterbridge-zigbee2mqtt.config.json')}${rs}`);
|
|
89
|
-
this.clearSelect();
|
|
90
97
|
this.z2m = new Zigbee2MQTT(this.mqttHost, this.mqttPort, this.mqttTopic, this.mqttUsername, this.mqttPassword, this.mqttProtocol, this.debugEnabled);
|
|
91
98
|
this.z2m.setLogDebug(this.debugEnabled);
|
|
92
99
|
this.z2m.setDataPath(path.join(matterbridge.matterbridgePluginDirectory, 'matterbridge-zigbee2mqtt'));
|
|
@@ -292,6 +299,9 @@ export class ZigbeePlatform extends MatterbridgeDynamicPlatform {
|
|
|
292
299
|
}
|
|
293
300
|
async onStart(reason) {
|
|
294
301
|
this.log.info(`Starting zigbee2mqtt dynamic platform v${this.version}: ` + reason);
|
|
302
|
+
await this.ready;
|
|
303
|
+
await this.clearSelect();
|
|
304
|
+
this.setSelectEntity('scenes', 'Scenes', 'component');
|
|
295
305
|
const hasOnline = await waiter('z2mBridgeOnline', () => this.z2mBridgeOnline !== undefined);
|
|
296
306
|
const hasInfo = await waiter('z2mBridgeInfo', () => this.z2mBridgeInfo !== undefined);
|
|
297
307
|
const hasDevices = await waiter('z2mBridgeDevices & z2mBridgeGroups', () => this.z2mBridgeDevices !== undefined || this.z2mBridgeGroups !== undefined);
|
|
@@ -333,12 +343,12 @@ export class ZigbeePlatform extends MatterbridgeDynamicPlatform {
|
|
|
333
343
|
this.log.info(`Configuring router ${bridgedEntity.bridgedDevice?.deviceName}.`);
|
|
334
344
|
if (this.z2mBridgeInfo?.permit_join) {
|
|
335
345
|
bridgedEntity.bridgedDevice?.setAttribute(DoorLock.Cluster.id, 'lockState', DoorLock.LockState.Unlocked, this.log);
|
|
336
|
-
if (bridgedEntity.bridgedDevice.
|
|
346
|
+
if (bridgedEntity.bridgedDevice.maybeNumber)
|
|
337
347
|
bridgedEntity.bridgedDevice?.triggerEvent(DoorLock.Cluster.id, 'lockOperation', { lockOperationType: DoorLock.LockOperationType.Unlock, operationSource: DoorLock.OperationSource.Manual, userIndex: null, fabricIndex: null, sourceNode: null }, this.log);
|
|
338
348
|
}
|
|
339
349
|
else {
|
|
340
350
|
bridgedEntity.bridgedDevice?.setAttribute(DoorLock.Cluster.id, 'lockState', DoorLock.LockState.Locked, this.log);
|
|
341
|
-
if (bridgedEntity.bridgedDevice.
|
|
351
|
+
if (bridgedEntity.bridgedDevice.maybeNumber)
|
|
342
352
|
bridgedEntity.bridgedDevice?.triggerEvent(DoorLock.Cluster.id, 'lockOperation', { lockOperationType: DoorLock.LockOperationType.Lock, operationSource: DoorLock.OperationSource.Manual, userIndex: null, fabricIndex: null, sourceNode: null }, this.log);
|
|
343
353
|
}
|
|
344
354
|
}
|
|
@@ -481,6 +491,22 @@ export class ZigbeePlatform extends MatterbridgeDynamicPlatform {
|
|
|
481
491
|
}
|
|
482
492
|
return matterGroup;
|
|
483
493
|
}
|
|
494
|
+
registerVirtualDevice(name, callback) {
|
|
495
|
+
let aggregator;
|
|
496
|
+
if (this.matterbridge.bridgeMode === 'bridge') {
|
|
497
|
+
aggregator = this.matterbridge.aggregatorNode;
|
|
498
|
+
}
|
|
499
|
+
else if (this.matterbridge.bridgeMode === 'childbridge') {
|
|
500
|
+
aggregator = this.matterbridge.plugins.get(this.name)?.aggregatorNode;
|
|
501
|
+
}
|
|
502
|
+
if (aggregator) {
|
|
503
|
+
if (aggregator.parts.has(name.replaceAll(' ', '') + ':' + this.config.scenesType)) {
|
|
504
|
+
this.log.warn(`Scene name ${name} already registered. Please use a different name. Changed to ${name + ' ' + this.namePostfix}`);
|
|
505
|
+
name = name + ' ' + this.namePostfix++;
|
|
506
|
+
}
|
|
507
|
+
addVirtualDevice(aggregator, name.slice(0, 32), this.config.scenesType, callback);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
484
510
|
async unregisterZigbeeEntity(friendly_name) {
|
|
485
511
|
const entity = this.zigbeeEntities.find((entity) => entity.entityName === friendly_name);
|
|
486
512
|
if (entity) {
|
|
@@ -119,28 +119,39 @@
|
|
|
119
119
|
"selectDeviceEntityFrom": "name"
|
|
120
120
|
}
|
|
121
121
|
},
|
|
122
|
-
"
|
|
123
|
-
"description": "
|
|
124
|
-
"type": "
|
|
125
|
-
"
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
122
|
+
"scenesType": {
|
|
123
|
+
"description": "Device type to use to expose scenes",
|
|
124
|
+
"type": "string",
|
|
125
|
+
"oneOf": [
|
|
126
|
+
{
|
|
127
|
+
"title": "Light",
|
|
128
|
+
"enum": ["light"]
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"title": "Outlet",
|
|
132
|
+
"enum": ["outlet"]
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"title": "Switch",
|
|
136
|
+
"enum": ["switch"]
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"title": "Mounted Switch",
|
|
140
|
+
"enum": ["mounted_switch"]
|
|
141
|
+
}
|
|
142
|
+
],
|
|
143
|
+
"default": "outlet"
|
|
144
|
+
},
|
|
145
|
+
"scenesPrefix": {
|
|
146
|
+
"description": "Add the device/group friendly name before the scene name.",
|
|
130
147
|
"type": "boolean",
|
|
131
|
-
"default":
|
|
132
|
-
"ui:widget": "hidden"
|
|
148
|
+
"default": true
|
|
133
149
|
},
|
|
134
150
|
"postfix": {
|
|
135
151
|
"description": "Add this unique postfix (3 characters max) to each device serial to avoid collision with other instances (you may loose the configuration of the devices in your controller when changing this value).",
|
|
136
152
|
"type": "string",
|
|
137
153
|
"default": ""
|
|
138
154
|
},
|
|
139
|
-
"postfixHostname": {
|
|
140
|
-
"description": "DEPRECATED: unique postfix added to each device identifier to avoid collision with other instances (you may loose the configuration of the devices in your controller when changing this value). Use postfix instead.",
|
|
141
|
-
"type": "boolean",
|
|
142
|
-
"default": true
|
|
143
|
-
},
|
|
144
155
|
"debug": {
|
|
145
156
|
"description": "Enable the debug for the plugin (development only)",
|
|
146
157
|
"type": "boolean",
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "matterbridge-zigbee2mqtt",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0-dev.2",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "matterbridge-zigbee2mqtt",
|
|
9
|
-
"version": "2.
|
|
9
|
+
"version": "2.5.0-dev.2",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"moment": "2.30.1",
|
|
13
|
-
"mqtt": "5.
|
|
13
|
+
"mqtt": "5.13.0",
|
|
14
14
|
"node-ansi-logger": "3.0.1",
|
|
15
15
|
"node-persist-manager": "1.0.8"
|
|
16
16
|
},
|
|
@@ -23,40 +23,27 @@
|
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
25
|
"node_modules/@babel/runtime": {
|
|
26
|
-
"version": "7.
|
|
27
|
-
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.
|
|
28
|
-
"integrity": "sha512-
|
|
26
|
+
"version": "7.27.1",
|
|
27
|
+
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz",
|
|
28
|
+
"integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==",
|
|
29
29
|
"license": "MIT",
|
|
30
|
-
"dependencies": {
|
|
31
|
-
"regenerator-runtime": "^0.14.0"
|
|
32
|
-
},
|
|
33
30
|
"engines": {
|
|
34
31
|
"node": ">=6.9.0"
|
|
35
32
|
}
|
|
36
33
|
},
|
|
37
34
|
"node_modules/@types/node": {
|
|
38
|
-
"version": "22.
|
|
39
|
-
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.
|
|
40
|
-
"integrity": "sha512-
|
|
35
|
+
"version": "22.15.21",
|
|
36
|
+
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.21.tgz",
|
|
37
|
+
"integrity": "sha512-EV/37Td6c+MgKAbkcLG6vqZ2zEYHD7bvSrzqqs2RIhbA6w3x+Dqz8MZM3sP6kGTeLrdoOgKZe+Xja7tUB2DNkQ==",
|
|
41
38
|
"license": "MIT",
|
|
42
39
|
"dependencies": {
|
|
43
|
-
"undici-types": "~6.
|
|
40
|
+
"undici-types": "~6.21.0"
|
|
44
41
|
}
|
|
45
42
|
},
|
|
46
43
|
"node_modules/@types/readable-stream": {
|
|
47
|
-
"version": "4.0.
|
|
48
|
-
"resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.
|
|
49
|
-
"integrity": "sha512-
|
|
50
|
-
"license": "MIT",
|
|
51
|
-
"dependencies": {
|
|
52
|
-
"@types/node": "*",
|
|
53
|
-
"safe-buffer": "~5.1.1"
|
|
54
|
-
}
|
|
55
|
-
},
|
|
56
|
-
"node_modules/@types/ws": {
|
|
57
|
-
"version": "8.18.0",
|
|
58
|
-
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.0.tgz",
|
|
59
|
-
"integrity": "sha512-8svvI3hMyvN0kKCJMvTJP/x6Y/EoQbepff882wL+Sn5QsXb3etnamgrJq4isrBxSJj5L2AuXcI0+bgkoAXGUJw==",
|
|
44
|
+
"version": "4.0.19",
|
|
45
|
+
"resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.19.tgz",
|
|
46
|
+
"integrity": "sha512-6Tgd3lMocKwOul/kwAAgSebkhdMCLhRvcJ6CKHA6wdql2qNIwK6hw3Y4PZQxn9HcJogoC/1ZOmkFM7OZKH/VrA==",
|
|
60
47
|
"license": "MIT",
|
|
61
48
|
"dependencies": {
|
|
62
49
|
"@types/node": "*"
|
|
@@ -172,9 +159,9 @@
|
|
|
172
159
|
}
|
|
173
160
|
},
|
|
174
161
|
"node_modules/debug": {
|
|
175
|
-
"version": "4.4.
|
|
176
|
-
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.
|
|
177
|
-
"integrity": "sha512-
|
|
162
|
+
"version": "4.4.1",
|
|
163
|
+
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
|
|
164
|
+
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
|
|
178
165
|
"license": "MIT",
|
|
179
166
|
"dependencies": {
|
|
180
167
|
"ms": "^2.1.3"
|
|
@@ -251,6 +238,19 @@
|
|
|
251
238
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
|
252
239
|
"license": "ISC"
|
|
253
240
|
},
|
|
241
|
+
"node_modules/ip-address": {
|
|
242
|
+
"version": "9.0.5",
|
|
243
|
+
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
|
|
244
|
+
"integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
|
|
245
|
+
"license": "MIT",
|
|
246
|
+
"dependencies": {
|
|
247
|
+
"jsbn": "1.1.0",
|
|
248
|
+
"sprintf-js": "^1.1.3"
|
|
249
|
+
},
|
|
250
|
+
"engines": {
|
|
251
|
+
"node": ">= 12"
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
254
|
"node_modules/js-sdsl": {
|
|
255
255
|
"version": "4.3.0",
|
|
256
256
|
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz",
|
|
@@ -261,6 +261,12 @@
|
|
|
261
261
|
"url": "https://opencollective.com/js-sdsl"
|
|
262
262
|
}
|
|
263
263
|
},
|
|
264
|
+
"node_modules/jsbn": {
|
|
265
|
+
"version": "1.1.0",
|
|
266
|
+
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
|
|
267
|
+
"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
|
|
268
|
+
"license": "MIT"
|
|
269
|
+
},
|
|
264
270
|
"node_modules/minimist": {
|
|
265
271
|
"version": "1.2.8",
|
|
266
272
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
|
@@ -280,24 +286,22 @@
|
|
|
280
286
|
}
|
|
281
287
|
},
|
|
282
288
|
"node_modules/mqtt": {
|
|
283
|
-
"version": "5.
|
|
284
|
-
"resolved": "https://registry.npmjs.org/mqtt/-/mqtt-5.
|
|
285
|
-
"integrity": "sha512-
|
|
289
|
+
"version": "5.13.0",
|
|
290
|
+
"resolved": "https://registry.npmjs.org/mqtt/-/mqtt-5.13.0.tgz",
|
|
291
|
+
"integrity": "sha512-pR+z+ChxFl3n8AKLQbTONVOOg/jl4KiKQRBAi78tjd6PksOWvl1nl9L8ZHOZ3MiavZfrUOjok2ddwc1VymGWRg==",
|
|
286
292
|
"license": "MIT",
|
|
287
293
|
"dependencies": {
|
|
288
|
-
"@types/readable-stream": "^4.0.18",
|
|
289
|
-
"@types/ws": "^8.5.14",
|
|
290
294
|
"commist": "^3.2.0",
|
|
291
295
|
"concat-stream": "^2.0.0",
|
|
292
296
|
"debug": "^4.4.0",
|
|
293
297
|
"help-me": "^5.0.0",
|
|
294
298
|
"lru-cache": "^10.4.3",
|
|
295
299
|
"minimist": "^1.2.8",
|
|
296
|
-
"mqtt-packet": "^9.0.
|
|
300
|
+
"mqtt-packet": "^9.0.2",
|
|
297
301
|
"number-allocator": "^1.0.14",
|
|
298
302
|
"readable-stream": "^4.7.0",
|
|
299
|
-
"reinterval": "^1.1.0",
|
|
300
303
|
"rfdc": "^1.4.1",
|
|
304
|
+
"socks": "^2.8.3",
|
|
301
305
|
"split2": "^4.2.0",
|
|
302
306
|
"worker-timers": "^7.1.8",
|
|
303
307
|
"ws": "^8.18.0"
|
|
@@ -431,18 +435,6 @@
|
|
|
431
435
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
|
432
436
|
}
|
|
433
437
|
},
|
|
434
|
-
"node_modules/regenerator-runtime": {
|
|
435
|
-
"version": "0.14.1",
|
|
436
|
-
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
|
437
|
-
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
|
|
438
|
-
"license": "MIT"
|
|
439
|
-
},
|
|
440
|
-
"node_modules/reinterval": {
|
|
441
|
-
"version": "1.1.0",
|
|
442
|
-
"resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz",
|
|
443
|
-
"integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==",
|
|
444
|
-
"license": "MIT"
|
|
445
|
-
},
|
|
446
438
|
"node_modules/rfdc": {
|
|
447
439
|
"version": "1.4.1",
|
|
448
440
|
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
|
|
@@ -450,11 +442,49 @@
|
|
|
450
442
|
"license": "MIT"
|
|
451
443
|
},
|
|
452
444
|
"node_modules/safe-buffer": {
|
|
453
|
-
"version": "5.1
|
|
454
|
-
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.
|
|
455
|
-
"integrity": "sha512-
|
|
445
|
+
"version": "5.2.1",
|
|
446
|
+
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
|
447
|
+
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
|
448
|
+
"funding": [
|
|
449
|
+
{
|
|
450
|
+
"type": "github",
|
|
451
|
+
"url": "https://github.com/sponsors/feross"
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
"type": "patreon",
|
|
455
|
+
"url": "https://www.patreon.com/feross"
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
"type": "consulting",
|
|
459
|
+
"url": "https://feross.org/support"
|
|
460
|
+
}
|
|
461
|
+
],
|
|
456
462
|
"license": "MIT"
|
|
457
463
|
},
|
|
464
|
+
"node_modules/smart-buffer": {
|
|
465
|
+
"version": "4.2.0",
|
|
466
|
+
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
|
|
467
|
+
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
|
|
468
|
+
"license": "MIT",
|
|
469
|
+
"engines": {
|
|
470
|
+
"node": ">= 6.0.0",
|
|
471
|
+
"npm": ">= 3.0.0"
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
"node_modules/socks": {
|
|
475
|
+
"version": "2.8.4",
|
|
476
|
+
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz",
|
|
477
|
+
"integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==",
|
|
478
|
+
"license": "MIT",
|
|
479
|
+
"dependencies": {
|
|
480
|
+
"ip-address": "^9.0.5",
|
|
481
|
+
"smart-buffer": "^4.2.0"
|
|
482
|
+
},
|
|
483
|
+
"engines": {
|
|
484
|
+
"node": ">= 10.0.0",
|
|
485
|
+
"npm": ">= 3.0.0"
|
|
486
|
+
}
|
|
487
|
+
},
|
|
458
488
|
"node_modules/split2": {
|
|
459
489
|
"version": "4.2.0",
|
|
460
490
|
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
|
|
@@ -464,6 +494,12 @@
|
|
|
464
494
|
"node": ">= 10.x"
|
|
465
495
|
}
|
|
466
496
|
},
|
|
497
|
+
"node_modules/sprintf-js": {
|
|
498
|
+
"version": "1.1.3",
|
|
499
|
+
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
|
|
500
|
+
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
|
|
501
|
+
"license": "BSD-3-Clause"
|
|
502
|
+
},
|
|
467
503
|
"node_modules/string_decoder": {
|
|
468
504
|
"version": "1.3.0",
|
|
469
505
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
|
@@ -473,26 +509,6 @@
|
|
|
473
509
|
"safe-buffer": "~5.2.0"
|
|
474
510
|
}
|
|
475
511
|
},
|
|
476
|
-
"node_modules/string_decoder/node_modules/safe-buffer": {
|
|
477
|
-
"version": "5.2.1",
|
|
478
|
-
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
|
479
|
-
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
|
480
|
-
"funding": [
|
|
481
|
-
{
|
|
482
|
-
"type": "github",
|
|
483
|
-
"url": "https://github.com/sponsors/feross"
|
|
484
|
-
},
|
|
485
|
-
{
|
|
486
|
-
"type": "patreon",
|
|
487
|
-
"url": "https://www.patreon.com/feross"
|
|
488
|
-
},
|
|
489
|
-
{
|
|
490
|
-
"type": "consulting",
|
|
491
|
-
"url": "https://feross.org/support"
|
|
492
|
-
}
|
|
493
|
-
],
|
|
494
|
-
"license": "MIT"
|
|
495
|
-
},
|
|
496
512
|
"node_modules/tslib": {
|
|
497
513
|
"version": "2.8.1",
|
|
498
514
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
|
@@ -506,9 +522,9 @@
|
|
|
506
522
|
"license": "MIT"
|
|
507
523
|
},
|
|
508
524
|
"node_modules/undici-types": {
|
|
509
|
-
"version": "6.
|
|
510
|
-
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.
|
|
511
|
-
"integrity": "sha512-
|
|
525
|
+
"version": "6.21.0",
|
|
526
|
+
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
|
527
|
+
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
|
512
528
|
"license": "MIT"
|
|
513
529
|
},
|
|
514
530
|
"node_modules/util-deprecate": {
|
|
@@ -552,9 +568,9 @@
|
|
|
552
568
|
}
|
|
553
569
|
},
|
|
554
570
|
"node_modules/ws": {
|
|
555
|
-
"version": "8.18.
|
|
556
|
-
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.
|
|
557
|
-
"integrity": "sha512-
|
|
571
|
+
"version": "8.18.2",
|
|
572
|
+
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz",
|
|
573
|
+
"integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==",
|
|
558
574
|
"license": "MIT",
|
|
559
575
|
"engines": {
|
|
560
576
|
"node": ">=10.0.0"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "matterbridge-zigbee2mqtt",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0-dev.2",
|
|
4
4
|
"description": "Matterbridge zigbee2mqtt plugin",
|
|
5
5
|
"author": "https://github.com/Luligu",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"moment": "2.30.1",
|
|
45
|
-
"mqtt": "5.
|
|
45
|
+
"mqtt": "5.13.0",
|
|
46
46
|
"node-ansi-logger": "3.0.1",
|
|
47
47
|
"node-persist-manager": "1.0.8"
|
|
48
48
|
}
|