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 +13 -0
- package/dist/entity.d.ts +5 -3
- package/dist/entity.d.ts.map +1 -1
- package/dist/entity.js +94 -99
- package/dist/entity.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/payloadTypes.d.ts +1 -1
- package/dist/payloadTypes.d.ts.map +1 -1
- package/dist/platform.d.ts +9 -1
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +34 -5
- package/dist/platform.js.map +1 -1
- package/dist/utils.d.ts +9 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +53 -1
- package/dist/utils.js.map +1 -1
- package/dist/zigbee2mqtt.d.ts +2 -1
- package/dist/zigbee2mqtt.d.ts.map +1 -1
- package/dist/zigbee2mqtt.js +4 -1
- package/dist/zigbee2mqtt.js.map +1 -1
- package/package.json +4 -4
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:
|
|
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,
|
|
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
|
}
|
package/dist/entity.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../src/entity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;;AAEH,OAAO,EAEL,oBAAoB,
|
|
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,
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
-
//
|
|
138
|
-
|
|
139
|
-
|
|
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(
|
|
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
|
|
172
|
+
/* ColorControl CurrenHue and CurrenSaturation */
|
|
174
173
|
if (key === 'color' && 'color_mode' in payload && payload['color_mode'] === 'xy') {
|
|
175
|
-
const
|
|
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
|
|
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
|
|
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(
|
|
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.
|
|
284
|
-
|
|
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
|
-
|
|
296
|
-
|
|
297
|
-
|
|
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: '
|
|
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(
|
|
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.
|
|
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', '
|
|
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', '
|
|
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
|
-
|
|
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
|
|
674
|
+
// Add all server clusters in the includelist
|
|
686
675
|
this.addDeviceClusterServer(includeServerList);
|
|
687
|
-
// Add
|
|
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:
|
|
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,
|
|
814
|
+
addChildDeviceTypeAndClusterServer(endpointName, deviceType, includeServerList) {
|
|
820
815
|
this.hasEndpoints = true;
|
|
821
816
|
/* Look for existing child endpoint */
|
|
822
817
|
let child = undefined;
|