matterbridge-zigbee2mqtt 3.1.0 → 3.2.0-dev-20260705-147850d
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 +22 -2
- package/README.md +4 -2
- package/dist/entity.js +95 -88
- package/dist/module.js +14 -14
- package/dist/zigbee2mqtt.js +24 -23
- package/npm-shrinkwrap.json +48 -48
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -9,9 +9,11 @@
|
|
|
9
9
|

|
|
10
10
|

|
|
11
11
|
[](https://codecov.io/gh/Luligu/matterbridge-zigbee2mqtt)
|
|
12
|
-
[](https://vitest.dev)
|
|
13
|
+
[](https://oxc.rs/docs/guide/usage/formatter.html)
|
|
14
|
+
[](https://oxc.rs/docs/guide/usage/linter.html)
|
|
14
15
|
[](https://www.typescriptlang.org/)
|
|
16
|
+
[](https://github.com/microsoft/typescript-go)
|
|
15
17
|
[](https://nodejs.org/)
|
|
16
18
|
[](https://matterbridge.io)
|
|
17
19
|
|
|
@@ -28,6 +30,24 @@ If you like this project and find it useful, please consider giving it a star on
|
|
|
28
30
|
|
|
29
31
|
<a href="https://www.buymeacoffee.com/luligugithub"><img src="https://matterbridge.io/assets/bmc-button.svg" alt="Buy me a coffee" width="120"></a>
|
|
30
32
|
|
|
33
|
+
## [3.2.0] - Dev branch
|
|
34
|
+
|
|
35
|
+
### Breaking changes
|
|
36
|
+
|
|
37
|
+
- [matterbridge]: Require matterbridge v.3.9.0.
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
- [toolchain]: Migrate to the native toolchain (tsgo + oxlint + oxfmt + vitest). Replace ESLint/Prettier/Jest with oxlint/oxfmt and Vitest.
|
|
42
|
+
- [vitest]: Move the tests from `src` to `vitest` and migrate them from Jest and `matterbridge/jestutils` to Vitest and `matterbridge/vitest-utils`.
|
|
43
|
+
- [vitest]: Update the test assertions for matterbridge v.3.9.x: endpoint names now use the device type name (i.e. `OnOffLightSwitch` instead of `MA-onoffswitch`) and `onOffLightSwitch` includes the `Binding` cluster.
|
|
44
|
+
- [package]: Update dependencies.
|
|
45
|
+
- [package]: Apply style.
|
|
46
|
+
- [package]: Bump `node-ansi-logger` to v.3.3.0.
|
|
47
|
+
- [package]: Bump `node-persist-manager` to v.2.1.0.
|
|
48
|
+
|
|
49
|
+
<a href="https://www.buymeacoffee.com/luligugithub"><img src="https://matterbridge.io/assets/bmc-button.svg" alt="Buy me a coffee" width="80"></a>
|
|
50
|
+
|
|
31
51
|
## [3.1.0] - 2026-06-07
|
|
32
52
|
|
|
33
53
|
### Breaking changes
|
package/README.md
CHANGED
|
@@ -9,9 +9,11 @@
|
|
|
9
9
|

|
|
10
10
|

|
|
11
11
|
[](https://codecov.io/gh/Luligu/matterbridge-zigbee2mqtt)
|
|
12
|
-
[](https://vitest.dev)
|
|
13
|
+
[](https://oxc.rs/docs/guide/usage/formatter.html)
|
|
14
|
+
[](https://oxc.rs/docs/guide/usage/linter.html)
|
|
14
15
|
[](https://www.typescriptlang.org/)
|
|
16
|
+
[](https://github.com/microsoft/typescript-go)
|
|
15
17
|
[](https://nodejs.org/)
|
|
16
18
|
[](https://matterbridge.io)
|
|
17
19
|
|
package/dist/entity.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import EventEmitter from 'node:events';
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
-
import { airQualitySensor, bridgedNode,
|
|
4
|
+
import { airQualitySensor, bridgedNode, colorDimmerSwitch, colorTemperatureLight, contactSensor, dimmableLight, dimmablePlugInUnit, dimmerSwitch, doorLock, electricalSensor, extendedColorLight, genericSwitch, humiditySensor, lightSensor, MatterbridgeEndpoint, occupancySensor, onOffLight, onOffLightSwitch, onOffPlugInUnit, powerSource, pressureSensor, rainSensor, smokeCoAlarm, temperatureSensor, thermostat, waterLeakDetector, windowCovering, } from 'matterbridge';
|
|
5
5
|
import { AnsiLogger, CYAN, db, debugStringify, dn, gn, hk, idn, ign, nf, or, rs, YELLOW, zb } from 'matterbridge/logger';
|
|
6
6
|
import { NumberTag, SwitchesTag } from 'matterbridge/matter';
|
|
7
7
|
import { AirQuality, BooleanState, BridgedDeviceBasicInformation, CarbonDioxideConcentrationMeasurement, CarbonMonoxideConcentrationMeasurement, ColorControl, DoorLock, ElectricalEnergyMeasurement, ElectricalPowerMeasurement, FormaldehydeConcentrationMeasurement, Identify, IlluminanceMeasurement, LevelControl, OccupancySensing, OnOff, Pm1ConcentrationMeasurement, Pm10ConcentrationMeasurement, Pm25ConcentrationMeasurement, PowerSource, PressureMeasurement, RelativeHumidityMeasurement, SmokeCoAlarm, TemperatureMeasurement, Thermostat, TotalVolatileOrganicCompoundsConcentrationMeasurement, WindowCovering, } from 'matterbridge/matter/clusters';
|
|
@@ -20,7 +20,7 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
20
20
|
en = '';
|
|
21
21
|
ien = '';
|
|
22
22
|
bridgedDevice;
|
|
23
|
-
eidn =
|
|
23
|
+
eidn = or;
|
|
24
24
|
lastPayload = {};
|
|
25
25
|
lastSeen = 0;
|
|
26
26
|
ignoreFeatures = [];
|
|
@@ -42,14 +42,14 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
42
42
|
constructor(platform, entity) {
|
|
43
43
|
super();
|
|
44
44
|
this.platform = platform;
|
|
45
|
-
if (entity
|
|
45
|
+
if (this.isValidDevice(entity)) {
|
|
46
46
|
this.device = entity;
|
|
47
47
|
this.entityName = entity.friendly_name;
|
|
48
48
|
this.isDevice = true;
|
|
49
49
|
this.en = dn;
|
|
50
50
|
this.ien = idn;
|
|
51
51
|
}
|
|
52
|
-
if (entity
|
|
52
|
+
if (this.isValidGroup(entity)) {
|
|
53
53
|
this.group = entity;
|
|
54
54
|
this.entityName = entity.friendly_name;
|
|
55
55
|
this.isGroup = true;
|
|
@@ -122,8 +122,7 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
122
122
|
`endpoint: ${CYAN}${propertyMap.endpoint === '' ? 'main' : propertyMap.endpoint}${db}`);
|
|
123
123
|
let z2m;
|
|
124
124
|
z2m = z2ms.find((z2m) => z2m.type === propertyMap?.type && z2m.property === propertyMap?.name);
|
|
125
|
-
|
|
126
|
-
z2m = z2ms.find((z2m) => z2m.property === propertyMap?.name);
|
|
125
|
+
z2m ??= z2ms.find((z2m) => z2m.property === propertyMap?.name);
|
|
127
126
|
if (z2m) {
|
|
128
127
|
if (z2m.valueLookup && propertyMap.values && propertyMap.values !== '' && typeof value === 'string' && !propertyMap.values.includes(value)) {
|
|
129
128
|
this.log.debug(`*Payload entry ${CYAN}${key}${db} value ${CYAN}${value}${db} not found in propertyMap values ${CYAN}${propertyMap.values}${db}`);
|
|
@@ -139,15 +138,15 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
139
138
|
}
|
|
140
139
|
else
|
|
141
140
|
this.log.debug(`*Payload entry ${CYAN}${key}${db} not found in propertyMap`);
|
|
142
|
-
if (key === 'action' && value !== '') {
|
|
143
|
-
const propertyMap = this.propertyMap.get(
|
|
141
|
+
if (key === 'action' && typeof value === 'string' && value !== '') {
|
|
142
|
+
const propertyMap = this.propertyMap.get('action_' + value);
|
|
144
143
|
if (propertyMap) {
|
|
145
144
|
const child = this.bridgedDevice.getChildEndpointById(propertyMap.endpoint);
|
|
146
|
-
if (child
|
|
145
|
+
if (child?.maybeNumber)
|
|
147
146
|
fireAndForget(child.triggerSwitchEvent(propertyMap.action, this.log), this.log, `Error triggering switch event ${propertyMap.action} on ${propertyMap.endpoint}`);
|
|
148
147
|
}
|
|
149
148
|
else
|
|
150
|
-
this.log.debug(`*Payload entry ${CYAN}${
|
|
149
|
+
this.log.debug(`*Payload entry ${CYAN}${'action_' + value}${db} not found in propertyMap`);
|
|
151
150
|
}
|
|
152
151
|
if (key === 'position' && this.isDevice && isValidNumber(value, 0, 100)) {
|
|
153
152
|
this.updateAttributeIfChanged(this.bridgedDevice, undefined, WindowCovering.id, 'currentPositionLiftPercent100ths', value * 100);
|
|
@@ -257,6 +256,12 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
257
256
|
this.mutableDevice.clear();
|
|
258
257
|
this.propertyMap.clear();
|
|
259
258
|
}
|
|
259
|
+
isValidDevice(entity) {
|
|
260
|
+
return 'ieee_address' in entity;
|
|
261
|
+
}
|
|
262
|
+
isValidGroup(entity) {
|
|
263
|
+
return 'id' in entity;
|
|
264
|
+
}
|
|
260
265
|
cachePublish(command = 'unknown', payload, transitionTime) {
|
|
261
266
|
if (command === 'moveToColorTemperature') {
|
|
262
267
|
delete this.cachePayload['color'];
|
|
@@ -286,17 +291,17 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
286
291
|
}, this.noUpdateTimeoutTime).unref();
|
|
287
292
|
}, this.cachePublishTimeoutTime).unref();
|
|
288
293
|
}
|
|
289
|
-
setCachePublishAttributes(endpoint, postfix
|
|
294
|
+
setCachePublishAttributes(endpoint, postfix) {
|
|
290
295
|
const brightness = endpoint.hasAttributeServer(LevelControl.id, 'currentLevel') ? Math.round((endpoint.getAttribute(LevelControl.id, 'currentLevel') / 254) * 255) : undefined;
|
|
291
296
|
if (isValidNumber(brightness, 1, 255))
|
|
292
|
-
this.cachePayload['brightness' + (postfix
|
|
297
|
+
this.cachePayload['brightness' + (postfix ?? '')] = brightness;
|
|
293
298
|
const color_temp = endpoint.hasClusterServer(ColorControl.id) &&
|
|
294
299
|
endpoint.hasAttributeServer(ColorControl.id, 'colorTemperatureMireds') &&
|
|
295
300
|
endpoint.getAttribute(ColorControl.id, 'colorMode') === ColorControl.ColorMode.ColorTemperatureMireds
|
|
296
301
|
? endpoint.getAttribute(ColorControl.id, 'colorTemperatureMireds')
|
|
297
302
|
: undefined;
|
|
298
303
|
if (isValidNumber(color_temp))
|
|
299
|
-
this.cachePayload['color_temp' + (postfix
|
|
304
|
+
this.cachePayload['color_temp' + (postfix ?? '')] = color_temp;
|
|
300
305
|
const hs_color = endpoint.hasClusterServer(ColorControl.id) &&
|
|
301
306
|
endpoint.hasAttributeServer(ColorControl.id, 'currentHue') &&
|
|
302
307
|
endpoint.hasAttributeServer(ColorControl.id, 'currentSaturation') &&
|
|
@@ -304,7 +309,7 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
304
309
|
? [Math.round((endpoint.getAttribute(ColorControl.id, 'currentHue') / 254) * 360), Math.round((endpoint.getAttribute(ColorControl.id, 'currentSaturation') / 254) * 100)]
|
|
305
310
|
: undefined;
|
|
306
311
|
if (isValidArray(hs_color, 2)) {
|
|
307
|
-
this.cachePayload['color' + (postfix
|
|
312
|
+
this.cachePayload['color' + (postfix ?? '')] = { h: hs_color[0], s: hs_color[1] };
|
|
308
313
|
}
|
|
309
314
|
const xy_color = endpoint.hasClusterServer(ColorControl.id) &&
|
|
310
315
|
endpoint.hasAttributeServer(ColorControl.id, 'currentX') &&
|
|
@@ -313,7 +318,7 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
313
318
|
? [endpoint.getAttribute(ColorControl.id, 'currentX') / 65535, endpoint.getAttribute(ColorControl.id, 'currentY') / 65535]
|
|
314
319
|
: undefined;
|
|
315
320
|
if (isValidArray(xy_color, 2))
|
|
316
|
-
this.cachePayload['color' + (postfix
|
|
321
|
+
this.cachePayload['color' + (postfix ?? '')] = { x: xy_color[0], y: xy_color[1] };
|
|
317
322
|
const lookupColorMode = [
|
|
318
323
|
'CurrentHueAndCurrentSaturation',
|
|
319
324
|
'CurrentXAndCurrentY',
|
|
@@ -470,11 +475,11 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
470
475
|
addBridgedDeviceBasicInformation() {
|
|
471
476
|
if (!this.bridgedDevice)
|
|
472
477
|
throw new Error('No bridged device');
|
|
473
|
-
const softwareVersion = parseInt(this.platform.z2mBridgeInfo?.version || '1');
|
|
478
|
+
const softwareVersion = Number.parseInt(this.platform.z2mBridgeInfo?.version || '1');
|
|
474
479
|
const softwareVersionString = `${this.platform.z2mBridgeInfo?.version} (commit ${this.platform.z2mBridgeInfo?.commit})`;
|
|
475
|
-
const hardwareVersion = parseInt(this.platform.matterbridge.matterbridgeVersion || '1');
|
|
480
|
+
const hardwareVersion = Number.parseInt(this.platform.matterbridge.matterbridgeVersion || '1');
|
|
476
481
|
const hardwareVersionString = this.platform.matterbridge.matterbridgeVersion || 'unknown';
|
|
477
|
-
if (this.isDevice && this.device
|
|
482
|
+
if (this.isDevice && this.device?.friendly_name === 'Coordinator') {
|
|
478
483
|
this.bridgedDevice.createDefaultBridgedDeviceBasicInformationClusterServer(this.device.friendly_name, this.serial, 0xfff1, 'zigbee2MQTT', 'Coordinator', softwareVersion, softwareVersionString, hardwareVersion, hardwareVersionString);
|
|
479
484
|
}
|
|
480
485
|
else if (this.isDevice && this.device) {
|
|
@@ -570,7 +575,7 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
570
575
|
return;
|
|
571
576
|
}
|
|
572
577
|
}
|
|
573
|
-
const localValue = deviceEndpoint.getAttribute(ClusterId(clusterId), attributeName
|
|
578
|
+
const localValue = deviceEndpoint.getAttribute(ClusterId(clusterId), attributeName);
|
|
574
579
|
if (typeof value === 'object' ? deepEqual(value, localValue) : value === localValue) {
|
|
575
580
|
this.log.debug(`Skip update endpoint ${deviceEndpoint.name}:${deviceEndpoint.maybeNumber}${childEndpointName ? ' (' + childEndpointName + ')' : ''} ` +
|
|
576
581
|
`attribute ${getClusterNameById(ClusterId(clusterId))}.${attributeName} already ${typeof value === 'object' ? debugStringify(value) : value}`);
|
|
@@ -603,11 +608,11 @@ export class ZigbeeGroup extends ZigbeeEntity {
|
|
|
603
608
|
}
|
|
604
609
|
static async create(platform, group) {
|
|
605
610
|
const zigbeeGroup = new ZigbeeGroup(platform, group);
|
|
606
|
-
if (zigbeeGroup.platform.postfix
|
|
607
|
-
zigbeeGroup.serial = `group-${group.id}
|
|
611
|
+
if (zigbeeGroup.platform.postfix === '') {
|
|
612
|
+
zigbeeGroup.serial = `group-${group.id}`.slice(0, 32);
|
|
608
613
|
}
|
|
609
614
|
else {
|
|
610
|
-
zigbeeGroup.serial = `group-${group.id}`.slice(0, 32);
|
|
615
|
+
zigbeeGroup.serial = `group-${group.id}-${zigbeeGroup.platform.postfix}`.slice(0, 32);
|
|
611
616
|
}
|
|
612
617
|
platform.setSelectDevice(`group-${group.id}`, group.friendly_name, 'wifi');
|
|
613
618
|
let useState = false;
|
|
@@ -623,7 +628,8 @@ export class ZigbeeGroup extends ZigbeeEntity {
|
|
|
623
628
|
let isThermostat = false;
|
|
624
629
|
if (group.members.length === 0) {
|
|
625
630
|
zigbeeGroup.log.debug(`Group: ${gn}${group.friendly_name}${rs}${db} is a ${CYAN}virtual${db} group`);
|
|
626
|
-
zigbeeGroup.bridgedDevice = new MatterbridgeEndpoint([
|
|
631
|
+
zigbeeGroup.bridgedDevice = new MatterbridgeEndpoint([onOffLightSwitch, bridgedNode, powerSource], { id: group.friendly_name }, zigbeeGroup.log.logLevel === "debug");
|
|
632
|
+
zigbeeGroup.bridgedDevice.createDefaultOnOffClusterServer();
|
|
627
633
|
isSwitch = true;
|
|
628
634
|
zigbeeGroup.propertyMap.set('state', { name: 'state', type: 'switch', endpoint: '' });
|
|
629
635
|
}
|
|
@@ -646,10 +652,10 @@ export class ZigbeeGroup extends ZigbeeEntity {
|
|
|
646
652
|
isSwitch = true;
|
|
647
653
|
if (expose.type === 'light')
|
|
648
654
|
isLight = true;
|
|
649
|
-
useState = useState
|
|
650
|
-
useBrightness = useBrightness
|
|
651
|
-
useColor = useColor
|
|
652
|
-
useColorTemperature = useColorTemperature
|
|
655
|
+
useState = useState || feature.name === 'state' ? true : false;
|
|
656
|
+
useBrightness = useBrightness || feature.name === 'brightness' ? true : false;
|
|
657
|
+
useColor = useColor || feature.property === 'color' ? true : false;
|
|
658
|
+
useColorTemperature = useColorTemperature || feature.name === 'color_temp' ? true : false;
|
|
653
659
|
if (feature.value_min)
|
|
654
660
|
minColorTemperature = Math.min(minColorTemperature, feature.value_min);
|
|
655
661
|
if (feature.value_max)
|
|
@@ -668,7 +674,7 @@ export class ZigbeeGroup extends ZigbeeEntity {
|
|
|
668
674
|
}
|
|
669
675
|
});
|
|
670
676
|
device.definition?.options.forEach((option) => {
|
|
671
|
-
useTransition = useTransition
|
|
677
|
+
useTransition = useTransition || option.name === 'transition' ? true : false;
|
|
672
678
|
});
|
|
673
679
|
});
|
|
674
680
|
zigbeeGroup.log.debug(`Group ${gn}${group.friendly_name}${rs}${db} switch: ${CYAN}${isSwitch}${db} light: ${CYAN}${isLight}${db} cover: ${CYAN}${isCover}${db} thermostat: ${CYAN}${isThermostat}${db}`);
|
|
@@ -677,11 +683,11 @@ export class ZigbeeGroup extends ZigbeeEntity {
|
|
|
677
683
|
if (useState) {
|
|
678
684
|
deviceType = onOffLight;
|
|
679
685
|
if (platform.switchList.includes(group.friendly_name))
|
|
680
|
-
deviceType =
|
|
686
|
+
deviceType = onOffLightSwitch;
|
|
681
687
|
else if (platform.lightList.includes(group.friendly_name))
|
|
682
688
|
deviceType = onOffLight;
|
|
683
689
|
else if (platform.outletList.includes(group.friendly_name))
|
|
684
|
-
deviceType =
|
|
690
|
+
deviceType = onOffPlugInUnit;
|
|
685
691
|
zigbeeGroup.propertyMap.set('state', { name: 'state', type: isLight ? 'light' : 'switch', endpoint: '' });
|
|
686
692
|
}
|
|
687
693
|
if (useBrightness) {
|
|
@@ -700,13 +706,13 @@ export class ZigbeeGroup extends ZigbeeEntity {
|
|
|
700
706
|
zigbeeGroup.propertyMap.set('color', { name: 'color', type: 'light', endpoint: '' });
|
|
701
707
|
}
|
|
702
708
|
if (isCover) {
|
|
703
|
-
deviceType =
|
|
709
|
+
deviceType = windowCovering;
|
|
704
710
|
zigbeeGroup.propertyMap.set('state', { name: 'state', type: 'cover', endpoint: '' });
|
|
705
711
|
zigbeeGroup.propertyMap.set('position', { name: 'position', type: 'cover', endpoint: '' });
|
|
706
712
|
zigbeeGroup.propertyMap.set('moving', { name: 'moving', type: 'cover', endpoint: '' });
|
|
707
713
|
}
|
|
708
714
|
if (isThermostat) {
|
|
709
|
-
deviceType =
|
|
715
|
+
deviceType = thermostat;
|
|
710
716
|
zigbeeGroup.propertyMap.set('local_temperature', { name: 'local_temperature', type: 'climate', endpoint: '' });
|
|
711
717
|
zigbeeGroup.propertyMap.set('current_heating_setpoint', { name: 'current_heating_setpoint', type: 'climate', endpoint: '' });
|
|
712
718
|
zigbeeGroup.propertyMap.set('current_cooling_setpoint', { name: 'current_cooling_setpoint', type: 'climate', endpoint: '' });
|
|
@@ -716,6 +722,8 @@ export class ZigbeeGroup extends ZigbeeEntity {
|
|
|
716
722
|
if (!deviceType)
|
|
717
723
|
return zigbeeGroup;
|
|
718
724
|
zigbeeGroup.bridgedDevice = new MatterbridgeEndpoint([deviceType, bridgedNode, powerSource], { id: group.friendly_name }, zigbeeGroup.log.logLevel === "debug");
|
|
725
|
+
if (deviceType.code === onOffLightSwitch.code)
|
|
726
|
+
zigbeeGroup.bridgedDevice.createDefaultOnOffClusterServer();
|
|
719
727
|
}
|
|
720
728
|
if (!platform.featureBlackList?.includes('scenes') && !platform.deviceFeatureBlackList[group.friendly_name]?.includes('scenes')) {
|
|
721
729
|
for (const scene of group.scenes) {
|
|
@@ -729,7 +737,7 @@ export class ZigbeeGroup extends ZigbeeEntity {
|
|
|
729
737
|
}
|
|
730
738
|
zigbeeGroup.addBridgedDeviceBasicInformation();
|
|
731
739
|
zigbeeGroup.addPowerSource();
|
|
732
|
-
zigbeeGroup.bridgedDevice.
|
|
740
|
+
zigbeeGroup.bridgedDevice.addRequiredClusters();
|
|
733
741
|
if (!zigbeeGroup.bridgedDevice || !zigbeeGroup.verifyMutableDevice(zigbeeGroup.bridgedDevice))
|
|
734
742
|
return zigbeeGroup;
|
|
735
743
|
zigbeeGroup.mutableDevice.clear();
|
|
@@ -855,34 +863,34 @@ export class ZigbeeGroup extends ZigbeeEntity {
|
|
|
855
863
|
}
|
|
856
864
|
}
|
|
857
865
|
const z2ms = [
|
|
858
|
-
{ type: 'switch', name: 'state', property: 'state', deviceType:
|
|
859
|
-
{ type: 'switch', name: 'brightness', property: 'brightness', deviceType:
|
|
860
|
-
{ type: 'switch', name: 'color_hs', property: 'color_hs', deviceType:
|
|
861
|
-
{ type: 'switch', name: 'color_xy', property: 'color_xy', deviceType:
|
|
862
|
-
{ type: 'switch', name: 'color_temp', property: 'color_temp', deviceType:
|
|
863
|
-
{ type: 'outlet', name: 'state', property: 'state', deviceType:
|
|
864
|
-
{ type: 'outlet', name: 'brightness', property: 'brightness', deviceType:
|
|
865
|
-
{ type: 'light', name: 'state', property: 'state', deviceType: onOffLight, cluster: OnOff.id, attribute: 'onOff', converter: (value) => { return value === 'ON'
|
|
866
|
+
{ type: 'switch', name: 'state', property: 'state', deviceType: onOffLightSwitch, cluster: OnOff.id, attribute: 'onOff', converter: (value) => { return value === 'ON'; } },
|
|
867
|
+
{ type: 'switch', name: 'brightness', property: 'brightness', deviceType: dimmerSwitch, cluster: LevelControl.id, attribute: 'currentLevel', converter: (value) => { return Math.max(1, Math.min(254, value)); } },
|
|
868
|
+
{ type: 'switch', name: 'color_hs', property: 'color_hs', deviceType: colorDimmerSwitch, cluster: ColorControl.id, attribute: 'colorMode' },
|
|
869
|
+
{ type: 'switch', name: 'color_xy', property: 'color_xy', deviceType: colorDimmerSwitch, cluster: ColorControl.id, attribute: 'colorMode' },
|
|
870
|
+
{ type: 'switch', name: 'color_temp', property: 'color_temp', deviceType: colorDimmerSwitch, cluster: ColorControl.id, attribute: 'colorMode' },
|
|
871
|
+
{ type: 'outlet', name: 'state', property: 'state', deviceType: onOffPlugInUnit, cluster: OnOff.id, attribute: 'onOff', converter: (value) => { return value === 'ON'; } },
|
|
872
|
+
{ type: 'outlet', name: 'brightness', property: 'brightness', deviceType: dimmablePlugInUnit, cluster: LevelControl.id, attribute: 'currentLevel', converter: (value) => { return Math.max(1, Math.min(254, value)); } },
|
|
873
|
+
{ type: 'light', name: 'state', property: 'state', deviceType: onOffLight, cluster: OnOff.id, attribute: 'onOff', converter: (value) => { return value === 'ON'; } },
|
|
866
874
|
{ type: 'light', name: 'brightness', property: 'brightness', deviceType: dimmableLight, cluster: LevelControl.id, attribute: 'currentLevel', converter: (value) => { return Math.max(1, Math.min(254, value)); } },
|
|
867
875
|
{ type: 'light', name: 'color_hs', property: 'color_hs', deviceType: extendedColorLight, cluster: ColorControl.id, attribute: 'colorMode' },
|
|
868
876
|
{ type: 'light', name: 'color_xy', property: 'color_xy', deviceType: extendedColorLight, cluster: ColorControl.id, attribute: 'colorMode' },
|
|
869
877
|
{ type: 'light', name: 'color_temp', property: 'color_temp', deviceType: colorTemperatureLight, cluster: ColorControl.id, attribute: 'colorMode' },
|
|
870
|
-
{ type: 'cover', name: 'state', property: 'state', deviceType:
|
|
871
|
-
{ type: 'cover', name: 'moving', property: 'moving', deviceType:
|
|
872
|
-
{ type: 'cover', name: 'position', property: 'position', deviceType:
|
|
873
|
-
{ type: 'lock', name: 'state', property: 'state', deviceType:
|
|
874
|
-
{ type: 'climate', name: 'local_temperature', property: 'local_temperature', deviceType:
|
|
875
|
-
{ type: 'climate', name: 'current_heating_setpoint', property: 'current_heating_setpoint', deviceType:
|
|
876
|
-
{ type: 'climate', name: 'occupied_heating_setpoint', property: 'occupied_heating_setpoint', deviceType:
|
|
877
|
-
{ type: 'climate', name: 'occupied_cooling_setpoint', property: 'occupied_cooling_setpoint', deviceType:
|
|
878
|
-
{ type: 'climate', name: 'unoccupied_heating_setpoint', property: 'unoccupied_heating_setpoint', deviceType:
|
|
879
|
-
{ type: 'climate', name: 'unoccupied_cooling_setpoint', property: 'unoccupied_cooling_setpoint', deviceType:
|
|
880
|
-
{ type: 'climate', name: 'running_state', property: 'running_state', deviceType:
|
|
881
|
-
{ type: 'climate', name: 'system_mode', property: 'system_mode', deviceType:
|
|
882
|
-
{ type: '', name: 'min_temperature_limit', property: 'min_temperature_limit', deviceType:
|
|
883
|
-
{ type: '', name: 'max_temperature_limit', property: 'max_temperature_limit', deviceType:
|
|
884
|
-
{ type: '', name: 'min_heat_setpoint_limit', property: 'min_heat_setpoint_limit', deviceType:
|
|
885
|
-
{ type: '', name: 'max_heat_setpoint_limit', property: 'max_heat_setpoint_limit', deviceType:
|
|
878
|
+
{ type: 'cover', name: 'state', property: 'state', deviceType: windowCovering, cluster: WindowCovering.id, attribute: 'targetPositionLiftPercent100ths' },
|
|
879
|
+
{ type: 'cover', name: 'moving', property: 'moving', deviceType: windowCovering, cluster: WindowCovering.id, attribute: 'operationalStatus' },
|
|
880
|
+
{ type: 'cover', name: 'position', property: 'position', deviceType: windowCovering, cluster: WindowCovering.id, attribute: 'currentPositionLiftPercent100ths' },
|
|
881
|
+
{ type: 'lock', name: 'state', property: 'state', deviceType: doorLock, cluster: DoorLock.id, attribute: 'lockState', converter: (value) => { return value === 'LOCK' ? DoorLock.LockState.Locked : DoorLock.LockState.Unlocked; } },
|
|
882
|
+
{ type: 'climate', name: 'local_temperature', property: 'local_temperature', deviceType: thermostat, cluster: Thermostat.id, attribute: 'localTemperature', converter: (value) => { return Math.max(-5000, Math.min(5000, value * 100)); } },
|
|
883
|
+
{ type: 'climate', name: 'current_heating_setpoint', property: 'current_heating_setpoint', deviceType: thermostat, cluster: Thermostat.id, attribute: 'occupiedHeatingSetpoint' },
|
|
884
|
+
{ type: 'climate', name: 'occupied_heating_setpoint', property: 'occupied_heating_setpoint', deviceType: thermostat, cluster: Thermostat.id, attribute: 'occupiedHeatingSetpoint', converter: (value) => { return Math.max(-5000, Math.min(5000, value * 100)); } },
|
|
885
|
+
{ type: 'climate', name: 'occupied_cooling_setpoint', property: 'occupied_cooling_setpoint', deviceType: thermostat, cluster: Thermostat.id, attribute: 'occupiedCoolingSetpoint', converter: (value) => { return Math.max(-5000, Math.min(5000, value * 100)); } },
|
|
886
|
+
{ type: 'climate', name: 'unoccupied_heating_setpoint', property: 'unoccupied_heating_setpoint', deviceType: thermostat, cluster: Thermostat.id, attribute: 'occupiedHeatingSetpoint', converter: (value) => { return Math.max(-5000, Math.min(5000, value * 100)); } },
|
|
887
|
+
{ type: 'climate', name: 'unoccupied_cooling_setpoint', property: 'unoccupied_cooling_setpoint', deviceType: thermostat, cluster: Thermostat.id, attribute: 'occupiedCoolingSetpoint', converter: (value) => { return Math.max(-5000, Math.min(5000, value * 100)); } },
|
|
888
|
+
{ type: 'climate', name: 'running_state', property: 'running_state', deviceType: thermostat, cluster: Thermostat.id, attribute: 'thermostatRunningMode', valueLookup: ['idle', '', '', 'cool', 'heat'] },
|
|
889
|
+
{ type: 'climate', name: 'system_mode', property: 'system_mode', deviceType: thermostat, cluster: Thermostat.id, attribute: 'systemMode', valueLookup: ['off', 'auto', '', 'cool', 'heat', '', '', 'fan_only'] },
|
|
890
|
+
{ type: '', name: 'min_temperature_limit', property: 'min_temperature_limit', deviceType: thermostat, cluster: Thermostat.id, attribute: 'minHeatSetpointLimit', converter: (value) => { return Math.max(-5000, Math.min(5000, value * 100)); } },
|
|
891
|
+
{ type: '', name: 'max_temperature_limit', property: 'max_temperature_limit', deviceType: thermostat, cluster: Thermostat.id, attribute: 'maxHeatSetpointLimit', converter: (value) => { return Math.max(-5000, Math.min(5000, value * 100)); } },
|
|
892
|
+
{ type: '', name: 'min_heat_setpoint_limit', property: 'min_heat_setpoint_limit', deviceType: thermostat, cluster: Thermostat.id, attribute: 'minHeatSetpointLimit', converter: (value) => { return Math.max(-5000, Math.min(5000, value * 100)); } },
|
|
893
|
+
{ type: '', name: 'max_heat_setpoint_limit', property: 'max_heat_setpoint_limit', deviceType: thermostat, cluster: Thermostat.id, attribute: 'maxHeatSetpointLimit', converter: (value) => { return Math.max(-5000, Math.min(5000, value * 100)); } },
|
|
886
894
|
{ type: '', name: 'presence', property: 'presence', deviceType: occupancySensor, cluster: OccupancySensing.id, attribute: 'occupancy', converter: (value) => { return { occupied: value }; } },
|
|
887
895
|
{ type: '', name: 'occupancy', property: 'occupancy', deviceType: occupancySensor, cluster: OccupancySensing.id, attribute: 'occupancy', converter: (value) => { return { occupied: value }; } },
|
|
888
896
|
{ type: '', name: 'illuminance', property: 'illuminance', deviceType: lightSensor, cluster: IlluminanceMeasurement.id, attribute: 'measuredValue', converter: (value) => { return Math.round(Math.max(Math.min(10000 * Math.log10(value), 0xfffe), 0)); } },
|
|
@@ -920,7 +928,7 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
920
928
|
}
|
|
921
929
|
static async create(platform, device) {
|
|
922
930
|
const zigbeeDevice = new ZigbeeDevice(platform, device);
|
|
923
|
-
zigbeeDevice.serial =
|
|
931
|
+
zigbeeDevice.serial = device.ieee_address;
|
|
924
932
|
if (zigbeeDevice.platform.postfix !== '') {
|
|
925
933
|
zigbeeDevice.serial = `${zigbeeDevice.serial}-${zigbeeDevice.platform.postfix}`.slice(0, 32);
|
|
926
934
|
}
|
|
@@ -929,7 +937,7 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
929
937
|
(device.model_id.startsWith('SLZB-') && device.manufacturer === 'SMLIGHT')) {
|
|
930
938
|
zigbeeDevice.isRouter = true;
|
|
931
939
|
platform.setSelectDevice(device.ieee_address, device.friendly_name, 'wifi');
|
|
932
|
-
zigbeeDevice.bridgedDevice = new MatterbridgeEndpoint([
|
|
940
|
+
zigbeeDevice.bridgedDevice = new MatterbridgeEndpoint([doorLock, bridgedNode, powerSource], { id: device.friendly_name }, zigbeeDevice.log.logLevel === "debug");
|
|
933
941
|
zigbeeDevice.addBridgedDeviceBasicInformation();
|
|
934
942
|
zigbeeDevice.addPowerSource();
|
|
935
943
|
zigbeeDevice.bridgedDevice.addRequiredClusterServers();
|
|
@@ -984,8 +992,8 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
984
992
|
descriptions.push(feature.description ?? '');
|
|
985
993
|
labels.push(feature.label ?? '');
|
|
986
994
|
units.push(feature.unit ?? '');
|
|
987
|
-
value_mins.push(feature.value_min ?? NaN);
|
|
988
|
-
value_maxs.push(feature.value_max ?? NaN);
|
|
995
|
+
value_mins.push(feature.value_min ?? Number.NaN);
|
|
996
|
+
value_maxs.push(feature.value_max ?? Number.NaN);
|
|
989
997
|
values.push(feature.values ? feature.values.join('|') : '');
|
|
990
998
|
});
|
|
991
999
|
}
|
|
@@ -1002,8 +1010,8 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1002
1010
|
descriptions.push(expose.description ?? '');
|
|
1003
1011
|
labels.push(expose.label ?? '');
|
|
1004
1012
|
units.push(expose.unit ?? '');
|
|
1005
|
-
value_mins.push(expose.value_min ?? NaN);
|
|
1006
|
-
value_maxs.push(expose.value_max ?? NaN);
|
|
1013
|
+
value_mins.push(expose.value_min ?? Number.NaN);
|
|
1014
|
+
value_maxs.push(expose.value_max ?? Number.NaN);
|
|
1007
1015
|
values.push(expose.values ? expose.values.join('|') : '');
|
|
1008
1016
|
if (expose.name === 'action' && expose.values) {
|
|
1009
1017
|
zigbeeDevice.actions.push(...expose.values);
|
|
@@ -1019,8 +1027,8 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1019
1027
|
descriptions.push(option.description ?? '');
|
|
1020
1028
|
labels.push(option.label ?? '');
|
|
1021
1029
|
units.push(option.unit ?? '');
|
|
1022
|
-
value_mins.push(option.value_min ?? NaN);
|
|
1023
|
-
value_maxs.push(option.value_max ?? NaN);
|
|
1030
|
+
value_mins.push(option.value_min ?? Number.NaN);
|
|
1031
|
+
value_maxs.push(option.value_max ?? Number.NaN);
|
|
1024
1032
|
values.push(option.values ? option.values.join('|') : '');
|
|
1025
1033
|
});
|
|
1026
1034
|
if (platform.switchList.includes(device.friendly_name)) {
|
|
@@ -1077,14 +1085,14 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1077
1085
|
zigbeeDevice.log.debug(`Device ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${zb}${endpoint}${db} type: ${zb}${type}${db} property: ${zb}${name}${db} => deviceType: ${z2m.deviceType?.name} cluster: ${z2m.cluster} attribute: ${z2m.attribute}`);
|
|
1078
1086
|
zigbeeDevice.propertyMap.set(property, { name, type, endpoint, category, description, label, unit, value_min, value_max, values: value });
|
|
1079
1087
|
if (endpoint === '') {
|
|
1080
|
-
if (
|
|
1081
|
-
zigbeeDevice.mutableDevice.set(endpoint, { tagList: [], deviceTypes: [z2m.deviceType], clusterServersIds: [...z2m.deviceType.requiredServerClusters, ClusterId(z2m.cluster)], clusterServersOptions: [], clusterClientsIds: [], clusterClientsOptions: [] });
|
|
1082
|
-
}
|
|
1083
|
-
else {
|
|
1088
|
+
if (zigbeeDevice.mutableDevice.has(endpoint)) {
|
|
1084
1089
|
zigbeeDevice.mutableDevice.get(endpoint)?.deviceTypes.push(z2m.deviceType);
|
|
1085
1090
|
zigbeeDevice.mutableDevice.get(endpoint)?.clusterServersIds.push(...z2m.deviceType.requiredServerClusters);
|
|
1086
1091
|
zigbeeDevice.mutableDevice.get(endpoint)?.clusterServersIds.push(ClusterId(z2m.cluster));
|
|
1087
1092
|
}
|
|
1093
|
+
else {
|
|
1094
|
+
zigbeeDevice.mutableDevice.set(endpoint, { tagList: [], deviceTypes: [z2m.deviceType], clusterServersIds: [...z2m.deviceType.requiredServerClusters, ClusterId(z2m.cluster)], clusterServersOptions: [], clusterClientsIds: [], clusterClientsOptions: [] });
|
|
1095
|
+
}
|
|
1088
1096
|
}
|
|
1089
1097
|
else {
|
|
1090
1098
|
const tagList = [];
|
|
@@ -1101,13 +1109,13 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1101
1109
|
if (endpoint === 'l6')
|
|
1102
1110
|
tagList.push({ mfgCode: null, namespaceId: NumberTag.Six.namespaceId, tag: NumberTag.Six.tag, label: 'endpoint ' + endpoint });
|
|
1103
1111
|
tagList.push({ mfgCode: null, namespaceId: SwitchesTag.Custom.namespaceId, tag: SwitchesTag.Custom.tag, label: 'endpoint ' + endpoint });
|
|
1104
|
-
if (
|
|
1105
|
-
zigbeeDevice.mutableDevice.set(endpoint, { tagList, deviceTypes: [z2m.deviceType], clusterServersIds: [...z2m.deviceType.requiredServerClusters, ClusterId(z2m.cluster)], clusterServersOptions: [], clusterClientsIds: [], clusterClientsOptions: [] });
|
|
1106
|
-
}
|
|
1107
|
-
else {
|
|
1112
|
+
if (zigbeeDevice.mutableDevice.has(endpoint)) {
|
|
1108
1113
|
zigbeeDevice.mutableDevice.get(endpoint)?.deviceTypes.push(z2m.deviceType);
|
|
1109
1114
|
zigbeeDevice.mutableDevice.get(endpoint)?.clusterServersIds.push(...z2m.deviceType.requiredServerClusters, ClusterId(z2m.cluster));
|
|
1110
1115
|
}
|
|
1116
|
+
else {
|
|
1117
|
+
zigbeeDevice.mutableDevice.set(endpoint, { tagList, deviceTypes: [z2m.deviceType], clusterServersIds: [...z2m.deviceType.requiredServerClusters, ClusterId(z2m.cluster)], clusterServersOptions: [], clusterClientsIds: [], clusterClientsOptions: [] });
|
|
1118
|
+
}
|
|
1111
1119
|
if (zigbeeDevice.composedType === '')
|
|
1112
1120
|
zigbeeDevice.composedType = type;
|
|
1113
1121
|
zigbeeDevice.hasEndpoints = true;
|
|
@@ -1118,8 +1126,7 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1118
1126
|
if (name === 'action' && zigbeeDevice.actions.length) {
|
|
1119
1127
|
zigbeeDevice.log.info(`Device ${zigbeeDevice.ien}${device.friendly_name}${rs}${nf} has actions mapped to these switches on sub endpoints:`);
|
|
1120
1128
|
zigbeeDevice.log.info(' controller events <=> zigbee2mqtt actions');
|
|
1121
|
-
|
|
1122
|
-
zigbeeDevice.bridgedDevice = new MatterbridgeEndpoint([bridgedNode], { id: device.friendly_name }, zigbeeDevice.log.logLevel === "debug");
|
|
1129
|
+
zigbeeDevice.bridgedDevice ??= new MatterbridgeEndpoint([bridgedNode], { id: device.friendly_name }, zigbeeDevice.log.logLevel === "debug");
|
|
1123
1130
|
zigbeeDevice.hasEndpoints = true;
|
|
1124
1131
|
const switchMap = ['Single Press', 'Double Press', 'Long Press '];
|
|
1125
1132
|
const triggerMap = ['Single', 'Double', 'Long'];
|
|
@@ -1189,12 +1196,12 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1189
1196
|
device.deviceTypes.forEach((deviceType) => {
|
|
1190
1197
|
deviceTypesMap.set(deviceType.code, deviceType);
|
|
1191
1198
|
});
|
|
1192
|
-
if (deviceTypesMap.has(
|
|
1193
|
-
deviceTypesMap.delete(
|
|
1194
|
-
if (deviceTypesMap.has(
|
|
1195
|
-
deviceTypesMap.delete(
|
|
1196
|
-
if (deviceTypesMap.has(
|
|
1197
|
-
deviceTypesMap.delete(
|
|
1199
|
+
if (deviceTypesMap.has(onOffLightSwitch.code) && deviceTypesMap.has(dimmerSwitch.code))
|
|
1200
|
+
deviceTypesMap.delete(onOffLightSwitch.code);
|
|
1201
|
+
if (deviceTypesMap.has(dimmerSwitch.code) && deviceTypesMap.has(colorDimmerSwitch.code))
|
|
1202
|
+
deviceTypesMap.delete(dimmerSwitch.code);
|
|
1203
|
+
if (deviceTypesMap.has(onOffPlugInUnit.code) && deviceTypesMap.has(dimmablePlugInUnit.code))
|
|
1204
|
+
deviceTypesMap.delete(onOffPlugInUnit.code);
|
|
1198
1205
|
if (deviceTypesMap.has(onOffLight.code) && deviceTypesMap.has(dimmableLight.code))
|
|
1199
1206
|
deviceTypesMap.delete(onOffLight.code);
|
|
1200
1207
|
if (deviceTypesMap.has(dimmableLight.code) && deviceTypesMap.has(colorTemperatureLight.code))
|
|
@@ -1264,12 +1271,12 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1264
1271
|
if (mainEndpoint.clusterServersIds.includes(Thermostat.id)) {
|
|
1265
1272
|
const system_mode = zigbeeDevice.propertyMap.get('system_mode');
|
|
1266
1273
|
const system_mode_values = system_mode?.values;
|
|
1267
|
-
const heat = zigbeeDevice.propertyMap.get('occupied_heating_setpoint')
|
|
1268
|
-
const cool = zigbeeDevice.propertyMap.get('occupied_cooling_setpoint')
|
|
1269
|
-
const minHeating = heat
|
|
1270
|
-
const maxHeating = heat
|
|
1271
|
-
const minCooling = cool
|
|
1272
|
-
const maxCooling = cool
|
|
1274
|
+
const heat = zigbeeDevice.propertyMap.get('occupied_heating_setpoint') ?? zigbeeDevice.propertyMap.get('unoccupied_heating_setpoint');
|
|
1275
|
+
const cool = zigbeeDevice.propertyMap.get('occupied_cooling_setpoint') ?? zigbeeDevice.propertyMap.get('unoccupied_cooling_setpoint');
|
|
1276
|
+
const minHeating = heat?.value_min !== undefined && !Number.isNaN(heat.value_min) ? heat.value_min : 0;
|
|
1277
|
+
const maxHeating = heat?.value_max !== undefined && !Number.isNaN(heat.value_max) ? heat.value_max : 50;
|
|
1278
|
+
const minCooling = cool?.value_min !== undefined && !Number.isNaN(cool.value_min) ? cool.value_min : 0;
|
|
1279
|
+
const maxCooling = cool?.value_max !== undefined && !Number.isNaN(cool.value_max) ? cool.value_max : 50;
|
|
1273
1280
|
zigbeeDevice.log.debug(`Configuring device ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} Thermostat cluster with heating ${CYAN}${heat ? 'supported' : '(un)occupied not supported'}${db} cooling ${CYAN}${cool ? 'supported' : '(un)occupied not supported'}${db} ` +
|
|
1274
1281
|
`system_mode ${CYAN}${system_mode_values ?? 'not supported'}${db} ` +
|
|
1275
1282
|
`minHeating ${CYAN}${minHeating}${db} maxHeating ${CYAN}${maxHeating}${db} minCooling ${CYAN}${minCooling}${db} maxCooling ${CYAN}${maxCooling}${db}`);
|
|
@@ -1414,7 +1421,7 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1414
1421
|
});
|
|
1415
1422
|
}
|
|
1416
1423
|
if (zigbeeDevice.bridgedDevice.hasClusterServer(Thermostat.id)) {
|
|
1417
|
-
zigbeeDevice.bridgedDevice.addCommandHandler('setpointRaiseLower', ({ request
|
|
1424
|
+
zigbeeDevice.bridgedDevice.addCommandHandler('setpointRaiseLower', ({ request }) => {
|
|
1418
1425
|
zigbeeDevice.log.debug(`Command setpointRaiseLower called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} request:`, request);
|
|
1419
1426
|
if (request.mode === Thermostat.SetpointRaiseLowerMode.Heat || request.mode === Thermostat.SetpointRaiseLowerMode.Both) {
|
|
1420
1427
|
const t = zigbeeDevice.bridgedDevice?.getAttribute(Thermostat.id, 'occupiedHeatingSetpoint', zigbeeDevice.log);
|
package/dist/module.js
CHANGED
|
@@ -2,7 +2,7 @@ import path from 'node:path';
|
|
|
2
2
|
import { MatterbridgeDynamicPlatform } from 'matterbridge';
|
|
3
3
|
import { CYAN, db, debugStringify, dn, er, gn, nf, payloadStringify, rs, wr, zb } from 'matterbridge/logger';
|
|
4
4
|
import { BridgedDeviceBasicInformation, DoorLock } from 'matterbridge/matter/clusters';
|
|
5
|
-
import { fireAndForget, isValidNumber, isValidString, waiter } from 'matterbridge/utils';
|
|
5
|
+
import { fireAndForget, getErrorMessage, isValidNumber, isValidString, waiter } from 'matterbridge/utils';
|
|
6
6
|
import { ZigbeeDevice, ZigbeeGroup } from './entity.js';
|
|
7
7
|
import { Zigbee2MQTT } from './zigbee2mqtt.js';
|
|
8
8
|
export default function initializePlugin(matterbridge, log, config) {
|
|
@@ -41,8 +41,8 @@ export class ZigbeePlatform extends MatterbridgeDynamicPlatform {
|
|
|
41
41
|
constructor(matterbridge, log, config) {
|
|
42
42
|
super(matterbridge, log, config);
|
|
43
43
|
this.config = config;
|
|
44
|
-
if (typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('3.
|
|
45
|
-
throw new Error(`This plugin requires Matterbridge version >= "3.
|
|
44
|
+
if (typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('3.9.0')) {
|
|
45
|
+
throw new Error(`This plugin requires Matterbridge version >= "3.9.0". Please update Matterbridge from ${this.matterbridge.matterbridgeVersion} to the latest version in the frontend."`);
|
|
46
46
|
}
|
|
47
47
|
this.shouldStart = false;
|
|
48
48
|
this.shouldConfigure = false;
|
|
@@ -81,6 +81,8 @@ export class ZigbeePlatform extends MatterbridgeDynamicPlatform {
|
|
|
81
81
|
this.postfix = config.postfix;
|
|
82
82
|
}
|
|
83
83
|
this.postfix = this.postfix.trim().slice(0, 3);
|
|
84
|
+
this.config.debug ??= false;
|
|
85
|
+
this.config.unregisterOnShutdown ??= false;
|
|
84
86
|
config.host = this.mqttHost;
|
|
85
87
|
config.port = this.mqttPort;
|
|
86
88
|
config.topic = this.mqttTopic;
|
|
@@ -93,10 +95,8 @@ export class ZigbeePlatform extends MatterbridgeDynamicPlatform {
|
|
|
93
95
|
delete config.deviceScenes;
|
|
94
96
|
if (config.groupScenes !== undefined)
|
|
95
97
|
delete config.groupScenes;
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
if (config.scenesPrefix === undefined)
|
|
99
|
-
config.scenesPrefix = true;
|
|
98
|
+
config.scenesType ??= 'outlet';
|
|
99
|
+
config.scenesPrefix ??= true;
|
|
100
100
|
this.log.info(`Initializing platform: ${CYAN}${this.config.name}${nf} version: ${CYAN}${this.config.version}${rs}`);
|
|
101
101
|
this.log.info(`Loaded zigbee2mqtt parameters from ${CYAN}${path.join(matterbridge.matterbridgeDirectory, 'matterbridge-zigbee2mqtt.config.json')}${rs}`);
|
|
102
102
|
this.z2m = new Zigbee2MQTT(this.mqttHost, this.mqttPort, this.mqttTopic, this.mqttUsername, this.mqttPassword, this.config.clientId, this.config.protocolVersion, this.config.ca, this.config.rejectUnauthorized, this.config.cert, this.config.key, config.debug);
|
|
@@ -142,9 +142,9 @@ export class ZigbeePlatform extends MatterbridgeDynamicPlatform {
|
|
|
142
142
|
this.log.info(`zigbee2MQTT version ${this.z2mBridgeInfo.version} zh version ${this.z2mBridgeInfo.zigbee_herdsman.version} zhc version ${this.z2mBridgeInfo.zigbee_herdsman_converters.version}`);
|
|
143
143
|
if (this.z2mBridgeInfo.config.advanced.output === 'attribute')
|
|
144
144
|
this.log.error(`zigbee2MQTT advanced.output must be 'json' or 'attribute_and_json'. Now is ${this.z2mBridgeInfo.config.advanced.output}`);
|
|
145
|
-
if (this.z2mBridgeInfo.config.advanced.legacy_api
|
|
145
|
+
if (this.z2mBridgeInfo.config.advanced.legacy_api)
|
|
146
146
|
this.log.info(`zigbee2MQTT advanced.legacy_api is ${this.z2mBridgeInfo.config.advanced.legacy_api}`);
|
|
147
|
-
if (this.z2mBridgeInfo.config.advanced.legacy_availability_payload
|
|
147
|
+
if (this.z2mBridgeInfo.config.advanced.legacy_availability_payload)
|
|
148
148
|
this.log.info(`zigbee2MQTT advanced.legacy_availability_payload is ${this.z2mBridgeInfo.config.advanced.legacy_availability_payload}`);
|
|
149
149
|
if (this.z2mBridgeInfo.config.frontend?.package)
|
|
150
150
|
this.log.info(`zigbee2MQTT frontend.package is ${this.z2mBridgeInfo.config.frontend?.package}`);
|
|
@@ -419,7 +419,7 @@ export class ZigbeePlatform extends MatterbridgeDynamicPlatform {
|
|
|
419
419
|
if (this.availabilityTimer)
|
|
420
420
|
clearInterval(this.availabilityTimer);
|
|
421
421
|
this.availabilityTimer = undefined;
|
|
422
|
-
if (this.config.unregisterOnShutdown
|
|
422
|
+
if (this.config.unregisterOnShutdown)
|
|
423
423
|
await this.unregisterAllDevices();
|
|
424
424
|
this.bridgedDevices = [];
|
|
425
425
|
this.zigbeeEntities = [];
|
|
@@ -437,7 +437,7 @@ export class ZigbeePlatform extends MatterbridgeDynamicPlatform {
|
|
|
437
437
|
requestDeviceUpdate(device) {
|
|
438
438
|
this.log.debug(`Requesting update for ${device.friendly_name} model_id: ${device.model_id} manufacturer: ${device.manufacturer}`);
|
|
439
439
|
const payload = {};
|
|
440
|
-
if (device.power_source === 'Battery' || !device.definition
|
|
440
|
+
if (device.power_source === 'Battery' || !device.definition?.exposes)
|
|
441
441
|
return;
|
|
442
442
|
for (const feature of device.definition.exposes) {
|
|
443
443
|
if (feature.features) {
|
|
@@ -485,7 +485,7 @@ export class ZigbeePlatform extends MatterbridgeDynamicPlatform {
|
|
|
485
485
|
this.log.warn(`Device ${dn}${device.friendly_name}${wr} ID: ${device.ieee_address} not registered`);
|
|
486
486
|
}
|
|
487
487
|
catch (error) {
|
|
488
|
-
this.log.error(`Error registering device ${dn}${device.friendly_name}${er} ID: ${device.ieee_address}: ${error}`);
|
|
488
|
+
this.log.error(`Error registering device ${dn}${device.friendly_name}${er} ID: ${device.ieee_address}: ${getErrorMessage(error)}`);
|
|
489
489
|
}
|
|
490
490
|
return matterDevice;
|
|
491
491
|
}
|
|
@@ -509,13 +509,13 @@ export class ZigbeePlatform extends MatterbridgeDynamicPlatform {
|
|
|
509
509
|
this.log.warn(`Group ${gn}${group.friendly_name}${wr} ID: ${group.id} not registered`);
|
|
510
510
|
}
|
|
511
511
|
catch (error) {
|
|
512
|
-
this.log.error(`Error registering group ${gn}${group.friendly_name}${er} ID: ${group.id}: ${error}`);
|
|
512
|
+
this.log.error(`Error registering group ${gn}${group.friendly_name}${er} ID: ${group.id}: ${getErrorMessage(error)}`);
|
|
513
513
|
}
|
|
514
514
|
return matterGroup;
|
|
515
515
|
}
|
|
516
516
|
async unregisterZigbeeEntity(friendly_name) {
|
|
517
517
|
const entity = this.zigbeeEntities.find((entity) => entity.entityName === friendly_name);
|
|
518
|
-
if (entity) {
|
|
518
|
+
if (entity?.bridgedDevice) {
|
|
519
519
|
this.log.info(`Removing device: ${friendly_name}`);
|
|
520
520
|
await this.unregisterDevice(entity.bridgedDevice);
|
|
521
521
|
entity.destroy();
|
package/dist/zigbee2mqtt.js
CHANGED
|
@@ -2,6 +2,7 @@ import crypto from 'node:crypto';
|
|
|
2
2
|
import { EventEmitter } from 'node:events';
|
|
3
3
|
import fs from 'node:fs';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
+
import { getErrorMessage, isErrnoException } from 'matterbridge/utils';
|
|
5
6
|
import { connectAsync } from 'mqtt';
|
|
6
7
|
import { AnsiLogger, db, dn, er, gn, hk, id, idn, ign, REVERSE, REVERSEOFF, rs, zb } from 'node-ansi-logger';
|
|
7
8
|
export class Zigbee2MQTT extends EventEmitter {
|
|
@@ -55,10 +56,7 @@ export class Zigbee2MQTT extends EventEmitter {
|
|
|
55
56
|
this.options.protocolVersion = protocolVersion;
|
|
56
57
|
if (mqttHost.startsWith('mqtts://') || mqttHost.startsWith('wss://')) {
|
|
57
58
|
this.log.debug('Using mqtts:// protocol for secure MQTT connection');
|
|
58
|
-
if (
|
|
59
|
-
this.log.info('When using mqtts:// protocol, you must provide the ca certificate for SSL/TLS connections with self-signed certificates.');
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
59
|
+
if (ca) {
|
|
62
60
|
try {
|
|
63
61
|
fs.accessSync(ca, fs.constants.R_OK);
|
|
64
62
|
this.options.ca = fs.readFileSync(ca);
|
|
@@ -68,7 +66,10 @@ export class Zigbee2MQTT extends EventEmitter {
|
|
|
68
66
|
this.log.error(`Error reading the CA certificate from ${ca}:`, error);
|
|
69
67
|
}
|
|
70
68
|
}
|
|
71
|
-
|
|
69
|
+
else {
|
|
70
|
+
this.log.info('When using mqtts:// protocol, you must provide the ca certificate for SSL/TLS connections with self-signed certificates.');
|
|
71
|
+
}
|
|
72
|
+
this.options.rejectUnauthorized = rejectUnauthorized;
|
|
72
73
|
this.log.info(`TLS rejectUnauthorized is set to ${this.options.rejectUnauthorized}`);
|
|
73
74
|
if (cert && key) {
|
|
74
75
|
try {
|
|
@@ -121,7 +122,7 @@ export class Zigbee2MQTT extends EventEmitter {
|
|
|
121
122
|
this.z2mPermitJoin = false;
|
|
122
123
|
this.z2mPermitJoinTimeout = 0;
|
|
123
124
|
this.z2mVersion = '';
|
|
124
|
-
this.z2mBridge =
|
|
125
|
+
this.z2mBridge = undefined;
|
|
125
126
|
this.z2mDevices = [];
|
|
126
127
|
this.z2mGroups = [];
|
|
127
128
|
this.log.debug(`Created new instance with host: ${mqttHost} port: ${mqttPort} protocol ${protocolVersion} topic: ${mqttTopic} username: ${mqttUsername !== undefined && mqttUsername !== '' ? mqttUsername : 'undefined'} password: ${mqttPassword !== undefined && mqttPassword !== '' ? '*****' : 'undefined'}`);
|
|
@@ -138,13 +139,12 @@ export class Zigbee2MQTT extends EventEmitter {
|
|
|
138
139
|
this.mqttDataPath = dataPath;
|
|
139
140
|
this.log.debug(`Data directory ${this.mqttDataPath} created successfully.`);
|
|
140
141
|
}
|
|
141
|
-
catch (
|
|
142
|
-
|
|
143
|
-
if (error.code === 'EEXIST') {
|
|
142
|
+
catch (error) {
|
|
143
|
+
if (isErrnoException(error) && error.code === 'EEXIST') {
|
|
144
144
|
this.log.debug('Data directory already exists');
|
|
145
145
|
}
|
|
146
146
|
else {
|
|
147
|
-
this.log.error(
|
|
147
|
+
this.log.error(`Error creating data directory: ${getErrorMessage(error)}`);
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
try {
|
|
@@ -152,21 +152,21 @@ export class Zigbee2MQTT extends EventEmitter {
|
|
|
152
152
|
fs.unlinkSync(filePath);
|
|
153
153
|
}
|
|
154
154
|
catch (error) {
|
|
155
|
-
this.log.debug(`Error deleting bridge-payloads.txt: ${error}`);
|
|
155
|
+
this.log.debug(`Error deleting bridge-payloads.txt: ${getErrorMessage(error)}`);
|
|
156
156
|
}
|
|
157
157
|
try {
|
|
158
158
|
const filePath = path.join(this.mqttDataPath, 'bridge-publish-payloads.txt');
|
|
159
159
|
fs.unlinkSync(filePath);
|
|
160
160
|
}
|
|
161
161
|
catch (error) {
|
|
162
|
-
this.log.debug(`Error deleting bridge-publish-payloads.txt: ${error}`);
|
|
162
|
+
this.log.debug(`Error deleting bridge-publish-payloads.txt: ${getErrorMessage(error)}`);
|
|
163
163
|
}
|
|
164
164
|
try {
|
|
165
165
|
const filePath = path.join(this.mqttDataPath, 'matter-commands.txt');
|
|
166
166
|
fs.unlinkSync(filePath);
|
|
167
167
|
}
|
|
168
168
|
catch (error) {
|
|
169
|
-
this.log.debug(`Error deleting matter-commands.txt: ${error}`);
|
|
169
|
+
this.log.debug(`Error deleting matter-commands.txt: ${getErrorMessage(error)}`);
|
|
170
170
|
}
|
|
171
171
|
}
|
|
172
172
|
getUrl() {
|
|
@@ -229,13 +229,13 @@ export class Zigbee2MQTT extends EventEmitter {
|
|
|
229
229
|
this.mqttKeepaliveInterval = setInterval(() => {
|
|
230
230
|
this.log.debug('Publishing keepalive MQTT message');
|
|
231
231
|
this.mqttClient?.publishAsync(`clients/${this.options.clientId}/heartbeat`, 'alive', { qos: 2 }).catch((error) => {
|
|
232
|
-
this.log.error(
|
|
232
|
+
this.log.error(`Error publishing keepalive MQTT message: ${getErrorMessage(error)}`);
|
|
233
233
|
});
|
|
234
234
|
}, (this.options.keepalive ?? 60) * 1000).unref();
|
|
235
235
|
return;
|
|
236
236
|
})
|
|
237
237
|
.catch((error) => {
|
|
238
|
-
this.log.error(`Error connecting to ${this.getUrl()}: ${error
|
|
238
|
+
this.log.error(`Error connecting to ${this.getUrl()}: ${getErrorMessage(error)}`);
|
|
239
239
|
this.emit('mqtt_error', error);
|
|
240
240
|
});
|
|
241
241
|
}
|
|
@@ -262,7 +262,7 @@ export class Zigbee2MQTT extends EventEmitter {
|
|
|
262
262
|
return;
|
|
263
263
|
})
|
|
264
264
|
.catch((error) => {
|
|
265
|
-
this.log.error(`Error closing connection: ${error
|
|
265
|
+
this.log.error(`Error closing connection: ${getErrorMessage(error)}`);
|
|
266
266
|
});
|
|
267
267
|
}
|
|
268
268
|
}
|
|
@@ -277,7 +277,7 @@ export class Zigbee2MQTT extends EventEmitter {
|
|
|
277
277
|
return;
|
|
278
278
|
})
|
|
279
279
|
.catch((error) => {
|
|
280
|
-
this.log.error(`Subscribe error: ${error} on topic: ${topic}`);
|
|
280
|
+
this.log.error(`Subscribe error: ${getErrorMessage(error)} on topic: ${topic}`);
|
|
281
281
|
});
|
|
282
282
|
}
|
|
283
283
|
else {
|
|
@@ -303,7 +303,7 @@ export class Zigbee2MQTT extends EventEmitter {
|
|
|
303
303
|
})
|
|
304
304
|
.catch((error) => {
|
|
305
305
|
this.mqttPublishInflights--;
|
|
306
|
-
this.log.error(`****Publish ${REVERSE}[${this.mqttPublishQueue.length}-${this.mqttPublishInflights}]${REVERSEOFF} error: ${error} on topic: ${topic} message: ${message} inflights: ${this.mqttPublishInflights}`);
|
|
306
|
+
this.log.error(`****Publish ${REVERSE}[${this.mqttPublishQueue.length}-${this.mqttPublishInflights}]${REVERSEOFF} error: ${getErrorMessage(error)} on topic: ${topic} message: ${message} inflights: ${this.mqttPublishInflights}`);
|
|
307
307
|
})
|
|
308
308
|
.finally(() => {
|
|
309
309
|
this.mqttPublishQueue.splice(0, 1);
|
|
@@ -342,7 +342,7 @@ export class Zigbee2MQTT extends EventEmitter {
|
|
|
342
342
|
}
|
|
343
343
|
})
|
|
344
344
|
.catch((error) => {
|
|
345
|
-
this.log.error(`****Publish ${REVERSE}[${this.mqttPublishInflights}]${REVERSEOFF} error: ${error} on topic: ${topic} message: ${message}`);
|
|
345
|
+
this.log.error(`****Publish ${REVERSE}[${this.mqttPublishInflights}]${REVERSEOFF} error: ${getErrorMessage(error)} on topic: ${topic} message: ${message}`);
|
|
346
346
|
})
|
|
347
347
|
.finally(() => {
|
|
348
348
|
this.mqttPublishInflights--;
|
|
@@ -375,7 +375,7 @@ export class Zigbee2MQTT extends EventEmitter {
|
|
|
375
375
|
writeFile(file, data) {
|
|
376
376
|
const filePath = path.join(this.mqttDataPath, file);
|
|
377
377
|
fs.promises
|
|
378
|
-
.writeFile(
|
|
378
|
+
.writeFile(filePath, data)
|
|
379
379
|
.then(() => {
|
|
380
380
|
this.log.debug(`Successfully wrote to ${filePath}`);
|
|
381
381
|
return;
|
|
@@ -428,9 +428,9 @@ export class Zigbee2MQTT extends EventEmitter {
|
|
|
428
428
|
this.log.debug(`Message bridge/info advanced.legacy_availability_payload => ${this.z2mBridge.config.advanced.legacy_availability_payload}`);
|
|
429
429
|
if (this.z2mBridge.config.advanced.output === 'attribute')
|
|
430
430
|
this.log.error(`Message bridge/info advanced.output must be 'json' or 'attribute_and_json'. Now is ${this.z2mBridge.config.advanced.output}`);
|
|
431
|
-
if (this.z2mBridge.config.advanced.legacy_api
|
|
431
|
+
if (this.z2mBridge.config.advanced.legacy_api)
|
|
432
432
|
this.log.info(`Message bridge/info advanced.legacy_api is ${this.z2mBridge.config.advanced.legacy_api}`);
|
|
433
|
-
if (this.z2mBridge.config.advanced.legacy_availability_payload
|
|
433
|
+
if (this.z2mBridge.config.advanced.legacy_availability_payload)
|
|
434
434
|
this.log.info(`Message bridge/info advanced.legacy_availability_payload is ${this.z2mBridge.config.advanced.legacy_availability_payload}`);
|
|
435
435
|
this.emit('bridge-info', this.z2mBridge);
|
|
436
436
|
if (this.log.logLevel === "debug")
|
|
@@ -761,7 +761,7 @@ export class Zigbee2MQTT extends EventEmitter {
|
|
|
761
761
|
handleResponseGroupAddMember(payload) {
|
|
762
762
|
const json = this.tryJsonParse(payload.toString());
|
|
763
763
|
this.log.debug(`handleResponseGroupAddMembers() add to group friendly_name ${json.data.group} device ieee_address ${json.data.device} status ${json.status}`);
|
|
764
|
-
if (json.status === 'ok' && json.data.device
|
|
764
|
+
if (json.status === 'ok' && json.data.device?.includes('/')) {
|
|
765
765
|
this.emit('group_add_member', json.data.group, json.data.device.split('/')[0], json.status);
|
|
766
766
|
}
|
|
767
767
|
}
|
|
@@ -801,6 +801,7 @@ export class Zigbee2MQTT extends EventEmitter {
|
|
|
801
801
|
this.log.debug(`handleEvent() type: device_interview name: ${json.data.friendly_name} address: ${json.data.ieee_address} status: ${json.data.status} supported: ${json.data.supported}`);
|
|
802
802
|
this.emit('device_interview', json.data.friendly_name, json.data.ieee_address, json.data.status, json.data.supported);
|
|
803
803
|
break;
|
|
804
|
+
default:
|
|
804
805
|
}
|
|
805
806
|
}
|
|
806
807
|
readConfig(filename) {
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "matterbridge-zigbee2mqtt",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0-dev-20260705-147850d",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "matterbridge-zigbee2mqtt",
|
|
9
|
-
"version": "3.
|
|
9
|
+
"version": "3.2.0-dev-20260705-147850d",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"moment": "2.30.1",
|
|
13
13
|
"mqtt": "5.15.1",
|
|
14
|
-
"node-ansi-logger": "3.
|
|
15
|
-
"node-persist-manager": "2.0
|
|
14
|
+
"node-ansi-logger": "3.3.0",
|
|
15
|
+
"node-persist-manager": "2.1.0"
|
|
16
16
|
},
|
|
17
17
|
"engines": {
|
|
18
18
|
"node": ">=20.19.0 <21.0.0 || >=22.13.0 <23.0.0 || >=24.0.0 <25.0.0 || >=26.0.0 <27.0.0"
|
|
@@ -32,18 +32,18 @@
|
|
|
32
32
|
}
|
|
33
33
|
},
|
|
34
34
|
"node_modules/@types/node": {
|
|
35
|
-
"version": "
|
|
36
|
-
"resolved": "https://registry.npmjs.org/@types/node/-/node-
|
|
37
|
-
"integrity": "sha512-
|
|
35
|
+
"version": "26.1.0",
|
|
36
|
+
"resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.0.tgz",
|
|
37
|
+
"integrity": "sha512-O0A1G3xPGy4w7AgQdAQYUlQ+BKk2Oovw8eRpofyp5KdBZULnbe+WqaOVNrm705SHphCiG4XHsACrSmPu1f+Kgw==",
|
|
38
38
|
"license": "MIT",
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"undici-types": "
|
|
40
|
+
"undici-types": "~8.3.0"
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
43
|
"node_modules/@types/readable-stream": {
|
|
44
|
-
"version": "4.0.
|
|
45
|
-
"resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.
|
|
46
|
-
"integrity": "sha512-
|
|
44
|
+
"version": "4.0.24",
|
|
45
|
+
"resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.24.tgz",
|
|
46
|
+
"integrity": "sha512-NRvUNC/JFGPJvqdAfEve8oginbM6V08u5NzLWpG8MwA2kTPOLnqk+wpwuPT+mp3aUsxyuT6m2gnrPuHYCruzEg==",
|
|
47
47
|
"license": "MIT",
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@types/node": "*"
|
|
@@ -103,15 +103,15 @@
|
|
|
103
103
|
}
|
|
104
104
|
},
|
|
105
105
|
"node_modules/broker-factory": {
|
|
106
|
-
"version": "3.1.
|
|
107
|
-
"resolved": "https://registry.npmjs.org/broker-factory/-/broker-factory-3.1.
|
|
108
|
-
"integrity": "sha512-
|
|
106
|
+
"version": "3.1.15",
|
|
107
|
+
"resolved": "https://registry.npmjs.org/broker-factory/-/broker-factory-3.1.15.tgz",
|
|
108
|
+
"integrity": "sha512-ko+aWvgNuP49meGrdjUu7rC+Y+Wai3cCPxP3xWwHsHfehFjOh5ZQM2yC4gEB2UddeZ/YXhm0K1eG/L6fxym2Og==",
|
|
109
109
|
"license": "MIT",
|
|
110
110
|
"dependencies": {
|
|
111
|
-
"@babel/runtime": "^7.29.
|
|
111
|
+
"@babel/runtime": "^7.29.7",
|
|
112
112
|
"fast-unique-numbers": "^9.0.27",
|
|
113
113
|
"tslib": "^2.8.1",
|
|
114
|
-
"worker-factory": "^7.0.
|
|
114
|
+
"worker-factory": "^7.0.50"
|
|
115
115
|
}
|
|
116
116
|
},
|
|
117
117
|
"node_modules/buffer": {
|
|
@@ -352,13 +352,13 @@
|
|
|
352
352
|
"license": "MIT"
|
|
353
353
|
},
|
|
354
354
|
"node_modules/node-ansi-logger": {
|
|
355
|
-
"version": "3.
|
|
356
|
-
"resolved": "https://registry.npmjs.org/node-ansi-logger/-/node-ansi-logger-3.
|
|
357
|
-
"integrity": "sha512-
|
|
355
|
+
"version": "3.3.0",
|
|
356
|
+
"resolved": "https://registry.npmjs.org/node-ansi-logger/-/node-ansi-logger-3.3.0.tgz",
|
|
357
|
+
"integrity": "sha512-ZW77lbZkA8h3r2HA2rcE5RjTIcwRDNB072RkZVyimGQpmEorJT8ajZ7UDhkHGoh0JRrCJL0iUKBE8q4oU8MHMg==",
|
|
358
358
|
"hasShrinkwrap": true,
|
|
359
359
|
"license": "Apache-2.0",
|
|
360
360
|
"engines": {
|
|
361
|
-
"node": ">=20.19.0 <21.0.0 || >=22.13.0 <23.0.0 || >=24.0.0 <25.0.0"
|
|
361
|
+
"node": ">=20.19.0 <21.0.0 || >=22.13.0 <23.0.0 || >=24.0.0 <25.0.0 || >=26.0.0 <27.0.0"
|
|
362
362
|
},
|
|
363
363
|
"funding": {
|
|
364
364
|
"type": "buymeacoffee",
|
|
@@ -366,16 +366,16 @@
|
|
|
366
366
|
}
|
|
367
367
|
},
|
|
368
368
|
"node_modules/node-persist-manager": {
|
|
369
|
-
"version": "2.0
|
|
370
|
-
"resolved": "https://registry.npmjs.org/node-persist-manager/-/node-persist-manager-2.0.
|
|
371
|
-
"integrity": "sha512-
|
|
369
|
+
"version": "2.1.0",
|
|
370
|
+
"resolved": "https://registry.npmjs.org/node-persist-manager/-/node-persist-manager-2.1.0.tgz",
|
|
371
|
+
"integrity": "sha512-LJze/Fcd8LijM4OMPnp0AQ+Z1e9mFMkjOEDw08xHA2HSRd2+N5s0uyH5ogYmXPC68f0sc4GrdKMpAcsHuO3PKA==",
|
|
372
372
|
"hasShrinkwrap": true,
|
|
373
373
|
"license": "Apache-2.0",
|
|
374
374
|
"dependencies": {
|
|
375
375
|
"node-persist": "4.0.4"
|
|
376
376
|
},
|
|
377
377
|
"engines": {
|
|
378
|
-
"node": ">=20.19.0 <21.0.0 || >=22.13.0 <23.0.0 || >=24.0.0 <25.0.0"
|
|
378
|
+
"node": ">=20.19.0 <21.0.0 || >=22.13.0 <23.0.0 || >=24.0.0 <25.0.0 || >=26.0.0 <27.0.0"
|
|
379
379
|
},
|
|
380
380
|
"funding": {
|
|
381
381
|
"type": "buymeacoffee",
|
|
@@ -543,9 +543,9 @@
|
|
|
543
543
|
"license": "MIT"
|
|
544
544
|
},
|
|
545
545
|
"node_modules/undici-types": {
|
|
546
|
-
"version": "
|
|
547
|
-
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-
|
|
548
|
-
"integrity": "sha512-
|
|
546
|
+
"version": "8.3.0",
|
|
547
|
+
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz",
|
|
548
|
+
"integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==",
|
|
549
549
|
"license": "MIT"
|
|
550
550
|
},
|
|
551
551
|
"node_modules/util-deprecate": {
|
|
@@ -555,50 +555,50 @@
|
|
|
555
555
|
"license": "MIT"
|
|
556
556
|
},
|
|
557
557
|
"node_modules/worker-factory": {
|
|
558
|
-
"version": "7.0.
|
|
559
|
-
"resolved": "https://registry.npmjs.org/worker-factory/-/worker-factory-7.0.
|
|
560
|
-
"integrity": "sha512-
|
|
558
|
+
"version": "7.0.50",
|
|
559
|
+
"resolved": "https://registry.npmjs.org/worker-factory/-/worker-factory-7.0.50.tgz",
|
|
560
|
+
"integrity": "sha512-hhwc0G+sFwM4qBuhJIUBn2p1Jf8v/FwmLUANBf/Q+Lt2uI8mfIZQhXaZQACodQD4R7Zp6cn/6702bIvNn2puJQ==",
|
|
561
561
|
"license": "MIT",
|
|
562
562
|
"dependencies": {
|
|
563
|
-
"@babel/runtime": "^7.29.
|
|
563
|
+
"@babel/runtime": "^7.29.7",
|
|
564
564
|
"fast-unique-numbers": "^9.0.27",
|
|
565
565
|
"tslib": "^2.8.1"
|
|
566
566
|
}
|
|
567
567
|
},
|
|
568
568
|
"node_modules/worker-timers": {
|
|
569
|
-
"version": "8.0.
|
|
570
|
-
"resolved": "https://registry.npmjs.org/worker-timers/-/worker-timers-8.0.
|
|
571
|
-
"integrity": "sha512-
|
|
569
|
+
"version": "8.0.33",
|
|
570
|
+
"resolved": "https://registry.npmjs.org/worker-timers/-/worker-timers-8.0.33.tgz",
|
|
571
|
+
"integrity": "sha512-RQVlKkek80v8M6SHvdMKiywaXFmX3XTpYTXTw0r62PdXB06t74XNxcTuG8wsQwnjorAQymNQyyQ0rzv7PykEMQ==",
|
|
572
572
|
"license": "MIT",
|
|
573
573
|
"dependencies": {
|
|
574
|
-
"@babel/runtime": "^7.29.
|
|
574
|
+
"@babel/runtime": "^7.29.7",
|
|
575
575
|
"tslib": "^2.8.1",
|
|
576
|
-
"worker-timers-broker": "^8.0.
|
|
577
|
-
"worker-timers-worker": "^9.0.
|
|
576
|
+
"worker-timers-broker": "^8.0.18",
|
|
577
|
+
"worker-timers-worker": "^9.0.15"
|
|
578
578
|
}
|
|
579
579
|
},
|
|
580
580
|
"node_modules/worker-timers-broker": {
|
|
581
|
-
"version": "8.0.
|
|
582
|
-
"resolved": "https://registry.npmjs.org/worker-timers-broker/-/worker-timers-broker-8.0.
|
|
583
|
-
"integrity": "sha512-
|
|
581
|
+
"version": "8.0.18",
|
|
582
|
+
"resolved": "https://registry.npmjs.org/worker-timers-broker/-/worker-timers-broker-8.0.18.tgz",
|
|
583
|
+
"integrity": "sha512-FrjzDVX1wKfZN0gRbCFqv8VHuTncG4sbI/WGEg4tSSQeIsnwqg4YBYWMAHYLJtUDEYYmiK65UKFrVMVk2irDSg==",
|
|
584
584
|
"license": "MIT",
|
|
585
585
|
"dependencies": {
|
|
586
|
-
"@babel/runtime": "^7.29.
|
|
587
|
-
"broker-factory": "^3.1.
|
|
586
|
+
"@babel/runtime": "^7.29.7",
|
|
587
|
+
"broker-factory": "^3.1.15",
|
|
588
588
|
"fast-unique-numbers": "^9.0.27",
|
|
589
589
|
"tslib": "^2.8.1",
|
|
590
|
-
"worker-timers-worker": "^9.0.
|
|
590
|
+
"worker-timers-worker": "^9.0.15"
|
|
591
591
|
}
|
|
592
592
|
},
|
|
593
593
|
"node_modules/worker-timers-worker": {
|
|
594
|
-
"version": "9.0.
|
|
595
|
-
"resolved": "https://registry.npmjs.org/worker-timers-worker/-/worker-timers-worker-9.0.
|
|
596
|
-
"integrity": "sha512
|
|
594
|
+
"version": "9.0.15",
|
|
595
|
+
"resolved": "https://registry.npmjs.org/worker-timers-worker/-/worker-timers-worker-9.0.15.tgz",
|
|
596
|
+
"integrity": "sha512-KKUe7lZ/Aignr51H6hOUik8LwTnIgojH/1lwhli8A8qIEIyewogZTpNpMW5B6BF7nmwBOkUoTYgf1H3QShcjSA==",
|
|
597
597
|
"license": "MIT",
|
|
598
598
|
"dependencies": {
|
|
599
|
-
"@babel/runtime": "^7.29.
|
|
599
|
+
"@babel/runtime": "^7.29.7",
|
|
600
600
|
"tslib": "^2.8.1",
|
|
601
|
-
"worker-factory": "^7.0.
|
|
601
|
+
"worker-factory": "^7.0.50"
|
|
602
602
|
}
|
|
603
603
|
},
|
|
604
604
|
"node_modules/ws": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "matterbridge-zigbee2mqtt",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0-dev-20260705-147850d",
|
|
4
4
|
"description": "Matterbridge zigbee2mqtt plugin",
|
|
5
5
|
"author": "https://github.com/Luligu",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"dependencies": {
|
|
69
69
|
"moment": "2.30.1",
|
|
70
70
|
"mqtt": "5.15.1",
|
|
71
|
-
"node-ansi-logger": "3.
|
|
72
|
-
"node-persist-manager": "2.0
|
|
71
|
+
"node-ansi-logger": "3.3.0",
|
|
72
|
+
"node-persist-manager": "2.1.0"
|
|
73
73
|
}
|
|
74
74
|
}
|