matterbridge-zigbee2mqtt 2.4.4 → 2.4.5-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 +14 -0
- package/dist/entity.js +48 -50
- package/npm-shrinkwrap.json +5 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,20 @@ If you like this project and find it useful, please consider giving it a star on
|
|
|
4
4
|
|
|
5
5
|
All notable changes to this project will be documented in this file.
|
|
6
6
|
|
|
7
|
+
## [2.4.5] - 2025-02-04
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- [package]: Updated dependencies.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- [endpoint]: Fix thermostat bug.
|
|
16
|
+
|
|
17
|
+
<a href="https://www.buymeacoffee.com/luligugithub">
|
|
18
|
+
<img src="./yellow-button.png" alt="Buy me a coffee" width="120">
|
|
19
|
+
</a>
|
|
20
|
+
|
|
7
21
|
## [2.4.4] - 2025-02-02
|
|
8
22
|
|
|
9
23
|
### Changed
|
package/dist/entity.js
CHANGED
|
@@ -5,12 +5,8 @@ import * as color from 'matterbridge/utils';
|
|
|
5
5
|
import { SwitchesTag, NumberTag } from 'matterbridge/matter';
|
|
6
6
|
import { getClusterNameById, ClusterId } from 'matterbridge/matter/types';
|
|
7
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';
|
|
8
|
-
import { PowerSourceBehavior } from 'matterbridge/matter/behaviors';
|
|
9
8
|
import EventEmitter from 'events';
|
|
10
9
|
import { hostname } from 'os';
|
|
11
|
-
function require(type, options) {
|
|
12
|
-
return { clusterId: ClusterId(1), options };
|
|
13
|
-
}
|
|
14
10
|
export class ZigbeeEntity extends EventEmitter {
|
|
15
11
|
log;
|
|
16
12
|
serial = '';
|
|
@@ -139,6 +135,12 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
139
135
|
this.updateAttributeIfChanged(this.bridgedDevice, undefined, WindowCovering.Cluster.id, 'targetPositionLiftPercent100ths', position);
|
|
140
136
|
}
|
|
141
137
|
}
|
|
138
|
+
if (key === 'current_heating_setpoint' && 'system_mode' in payload && payload['system_mode'] === 'heat' && isValidNumber(value)) {
|
|
139
|
+
this.updateAttributeIfChanged(this.bridgedDevice, undefined, Thermostat.Cluster.id, 'occupiedHeatingSetpoint', value * 100);
|
|
140
|
+
}
|
|
141
|
+
if (key === 'current_heating_setpoint' && 'system_mode' in payload && payload['system_mode'] === 'cool' && isValidNumber(value)) {
|
|
142
|
+
this.updateAttributeIfChanged(this.bridgedDevice, undefined, Thermostat.Cluster.id, 'occupiedCoolingSetpoint', value * 100);
|
|
143
|
+
}
|
|
142
144
|
if (key === 'color_temp' && 'color_mode' in payload && payload['color_mode'] === 'color_temp') {
|
|
143
145
|
this.updateAttributeIfChanged(this.bridgedDevice, undefined, ColorControl.Cluster.id, 'colorMode', ColorControl.ColorMode.ColorTemperatureMireds);
|
|
144
146
|
this.updateAttributeIfChanged(this.bridgedDevice, undefined, ColorControl.Cluster.id, 'colorTemperatureMireds', Math.max(147, Math.min(500, typeof value === 'number' ? value : 0)));
|
|
@@ -592,10 +594,11 @@ export const z2ms = [
|
|
|
592
594
|
{ type: 'cover', name: 'position', property: 'position', deviceType: coverDevice, cluster: WindowCovering.Cluster.id, attribute: 'currentPositionLiftPercent100ths' },
|
|
593
595
|
{ type: 'lock', name: 'state', property: 'state', deviceType: doorLockDevice, cluster: DoorLock.Cluster.id, attribute: 'lockState', converter: (value) => { return value === 'LOCK' ? DoorLock.LockState.Locked : DoorLock.LockState.Unlocked; } },
|
|
594
596
|
{ type: 'climate', name: 'local_temperature', property: 'local_temperature', deviceType: thermostatDevice, cluster: Thermostat.Cluster.id, attribute: 'localTemperature', converter: (value) => { return Math.max(-5000, Math.min(5000, value * 100)); } },
|
|
595
|
-
{ type: 'climate', name: 'current_heating_setpoint', property: 'current_heating_setpoint', deviceType: thermostatDevice, cluster: Thermostat.Cluster.id, attribute: 'occupiedHeatingSetpoint'
|
|
596
|
-
{ type: 'climate', name: 'current_cooling_setpoint', property: 'current_cooling_setpoint', deviceType: thermostatDevice, cluster: Thermostat.Cluster.id, attribute: 'occupiedCoolingSetpoint', converter: (value) => { return Math.max(-5000, Math.min(5000, value * 100)); } },
|
|
597
|
+
{ type: 'climate', name: 'current_heating_setpoint', property: 'current_heating_setpoint', deviceType: thermostatDevice, cluster: Thermostat.Cluster.id, attribute: 'occupiedHeatingSetpoint' },
|
|
597
598
|
{ type: 'climate', name: 'occupied_heating_setpoint', property: 'occupied_heating_setpoint', deviceType: thermostatDevice, cluster: Thermostat.Cluster.id, attribute: 'occupiedHeatingSetpoint', converter: (value) => { return Math.max(-5000, Math.min(5000, value * 100)); } },
|
|
598
599
|
{ type: 'climate', name: 'occupied_cooling_setpoint', property: 'occupied_cooling_setpoint', deviceType: thermostatDevice, cluster: Thermostat.Cluster.id, attribute: 'occupiedCoolingSetpoint', converter: (value) => { return Math.max(-5000, Math.min(5000, value * 100)); } },
|
|
600
|
+
{ type: 'climate', name: 'unoccupied_heating_setpoint', property: 'unoccupied_heating_setpoint', deviceType: thermostatDevice, cluster: Thermostat.Cluster.id, attribute: 'occupiedHeatingSetpoint', converter: (value) => { return Math.max(-5000, Math.min(5000, value * 100)); } },
|
|
601
|
+
{ type: 'climate', name: 'unoccupied_cooling_setpoint', property: 'unoccupied_cooling_setpoint', deviceType: thermostatDevice, cluster: Thermostat.Cluster.id, attribute: 'occupiedCoolingSetpoint', converter: (value) => { return Math.max(-5000, Math.min(5000, value * 100)); } },
|
|
599
602
|
{ type: 'climate', name: 'running_state', property: 'running_state', deviceType: thermostatDevice, cluster: Thermostat.Cluster.id, attribute: 'thermostatRunningMode', valueLookup: ['idle', '', '', 'cool', 'heat'] },
|
|
600
603
|
{ type: 'climate', name: 'system_mode', property: 'system_mode', deviceType: thermostatDevice, cluster: Thermostat.Cluster.id, attribute: 'systemMode', valueLookup: ['off', 'auto', '', 'cool', 'heat'] },
|
|
601
604
|
{ type: '', name: 'min_temperature_limit', property: 'min_temperature_limit', deviceType: thermostatDevice, cluster: Thermostat.Cluster.id, attribute: 'minHeatSetpointLimit', converter: (value) => { return Math.max(-5000, Math.min(5000, value * 100)); } },
|
|
@@ -890,45 +893,6 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
890
893
|
zigbeeDevice.addBridgedDeviceBasicInformation();
|
|
891
894
|
zigbeeDevice.addPowerSource();
|
|
892
895
|
mainEndpoint.clusterServersIds.splice(mainEndpoint.clusterServersIds.indexOf(PowerSource.Cluster.id), 1);
|
|
893
|
-
const options = require(PowerSourceBehavior.with(PowerSource.Feature.Wired), {
|
|
894
|
-
wiredCurrentType: PowerSource.WiredCurrentType.Ac,
|
|
895
|
-
description: 'AC Power',
|
|
896
|
-
status: PowerSource.PowerSourceStatus.Active,
|
|
897
|
-
order: 0,
|
|
898
|
-
endpointList: [],
|
|
899
|
-
});
|
|
900
|
-
mainEndpoint.clusterServersOptions.push(options);
|
|
901
|
-
if (mainEndpoint.clusterServersIds.includes(ColorControl.Cluster.id)) {
|
|
902
|
-
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')}`);
|
|
903
|
-
if (!names.includes('color_hs') && !names.includes('color_xy')) {
|
|
904
|
-
zigbeeDevice.bridgedDevice.createCtColorControlClusterServer();
|
|
905
|
-
mainEndpoint.clusterServersIds.splice(mainEndpoint.clusterServersIds.indexOf(ColorControl.Cluster.id), 1);
|
|
906
|
-
}
|
|
907
|
-
}
|
|
908
|
-
if (mainEndpoint.clusterServersIds.includes(Thermostat.Cluster.id)) {
|
|
909
|
-
const heat = zigbeeDevice.propertyMap.get('occupied_heating_setpoint') || zigbeeDevice.propertyMap.get('current_heating_setpoint');
|
|
910
|
-
const cool = zigbeeDevice.propertyMap.get('occupied_cooling_setpoint') || zigbeeDevice.propertyMap.get('current_cooling_setpoint');
|
|
911
|
-
const minHeating = heat && heat.value_min !== undefined && !isNaN(heat.value_min) ? heat.value_min : 0;
|
|
912
|
-
const maxHeating = heat && heat.value_max !== undefined && !isNaN(heat.value_max) ? heat.value_max : 50;
|
|
913
|
-
const minCooling = cool && cool.value_min !== undefined && !isNaN(cool.value_min) ? cool.value_min : 0;
|
|
914
|
-
const maxCooling = cool && cool.value_max !== undefined && !isNaN(cool.value_max) ? cool.value_max : 50;
|
|
915
|
-
zigbeeDevice.log.debug(`Configuring device ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} Thermostat cluster with heating ${CYAN}${heat ? 'supported' : 'not supported'}${db} cooling ${CYAN}${cool ? 'supported' : 'not supported'}${db} ` +
|
|
916
|
-
`minHeating ${CYAN}${minHeating}${db} maxHeating ${CYAN}${maxHeating}${db} minCooling ${CYAN}${minCooling}${db} maxCooling ${CYAN}${maxCooling}${db}`);
|
|
917
|
-
if (heat && !cool) {
|
|
918
|
-
zigbeeDevice.propertyMap.delete('running_state');
|
|
919
|
-
zigbeeDevice.bridgedDevice.createDefaultHeatingThermostatClusterServer(undefined, undefined, minHeating, maxHeating);
|
|
920
|
-
mainEndpoint.clusterServersIds.splice(mainEndpoint.clusterServersIds.indexOf(Thermostat.Cluster.id), 1);
|
|
921
|
-
}
|
|
922
|
-
else if (!heat && cool) {
|
|
923
|
-
zigbeeDevice.propertyMap.delete('running_state');
|
|
924
|
-
zigbeeDevice.bridgedDevice.createDefaultCoolingThermostatClusterServer(undefined, undefined, minCooling, maxCooling);
|
|
925
|
-
mainEndpoint.clusterServersIds.splice(mainEndpoint.clusterServersIds.indexOf(Thermostat.Cluster.id), 1);
|
|
926
|
-
}
|
|
927
|
-
else if (heat && cool) {
|
|
928
|
-
zigbeeDevice.bridgedDevice.createDefaultThermostatClusterServer(undefined, undefined, undefined, undefined, minHeating, maxHeating, minCooling, maxCooling);
|
|
929
|
-
mainEndpoint.clusterServersIds.splice(mainEndpoint.clusterServersIds.indexOf(Thermostat.Cluster.id), 1);
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
896
|
for (const [endpoint, device] of zigbeeDevice.mutableDevice) {
|
|
933
897
|
const deviceClusterServersIdMap = new Map();
|
|
934
898
|
device.clusterServersIds.forEach((clusterServer) => {
|
|
@@ -955,6 +919,40 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
955
919
|
zigbeeDevice.log.debug(`Device ${zigbeeDevice.ien}${zigbeeDevice.device?.friendly_name}${rs}${db} endpoint: ${ign}${endpoint === '' ? 'main' : endpoint}${rs}${db} => ` +
|
|
956
920
|
`${nf}tagList: ${debugStringify(device.tagList)} deviceTypes: ${debugStringify(device.deviceTypes)} clusterServersIds: ${debugStringify(device.clusterServersIds)}`);
|
|
957
921
|
}
|
|
922
|
+
if (mainEndpoint.clusterServersIds.includes(ColorControl.Cluster.id)) {
|
|
923
|
+
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')}`);
|
|
924
|
+
if (!names.includes('color_hs') && !names.includes('color_xy')) {
|
|
925
|
+
zigbeeDevice.bridgedDevice.createCtColorControlClusterServer();
|
|
926
|
+
mainEndpoint.clusterServersIds.splice(mainEndpoint.clusterServersIds.indexOf(ColorControl.Cluster.id), 1);
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
if (mainEndpoint.clusterServersIds.includes(Thermostat.Cluster.id)) {
|
|
930
|
+
const system_mode = zigbeeDevice.propertyMap.get('system_mode');
|
|
931
|
+
const system_mode_values = system_mode?.values;
|
|
932
|
+
const heat = zigbeeDevice.propertyMap.get('occupied_heating_setpoint') || zigbeeDevice.propertyMap.get('unoccupied_heating_setpoint');
|
|
933
|
+
const cool = zigbeeDevice.propertyMap.get('occupied_cooling_setpoint') || zigbeeDevice.propertyMap.get('unoccupied_cooling_setpoint');
|
|
934
|
+
const minHeating = heat && heat.value_min !== undefined && !isNaN(heat.value_min) ? heat.value_min : 0;
|
|
935
|
+
const maxHeating = heat && heat.value_max !== undefined && !isNaN(heat.value_max) ? heat.value_max : 50;
|
|
936
|
+
const minCooling = cool && cool.value_min !== undefined && !isNaN(cool.value_min) ? cool.value_min : 0;
|
|
937
|
+
const maxCooling = cool && cool.value_max !== undefined && !isNaN(cool.value_max) ? cool.value_max : 50;
|
|
938
|
+
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} ` +
|
|
939
|
+
`system_mode ${CYAN}${system_mode_values ?? 'not supported'}${db} ` +
|
|
940
|
+
`minHeating ${CYAN}${minHeating}${db} maxHeating ${CYAN}${maxHeating}${db} minCooling ${CYAN}${minCooling}${db} maxCooling ${CYAN}${maxCooling}${db}`);
|
|
941
|
+
if ((heat && !cool) || (!system_mode_values?.includes('auto') && system_mode_values?.includes('heat'))) {
|
|
942
|
+
zigbeeDevice.propertyMap.delete('running_state');
|
|
943
|
+
zigbeeDevice.bridgedDevice.createDefaultHeatingThermostatClusterServer(undefined, undefined, minHeating, maxHeating);
|
|
944
|
+
mainEndpoint.clusterServersIds.splice(mainEndpoint.clusterServersIds.indexOf(Thermostat.Cluster.id), 1);
|
|
945
|
+
}
|
|
946
|
+
else if ((!heat && cool) || (!system_mode_values?.includes('auto') && system_mode_values?.includes('cool'))) {
|
|
947
|
+
zigbeeDevice.propertyMap.delete('running_state');
|
|
948
|
+
zigbeeDevice.bridgedDevice.createDefaultCoolingThermostatClusterServer(undefined, undefined, minCooling, maxCooling);
|
|
949
|
+
mainEndpoint.clusterServersIds.splice(mainEndpoint.clusterServersIds.indexOf(Thermostat.Cluster.id), 1);
|
|
950
|
+
}
|
|
951
|
+
else {
|
|
952
|
+
zigbeeDevice.bridgedDevice.createDefaultThermostatClusterServer(undefined, undefined, undefined, undefined, minHeating, maxHeating, minCooling, maxCooling);
|
|
953
|
+
mainEndpoint.clusterServersIds.splice(mainEndpoint.clusterServersIds.indexOf(Thermostat.Cluster.id), 1);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
958
956
|
zigbeeDevice.bridgedDevice.addClusterServers(mainEndpoint.clusterServersIds);
|
|
959
957
|
zigbeeDevice.bridgedDevice.addRequiredClusterServers();
|
|
960
958
|
if (zigbeeDevice.composedType !== '')
|
|
@@ -1191,9 +1189,9 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1191
1189
|
if (request.mode === Thermostat.SetpointRaiseLowerMode.Cool || request.mode === Thermostat.SetpointRaiseLowerMode.Both) {
|
|
1192
1190
|
const t = zigbeeDevice.bridgedDevice?.getAttribute(ThermostatCluster.id, 'occupiedCoolingSetpoint', zigbeeDevice.log);
|
|
1193
1191
|
const setpoint = Math.round(t / 100 + request.amount / 10);
|
|
1194
|
-
if (zigbeeDevice.propertyMap.has('
|
|
1195
|
-
zigbeeDevice.publishCommand('OccupiedCoolingSetpoint', device.friendly_name, {
|
|
1196
|
-
zigbeeDevice.log.debug('Command setpointRaiseLower sent:', debugStringify({
|
|
1192
|
+
if (zigbeeDevice.propertyMap.has('current_heating_setpoint')) {
|
|
1193
|
+
zigbeeDevice.publishCommand('OccupiedCoolingSetpoint', device.friendly_name, { current_heating_setpoint: setpoint });
|
|
1194
|
+
zigbeeDevice.log.debug('Command setpointRaiseLower sent:', debugStringify({ current_heating_setpoint: setpoint }));
|
|
1197
1195
|
}
|
|
1198
1196
|
else if (zigbeeDevice.propertyMap.has('occupied_cooling_setpoint')) {
|
|
1199
1197
|
zigbeeDevice.publishCommand('OccupiedCoolingSetpoint', device.friendly_name, { occupied_cooling_setpoint: setpoint });
|
|
@@ -1225,8 +1223,8 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1225
1223
|
if (zigbeeDevice.bridgedDevice.hasAttributeServer(ThermostatCluster.id, 'occupiedCoolingSetpoint'))
|
|
1226
1224
|
zigbeeDevice.bridgedDevice.subscribeAttribute(ThermostatCluster.id, 'occupiedCoolingSetpoint', async (value) => {
|
|
1227
1225
|
zigbeeDevice.log.debug(`Subscribe occupiedCoolingSetpoint called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} with:`, value);
|
|
1228
|
-
if (zigbeeDevice.propertyMap.has('
|
|
1229
|
-
zigbeeDevice.publishCommand('OccupiedCoolingSetpoint', device.friendly_name, {
|
|
1226
|
+
if (zigbeeDevice.propertyMap.has('current_heating_setpoint'))
|
|
1227
|
+
zigbeeDevice.publishCommand('OccupiedCoolingSetpoint', device.friendly_name, { current_heating_setpoint: Math.round(value / 100) });
|
|
1230
1228
|
else if (zigbeeDevice.propertyMap.has('occupied_cooling_setpoint'))
|
|
1231
1229
|
zigbeeDevice.publishCommand('OccupiedCoolingSetpoint', device.friendly_name, { occupied_cooling_setpoint: Math.round(value / 100) });
|
|
1232
1230
|
zigbeeDevice.noUpdate = true;
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "matterbridge-zigbee2mqtt",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.5-dev.2",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "matterbridge-zigbee2mqtt",
|
|
9
|
-
"version": "2.4.
|
|
9
|
+
"version": "2.4.5-dev.2",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"moment": "2.30.1",
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
37
|
"node_modules/@types/node": {
|
|
38
|
-
"version": "22.13.
|
|
39
|
-
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.
|
|
40
|
-
"integrity": "sha512-
|
|
38
|
+
"version": "22.13.1",
|
|
39
|
+
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz",
|
|
40
|
+
"integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==",
|
|
41
41
|
"license": "MIT",
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"undici-types": "~6.20.0"
|