matterbridge-zigbee2mqtt 2.0.9 → 2.0.10

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
@@ -2,8 +2,21 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [2.0.10] - 2024-04-22
6
+
7
+ ### Added
8
+
9
+ - [z2m]: Added a check for not changed mqtt messages.
10
+ - [extension]: Finalized implementation of zigbee2MQTT internal extension v. 1.0.0.
11
+
12
+ ### Changed
13
+
14
+ - [z2m]: Changed vendorName and productName with the values from device definition if present.
15
+
5
16
  ## [2.0.9] - 2024-04-19
6
17
 
18
+ ### Added
19
+
7
20
  - [extension]: Implementation of zigbee2MQTT internal extension.
8
21
 
9
22
  ## [2.0.8] - 2024-04-16
package/dist/entity.d.ts CHANGED
@@ -25,7 +25,7 @@ import { DeviceTypeDefinition, MatterbridgeDevice, ClusterId, Endpoint, AtLeastO
25
25
  import { AnsiLogger } from 'node-ansi-logger';
26
26
  import { ZigbeePlatform } from './platform.js';
27
27
  import { BridgeDevice, BridgeGroup } from './zigbee2mqttTypes.js';
28
- import { Payload } from './payloadTypes.js';
28
+ import { Payload, PayloadValue } from './payloadTypes.js';
29
29
  import EventEmitter from 'events';
30
30
  export declare class ZigbeeEntity extends EventEmitter {
31
31
  log: AnsiLogger;
@@ -39,8 +39,9 @@ export declare class ZigbeeEntity extends EventEmitter {
39
39
  protected ien: string;
40
40
  bridgedDevice: BridgedBaseDevice | undefined;
41
41
  eidn: string;
42
+ private lastPayload;
42
43
  constructor(platform: ZigbeePlatform, entity: BridgeDevice | BridgeGroup);
43
- protected updateAttributeIfChanged(endpoint: Endpoint, endpointName: string | undefined, clusterId: number, attributeName: string, value: any): void;
44
+ protected updateAttributeIfChanged(endpoint: Endpoint, endpointName: string | undefined, clusterId: number, attributeName: string, value: PayloadValue, lookup?: string[]): void;
44
45
  protected publishCommand(command: string, entityName: string, payload: Payload): void;
45
46
  }
46
47
  export declare class ZigbeeGroup extends ZigbeeEntity {
@@ -54,6 +55,7 @@ export interface ZigbeeToMatter {
54
55
  cluster: number;
55
56
  attribute: string;
56
57
  converter?: (value: any) => any;
58
+ valueLookup?: string[];
57
59
  }
58
60
  export declare const z2ms: ZigbeeToMatter[];
59
61
  export declare class ZigbeeDevice extends ZigbeeEntity {
@@ -89,7 +91,7 @@ export declare class BridgedBaseDevice extends MatterbridgeDevice {
89
91
  */
90
92
  protected addDeviceClusterClient(includeClientList?: ClusterId[]): void;
91
93
  addDeviceTypeAndClusterServer(deviceType: DeviceTypeDefinition | undefined, serverList: ClusterId[]): void;
92
- addChildDeviceTypeAndClusterServer(endpointName: string, state: string, deviceType: DeviceTypeDefinition | undefined, includeServerList: ClusterId[]): Endpoint;
94
+ addChildDeviceTypeAndClusterServer(endpointName: string, deviceType: DeviceTypeDefinition | undefined, includeServerList: ClusterId[]): Endpoint;
93
95
  getChildPayload(endpointNumber: EndpointNumber | undefined, key: string, value: string): Payload;
94
96
  configure(): void;
95
97
  }
@@ -1 +1 @@
1
- {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../src/entity.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../src/entity.ts"],"names":[],"mappings":"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"}
package/dist/entity.js CHANGED
@@ -20,12 +20,12 @@
20
20
  * See the License for the specific language governing permissions and
21
21
  * limitations under the License. *
22
22
  */
23
- import { DeviceTypes, logEndpoint, AirQuality, MatterbridgeDevice, airQualitySensor, colorTemperatureSwitch, dimmableSwitch, onOffSwitch, Identify, Groups, Scenes, OnOff, LevelControl, ColorControl, ColorControlCluster, Switch, TemperatureMeasurement, BooleanState, RelativeHumidityMeasurement, PressureMeasurement, OccupancySensing, IlluminanceMeasurement, PowerSource, ClusterId, TvocMeasurement, WindowCovering, DoorLock, BridgedDeviceBasicInformation, ThermostatCluster, Thermostat, TimeSync, Endpoint, FixedLabelCluster, SwitchCluster, ElectricalMeasurement, EveHistory, getClusterNameById, FlowMeasurement, } from 'matterbridge';
23
+ import { DeviceTypes, AirQuality, MatterbridgeDevice, airQualitySensor, colorTemperatureSwitch, dimmableSwitch, onOffSwitch, Identify, Groups, Scenes, OnOff, LevelControl, ColorControl, ColorControlCluster, Switch, TemperatureMeasurement, BooleanState, RelativeHumidityMeasurement, PressureMeasurement, OccupancySensing, IlluminanceMeasurement, PowerSource, ClusterId, TvocMeasurement, WindowCovering, DoorLock, BridgedDeviceBasicInformation, ThermostatCluster, Thermostat, TimeSync, Endpoint, FixedLabelCluster, SwitchCluster, ElectricalMeasurement, EveHistory, getClusterNameById, FlowMeasurement, } from 'matterbridge';
24
24
  import { AnsiLogger, gn, dn, ign, idn, rs, db, wr, debugStringify, hk, zb, or } from 'node-ansi-logger';
25
25
  import * as color from './colorUtils.js';
26
26
  import EventEmitter from 'events';
27
27
  import { hostname } from 'os';
28
- import { deepEqual } from './utils.js';
28
+ import { deepCopy, deepEqual } from './utils.js';
29
29
  export class ZigbeeEntity extends EventEmitter {
30
30
  log;
31
31
  platform;
@@ -38,6 +38,7 @@ export class ZigbeeEntity extends EventEmitter {
38
38
  ien = '';
39
39
  bridgedDevice;
40
40
  eidn = `${or}`;
41
+ lastPayload = {};
41
42
  constructor(platform, entity) {
42
43
  super();
43
44
  this.platform = platform;
@@ -58,18 +59,20 @@ export class ZigbeeEntity extends EventEmitter {
58
59
  this.log = new AnsiLogger({ logName: this.accessoryName, logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logDebug: platform.debugEnabled });
59
60
  this.log.debug(`Created MatterEntity: ${this.accessoryName}`);
60
61
  this.platform.z2m.on('MESSAGE-' + this.accessoryName, (payload) => {
62
+ if (deepEqual(this.lastPayload, payload, ['last_seen', 'linkquality']))
63
+ return;
64
+ this.lastPayload = deepCopy(payload);
65
+ const debugEnabled = this.platform.debugEnabled;
66
+ this.log.setLogDebug(true);
61
67
  if (this.bridgedDevice === undefined) {
62
- this.log.debug(`***Skipping (no device) MQTT message for accessory ${this.ien}${this.accessoryName}${rs}${db} payload: ${debugStringify(payload)}`);
68
+ this.log.debug(`*Skipping (no device) ${platform.z2mDevicesRegistered ? 'MQTT message' : 'State update'} for accessory ${this.ien}${this.accessoryName}${rs}${db} payload: ${debugStringify(payload)}`);
63
69
  return;
64
70
  }
65
71
  if (this.bridgedDevice.noUpdate) {
66
- this.log.debug(`***Skipping (no update) MQTT message for accessory ${this.ien}${this.accessoryName}${rs}${db} payload: ${debugStringify(payload)}`);
72
+ this.log.debug(`*Skipping (no update) ${platform.z2mDevicesRegistered ? 'MQTT message' : 'State update'} for accessory ${this.ien}${this.accessoryName}${rs}${db} payload: ${debugStringify(payload)}`);
67
73
  return;
68
74
  }
69
- const debugEnabled = this.platform.debugEnabled;
70
- this.log.setLogDebug(true);
71
- this.log.debug(`MQTT message for accessory ${this.ien}${this.accessoryName}${rs}${db} payload: ${debugStringify(payload)}`);
72
- //this.log.debug(`MQTT message for accessory ${this.ien}${this.accessoryName}${rs}${db} device: ${this.isDevice} group: ${this.isGroup} power_source: ${this.device?.power_source}`);
75
+ this.log.debug(`${platform.z2mDevicesRegistered ? 'MQTT message' : 'State update'} for device ${this.ien}${this.accessoryName}${rs}${db} payload: ${debugStringify(payload)}`);
73
76
  /* Multi endpoint section */
74
77
  if (this.bridgedDevice.hasEndpoints && !this.bridgedDevice.noUpdate) {
75
78
  const childs = this.bridgedDevice.getChildEndpoints();
@@ -100,9 +103,9 @@ export class ZigbeeEntity extends EventEmitter {
100
103
  z2m = z2ms.find((z2m) => z2m.property + '_' + endpointName.value === key);
101
104
  }
102
105
  if (z2m) {
103
- if (z2m.converter) {
106
+ if (z2m.converter || z2m.valueLookup) {
104
107
  // this.log.debug(`*Endpoint ${this.eidn}${child.number}${db} type ${zb}${endpointType?.value}${db} found converter for ${key} => ${z2m.type}-${z2m.name}-${z2m.property} ${hk}${getClusterNameById(ClusterId(z2m.cluster))}${db}.${hk}${z2m.attribute}${db}`);
105
- this.updateAttributeIfChanged(child, endpointName.value, z2m.cluster, z2m.attribute, z2m.converter(value));
108
+ this.updateAttributeIfChanged(child, endpointName.value, z2m.cluster, z2m.attribute, z2m.converter ? z2m.converter(value) : value, z2m.valueLookup);
106
109
  return;
107
110
  }
108
111
  }
@@ -122,7 +125,7 @@ export class ZigbeeEntity extends EventEmitter {
122
125
  //if (key === 'illuminance') console.log('illuminance', this.device?.definition?.model);
123
126
  if (key === 'illuminance' && this.isDevice && this.device?.definition?.model === 'ZG-204ZL') {
124
127
  key = 'illuminance_lux';
125
- value = Math.pow(10, value / 10000);
128
+ value = Math.pow(10, typeof value === 'number' ? value / 10000 : 0);
126
129
  }
127
130
  if (key === 'illuminance' && this.isDevice && this.device?.definition?.model === 'RTCGQ14LM') {
128
131
  key = 'illuminance_lux';
@@ -134,26 +137,24 @@ export class ZigbeeEntity extends EventEmitter {
134
137
  let z2m;
135
138
  z2m = z2ms.find((z2m) => z2m.type === endpointType?.value && z2m.property === key);
136
139
  if (z2m) {
137
- // eslint-disable-next-line max-len
138
- /*
139
- this.log.debug(
140
- `*Endpoint ${this.eidn}${this.bridgedDevice.number}${db} type ${zb}${endpointType?.value}${db} found converter for type ${z2m.type} property ${key} => ${z2m.type}-${z2m.name}-${z2m.property} ${hk}${getClusterNameById(ClusterId(z2m.cluster))}${db}.${hk}${z2m.attribute}${db}`,
141
- );
142
- */
140
+ //this.log.debug(
141
+ //`***Endpoint ${this.eidn}${this.bridgedDevice.number}${db} type ${zb}${endpointType?.value}${db} found converter for type ${z2m.type} property ${key} => ${z2m.type}-${z2m.name}-${z2m.property} ${hk}${getClusterNameById(ClusterId(z2m.cluster))}${db}.${hk}${z2m.attribute}${db}`,
142
+ //);
143
143
  }
144
144
  else {
145
145
  z2m = z2ms.find((z2m) => z2m.property === key);
146
+ //if (z2m) this.log.debug(`***Endpoint ${this.eidn}${this.bridgedDevice.number}${db} type ${zb}${endpointType?.value}${db} found converter for ${key} => ${z2m.type}-${z2m.name}-${z2m.property} ${hk}${getClusterNameById(ClusterId(z2m.cluster))}${db}.${hk}${z2m.attribute}${db}`);
146
147
  }
147
148
  if (z2m) {
148
- if (z2m.converter) {
149
- // this.log.debug(`*Endpoint ${this.eidn}${this.bridgedDevice.number}${db} type ${zb}${endpointType?.value}${db} found converter for ${key} => ${z2m.type}-${z2m.name}-${z2m.property} ${hk}${getClusterNameById(ClusterId(z2m.cluster))}${db}.${hk}${z2m.attribute}${db}`);
150
- this.updateAttributeIfChanged(this.bridgedDevice, undefined, z2m.cluster, z2m.attribute, z2m.converter(value));
149
+ if (z2m.converter || z2m.valueLookup) {
150
+ // if (z2m.converter) this.log.debug(`***converter for ${key} ${value} => ${z2m.converter(value)}`);
151
+ this.updateAttributeIfChanged(this.bridgedDevice, undefined, z2m.cluster, z2m.attribute, z2m.converter ? z2m.converter(value) : value, z2m.valueLookup);
151
152
  return;
152
153
  }
153
154
  }
154
155
  /* WindowCovering */
155
156
  if (key === 'position') {
156
- this.updateAttributeIfChanged(this.bridgedDevice, undefined, WindowCovering.Cluster.id, 'currentPositionLiftPercent100ths', 10000 - value * 100);
157
+ this.updateAttributeIfChanged(this.bridgedDevice, undefined, WindowCovering.Cluster.id, 'currentPositionLiftPercent100ths', typeof value === 'number' ? 10000 - value * 100 : 0);
157
158
  }
158
159
  if (key === 'moving') {
159
160
  const status = value === 'UP' ? WindowCovering.MovementStatus.Opening : value === 'DOWN' ? WindowCovering.MovementStatus.Closing : WindowCovering.MovementStatus.Stopped;
@@ -163,16 +164,15 @@ export class ZigbeeEntity extends EventEmitter {
163
164
  this.updateAttributeIfChanged(this.bridgedDevice, undefined, WindowCovering.Cluster.id, 'currentPositionLiftPercent100ths', position);
164
165
  }
165
166
  }
166
- /* OnOff */
167
- /* LevelControl */
168
167
  /* ColorControl ColorTemperatureMired */
169
168
  if (key === 'color_temp' && 'color_mode' in payload && payload['color_mode'] === 'color_temp') {
170
- this.updateAttributeIfChanged(this.bridgedDevice, undefined, ColorControl.Cluster.id, 'colorTemperatureMireds', Math.max(147, Math.min(500, value)));
169
+ this.updateAttributeIfChanged(this.bridgedDevice, undefined, ColorControl.Cluster.id, 'colorTemperatureMireds', Math.max(147, Math.min(500, typeof value === 'number' ? value : 0)));
171
170
  this.updateAttributeIfChanged(this.bridgedDevice, undefined, ColorControl.Cluster.id, 'colorMode', ColorControl.ColorMode.ColorTemperatureMireds);
172
171
  }
173
- /* ColorControl Hue and Saturation */
172
+ /* ColorControl CurrenHue and CurrenSaturation */
174
173
  if (key === 'color' && 'color_mode' in payload && payload['color_mode'] === 'xy') {
175
- const hsl = color.xyToHsl(value.x, value.y);
174
+ const { x, y } = value;
175
+ const hsl = color.xyToHsl(x, y);
176
176
  this.updateAttributeIfChanged(this.bridgedDevice, undefined, ColorControl.Cluster.id, 'currentHue', Math.round((hsl.h / 360) * 254));
177
177
  this.updateAttributeIfChanged(this.bridgedDevice, undefined, ColorControl.Cluster.id, 'currentSaturation', Math.round((hsl.s / 100) * 254));
178
178
  this.updateAttributeIfChanged(this.bridgedDevice, undefined, ColorControl.Cluster.id, 'colorMode', ColorControl.ColorMode.CurrentHueAndCurrentSaturation);
@@ -208,93 +208,76 @@ export class ZigbeeEntity extends EventEmitter {
208
208
  this.log.debug(`*Set accessory ${hk}Switch.currentPosition: ${position}`);
209
209
  }
210
210
  if (value === 'release') {
211
- this.bridgedDevice?.getClusterServerById(BridgedDeviceBasicInformation.Cluster.id)?.triggerReachableChangedEvent({ reachableNewValue: true });
211
+ // this.bridgedDevice?.getClusterServerById(BridgedDeviceBasicInformation.Cluster.id)?.triggerReachableChangedEvent({ reachableNewValue: true });
212
212
  }
213
213
  }
214
- /* Thermostat */
215
- if (key === 'local_temperature') {
216
- this.updateAttributeIfChanged(this.bridgedDevice, undefined, Thermostat.Cluster.id, 'localTemperature', Math.max(-5000, Math.min(5000, value * 100)));
217
- }
218
- if (key === 'current_heating_setpoint') {
219
- this.updateAttributeIfChanged(this.bridgedDevice, undefined, Thermostat.Cluster.id, 'occupiedHeatingSetpoint', Math.max(-5000, Math.min(5000, value * 100)));
220
- }
221
- if (key === 'current_cooling_setpoint') {
222
- this.updateAttributeIfChanged(this.bridgedDevice, undefined, Thermostat.Cluster.id, 'occupiedCoolingSetpoint', Math.max(-5000, Math.min(5000, value * 100)));
223
- }
224
- if (key === 'running_state') {
225
- //const state = value === 'idle' ? Thermostat.ThermostatRunningMode.Off : value === 'heat' ? Thermostat.ThermostatRunningMode.Heat : Thermostat.ThermostatRunningMode.Cool;
226
- //this.bridgedDevice.getClusterServerById(Thermostat.Cluster.id)?.setThermostatRunningModeAttribute(state);
227
- //this.log.debug(`Get accessory ${hk}Thermostat.thermostatRunningMode: ${state} (${value})`);
228
- }
229
- if (key === 'system_mode') {
230
- const state = value === 'off' ? Thermostat.SystemMode.Off : value === 'heat' ? Thermostat.SystemMode.Heat : Thermostat.SystemMode.Cool;
231
- this.updateAttributeIfChanged(this.bridgedDevice, undefined, Thermostat.Cluster.id, 'systemMode', state);
232
- }
233
- if (key === 'air_quality') {
234
- // excellent, good, moderate, poor, unhealthy, out_of_range unknown
235
- const airQuality = value === 'unhealthy'
236
- ? AirQuality.AirQualityType.VeryPoor
237
- : value === 'poor'
238
- ? AirQuality.AirQualityType.Poor
239
- : value === 'moderate'
240
- ? AirQuality.AirQualityType.Moderate
241
- : value === 'good'
242
- ? AirQuality.AirQualityType.Fair
243
- : value === 'excellent'
244
- ? AirQuality.AirQualityType.Good
245
- : AirQuality.AirQualityType.Unknown;
246
- this.bridgedDevice.getClusterServerById(AirQuality.Cluster.id)?.setAirQualityAttribute(airQuality);
247
- this.log.debug(`Set accessory ${hk}AirQuality.airQuality: ${airQuality}`);
248
- }
249
214
  });
250
215
  this.log.setLogDebug(debugEnabled);
251
216
  });
252
217
  this.platform.z2m.on('ONLINE-' + this.accessoryName, () => {
253
- this.log.info(`ONLINE message for accessory ${this.ien}${this.accessoryName}${rs}`);
218
+ this.log.info(`ONLINE message for device ${this.ien}${this.accessoryName}${rs}`);
254
219
  if (this.bridgedDevice?.number !== undefined) {
255
220
  this.bridgedDevice?.getClusterServerById(BridgedDeviceBasicInformation.Cluster.id)?.setReachableAttribute(true);
256
221
  this.bridgedDevice?.getClusterServerById(BridgedDeviceBasicInformation.Cluster.id)?.triggerReachableChangedEvent({ reachableNewValue: true });
257
- this.log.info(`${db}Set accessory ${hk}BridgedDeviceBasicInformation.reachable: true`);
222
+ this.log.info(`${db}Set accessory attribute ${hk}BridgedDeviceBasicInformation.reachable: true`);
223
+ this.log.info(`${db}Trigger accessory event ${hk}ReachableChangedEvent: true`);
258
224
  }
259
225
  });
260
226
  this.platform.z2m.on('OFFLINE-' + this.accessoryName, () => {
261
- this.log.warn(`OFFLINE message for accessory ${this.ien}${this.accessoryName}${wr}`);
227
+ this.log.warn(`OFFLINE message for device ${this.ien}${this.accessoryName}${wr}`);
262
228
  if (this.bridgedDevice?.number !== undefined) {
263
229
  this.bridgedDevice?.getClusterServerById(BridgedDeviceBasicInformation.Cluster.id)?.setReachableAttribute(false);
264
230
  this.bridgedDevice?.getClusterServerById(BridgedDeviceBasicInformation.Cluster.id)?.triggerReachableChangedEvent({ reachableNewValue: false });
265
- this.log.info(`${db}Set accessory ${hk}BridgedDeviceBasicInformation.reachable: false`);
231
+ this.log.info(`${db}Set accessory attribute ${hk}BridgedDeviceBasicInformation.reachable: false`);
232
+ this.log.info(`${db}Trigger accessory event ${hk}ReachableChangedEvent: false`);
266
233
  }
267
234
  });
268
235
  }
269
236
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
270
- updateAttributeIfChanged(endpoint, endpointName, clusterId, attributeName, value) {
237
+ updateAttributeIfChanged(endpoint, endpointName, clusterId, attributeName, value, lookup) {
271
238
  const cluster = endpoint.getClusterServerById(ClusterId(clusterId));
272
239
  if (cluster === undefined) {
273
240
  this.log.debug(`Update endpoint ${this.eidn}${endpoint.number}${db}${endpointName ? ' (' + zb + endpointName + db + ')' : ''} cluster ${hk}${clusterId}${db}-${hk}${getClusterNameById(ClusterId(clusterId))}${db} not found: is z2m converter exposing all features?`);
274
241
  return;
275
242
  }
276
243
  if (!cluster.isAttributeSupportedByName(attributeName)) {
277
- this.log.debug(`Update endpoint ${this.eidn}${endpoint.number}${db}${endpointName ? ' (' + zb + endpointName + db + ')' : ''} error attribute ${hk}${clusterId}${db}-${hk}${getClusterNameById(ClusterId(clusterId))}${db}-${hk}${attributeName}${db} not found`);
244
+ this.log.debug(`***Update endpoint ${this.eidn}${endpoint.number}${db}${endpointName ? ' (' + zb + endpointName + db + ')' : ''} error attribute ${hk}${clusterId}${db}-${hk}${getClusterNameById(ClusterId(clusterId))}${db}-${hk}${attributeName}${db} not found`);
278
245
  return;
279
246
  }
247
+ if (lookup !== undefined) {
248
+ if (typeof value === 'string' && lookup.indexOf(value) !== -1)
249
+ value = lookup.indexOf(value);
250
+ else {
251
+ this.log.debug(`Update endpoint ${this.eidn}${endpoint.number}${db}${endpointName ? ' (' + zb + endpointName + db + ')' : ''} ` +
252
+ `attribute ${hk}${getClusterNameById(ClusterId(clusterId))}${db}-${hk}${attributeName}${db} value ${zb}${typeof value === 'object' ? debugStringify(value) : value}${db} not found in lookup ${debugStringify(lookup)}`);
253
+ return;
254
+ }
255
+ }
280
256
  const localValue = cluster.attributes[attributeName].getLocal();
281
257
  if (typeof value === 'object' ? deepEqual(value, localValue) : value === localValue) {
282
- /*
283
- this.log.debug(
284
- `Skip update endpoint ${this.eidn}${endpoint.number}${db}${endpointName ? ' (' + zb + endpointName + db + ')' : ''} ` + `attribute ${hk}${getClusterNameById(ClusterId(clusterId))}${db}-${hk}${attributeName}${db} already ${zb}${typeof value === 'object' ? debugStringify(value) : value}${db}`,
285
- );
286
- */
258
+ //this.log.debug(
259
+ //`Skip update endpoint ${this.eidn}${endpoint.number}${db}${endpointName ? ' (' + zb + endpointName + db + ')' : ''} ` + `attribute ${hk}${getClusterNameById(ClusterId(clusterId))}${db}-${hk}${attributeName}${db} already ${zb}${typeof value === 'object' ? debugStringify(value) : value}${db}`,
260
+ //);
287
261
  return;
288
262
  }
289
- cluster.attributes[attributeName].setLocal(value);
290
263
  this.log.debug(`Update endpoint ${this.eidn}${endpoint.number}${db}${endpointName ? ' (' + zb + endpointName + db + ')' : ''} ` +
291
264
  `attribute ${hk}${getClusterNameById(ClusterId(clusterId))}${db}-${hk}${attributeName}${db} from ${zb}${typeof localValue === 'object' ? debugStringify(localValue) : localValue}${db} to ${zb}${typeof value === 'object' ? debugStringify(value) : value}${db}`);
265
+ try {
266
+ cluster.attributes[attributeName].setLocal(value);
267
+ }
268
+ catch (error) {
269
+ this.log.error(`Error setting attribute ${attributeName} to ${value}: ${error}`);
270
+ }
292
271
  }
272
+ // this.publishCommand('permit_join: false', 'bridge/request/permit_join', { value: false });
293
273
  publishCommand(command, entityName, payload) {
294
274
  this.log.debug(`executeCommand ${command} called for ${this.ien}${entityName}${rs}${db} payload: ${debugStringify(payload)}`);
295
- const topic = entityName.includes('bridge/request') ? entityName : this.platform.z2m.mqttTopic + '/' + entityName + '/set';
296
- this.platform.z2m.publish(topic, JSON.stringify(payload));
297
- this.log.info(`MQTT publish topic: ${topic} payload: ${debugStringify(payload)} for ${this.en}${entityName}`);
275
+ if (entityName.startsWith('bridge/request')) {
276
+ this.platform.publish(entityName, '', JSON.stringify(payload));
277
+ }
278
+ else {
279
+ this.platform.publish(entityName, 'set', JSON.stringify(payload));
280
+ }
298
281
  }
299
282
  }
300
283
  export class ZigbeeGroup extends ZigbeeEntity {
@@ -305,7 +288,7 @@ export class ZigbeeGroup extends ZigbeeEntity {
305
288
  // Command handlers
306
289
  this.bridgedDevice.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
307
290
  this.log.warn(`Command identify called for ${this.ien}${group.friendly_name}${rs}${db} identifyTime:${identifyTime}`);
308
- logEndpoint(this.bridgedDevice);
291
+ // logEndpoint(this.bridgedDevice!);
309
292
  });
310
293
  this.bridgedDevice.addCommandHandler('on', async ({ attributes: { onOff } }) => {
311
294
  this.log.debug(`Command on called for ${this.ien}${group.friendly_name}${rs}${db} attribute: ${onOff.getLocal()}`);
@@ -334,7 +317,11 @@ export const z2ms = [
334
317
  { type: 'light', name: 'color_xy', property: 'color_xy', deviceType: DeviceTypes.COLOR_TEMPERATURE_LIGHT, cluster: ColorControl.Cluster.id, attribute: 'colorMode' },
335
318
  { type: 'cover', name: 'state', property: 'state', deviceType: DeviceTypes.WINDOW_COVERING, cluster: WindowCovering.Cluster.id, attribute: 'currentPositionLiftPercent100ths' },
336
319
  { type: 'lock', name: 'state', property: 'state', deviceType: DeviceTypes.DOOR_LOCK, cluster: DoorLock.Cluster.id, attribute: 'lockState', converter: (value) => { return value === 'LOCK' ? DoorLock.LockState.Locked : DoorLock.LockState.Unlocked; } },
337
- { type: 'climate', name: 'current_heating_setpoint', property: 'current_heating_setpoint', deviceType: DeviceTypes.THERMOSTAT, cluster: Thermostat.Cluster.id, attribute: 'occupiedHeatingSetpoint' },
320
+ { type: 'climate', name: 'local_temperature', property: 'local_temperature', deviceType: DeviceTypes.THERMOSTAT, cluster: Thermostat.Cluster.id, attribute: 'localTemperature', converter: (value) => { return Math.max(-5000, Math.min(5000, value * 100)); } },
321
+ { type: 'climate', name: 'current_heating_setpoint', property: 'current_heating_setpoint', deviceType: DeviceTypes.THERMOSTAT, cluster: Thermostat.Cluster.id, attribute: 'occupiedHeatingSetpoint', converter: (value) => { return Math.max(-5000, Math.min(5000, value * 100)); } },
322
+ { type: 'climate', name: 'current_cooling_setpoint', property: 'current_cooling_setpoint', deviceType: DeviceTypes.THERMOSTAT, cluster: Thermostat.Cluster.id, attribute: 'occupiedCoolingSetpoint', converter: (value) => { return Math.max(-5000, Math.min(5000, value * 100)); } },
323
+ { type: 'climate', name: 'running_state', property: 'running_state', deviceType: DeviceTypes.THERMOSTAT, cluster: Thermostat.Cluster.id, attribute: 'thermostatRunningMode', valueLookup: ['idle', '', '', 'cool', 'heat'] },
324
+ { type: 'climate', name: 'system_mode', property: 'system_mode', deviceType: DeviceTypes.THERMOSTAT, cluster: Thermostat.Cluster.id, attribute: 'systemMode', valueLookup: ['off', 'auto', '', 'cool', 'heat'] },
338
325
  { type: '', name: 'presence', property: 'presence', deviceType: DeviceTypes.OCCUPANCY_SENSOR, cluster: OccupancySensing.Cluster.id, attribute: 'occupancy', converter: (value) => { return { occupied: value }; } },
339
326
  { type: '', name: 'occupancy', property: 'occupancy', deviceType: DeviceTypes.OCCUPANCY_SENSOR, cluster: OccupancySensing.Cluster.id, attribute: 'occupancy', converter: (value) => { return { occupied: value }; } },
340
327
  { type: '', name: 'illuminance', property: 'illuminance', deviceType: DeviceTypes.LIGHT_SENSOR, cluster: IlluminanceMeasurement.Cluster.id, attribute: 'measuredValue' },
@@ -347,7 +334,7 @@ export const z2ms = [
347
334
  { type: '', name: 'temperature', property: 'temperature', deviceType: DeviceTypes.TEMPERATURE_SENSOR, cluster: TemperatureMeasurement.Cluster.id, attribute: 'measuredValue', converter: (value) => { return Math.round(value * 100); } },
348
335
  { type: '', name: 'humidity', property: 'humidity', deviceType: DeviceTypes.HUMIDITY_SENSOR, cluster: RelativeHumidityMeasurement.Cluster.id, attribute: 'measuredValue', converter: (value) => { return Math.round(value * 100); } },
349
336
  { type: '', name: 'pressure', property: 'pressure', deviceType: DeviceTypes.PRESSURE_SENSOR, cluster: PressureMeasurement.Cluster.id, attribute: 'measuredValue', converter: (value) => { return value; } },
350
- { type: '', name: 'air_quality', property: 'air_quality', deviceType: airQualitySensor, cluster: AirQuality.Cluster.id, attribute: 'airQuality' },
337
+ { type: '', name: 'air_quality', property: 'air_quality', deviceType: airQualitySensor, cluster: AirQuality.Cluster.id, attribute: 'airQuality', valueLookup: ['unknown', 'excellent', 'good', 'moderate', 'poor', 'unhealthy', 'out_of_range'] },
351
338
  { type: '', name: 'voc', property: 'voc', deviceType: airQualitySensor, cluster: TvocMeasurement.Cluster.id, attribute: 'measuredValue', converter: (value) => { return Math.min(65535, value); } },
352
339
  { type: '', name: 'action', property: 'action', deviceType: DeviceTypes.GENERIC_SWITCH, cluster: Switch.Cluster.id, attribute: 'currentPosition' },
353
340
  { type: '', name: 'cpu_temperature', property: 'temperature', deviceType: DeviceTypes.TEMPERATURE_SENSOR, cluster: TemperatureMeasurement.Cluster.id, attribute: 'measuredValue', converter: (value) => { return Math.round(value * 100); } },
@@ -367,14 +354,16 @@ export class ZigbeeDevice extends ZigbeeEntity {
367
354
  super(platform, device);
368
355
  if (device.friendly_name === 'Coordinator') {
369
356
  this.bridgedDevice = new BridgedBaseDevice(this, [DeviceTypes.DOOR_LOCK], [Identify.Cluster.id, DoorLock.Cluster.id]);
357
+ this.bridgedDevice.addFixedLabel('type', 'lock');
370
358
  this.bridgedDevice.isRouter = true;
371
359
  }
372
360
  else if (device.model_id === 'ti.router' && device.manufacturer === 'TexasInstruments') {
373
361
  this.bridgedDevice = new BridgedBaseDevice(this, [DeviceTypes.DOOR_LOCK], [Identify.Cluster.id, DoorLock.Cluster.id]);
362
+ this.bridgedDevice.addFixedLabel('type', 'lock');
374
363
  this.bridgedDevice.isRouter = true;
375
364
  }
376
365
  const debugEnabled = this.platform.debugEnabled;
377
- this.log.setLogDebug(true);
366
+ // this.log.setLogDebug(true);
378
367
  // Get types and properties
379
368
  const types = [];
380
369
  const endpoints = [];
@@ -414,7 +403,7 @@ export class ZigbeeDevice extends ZigbeeEntity {
414
403
  }
415
404
  });
416
405
  device.definition?.options.forEach((option) => {
417
- //this.log.debug(option);
406
+ // this.log.debug(option);
418
407
  if (option.name)
419
408
  names.push(option.name);
420
409
  properties.push(option.property);
@@ -425,27 +414,27 @@ export class ZigbeeDevice extends ZigbeeEntity {
425
414
  endpoints.push('');
426
415
  });
427
416
  if (platform.switchList.includes(device.friendly_name)) {
428
- this.log.debug(`Changed ${device.friendly_name} to switch`);
417
+ // this.log.debug(`Changed ${device.friendly_name} to switch`);
429
418
  types.forEach((type, index) => {
430
419
  types[index] = type === 'light' ? 'switch' : type;
431
420
  });
432
421
  }
433
422
  if (platform.lightList.includes(device.friendly_name)) {
434
- this.log.debug(`Changed ${device.friendly_name} to light`);
423
+ // this.log.debug(`Changed ${device.friendly_name} to light`);
435
424
  types.forEach((type, index) => {
436
425
  types[index] = type === 'switch' ? 'light' : type;
437
426
  });
438
427
  }
439
428
  if (platform.outletList.includes(device.friendly_name)) {
440
- this.log.debug(`Changed ${device.friendly_name} to outlet`);
429
+ // this.log.debug(`Changed ${device.friendly_name} to outlet`);
441
430
  types.forEach((type, index) => {
442
431
  types[index] = type === 'switch' || type === 'light' ? 'outlet' : type;
443
432
  });
444
433
  }
445
- this.log.debug(`*Device ${this.ien}${device.friendly_name}${rs}${db} - types[${types.length}]: ${debugStringify(types)}`);
446
- this.log.debug(`*Device ${this.ien}${device.friendly_name}${rs}${db} - endpoints[${endpoints.length}]: ${debugStringify(endpoints)}`);
447
- this.log.debug(`*Device ${this.ien}${device.friendly_name}${rs}${db} - names[${names.length}]: ${debugStringify(names)}`);
448
- this.log.debug(`*Device ${this.ien}${device.friendly_name}${rs}${db} - properties[${properties.length}]: ${debugStringify(properties)}`);
434
+ // this.log.debug(`*Device ${this.ien}${device.friendly_name}${rs}${db} - types[${types.length}]: ${debugStringify(types)}`);
435
+ // this.log.debug(`*Device ${this.ien}${device.friendly_name}${rs}${db} - endpoints[${endpoints.length}]: ${debugStringify(endpoints)}`);
436
+ // this.log.debug(`*Device ${this.ien}${device.friendly_name}${rs}${db} - names[${names.length}]: ${debugStringify(names)}`);
437
+ // this.log.debug(`*Device ${this.ien}${device.friendly_name}${rs}${db} - properties[${properties.length}]: ${debugStringify(properties)}`);
449
438
  names.forEach((name, index) => {
450
439
  if (platform.featureBlackList.includes(name))
451
440
  return;
@@ -453,7 +442,7 @@ export class ZigbeeDevice extends ZigbeeEntity {
453
442
  const endpoint = endpoints[index];
454
443
  const z2m = z2ms.find((z2m) => z2m.type === type && z2m.name === name);
455
444
  if (z2m) {
456
- this.log.debug(`*Device ${this.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}`);
445
+ this.log.debug(`Device ${this.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}`);
457
446
  if (endpoint === '') {
458
447
  if (!this.bridgedDevice)
459
448
  this.bridgedDevice = new BridgedBaseDevice(this, [z2m.deviceType ?? DeviceTypes.BRIDGED_DEVICE_WITH_POWERSOURCE_INFO], z2m.deviceType ? [...z2m.deviceType.requiredServerClusters, ClusterId(z2m.cluster)] : [ClusterId(z2m.cluster)]);
@@ -465,7 +454,7 @@ export class ZigbeeDevice extends ZigbeeEntity {
465
454
  else {
466
455
  if (!this.bridgedDevice)
467
456
  this.bridgedDevice = new BridgedBaseDevice(this, [DeviceTypes.BRIDGED_DEVICE_WITH_POWERSOURCE_INFO]);
468
- const childEndpoint = this.bridgedDevice.addChildDeviceTypeAndClusterServer(endpoint, z2m.property, z2m.deviceType, z2m.deviceType ? [...z2m.deviceType.requiredServerClusters, ClusterId(z2m.cluster)] : [ClusterId(z2m.cluster)]);
457
+ const childEndpoint = this.bridgedDevice.addChildDeviceTypeAndClusterServer(endpoint, z2m.deviceType, z2m.deviceType ? [...z2m.deviceType.requiredServerClusters, ClusterId(z2m.cluster)] : [ClusterId(z2m.cluster)]);
469
458
  if (type !== '')
470
459
  childEndpoint.addFixedLabel('type', type);
471
460
  //childEndpoint.addClusterServer(this.bridgedDevice.getDefaultBasicInformationClusterServer(device.friendly_name + ' ' + endpoint, device.ieee_address, 0xfff1, '', 0x0001, 'sub'));
@@ -601,7 +590,7 @@ export class ZigbeeDevice extends ZigbeeEntity {
601
590
  if (!this.bridgedDevice?.isRouter)
602
591
  this.publishCommand('lockDoor', device.friendly_name, { state: 'LOCK' });
603
592
  else
604
- this.publishCommand('permit_join: false', 'zigbee2mqtt/bridge/request/permit_join', { value: false });
593
+ this.publishCommand('permit_join: false', 'bridge/request/permit_join', { value: false });
605
594
  });
606
595
  this.bridgedDevice.addCommandHandler('unlockDoor', async ({ request: request, attributes: attributes }) => {
607
596
  this.log.info(`Command unlockDoor called for ${this.ien}${device.friendly_name}${rs}${db}`, request);
@@ -609,7 +598,7 @@ export class ZigbeeDevice extends ZigbeeEntity {
609
598
  if (!this.bridgedDevice?.isRouter)
610
599
  this.publishCommand('unlockDoor', device.friendly_name, { state: 'UNLOCK' });
611
600
  else
612
- this.publishCommand('permit_join: true', 'zigbee2mqtt/bridge/request/permit_join', { value: true });
601
+ this.publishCommand('permit_join: true', 'bridge/request/permit_join', { value: true });
613
602
  });
614
603
  }
615
604
  if (this.bridgedDevice.hasClusterServer(Thermostat.Complete)) {
@@ -678,18 +667,20 @@ export class BridgedBaseDevice extends MatterbridgeDevice {
678
667
  this.addDeviceType(deviceType);
679
668
  this.log.debug(`new BridgedBaseDevice ${entity.isDevice ? entity.device?.friendly_name : entity.group?.friendly_name} deviceType: ${hk}${deviceType.name}${db}`);
680
669
  });
681
- this.addDeviceType(DeviceTypes.BRIDGED_DEVICE_WITH_POWERSOURCE_INFO);
670
+ // Log all server clusters in the includelist
682
671
  includeServerList.forEach((clusterId) => {
683
672
  this.log.debug(`- with cluster: ${hk}${clusterId}${db}-${hk}${getClusterNameById(clusterId)}${db}`);
684
673
  });
685
- // Add all other server clusters in the includelist
674
+ // Add all server clusters in the includelist
686
675
  this.addDeviceClusterServer(includeServerList);
687
- // Add BridgedDeviceBasicInformationCluster
676
+ // Add BridgedDevice with PowerSourceInformation device type
677
+ this.addDeviceType(DeviceTypes.BRIDGED_DEVICE_WITH_POWERSOURCE_INFO);
678
+ // Add BridgedDeviceBasicInformation cluster
688
679
  if (entity.isDevice && entity.device && entity.device.friendly_name === 'Coordinator') {
689
680
  this.addBridgedDeviceBasicInformationCluster(entity.device.friendly_name, 'zigbee2MQTT', 'Coordinator', entity.device.ieee_address);
690
681
  }
691
682
  else if (entity.isDevice && entity.device) {
692
- this.addBridgedDeviceBasicInformationCluster(entity.device.friendly_name, entity.device.manufacturer, entity.device.model_id, entity.device.ieee_address);
683
+ this.addBridgedDeviceBasicInformationCluster(entity.device.friendly_name, entity.device.definition ? entity.device.definition.vendor : entity.device.manufacturer, entity.device.definition ? entity.device.definition.model : entity.device.model_id, entity.device.ieee_address);
693
684
  }
694
685
  else if (entity.isGroup && entity.group) {
695
686
  this.addBridgedDeviceBasicInformationCluster(entity.group.friendly_name, 'zigbee2MQTT', 'Group', `group-${entity.group.id}`);
@@ -811,12 +802,16 @@ export class BridgedBaseDevice extends MatterbridgeDevice {
811
802
  /* Not implemented since not supported by matter.js */
812
803
  }
813
804
  addDeviceTypeAndClusterServer(deviceType, serverList) {
814
- this.log.debug(`addDeviceTypeAndClusterServer deviceType: ${deviceType?.name} serverList: ${serverList}`);
805
+ this.log.debug(`addDeviceTypeAndClusterServer ${deviceType ? 'deviceType: ' + hk + deviceType.name + db : ''}`);
815
806
  if (deviceType)
816
807
  this.addDeviceType(deviceType);
808
+ // Log all server clusters in the serverList
809
+ serverList.forEach((clusterId) => {
810
+ this.log.debug(`- with cluster: ${hk}${clusterId}${db}-${hk}${getClusterNameById(clusterId)}${db}`);
811
+ });
817
812
  this.addDeviceClusterServer(serverList);
818
813
  }
819
- addChildDeviceTypeAndClusterServer(endpointName, state, deviceType, includeServerList) {
814
+ addChildDeviceTypeAndClusterServer(endpointName, deviceType, includeServerList) {
820
815
  this.hasEndpoints = true;
821
816
  /* Look for existing child endpoint */
822
817
  let child = undefined;