matterbridge-zigbee2mqtt 2.0.0 → 2.0.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/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +9 -5
- package/dist/platform.js.map +1 -1
- package/link-matterbridge-script.js +0 -1
- package/package.json +4 -5
- package/.eslintignore +0 -2
- package/.eslintrc.json +0 -46
- package/.gitattributes +0 -2
- package/.prettierignore +0 -2
- package/.prettierrc.json +0 -12
- package/src/colorUtils.ts +0 -372
- package/src/entity.ts +0 -578
- package/src/index.ts +0 -42
- package/src/payloadTypes.ts +0 -28
- package/src/platform.ts +0 -257
- package/src/zigbee2mqtt.ts +0 -1202
- package/src/zigbee2mqttTypes.ts +0 -322
- package/tsconfig.json +0 -112
package/src/entity.ts
DELETED
|
@@ -1,578 +0,0 @@
|
|
|
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 2.0.0
|
|
8
|
-
*
|
|
9
|
-
* Copyright 2023, 2024 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
|
-
|
|
24
|
-
// matter.js imports
|
|
25
|
-
import {
|
|
26
|
-
DeviceTypes,
|
|
27
|
-
DeviceTypeDefinition,
|
|
28
|
-
logEndpoint,
|
|
29
|
-
AirQuality,
|
|
30
|
-
MatterbridgeDevice,
|
|
31
|
-
airQualitySensor,
|
|
32
|
-
colorTemperatureSwitch,
|
|
33
|
-
dimmableSwitch,
|
|
34
|
-
onOffSwitch,
|
|
35
|
-
BridgedDeviceBasicInformation,
|
|
36
|
-
Identify,
|
|
37
|
-
Groups,
|
|
38
|
-
Scenes,
|
|
39
|
-
OnOff,
|
|
40
|
-
LevelControl,
|
|
41
|
-
ColorControl,
|
|
42
|
-
ColorControlCluster,
|
|
43
|
-
Switch,
|
|
44
|
-
TemperatureMeasurement,
|
|
45
|
-
BooleanState,
|
|
46
|
-
RelativeHumidityMeasurement,
|
|
47
|
-
PressureMeasurement,
|
|
48
|
-
OccupancySensing,
|
|
49
|
-
IlluminanceMeasurement,
|
|
50
|
-
PowerSource,
|
|
51
|
-
ClusterId,
|
|
52
|
-
TvocMeasurement,
|
|
53
|
-
WindowCovering,
|
|
54
|
-
WindowCoveringCluster,
|
|
55
|
-
OnOffCluster,
|
|
56
|
-
LevelControlCluster,
|
|
57
|
-
} from 'matterbridge';
|
|
58
|
-
|
|
59
|
-
import { AnsiLogger, TimestampFormat, gn, dn, ign, idn, rs, db, nf, wr, stringify, debugStringify } from 'node-ansi-logger';
|
|
60
|
-
import { ZigbeePlatform } from './platform.js';
|
|
61
|
-
import { BridgeDevice, BridgeGroup } from './zigbee2mqttTypes.js';
|
|
62
|
-
import { Payload } from './payloadTypes.js';
|
|
63
|
-
import * as color from './colorUtils.js';
|
|
64
|
-
import EventEmitter from 'events';
|
|
65
|
-
import { hostname } from 'os';
|
|
66
|
-
|
|
67
|
-
export class ZigbeeEntity extends EventEmitter {
|
|
68
|
-
protected log: AnsiLogger;
|
|
69
|
-
protected platform: ZigbeePlatform;
|
|
70
|
-
public device: BridgeDevice | undefined;
|
|
71
|
-
public group: BridgeGroup | undefined;
|
|
72
|
-
protected accessoryName: string = '';
|
|
73
|
-
public isDevice: boolean = false;
|
|
74
|
-
public isGroup: boolean = false;
|
|
75
|
-
protected en = '';
|
|
76
|
-
protected ien = '';
|
|
77
|
-
public bridgedDevice: BridgedBaseDevice | undefined;
|
|
78
|
-
|
|
79
|
-
constructor(platform: ZigbeePlatform, entity: BridgeDevice | BridgeGroup) {
|
|
80
|
-
super();
|
|
81
|
-
this.platform = platform;
|
|
82
|
-
if ((entity as BridgeDevice).ieee_address !== undefined) {
|
|
83
|
-
this.device = entity as BridgeDevice;
|
|
84
|
-
this.accessoryName = entity.friendly_name;
|
|
85
|
-
this.isDevice = true;
|
|
86
|
-
this.en = dn;
|
|
87
|
-
this.ien = idn;
|
|
88
|
-
}
|
|
89
|
-
if ((entity as BridgeGroup).id !== undefined) {
|
|
90
|
-
this.group = entity as BridgeGroup;
|
|
91
|
-
this.accessoryName = entity.friendly_name;
|
|
92
|
-
this.isGroup = true;
|
|
93
|
-
this.en = gn;
|
|
94
|
-
this.ien = ign;
|
|
95
|
-
}
|
|
96
|
-
this.log = new AnsiLogger({ logName: this.accessoryName, logTimestampFormat: TimestampFormat.TIME_MILLIS, logDebug: platform.debugEnabled });
|
|
97
|
-
this.log.debug(`Created MatterEntity: ${this.accessoryName}`);
|
|
98
|
-
|
|
99
|
-
this.platform.z2m.on('MESSAGE-' + this.accessoryName, (payload: object) => {
|
|
100
|
-
if (this.bridgedDevice === undefined) return;
|
|
101
|
-
const debugEnabled = this.platform.debugEnabled;
|
|
102
|
-
this.log.setLogDebug(true);
|
|
103
|
-
this.log.debug(`MQTT message for accessory ${this.ien}${this.accessoryName}${rs}${db} payload: ${debugStringify(payload)}`);
|
|
104
|
-
this.log.setLogDebug(debugEnabled);
|
|
105
|
-
Object.entries(payload).forEach(([key, value]) => {
|
|
106
|
-
if (this.bridgedDevice === undefined) return;
|
|
107
|
-
if (key === 'position') {
|
|
108
|
-
this.bridgedDevice.getClusterServerById(WindowCovering.Cluster.id)?.setCurrentPositionLiftPercent100thsAttribute(10000 - value * 100);
|
|
109
|
-
}
|
|
110
|
-
if (key === 'moving') {
|
|
111
|
-
const status = value === 'UP' ? WindowCovering.MovementStatus.Opening : value === 'DOWN' ? WindowCovering.MovementStatus.Closing : WindowCovering.MovementStatus.Stopped;
|
|
112
|
-
this.bridgedDevice.getClusterServerById(WindowCovering.Cluster.id)?.setOperationalStatusAttribute({ global: status, lift: status, tilt: status });
|
|
113
|
-
this.log.debug(`Setting accessory ${this.ien}${this.accessoryName}${rs}${db} operationalStatus: ${status}`);
|
|
114
|
-
if (value === 'STOP') {
|
|
115
|
-
const position = this.bridgedDevice.getClusterServerById(WindowCovering.Cluster.id)?.getCurrentPositionLiftPercent100thsAttribute();
|
|
116
|
-
this.bridgedDevice.getClusterServerById(WindowCovering.Cluster.id)?.setCurrentPositionLiftPercent100thsAttribute(position);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
if (key === 'state') {
|
|
120
|
-
this.bridgedDevice.getClusterServerById(OnOff.Cluster.id)?.setOnOffAttribute(value === 'ON' ? true : false);
|
|
121
|
-
this.log.debug(`Setting accessory ${this.ien}${this.accessoryName}${rs}${db} onOffAttribute: ${value === 'ON' ? true : false}`);
|
|
122
|
-
}
|
|
123
|
-
if (key === 'brightness') {
|
|
124
|
-
this.bridgedDevice.getClusterServerById(LevelControl.Cluster.id)?.setCurrentLevelAttribute(value);
|
|
125
|
-
this.log.debug(`Setting accessory ${this.ien}${this.accessoryName}${rs}${db} currentLevelAttribute: ${value}`);
|
|
126
|
-
}
|
|
127
|
-
if (key === 'color_temp' && 'color_mode' in payload && payload['color_mode'] === 'color_temp') {
|
|
128
|
-
this.bridgedDevice.getClusterServerById(ColorControl.Cluster.id)?.setColorTemperatureMiredsAttribute(value);
|
|
129
|
-
this.bridgedDevice.getClusterServerById(ColorControl.Cluster.id)?.setColorModeAttribute(ColorControl.ColorMode.ColorTemperatureMireds);
|
|
130
|
-
this.log.debug(`Setting accessory ${this.ien}${this.accessoryName}${rs}${db} colorTemperatureMireds: ${value}`);
|
|
131
|
-
}
|
|
132
|
-
if (key === 'color' && 'color_mode' in payload && payload['color_mode'] === 'xy') {
|
|
133
|
-
const hsl = color.xyToHsl(value.x, value.y);
|
|
134
|
-
this.bridgedDevice.getClusterServerById(ColorControl.Cluster.id)?.setCurrentHueAttribute((hsl.h / 360) * 254);
|
|
135
|
-
this.bridgedDevice.getClusterServerById(ColorControl.Cluster.id)?.setCurrentSaturationAttribute((hsl.s / 100) * 254);
|
|
136
|
-
this.bridgedDevice.getClusterServerById(ColorControl.Cluster.id)?.setColorModeAttribute(ColorControl.ColorMode.CurrentHueAndCurrentSaturation);
|
|
137
|
-
this.log.debug(`Setting accessory ${this.ien}${this.accessoryName}${rs}${db} colorXY: X:${value.x} Y:${value.y}`);
|
|
138
|
-
}
|
|
139
|
-
if (key === 'battery') {
|
|
140
|
-
this.bridgedDevice.getClusterServerById(PowerSource.Cluster.id)?.setBatPercentRemainingAttribute(Math.round(value * 2));
|
|
141
|
-
this.log.debug(`Setting accessory ${this.ien}${this.accessoryName}${rs}${db} batPercentRemaining: ${Math.round(value * 2)}`);
|
|
142
|
-
}
|
|
143
|
-
if (key === 'temperature') {
|
|
144
|
-
this.bridgedDevice.getClusterServerById(TemperatureMeasurement.Cluster.id)?.setMeasuredValueAttribute(Math.round(value * 100));
|
|
145
|
-
this.log.debug(`Setting accessory ${this.ien}${this.accessoryName}${rs}${db} measuredValue: ${Math.round(value * 100)}`);
|
|
146
|
-
}
|
|
147
|
-
if (key === 'humidity') {
|
|
148
|
-
this.bridgedDevice.getClusterServerById(RelativeHumidityMeasurement.Cluster.id)?.setMeasuredValueAttribute(Math.round(value * 100));
|
|
149
|
-
this.log.debug(`Setting accessory ${this.ien}${this.accessoryName}${rs}${db} measuredValue: ${Math.round(value * 100)}`);
|
|
150
|
-
}
|
|
151
|
-
if (key === 'pressure') {
|
|
152
|
-
this.bridgedDevice.getClusterServerById(PressureMeasurement.Cluster.id)?.setMeasuredValueAttribute(Math.round(value));
|
|
153
|
-
this.log.debug(`Setting accessory ${this.ien}${this.accessoryName}${rs}${db} measuredValue: ${Math.round(value)}`);
|
|
154
|
-
}
|
|
155
|
-
if (key === 'contact') {
|
|
156
|
-
this.bridgedDevice.getClusterServerById(BooleanState.Cluster.id)?.setStateValueAttribute(value);
|
|
157
|
-
this.log.debug(`Setting accessory ${this.ien}${this.accessoryName}${rs}${db} stateValue: ${Math.round(value)}`);
|
|
158
|
-
}
|
|
159
|
-
if (key === 'water_leak') {
|
|
160
|
-
this.bridgedDevice.getClusterServerById(BooleanState.Cluster.id)?.setStateValueAttribute(value);
|
|
161
|
-
this.log.debug(`Setting accessory ${this.ien}${this.accessoryName}${rs}${db} stateValue: ${Math.round(value)}`);
|
|
162
|
-
}
|
|
163
|
-
if (key === 'carbon_monoxide') {
|
|
164
|
-
this.bridgedDevice.getClusterServerById(BooleanState.Cluster.id)?.setStateValueAttribute(value);
|
|
165
|
-
this.log.debug(`Setting accessory ${this.ien}${this.accessoryName}${rs}${db} stateValue: ${Math.round(value)}`);
|
|
166
|
-
}
|
|
167
|
-
if (key === 'air_quality') {
|
|
168
|
-
// excellent, good, moderate, poor, unhealthy, out_of_range unknown
|
|
169
|
-
const airQuality =
|
|
170
|
-
value === 'unhealthy'
|
|
171
|
-
? AirQuality.AirQualityType.VeryPoor
|
|
172
|
-
: value === 'poor'
|
|
173
|
-
? AirQuality.AirQualityType.Poor
|
|
174
|
-
: value === 'moderate'
|
|
175
|
-
? AirQuality.AirQualityType.Moderate
|
|
176
|
-
: value === 'good'
|
|
177
|
-
? AirQuality.AirQualityType.Fair
|
|
178
|
-
: value === 'excellent'
|
|
179
|
-
? AirQuality.AirQualityType.Good
|
|
180
|
-
: AirQuality.AirQualityType.Unknown;
|
|
181
|
-
this.bridgedDevice.getClusterServerById(AirQuality.Cluster.id)?.setAirQualityAttribute(airQuality);
|
|
182
|
-
this.log.debug(`Setting accessory ${this.ien}${this.accessoryName}${rs}${db} airQuality: ${airQuality}`);
|
|
183
|
-
}
|
|
184
|
-
if (key === 'voc') {
|
|
185
|
-
this.bridgedDevice.getClusterServerById(TvocMeasurement.Cluster.id)?.setMeasuredValueAttribute(value);
|
|
186
|
-
this.log.debug(`Setting accessory ${this.ien}${this.accessoryName}${rs}${db} measuredValue: ${value}`);
|
|
187
|
-
}
|
|
188
|
-
if (key === 'occupancy') {
|
|
189
|
-
this.bridgedDevice.getClusterServerById(OccupancySensing.Cluster.id)?.setOccupancyAttribute({ occupied: value as boolean });
|
|
190
|
-
this.log.debug(`Setting accessory ${this.ien}${this.accessoryName}${rs}${db} occupancy: ${value}`);
|
|
191
|
-
}
|
|
192
|
-
if (key === 'illuminance_lux' || (key === 'illuminance' && !('illuminance_lux' in payload))) {
|
|
193
|
-
this.bridgedDevice.getClusterServerById(IlluminanceMeasurement.Cluster.id)?.setMeasuredValueAttribute(Math.round(Math.max(Math.min(10000 * Math.log10(value) + 1, 0xfffe), 0)));
|
|
194
|
-
this.log.debug(`Setting accessory ${this.ien}${this.accessoryName}${rs}${db} measuredValue: ${Math.round(Math.max(Math.min(10000 * Math.log10(value) + 1, 0xfffe), 0))}`);
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
this.platform.z2m.on('ONLINE-' + this.accessoryName, () => {
|
|
200
|
-
this.log.info(`ONLINE message for accessory ${this.ien}${this.accessoryName}${rs}`);
|
|
201
|
-
this.bridgedDevice?.getClusterServerById(BridgedDeviceBasicInformation.Cluster.id)?.setReachableAttribute(true);
|
|
202
|
-
this.log.debug(`Setting accessory ${this.ien}${this.accessoryName}${rs}${db} reachable: true`);
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
this.platform.z2m.on('OFFLINE-' + this.accessoryName, () => {
|
|
206
|
-
this.log.warn(`OFFLINE message for accessory ${this.ien}${this.accessoryName}${wr}`);
|
|
207
|
-
this.bridgedDevice?.getClusterServerById(BridgedDeviceBasicInformation.Cluster.id)?.setReachableAttribute(false);
|
|
208
|
-
this.log.debug(`Setting accessory ${this.ien}${this.accessoryName}${rs}${db} reachable: false`);
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
protected publishCommand(command: string, entityName: string, payload: Payload) {
|
|
213
|
-
this.log.debug(`executeCommand ${command} called for ${this.ien}${entityName}${rs}${db} payload: ${stringify(payload, true)}`);
|
|
214
|
-
const topic = this.platform.z2m.mqttTopic + '/' + entityName + '/set';
|
|
215
|
-
this.platform.z2m.publish(topic, JSON.stringify(payload));
|
|
216
|
-
this.log.info(`MQTT publish topic: ${topic} payload: ${stringify(payload, true)} for ${this.en}${entityName}`);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
export class ZigbeeGroup extends ZigbeeEntity {
|
|
221
|
-
constructor(platform: ZigbeePlatform, group: BridgeGroup) {
|
|
222
|
-
super(platform, group);
|
|
223
|
-
|
|
224
|
-
// TODO Add the group scanning for real groups. This cover only automations
|
|
225
|
-
this.bridgedDevice = new BridgedBaseDevice(this, onOffSwitch, [Identify.Cluster.id, Groups.Cluster.id, Scenes.Cluster.id, OnOff.Cluster.id]);
|
|
226
|
-
|
|
227
|
-
// Command handlers
|
|
228
|
-
this.bridgedDevice.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
|
|
229
|
-
this.log.warn(`Command identify called for ${this.ien}${group.friendly_name}${rs}${db} identifyTime:${identifyTime}`);
|
|
230
|
-
logEndpoint(this.bridgedDevice!);
|
|
231
|
-
});
|
|
232
|
-
this.bridgedDevice.addCommandHandler('on', async ({ attributes: { onOff } }) => {
|
|
233
|
-
this.log.debug(`Command on called for ${this.ien}${group.friendly_name}${rs}${db} attribute: ${onOff.getLocal()}`);
|
|
234
|
-
this.publishCommand('on', group.friendly_name, { state: 'ON' });
|
|
235
|
-
});
|
|
236
|
-
this.bridgedDevice.addCommandHandler('off', async ({ attributes: { onOff } }) => {
|
|
237
|
-
this.log.debug(`Command off called for ${this.ien}${group.friendly_name}${rs}${db} attribute: ${onOff.getLocal()}`);
|
|
238
|
-
this.publishCommand('off', group.friendly_name, { state: 'OFF' });
|
|
239
|
-
});
|
|
240
|
-
this.bridgedDevice.addCommandHandler('toggle', async ({ attributes: { onOff } }) => {
|
|
241
|
-
this.log.debug(`Command toggle called for ${this.ien}${group.friendly_name}${rs}${db} attribute: ${onOff.getLocal()}`);
|
|
242
|
-
this.publishCommand('toggle', group.friendly_name, { state: 'TOGGLE' });
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
interface ZigbeeToMatter {
|
|
248
|
-
//[key: string]: string;
|
|
249
|
-
type: string;
|
|
250
|
-
name: string;
|
|
251
|
-
property: string;
|
|
252
|
-
deviceType: DeviceTypeDefinition;
|
|
253
|
-
cluster: number;
|
|
254
|
-
attribute: number;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/* eslint-disable */
|
|
258
|
-
// prettier-ignore
|
|
259
|
-
const z2ms: ZigbeeToMatter[] = [
|
|
260
|
-
{ type: 'switch', name: 'state', property: 'state', deviceType: onOffSwitch, cluster: OnOff.Cluster.id, attribute: OnOff.Cluster.attributes.onOff.id },
|
|
261
|
-
{ type: 'switch', name: 'brightness', property: 'brightness', deviceType: dimmableSwitch, cluster: LevelControl.Cluster.id, attribute: LevelControl.Cluster.attributes.currentLevel.id },
|
|
262
|
-
{ type: 'switch', name: 'color_xy', property: 'color_xy', deviceType: colorTemperatureSwitch, cluster: ColorControl.Cluster.id, attribute: ColorControl.Cluster.attributes.colorMode.id },
|
|
263
|
-
{ type: 'outlet', name: 'state', property: 'state', deviceType: DeviceTypes.ON_OFF_LIGHT, cluster: OnOff.Cluster.id, attribute: OnOff.Cluster.attributes.onOff.id },
|
|
264
|
-
{ type: 'outlet', name: 'brightness', property: 'brightness', deviceType: DeviceTypes.DIMMABLE_PLUGIN_UNIT, cluster: LevelControl.Cluster.id, attribute: LevelControl.Cluster.attributes.currentLevel.id },
|
|
265
|
-
{ type: 'light', name: 'state', property: 'state', deviceType: DeviceTypes.ON_OFF_LIGHT, cluster: OnOff.Cluster.id, attribute: OnOff.Cluster.attributes.onOff.id },
|
|
266
|
-
{ type: 'light', name: 'brightness', property: 'brightness', deviceType: DeviceTypes.DIMMABLE_LIGHT, cluster: LevelControl.Cluster.id, attribute: LevelControl.Cluster.attributes.currentLevel.id },
|
|
267
|
-
{ type: 'light', name: 'color_xy', property: 'color_xy', deviceType: DeviceTypes.COLOR_TEMPERATURE_LIGHT, cluster: ColorControl.Cluster.id, attribute: ColorControl.Cluster.attributes.colorMode.id },
|
|
268
|
-
{ type: 'cover', name: 'state', property: 'state', deviceType: DeviceTypes.WINDOW_COVERING, cluster: WindowCovering.Cluster.id, attribute: WindowCovering.Complete.attributes.currentPositionLiftPercent100ths.id },
|
|
269
|
-
{ type: '', name: 'occupancy', property: 'occupancy', deviceType: DeviceTypes.OCCUPANCY_SENSOR, cluster: OccupancySensing.Cluster.id, attribute: OccupancySensing.Cluster.attributes.occupancy.id },
|
|
270
|
-
{ type: '', name: 'illuminance', property: 'illuminance', deviceType: DeviceTypes.LIGHT_SENSOR, cluster: IlluminanceMeasurement.Cluster.id, attribute: IlluminanceMeasurement.Cluster.attributes.measuredValue.id },
|
|
271
|
-
{ type: '', name: 'contact', property: 'contact', deviceType: DeviceTypes.CONTACT_SENSOR, cluster: BooleanState.Cluster.id, attribute: BooleanState.Cluster.attributes.stateValue.id },
|
|
272
|
-
{ type: '', name: 'water_leak', property: 'water_leak', deviceType: DeviceTypes.CONTACT_SENSOR, cluster: BooleanState.Cluster.id, attribute: BooleanState.Cluster.attributes.stateValue.id },
|
|
273
|
-
{ type: '', name: 'vibration', property: 'vibration', deviceType: DeviceTypes.CONTACT_SENSOR, cluster: BooleanState.Cluster.id, attribute: BooleanState.Cluster.attributes.stateValue.id },
|
|
274
|
-
{ type: '', name: 'smoke', property: 'smoke', deviceType: DeviceTypes.CONTACT_SENSOR, cluster: BooleanState.Cluster.id, attribute: BooleanState.Cluster.attributes.stateValue.id },
|
|
275
|
-
{ type: '', name: 'carbon_monoxide', property: 'carbon_monoxide', deviceType: DeviceTypes.CONTACT_SENSOR, cluster: BooleanState.Cluster.id, attribute: BooleanState.Cluster.attributes.stateValue.id },
|
|
276
|
-
{ type: '', name: 'temperature', property: 'temperature', deviceType: DeviceTypes.TEMPERATURE_SENSOR, cluster: TemperatureMeasurement.Cluster.id, attribute: TemperatureMeasurement.Cluster.attributes.measuredValue.id },
|
|
277
|
-
{ type: '', name: 'humidity', property: 'humidity', deviceType: DeviceTypes.HUMIDITY_SENSOR, cluster: RelativeHumidityMeasurement.Cluster.id, attribute: RelativeHumidityMeasurement.Cluster.attributes.measuredValue.id },
|
|
278
|
-
{ type: '', name: 'pressure', property: 'pressure', deviceType: DeviceTypes.PRESSURE_SENSOR, cluster: PressureMeasurement.Cluster.id, attribute: PressureMeasurement.Cluster.attributes.measuredValue.id },
|
|
279
|
-
{ type: '', name: 'air_quality', property: 'air_quality', deviceType: airQualitySensor, cluster: AirQuality.Cluster.id, attribute: AirQuality.Cluster.attributes.airQuality.id },
|
|
280
|
-
{ type: '', name: 'voc', property: 'voc', deviceType: airQualitySensor, cluster: TvocMeasurement.Cluster.id, attribute: TvocMeasurement.Cluster.attributes.measuredValue.id },
|
|
281
|
-
{ type: '', name: 'action', property: 'action', deviceType: DeviceTypes.GENERIC_SWITCH, cluster: Switch.Cluster.id, attribute: Switch.Cluster.attributes.currentPosition.id },
|
|
282
|
-
];
|
|
283
|
-
/* eslint-enable */
|
|
284
|
-
|
|
285
|
-
export class ZigbeeDevice extends ZigbeeEntity {
|
|
286
|
-
constructor(platform: ZigbeePlatform, device: BridgeDevice) {
|
|
287
|
-
super(platform, device);
|
|
288
|
-
if (device.friendly_name === 'Coordinator') return;
|
|
289
|
-
|
|
290
|
-
// Get types and properties
|
|
291
|
-
const types: string[] = [];
|
|
292
|
-
const endpoints: string[] = [];
|
|
293
|
-
const names: string[] = [];
|
|
294
|
-
const properties: string[] = [];
|
|
295
|
-
const forceLight = ['Aqara switch T1'];
|
|
296
|
-
const forceOutlet = ['Aqara switch no neutral'];
|
|
297
|
-
device.definition?.exposes.forEach((expose) => {
|
|
298
|
-
if (expose.features) {
|
|
299
|
-
//Specific features with type
|
|
300
|
-
types.push(expose.type);
|
|
301
|
-
if (expose.endpoint) endpoints.push(expose.endpoint);
|
|
302
|
-
expose.features?.forEach((feature) => {
|
|
303
|
-
names.push(feature.name);
|
|
304
|
-
properties.push(feature.property);
|
|
305
|
-
});
|
|
306
|
-
} else {
|
|
307
|
-
//Generic features without type
|
|
308
|
-
if (expose.name) names.push(expose.name);
|
|
309
|
-
properties.push(expose.property);
|
|
310
|
-
}
|
|
311
|
-
});
|
|
312
|
-
device.definition?.options.forEach((option) => {
|
|
313
|
-
if (option.name) names.push(option.name);
|
|
314
|
-
properties.push(option.property);
|
|
315
|
-
});
|
|
316
|
-
if (forceLight.includes(device.friendly_name)) {
|
|
317
|
-
types.forEach((type, index) => {
|
|
318
|
-
types[index] = type === 'switch' ? 'light' : type;
|
|
319
|
-
this.log.info(`Changed ${device.friendly_name} to light`);
|
|
320
|
-
});
|
|
321
|
-
}
|
|
322
|
-
if (forceOutlet.includes(device.friendly_name)) {
|
|
323
|
-
types.forEach((type, index) => {
|
|
324
|
-
types[index] = type === 'switch' ? 'outlet' : type;
|
|
325
|
-
this.log.info(`Changed ${device.friendly_name} to outlet`);
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
if (types.length === 0) types.push('');
|
|
329
|
-
this.log.debug(`**Device ${this.ien}${device.friendly_name}${rs}${nf} endpoints: ${endpoints.length} \ntypes: ${types.join(' ')} \nproperties: ${properties.join(' ')} \nnames: ${names.join(' ')}`);
|
|
330
|
-
|
|
331
|
-
[...types].forEach((type) => {
|
|
332
|
-
[...names].forEach((name) => {
|
|
333
|
-
const z2m = z2ms.find((z2m) => z2m.type === type && z2m.property === name);
|
|
334
|
-
if (z2m) {
|
|
335
|
-
this.log.debug(`***Device ${this.ien}${device.friendly_name}${rs}${nf} type: ${type} property: ${name} => deviceType: ${z2m.deviceType.name} cluster: ${z2m.cluster} attribute: ${z2m.attribute}`);
|
|
336
|
-
const requiredServerClusters: ClusterId[] = [];
|
|
337
|
-
if (z2m.deviceType.requiredServerClusters.includes(Groups.Cluster.id)) requiredServerClusters.push(Groups.Cluster.id);
|
|
338
|
-
if (z2m.deviceType.requiredServerClusters.includes(Scenes.Cluster.id)) requiredServerClusters.push(Scenes.Cluster.id);
|
|
339
|
-
if (!this.bridgedDevice) this.bridgedDevice = new BridgedBaseDevice(this, z2m.deviceType, [Identify.Cluster.id, ...requiredServerClusters, ClusterId(z2m.cluster)]);
|
|
340
|
-
else this.bridgedDevice.addDeviceTypeAndClusterServer(z2m.deviceType, [ClusterId(z2m.cluster)]);
|
|
341
|
-
names.splice(names.indexOf(name), 1);
|
|
342
|
-
}
|
|
343
|
-
});
|
|
344
|
-
types.splice(types.indexOf(type), 1);
|
|
345
|
-
});
|
|
346
|
-
this.log.debug(`****Device ${this.ien}${device.friendly_name}${rs}${nf} endpoints: ${endpoints.length} \ntypes: ${types.join(' ')} \nproperties: ${properties.join(' ')} \nnames: ${names.join(' ')}`);
|
|
347
|
-
|
|
348
|
-
if (!this.bridgedDevice) return;
|
|
349
|
-
|
|
350
|
-
// Command handlers
|
|
351
|
-
this.bridgedDevice.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
|
|
352
|
-
this.log.debug(`Command identify called for ${this.ien}${device.friendly_name}${rs}${db} identifyTime:${identifyTime}`);
|
|
353
|
-
logEndpoint(this.bridgedDevice!);
|
|
354
|
-
});
|
|
355
|
-
if (this.bridgedDevice.hasClusterServer(OnOffCluster)) {
|
|
356
|
-
this.bridgedDevice.addCommandHandler('on', async ({ attributes: { onOff } }) => {
|
|
357
|
-
this.log.debug(`Command on called for ${this.ien}${device.friendly_name}${rs}${db} attribute: ${onOff.getLocal()}`);
|
|
358
|
-
this.publishCommand('on', device.friendly_name, { state: 'ON' });
|
|
359
|
-
});
|
|
360
|
-
this.bridgedDevice.addCommandHandler('off', async ({ attributes: { onOff } }) => {
|
|
361
|
-
this.log.debug(`Command off called for ${this.ien}${device.friendly_name}${rs}${db} attribute: ${onOff.getLocal()}`);
|
|
362
|
-
this.publishCommand('off', device.friendly_name, { state: 'OFF' });
|
|
363
|
-
});
|
|
364
|
-
this.bridgedDevice.addCommandHandler('toggle', async ({ attributes: { onOff } }) => {
|
|
365
|
-
this.log.debug(`Command toggle called for ${this.ien}${device.friendly_name}${rs}${db} attribute: ${onOff.getLocal()}`);
|
|
366
|
-
this.publishCommand('toggle', device.friendly_name, { state: 'TOGGLE' });
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
if (this.bridgedDevice.hasClusterServer(LevelControlCluster)) {
|
|
370
|
-
this.bridgedDevice.addCommandHandler('moveToLevel', async ({ request: { level }, attributes: { currentLevel } }) => {
|
|
371
|
-
this.log.debug(`Command moveToLevel called for ${this.ien}${device.friendly_name}${rs}${db} request: ${level} attributes: ${currentLevel}`);
|
|
372
|
-
this.publishCommand('moveToLevel', device.friendly_name, { brightness: level });
|
|
373
|
-
});
|
|
374
|
-
this.bridgedDevice.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level }, attributes: { currentLevel } }) => {
|
|
375
|
-
this.log.debug(`Command moveToLevelWithOnOff called for ${this.ien}${device.friendly_name}${rs}${db} request: ${level} attributes: ${currentLevel}`);
|
|
376
|
-
this.publishCommand('moveToLevelWithOnOff', device.friendly_name, { brightness: level });
|
|
377
|
-
});
|
|
378
|
-
}
|
|
379
|
-
if (this.bridgedDevice.hasClusterServer(ColorControlCluster) && this.bridgedDevice.getClusterServer(ColorControlCluster)?.isAttributeSupportedByName('colorTemperatureMireds')) {
|
|
380
|
-
this.bridgedDevice.addCommandHandler('moveToColorTemperature', async ({ request: request, attributes: attributes }) => {
|
|
381
|
-
this.log.debug(`Command moveToColorTemperature called for ${this.ien}${device.friendly_name}${rs}${db} request: ${request.colorTemperatureMireds} attributes: ${attributes.colorTemperatureMireds?.getLocal()} colorMode ${attributes.colorMode.getLocal()}`);
|
|
382
|
-
this.log.warn(`Command moveToColorTemperature called for ${this.ien}${device.friendly_name}${rs}${db} colorMode`, attributes.colorMode.getLocal());
|
|
383
|
-
attributes.colorMode.setLocal(ColorControl.ColorMode.ColorTemperatureMireds);
|
|
384
|
-
this.publishCommand('moveToColorTemperature', device.friendly_name, { color_temp: request.colorTemperatureMireds });
|
|
385
|
-
});
|
|
386
|
-
}
|
|
387
|
-
if (this.bridgedDevice.hasClusterServer(ColorControlCluster) && this.bridgedDevice.getClusterServer(ColorControlCluster)?.isAttributeSupportedByName('currentHue')) {
|
|
388
|
-
let lastRequestedHue = 0;
|
|
389
|
-
let lastRequestedSaturation = 0;
|
|
390
|
-
let lastRequestTimeout: NodeJS.Timeout;
|
|
391
|
-
this.bridgedDevice.addCommandHandler('moveToHue', async ({ request: request, attributes: attributes }) => {
|
|
392
|
-
this.log.debug(`Command moveToHue called for ${this.ien}${device.friendly_name}${rs}${db} request: ${request.hue} attributes: hue ${attributes.currentHue?.getLocal()} saturation ${attributes.currentSaturation?.getLocal()} colorMode ${attributes.colorMode.getLocal()}`);
|
|
393
|
-
attributes.colorMode.setLocal(ColorControl.ColorMode.CurrentHueAndCurrentSaturation);
|
|
394
|
-
lastRequestedHue = request.hue;
|
|
395
|
-
lastRequestTimeout = setTimeout(() => {
|
|
396
|
-
clearTimeout(lastRequestTimeout);
|
|
397
|
-
const rgb = color.hslColorToRgbColor((request.hue / 254) * 360, (lastRequestedSaturation / 254) * 100, 50);
|
|
398
|
-
this.publishCommand('moveToHue', device.friendly_name, { color: { r: rgb.r, g: rgb.g, b: rgb.b } });
|
|
399
|
-
}, 500);
|
|
400
|
-
});
|
|
401
|
-
this.bridgedDevice.addCommandHandler('moveToSaturation', async ({ request: request, attributes: attributes }) => {
|
|
402
|
-
this.log.debug(`Command moveToSaturation called for ${this.ien}${device.friendly_name}${rs}${db} request: ${request.saturation} attributes: hue ${attributes.currentHue?.getLocal()} saturation ${attributes.currentSaturation?.getLocal()} colorMode ${attributes.colorMode.getLocal()}`);
|
|
403
|
-
attributes.colorMode.setLocal(ColorControl.ColorMode.CurrentHueAndCurrentSaturation);
|
|
404
|
-
lastRequestedSaturation = request.saturation;
|
|
405
|
-
lastRequestTimeout = setTimeout(() => {
|
|
406
|
-
clearTimeout(lastRequestTimeout);
|
|
407
|
-
const rgb = color.hslColorToRgbColor((lastRequestedHue / 254) * 360, (request.saturation / 254) * 100, 50);
|
|
408
|
-
this.publishCommand('moveToHue', device.friendly_name, { color: { r: rgb.r, g: rgb.g, b: rgb.b } });
|
|
409
|
-
}, 500);
|
|
410
|
-
});
|
|
411
|
-
this.bridgedDevice.addCommandHandler('moveToHueAndSaturation', async ({ request: request, attributes: attributes }) => {
|
|
412
|
-
this.log.debug(
|
|
413
|
-
`Command moveToHueAndSaturation called for ${this.ien}${device.friendly_name}${rs}${db} request: ${request.hue}-${request.saturation} attributes: hue ${attributes.currentHue?.getLocal()} saturation ${attributes.currentSaturation?.getLocal()} colorMode ${attributes.colorMode.getLocal()}`,
|
|
414
|
-
);
|
|
415
|
-
attributes.colorMode.setLocal(ColorControl.ColorMode.CurrentHueAndCurrentSaturation);
|
|
416
|
-
const rgb = color.hslColorToRgbColor((request.hue / 254) * 360, (request.saturation / 254) * 100, 50);
|
|
417
|
-
this.publishCommand('moveToHueAndSaturation', device.friendly_name, { color: { r: rgb.r, g: rgb.g, b: rgb.b } });
|
|
418
|
-
});
|
|
419
|
-
}
|
|
420
|
-
if (this.bridgedDevice.hasClusterServer(WindowCoveringCluster)) {
|
|
421
|
-
this.bridgedDevice.addCommandHandler('upOrOpen', async (data) => {
|
|
422
|
-
this.log.info(`Command upOrOpen called for ${this.ien}${device.friendly_name}${rs}${db} attribute: ${data.attributes.currentPositionLiftPercent100ths?.getLocal()}`);
|
|
423
|
-
data.attributes.currentPositionLiftPercent100ths?.setLocal(0);
|
|
424
|
-
data.attributes.targetPositionLiftPercent100ths?.setLocal(0);
|
|
425
|
-
this.publishCommand('upOrOpen', device.friendly_name, { state: 'OPEN' });
|
|
426
|
-
});
|
|
427
|
-
this.bridgedDevice.addCommandHandler('downOrClose', async (data) => {
|
|
428
|
-
this.log.info(`Command downOrClose called for ${this.ien}${device.friendly_name}${rs}${db} attribute: ${data.attributes.currentPositionLiftPercent100ths?.getLocal()}`);
|
|
429
|
-
data.attributes.currentPositionLiftPercent100ths?.setLocal(10000);
|
|
430
|
-
data.attributes.targetPositionLiftPercent100ths?.setLocal(10000);
|
|
431
|
-
this.publishCommand('downOrClose', device.friendly_name, { state: 'CLOSE' });
|
|
432
|
-
});
|
|
433
|
-
this.bridgedDevice.addCommandHandler('stopMotion', async (data) => {
|
|
434
|
-
this.log.info(`Command stopMotion called for ${this.ien}${device.friendly_name}${rs}${db} attribute: ${data.attributes.operationalStatus?.getLocal()}`);
|
|
435
|
-
const liftPercent100thsValue = data.attributes.currentPositionLiftPercent100ths?.getLocal();
|
|
436
|
-
if (liftPercent100thsValue) {
|
|
437
|
-
data.attributes.currentPositionLiftPercent100ths?.setLocal(liftPercent100thsValue);
|
|
438
|
-
data.attributes.targetPositionLiftPercent100ths?.setLocal(liftPercent100thsValue);
|
|
439
|
-
}
|
|
440
|
-
data.attributes.operationalStatus?.setLocal({ global: WindowCovering.MovementStatus.Stopped, lift: WindowCovering.MovementStatus.Stopped, tilt: WindowCovering.MovementStatus.Stopped });
|
|
441
|
-
this.publishCommand('stopMotion', device.friendly_name, { state: 'STOP' });
|
|
442
|
-
});
|
|
443
|
-
this.bridgedDevice.addCommandHandler('goToLiftPercentage', async ({ request: { liftPercent100thsValue }, attributes }) => {
|
|
444
|
-
this.log.info(`Command goToLiftPercentage called for ${this.ien}${device.friendly_name}${rs}${db} liftPercent100thsValue: ${liftPercent100thsValue}`);
|
|
445
|
-
this.log.info(`Command goToLiftPercentage current: ${attributes.currentPositionLiftPercent100ths?.getLocal()} target: ${attributes.targetPositionLiftPercent100ths?.getLocal()}`);
|
|
446
|
-
//attributes.currentPositionLiftPercent100ths?.setLocal(liftPercent100thsValue);
|
|
447
|
-
attributes.targetPositionLiftPercent100ths?.setLocal(liftPercent100thsValue);
|
|
448
|
-
this.publishCommand('goToLiftPercentage', device.friendly_name, { position: 100 - liftPercent100thsValue / 100 });
|
|
449
|
-
});
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
export class BridgedBaseDevice extends MatterbridgeDevice {
|
|
455
|
-
//public deviceName: string;
|
|
456
|
-
public hasEndpoints = false;
|
|
457
|
-
|
|
458
|
-
constructor(entity: ZigbeeEntity, definition: DeviceTypeDefinition, includeServerList: ClusterId[] = [], includeClientList?: ClusterId[]) {
|
|
459
|
-
super(definition);
|
|
460
|
-
|
|
461
|
-
// Add all other server clusters in the includelist
|
|
462
|
-
this.addDeviceClusterServer(includeServerList);
|
|
463
|
-
|
|
464
|
-
// Add BridgedDeviceBasicInformationCluster
|
|
465
|
-
if (entity.isDevice && entity.device) {
|
|
466
|
-
this.addBridgedDeviceBasicInformationCluster(entity.device.friendly_name, entity.device.definition.vendor, entity.device.definition.model, entity.device.ieee_address);
|
|
467
|
-
} else if (entity.isGroup && entity.group) {
|
|
468
|
-
this.addBridgedDeviceBasicInformationCluster(entity.group.friendly_name, 'zigbee2MQTT', 'Group', `group-${entity.group.id}`);
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
// Add PowerSource cluster
|
|
472
|
-
if (entity.isDevice) {
|
|
473
|
-
if (entity.device?.power_source === 'Battery') this.createDefaultPowerSourceReplaceableBatteryClusterServer(100, PowerSource.BatChargeLevel.Ok);
|
|
474
|
-
else this.createDefaultPowerSourceWiredClusterServer();
|
|
475
|
-
} else if (entity.isGroup) {
|
|
476
|
-
this.createDefaultPowerSourceWiredClusterServer();
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
// Add all other client clusters in the includelist
|
|
480
|
-
this.addDeviceClusterClient(includeClientList);
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
/**
|
|
484
|
-
* Adds BridgedDeviceBasicInformationCluster
|
|
485
|
-
*
|
|
486
|
-
* @protected
|
|
487
|
-
* @param deviceName Name of the device
|
|
488
|
-
* @param deviceSerial Serial of the device
|
|
489
|
-
*/
|
|
490
|
-
protected addBridgedDeviceBasicInformationCluster(deviceName: string, vendorName: string, productName: string, deviceSerial: string) {
|
|
491
|
-
this.createDefaultBridgedDeviceBasicInformationClusterServer(deviceName.slice(0, 32), (deviceSerial + '_' + hostname).slice(0, 32), 0xfff1, vendorName, productName);
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
/**
|
|
495
|
-
* Adds mandatory clusters to the device
|
|
496
|
-
*
|
|
497
|
-
* @protected
|
|
498
|
-
* @param attributeInitialValues Optional object with initial attribute values for automatically added clusters
|
|
499
|
-
* @param includeServerList List of clusters to include
|
|
500
|
-
*/
|
|
501
|
-
// attributeInitialValues?: { [key: ClusterId]: AttributeInitialValues<any> }
|
|
502
|
-
protected addDeviceClusterServer(includeServerList: ClusterId[] = []) {
|
|
503
|
-
if (includeServerList.includes(Identify.Cluster.id) && !this.hasClusterServer(Identify.Cluster)) {
|
|
504
|
-
this.createDefaultIdentifyClusterServer();
|
|
505
|
-
}
|
|
506
|
-
if (includeServerList.includes(Groups.Cluster.id) && !this.hasClusterServer(Groups.Cluster)) {
|
|
507
|
-
this.createDefaultGroupsClusterServer();
|
|
508
|
-
}
|
|
509
|
-
if (includeServerList.includes(Scenes.Cluster.id) && !this.hasClusterServer(Scenes.Cluster)) {
|
|
510
|
-
this.createDefaultScenesClusterServer();
|
|
511
|
-
}
|
|
512
|
-
if (includeServerList.includes(OnOff.Cluster.id)) {
|
|
513
|
-
this.createDefaultOnOffClusterServer();
|
|
514
|
-
}
|
|
515
|
-
if (includeServerList.includes(LevelControl.Cluster.id)) {
|
|
516
|
-
this.createDefaultLevelControlClusterServer();
|
|
517
|
-
}
|
|
518
|
-
if (includeServerList.includes(ColorControl.Cluster.id)) {
|
|
519
|
-
this.createDefaultColorControlClusterServer();
|
|
520
|
-
}
|
|
521
|
-
if (includeServerList.includes(WindowCovering.Cluster.id)) {
|
|
522
|
-
this.createDefaultWindowCoveringClusterServer();
|
|
523
|
-
}
|
|
524
|
-
if (includeServerList.includes(Switch.Cluster.id)) {
|
|
525
|
-
this.createDefaultSwitchClusterServer();
|
|
526
|
-
}
|
|
527
|
-
if (includeServerList.includes(TemperatureMeasurement.Cluster.id)) {
|
|
528
|
-
this.createDefaultTemperatureMeasurementClusterServer();
|
|
529
|
-
}
|
|
530
|
-
if (includeServerList.includes(RelativeHumidityMeasurement.Cluster.id)) {
|
|
531
|
-
this.createDefaultRelativeHumidityMeasurementClusterServer();
|
|
532
|
-
}
|
|
533
|
-
if (includeServerList.includes(PressureMeasurement.Cluster.id)) {
|
|
534
|
-
this.createDefaultPressureMeasurementClusterServer();
|
|
535
|
-
}
|
|
536
|
-
if (includeServerList.includes(BooleanState.Cluster.id)) {
|
|
537
|
-
this.createDefaultBooleanStateClusterServer(true);
|
|
538
|
-
}
|
|
539
|
-
if (includeServerList.includes(OccupancySensing.Cluster.id)) {
|
|
540
|
-
this.createDefaultOccupancySensingClusterServer(false);
|
|
541
|
-
}
|
|
542
|
-
if (includeServerList.includes(IlluminanceMeasurement.Cluster.id)) {
|
|
543
|
-
this.createDefaultIlluminanceMeasurementClusterServer();
|
|
544
|
-
}
|
|
545
|
-
if (includeServerList.includes(AirQuality.Cluster.id)) {
|
|
546
|
-
this.createDefaultAirQualityClusterServer();
|
|
547
|
-
}
|
|
548
|
-
if (includeServerList.includes(TvocMeasurement.Cluster.id)) {
|
|
549
|
-
this.createDefaultTvocMeasurementClusterServer();
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
/**
|
|
554
|
-
* Adds mandatory client clusters to the device
|
|
555
|
-
*
|
|
556
|
-
* @protected
|
|
557
|
-
* @param attributeInitialValues Optional object with initial attribute values for automatically added clusters
|
|
558
|
-
* @param includeClientList List of clusters to include
|
|
559
|
-
*/
|
|
560
|
-
// attributeInitialValues?: { [key: ClusterId]: AttributeInitialValues<any> },
|
|
561
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
562
|
-
protected addDeviceClusterClient(includeClientList: ClusterId[] = []) {
|
|
563
|
-
/* Not implemented */
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
public addDeviceTypeAndClusterServer(deviceType: DeviceTypeDefinition, serverList: ClusterId[]) {
|
|
567
|
-
this.addDeviceType(deviceType);
|
|
568
|
-
this.addDeviceClusterServer(serverList);
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
configure() {
|
|
572
|
-
if (this.getClusterServerById(WindowCovering.Cluster.id)) {
|
|
573
|
-
// eslint-disable-next-line no-console
|
|
574
|
-
console.log(`Configuring ${this.deviceName}`);
|
|
575
|
-
this.setWindowCoveringTargetAsCurrentAndStopped();
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file contains the entry point of Matterbridge.
|
|
3
|
-
*
|
|
4
|
-
* @file index.ts
|
|
5
|
-
* @author Luca Liguori
|
|
6
|
-
* @date 2023-12-29
|
|
7
|
-
* @version 2.0.0
|
|
8
|
-
*
|
|
9
|
-
* Copyright 2023, 2024 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
|
-
|
|
24
|
-
import { Matterbridge, PlatformConfig } from 'matterbridge';
|
|
25
|
-
import { AnsiLogger } from 'node-ansi-logger';
|
|
26
|
-
import { ZigbeePlatform } from './platform.js';
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* This is the standard interface for Matterbridge plugins.
|
|
30
|
-
* Each plugin should export a default function that follows this signature.
|
|
31
|
-
* Each plugin should return the platform.
|
|
32
|
-
*
|
|
33
|
-
* Initializes the Zigbee2mqtt plugin.
|
|
34
|
-
*
|
|
35
|
-
* @param {Matterbridge} matterbridge - The Matterbridge instance.
|
|
36
|
-
* @param {AnsiLogger} log - The logger instance.
|
|
37
|
-
* @param {PlatformConfig} config - The platform configuration.
|
|
38
|
-
* @returns {ZigbeePlatform} The initialized Zigbee platform.
|
|
39
|
-
*/
|
|
40
|
-
export default function initializePlugin(matterbridge: Matterbridge, log: AnsiLogger, config: PlatformConfig): ZigbeePlatform {
|
|
41
|
-
return new ZigbeePlatform(matterbridge, log, config);
|
|
42
|
-
}
|
package/src/payloadTypes.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file contains the types for Payload.
|
|
3
|
-
*
|
|
4
|
-
* @file payloadTypes.ts
|
|
5
|
-
* @author Luca Liguori
|
|
6
|
-
* @date 2023-12-29
|
|
7
|
-
* @version 1.0.0
|
|
8
|
-
*
|
|
9
|
-
* Copyright 2023, 2024 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
|
-
|
|
24
|
-
export type PayloadValue = string | number | boolean | bigint | object | undefined | null;
|
|
25
|
-
|
|
26
|
-
export type Payload = {
|
|
27
|
-
[key: string]: PayloadValue; // This allows any string as a key, and the value can be PayloadValue.
|
|
28
|
-
};
|