matterbridge-zigbee2mqtt 2.3.0-dev.1 → 2.3.0-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 +2 -1
- package/dist/entity.js +10 -247
- package/dist/index.js +0 -35
- package/dist/payloadTypes.js +0 -23
- package/dist/platform.js +3 -50
- package/dist/zigbee2mqtt.js +22 -272
- package/dist/zigbee2mqttTypes.js +0 -23
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/tsconfig.production.json +19 -0
- package/dist/entity.d.ts +0 -492
- package/dist/entity.d.ts.map +0 -1
- package/dist/entity.js.map +0 -1
- package/dist/index.d.ts +0 -40
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/payloadTypes.d.ts +0 -25
- package/dist/payloadTypes.d.ts.map +0 -1
- package/dist/payloadTypes.js.map +0 -1
- package/dist/platform.d.ts +0 -88
- package/dist/platform.d.ts.map +0 -1
- package/dist/platform.js.map +0 -1
- package/dist/zigbee2mqtt.d.ts +0 -182
- package/dist/zigbee2mqtt.d.ts.map +0 -1
- package/dist/zigbee2mqtt.js.map +0 -1
- package/dist/zigbee2mqttTypes.d.ts +0 -350
- package/dist/zigbee2mqttTypes.d.ts.map +0 -1
- package/dist/zigbee2mqttTypes.js.map +0 -1
package/dist/entity.js
CHANGED
|
@@ -1,37 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file contains the classes ZigbeeEntity, ZigbeeDevice and ZigbeeGroup.
|
|
3
|
-
*
|
|
4
|
-
* @file entity.ts
|
|
5
|
-
* @author Luca Liguori
|
|
6
|
-
* @date 2023-12-29
|
|
7
|
-
* @version 3.1.0
|
|
8
|
-
*
|
|
9
|
-
* Copyright 2023, 2024, 2025 Luca Liguori.
|
|
10
|
-
*
|
|
11
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
12
|
-
* you may not use this file except in compliance with the License.
|
|
13
|
-
* You may obtain a copy of the License at
|
|
14
|
-
*
|
|
15
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
16
|
-
*
|
|
17
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
18
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
19
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
20
|
-
* See the License for the specific language governing permissions and
|
|
21
|
-
* limitations under the License. *
|
|
22
|
-
*/
|
|
23
1
|
import { MatterbridgeDevice, airQualitySensor, colorTemperatureSwitch, dimmableSwitch, onOffSwitch, OnOff, LevelControl, ColorControl, ColorControlCluster, TemperatureMeasurement, BooleanState, RelativeHumidityMeasurement, PressureMeasurement, OccupancySensing, IlluminanceMeasurement, PowerSource, ClusterId, WindowCovering, DoorLock, BridgedDeviceBasicInformation, ThermostatCluster, Thermostat, getClusterNameById, powerSource, bridgedNode, AirQuality, TotalVolatileOrganicCompoundsConcentrationMeasurement, CarbonDioxideConcentrationMeasurement, CarbonMonoxideConcentrationMeasurement, FormaldehydeConcentrationMeasurement, Pm1ConcentrationMeasurement, Pm25ConcentrationMeasurement, Pm10ConcentrationMeasurement, electricalSensor, ElectricalEnergyMeasurement, ElectricalPowerMeasurement, onOffLight, dimmableLight, colorTemperatureLight, onOffOutlet, SwitchesTag, NumberTag, coverDevice, thermostatDevice, MatterbridgeEndpoint, dimmableOutlet, doorLockDevice, occupancySensor, lightSensor, contactSensor, temperatureSensor, humiditySensor, pressureSensor, genericSwitch, OnOffCluster, LevelControlCluster, WindowCoveringCluster, DoorLockCluster, } from 'matterbridge';
|
|
24
2
|
import { AnsiLogger, gn, dn, ign, idn, rs, db, debugStringify, hk, zb, or, nf, CYAN, er, YELLOW } from 'matterbridge/logger';
|
|
25
3
|
import { deepCopy, deepEqual, isValidNumber } from 'matterbridge/utils';
|
|
26
4
|
import * as color from 'matterbridge/utils';
|
|
27
5
|
import EventEmitter from 'events';
|
|
28
6
|
import { hostname } from 'os';
|
|
29
|
-
/**
|
|
30
|
-
* Represents a Zigbee entity: a group or a device.
|
|
31
|
-
*
|
|
32
|
-
* @class
|
|
33
|
-
* @extends {EventEmitter}
|
|
34
|
-
*/
|
|
35
7
|
export class ZigbeeEntity extends EventEmitter {
|
|
36
8
|
log;
|
|
37
9
|
serial = '';
|
|
@@ -51,7 +23,6 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
51
23
|
ignoreFeatures = [];
|
|
52
24
|
transition = false;
|
|
53
25
|
propertyMap = new Map();
|
|
54
|
-
// We save the tag list and device types and cluster servers and clients to avoid multiple lookups
|
|
55
26
|
mutableDevice = new Map();
|
|
56
27
|
colorTimeout = undefined;
|
|
57
28
|
thermostatTimeout = undefined;
|
|
@@ -59,12 +30,6 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
59
30
|
hasEndpoints = false;
|
|
60
31
|
isRouter = false;
|
|
61
32
|
noUpdate = false;
|
|
62
|
-
/**
|
|
63
|
-
* Creates an instance of ZigbeeEntity.
|
|
64
|
-
*
|
|
65
|
-
* @param {ZigbeePlatform} platform - The Zigbee platform instance.
|
|
66
|
-
* @param {BridgeDevice | BridgeGroup} entity - The bridge device or group instance received from zigbee2mqtt.
|
|
67
|
-
*/
|
|
68
33
|
constructor(platform, entity) {
|
|
69
34
|
super();
|
|
70
35
|
this.platform = platform;
|
|
@@ -82,26 +47,22 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
82
47
|
this.en = gn;
|
|
83
48
|
this.ien = ign;
|
|
84
49
|
}
|
|
85
|
-
this.log = new AnsiLogger({ logName: this.entityName, logTimestampFormat: 4
|
|
50
|
+
this.log = new AnsiLogger({ logName: this.entityName, logTimestampFormat: 4, logLevel: platform.debugEnabled ? "debug" : "info" });
|
|
86
51
|
this.log.debug(`Created MatterEntity: ${this.entityName}`);
|
|
87
52
|
this.platform.z2m.on('MESSAGE-' + this.entityName, (payload) => {
|
|
88
|
-
// Check if the message is a duplicate that can be ingored cause only linkquality and last_seen have changed (action is always passed)
|
|
89
53
|
const now = Date.now();
|
|
90
54
|
if (now - this.lastSeen < 1000 * 60 && deepEqual(this.lastPayload, payload, ['linkquality', 'last_seen', ...this.ignoreFeatures]) && !Object.prototype.hasOwnProperty.call(this.lastPayload, 'action')) {
|
|
91
55
|
this.log.debug(`Skipping not changed ${platform.z2mDevicesRegistered ? 'MQTT message' : 'State update'} for accessory ${this.entityName}`);
|
|
92
56
|
return;
|
|
93
57
|
}
|
|
94
58
|
this.lastSeen = Date.now();
|
|
95
|
-
// Check and deep copy the payload
|
|
96
59
|
if (deepEqual(this.lastPayload, payload, this.ignoreFeatures))
|
|
97
60
|
return;
|
|
98
61
|
this.lastPayload = deepCopy(payload);
|
|
99
62
|
if (Object.prototype.hasOwnProperty.call(this.lastPayload, 'action'))
|
|
100
63
|
delete this.lastPayload.action;
|
|
101
|
-
// Remove each key in ignoreFeatures from the payload copy
|
|
102
64
|
for (const key of this.ignoreFeatures) {
|
|
103
65
|
if (Object.prototype.hasOwnProperty.call(payload, key)) {
|
|
104
|
-
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
|
105
66
|
delete payload[key];
|
|
106
67
|
this.log.debug(`Removed key ${CYAN}${key}${db} from payload`);
|
|
107
68
|
}
|
|
@@ -115,24 +76,19 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
115
76
|
return;
|
|
116
77
|
}
|
|
117
78
|
this.log.info(`${db}${platform.z2mDevicesRegistered ? 'MQTT message' : 'State update'} for device ${this.ien}${this.entityName}${rs}${db} payload: ${debugStringify(payload)}`);
|
|
118
|
-
// Parse the payload and update the accessory
|
|
119
79
|
Object.entries(payload).forEach(([key, value]) => {
|
|
120
|
-
// Skip null and undefined values
|
|
121
80
|
if (value === undefined || value === null)
|
|
122
81
|
return;
|
|
123
82
|
if (this.bridgedDevice === undefined || this.noUpdate)
|
|
124
83
|
return;
|
|
125
|
-
// Modify voltage to battery_voltage
|
|
126
84
|
if (key === 'voltage' && this.isDevice && this.device?.power_source === 'Battery')
|
|
127
85
|
key = 'battery_voltage';
|
|
128
|
-
// Modify illuminance and illuminance_lux
|
|
129
86
|
if (key === 'illuminance' && this.isDevice && this.device && this.device.definition && ['RTCGQ14LM'].includes(this.device.definition.model)) {
|
|
130
87
|
key = 'illuminance_lux';
|
|
131
88
|
}
|
|
132
89
|
if (key === 'illuminance' && typeof value === 'number' && this.isDevice && this.device && this.device.definition && ['ZG-204ZL', 'ZG-205Z/A'].includes(this.device.definition.model)) {
|
|
133
90
|
value = value * 10;
|
|
134
91
|
}
|
|
135
|
-
// Lookup the property in the propertyMap and ZigbeeToMatter table
|
|
136
92
|
const propertyMap = this.propertyMap.get(key);
|
|
137
93
|
if (propertyMap) {
|
|
138
94
|
this.log.debug(`Payload entry ${CYAN}${key}${db} => name: ${CYAN}${propertyMap.name}${db} type: ${CYAN}${propertyMap.type === '' ? 'generic' : propertyMap.type}${db} ` +
|
|
@@ -152,11 +108,9 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
152
108
|
}
|
|
153
109
|
else
|
|
154
110
|
this.log.debug(`*Payload entry ${CYAN}${key}${db} not found in propertyMap`);
|
|
155
|
-
// Switch actions on the endpoints
|
|
156
111
|
if (key === 'action' && value !== '') {
|
|
157
112
|
const propertyMap = this.propertyMap.get(('action_' + value));
|
|
158
113
|
if (propertyMap) {
|
|
159
|
-
// this.log.debug(`Payload entry ${CYAN}${value}${db} => name: ${CYAN}${propertyMap.name}${db} endpoint: ${CYAN}${propertyMap.endpoint}${db} action: ${CYAN}${propertyMap.action}${db}`);
|
|
160
114
|
const child = this.bridgedDevice.getChildEndpointByName(propertyMap.endpoint);
|
|
161
115
|
if (child && child.number)
|
|
162
116
|
this.bridgedDevice.triggerSwitchEvent(propertyMap.action, this.log, child);
|
|
@@ -164,9 +118,6 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
164
118
|
else
|
|
165
119
|
this.log.debug(`*Payload entry ${CYAN}${('action_' + value)}${db} not found in propertyMap`);
|
|
166
120
|
}
|
|
167
|
-
// WindowCovering
|
|
168
|
-
// Zigbee2MQTT cover: 0 = open, 100 = closed
|
|
169
|
-
// Matter WindowCovering: 0 = open 10000 = closed
|
|
170
121
|
if (key === 'position' && this.isDevice && isValidNumber(value, 0, 100)) {
|
|
171
122
|
this.updateAttributeIfChanged(this.bridgedDevice, undefined, WindowCovering.Cluster.id, 'currentPositionLiftPercent100ths', value * 100);
|
|
172
123
|
}
|
|
@@ -187,12 +138,10 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
187
138
|
this.updateAttributeIfChanged(this.bridgedDevice, undefined, WindowCovering.Cluster.id, 'targetPositionLiftPercent100ths', position);
|
|
188
139
|
}
|
|
189
140
|
}
|
|
190
|
-
// ColorControl colorTemperatureMired and colorMode
|
|
191
141
|
if (key === 'color_temp' && 'color_mode' in payload && payload['color_mode'] === 'color_temp') {
|
|
192
142
|
this.updateAttributeIfChanged(this.bridgedDevice, undefined, ColorControl.Cluster.id, 'colorTemperatureMireds', Math.max(147, Math.min(500, typeof value === 'number' ? value : 0)));
|
|
193
143
|
this.updateAttributeIfChanged(this.bridgedDevice, undefined, ColorControl.Cluster.id, 'colorMode', ColorControl.ColorMode.ColorTemperatureMireds);
|
|
194
144
|
}
|
|
195
|
-
// ColorControl currentHue, currentSaturation and colorMode
|
|
196
145
|
if (key === 'color' && 'color_mode' in payload && payload['color_mode'] === 'xy') {
|
|
197
146
|
const { x, y } = value;
|
|
198
147
|
const hsl = color.xyToHsl(x, y);
|
|
@@ -220,13 +169,6 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
220
169
|
}
|
|
221
170
|
});
|
|
222
171
|
}
|
|
223
|
-
/**
|
|
224
|
-
* Destroys the ZigbeeEntity instance by clearing any active timeouts.
|
|
225
|
-
*
|
|
226
|
-
* @remarks
|
|
227
|
-
* This method is used to clean up the ZigbeeEntity instance by clearing any active timeouts for color and thermostat operations.
|
|
228
|
-
* It ensures that no further actions are taken on these timeouts after the entity is destroyed.
|
|
229
|
-
*/
|
|
230
172
|
destroy() {
|
|
231
173
|
if (this.colorTimeout)
|
|
232
174
|
clearTimeout(this.colorTimeout);
|
|
@@ -235,22 +177,6 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
235
177
|
clearTimeout(this.thermostatTimeout);
|
|
236
178
|
this.thermostatTimeout = undefined;
|
|
237
179
|
}
|
|
238
|
-
/**
|
|
239
|
-
* Creates a mutable device with the specified definition and includes the specified server list.
|
|
240
|
-
*
|
|
241
|
-
* @param {DeviceTypeDefinition | AtLeastOne<DeviceTypeDefinition>} definition - The device type definition.
|
|
242
|
-
* @param {ClusterId[]} [includeServerList=[]] - The list of server clusters to include.
|
|
243
|
-
* @param {EndpointOptions} [options] - Optional endpoint options.
|
|
244
|
-
* @param {boolean} [debug] - Optional debug flag.
|
|
245
|
-
* @returns {MatterbridgeDevice} The created mutable device.
|
|
246
|
-
*
|
|
247
|
-
* @remarks
|
|
248
|
-
* This method creates a mutable device based on the provided definition. It adds the specified server clusters
|
|
249
|
-
* to the device and configures the device with basic information and power source clusters. If the device is a
|
|
250
|
-
* coordinator, it sets up the basic information cluster with coordinator-specific details. If the device is a
|
|
251
|
-
* group, it sets up the basic information cluster with group-specific details. The method also configures the
|
|
252
|
-
* power source cluster based on the device's power source.
|
|
253
|
-
*/
|
|
254
180
|
async createMutableDevice(definition, options, debug) {
|
|
255
181
|
if (this.platform.matterbridge.edge === true) {
|
|
256
182
|
this.bridgedDevice = (await MatterbridgeEndpoint.loadInstance(definition, options, debug));
|
|
@@ -263,7 +189,6 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
263
189
|
getBridgedDeviceBasicInformation() {
|
|
264
190
|
if (!this.bridgedDevice)
|
|
265
191
|
throw new Error('No bridged device');
|
|
266
|
-
// Add BridgedDeviceBasicInformation cluster and device type
|
|
267
192
|
const softwareVersion = parseInt(this.platform.z2mBridgeInfo?.version || '1');
|
|
268
193
|
const softwareVersionString = `${this.platform.z2mBridgeInfo?.version} (commit ${this.platform.z2mBridgeInfo?.commit})`;
|
|
269
194
|
const hardwareVersion = parseInt(this.platform.matterbridge.matterbridgeVersion || '1');
|
|
@@ -281,7 +206,6 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
281
206
|
addBridgedDeviceBasicInformation() {
|
|
282
207
|
if (!this.bridgedDevice)
|
|
283
208
|
throw new Error('No bridged device');
|
|
284
|
-
// Add BridgedDeviceBasicInformation cluster and device type
|
|
285
209
|
this.bridgedDevice.addDeviceType(bridgedNode);
|
|
286
210
|
this.bridgedDevice.addClusterServer(this.getBridgedDeviceBasicInformation());
|
|
287
211
|
return this.bridgedDevice;
|
|
@@ -302,26 +226,13 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
302
226
|
addPowerSource() {
|
|
303
227
|
if (!this.bridgedDevice)
|
|
304
228
|
throw new Error('No bridged device');
|
|
305
|
-
// Add PowerSource device type and cluster
|
|
306
229
|
this.bridgedDevice.addDeviceType(powerSource);
|
|
307
230
|
this.bridgedDevice.addClusterServer(this.getPowerSource());
|
|
308
231
|
return this.bridgedDevice;
|
|
309
232
|
}
|
|
310
|
-
/**
|
|
311
|
-
* Verifies that all required server clusters are present on the main endpoint and child endpoints.
|
|
312
|
-
*
|
|
313
|
-
* @param {MatterbridgeDevice} endpoint - The device endpoint to verify.
|
|
314
|
-
* @returns {boolean} True if all required server clusters are present, false otherwise.
|
|
315
|
-
*
|
|
316
|
-
* @remarks
|
|
317
|
-
* This method checks if all required server clusters are present on the main endpoint and its child endpoints.
|
|
318
|
-
* It logs an error message if any required server cluster is missing and returns false. If all required server
|
|
319
|
-
* clusters are present, it returns true.
|
|
320
|
-
*/
|
|
321
233
|
verifyMutableDevice(endpoint) {
|
|
322
234
|
if (!endpoint)
|
|
323
235
|
return false;
|
|
324
|
-
// Verify that all required server clusters are present in the main endpoint and in the child endpoints
|
|
325
236
|
for (const deviceType of endpoint.getDeviceTypes()) {
|
|
326
237
|
for (const clusterId of deviceType.requiredServerClusters) {
|
|
327
238
|
if (!endpoint.getClusterServerById(clusterId)) {
|
|
@@ -330,7 +241,6 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
330
241
|
}
|
|
331
242
|
}
|
|
332
243
|
}
|
|
333
|
-
// Verify that all required server clusters are present in the child endpoints
|
|
334
244
|
for (const childEndpoint of endpoint.getChildEndpoints()) {
|
|
335
245
|
for (const deviceType of childEndpoint.getDeviceTypes()) {
|
|
336
246
|
for (const clusterId of deviceType.requiredServerClusters) {
|
|
@@ -343,17 +253,6 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
343
253
|
}
|
|
344
254
|
return true;
|
|
345
255
|
}
|
|
346
|
-
/**
|
|
347
|
-
* Configures the device by setting up the WindowCovering and DoorLock clusters if they are present.
|
|
348
|
-
*
|
|
349
|
-
* @returns {Promise<void>} A promise that resolves when the configuration is complete.
|
|
350
|
-
*
|
|
351
|
-
* @remarks
|
|
352
|
-
* This method configures the device by checking for the presence of the WindowCovering and DoorLock clusters.
|
|
353
|
-
* If the WindowCovering cluster is present, it sets the target as the current position and stops any ongoing
|
|
354
|
-
* movement. If the DoorLock cluster is present, it retrieves the lock state and triggers the appropriate lock
|
|
355
|
-
* operation event based on the current state.
|
|
356
|
-
*/
|
|
357
256
|
async configure() {
|
|
358
257
|
if (this.bridgedDevice?.getClusterServerById(WindowCovering.Cluster.id)) {
|
|
359
258
|
this.log.info(`Configuring ${this.bridgedDevice?.deviceName} WindowCovering cluster`);
|
|
@@ -370,22 +269,6 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
370
269
|
}
|
|
371
270
|
}
|
|
372
271
|
}
|
|
373
|
-
/**
|
|
374
|
-
* Updates the attribute of a cluster on a device endpoint if the value has changed.
|
|
375
|
-
*
|
|
376
|
-
* @param {Endpoint} deviceEndpoint - The device endpoint to update.
|
|
377
|
-
* @param {string | undefined} childEndpointName - The name of the child endpoint, if any.
|
|
378
|
-
* @param {number} clusterId - The ID of the cluster to update.
|
|
379
|
-
* @param {string} attributeName - The name of the attribute to update.
|
|
380
|
-
* @param {PayloadValue} value - The new value of the attribute.
|
|
381
|
-
* @param {string[]} [lookup] - Optional lookup array for converting string values to indices.
|
|
382
|
-
*
|
|
383
|
-
* @remarks
|
|
384
|
-
* This method checks if the specified attribute of a cluster on a device endpoint has changed. If the attribute
|
|
385
|
-
* has changed, it updates the attribute with the new value. If a lookup array is provided, it converts string
|
|
386
|
-
* values to their corresponding indices in the lookup array. The method logs the update process and handles any
|
|
387
|
-
* errors that occur during the update.
|
|
388
|
-
*/
|
|
389
272
|
updateAttributeIfChanged(deviceEndpoint, childEndpointName, clusterId, attributeName, value, lookup) {
|
|
390
273
|
if (childEndpointName && childEndpointName !== '') {
|
|
391
274
|
deviceEndpoint = this.bridgedDevice?.getChildEndpointByName(childEndpointName) ?? deviceEndpoint;
|
|
@@ -424,18 +307,6 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
424
307
|
this.log.error(`Error setting attribute ${hk}${getClusterNameById(ClusterId(clusterId))}${er}.${hk}${attributeName}${er} to ${value}: ${error}`);
|
|
425
308
|
}
|
|
426
309
|
}
|
|
427
|
-
/**
|
|
428
|
-
* Publishes a command to the specified entity with the given payload.
|
|
429
|
-
*
|
|
430
|
-
* @param {string} command - The command to execute.
|
|
431
|
-
* @param {string} entityName - The name of the entity to publish the command to.
|
|
432
|
-
* @param {Payload} payload - The payload of the command.
|
|
433
|
-
*
|
|
434
|
-
* @remarks
|
|
435
|
-
* This method logs the execution of the command and publishes the command to the specified entity.
|
|
436
|
-
* If the entity name starts with 'bridge/request', it publishes the payload without a 'set' suffix.
|
|
437
|
-
* Otherwise, it publishes the payload with a 'set' suffix.
|
|
438
|
-
*/
|
|
439
310
|
publishCommand(command, entityName, payload) {
|
|
440
311
|
this.log.debug(`executeCommand ${command} called for ${this.ien}${entityName}${rs}${db} payload: ${debugStringify(payload)}`);
|
|
441
312
|
if (entityName.startsWith('bridge/request')) {
|
|
@@ -445,16 +316,7 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
445
316
|
this.platform.publish(entityName, 'set', JSON.stringify(payload));
|
|
446
317
|
}
|
|
447
318
|
}
|
|
448
|
-
/**
|
|
449
|
-
* Logs the property map of the Zigbee entity.
|
|
450
|
-
*
|
|
451
|
-
* @remarks
|
|
452
|
-
* This method iterates over the property map of the Zigbee entity and logs each property's details,
|
|
453
|
-
* including its name, type, values, minimum and maximum values, unit, and endpoint.
|
|
454
|
-
*/
|
|
455
|
-
// zigbeeDevice.propertyMap.set(property, { name, type, endpoint, category, description, label, unit, value_min, value_max, values: value });
|
|
456
319
|
logPropertyMap() {
|
|
457
|
-
// Log properties
|
|
458
320
|
this.propertyMap.forEach((value, key) => {
|
|
459
321
|
this.log.debug(`Property ${CYAN}${key}${db} name ${CYAN}${value.name}${db} type ${CYAN}${value.type === '' ? 'generic' : value.type}${db} endpoint ${CYAN}${value.endpoint === '' ? 'main' : value.endpoint}${db} ` +
|
|
460
322
|
`category ${CYAN}${value.category}${db} description ${CYAN}${value.description}${db} label ${CYAN}${value.label}${db} unit ${CYAN}${value.unit}${db} ` +
|
|
@@ -462,33 +324,10 @@ export class ZigbeeEntity extends EventEmitter {
|
|
|
462
324
|
});
|
|
463
325
|
}
|
|
464
326
|
}
|
|
465
|
-
/**
|
|
466
|
-
* Represents a Zigbee group entity.
|
|
467
|
-
*
|
|
468
|
-
* @class
|
|
469
|
-
* @extends {ZigbeeEntity}
|
|
470
|
-
*/
|
|
471
327
|
export class ZigbeeGroup extends ZigbeeEntity {
|
|
472
|
-
/**
|
|
473
|
-
* Creates an instance of ZigbeeGroup.
|
|
474
|
-
*
|
|
475
|
-
* @param {ZigbeePlatform} platform - The Zigbee platform instance.
|
|
476
|
-
* @param {BridgeGroup} group - The bridge group instance.
|
|
477
|
-
*/
|
|
478
328
|
constructor(platform, group) {
|
|
479
329
|
super(platform, group);
|
|
480
330
|
}
|
|
481
|
-
/**
|
|
482
|
-
* Creates a new ZigbeeGroup instance.
|
|
483
|
-
*
|
|
484
|
-
* @param {ZigbeePlatform} platform - The Zigbee platform instance.
|
|
485
|
-
* @param {BridgeGroup} group - The bridge group instance.
|
|
486
|
-
* @returns {Promise<ZigbeeGroup>} A promise that resolves to the created ZigbeeGroup instance.
|
|
487
|
-
*
|
|
488
|
-
* @remarks
|
|
489
|
-
* This method initializes a new ZigbeeGroup instance, sets up its properties, and configures the device
|
|
490
|
-
* based on the group members. It also adds command handlers for the group.
|
|
491
|
-
*/
|
|
492
331
|
static async create(platform, group) {
|
|
493
332
|
const zigbeeGroup = new ZigbeeGroup(platform, group);
|
|
494
333
|
if (zigbeeGroup.platform.postfixHostname) {
|
|
@@ -508,23 +347,19 @@ export class ZigbeeGroup extends ZigbeeEntity {
|
|
|
508
347
|
let isCover = false;
|
|
509
348
|
let isThermostat = false;
|
|
510
349
|
if (group.members.length === 0) {
|
|
511
|
-
// Create a virtual device for the empty group to use in automations
|
|
512
350
|
zigbeeGroup.log.debug(`Group: ${gn}${group.friendly_name}${rs}${db} is a ${CYAN}virtual${db} group`);
|
|
513
|
-
zigbeeGroup.bridgedDevice = await zigbeeGroup.createMutableDevice([onOffSwitch], { uniqueStorageKey: group.friendly_name }, zigbeeGroup.log.logLevel === "debug"
|
|
351
|
+
zigbeeGroup.bridgedDevice = await zigbeeGroup.createMutableDevice([onOffSwitch], { uniqueStorageKey: group.friendly_name }, zigbeeGroup.log.logLevel === "debug");
|
|
514
352
|
isSwitch = true;
|
|
515
353
|
zigbeeGroup.propertyMap.set('state', { name: 'state', type: 'switch', endpoint: '' });
|
|
516
354
|
}
|
|
517
355
|
else {
|
|
518
|
-
// Create a switch or light or outlet device for the group
|
|
519
356
|
group.members.forEach((member) => {
|
|
520
|
-
// const device = zigbeeGroup.platform.z2m.getDevice(member.ieee_address);
|
|
521
357
|
const device = zigbeeGroup.platform.z2mBridgeDevices?.find((device) => device.ieee_address === member.ieee_address);
|
|
522
358
|
if (!device)
|
|
523
359
|
return;
|
|
524
360
|
zigbeeGroup.log.debug(`Group ${gn}${group.friendly_name}${db}: member device ${dn}${device.friendly_name}${db}`);
|
|
525
361
|
device.definition?.exposes.forEach((expose) => {
|
|
526
362
|
if (expose.features) {
|
|
527
|
-
// Specific features with type
|
|
528
363
|
expose.features?.forEach((feature) => {
|
|
529
364
|
if (expose.type === 'lock' && feature.name === 'state' && feature.property === 'child_lock') {
|
|
530
365
|
expose.type = 'child_lock';
|
|
@@ -554,7 +389,6 @@ export class ZigbeeGroup extends ZigbeeEntity {
|
|
|
554
389
|
});
|
|
555
390
|
}
|
|
556
391
|
else {
|
|
557
|
-
// Generic features without type
|
|
558
392
|
zigbeeGroup.log.debug(`- generic type ${CYAN}${expose.type}${db} expose name ${CYAN}${expose.name}${db} property ${CYAN}${expose.property}${db}`);
|
|
559
393
|
}
|
|
560
394
|
});
|
|
@@ -600,17 +434,14 @@ export class ZigbeeGroup extends ZigbeeEntity {
|
|
|
600
434
|
}
|
|
601
435
|
if (!deviceType)
|
|
602
436
|
return zigbeeGroup;
|
|
603
|
-
zigbeeGroup.bridgedDevice = await zigbeeGroup.createMutableDevice([deviceType], { uniqueStorageKey: group.friendly_name }, zigbeeGroup.log.logLevel === "debug"
|
|
437
|
+
zigbeeGroup.bridgedDevice = await zigbeeGroup.createMutableDevice([deviceType], { uniqueStorageKey: group.friendly_name }, zigbeeGroup.log.logLevel === "debug");
|
|
604
438
|
}
|
|
605
439
|
zigbeeGroup.addBridgedDeviceBasicInformation();
|
|
606
440
|
zigbeeGroup.addPowerSource();
|
|
607
441
|
zigbeeGroup.bridgedDevice.addRequiredClusterServers(zigbeeGroup.bridgedDevice);
|
|
608
|
-
// Verify the device
|
|
609
442
|
if (!zigbeeGroup.bridgedDevice || !zigbeeGroup.verifyMutableDevice(zigbeeGroup.bridgedDevice))
|
|
610
443
|
return zigbeeGroup;
|
|
611
|
-
// Log properties
|
|
612
444
|
zigbeeGroup.logPropertyMap();
|
|
613
|
-
// Add command handlers
|
|
614
445
|
if (isSwitch || isLight) {
|
|
615
446
|
if (isSwitch)
|
|
616
447
|
await zigbeeGroup.bridgedDevice.addFixedLabel('type', 'switch');
|
|
@@ -618,7 +449,6 @@ export class ZigbeeGroup extends ZigbeeEntity {
|
|
|
618
449
|
await zigbeeGroup.bridgedDevice.addFixedLabel('type', 'light');
|
|
619
450
|
zigbeeGroup.bridgedDevice.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
|
|
620
451
|
zigbeeGroup.log.warn(`Command identify called for ${zigbeeGroup.ien}${group.friendly_name}${rs}${db} identifyTime:${identifyTime}`);
|
|
621
|
-
// logEndpoint(zigbeeGroup.bridgedDevice!);
|
|
622
452
|
});
|
|
623
453
|
zigbeeGroup.bridgedDevice.addCommandHandler('on', async () => {
|
|
624
454
|
zigbeeGroup.log.debug(`Command on called for ${zigbeeGroup.ien}${group.friendly_name}${rs}${db}`);
|
|
@@ -710,7 +540,6 @@ export class ZigbeeGroup extends ZigbeeEntity {
|
|
|
710
540
|
zigbeeGroup.bridgedDevice.subscribeAttribute(ThermostatCluster.id, 'systemMode', (newValue, oldValue) => {
|
|
711
541
|
zigbeeGroup.bridgedDevice?.log.info(`Thermostat systemMode changed from ${oldValue} to ${newValue}`);
|
|
712
542
|
if (oldValue !== newValue) {
|
|
713
|
-
// Thermostat.SystemMode.Heat && newValue === Thermostat.SystemMode.Off
|
|
714
543
|
zigbeeGroup.bridgedDevice?.log.info(`Setting thermostat systemMode to ${newValue}`);
|
|
715
544
|
if (newValue === Thermostat.SystemMode.Off) {
|
|
716
545
|
zigbeeGroup.publishCommand('SystemMode', group.friendly_name, { system_mode: 'off' });
|
|
@@ -751,7 +580,6 @@ export class ZigbeeGroup extends ZigbeeEntity {
|
|
|
751
580
|
return zigbeeGroup;
|
|
752
581
|
}
|
|
753
582
|
}
|
|
754
|
-
// prettier-ignore
|
|
755
583
|
export const z2ms = [
|
|
756
584
|
{ type: 'switch', name: 'state', property: 'state', deviceType: onOffSwitch, cluster: OnOff.Cluster.id, attribute: 'onOff', converter: (value) => { return value === 'ON' ? true : false; } },
|
|
757
585
|
{ type: 'switch', name: 'brightness', property: 'brightness', deviceType: dimmableSwitch, cluster: LevelControl.Cluster.id, attribute: 'currentLevel', converter: (value) => { return Math.max(0, Math.min(254, value)); } },
|
|
@@ -811,43 +639,19 @@ export const z2ms = [
|
|
|
811
639
|
{ type: '', name: 'voltage', property: 'voltage', deviceType: electricalSensor, cluster: ElectricalPowerMeasurement.Cluster.id, attribute: 'voltage', converter: (value) => { return value * 1000; } },
|
|
812
640
|
{ type: '', name: 'current', property: 'current', deviceType: electricalSensor, cluster: ElectricalPowerMeasurement.Cluster.id, attribute: 'activeCurrent', converter: (value) => { return value * 1000; } },
|
|
813
641
|
];
|
|
814
|
-
/**
|
|
815
|
-
* Represents a Zigbee device entity.
|
|
816
|
-
*
|
|
817
|
-
* @class
|
|
818
|
-
* @extends {ZigbeeEntity}
|
|
819
|
-
*/
|
|
820
642
|
export class ZigbeeDevice extends ZigbeeEntity {
|
|
821
|
-
/**
|
|
822
|
-
* Represents a Zigbee device entity.
|
|
823
|
-
*
|
|
824
|
-
* @class
|
|
825
|
-
* @extends {ZigbeeEntity}
|
|
826
|
-
*/
|
|
827
643
|
constructor(platform, device) {
|
|
828
644
|
super(platform, device);
|
|
829
645
|
}
|
|
830
|
-
/**
|
|
831
|
-
* Creates a new ZigbeeDevice instance.
|
|
832
|
-
*
|
|
833
|
-
* @param {ZigbeePlatform} platform - The Zigbee platform instance.
|
|
834
|
-
* @param {BridgeDevice} device - The bridge device instance.
|
|
835
|
-
* @returns {Promise<ZigbeeDevice>} A promise that resolves to the created ZigbeeDevice instance.
|
|
836
|
-
*
|
|
837
|
-
* @remarks
|
|
838
|
-
* This method initializes a new ZigbeeDevice instance, sets up its properties, and configures the device
|
|
839
|
-
* based on the device definition and options. It also adds command handlers for the device.
|
|
840
|
-
*/
|
|
841
646
|
static async create(platform, device) {
|
|
842
647
|
const zigbeeDevice = new ZigbeeDevice(platform, device);
|
|
843
648
|
zigbeeDevice.serial = `${device.ieee_address}`;
|
|
844
649
|
if (zigbeeDevice.platform.postfixHostname) {
|
|
845
650
|
zigbeeDevice.serial = `${zigbeeDevice.serial}_${hostname}`.slice(0, 32);
|
|
846
651
|
}
|
|
847
|
-
// Set Coordinator and dedicated routers
|
|
848
652
|
if (device.friendly_name === 'Coordinator' || (device.model_id === 'ti.router' && device.manufacturer === 'TexasInstruments') || (device.model_id.startsWith('SLZB-') && device.manufacturer === 'SMLIGHT')) {
|
|
849
653
|
zigbeeDevice.isRouter = true;
|
|
850
|
-
zigbeeDevice.bridgedDevice = await zigbeeDevice.createMutableDevice([doorLockDevice], { uniqueStorageKey: device.friendly_name }, zigbeeDevice.log.logLevel === "debug"
|
|
654
|
+
zigbeeDevice.bridgedDevice = await zigbeeDevice.createMutableDevice([doorLockDevice], { uniqueStorageKey: device.friendly_name }, zigbeeDevice.log.logLevel === "debug");
|
|
851
655
|
zigbeeDevice.addBridgedDeviceBasicInformation();
|
|
852
656
|
zigbeeDevice.addPowerSource();
|
|
853
657
|
zigbeeDevice.bridgedDevice.addRequiredClusterServers(zigbeeDevice.bridgedDevice);
|
|
@@ -865,7 +669,6 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
865
669
|
});
|
|
866
670
|
return zigbeeDevice;
|
|
867
671
|
}
|
|
868
|
-
// Get types and properties
|
|
869
672
|
const types = [];
|
|
870
673
|
const endpoints = [];
|
|
871
674
|
const names = [];
|
|
@@ -879,7 +682,6 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
879
682
|
const values = [];
|
|
880
683
|
device.definition?.exposes.forEach((expose) => {
|
|
881
684
|
if (expose.features) {
|
|
882
|
-
// Specific features with type
|
|
883
685
|
expose.features?.forEach((feature) => {
|
|
884
686
|
if (expose.type === 'lock' && feature.name === 'state' && feature.property === 'child_lock')
|
|
885
687
|
feature.name = 'child_lock';
|
|
@@ -897,17 +699,10 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
897
699
|
});
|
|
898
700
|
}
|
|
899
701
|
else {
|
|
900
|
-
// Generic features without type
|
|
901
|
-
// Change voltage to battery_voltage for battery powered devices
|
|
902
702
|
if (device.power_source === 'Battery' && expose.name === 'voltage')
|
|
903
703
|
expose.name = 'battery_voltage';
|
|
904
704
|
if (device.power_source === 'Battery' && expose.property === 'voltage')
|
|
905
705
|
expose.property = 'battery_voltage';
|
|
906
|
-
// Fix illuminance and illuminance_lux for light sensors:
|
|
907
|
-
// illuminance is raw value (use like it is)
|
|
908
|
-
// illuminance_lux is in lux (convert with log10)
|
|
909
|
-
// illuminance has description "Raw measured illuminance"
|
|
910
|
-
// illuminance_lux has description "Measured illuminance in lux"
|
|
911
706
|
if (expose.description === 'Raw measured illuminance') {
|
|
912
707
|
expose.name = 'illuminance';
|
|
913
708
|
expose.property = 'illuminance';
|
|
@@ -968,16 +763,6 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
968
763
|
zigbeeDevice.ignoreFeatures = [...zigbeeDevice.ignoreFeatures, ...platform.featureBlackList];
|
|
969
764
|
if (platform.deviceFeatureBlackList[device.friendly_name])
|
|
970
765
|
zigbeeDevice.ignoreFeatures = [...zigbeeDevice.ignoreFeatures, ...platform.deviceFeatureBlackList[device.friendly_name]];
|
|
971
|
-
/*
|
|
972
|
-
zigbeeDevice.log.debug(`Device ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} - types[${types.length}]: ${debugStringify(types)}`);
|
|
973
|
-
zigbeeDevice.log.debug(`Device ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} - endpoints[${endpoints.length}]: ${debugStringify(endpoints)}`);
|
|
974
|
-
zigbeeDevice.log.debug(`Device ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} - names[${names.length}]: ${debugStringify(names)}`);
|
|
975
|
-
zigbeeDevice.log.debug(`Device ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} - properties[${properties.length}]: ${debugStringify(properties)}`);
|
|
976
|
-
zigbeeDevice.log.debug(`Device ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} - categories[${categories.length}]: ${debugStringify(categories)}`);
|
|
977
|
-
zigbeeDevice.log.debug(`Device ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} - descriptions[${descriptions.length}]: ${debugStringify(descriptions)}`);
|
|
978
|
-
zigbeeDevice.log.debug(`Device ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} - labels[${labels.length}]: ${debugStringify(labels)}`);
|
|
979
|
-
zigbeeDevice.log.debug(`Device ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} - units[${units.length}]: ${debugStringify(units)}`);
|
|
980
|
-
*/
|
|
981
766
|
for (const [index, name] of names.entries()) {
|
|
982
767
|
if (platform.featureBlackList.includes(name)) {
|
|
983
768
|
zigbeeDevice.log.debug(`Device ${zigbeeDevice.en}${device.friendly_name}${db} feature ${name} is globally blacklisted`);
|
|
@@ -1006,7 +791,6 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1006
791
|
zigbeeDevice.log.debug(`Device ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${zb}${endpoint}${db} type: ${zb}${type}${db} property: ${zb}${name}${db} => deviceType: ${z2m.deviceType?.name} cluster: ${z2m.cluster} attribute: ${z2m.attribute}`);
|
|
1007
792
|
zigbeeDevice.propertyMap.set(property, { name, type, endpoint, category, description, label, unit, value_min, value_max, values: value });
|
|
1008
793
|
if (endpoint === '') {
|
|
1009
|
-
/* prettier-ignore */
|
|
1010
794
|
if (!zigbeeDevice.mutableDevice.has(endpoint)) {
|
|
1011
795
|
zigbeeDevice.mutableDevice.set(endpoint, { tagList: [], deviceTypes: [z2m.deviceType], clusterServersIds: [...z2m.deviceType.requiredServerClusters, ClusterId(z2m.cluster)], clusterServersObjs: [], clusterClientsIds: [], clusterClientsObjs: [] });
|
|
1012
796
|
}
|
|
@@ -1030,7 +814,6 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1030
814
|
if (endpoint === 'l6')
|
|
1031
815
|
tagList.push({ mfgCode: null, namespaceId: NumberTag.Six.namespaceId, tag: NumberTag.Six.tag, label: 'endpoint ' + endpoint });
|
|
1032
816
|
tagList.push({ mfgCode: null, namespaceId: SwitchesTag.Custom.namespaceId, tag: SwitchesTag.Custom.tag, label: 'endpoint ' + endpoint });
|
|
1033
|
-
/* prettier-ignore */
|
|
1034
817
|
if (!zigbeeDevice.mutableDevice.has(endpoint)) {
|
|
1035
818
|
zigbeeDevice.mutableDevice.set(endpoint, { tagList, deviceTypes: [z2m.deviceType], clusterServersIds: [...z2m.deviceType.requiredServerClusters, ClusterId(z2m.cluster)], clusterServersObjs: [], clusterClientsIds: [], clusterClientsObjs: [] });
|
|
1036
819
|
}
|
|
@@ -1044,16 +827,13 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1044
827
|
}
|
|
1045
828
|
}
|
|
1046
829
|
else {
|
|
1047
|
-
// zigbeeDevice.log.debug(`Device ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${zb}${endpoint}${db} type: ${zb}${type}${db} property: ${zb}${name}${db} => no mapping found`);
|
|
1048
830
|
}
|
|
1049
|
-
// Map actions to switches
|
|
1050
831
|
if (name === 'action' && zigbeeDevice.actions.length) {
|
|
1051
832
|
zigbeeDevice.log.info(`Device ${zigbeeDevice.ien}${device.friendly_name}${rs}${nf} has actions mapped to these switches on sub endpoints:`);
|
|
1052
833
|
zigbeeDevice.log.info(' controller events <=> zigbee2mqtt actions');
|
|
1053
834
|
if (!zigbeeDevice.bridgedDevice)
|
|
1054
|
-
zigbeeDevice.bridgedDevice = await zigbeeDevice.createMutableDevice([bridgedNode], { uniqueStorageKey: device.friendly_name }, zigbeeDevice.log.logLevel === "debug"
|
|
835
|
+
zigbeeDevice.bridgedDevice = await zigbeeDevice.createMutableDevice([bridgedNode], { uniqueStorageKey: device.friendly_name }, zigbeeDevice.log.logLevel === "debug");
|
|
1055
836
|
zigbeeDevice.hasEndpoints = true;
|
|
1056
|
-
// Mapping actions
|
|
1057
837
|
const switchMap = ['Single Press', 'Double Press', 'Long Press '];
|
|
1058
838
|
const triggerMap = ['Single', 'Double', 'Long'];
|
|
1059
839
|
let count = 1;
|
|
@@ -1086,7 +866,6 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1086
866
|
zigbeeDevice.composedType = 'button';
|
|
1087
867
|
}
|
|
1088
868
|
}
|
|
1089
|
-
// Add battery properties
|
|
1090
869
|
if (device.power_source === 'Battery') {
|
|
1091
870
|
zigbeeDevice.propertyMap.set('battery', { name: 'battery', type: '', endpoint: '' });
|
|
1092
871
|
zigbeeDevice.propertyMap.set('battery_low', { name: 'battery_low', type: '', endpoint: '' });
|
|
@@ -1097,7 +876,6 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1097
876
|
const mainEndpoint = zigbeeDevice.mutableDevice.get('');
|
|
1098
877
|
if (!mainEndpoint)
|
|
1099
878
|
return zigbeeDevice;
|
|
1100
|
-
// Remove superset device Types and order them
|
|
1101
879
|
for (const device of zigbeeDevice.mutableDevice.values()) {
|
|
1102
880
|
const deviceTypesMap = new Map();
|
|
1103
881
|
device.deviceTypes.forEach((deviceType) => {
|
|
@@ -1113,20 +891,15 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1113
891
|
deviceTypesMap.delete(onOffLight.code);
|
|
1114
892
|
if (deviceTypesMap.has(dimmableLight.code) && deviceTypesMap.has(colorTemperatureLight.code))
|
|
1115
893
|
deviceTypesMap.delete(dimmableLight.code);
|
|
1116
|
-
device.deviceTypes = Array.from(deviceTypesMap.values());
|
|
894
|
+
device.deviceTypes = Array.from(deviceTypesMap.values());
|
|
1117
895
|
}
|
|
1118
|
-
|
|
1119
|
-
zigbeeDevice.bridgedDevice = await zigbeeDevice.createMutableDevice(mainEndpoint.deviceTypes, { uniqueStorageKey: device.friendly_name }, zigbeeDevice.log.logLevel === "debug" /* LogLevel.DEBUG */);
|
|
1120
|
-
// Configure BridgedDeviceBasicInformation cluster
|
|
896
|
+
zigbeeDevice.bridgedDevice = await zigbeeDevice.createMutableDevice(mainEndpoint.deviceTypes, { uniqueStorageKey: device.friendly_name }, zigbeeDevice.log.logLevel === "debug");
|
|
1121
897
|
mainEndpoint.clusterServersObjs.push(zigbeeDevice.getBridgedDeviceBasicInformation());
|
|
1122
|
-
// Configure PowerSource cluster
|
|
1123
898
|
mainEndpoint.clusterServersObjs.push(zigbeeDevice.getPowerSource());
|
|
1124
|
-
// Configure ColorControlCluster
|
|
1125
899
|
if (mainEndpoint.clusterServersIds.includes(ColorControl.Cluster.id)) {
|
|
1126
900
|
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')}`);
|
|
1127
901
|
zigbeeDevice.bridgedDevice.configureColorControlCluster(names.includes('color_hs') || names.includes('color_xy'), false, names.includes('color_temp'));
|
|
1128
902
|
}
|
|
1129
|
-
// Configure ThermostatCluster
|
|
1130
903
|
if (mainEndpoint.clusterServersIds.includes(Thermostat.Cluster.id)) {
|
|
1131
904
|
const heat = zigbeeDevice.propertyMap.get('occupied_heating_setpoint') || zigbeeDevice.propertyMap.get('current_heating_setpoint');
|
|
1132
905
|
const cool = zigbeeDevice.propertyMap.get('occupied_cooling_setpoint') || zigbeeDevice.propertyMap.get('current_cooling_setpoint');
|
|
@@ -1137,20 +910,18 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1137
910
|
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} ` +
|
|
1138
911
|
`minHeating ${CYAN}${minHeating}${db} maxHeating ${CYAN}${maxHeating}${db} minCooling ${CYAN}${minCooling}${db} maxCooling ${CYAN}${maxCooling}${db}`);
|
|
1139
912
|
if (heat && !cool) {
|
|
1140
|
-
zigbeeDevice.propertyMap.delete('running_state');
|
|
913
|
+
zigbeeDevice.propertyMap.delete('running_state');
|
|
1141
914
|
mainEndpoint.clusterServersObjs.push(zigbeeDevice.bridgedDevice.getDefaultHeatingThermostatClusterServer(undefined, undefined, minHeating, maxHeating));
|
|
1142
915
|
}
|
|
1143
916
|
else if (!heat && cool) {
|
|
1144
|
-
zigbeeDevice.propertyMap.delete('running_state');
|
|
917
|
+
zigbeeDevice.propertyMap.delete('running_state');
|
|
1145
918
|
mainEndpoint.clusterServersObjs.push(zigbeeDevice.bridgedDevice.getDefaultCoolingThermostatClusterServer(undefined, undefined, minCooling, maxCooling));
|
|
1146
919
|
}
|
|
1147
920
|
else if (heat && cool) {
|
|
1148
921
|
mainEndpoint.clusterServersObjs.push(zigbeeDevice.bridgedDevice.getDefaultThermostatClusterServer(undefined, undefined, undefined, undefined, minHeating, maxHeating, minCooling, maxCooling));
|
|
1149
922
|
}
|
|
1150
923
|
}
|
|
1151
|
-
// Filter out duplicate server clusters and server clusters objects
|
|
1152
924
|
for (const [endpoint, device] of zigbeeDevice.mutableDevice) {
|
|
1153
|
-
// Filter out duplicate server clusters and server clusters objects
|
|
1154
925
|
const deviceClusterServersMap = new Map();
|
|
1155
926
|
device.clusterServersIds.forEach((clusterServer) => {
|
|
1156
927
|
deviceClusterServersMap.set(clusterServer, clusterServer);
|
|
@@ -1162,7 +933,6 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1162
933
|
});
|
|
1163
934
|
device.clusterServersIds = Array.from(deviceClusterServersMap.values());
|
|
1164
935
|
device.clusterServersObjs = Array.from(deviceClusterServersObjMap.values());
|
|
1165
|
-
// Filter out duplicate client clusters and client clusters objects
|
|
1166
936
|
const deviceClusterClientsMap = new Map();
|
|
1167
937
|
device.clusterClientsIds.forEach((clusterClient) => {
|
|
1168
938
|
deviceClusterClientsMap.set(clusterClient, clusterClient);
|
|
@@ -1177,7 +947,6 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1177
947
|
zigbeeDevice.log.debug(`Device ${zigbeeDevice.ien}${zigbeeDevice.device?.friendly_name}${rs}${db} endpoint: ${ign}${endpoint === '' ? 'main' : endpoint}${rs}${db} => ` +
|
|
1178
948
|
`${nf}tagList: ${debugStringify(device.tagList)} deviceTypes: ${debugStringify(device.deviceTypes)} clusterServersIds: ${debugStringify(device.clusterServersIds)}`);
|
|
1179
949
|
}
|
|
1180
|
-
// Add the clusters to the main endpoint
|
|
1181
950
|
mainEndpoint.clusterServersObjs.forEach((clusterServerObj) => {
|
|
1182
951
|
zigbeeDevice.bridgedDevice?.addClusterServer(clusterServerObj);
|
|
1183
952
|
});
|
|
@@ -1185,24 +954,19 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1185
954
|
zigbeeDevice.bridgedDevice.addRequiredClusterServers(zigbeeDevice.bridgedDevice);
|
|
1186
955
|
if (zigbeeDevice.composedType !== '')
|
|
1187
956
|
await zigbeeDevice.bridgedDevice.addFixedLabel('composed', zigbeeDevice.composedType);
|
|
1188
|
-
// Create the child endpoints
|
|
1189
957
|
for (const [endpoint, device] of zigbeeDevice.mutableDevice) {
|
|
1190
958
|
if (endpoint === '')
|
|
1191
959
|
continue;
|
|
1192
|
-
const child = zigbeeDevice.bridgedDevice?.addChildDeviceTypeWithClusterServer(endpoint, device.deviceTypes, device.clusterServersIds, { tagList: device.tagList }, zigbeeDevice.log.logLevel === "debug"
|
|
960
|
+
const child = zigbeeDevice.bridgedDevice?.addChildDeviceTypeWithClusterServer(endpoint, device.deviceTypes, device.clusterServersIds, { tagList: device.tagList }, zigbeeDevice.log.logLevel === "debug");
|
|
1193
961
|
device.clusterServersObjs.forEach((clusterServerObj) => {
|
|
1194
962
|
child.addClusterServer(clusterServerObj);
|
|
1195
963
|
});
|
|
1196
964
|
}
|
|
1197
|
-
// Verify the device
|
|
1198
965
|
if (!zigbeeDevice.verifyMutableDevice(zigbeeDevice.bridgedDevice))
|
|
1199
966
|
return zigbeeDevice;
|
|
1200
|
-
// Log properties
|
|
1201
967
|
zigbeeDevice.logPropertyMap();
|
|
1202
|
-
// Add command handlers
|
|
1203
968
|
zigbeeDevice.bridgedDevice.addCommandHandler('identify', async (data) => {
|
|
1204
969
|
zigbeeDevice.log.debug(`Command identify called for ${zigbeeDevice.ien}${device.friendly_name}${rs}${db} endpoint: ${data.endpoint.number} request identifyTime:${data.request.identifyTime} `);
|
|
1205
|
-
// logEndpoint(zigbeeDevice.bridgedDevice!);
|
|
1206
970
|
});
|
|
1207
971
|
if (zigbeeDevice.bridgedDevice.getClusterServerById(OnOffCluster.id) || zigbeeDevice.hasEndpoints) {
|
|
1208
972
|
for (const child of zigbeeDevice.bridgedDevice.getChildEndpoints()) {
|
|
@@ -1464,4 +1228,3 @@ export class ZigbeeDevice extends ZigbeeEntity {
|
|
|
1464
1228
|
return zigbeeDevice;
|
|
1465
1229
|
}
|
|
1466
1230
|
}
|
|
1467
|
-
//# sourceMappingURL=entity.js.map
|