matterbridge-example-dynamic-platform 1.0.22 → 1.0.24

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.js CHANGED
@@ -1,7 +1,6 @@
1
- import { AirQuality, AirQualityCluster, BooleanStateCluster, BooleanStateConfiguration, CarbonDioxideConcentrationMeasurement, CarbonMonoxideConcentrationMeasurement, ColorControl, ColorControlCluster, DeviceTypes, DoorLock, DoorLockCluster, FanControl, FanControlCluster, FlowMeasurement, FormaldehydeConcentrationMeasurement, LevelControlCluster, NitrogenDioxideConcentrationMeasurement, OnOffCluster, OzoneConcentrationMeasurement, Pm10ConcentrationMeasurement, Pm1ConcentrationMeasurement, Pm25ConcentrationMeasurement, RadonConcentrationMeasurement, RelativeHumidityMeasurement, SmokeCoAlarm, SmokeCoAlarmCluster, TemperatureMeasurement, Thermostat, ThermostatCluster, TotalVolatileOrganicCompoundsConcentrationMeasurement, WindowCovering, WindowCoveringCluster, airQualitySensor, bridgedNode, onOffSwitch, powerSource, rainSensor, smokeCoAlarm, waterFreezeDetector, waterLeakDetector, } from 'matterbridge';
2
- import { MatterbridgeDevice, MatterbridgeDynamicPlatform } from 'matterbridge';
1
+ import { AirQuality, AirQualityCluster, BooleanStateCluster, BooleanStateConfiguration, CarbonDioxideConcentrationMeasurement, CarbonMonoxideConcentrationMeasurement, ColorControl, ColorControlCluster, DeviceTypes, DoorLock, DoorLockCluster, FanControl, FanControlCluster, FlowMeasurement, FlowMeasurementCluster, FormaldehydeConcentrationMeasurement, LevelControlCluster, NitrogenDioxideConcentrationMeasurement, OnOffCluster, OzoneConcentrationMeasurement, Pm10ConcentrationMeasurement, Pm1ConcentrationMeasurement, Pm25ConcentrationMeasurement, RadonConcentrationMeasurement, RelativeHumidityMeasurement, RelativeHumidityMeasurementCluster, SmokeCoAlarm, SmokeCoAlarmCluster, TemperatureMeasurement, TemperatureMeasurementCluster, Thermostat, ThermostatCluster, TotalVolatileOrganicCompoundsConcentrationMeasurement, WindowCovering, WindowCoveringCluster, airQualitySensor, bridgedNode, onOffSwitch, powerSource, rainSensor, smokeCoAlarm, waterFreezeDetector, waterLeakDetector, } from 'matterbridge';
2
+ import { /* MatterbridgeEndpoint as */ MatterbridgeDevice, MatterbridgeDynamicPlatform } from 'matterbridge';
3
3
  import { isValidBoolean, isValidNumber } from 'matterbridge/utils';
4
- import { db, hk, or } from 'matterbridge/logger';
5
4
  export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatform {
6
5
  switch;
7
6
  lightOnOff;
@@ -34,12 +33,16 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
34
33
  airQualityInterval;
35
34
  constructor(matterbridge, log, config) {
36
35
  super(matterbridge, log, config);
36
+ // Verify that Matterbridge is the correct version
37
+ if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('1.6.0')) {
38
+ throw new Error(`This plugin requires Matterbridge version >= "1.6.0". Please update Matterbridge from ${this.matterbridge.matterbridgeVersion} to the latest version in the frontend."`);
39
+ }
37
40
  this.log.info('Initializing platform:', this.config.name);
38
41
  }
39
42
  async onStart(reason) {
40
43
  this.log.info('onStart called with reason:', reason ?? 'none');
41
44
  // Create a switch device
42
- this.switch = new MatterbridgeDevice(onOffSwitch, undefined, this.config.debug);
45
+ this.switch = new MatterbridgeDevice([onOffSwitch, bridgedNode], { uniqueStorageKey: 'Switch' }, this.config.debug);
43
46
  this.switch.log.logName = 'Switch';
44
47
  this.switch.createDefaultIdentifyClusterServer();
45
48
  this.switch.createDefaultGroupsClusterServer();
@@ -60,30 +63,8 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
60
63
  this.switch?.setAttribute(OnOffCluster.id, 'onOff', false, this.switch.log, this.switch);
61
64
  this.switch?.log.info('Command off called');
62
65
  });
63
- /*
64
- addCommandHandler(
65
- OnOffCluster.id,
66
- 'on',
67
- async (data) => {
68
- this.switch?.setAttribute(OnOffCluster.id, 'onOff', true, this.switch.log, this.switch);
69
- this.switch?.log.info(`Command on called with: ${data}`);
70
- },
71
- this.switch.log,
72
- this.switch,
73
- );
74
- addCommandHandler(
75
- OnOffCluster.id,
76
- 'off',
77
- async (data) => {
78
- this.switch?.setAttribute(OnOffCluster.id, 'onOff', false, this.switch.log, this.switch);
79
- this.switch?.log.info(`Command off called with: ${data}`);
80
- },
81
- this.switch.log,
82
- this.switch,
83
- );
84
- */
85
66
  // Create a on off light device
86
- this.lightOnOff = new MatterbridgeDevice(DeviceTypes.ON_OFF_LIGHT, undefined, this.config.debug);
67
+ this.lightOnOff = new MatterbridgeDevice([DeviceTypes.ON_OFF_LIGHT, bridgedNode], { uniqueStorageKey: 'Light (on/off)' }, this.config.debug);
87
68
  this.lightOnOff.log.logName = 'Light (on/off)';
88
69
  this.lightOnOff.createDefaultIdentifyClusterServer();
89
70
  this.lightOnOff.createDefaultGroupsClusterServer();
@@ -105,7 +86,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
105
86
  this.lightOnOff?.log.info('Command off called');
106
87
  });
107
88
  // Create a dimmer device
108
- this.dimmer = new MatterbridgeDevice(DeviceTypes.DIMMABLE_LIGHT, undefined, this.config.debug);
89
+ this.dimmer = new MatterbridgeDevice([DeviceTypes.DIMMABLE_LIGHT, bridgedNode], { uniqueStorageKey: 'Dimmer' }, this.config.debug);
109
90
  this.dimmer.log.logName = 'Dimmer';
110
91
  this.dimmer.createDefaultIdentifyClusterServer();
111
92
  this.dimmer.createDefaultGroupsClusterServer();
@@ -127,16 +108,16 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
127
108
  this.dimmer?.setAttribute(OnOffCluster.id, 'onOff', false, this.dimmer.log, this.dimmer);
128
109
  this.dimmer?.log.info('Command off called');
129
110
  });
130
- this.dimmer.addCommandHandler('moveToLevel', async ({ request: { level }, attributes: { currentLevel } }) => {
111
+ this.dimmer.addCommandHandler('moveToLevel', async ({ request: { level } }) => {
131
112
  this.dimmer?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.dimmer.log, this.dimmer);
132
- this.dimmer?.log.debug(`Command moveToLevel called request: ${level} attributes: ${currentLevel?.getLocal()}`);
113
+ this.dimmer?.log.debug(`Command moveToLevel called request: ${level}`);
133
114
  });
134
- this.dimmer.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level }, attributes: { currentLevel } }) => {
115
+ this.dimmer.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level } }) => {
135
116
  this.dimmer?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.dimmer.log, this.dimmer);
136
- this.dimmer?.log.debug(`Command moveToLevelWithOnOff called request: ${level} attributes: ${currentLevel?.getLocal()}`);
117
+ this.dimmer?.log.debug(`Command moveToLevelWithOnOff called request: ${level}`);
137
118
  });
138
119
  // Create a light device
139
- this.light = new MatterbridgeDevice(DeviceTypes.COLOR_TEMPERATURE_LIGHT, undefined, this.config.debug);
120
+ this.light = new MatterbridgeDevice([DeviceTypes.COLOR_TEMPERATURE_LIGHT, bridgedNode], { uniqueStorageKey: 'Light (XY, HS and CT)' }, this.config.debug);
140
121
  this.light.log.logName = 'Light (XY, HS and CT)';
141
122
  this.light.createDefaultIdentifyClusterServer();
142
123
  this.light.createDefaultGroupsClusterServer();
@@ -144,7 +125,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
144
125
  this.light.createDefaultBridgedDeviceBasicInformationClusterServer('Light (XY, HS and CT)', '0x23480564', 0xfff1, 'Luligu', 'Matterbridge Light');
145
126
  this.light.createDefaultOnOffClusterServer();
146
127
  this.light.createDefaultLevelControlClusterServer();
147
- this.light.createDefaultCompleteColorControlClusterServer();
128
+ this.light.createDefaultColorControlClusterServer();
148
129
  this.light.addDeviceType(powerSource);
149
130
  this.light.createDefaultPowerSourceReplaceableBatteryClusterServer(70);
150
131
  await this.registerDevice(this.light);
@@ -159,18 +140,18 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
159
140
  this.light?.setAttribute(OnOffCluster.id, 'onOff', false, this.light?.log, this.light);
160
141
  this.light?.log.info('Command off called');
161
142
  });
162
- this.light.addCommandHandler('moveToLevel', async ({ request: { level }, attributes: { currentLevel } }) => {
143
+ this.light.addCommandHandler('moveToLevel', async ({ request: { level } }) => {
163
144
  this.light?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.light?.log, this.light);
164
- this.light?.log.debug(`Command moveToLevel called request: ${level} attributes: ${currentLevel?.getLocal()}`);
145
+ this.light?.log.debug(`Command moveToLevel called request: ${level}`);
165
146
  });
166
- this.light.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level }, attributes: { currentLevel } }) => {
147
+ this.light.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level } }) => {
167
148
  this.light?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.light?.log, this.light);
168
- this.light?.log.debug(`Command moveToLevelWithOnOff called request: ${level} attributes: ${currentLevel?.getLocal()}`);
149
+ this.light?.log.debug(`Command moveToLevelWithOnOff called request: ${level}`);
169
150
  });
170
- this.light.addCommandHandler('moveToColor', async ({ request: { colorX, colorY }, attributes: { currentX, currentY } }) => {
151
+ this.light.addCommandHandler('moveToColor', async ({ request: { colorX, colorY } }) => {
171
152
  this.light?.setAttribute(ColorControlCluster.id, 'currentX', colorX, this.light?.log, this.light);
172
153
  this.light?.setAttribute(ColorControlCluster.id, 'currentY', colorY, this.light?.log, this.light);
173
- this.light?.log.debug(`Command moveToColor called request: X ${colorX / 65536} Y ${colorY / 65536} attributes: X ${(currentX?.getLocal() ?? 0) / 65536} Y ${(currentY?.getLocal() ?? 0) / 65536}`);
154
+ this.light?.log.debug(`Command moveToColor called request: X ${colorX / 65536} Y ${colorY / 65536}`);
174
155
  });
175
156
  this.light.addCommandHandler('moveToHueAndSaturation', async ({ request: { hue, saturation }, attributes: { currentHue, currentSaturation } }) => {
176
157
  this.light?.setAttribute(ColorControlCluster.id, 'currentHue', hue, this.light?.log, this.light);
@@ -190,7 +171,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
190
171
  this.light?.log.debug(`Command moveToColorTemperature called request: ${request.colorTemperatureMireds} attributes: ${attributes.colorTemperatureMireds?.getLocal()}`);
191
172
  });
192
173
  // Create a light device with HS color control
193
- this.lightHS = new MatterbridgeDevice(DeviceTypes.COLOR_TEMPERATURE_LIGHT, undefined, this.config.debug);
174
+ this.lightHS = new MatterbridgeDevice([DeviceTypes.COLOR_TEMPERATURE_LIGHT, bridgedNode], { uniqueStorageKey: 'Light (HS)' }, this.config.debug);
194
175
  this.lightHS.log.logName = 'Light (HS)';
195
176
  this.lightHS.createDefaultIdentifyClusterServer();
196
177
  this.lightHS.createDefaultGroupsClusterServer();
@@ -198,7 +179,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
198
179
  this.lightHS.createDefaultBridgedDeviceBasicInformationClusterServer('Light (HS)', '0x25097564', 0xfff1, 'Luligu', 'Matterbridge Light');
199
180
  this.lightHS.createDefaultOnOffClusterServer();
200
181
  this.lightHS.createDefaultLevelControlClusterServer();
201
- this.lightHS.createDefaultCompleteColorControlClusterServer();
182
+ this.lightHS.createDefaultColorControlClusterServer();
202
183
  this.lightHS.configureColorControlCluster(true, false, false, ColorControl.ColorMode.CurrentHueAndCurrentSaturation);
203
184
  this.lightHS.addDeviceType(powerSource);
204
185
  this.lightHS.createDefaultPowerSourceWiredClusterServer();
@@ -236,7 +217,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
236
217
  this.lightHS?.log.debug(`Command moveToSaturation called request: saturation ${saturation} attributes: hue ${currentHue?.getLocal()} saturation ${currentSaturation?.getLocal()}`);
237
218
  });
238
219
  // Create a light device with XY color control
239
- this.lightXY = new MatterbridgeDevice(DeviceTypes.COLOR_TEMPERATURE_LIGHT, undefined, this.config.debug);
220
+ this.lightXY = new MatterbridgeDevice([DeviceTypes.COLOR_TEMPERATURE_LIGHT, bridgedNode], { uniqueStorageKey: 'Light (XY)' }, this.config.debug);
240
221
  this.lightXY.log.logName = 'Light (XY)';
241
222
  this.lightXY.createDefaultIdentifyClusterServer();
242
223
  this.lightXY.createDefaultGroupsClusterServer();
@@ -244,7 +225,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
244
225
  this.lightXY.createDefaultBridgedDeviceBasicInformationClusterServer('Light (XY)', '0x23497564', 0xfff1, 'Luligu', 'Matterbridge Light');
245
226
  this.lightXY.createDefaultOnOffClusterServer();
246
227
  this.lightXY.createDefaultLevelControlClusterServer();
247
- this.lightXY.createDefaultCompleteColorControlClusterServer();
228
+ this.lightXY.createDefaultColorControlClusterServer();
248
229
  this.lightXY.configureColorControlCluster(false, true, false, ColorControl.ColorMode.CurrentXAndCurrentY);
249
230
  this.lightXY.addDeviceType(powerSource);
250
231
  this.lightXY.createDefaultPowerSourceWiredClusterServer();
@@ -260,21 +241,21 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
260
241
  this.lightXY?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightXY?.log, this.lightXY);
261
242
  this.lightXY?.log.info('Command off called');
262
243
  });
263
- this.lightXY.addCommandHandler('moveToLevel', async ({ request: { level }, attributes: { currentLevel } }) => {
244
+ this.lightXY.addCommandHandler('moveToLevel', async ({ request: { level } }) => {
264
245
  this.lightXY?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightXY?.log, this.lightXY);
265
- this.lightXY?.log.debug(`Command moveToLevel called request: ${level} attributes: ${currentLevel?.getLocal()}`);
246
+ this.lightXY?.log.debug(`Command moveToLevel called request: ${level}`);
266
247
  });
267
- this.lightXY.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level }, attributes: { currentLevel } }) => {
248
+ this.lightXY.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level } }) => {
268
249
  this.lightXY?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightXY?.log, this.lightXY);
269
- this.lightXY?.log.debug(`Command moveToLevelWithOnOff called request: ${level} attributes: ${currentLevel?.getLocal()}`);
250
+ this.lightXY?.log.debug(`Command moveToLevelWithOnOff called request: ${level}`);
270
251
  });
271
- this.lightXY.addCommandHandler('moveToColor', async ({ request: { colorX, colorY }, attributes: { currentX, currentY } }) => {
272
- this.lightXY?.setAttribute(ColorControlCluster.id, 'currentX', colorX, this.lightXY?.log, this.lightXY);
273
- this.lightXY?.setAttribute(ColorControlCluster.id, 'currentY', colorY, this.lightXY?.log, this.lightXY);
274
- this.lightXY?.log.debug(`Command moveToColor called request: X ${colorX / 65536} Y ${colorY / 65536} attributes: X ${(currentX?.getLocal() ?? 0) / 65536} Y ${(currentY?.getLocal() ?? 0) / 65536}`);
252
+ this.lightXY.addCommandHandler('moveToColor', async ({ request: { colorX, colorY } }) => {
253
+ this.lightXY?.setAttribute(ColorControlCluster.id, 'currentX', colorX, this.light?.log, this.light);
254
+ this.lightXY?.setAttribute(ColorControlCluster.id, 'currentY', colorY, this.light?.log, this.light);
255
+ this.lightXY?.log.debug(`Command moveToColor called request: X ${colorX / 65536} Y ${colorY / 65536}`);
275
256
  });
276
257
  // Create a light device with CT color control
277
- this.lightCT = new MatterbridgeDevice(DeviceTypes.COLOR_TEMPERATURE_LIGHT, undefined, this.config.debug);
258
+ this.lightCT = new MatterbridgeDevice([DeviceTypes.COLOR_TEMPERATURE_LIGHT, bridgedNode], { uniqueStorageKey: 'Light (CT)' }, this.config.debug);
278
259
  this.lightCT.log.logName = 'Light (CT)';
279
260
  this.lightCT.createDefaultIdentifyClusterServer();
280
261
  this.lightCT.createDefaultGroupsClusterServer();
@@ -282,7 +263,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
282
263
  this.lightCT.createDefaultBridgedDeviceBasicInformationClusterServer('Light (CT)', '0x23480749', 0xfff1, 'Luligu', 'Matterbridge Light');
283
264
  this.lightCT.createDefaultOnOffClusterServer();
284
265
  this.lightCT.createDefaultLevelControlClusterServer();
285
- this.lightCT.createDefaultCompleteColorControlClusterServer();
266
+ this.lightCT.createDefaultColorControlClusterServer();
286
267
  this.lightCT.configureColorControlCluster(false, false, true, ColorControl.ColorMode.ColorTemperatureMireds);
287
268
  this.lightCT.addDeviceType(powerSource);
288
269
  this.lightCT.createDefaultPowerSourceReplaceableBatteryClusterServer(70);
@@ -298,20 +279,20 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
298
279
  this.lightCT?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightCT?.log, this.lightCT);
299
280
  this.lightCT?.log.info('Command off called');
300
281
  });
301
- this.lightCT.addCommandHandler('moveToLevel', async ({ request: { level }, attributes: { currentLevel } }) => {
282
+ this.lightCT.addCommandHandler('moveToLevel', async ({ request: { level } }) => {
302
283
  this.lightCT?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightCT?.log, this.lightCT);
303
- this.lightCT?.log.debug(`Command moveToLevel called request: ${level} attributes: ${currentLevel?.getLocal()}`);
284
+ this.lightCT?.log.debug(`Command moveToLevel called request: ${level}`);
304
285
  });
305
- this.lightCT.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level }, attributes: { currentLevel } }) => {
286
+ this.lightCT.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level } }) => {
306
287
  this.lightCT?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightCT?.log, this.lightCT);
307
- this.lightCT?.log.debug(`Command moveToLevelWithOnOff called request: ${level} attributes: ${currentLevel?.getLocal()}`);
288
+ this.lightCT?.log.debug(`Command moveToLevelWithOnOff called request: ${level}`);
308
289
  });
309
- this.lightCT.addCommandHandler('moveToColorTemperature', async ({ request, attributes }) => {
290
+ this.lightCT.addCommandHandler('moveToColorTemperature', async ({ request }) => {
310
291
  this.lightCT?.setAttribute(ColorControlCluster.id, 'colorTemperatureMireds', request.colorTemperatureMireds, this.lightCT?.log, this.lightCT);
311
- this.lightCT?.log.debug(`Command moveToColorTemperature called request: ${request.colorTemperatureMireds} attributes: ${attributes.colorTemperatureMireds?.getLocal()}`);
292
+ this.lightCT?.log.debug(`Command moveToColorTemperature called request: ${request.colorTemperatureMireds}`);
312
293
  });
313
294
  // Create an outlet device
314
- this.outlet = new MatterbridgeDevice(DeviceTypes.ON_OFF_PLUGIN_UNIT, undefined, this.config.debug);
295
+ this.outlet = new MatterbridgeDevice([DeviceTypes.ON_OFF_PLUGIN_UNIT, bridgedNode], { uniqueStorageKey: 'Outlet' }, this.config.debug);
315
296
  this.outlet.log.logName = 'Outlet';
316
297
  this.outlet.createDefaultIdentifyClusterServer();
317
298
  this.outlet.createDefaultGroupsClusterServer();
@@ -334,7 +315,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
334
315
  });
335
316
  // Create a window covering device
336
317
  // Matter uses 10000 = fully closed 0 = fully opened
337
- this.cover = new MatterbridgeDevice(DeviceTypes.WINDOW_COVERING, undefined, this.config.debug);
318
+ this.cover = new MatterbridgeDevice([DeviceTypes.WINDOW_COVERING, bridgedNode], { uniqueStorageKey: 'Cover' }, this.config.debug);
338
319
  this.cover.log.logName = 'Cover';
339
320
  this.cover.createDefaultIdentifyClusterServer();
340
321
  this.cover.createDefaultGroupsClusterServer();
@@ -344,27 +325,30 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
344
325
  this.cover.addDeviceType(powerSource);
345
326
  this.cover.createDefaultPowerSourceRechargeableBatteryClusterServer(86);
346
327
  await this.registerDevice(this.cover);
328
+ this.cover.subscribeAttribute(WindowCoveringCluster.id, 'mode', (newValue, oldValue) => {
329
+ this.cover?.log.info(`Attribute mode changed from ${oldValue} to ${newValue}. Reverse: ${newValue.motorDirectionReversed}. Calibration: ${newValue.calibrationMode}. Maintenance: ${newValue.maintenanceMode}. LED: ${newValue.ledFeedback}`);
330
+ }, this.cover.log);
347
331
  this.cover.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
348
332
  this.cover?.log.info(`Command identify called identifyTime:${identifyTime}`);
349
333
  });
350
- this.cover.addCommandHandler('stopMotion', async ({ attributes: { currentPositionLiftPercent100ths, targetPositionLiftPercent100ths, operationalStatus } }) => {
334
+ this.cover.addCommandHandler('stopMotion', async () => {
351
335
  this.cover?.setWindowCoveringTargetAsCurrentAndStopped();
352
- this.cover?.log.info(`Command stopMotion called: current ${currentPositionLiftPercent100ths?.getLocal()} target ${targetPositionLiftPercent100ths?.getLocal()} status ${operationalStatus?.getLocal().lift}`);
336
+ this.cover?.log.info(`Command stopMotion called`);
353
337
  });
354
- this.cover.addCommandHandler('downOrClose', async ({ attributes: { currentPositionLiftPercent100ths, targetPositionLiftPercent100ths, operationalStatus } }) => {
338
+ this.cover.addCommandHandler('downOrClose', async () => {
355
339
  this.cover?.setWindowCoveringCurrentTargetStatus(10000, 10000, WindowCovering.MovementStatus.Stopped);
356
- this.cover?.log.info(`Command downOrClose called: current ${currentPositionLiftPercent100ths?.getLocal()} target ${targetPositionLiftPercent100ths?.getLocal()} status ${operationalStatus?.getLocal().lift}`);
340
+ this.cover?.log.info(`Command downOrClose called`);
357
341
  });
358
- this.cover.addCommandHandler('upOrOpen', async ({ attributes: { currentPositionLiftPercent100ths, targetPositionLiftPercent100ths, operationalStatus } }) => {
342
+ this.cover.addCommandHandler('upOrOpen', async () => {
359
343
  this.cover?.setWindowCoveringCurrentTargetStatus(0, 0, WindowCovering.MovementStatus.Stopped);
360
- this.cover?.log.info(`Command upOrOpen called: current ${currentPositionLiftPercent100ths?.getLocal()} target ${targetPositionLiftPercent100ths?.getLocal()} status ${operationalStatus?.getLocal().lift}`);
344
+ this.cover?.log.info(`Command upOrOpen called`);
361
345
  });
362
- this.cover.addCommandHandler('goToLiftPercentage', async ({ request: { liftPercent100thsValue }, attributes: { currentPositionLiftPercent100ths, targetPositionLiftPercent100ths, operationalStatus } }) => {
346
+ this.cover.addCommandHandler('goToLiftPercentage', async ({ request: { liftPercent100thsValue } }) => {
363
347
  this.cover?.setWindowCoveringCurrentTargetStatus(liftPercent100thsValue, liftPercent100thsValue, WindowCovering.MovementStatus.Stopped);
364
- this.cover?.log.info(`Command goToLiftPercentage ${liftPercent100thsValue} called: current ${currentPositionLiftPercent100ths?.getLocal()} target ${targetPositionLiftPercent100ths?.getLocal()} status ${operationalStatus?.getLocal().lift}`);
348
+ this.cover?.log.info(`Command goToLiftPercentage ${liftPercent100thsValue} called`);
365
349
  });
366
350
  // Create a lock device
367
- this.lock = new MatterbridgeDevice(DeviceTypes.DOOR_LOCK, undefined, this.config.debug);
351
+ this.lock = new MatterbridgeDevice([DeviceTypes.DOOR_LOCK, bridgedNode], { uniqueStorageKey: 'Lock' }, this.config.debug);
368
352
  this.lock.log.logName = 'Lock';
369
353
  this.lock.createDefaultIdentifyClusterServer();
370
354
  this.lock.createDefaultBridgedDeviceBasicInformationClusterServer('Lock', '0x96352164', 0xfff1, 'Luligu', 'Matterbridge Lock');
@@ -384,7 +368,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
384
368
  this.lock?.log.info('Command unlockDoor called');
385
369
  });
386
370
  // Create a thermostat device
387
- this.thermo = new MatterbridgeDevice(DeviceTypes.THERMOSTAT, undefined, this.config.debug);
371
+ this.thermo = new MatterbridgeDevice([DeviceTypes.THERMOSTAT, bridgedNode], { uniqueStorageKey: 'Thermostat' }, this.config.debug);
388
372
  this.thermo.log.logName = 'Thermostat';
389
373
  this.thermo.createDefaultIdentifyClusterServer();
390
374
  this.thermo.createDefaultGroupsClusterServer();
@@ -403,102 +387,96 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
403
387
  this.thermo.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
404
388
  this.thermo?.log.info(`Command identify called identifyTime:${identifyTime}`);
405
389
  });
406
- this.thermo.addCommandHandler('setpointRaiseLower', async ({ request: { mode, amount }, attributes }) => {
390
+ this.thermo.addCommandHandler('setpointRaiseLower', async ({ request: { mode, amount } }) => {
407
391
  const lookupSetpointAdjustMode = ['Heat', 'Cool', 'Both'];
408
392
  this.thermo?.log.info(`Command setpointRaiseLower called with mode: ${lookupSetpointAdjustMode[mode]} amount: ${amount / 10}`);
409
- if (mode === /* Thermostat.SetpointRaiseLowerMode.Heat*/ 0 && attributes.occupiedHeatingSetpoint) {
410
- const setpoint = attributes.occupiedHeatingSetpoint?.getLocal() / 100 + amount / 10;
411
- attributes.occupiedHeatingSetpoint.setLocal(setpoint * 100);
393
+ if (mode === Thermostat.SetpointRaiseLowerMode.Heat || mode === Thermostat.SetpointRaiseLowerMode.Both) {
394
+ const setpoint = this.thermo?.getAttribute(ThermostatCluster.id, 'occupiedHeatingSetpoint', this.thermo?.log) / 100 + amount / 10;
395
+ this.thermo?.setAttribute(ThermostatCluster.id, 'occupiedHeatingSetpoint', setpoint * 100, this.thermo?.log);
412
396
  this.thermo?.log.info('Set occupiedHeatingSetpoint:', setpoint);
413
397
  }
414
- if (mode === /* Thermostat.SetpointRaiseLowerMode.Cool*/ 1 && attributes.occupiedCoolingSetpoint) {
415
- const setpoint = attributes.occupiedCoolingSetpoint.getLocal() / 100 + amount / 10;
416
- attributes.occupiedCoolingSetpoint.setLocal(setpoint * 100);
398
+ if (mode === Thermostat.SetpointRaiseLowerMode.Cool || mode === Thermostat.SetpointRaiseLowerMode.Both) {
399
+ const setpoint = this.thermo?.getAttribute(ThermostatCluster.id, 'occupiedCoolingSetpoint', this.thermo?.log) / 100 + amount / 10;
400
+ this.thermo?.setAttribute(ThermostatCluster.id, 'occupiedCoolingSetpoint', setpoint * 100, this.thermo?.log);
417
401
  this.thermo?.log.info('Set occupiedCoolingSetpoint:', setpoint);
418
402
  }
419
403
  });
420
- const thermostat = this.thermo.getClusterServer(ThermostatCluster.with(Thermostat.Feature.Heating, Thermostat.Feature.Cooling, Thermostat.Feature.AutoMode));
421
- if (thermostat) {
422
- subscribeAttribute(ThermostatCluster.id, 'systemMode', async (value) => {
423
- const lookupSystemMode = ['Off', 'Auto', '', 'Cool', 'Heat', 'EmergencyHeat', 'Precooling', 'FanOnly', 'Dry', 'Sleep'];
424
- this.thermo?.log.info('Subscribe systemMode called with:', lookupSystemMode[value]);
425
- }, this.thermo.log, this.thermo);
426
- subscribeAttribute(ThermostatCluster.id, 'occupiedHeatingSetpoint', async (value) => {
427
- this.thermo?.log.info('Subscribe occupiedHeatingSetpoint called with:', value / 100);
428
- }, this.thermo.log, this.thermo);
429
- subscribeAttribute(ThermostatCluster.id, 'occupiedCoolingSetpoint', async (value) => {
430
- this.thermo?.log.info('Subscribe occupiedCoolingSetpoint called with:', value / 100);
431
- }, this.thermo.log, this.thermo);
432
- }
404
+ this.thermo.subscribeAttribute(ThermostatCluster.id, 'systemMode', async (value) => {
405
+ const lookupSystemMode = ['Off', 'Auto', '', 'Cool', 'Heat', 'EmergencyHeat', 'Precooling', 'FanOnly', 'Dry', 'Sleep'];
406
+ this.thermo?.log.info('Subscribe systemMode called with:', lookupSystemMode[value]);
407
+ }, this.thermo.log, this.thermo);
408
+ this.thermo.subscribeAttribute(ThermostatCluster.id, 'occupiedHeatingSetpoint', async (value) => {
409
+ this.thermo?.log.info('Subscribe occupiedHeatingSetpoint called with:', value / 100);
410
+ }, this.thermo.log, this.thermo);
411
+ this.thermo.subscribeAttribute(ThermostatCluster.id, 'occupiedCoolingSetpoint', async (value) => {
412
+ this.thermo?.log.info('Subscribe occupiedCoolingSetpoint called with:', value / 100);
413
+ }, this.thermo.log, this.thermo);
433
414
  // Create a fan device
434
- this.fan = new MatterbridgeDevice([DeviceTypes.FAN, bridgedNode], undefined, this.config.debug);
415
+ this.fan = new MatterbridgeDevice([DeviceTypes.FAN, bridgedNode], { uniqueStorageKey: 'Fan' }, this.config.debug);
435
416
  this.fan.log.logName = 'Fan';
436
417
  this.fan.createDefaultBridgedDeviceBasicInformationClusterServer('Fan', 'serial_980545631228', 0xfff1, 'Luligu', 'Matterbridge Fan', 2, '2.1.1');
437
418
  this.fan.addDeviceTypeWithClusterServer([DeviceTypes.FAN], []);
438
419
  await this.registerDevice(this.fan);
439
- const fanCluster = this.fan.getClusterServer(FanControlCluster.with(FanControl.Feature.MultiSpeed, FanControl.Feature.Auto));
440
- if (fanCluster) {
441
- const fanModeLookup = ['Off', 'Low', 'Medium', 'High', 'On', 'Auto', 'Smart'];
442
- subscribeAttribute(FanControlCluster.id, 'fanMode', (newValue, oldValue) => {
443
- this.fan?.log.info(`Fan mode changed from ${fanModeLookup[oldValue]} to ${fanModeLookup[newValue]}`);
444
- if (newValue === FanControl.FanMode.Off) {
445
- fanCluster.setPercentCurrentAttribute(0);
446
- }
447
- else if (newValue === FanControl.FanMode.Low) {
448
- fanCluster.setPercentCurrentAttribute(33);
449
- }
450
- else if (newValue === FanControl.FanMode.Medium) {
451
- fanCluster.setPercentCurrentAttribute(66);
452
- }
453
- else if (newValue === FanControl.FanMode.High) {
454
- fanCluster.setPercentCurrentAttribute(100);
455
- }
456
- else if (newValue === FanControl.FanMode.On) {
457
- fanCluster.setPercentCurrentAttribute(100);
458
- }
459
- else if (newValue === FanControl.FanMode.Auto) {
460
- fanCluster.setPercentCurrentAttribute(50);
461
- }
462
- }, this.fan.log, this.fan);
463
- subscribeAttribute(FanControlCluster.id, 'percentSetting', (newValue, oldValue) => {
464
- this.fan?.log.info(`Percent setting changed from ${oldValue} to ${newValue}`);
465
- if (newValue)
466
- fanCluster.setPercentCurrentAttribute(newValue);
467
- }, this.fan.log, this.fan);
468
- subscribeAttribute(FanControlCluster.id, 'speedSetting', (newValue, oldValue) => {
469
- this.fan?.log.info(`Speed setting changed from ${oldValue} to ${newValue}`);
470
- if (newValue)
471
- fanCluster.setSpeedCurrentAttribute(newValue);
472
- }, this.fan.log, this.fan);
473
- }
474
- this.waterLeak = new MatterbridgeDevice([waterLeakDetector, bridgedNode], undefined, this.config.debug);
420
+ const fanModeLookup = ['Off', 'Low', 'Medium', 'High', 'On', 'Auto', 'Smart'];
421
+ this.thermo.subscribeAttribute(FanControlCluster.id, 'fanMode', (newValue, oldValue) => {
422
+ this.fan?.log.info(`Fan mode changed from ${fanModeLookup[oldValue]} to ${fanModeLookup[newValue]}`);
423
+ if (newValue === FanControl.FanMode.Off) {
424
+ this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', 0, this.fan?.log);
425
+ }
426
+ else if (newValue === FanControl.FanMode.Low) {
427
+ this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', 33, this.fan?.log);
428
+ }
429
+ else if (newValue === FanControl.FanMode.Medium) {
430
+ this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', 66, this.fan?.log);
431
+ }
432
+ else if (newValue === FanControl.FanMode.High) {
433
+ this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', 100, this.fan?.log);
434
+ }
435
+ else if (newValue === FanControl.FanMode.On) {
436
+ this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', 100, this.fan?.log);
437
+ }
438
+ else if (newValue === FanControl.FanMode.Auto) {
439
+ this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', 50, this.fan?.log);
440
+ }
441
+ }, this.fan.log, this.fan);
442
+ this.thermo.subscribeAttribute(FanControlCluster.id, 'percentSetting', (newValue, oldValue) => {
443
+ this.fan?.log.info(`Percent setting changed from ${oldValue} to ${newValue}`);
444
+ if (isValidNumber(newValue, 0, 100))
445
+ this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', newValue, this.fan?.log);
446
+ }, this.fan.log, this.fan);
447
+ this.thermo.subscribeAttribute(FanControlCluster.id, 'speedSetting', (newValue, oldValue) => {
448
+ this.fan?.log.info(`Speed setting changed from ${oldValue} to ${newValue}`);
449
+ if (isValidNumber(newValue, 0, 100))
450
+ this.fan?.setAttribute(FanControlCluster.id, 'speedCurrent', newValue, this.fan?.log);
451
+ }, this.fan.log, this.fan);
452
+ this.waterLeak = new MatterbridgeDevice([waterLeakDetector, bridgedNode], { uniqueStorageKey: 'Water leak detector' }, this.config.debug);
475
453
  this.waterLeak.log.logName = 'Water leak detector';
476
454
  this.waterLeak.createDefaultBridgedDeviceBasicInformationClusterServer('Water leak detector', 'serial_98745631222', 0xfff1, 'Luligu', 'Matterbridge WaterLeakDetector');
477
455
  this.waterLeak.addDeviceTypeWithClusterServer([waterLeakDetector], [BooleanStateConfiguration.Cluster.id]);
478
- this.waterLeak.setAttribute(BooleanStateCluster.id, 'stateValue', false, this.waterLeak.log);
479
456
  await this.registerDevice(this.waterLeak);
480
- this.waterFreeze = new MatterbridgeDevice([waterFreezeDetector, bridgedNode], undefined, this.config.debug);
457
+ this.waterLeak.setAttribute(BooleanStateCluster.id, 'stateValue', false, this.waterLeak.log);
458
+ this.waterFreeze = new MatterbridgeDevice([waterFreezeDetector, bridgedNode], { uniqueStorageKey: 'Water freeze detector' }, this.config.debug);
481
459
  this.waterFreeze.log.logName = 'Water freeze detector';
482
460
  this.waterFreeze.createDefaultBridgedDeviceBasicInformationClusterServer('Water freeze detector', 'serial_98745631223', 0xfff1, 'Luligu', 'Matterbridge WaterFreezeDetector');
483
461
  this.waterFreeze.addDeviceTypeWithClusterServer([waterFreezeDetector], [BooleanStateConfiguration.Cluster.id]);
484
- this.waterFreeze.setAttribute(BooleanStateCluster.id, 'stateValue', false, this.waterFreeze.log);
485
462
  await this.registerDevice(this.waterFreeze);
486
- this.rain = new MatterbridgeDevice([rainSensor, bridgedNode], undefined, this.config.debug);
463
+ this.waterFreeze.setAttribute(BooleanStateCluster.id, 'stateValue', false, this.waterFreeze.log);
464
+ this.rain = new MatterbridgeDevice([rainSensor, bridgedNode], { uniqueStorageKey: 'Rain sensor' }, this.config.debug);
487
465
  this.rain.log.logName = 'Rain sensor';
488
466
  this.rain.createDefaultBridgedDeviceBasicInformationClusterServer('Rain sensor', 'serial_98745631224', 0xfff1, 'Luligu', 'Matterbridge RainSensor');
489
467
  this.rain.addDeviceTypeWithClusterServer([rainSensor], [BooleanStateConfiguration.Cluster.id]);
490
- this.rain.setAttribute(BooleanStateCluster.id, 'stateValue', false, this.rain.log);
491
468
  await this.registerDevice(this.rain);
492
- this.smoke = new MatterbridgeDevice([smokeCoAlarm, bridgedNode], undefined, this.config.debug);
469
+ this.rain.setAttribute(BooleanStateCluster.id, 'stateValue', false, this.rain.log);
470
+ this.smoke = new MatterbridgeDevice([smokeCoAlarm, bridgedNode], { uniqueStorageKey: 'Smoke alarm sensor' }, this.config.debug);
493
471
  this.smoke.log.logName = 'Smoke alarm sensor';
494
472
  this.smoke.createDefaultBridgedDeviceBasicInformationClusterServer('Smoke alarm sensor', 'serial_94745631225', 0xfff1, 'Luligu', 'Matterbridge SmokeCoAlarm');
495
473
  this.smoke.addDeviceTypeWithClusterServer([smokeCoAlarm], [CarbonMonoxideConcentrationMeasurement.Cluster.id]);
474
+ await this.registerDevice(this.smoke);
496
475
  this.smoke.setAttribute(SmokeCoAlarmCluster.id, 'smokeState', SmokeCoAlarm.AlarmState.Normal, this.smoke.log);
497
476
  this.smoke.setAttribute(SmokeCoAlarmCluster.id, 'coState', SmokeCoAlarm.AlarmState.Normal, this.smoke.log);
498
477
  this.smoke.setAttribute(CarbonMonoxideConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.smoke.log);
499
- await this.registerDevice(this.smoke);
500
478
  // Create an airQuality device
501
- this.airQuality = new MatterbridgeDevice([airQualitySensor, bridgedNode], undefined, this.config.debug);
479
+ this.airQuality = new MatterbridgeDevice([airQualitySensor, bridgedNode], { uniqueStorageKey: 'Air quality sensor' }, this.config.debug);
502
480
  this.airQuality.log.logName = 'Air quality Sensor';
503
481
  this.airQuality.createDefaultBridgedDeviceBasicInformationClusterServer('Air quality sensor', 'serial_987484318322', 0xfff1, 'Luligu', 'Matterbridge Air Quality Sensor');
504
482
  this.airQuality.addDeviceTypeWithClusterServer([airQualitySensor], [
@@ -515,6 +493,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
515
493
  RadonConcentrationMeasurement.Cluster.id,
516
494
  TotalVolatileOrganicCompoundsConcentrationMeasurement.Cluster.id,
517
495
  ]);
496
+ await this.registerDevice(this.airQuality);
518
497
  this.airQuality.setAttribute(AirQuality.Cluster.id, 'airQuality', AirQuality.AirQualityEnum.Good, this.airQuality.log);
519
498
  this.airQuality.setAttribute(TemperatureMeasurement.Cluster.id, 'measuredValue', 2150, this.airQuality.log);
520
499
  this.airQuality.setAttribute(RelativeHumidityMeasurement.Cluster.id, 'measuredValue', 5500, this.airQuality.log);
@@ -528,7 +507,6 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
528
507
  this.airQuality.setAttribute(Pm10ConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
529
508
  this.airQuality.setAttribute(RadonConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
530
509
  this.airQuality.setAttribute(TotalVolatileOrganicCompoundsConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
531
- await this.registerDevice(this.airQuality);
532
510
  }
533
511
  async onConfigure() {
534
512
  this.log.info('onConfigure called');
@@ -652,15 +630,28 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
652
630
  }
653
631
  }, 60 * 1000 + 500);
654
632
  // Set local to 16°C
655
- this.thermo?.setAttribute(ThermostatCluster.id, 'localTemperature', 1600, this.thermo.log);
633
+ this.thermo?.setAttribute(ThermostatCluster.id, 'localTemperature', 16 * 100, this.thermo.log);
656
634
  this.thermo?.setAttribute(ThermostatCluster.id, 'systemMode', Thermostat.SystemMode.Auto, this.thermo.log);
657
635
  this.thermo?.log.info('Set thermostat initial localTemperature to 16°C and mode Auto');
636
+ const temperature = this.thermo?.getChildEndpointByName('Temperature');
637
+ this.thermo?.setAttribute(TemperatureMeasurementCluster.id, 'measuredValue', 16 * 100, this.thermo.log, temperature);
638
+ const humidity = this.thermo?.getChildEndpointByName('Humidity');
639
+ this.thermo?.setAttribute(RelativeHumidityMeasurementCluster.id, 'measuredValue', 50 * 100, this.thermo.log, humidity);
640
+ const flow = this.thermo?.getChildEndpointByName('Flow');
641
+ this.thermo?.setAttribute(FlowMeasurementCluster.id, 'measuredValue', 10, this.thermo.log, flow);
642
+ this.thermo?.log.info('Set thermostat ext temperature to 16°C, ext humidity to 50% and ext valve flow to 10');
658
643
  // Increment localTemperature every minute
659
644
  this.thermoInterval = setInterval(() => {
660
645
  let temperature = this.thermo?.getAttribute(ThermostatCluster.id, 'localTemperature', this.thermo.log);
661
646
  if (isValidNumber(temperature, 1600, 2400)) {
662
- temperature = temperature + 100 >= 2400 ? 1600 : temperature + 100;
647
+ temperature = temperature + 100 > 2400 ? 1600 : temperature + 100;
663
648
  this.thermo?.setAttribute(ThermostatCluster.id, 'localTemperature', temperature, this.thermo.log);
649
+ const temp = this.thermo?.getChildEndpointByName('Temperature');
650
+ this.thermo?.setAttribute(TemperatureMeasurementCluster.id, 'measuredValue', temperature, this.thermo.log, temp);
651
+ const humidity = this.thermo?.getChildEndpointByName('Humidity');
652
+ this.thermo?.setAttribute(RelativeHumidityMeasurementCluster.id, 'measuredValue', 50 * 100, this.thermo.log, humidity);
653
+ const flow = this.thermo?.getChildEndpointByName('Flow');
654
+ this.thermo?.setAttribute(FlowMeasurementCluster.id, 'measuredValue', 10, this.thermo.log, flow);
664
655
  this.thermo?.log.info(`Set thermostat localTemperature to ${temperature / 100}°C`);
665
656
  }
666
657
  }, 60 * 1000 + 600);
@@ -755,77 +746,4 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
755
746
  await this.unregisterAllDevices();
756
747
  }
757
748
  }
758
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
759
- function subscribeAttribute(clusterId, attribute, listener, log, endpoint) {
760
- // if (!endpoint) endpoint = this as Endpoint;
761
- if (!endpoint)
762
- return false;
763
- const clusterServer = endpoint.getClusterServerById(clusterId);
764
- if (!clusterServer) {
765
- log?.error(`subscribeAttribute error: Cluster ${clusterId} not found on endpoint ${endpoint.name}:${endpoint.number}`);
766
- return false;
767
- }
768
- const capitalizedAttributeName = attribute.charAt(0).toUpperCase() + attribute.slice(1);
769
- if (!clusterServer.isAttributeSupportedByName(attribute) && !clusterServer.isAttributeSupportedByName(capitalizedAttributeName)) {
770
- if (log)
771
- log.error(`subscribeAttribute error: Attribute ${attribute} not found on Cluster ${clusterServer.name} on endpoint ${endpoint.name}:${endpoint.number}`);
772
- return false;
773
- }
774
- // Find the subscribe method
775
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
776
- if (!clusterServer[`subscribe${capitalizedAttributeName}Attribute`]) {
777
- log?.error(`subscribeAttribute error: subscribe${capitalizedAttributeName}Attribute not found on Cluster ${clusterServer.name} on endpoint ${endpoint.name}:${endpoint.number}`);
778
- return false;
779
- }
780
- // Subscribe to the attribute
781
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-empty-object-type
782
- const subscribe = clusterServer[`subscribe${capitalizedAttributeName}Attribute`];
783
- subscribe(listener);
784
- log?.info(`${db}Subscribe endpoint ${or}${endpoint.name}:${endpoint.number}${db} attribute ${hk}${clusterServer.name}.${capitalizedAttributeName}${db}`);
785
- return true;
786
- }
787
- /*
788
-
789
- interface MatterCommandData {
790
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
791
- request: any;
792
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
793
- attributes: any;
794
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
795
- events: any;
796
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
797
- session: any;
798
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
799
- message: any;
800
- endpoint: Endpoint;
801
- }
802
-
803
- function addCommandHandler(clusterId: ClusterId, command: string, handler: (data: MatterCommandData) => void, log?: AnsiLogger, endpoint?: Endpoint): boolean {
804
- // if (!endpoint) endpoint = this as Endpoint;
805
- if (!endpoint) return false;
806
-
807
- const clusterServer = endpoint.getClusterServerById(clusterId);
808
- if (!clusterServer) {
809
- log?.error(`addCommandHandler error: Cluster ${clusterId} not found on endpoint ${endpoint.name}:${endpoint.number}`);
810
- return false;
811
- }
812
- if (!clusterServer.isCommandSupportedByName(command)) {
813
- if (log) log.error(`addCommandHandler error: Command ${command} not found on Cluster ${clusterServer.name} on endpoint ${endpoint.name}:${endpoint.number}`);
814
- return false;
815
- }
816
- // Find the command
817
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
818
- const commands = (clusterServer as any).commands as object;
819
- for (const [key, value] of Object.entries(commands)) {
820
- // console.log(`Key "${key}": ${debugStringify(value)}`);
821
- if (key === command) {
822
- value.handler = handler;
823
- log?.info(`${db}Command handler added for endpoint ${or}${endpoint.name}:${endpoint.number}${db} ${hk}${clusterServer.name}.${command}${db}`);
824
- return true;
825
- }
826
- }
827
- log?.error(`Command handler not found for endpoint ${or}${endpoint.name}:${endpoint.number}${er} ${hk}${clusterServer.name}.${command}${er}`);
828
- return false;
829
- }
830
- */
831
749
  //# sourceMappingURL=platform.js.map