matterbridge-zigbee2mqtt 2.4.5-dev.2 → 2.4.5-dev.4

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 CHANGED
@@ -6,13 +6,17 @@ All notable changes to this project will be documented in this file.
6
6
 
7
7
  ## [2.4.5] - 2025-02-04
8
8
 
9
+ ### Added
10
+
11
+ - [thermostat]: Added fan_only mode (tested by https://github.com/robvanoostenrijk).
12
+
9
13
  ### Changed
10
14
 
11
15
  - [package]: Updated dependencies.
12
16
 
13
17
  ### Fixed
14
18
 
15
- - [endpoint]: Fix thermostat bug.
19
+ - [thermostat]: Fix thermostat bug (thanks https://github.com/robvanoostenrijk).
16
20
 
17
21
  <a href="https://www.buymeacoffee.com/luligugithub">
18
22
  <img src="./yellow-button.png" alt="Buy me a coffee" width="120">
package/dist/entity.js CHANGED
@@ -29,6 +29,7 @@ export class ZigbeeEntity extends EventEmitter {
29
29
  mutableDevice = new Map();
30
30
  colorTimeout = undefined;
31
31
  thermostatTimeout = undefined;
32
+ thermostatSystemModeLookup = ['off', 'auto', '', 'cool', 'heat', '', '', 'fan_only'];
32
33
  composedType = '';
33
34
  hasEndpoints = false;
34
35
  isRouter = false;
@@ -179,12 +180,18 @@ export class ZigbeeEntity extends EventEmitter {
179
180
  });
180
181
  }
181
182
  destroy() {
183
+ this.removeAllListeners();
182
184
  if (this.colorTimeout)
183
185
  clearTimeout(this.colorTimeout);
184
186
  this.colorTimeout = undefined;
185
187
  if (this.thermostatTimeout)
186
188
  clearTimeout(this.thermostatTimeout);
187
189
  this.thermostatTimeout = undefined;
190
+ this.device = undefined;
191
+ this.group = undefined;
192
+ this.bridgedDevice = undefined;
193
+ this.mutableDevice.clear();
194
+ this.propertyMap.clear();
188
195
  }
189
196
  addBridgedDeviceBasicInformation() {
190
197
  if (!this.bridgedDevice)
@@ -437,6 +444,7 @@ export class ZigbeeGroup extends ZigbeeEntity {
437
444
  zigbeeGroup.bridgedDevice.addRequiredClusterServers();
438
445
  if (!zigbeeGroup.bridgedDevice || !zigbeeGroup.verifyMutableDevice(zigbeeGroup.bridgedDevice))
439
446
  return zigbeeGroup;
447
+ zigbeeGroup.mutableDevice.clear();
440
448
  zigbeeGroup.logPropertyMap();
441
449
  if (isSwitch || isLight) {
442
450
  if (isSwitch && !isLight)
@@ -565,7 +573,7 @@ export class ZigbeeGroup extends ZigbeeEntity {
565
573
  zigbeeGroup.bridgedDevice.subscribeAttribute(ThermostatCluster.id, 'occupiedCoolingSetpoint', (newValue, oldValue) => {
566
574
  zigbeeGroup.bridgedDevice?.log.info(`Thermostat occupiedCoolingSetpoint changed from ${oldValue / 100} to ${newValue / 100}`);
567
575
  zigbeeGroup.bridgedDevice?.log.info(`Setting thermostat occupiedCoolingSetpoint to ${newValue / 100}`);
568
- zigbeeGroup.publishCommand('CurrentCoolingSetpoint', group.friendly_name, { current_cooling_setpoint: Math.round(newValue / 100) });
576
+ zigbeeGroup.publishCommand('CurrentCoolingSetpoint', group.friendly_name, { current_heating_setpoint: Math.round(newValue / 100) });
569
577
  zigbeeGroup.publishCommand('OccupiedCoolingSetpoint', group.friendly_name, { occupied_cooling_setpoint: Math.round(newValue / 100) });
570
578
  zigbeeGroup.noUpdate = true;
571
579
  zigbeeGroup.thermostatTimeout = setTimeout(() => {
@@ -600,7 +608,7 @@ export const z2ms = [
600
608
  { 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
609
  { 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)); } },
602
610
  { type: 'climate', name: 'running_state', property: 'running_state', deviceType: thermostatDevice, cluster: Thermostat.Cluster.id, attribute: 'thermostatRunningMode', valueLookup: ['idle', '', '', 'cool', 'heat'] },
603
- { type: 'climate', name: 'system_mode', property: 'system_mode', deviceType: thermostatDevice, cluster: Thermostat.Cluster.id, attribute: 'systemMode', valueLookup: ['off', 'auto', '', 'cool', 'heat'] },
611
+ { type: 'climate', name: 'system_mode', property: 'system_mode', deviceType: thermostatDevice, cluster: Thermostat.Cluster.id, attribute: 'systemMode', valueLookup: ['off', 'auto', '', 'cool', 'heat', '', '', 'fan_only'] },
604
612
  { 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)); } },
605
613
  { type: '', name: 'max_temperature_limit', property: 'max_temperature_limit', deviceType: thermostatDevice, cluster: Thermostat.Cluster.id, attribute: 'maxHeatSetpointLimit', converter: (value) => { return Math.max(-5000, Math.min(5000, value * 100)); } },
606
614
  { type: '', name: 'min_heat_setpoint_limit', property: 'min_heat_setpoint_limit', deviceType: thermostatDevice, cluster: Thermostat.Cluster.id, attribute: 'minHeatSetpointLimit', converter: (value) => { return Math.max(-5000, Math.min(5000, value * 100)); } },
@@ -1179,11 +1187,9 @@ export class ZigbeeDevice extends ZigbeeEntity {
1179
1187
  const setpoint = Math.round(t / 100 + request.amount / 10);
1180
1188
  if (zigbeeDevice.propertyMap.has('current_heating_setpoint')) {
1181
1189
  zigbeeDevice.publishCommand('OccupiedHeatingSetpoint', device.friendly_name, { current_heating_setpoint: setpoint });
1182
- zigbeeDevice.log.debug('Command setpointRaiseLower sent:', debugStringify({ current_heating_setpoint: setpoint }));
1183
1190
  }
1184
1191
  else if (zigbeeDevice.propertyMap.has('occupied_heating_setpoint')) {
1185
1192
  zigbeeDevice.publishCommand('OccupiedHeatingSetpoint', device.friendly_name, { occupied_heating_setpoint: setpoint });
1186
- zigbeeDevice.log.debug('Command setpointRaiseLower sent:', debugStringify({ occupied_heating_setpoint: setpoint }));
1187
1193
  }
1188
1194
  }
1189
1195
  if (request.mode === Thermostat.SetpointRaiseLowerMode.Cool || request.mode === Thermostat.SetpointRaiseLowerMode.Both) {
@@ -1191,22 +1197,22 @@ export class ZigbeeDevice extends ZigbeeEntity {
1191
1197
  const setpoint = Math.round(t / 100 + request.amount / 10);
1192
1198
  if (zigbeeDevice.propertyMap.has('current_heating_setpoint')) {
1193
1199
  zigbeeDevice.publishCommand('OccupiedCoolingSetpoint', device.friendly_name, { current_heating_setpoint: setpoint });
1194
- zigbeeDevice.log.debug('Command setpointRaiseLower sent:', debugStringify({ current_heating_setpoint: setpoint }));
1195
1200
  }
1196
1201
  else if (zigbeeDevice.propertyMap.has('occupied_cooling_setpoint')) {
1197
1202
  zigbeeDevice.publishCommand('OccupiedCoolingSetpoint', device.friendly_name, { occupied_cooling_setpoint: setpoint });
1198
- zigbeeDevice.log.debug('Command setpointRaiseLower sent:', debugStringify({ occupied_cooling_setpoint: setpoint }));
1199
1203
  }
1200
1204
  }
1201
1205
  });
1202
1206
  zigbeeDevice.bridgedDevice.subscribeAttribute(ThermostatCluster.id, 'systemMode', async (value) => {
1203
- zigbeeDevice.log.debug(`Subscribe systemMode called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} with:`, value);
1204
- const system_mode = value === Thermostat.SystemMode.Off ? 'off' : value === Thermostat.SystemMode.Heat ? 'heat' : 'cool';
1205
- zigbeeDevice.publishCommand('SystemMode', device.friendly_name, { system_mode });
1206
- zigbeeDevice.noUpdate = true;
1207
- zigbeeDevice.thermostatTimeout = setTimeout(() => {
1208
- zigbeeDevice.noUpdate = false;
1209
- }, 5 * 1000);
1207
+ if (isValidNumber(value, Thermostat.SystemMode.Off, Thermostat.SystemMode.FanOnly) && zigbeeDevice.thermostatSystemModeLookup[value] !== '') {
1208
+ const system_mode = zigbeeDevice.thermostatSystemModeLookup[value];
1209
+ zigbeeDevice.log.debug(`Subscribe systemMode called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} with ${value} => ${system_mode}`);
1210
+ zigbeeDevice.publishCommand('SystemMode', device.friendly_name, { system_mode });
1211
+ zigbeeDevice.noUpdate = true;
1212
+ zigbeeDevice.thermostatTimeout = setTimeout(() => {
1213
+ zigbeeDevice.noUpdate = false;
1214
+ }, 5 * 1000);
1215
+ }
1210
1216
  }, zigbeeDevice.log);
1211
1217
  if (zigbeeDevice.bridgedDevice.hasAttributeServer(ThermostatCluster.id, 'occupiedHeatingSetpoint'))
1212
1218
  zigbeeDevice.bridgedDevice.subscribeAttribute(ThermostatCluster.id, 'occupiedHeatingSetpoint', async (value) => {
package/dist/platform.js CHANGED
@@ -223,7 +223,7 @@ export class ZigbeePlatform extends MatterbridgeDynamicPlatform {
223
223
  this.z2m.on('device_interview', async (friendly_name, ieee_address, status, supported) => {
224
224
  this.log.info(`zigbee2MQTT sent device_interview device: ${friendly_name} ieee_address: ${ieee_address} status: ${status} supported: ${supported}`);
225
225
  if (status === 'successful' && supported) {
226
- if (!this.validateDeviceWhiteBlackList(friendly_name))
226
+ if (!this.validateDevice(friendly_name))
227
227
  return;
228
228
  this.log.info(`Registering device: ${friendly_name}`);
229
229
  const bridgedDevice = this.z2mBridgeDevices?.find((device) => device.friendly_name === friendly_name);
@@ -243,7 +243,7 @@ export class ZigbeePlatform extends MatterbridgeDynamicPlatform {
243
243
  });
244
244
  this.z2m.on('group_add', async (friendly_name, id, status) => {
245
245
  this.log.info(`zigbee2MQTT sent group_add friendly_name: ${friendly_name} id ${id} status ${status}`);
246
- if (!this.validateDeviceWhiteBlackList(friendly_name))
246
+ if (!this.validateDevice(friendly_name))
247
247
  return;
248
248
  this.log.info(`Registering group: ${friendly_name}`);
249
249
  const bridgedGroup = this.z2mBridgeGroups?.find((group) => group.friendly_name === friendly_name);
@@ -479,6 +479,7 @@ export class ZigbeePlatform extends MatterbridgeDynamicPlatform {
479
479
  if (entity) {
480
480
  this.log.info(`Removing device: ${friendly_name}`);
481
481
  await this.unregisterDevice(entity.bridgedDevice);
482
+ entity.destroy();
482
483
  this.zigbeeEntities = this.zigbeeEntities.filter((entity) => entity.entityName !== friendly_name);
483
484
  this.bridgedDevices = this.bridgedDevices.filter((device) => device.deviceName !== friendly_name);
484
485
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "matterbridge-zigbee2mqtt",
3
- "version": "2.4.5-dev.2",
3
+ "version": "2.4.5-dev.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "matterbridge-zigbee2mqtt",
9
- "version": "2.4.5-dev.2",
9
+ "version": "2.4.5-dev.4",
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
12
  "moment": "2.30.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "matterbridge-zigbee2mqtt",
3
- "version": "2.4.5-dev.2",
3
+ "version": "2.4.5-dev.4",
4
4
  "description": "Matterbridge zigbee2mqtt plugin",
5
5
  "author": "https://github.com/Luligu",
6
6
  "license": "Apache-2.0",