matterbridge-example-dynamic-platform 1.1.7 → 1.1.9

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
@@ -4,6 +4,8 @@ import { LocationTag } from 'matterbridge/matter';
4
4
  import { PowerSource, BooleanState, OnOff, LevelControl, AirQuality, CarbonDioxideConcentrationMeasurement, CarbonMonoxideConcentrationMeasurement, FlowMeasurement, ColorControl, DoorLock, FanControl, FormaldehydeConcentrationMeasurement, NitrogenDioxideConcentrationMeasurement, OzoneConcentrationMeasurement, Pm10ConcentrationMeasurement, Pm1ConcentrationMeasurement, Pm25ConcentrationMeasurement, RadonConcentrationMeasurement, RelativeHumidityMeasurement, RelativeHumidityMeasurementCluster, SmokeCoAlarm, TemperatureMeasurement, Thermostat, ThermostatCluster, TotalVolatileOrganicCompoundsConcentrationMeasurement, WindowCovering, } from 'matterbridge/matter/clusters';
5
5
  export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatform {
6
6
  switch;
7
+ mountedOnOffSwitch;
8
+ mountedDimmerSwitch;
7
9
  lightOnOff;
8
10
  dimmer;
9
11
  light;
@@ -20,7 +22,9 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
20
22
  waterLeak;
21
23
  waterFreeze;
22
24
  rain;
23
- smoke;
25
+ smokeCo;
26
+ smokeOnly;
27
+ coOnly;
24
28
  airQuality;
25
29
  airConditioner;
26
30
  airPurifier;
@@ -28,6 +32,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
28
32
  valve;
29
33
  momentarySwitch;
30
34
  latchingSwitch;
35
+ vacuum;
31
36
  switchInterval;
32
37
  lightInterval;
33
38
  outletInterval;
@@ -47,29 +52,41 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
47
52
  fanModeLookup = ['Off', 'Low', 'Medium', 'High', 'On', 'Auto', 'Smart'];
48
53
  constructor(matterbridge, log, config) {
49
54
  super(matterbridge, log, config);
50
- if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('2.1.5')) {
51
- throw new Error(`This plugin requires Matterbridge version >= "2.1.5". Please update Matterbridge from ${this.matterbridge.matterbridgeVersion} to the latest version in the frontend.`);
55
+ if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('2.2.7')) {
56
+ throw new Error(`This plugin requires Matterbridge version >= "2.2.7". Please update Matterbridge from ${this.matterbridge.matterbridgeVersion} to the latest version in the frontend.`);
52
57
  }
53
58
  this.log.info('Initializing platform:', this.config.name);
59
+ if (config.whiteList === undefined)
60
+ config.whiteList = [];
61
+ if (config.blackList === undefined)
62
+ config.blackList = [];
54
63
  }
55
64
  async onStart(reason) {
56
65
  this.log.info('onStart called with reason:', reason ?? 'none');
57
- this.switch = new MatterbridgeEndpoint([onOffSwitch, bridgedNode, powerSource], { uniqueStorageKey: 'Switch' }, this.config.debug).createDefaultIdentifyClusterServer();
58
- this.switch
66
+ await this.ready;
67
+ await this.clearSelect();
68
+ this.switch = new MatterbridgeEndpoint([onOffSwitch, bridgedNode, powerSource], { uniqueStorageKey: 'Switch' }, this.config.debug)
69
+ .createDefaultIdentifyClusterServer()
59
70
  .createDefaultGroupsClusterServer()
60
71
  .createDefaultBridgedDeviceBasicInformationClusterServer('Switch', '0x23452164', 0xfff1, 'Matterbridge', 'Matterbridge Switch', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
61
72
  .createDefaultOnOffClusterServer()
62
73
  .createDefaultPowerSourceRechargeableBatteryClusterServer(70);
63
- await this.registerDevice(this.switch);
64
- this.bridgedDevices.set(this.switch.deviceName ?? '', this.switch);
65
- this.switch.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
74
+ this.setSelectDevice(this.switch.serialNumber ?? '', this.switch.deviceName ?? '', undefined, 'hub');
75
+ if (this.validateDevice(this.switch.deviceName ?? '')) {
76
+ await this.registerDevice(this.switch);
77
+ this.bridgedDevices.set(this.switch.deviceName ?? '', this.switch);
78
+ }
79
+ else {
80
+ this.switch = undefined;
81
+ }
82
+ this.switch?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
66
83
  this.log.info(`Command identify called identifyTime:${identifyTime}`);
67
84
  });
68
- this.switch.addCommandHandler('on', async () => {
85
+ this.switch?.addCommandHandler('on', async () => {
69
86
  await this.switch?.setAttribute(OnOff.Cluster.id, 'onOff', true, this.switch.log);
70
87
  this.switch?.log.info('Command on called');
71
88
  });
72
- this.switch.addCommandHandler('off', async () => {
89
+ this.switch?.addCommandHandler('off', async () => {
73
90
  await this.switch?.setAttribute(OnOff.Cluster.id, 'onOff', false, this.switch.log);
74
91
  this.switch?.log.info('Command off called');
75
92
  });
@@ -79,284 +96,338 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
79
96
  .createDefaultBridgedDeviceBasicInformationClusterServer('Light (on/off)', '0x2342375564', 0xfff1, 'Matterbridge', 'Matterbridge Light on/off', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
80
97
  .createDefaultOnOffClusterServer()
81
98
  .createDefaultPowerSourceWiredClusterServer();
82
- await this.registerDevice(this.lightOnOff);
83
- this.bridgedDevices.set(this.lightOnOff.deviceName ?? '', this.lightOnOff);
84
- this.lightOnOff.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
99
+ this.setSelectDevice(this.lightOnOff.serialNumber ?? '', this.lightOnOff.deviceName ?? '', undefined, 'hub');
100
+ if (this.validateDevice(this.lightOnOff.deviceName ?? '')) {
101
+ await this.registerDevice(this.lightOnOff);
102
+ this.bridgedDevices.set(this.lightOnOff.deviceName ?? '', this.lightOnOff);
103
+ }
104
+ else {
105
+ this.lightOnOff = undefined;
106
+ }
107
+ this.lightOnOff?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
85
108
  this.lightOnOff?.log.info(`Command identify called identifyTime:${identifyTime}`);
86
109
  });
87
- this.lightOnOff.addCommandHandler('on', async () => {
110
+ this.lightOnOff?.addCommandHandler('on', async () => {
88
111
  await this.lightOnOff?.setAttribute(OnOff.Cluster.id, 'onOff', true, this.lightOnOff?.log);
89
112
  this.lightOnOff?.log.info('Command on called');
90
113
  });
91
- this.lightOnOff.addCommandHandler('off', async () => {
114
+ this.lightOnOff?.addCommandHandler('off', async () => {
92
115
  await this.lightOnOff?.setAttribute(OnOff.Cluster.id, 'onOff', false, this.lightOnOff?.log);
93
116
  this.lightOnOff?.log.info('Command off called');
94
117
  });
95
- this.dimmer = new MatterbridgeEndpoint([dimmableLight, bridgedNode, powerSource], { uniqueStorageKey: 'Dimmer' }, this.config.debug).createDefaultIdentifyClusterServer();
96
- this.dimmer
118
+ this.dimmer = new MatterbridgeEndpoint([dimmableLight, bridgedNode, powerSource], { uniqueStorageKey: 'Dimmer' }, this.config.debug)
119
+ .createDefaultIdentifyClusterServer()
97
120
  .createDefaultGroupsClusterServer()
98
121
  .createDefaultBridgedDeviceBasicInformationClusterServer('Dimmer', '0x234554564', 0xfff1, 'Matterbridge', 'Matterbridge Dimmer', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
99
122
  .createDefaultOnOffClusterServer()
100
123
  .createDefaultLevelControlClusterServer()
101
124
  .createDefaultPowerSourceReplaceableBatteryClusterServer(70);
102
- await this.registerDevice(this.dimmer);
103
- this.bridgedDevices.set(this.dimmer.deviceName ?? '', this.dimmer);
104
- this.dimmer.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
125
+ this.setSelectDevice(this.dimmer.serialNumber ?? '', this.dimmer.deviceName ?? '', undefined, 'hub');
126
+ if (this.validateDevice(this.dimmer.deviceName ?? '')) {
127
+ await this.registerDevice(this.dimmer);
128
+ this.bridgedDevices.set(this.dimmer.deviceName ?? '', this.dimmer);
129
+ }
130
+ else {
131
+ this.dimmer = undefined;
132
+ }
133
+ this.dimmer?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
105
134
  this.dimmer?.log.info(`Command identify called identifyTime:${identifyTime}`);
106
135
  });
107
- this.dimmer.addCommandHandler('on', async () => {
136
+ this.dimmer?.addCommandHandler('on', async () => {
108
137
  await this.dimmer?.setAttribute(OnOff.Cluster.id, 'onOff', true, this.dimmer.log);
109
138
  this.dimmer?.log.info('Command on called');
110
139
  });
111
- this.dimmer.addCommandHandler('off', async () => {
140
+ this.dimmer?.addCommandHandler('off', async () => {
112
141
  await this.dimmer?.setAttribute(OnOff.Cluster.id, 'onOff', false, this.dimmer.log);
113
142
  this.dimmer?.log.info('Command off called');
114
143
  });
115
- this.dimmer.addCommandHandler('moveToLevel', async ({ request: { level } }) => {
144
+ this.dimmer?.addCommandHandler('moveToLevel', async ({ request: { level } }) => {
116
145
  await this.dimmer?.setAttribute(LevelControl.Cluster.id, 'currentLevel', level, this.dimmer.log);
117
146
  this.dimmer?.log.debug(`Command moveToLevel called request: ${level}`);
118
147
  });
119
- this.dimmer.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level } }) => {
148
+ this.dimmer?.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level } }) => {
120
149
  await this.dimmer?.setAttribute(LevelControl.Cluster.id, 'currentLevel', level, this.dimmer.log);
121
150
  this.dimmer?.log.debug(`Command moveToLevelWithOnOff called request: ${level}`);
122
151
  });
123
- this.light = new MatterbridgeEndpoint([colorTemperatureLight, bridgedNode, powerSource], { uniqueStorageKey: 'Light (XY, HS and CT)' }, this.config.debug).createDefaultIdentifyClusterServer();
124
- this.light
152
+ this.light = new MatterbridgeEndpoint([colorTemperatureLight, bridgedNode, powerSource], { uniqueStorageKey: 'Light (XY, HS and CT)' }, this.config.debug)
153
+ .createDefaultIdentifyClusterServer()
125
154
  .createDefaultGroupsClusterServer()
126
155
  .createDefaultBridgedDeviceBasicInformationClusterServer('Light (XY, HS and CT)', '0x23480564', 0xfff1, 'Matterbridge', 'Matterbridge Light', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
127
156
  .createDefaultOnOffClusterServer()
128
157
  .createDefaultLevelControlClusterServer()
129
158
  .createDefaultColorControlClusterServer()
130
159
  .createDefaultPowerSourceReplaceableBatteryClusterServer(70);
131
- await this.registerDevice(this.light);
132
- this.bridgedDevices.set(this.light.deviceName ?? '', this.light);
133
- this.light.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
160
+ this.setSelectDevice(this.light.serialNumber ?? '', this.light.deviceName ?? '', undefined, 'hub');
161
+ if (this.validateDevice(this.light.deviceName ?? '')) {
162
+ await this.registerDevice(this.light);
163
+ this.bridgedDevices.set(this.light.deviceName ?? '', this.light);
164
+ }
165
+ else {
166
+ this.light = undefined;
167
+ }
168
+ this.light?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
134
169
  this.light?.log.info(`Command identify called identifyTime:${identifyTime}`);
135
170
  });
136
- this.light.addCommandHandler('on', async () => {
171
+ this.light?.addCommandHandler('on', async () => {
137
172
  await this.light?.setAttribute(OnOff.Cluster.id, 'onOff', true, this.light?.log);
138
173
  this.light?.log.info('Command on called');
139
174
  });
140
- this.light.addCommandHandler('off', async () => {
175
+ this.light?.addCommandHandler('off', async () => {
141
176
  await this.light?.setAttribute(OnOff.Cluster.id, 'onOff', false, this.light?.log);
142
177
  this.light?.log.info('Command off called');
143
178
  });
144
- this.light.addCommandHandler('moveToLevel', async ({ request: { level } }) => {
179
+ this.light?.addCommandHandler('moveToLevel', async ({ request: { level } }) => {
145
180
  await this.light?.setAttribute(LevelControl.Cluster.id, 'currentLevel', level, this.light?.log);
146
181
  this.light?.log.debug(`Command moveToLevel called request: ${level}`);
147
182
  });
148
- this.light.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level } }) => {
183
+ this.light?.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level } }) => {
149
184
  await this.light?.setAttribute(LevelControl.Cluster.id, 'currentLevel', level, this.light?.log);
150
185
  this.light?.log.debug(`Command moveToLevelWithOnOff called request: ${level}`);
151
186
  });
152
- this.light.addCommandHandler('moveToColor', async ({ request: { colorX, colorY } }) => {
187
+ this.light?.addCommandHandler('moveToColor', async ({ request: { colorX, colorY } }) => {
153
188
  await this.light?.setAttribute(ColorControl.Cluster.id, 'currentX', colorX, this.light?.log);
154
189
  await this.light?.setAttribute(ColorControl.Cluster.id, 'currentY', colorY, this.light?.log);
155
190
  this.light?.log.debug(`Command moveToColor called request: X ${colorX / 65536} Y ${colorY / 65536}`);
156
191
  });
157
- this.light.addCommandHandler('moveToHueAndSaturation', async ({ request: { hue, saturation } }) => {
192
+ this.light?.addCommandHandler('moveToHueAndSaturation', async ({ request: { hue, saturation } }) => {
158
193
  await this.light?.setAttribute(ColorControl.Cluster.id, 'currentHue', hue, this.light?.log);
159
194
  await this.light?.setAttribute(ColorControl.Cluster.id, 'currentSaturation', saturation, this.light?.log);
160
195
  this.light?.log.debug(`Command moveToHueAndSaturation called request: hue ${hue} saturation ${saturation}`);
161
196
  });
162
- this.light.addCommandHandler('moveToHue', async ({ request: { hue } }) => {
197
+ this.light?.addCommandHandler('moveToHue', async ({ request: { hue } }) => {
163
198
  await this.light?.setAttribute(ColorControl.Cluster.id, 'currentHue', hue, this.light?.log);
164
199
  this.light?.log.debug(`Command moveToHue called request: hue ${hue}`);
165
200
  });
166
- this.light.addCommandHandler('moveToSaturation', async ({ request: { saturation } }) => {
201
+ this.light?.addCommandHandler('moveToSaturation', async ({ request: { saturation } }) => {
167
202
  await this.light?.setAttribute(ColorControl.Cluster.id, 'currentSaturation', saturation, this.light?.log);
168
203
  this.light?.log.debug(`Command moveToSaturation called request: saturation ${saturation}}`);
169
204
  });
170
- this.light.addCommandHandler('moveToColorTemperature', async ({ request: { colorTemperatureMireds } }) => {
205
+ this.light?.addCommandHandler('moveToColorTemperature', async ({ request: { colorTemperatureMireds } }) => {
171
206
  await this.light?.setAttribute(ColorControl.Cluster.id, 'colorTemperatureMireds', colorTemperatureMireds, this.light?.log);
172
207
  this.light?.log.debug(`Command moveToColorTemperature called request: ${colorTemperatureMireds}`);
173
208
  });
174
- this.lightHS = new MatterbridgeEndpoint([colorTemperatureLight, bridgedNode, powerSource], { uniqueStorageKey: 'Light (HS, CT)' }, this.config.debug).createDefaultIdentifyClusterServer();
175
- this.lightHS
209
+ this.lightHS = new MatterbridgeEndpoint([colorTemperatureLight, bridgedNode, powerSource], { uniqueStorageKey: 'Light (HS, CT)' }, this.config.debug)
210
+ .createDefaultIdentifyClusterServer()
176
211
  .createDefaultGroupsClusterServer()
177
212
  .createDefaultBridgedDeviceBasicInformationClusterServer('Light (HS, CT)', '0x25097564', 0xfff1, 'Matterbridge', 'Matterbridge Light', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
178
213
  .createDefaultOnOffClusterServer()
179
214
  .createDefaultLevelControlClusterServer()
180
215
  .createHsColorControlClusterServer()
181
216
  .createDefaultPowerSourceWiredClusterServer();
182
- await this.registerDevice(this.lightHS);
183
- this.bridgedDevices.set(this.lightHS.deviceName ?? '', this.lightHS);
184
- this.lightHS.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
217
+ this.setSelectDevice(this.lightHS.serialNumber ?? '', this.lightHS.deviceName ?? '', undefined, 'hub');
218
+ if (this.validateDevice(this.lightHS.deviceName ?? '')) {
219
+ await this.registerDevice(this.lightHS);
220
+ this.bridgedDevices.set(this.lightHS.deviceName ?? '', this.lightHS);
221
+ }
222
+ else {
223
+ this.lightHS = undefined;
224
+ }
225
+ this.lightHS?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
185
226
  this.lightHS?.log.info(`Command identify called identifyTime:${identifyTime}`);
186
227
  });
187
- this.lightHS.addCommandHandler('on', async () => {
228
+ this.lightHS?.addCommandHandler('on', async () => {
188
229
  await this.lightHS?.setAttribute(OnOff.Cluster.id, 'onOff', true, this.lightHS?.log);
189
230
  this.lightHS?.log.info('Command on called');
190
231
  });
191
- this.lightHS.addCommandHandler('off', async () => {
232
+ this.lightHS?.addCommandHandler('off', async () => {
192
233
  await this.lightHS?.setAttribute(OnOff.Cluster.id, 'onOff', false, this.lightHS?.log);
193
234
  this.lightHS?.log.info('Command off called');
194
235
  });
195
- this.lightHS.addCommandHandler('moveToLevel', async ({ request: { level } }) => {
236
+ this.lightHS?.addCommandHandler('moveToLevel', async ({ request: { level } }) => {
196
237
  await this.lightHS?.setAttribute(LevelControl.Cluster.id, 'currentLevel', level, this.lightHS?.log);
197
238
  this.lightHS?.log.debug(`Command moveToLevel called request: ${level}`);
198
239
  });
199
- this.lightHS.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level } }) => {
240
+ this.lightHS?.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level } }) => {
200
241
  await this.lightHS?.setAttribute(LevelControl.Cluster.id, 'currentLevel', level, this.lightHS?.log);
201
242
  this.lightHS?.log.debug(`Command moveToLevelWithOnOff called request: ${level}`);
202
243
  });
203
- this.lightHS.addCommandHandler('moveToHueAndSaturation', async ({ request: { hue, saturation } }) => {
244
+ this.lightHS?.addCommandHandler('moveToHueAndSaturation', async ({ request: { hue, saturation } }) => {
204
245
  await this.lightHS?.setAttribute(ColorControl.Cluster.id, 'currentHue', hue, this.lightHS?.log);
205
246
  await this.lightHS?.setAttribute(ColorControl.Cluster.id, 'currentSaturation', saturation, this.lightHS?.log);
206
247
  this.lightHS?.log.debug(`Command moveToHueAndSaturation called request: hue ${hue} saturation ${saturation}}`);
207
248
  });
208
- this.lightHS.addCommandHandler('moveToHue', async ({ request: { hue } }) => {
249
+ this.lightHS?.addCommandHandler('moveToHue', async ({ request: { hue } }) => {
209
250
  await this.lightHS?.setAttribute(ColorControl.Cluster.id, 'currentHue', hue, this.lightHS?.log);
210
251
  this.lightHS?.log.debug(`Command moveToHue called request: hue ${hue}`);
211
252
  });
212
- this.lightHS.addCommandHandler('moveToSaturation', async ({ request: { saturation } }) => {
253
+ this.lightHS?.addCommandHandler('moveToSaturation', async ({ request: { saturation } }) => {
213
254
  await this.lightHS?.setAttribute(ColorControl.Cluster.id, 'currentSaturation', saturation, this.lightHS?.log);
214
255
  this.lightHS?.log.debug(`Command moveToSaturation called request: saturation ${saturation}`);
215
256
  });
216
- this.lightHS.addCommandHandler('moveToColorTemperature', async ({ request: colorTemperatureMireds }) => {
257
+ this.lightHS?.addCommandHandler('moveToColorTemperature', async ({ request: { colorTemperatureMireds } }) => {
258
+ await this.lightHS?.setAttribute(ColorControl.Cluster.id, 'colorTemperatureMireds', colorTemperatureMireds, this.lightHS?.log);
217
259
  this.lightHS?.log.debug(`Command moveToColorTemperature called request: ${colorTemperatureMireds}`);
218
260
  });
219
- this.lightXY = new MatterbridgeEndpoint([colorTemperatureLight, bridgedNode, powerSource], { uniqueStorageKey: 'Light (XY, CT)' }, this.config.debug).createDefaultIdentifyClusterServer();
220
- this.lightXY
261
+ this.lightXY = new MatterbridgeEndpoint([colorTemperatureLight, bridgedNode, powerSource], { uniqueStorageKey: 'Light (XY, CT)' }, this.config.debug)
262
+ .createDefaultIdentifyClusterServer()
221
263
  .createDefaultGroupsClusterServer()
222
264
  .createDefaultBridgedDeviceBasicInformationClusterServer('Light (XY, CT)', '0x23497564', 0xfff1, 'Matterbridge', 'Matterbridge Light', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
223
265
  .createDefaultOnOffClusterServer()
224
266
  .createDefaultLevelControlClusterServer()
225
267
  .createXyColorControlClusterServer()
226
268
  .createDefaultPowerSourceWiredClusterServer();
227
- await this.registerDevice(this.lightXY);
228
- this.bridgedDevices.set(this.lightXY.deviceName ?? '', this.lightXY);
229
- this.lightXY.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
269
+ this.setSelectDevice(this.lightXY.serialNumber ?? '', this.lightXY.deviceName ?? '', undefined, 'hub');
270
+ if (this.validateDevice(this.lightXY.deviceName ?? '')) {
271
+ await this.registerDevice(this.lightXY);
272
+ this.bridgedDevices.set(this.lightXY.deviceName ?? '', this.lightXY);
273
+ }
274
+ else {
275
+ this.lightXY = undefined;
276
+ }
277
+ this.lightXY?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
230
278
  this.lightXY?.log.info(`Command identify called identifyTime:${identifyTime}`);
231
279
  });
232
- this.lightXY.addCommandHandler('on', async () => {
280
+ this.lightXY?.addCommandHandler('on', async () => {
233
281
  await this.lightXY?.setAttribute(OnOff.Cluster.id, 'onOff', true, this.lightXY?.log);
234
282
  this.lightXY?.log.info('Command on called');
235
283
  });
236
- this.lightXY.addCommandHandler('off', async () => {
284
+ this.lightXY?.addCommandHandler('off', async () => {
237
285
  await this.lightXY?.setAttribute(OnOff.Cluster.id, 'onOff', false, this.lightXY?.log);
238
286
  this.lightXY?.log.info('Command off called');
239
287
  });
240
- this.lightXY.addCommandHandler('moveToLevel', async ({ request: { level } }) => {
288
+ this.lightXY?.addCommandHandler('moveToLevel', async ({ request: { level } }) => {
241
289
  await this.lightXY?.setAttribute(LevelControl.Cluster.id, 'currentLevel', level, this.lightXY?.log);
242
290
  this.lightXY?.log.debug(`Command moveToLevel called request: ${level}`);
243
291
  });
244
- this.lightXY.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level } }) => {
292
+ this.lightXY?.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level } }) => {
245
293
  await this.lightXY?.setAttribute(LevelControl.Cluster.id, 'currentLevel', level, this.lightXY?.log);
246
294
  this.lightXY?.log.debug(`Command moveToLevelWithOnOff called request: ${level}`);
247
295
  });
248
- this.lightXY.addCommandHandler('moveToColor', async ({ request: { colorX, colorY } }) => {
296
+ this.lightXY?.addCommandHandler('moveToColor', async ({ request: { colorX, colorY } }) => {
249
297
  await this.lightXY?.setAttribute(ColorControl.Cluster.id, 'currentX', colorX, this.lightXY?.log);
250
298
  await this.lightXY?.setAttribute(ColorControl.Cluster.id, 'currentY', colorY, this.lightXY?.log);
251
299
  this.lightXY?.log.debug(`Command moveToColor called request: X ${colorX / 65536} Y ${colorY / 65536}`);
252
300
  });
253
- this.lightXY.addCommandHandler('moveToColorTemperature', async ({ request: { colorTemperatureMireds } }) => {
301
+ this.lightXY?.addCommandHandler('moveToColorTemperature', async ({ request: { colorTemperatureMireds } }) => {
254
302
  await this.lightXY?.setAttribute(ColorControl.Cluster.id, 'colorTemperatureMireds', colorTemperatureMireds, this.lightXY?.log);
255
303
  this.lightXY?.log.debug(`Command moveToColorTemperature called request: ${colorTemperatureMireds}`);
256
304
  });
257
- this.lightCT = new MatterbridgeEndpoint([colorTemperatureLight, bridgedNode, powerSource], { uniqueStorageKey: 'Light (CT)' }, this.config.debug).createDefaultIdentifyClusterServer();
258
- this.lightCT
305
+ this.lightCT = new MatterbridgeEndpoint([colorTemperatureLight, bridgedNode, powerSource], { uniqueStorageKey: 'Light (CT)' }, this.config.debug)
306
+ .createDefaultIdentifyClusterServer()
259
307
  .createDefaultGroupsClusterServer()
260
308
  .createDefaultBridgedDeviceBasicInformationClusterServer('Light (CT)', '0x23480749', 0xfff1, 'Matterbridge', 'Matterbridge Light', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
261
309
  .createDefaultOnOffClusterServer()
262
310
  .createDefaultLevelControlClusterServer()
263
311
  .createCtColorControlClusterServer()
264
312
  .createDefaultPowerSourceReplaceableBatteryClusterServer(70);
265
- await this.registerDevice(this.lightCT);
266
- this.bridgedDevices.set(this.lightCT.deviceName ?? '', this.lightCT);
267
- this.lightCT.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
313
+ this.setSelectDevice(this.lightCT.serialNumber ?? '', this.lightCT.deviceName ?? '', undefined, 'hub');
314
+ if (this.validateDevice(this.lightCT.deviceName ?? '')) {
315
+ await this.registerDevice(this.lightCT);
316
+ this.bridgedDevices.set(this.lightCT.deviceName ?? '', this.lightCT);
317
+ }
318
+ else {
319
+ this.lightCT = undefined;
320
+ }
321
+ this.lightCT?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
268
322
  this.lightCT?.log.info(`Command identify called identifyTime:${identifyTime}`);
269
323
  });
270
- this.lightCT.addCommandHandler('on', async () => {
324
+ this.lightCT?.addCommandHandler('on', async () => {
271
325
  await this.lightCT?.setAttribute(OnOff.Cluster.id, 'onOff', true, this.lightCT?.log);
272
326
  this.lightCT?.log.info('Command on called');
273
327
  });
274
- this.lightCT.addCommandHandler('off', async () => {
328
+ this.lightCT?.addCommandHandler('off', async () => {
275
329
  await this.lightCT?.setAttribute(OnOff.Cluster.id, 'onOff', false, this.lightCT?.log);
276
330
  this.lightCT?.log.info('Command off called');
277
331
  });
278
- this.lightCT.addCommandHandler('moveToLevel', async ({ request: { level } }) => {
332
+ this.lightCT?.addCommandHandler('moveToLevel', async ({ request: { level } }) => {
279
333
  await this.lightCT?.setAttribute(LevelControl.Cluster.id, 'currentLevel', level, this.lightCT?.log);
280
334
  this.lightCT?.log.debug(`Command moveToLevel called request: ${level}`);
281
335
  });
282
- this.lightCT.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level } }) => {
336
+ this.lightCT?.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level } }) => {
283
337
  await this.lightCT?.setAttribute(LevelControl.Cluster.id, 'currentLevel', level, this.lightCT?.log);
284
338
  this.lightCT?.log.debug(`Command moveToLevelWithOnOff called request: ${level}`);
285
339
  });
286
- this.lightCT.addCommandHandler('moveToColorTemperature', async ({ request: { colorTemperatureMireds } }) => {
340
+ this.lightCT?.addCommandHandler('moveToColorTemperature', async ({ request: { colorTemperatureMireds } }) => {
287
341
  await this.lightCT?.setAttribute(ColorControl.Cluster.id, 'colorTemperatureMireds', colorTemperatureMireds, this.lightCT?.log);
288
342
  this.lightCT?.log.debug(`Command moveToColorTemperature called request: ${colorTemperatureMireds}`);
289
343
  });
290
- this.outlet = new MatterbridgeEndpoint([onOffOutlet, bridgedNode, powerSource], { uniqueStorageKey: 'Outlet' }, this.config.debug).createDefaultIdentifyClusterServer();
291
- this.outlet
344
+ this.outlet = new MatterbridgeEndpoint([onOffOutlet, bridgedNode, powerSource], { uniqueStorageKey: 'Outlet' }, this.config.debug)
345
+ .createDefaultIdentifyClusterServer()
292
346
  .createDefaultGroupsClusterServer()
293
347
  .createDefaultBridgedDeviceBasicInformationClusterServer('Outlet', '0x29252164', 0xfff1, 'Matterbridge', 'Matterbridge Outlet', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
294
348
  .createDefaultOnOffClusterServer()
295
349
  .createDefaultPowerSourceWiredClusterServer();
296
- await this.registerDevice(this.outlet);
297
- this.bridgedDevices.set(this.outlet.deviceName ?? '', this.outlet);
298
- this.outlet.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
350
+ this.setSelectDevice(this.outlet.serialNumber ?? '', this.outlet.deviceName ?? '', undefined, 'hub');
351
+ if (this.validateDevice(this.outlet.deviceName ?? '')) {
352
+ await this.registerDevice(this.outlet);
353
+ this.bridgedDevices.set(this.outlet.deviceName ?? '', this.outlet);
354
+ }
355
+ else {
356
+ this.outlet = undefined;
357
+ }
358
+ this.outlet?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
299
359
  this.outlet?.log.info(`Command identify called identifyTime:${identifyTime}`);
300
360
  });
301
- this.outlet.addCommandHandler('on', async () => {
361
+ this.outlet?.addCommandHandler('on', async () => {
302
362
  await this.outlet?.setAttribute(OnOff.Cluster.id, 'onOff', true, this.outlet?.log);
303
363
  this.outlet?.log.info('Command on called');
304
364
  });
305
- this.outlet.addCommandHandler('off', async () => {
365
+ this.outlet?.addCommandHandler('off', async () => {
306
366
  await this.outlet?.setAttribute(OnOff.Cluster.id, 'onOff', false, this.outlet?.log);
307
367
  this.outlet?.log.info('Command off called');
308
368
  });
309
- this.cover = new MatterbridgeEndpoint([coverDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Cover' }, this.config.debug);
310
- this.cover.log.logName = 'Cover';
311
- this.cover.createDefaultIdentifyClusterServer();
312
- this.cover.createDefaultGroupsClusterServer();
313
- this.cover.createDefaultBridgedDeviceBasicInformationClusterServer('Cover', '0x01020564', 0xfff1, 'Matterbridge', 'Matterbridge Cover', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion);
314
- this.cover.createDefaultWindowCoveringClusterServer();
315
- this.cover.createDefaultPowerSourceRechargeableBatteryClusterServer(86);
316
- await this.registerDevice(this.cover);
317
- this.bridgedDevices.set(this.cover.deviceName ?? '', this.cover);
318
- this.cover.subscribeAttribute(WindowCovering.Cluster.id, 'mode', (newValue, oldValue) => {
369
+ this.cover = new MatterbridgeEndpoint([coverDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Cover' }, this.config.debug)
370
+ .createDefaultIdentifyClusterServer()
371
+ .createDefaultGroupsClusterServer()
372
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Cover', '0x01020564', 0xfff1, 'Matterbridge', 'Matterbridge Cover', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
373
+ .createDefaultWindowCoveringClusterServer()
374
+ .createDefaultPowerSourceRechargeableBatteryClusterServer(86);
375
+ this.setSelectDevice(this.cover.serialNumber ?? '', this.cover.deviceName ?? '', undefined, 'hub');
376
+ if (this.validateDevice(this.cover.deviceName ?? '')) {
377
+ await this.registerDevice(this.cover);
378
+ this.bridgedDevices.set(this.cover.deviceName ?? '', this.cover);
379
+ }
380
+ else {
381
+ this.cover = undefined;
382
+ }
383
+ this.cover?.subscribeAttribute(WindowCovering.Cluster.id, 'mode', (newValue, oldValue) => {
319
384
  this.cover?.log.info(`Attribute mode changed from ${oldValue} to ${newValue}. Reverse: ${newValue.motorDirectionReversed}. Calibration: ${newValue.calibrationMode}. Maintenance: ${newValue.maintenanceMode}. LED: ${newValue.ledFeedback}`);
320
385
  }, this.cover.log);
321
- this.cover.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
386
+ this.cover?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
322
387
  this.cover?.log.info(`Command identify called identifyTime:${identifyTime}`);
323
388
  });
324
- this.cover.addCommandHandler('stopMotion', async () => {
389
+ this.cover?.addCommandHandler('stopMotion', async () => {
325
390
  await this.cover?.setWindowCoveringTargetAsCurrentAndStopped();
326
391
  this.cover?.log.info(`Command stopMotion called`);
327
392
  });
328
- this.cover.addCommandHandler('downOrClose', async () => {
393
+ this.cover?.addCommandHandler('downOrClose', async () => {
329
394
  await this.cover?.setWindowCoveringCurrentTargetStatus(10000, 10000, WindowCovering.MovementStatus.Stopped);
330
395
  this.cover?.log.info(`Command downOrClose called`);
331
396
  });
332
- this.cover.addCommandHandler('upOrOpen', async () => {
397
+ this.cover?.addCommandHandler('upOrOpen', async () => {
333
398
  await this.cover?.setWindowCoveringCurrentTargetStatus(0, 0, WindowCovering.MovementStatus.Stopped);
334
399
  this.cover?.log.info(`Command upOrOpen called`);
335
400
  });
336
- this.cover.addCommandHandler('goToLiftPercentage', async ({ request: { liftPercent100thsValue } }) => {
401
+ this.cover?.addCommandHandler('goToLiftPercentage', async ({ request: { liftPercent100thsValue } }) => {
337
402
  await this.cover?.setWindowCoveringCurrentTargetStatus(liftPercent100thsValue, liftPercent100thsValue, WindowCovering.MovementStatus.Stopped);
338
403
  this.cover?.log.info(`Command goToLiftPercentage ${liftPercent100thsValue} called`);
339
404
  });
340
- this.lock = new MatterbridgeEndpoint([doorLockDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Lock' }, this.config.debug).createDefaultIdentifyClusterServer();
341
- this.lock
405
+ this.lock = new MatterbridgeEndpoint([doorLockDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Lock' }, this.config.debug)
406
+ .createDefaultIdentifyClusterServer()
342
407
  .createDefaultBridgedDeviceBasicInformationClusterServer('Lock', '0x96352164', 0xfff1, 'Matterbridge', 'Matterbridge Lock', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
343
408
  .createDefaultDoorLockClusterServer()
344
409
  .createDefaultPowerSourceRechargeableBatteryClusterServer(30);
345
- await this.registerDevice(this.lock);
346
- this.bridgedDevices.set(this.lock.deviceName ?? '', this.lock);
347
- this.lock.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
410
+ this.setSelectDevice(this.lock.serialNumber ?? '', this.lock.deviceName ?? '', undefined, 'hub');
411
+ if (this.validateDevice(this.lock.deviceName ?? '')) {
412
+ await this.registerDevice(this.lock);
413
+ this.bridgedDevices.set(this.lock.deviceName ?? '', this.lock);
414
+ }
415
+ else {
416
+ this.lock = undefined;
417
+ }
418
+ this.lock?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
348
419
  this.lock?.log.info(`Command identify called identifyTime:${identifyTime}`);
349
420
  });
350
- this.lock.addCommandHandler('lockDoor', async () => {
421
+ this.lock?.addCommandHandler('lockDoor', async () => {
351
422
  await this.lock?.setAttribute(DoorLock.Cluster.id, 'lockState', DoorLock.LockState.Locked, this.lock?.log);
352
423
  this.lock?.log.info('Command lockDoor called');
353
424
  });
354
- this.lock.addCommandHandler('unlockDoor', async () => {
425
+ this.lock?.addCommandHandler('unlockDoor', async () => {
355
426
  await this.lock?.setAttribute(DoorLock.Cluster.id, 'lockState', DoorLock.LockState.Unlocked, this.lock?.log);
356
427
  this.lock?.log.info('Command unlockDoor called');
357
428
  });
358
- this.thermoAuto = new MatterbridgeEndpoint([thermostatDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Thermostat (AutoMode)' }, this.config.debug).createDefaultIdentifyClusterServer();
359
- this.thermoAuto
429
+ this.thermoAuto = new MatterbridgeEndpoint([thermostatDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Thermostat (AutoMode)' }, this.config.debug)
430
+ .createDefaultIdentifyClusterServer()
360
431
  .createDefaultGroupsClusterServer()
361
432
  .createDefaultBridgedDeviceBasicInformationClusterServer('Thermostat (AutoMode)', '0x96382164A', 0xfff1, 'Matterbridge', 'Matterbridge Thermostat', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
362
433
  .createDefaultThermostatClusterServer(20, 18, 22)
@@ -373,15 +444,21 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
373
444
  .addChildDeviceType('Humidity', humiditySensor)
374
445
  .createDefaultRelativeHumidityMeasurementClusterServer(50 * 100)
375
446
  .addRequiredClusterServers();
376
- await this.registerDevice(this.thermoAuto);
377
- this.bridgedDevices.set(this.thermoAuto.deviceName ?? '', this.thermoAuto);
378
- this.thermoAuto.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
447
+ this.setSelectDevice(this.thermoAuto.serialNumber ?? '', this.thermoAuto.deviceName ?? '', undefined, 'hub');
448
+ if (this.validateDevice(this.thermoAuto.deviceName ?? '')) {
449
+ await this.registerDevice(this.thermoAuto);
450
+ this.bridgedDevices.set(this.thermoAuto.deviceName ?? '', this.thermoAuto);
451
+ }
452
+ else {
453
+ this.thermoAuto = undefined;
454
+ }
455
+ this.thermoAuto?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
379
456
  this.thermoAuto?.log.info(`Command identify called identifyTime ${identifyTime}`);
380
457
  });
381
- this.thermoAuto.addCommandHandler('triggerEffect', async ({ request: { effectIdentifier, effectVariant } }) => {
458
+ this.thermoAuto?.addCommandHandler('triggerEffect', async ({ request: { effectIdentifier, effectVariant } }) => {
382
459
  this.thermoAuto?.log.info(`Command identify called effectIdentifier ${effectIdentifier} effectVariant ${effectVariant}`);
383
460
  });
384
- this.thermoAuto.addCommandHandler('setpointRaiseLower', async ({ request: { mode, amount } }) => {
461
+ this.thermoAuto?.addCommandHandler('setpointRaiseLower', async ({ request: { mode, amount } }) => {
385
462
  const lookupSetpointAdjustMode = ['Heat', 'Cool', 'Both'];
386
463
  this.thermoAuto?.log.info(`Command setpointRaiseLower called with mode: ${lookupSetpointAdjustMode[mode]} amount: ${amount / 10}`);
387
464
  if (mode === Thermostat.SetpointRaiseLowerMode.Heat || mode === Thermostat.SetpointRaiseLowerMode.Both) {
@@ -395,18 +472,18 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
395
472
  this.thermoAuto?.log.info('Set occupiedCoolingSetpoint:', setpoint);
396
473
  }
397
474
  });
398
- this.thermoAuto.subscribeAttribute(ThermostatCluster.id, 'systemMode', async (value) => {
475
+ this.thermoAuto?.subscribeAttribute(ThermostatCluster.id, 'systemMode', async (value) => {
399
476
  const lookupSystemMode = ['Off', 'Auto', '', 'Cool', 'Heat', 'EmergencyHeat', 'Precooling', 'FanOnly', 'Dry', 'Sleep'];
400
477
  this.thermoAuto?.log.info('Subscribe systemMode called with:', lookupSystemMode[value]);
401
478
  }, this.thermoAuto.log);
402
- this.thermoAuto.subscribeAttribute(ThermostatCluster.id, 'occupiedHeatingSetpoint', async (value) => {
479
+ this.thermoAuto?.subscribeAttribute(ThermostatCluster.id, 'occupiedHeatingSetpoint', async (value) => {
403
480
  this.thermoAuto?.log.info('Subscribe occupiedHeatingSetpoint called with:', value / 100);
404
481
  }, this.thermoAuto.log);
405
- this.thermoAuto.subscribeAttribute(ThermostatCluster.id, 'occupiedCoolingSetpoint', async (value) => {
482
+ this.thermoAuto?.subscribeAttribute(ThermostatCluster.id, 'occupiedCoolingSetpoint', async (value) => {
406
483
  this.thermoAuto?.log.info('Subscribe occupiedCoolingSetpoint called with:', value / 100);
407
484
  }, this.thermoAuto.log);
408
- this.thermoHeat = new MatterbridgeEndpoint([thermostatDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Thermostat (Heat)' }, this.config.debug).createDefaultIdentifyClusterServer();
409
- this.thermoHeat
485
+ this.thermoHeat = new MatterbridgeEndpoint([thermostatDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Thermostat (Heat)' }, this.config.debug)
486
+ .createDefaultIdentifyClusterServer()
410
487
  .createDefaultGroupsClusterServer()
411
488
  .createDefaultBridgedDeviceBasicInformationClusterServer('Thermostat (Heat)', '0x96382164H', 0xfff1, 'Matterbridge', 'Matterbridge Thermostat', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
412
489
  .createDefaultHeatingThermostatClusterServer(20, 18, 5, 35)
@@ -423,19 +500,25 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
423
500
  })
424
501
  .createDefaultIdentifyClusterServer()
425
502
  .createDefaultTemperatureMeasurementClusterServer(15 * 100);
426
- await this.registerDevice(this.thermoHeat);
427
- this.bridgedDevices.set(this.thermoHeat.deviceName ?? '', this.thermoHeat);
428
- this.thermoHeat.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
503
+ this.setSelectDevice(this.thermoHeat.serialNumber ?? '', this.thermoHeat.deviceName ?? '', undefined, 'hub');
504
+ if (this.validateDevice(this.thermoHeat.deviceName ?? '')) {
505
+ await this.registerDevice(this.thermoHeat);
506
+ this.bridgedDevices.set(this.thermoHeat.deviceName ?? '', this.thermoHeat);
507
+ }
508
+ else {
509
+ this.thermoHeat = undefined;
510
+ }
511
+ this.thermoHeat?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
429
512
  this.thermoHeat?.log.info(`Command identify called identifyTime ${identifyTime}`);
430
513
  });
431
- this.thermoHeat.addCommandHandler('triggerEffect', async ({ request: { effectIdentifier, effectVariant } }) => {
514
+ this.thermoHeat?.addCommandHandler('triggerEffect', async ({ request: { effectIdentifier, effectVariant } }) => {
432
515
  this.thermoHeat?.log.info(`Command identify called effectIdentifier ${effectIdentifier} effectVariant ${effectVariant}`);
433
516
  });
434
- this.thermoHeat.subscribeAttribute(ThermostatCluster.id, 'systemMode', async (value) => {
517
+ this.thermoHeat?.subscribeAttribute(ThermostatCluster.id, 'systemMode', async (value) => {
435
518
  const lookupSystemMode = ['Off', 'Auto', '', 'Cool', 'Heat', 'EmergencyHeat', 'Precooling', 'FanOnly', 'Dry', 'Sleep'];
436
519
  this.thermoHeat?.log.info('Subscribe systemMode called with:', lookupSystemMode[value]);
437
520
  }, this.thermoHeat.log);
438
- this.thermoHeat.subscribeAttribute(ThermostatCluster.id, 'occupiedHeatingSetpoint', async (value) => {
521
+ this.thermoHeat?.subscribeAttribute(ThermostatCluster.id, 'occupiedHeatingSetpoint', async (value) => {
439
522
  this.thermoHeat?.log.info('Subscribe occupiedHeatingSetpoint called with:', value / 100);
440
523
  }, this.thermoHeat.log);
441
524
  this.thermoCool = new MatterbridgeEndpoint([thermostatDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Thermostat (Cool)' }, this.config.debug)
@@ -444,36 +527,46 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
444
527
  .createDefaultBridgedDeviceBasicInformationClusterServer('Thermostat (Cool)', '0x96382164C', 0xfff1, 'Matterbridge', 'Matterbridge Thermostat', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
445
528
  .createDefaultCoolingThermostatClusterServer(20, 18, 5, 35)
446
529
  .createDefaultPowerSourceReplaceableBatteryClusterServer(40, PowerSource.BatChargeLevel.Ok, 5080, 'AA 1.5V', 4);
447
- await this.registerDevice(this.thermoCool);
448
- this.bridgedDevices.set(this.thermoCool.deviceName ?? '', this.thermoCool);
449
- this.thermoCool.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
530
+ this.setSelectDevice(this.thermoCool.serialNumber ?? '', this.thermoCool.deviceName ?? '', undefined, 'hub');
531
+ if (this.validateDevice(this.thermoCool.deviceName ?? '')) {
532
+ await this.registerDevice(this.thermoCool);
533
+ this.bridgedDevices.set(this.thermoCool.deviceName ?? '', this.thermoCool);
534
+ }
535
+ else {
536
+ this.thermoCool = undefined;
537
+ }
538
+ this.thermoCool?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
450
539
  this.thermoCool?.log.info(`Command identify called identifyTime ${identifyTime}`);
451
540
  });
452
- this.thermoCool.addCommandHandler('triggerEffect', async ({ request: { effectIdentifier, effectVariant } }) => {
541
+ this.thermoCool?.addCommandHandler('triggerEffect', async ({ request: { effectIdentifier, effectVariant } }) => {
453
542
  this.thermoCool?.log.info(`Command identify called effectIdentifier ${effectIdentifier} effectVariant ${effectVariant}`);
454
543
  });
455
- this.thermoCool.subscribeAttribute(ThermostatCluster.id, 'systemMode', async (value) => {
544
+ this.thermoCool?.subscribeAttribute(ThermostatCluster.id, 'systemMode', async (value) => {
456
545
  const lookupSystemMode = ['Off', 'Auto', '', 'Cool', 'Heat', 'EmergencyHeat', 'Precooling', 'FanOnly', 'Dry', 'Sleep'];
457
546
  this.thermoCool?.log.info('Subscribe systemMode called with:', lookupSystemMode[value]);
458
547
  }, this.thermoCool.log);
459
- this.thermoCool.subscribeAttribute(ThermostatCluster.id, 'occupiedCoolingSetpoint', async (value) => {
548
+ this.thermoCool?.subscribeAttribute(ThermostatCluster.id, 'occupiedCoolingSetpoint', async (value) => {
460
549
  this.thermoCool?.log.info('Subscribe occupiedCoolingSetpoint called with:', value / 100);
461
550
  }, this.thermoCool.log);
462
- this.airPurifier = new MatterbridgeEndpoint([airPurifier, temperatureSensor, humiditySensor, bridgedNode, powerSource], { uniqueStorageKey: 'Air purifier' }, this.config.debug);
463
- this.airPurifier.log.logName = 'Air purifier';
464
- this.airPurifier
551
+ this.airPurifier = new MatterbridgeEndpoint([airPurifier, temperatureSensor, humiditySensor, bridgedNode, powerSource], { uniqueStorageKey: 'Air purifier' }, this.config.debug)
465
552
  .createDefaultBridgedDeviceBasicInformationClusterServer('Air purifier', '0x96584864AP', 0xfff1, 'Matterbridge', 'Matterbridge Air purifier', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
466
553
  .createDefaultIdentifyClusterServer()
467
554
  .createDefaultFanControlClusterServer()
468
555
  .createDefaultTemperatureMeasurementClusterServer(20 * 100)
469
556
  .createDefaultRelativeHumidityMeasurementClusterServer(50 * 100)
470
557
  .createDefaultPowerSourceWiredClusterServer();
471
- await this.registerDevice(this.airPurifier);
472
- this.bridgedDevices.set(this.airPurifier.deviceName ?? '', this.airPurifier);
473
- this.airPurifier.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
558
+ this.setSelectDevice(this.airPurifier.serialNumber ?? '', this.airPurifier.deviceName ?? '', undefined, 'hub');
559
+ if (this.validateDevice(this.airPurifier.deviceName ?? '')) {
560
+ await this.registerDevice(this.airPurifier);
561
+ this.bridgedDevices.set(this.airPurifier.deviceName ?? '', this.airPurifier);
562
+ }
563
+ else {
564
+ this.airPurifier = undefined;
565
+ }
566
+ this.airPurifier?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
474
567
  this.airPurifier?.log.info(`Command identify called identifyTime:${identifyTime}`);
475
568
  });
476
- this.airPurifier.subscribeAttribute(FanControl.Cluster.id, 'fanMode', async (newValue, oldValue) => {
569
+ this.airPurifier?.subscribeAttribute(FanControl.Cluster.id, 'fanMode', async (newValue, oldValue) => {
477
570
  this.fan?.log.info(`Fan mode changed from ${this.fanModeLookup[oldValue]} to ${this.fanModeLookup[newValue]}`);
478
571
  if (newValue === FanControl.FanMode.Off) {
479
572
  await this.airPurifier?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 0, this.airPurifier?.log);
@@ -494,7 +587,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
494
587
  await this.airPurifier?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 50, this.airPurifier?.log);
495
588
  }
496
589
  }, this.airPurifier.log);
497
- this.airPurifier.subscribeAttribute(FanControl.Cluster.id, 'percentSetting', async (newValue, oldValue) => {
590
+ this.airPurifier?.subscribeAttribute(FanControl.Cluster.id, 'percentSetting', async (newValue, oldValue) => {
498
591
  this.fan?.log.info(`Percent setting changed from ${oldValue} to ${newValue}`);
499
592
  if (isValidNumber(newValue, 0, 100))
500
593
  await this.airPurifier?.setAttribute(FanControl.Cluster.id, 'percentCurrent', newValue, this.airPurifier?.log);
@@ -509,12 +602,18 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
509
602
  .createDefaultRelativeHumidityMeasurementClusterServer(50 * 100)
510
603
  .createDefaultPowerSourceWiredClusterServer()
511
604
  .addRequiredClusterServers();
512
- await this.registerDevice(this.airConditioner);
513
- this.bridgedDevices.set(this.airConditioner.deviceName ?? '', this.airConditioner);
514
- this.airConditioner.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
605
+ this.setSelectDevice(this.airConditioner.serialNumber ?? '', this.airConditioner.deviceName ?? '', undefined, 'hub');
606
+ if (this.validateDevice(this.airConditioner.deviceName ?? '')) {
607
+ await this.registerDevice(this.airConditioner);
608
+ this.bridgedDevices.set(this.airConditioner.deviceName ?? '', this.airConditioner);
609
+ }
610
+ else {
611
+ this.airConditioner = undefined;
612
+ }
613
+ this.airConditioner?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
515
614
  this.airConditioner?.log.info(`Command identify called identifyTime:${identifyTime}`);
516
615
  });
517
- this.airConditioner.addCommandHandler('on', async () => {
616
+ this.airConditioner?.addCommandHandler('on', async () => {
518
617
  this.airConditioner?.log.info('Command on called');
519
618
  await this.airConditioner?.setAttribute(OnOff.Cluster.id, 'onOff', true, this.airConditioner?.log);
520
619
  await this.airConditioner?.setAttribute(OnOff.Cluster.id, 'onOff', true, this.airConditioner?.log);
@@ -524,7 +623,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
524
623
  await this.airConditioner?.setAttribute(FanControl.Cluster.id, 'speedSetting', 50, this.airConditioner?.log);
525
624
  await this.airConditioner?.setAttribute(FanControl.Cluster.id, 'percentSetting', 50, this.airConditioner?.log);
526
625
  });
527
- this.airConditioner.addCommandHandler('off', async () => {
626
+ this.airConditioner?.addCommandHandler('off', async () => {
528
627
  this.airConditioner?.log.info('Command off called');
529
628
  await this.airConditioner?.setAttribute(OnOff.Cluster.id, 'onOff', false, this.airConditioner?.log);
530
629
  await this.airConditioner?.setAttribute(ThermostatCluster.id, 'localTemperature', null, this.airConditioner?.log);
@@ -539,16 +638,22 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
539
638
  .createDefaultOnOffClusterServer(true)
540
639
  .createDefaultPumpConfigurationAndControlClusterServer()
541
640
  .createDefaultPowerSourceWiredClusterServer();
542
- await this.registerDevice(this.pump);
543
- this.bridgedDevices.set(this.pump.deviceName ?? '', this.pump);
544
- this.pump.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
641
+ this.setSelectDevice(this.pump.serialNumber ?? '', this.pump.deviceName ?? '', undefined, 'hub');
642
+ if (this.validateDevice(this.pump.deviceName ?? '')) {
643
+ await this.registerDevice(this.pump);
644
+ this.bridgedDevices.set(this.pump.deviceName ?? '', this.pump);
645
+ }
646
+ else {
647
+ this.pump = undefined;
648
+ }
649
+ this.pump?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
545
650
  this.pump?.log.info(`Command identify called identifyTime:${identifyTime}`);
546
651
  });
547
- this.pump.addCommandHandler('on', async () => {
652
+ this.pump?.addCommandHandler('on', async () => {
548
653
  this.pump?.log.info('Command on called');
549
654
  await this.pump?.setAttribute(OnOff.Cluster.id, 'onOff', true, this.pump?.log);
550
655
  });
551
- this.pump.addCommandHandler('off', async () => {
656
+ this.pump?.addCommandHandler('off', async () => {
552
657
  this.pump?.log.info('Command off called');
553
658
  await this.pump?.setAttribute(OnOff.Cluster.id, 'onOff', false, this.pump?.log);
554
659
  });
@@ -557,43 +662,61 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
557
662
  .createDefaultIdentifyClusterServer()
558
663
  .createDefaultValveConfigurationAndControlClusterServer()
559
664
  .createDefaultPowerSourceWiredClusterServer();
560
- await this.registerDevice(this.valve);
561
- this.bridgedDevices.set(this.valve.deviceName ?? '', this.valve);
562
- this.valve.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
665
+ this.setSelectDevice(this.valve.serialNumber ?? '', this.valve.deviceName ?? '', undefined, 'hub');
666
+ if (this.validateDevice(this.valve.deviceName ?? '')) {
667
+ await this.registerDevice(this.valve);
668
+ this.bridgedDevices.set(this.valve.deviceName ?? '', this.valve);
669
+ }
670
+ else {
671
+ this.valve = undefined;
672
+ }
673
+ this.valve?.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
563
674
  this.valve?.log.info(`Command identify called identifyTime:${identifyTime}`);
564
675
  });
565
676
  this.fan = new MatterbridgeEndpoint([fanDevice, bridgedNode], { uniqueStorageKey: 'Fan' }, this.config.debug)
566
677
  .createDefaultBridgedDeviceBasicInformationClusterServer('Fan', 'serial_980545631228', 0xfff1, 'Matterbridge', 'Matterbridge Fan', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
567
678
  .addRequiredClusterServers();
568
- await this.registerDevice(this.fan);
569
- this.bridgedDevices.set(this.fan.deviceName ?? '', this.fan);
570
- this.fan.subscribeAttribute(FanControl.Cluster.id, 'fanMode', async (newValue, oldValue) => {
679
+ this.setSelectDevice(this.fan.serialNumber ?? '', this.fan.deviceName ?? '', undefined, 'hub');
680
+ if (this.validateDevice(this.fan.deviceName ?? '')) {
681
+ await this.registerDevice(this.fan);
682
+ this.bridgedDevices.set(this.fan.deviceName ?? '', this.fan);
683
+ }
684
+ else {
685
+ this.fan = undefined;
686
+ }
687
+ this.fan?.subscribeAttribute(FanControl.Cluster.id, 'fanMode', async (newValue, oldValue) => {
571
688
  this.fan?.log.info(`Fan mode changed from ${this.fanModeLookup[oldValue]} to ${this.fanModeLookup[newValue]}`);
572
689
  if (newValue === FanControl.FanMode.Off) {
690
+ await this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 0, this.fan?.log);
573
691
  await this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 0, this.fan?.log);
574
692
  }
575
693
  else if (newValue === FanControl.FanMode.Low) {
694
+ await this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 33, this.fan?.log);
576
695
  await this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 33, this.fan?.log);
577
696
  }
578
697
  else if (newValue === FanControl.FanMode.Medium) {
698
+ await this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 66, this.fan?.log);
579
699
  await this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 66, this.fan?.log);
580
700
  }
581
701
  else if (newValue === FanControl.FanMode.High) {
702
+ await this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 100, this.fan?.log);
582
703
  await this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 100, this.fan?.log);
583
704
  }
584
705
  else if (newValue === FanControl.FanMode.On) {
706
+ await this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 100, this.fan?.log);
585
707
  await this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 100, this.fan?.log);
586
708
  }
587
709
  else if (newValue === FanControl.FanMode.Auto) {
710
+ await this.fan?.setAttribute(FanControl.Cluster.id, 'percentSetting', 50, this.fan?.log);
588
711
  await this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', 50, this.fan?.log);
589
712
  }
590
713
  }, this.fan.log);
591
- this.fan.subscribeAttribute(FanControl.Cluster.id, 'percentSetting', async (newValue, oldValue) => {
714
+ this.fan?.subscribeAttribute(FanControl.Cluster.id, 'percentSetting', async (newValue, oldValue) => {
592
715
  this.fan?.log.info(`Percent setting changed from ${oldValue} to ${newValue}`);
593
716
  if (isValidNumber(newValue, 0, 100))
594
717
  await this.fan?.setAttribute(FanControl.Cluster.id, 'percentCurrent', newValue, this.fan?.log);
595
718
  }, this.fan.log);
596
- this.fan.subscribeAttribute(FanControl.Cluster.id, 'speedSetting', async (newValue, oldValue) => {
719
+ this.fan?.subscribeAttribute(FanControl.Cluster.id, 'speedSetting', async (newValue, oldValue) => {
597
720
  this.fan?.log.info(`Speed setting changed from ${oldValue} to ${newValue}`);
598
721
  if (isValidNumber(newValue, 0, 100))
599
722
  await this.fan?.setAttribute(FanControl.Cluster.id, 'speedCurrent', newValue, this.fan?.log);
@@ -603,62 +726,130 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
603
726
  .createDefaultBooleanStateClusterServer(false)
604
727
  .addRequiredClusterServers()
605
728
  .addOptionalClusterServers();
606
- this.registerDevice(this.waterLeak);
607
- this.bridgedDevices.set(this.waterLeak.deviceName ?? '', this.waterLeak);
729
+ this.setSelectDevice(this.waterLeak.serialNumber ?? '', this.waterLeak.deviceName ?? '', undefined, 'hub');
730
+ if (this.validateDevice(this.waterLeak.deviceName ?? '')) {
731
+ await this.registerDevice(this.waterLeak);
732
+ this.bridgedDevices.set(this.waterLeak.deviceName ?? '', this.waterLeak);
733
+ }
734
+ else {
735
+ this.waterLeak = undefined;
736
+ }
608
737
  this.waterFreeze = new MatterbridgeEndpoint([waterFreezeDetector, bridgedNode], { uniqueStorageKey: 'Water freeze detector' }, this.config.debug)
609
738
  .createDefaultBridgedDeviceBasicInformationClusterServer('Water freeze detector', 'serial_98745631223', 0xfff1, 'Matterbridge', 'Matterbridge WaterFreezeDetector', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
610
739
  .createDefaultBooleanStateClusterServer(false)
611
740
  .addRequiredClusterServers()
612
741
  .addOptionalClusterServers();
613
- await this.registerDevice(this.waterFreeze);
614
- this.bridgedDevices.set(this.waterFreeze.deviceName ?? '', this.waterFreeze);
742
+ this.setSelectDevice(this.waterFreeze.serialNumber ?? '', this.waterFreeze.deviceName ?? '', undefined, 'hub');
743
+ if (this.validateDevice(this.waterFreeze.deviceName ?? '')) {
744
+ await this.registerDevice(this.waterFreeze);
745
+ this.bridgedDevices.set(this.waterFreeze.deviceName ?? '', this.waterFreeze);
746
+ }
747
+ else {
748
+ this.waterFreeze = undefined;
749
+ }
615
750
  this.rain = new MatterbridgeEndpoint([rainSensor, bridgedNode], { uniqueStorageKey: 'Rain sensor' }, this.config.debug)
616
751
  .createDefaultBridgedDeviceBasicInformationClusterServer('Rain sensor', 'serial_98745631224', 0xfff1, 'Matterbridge', 'Matterbridge RainSensor', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
617
752
  .createDefaultIdentifyClusterServer()
618
753
  .createDefaultBooleanStateClusterServer(false)
619
754
  .createDefaultBooleanStateConfigurationClusterServer();
620
- await this.registerDevice(this.rain);
621
- this.bridgedDevices.set(this.rain.deviceName ?? '', this.rain);
622
- this.smoke = new MatterbridgeEndpoint([smokeCoAlarm, bridgedNode], { uniqueStorageKey: 'Smoke alarm sensor' }, this.config.debug)
623
- .createDefaultBridgedDeviceBasicInformationClusterServer('Smoke alarm sensor', 'serial_94745631225', 0xfff1, 'Matterbridge', 'Matterbridge SmokeCoAlarm', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
755
+ this.setSelectDevice(this.rain.serialNumber ?? '', this.rain.deviceName ?? '', undefined, 'hub');
756
+ if (this.validateDevice(this.rain.deviceName ?? '')) {
757
+ await this.registerDevice(this.rain);
758
+ this.bridgedDevices.set(this.rain.deviceName ?? '', this.rain);
759
+ }
760
+ else {
761
+ this.rain = undefined;
762
+ }
763
+ this.smokeCo = new MatterbridgeEndpoint([smokeCoAlarm, bridgedNode], { uniqueStorageKey: 'SmokeCo alarm sensor' }, this.config.debug)
764
+ .createDefaultBridgedDeviceBasicInformationClusterServer('SmokeCo alarm sensor', 'serial_94745631225', 0xfff1, 'Matterbridge', 'Matterbridge SmokeCoAlarm', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
765
+ .createDefaultIdentifyClusterServer()
766
+ .createDefaultSmokeCOAlarmClusterServer(SmokeCoAlarm.AlarmState.Normal, SmokeCoAlarm.AlarmState.Normal);
767
+ if (this.config.enableConcentrationMeasurements === true)
768
+ this.smokeCo.createDefaultCarbonMonoxideConcentrationMeasurementClusterServer(100);
769
+ this.setSelectDevice(this.smokeCo.serialNumber ?? '', this.smokeCo.deviceName ?? '', undefined, 'hub');
770
+ if (this.validateDevice(this.smokeCo.deviceName ?? '')) {
771
+ await this.registerDevice(this.smokeCo);
772
+ this.bridgedDevices.set(this.smokeCo.deviceName ?? '', this.smokeCo);
773
+ }
774
+ else {
775
+ this.smokeCo = undefined;
776
+ }
777
+ this.smokeOnly = new MatterbridgeEndpoint([smokeCoAlarm, bridgedNode], { uniqueStorageKey: 'Smoke only SmokeCo alarm sensor' }, this.config.debug)
778
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Smoke only SmokeCo alarm sensor', 'serial_94755661225', 0xfff1, 'Matterbridge', 'Matterbridge SmokeCoAlarm', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
624
779
  .createDefaultIdentifyClusterServer()
625
- .createDefaultSmokeCOAlarmClusterServer(SmokeCoAlarm.AlarmState.Normal, SmokeCoAlarm.AlarmState.Normal)
626
- .createDefaultCarbonMonoxideConcentrationMeasurementClusterServer(100);
627
- await this.registerDevice(this.smoke);
628
- this.bridgedDevices.set(this.smoke.deviceName ?? '', this.smoke);
780
+ .createSmokeOnlySmokeCOAlarmClusterServer(SmokeCoAlarm.AlarmState.Normal);
781
+ this.setSelectDevice(this.smokeOnly.serialNumber ?? '', this.smokeOnly.deviceName ?? '', undefined, 'hub');
782
+ if (this.validateDevice(this.smokeOnly.deviceName ?? '')) {
783
+ await this.registerDevice(this.smokeOnly);
784
+ this.bridgedDevices.set(this.smokeOnly.deviceName ?? '', this.smokeOnly);
785
+ }
786
+ else {
787
+ this.smokeOnly = undefined;
788
+ }
789
+ this.coOnly = new MatterbridgeEndpoint([smokeCoAlarm, bridgedNode], { uniqueStorageKey: 'Co only SmokeCo alarm sensor' }, this.config.debug)
790
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Co only SmokeCo alarm sensor', 'serial_947456317488', 0xfff1, 'Matterbridge', 'Matterbridge SmokeCoAlarm', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
791
+ .createDefaultIdentifyClusterServer()
792
+ .createCoOnlySmokeCOAlarmClusterServer(SmokeCoAlarm.AlarmState.Normal);
793
+ if (this.config.enableConcentrationMeasurements === true)
794
+ this.coOnly.createDefaultCarbonMonoxideConcentrationMeasurementClusterServer(100);
795
+ this.setSelectDevice(this.coOnly.serialNumber ?? '', this.coOnly.deviceName ?? '', undefined, 'hub');
796
+ if (this.validateDevice(this.coOnly.deviceName ?? '')) {
797
+ await this.registerDevice(this.coOnly);
798
+ this.bridgedDevices.set(this.coOnly.deviceName ?? '', this.coOnly);
799
+ }
800
+ else {
801
+ this.coOnly = undefined;
802
+ }
629
803
  this.airQuality = new MatterbridgeEndpoint([airQualitySensor, bridgedNode], { uniqueStorageKey: 'Air quality sensor' }, this.config.debug)
630
804
  .createDefaultBridgedDeviceBasicInformationClusterServer('Air quality sensor', 'serial_987484318322', 0xfff1, 'Matterbridge', 'Matterbridge Air Quality Sensor', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
631
805
  .addRequiredClusterServers()
632
- .addClusterServers([
633
- TemperatureMeasurement.Cluster.id,
634
- RelativeHumidityMeasurement.Cluster.id,
635
- CarbonMonoxideConcentrationMeasurement.Cluster.id,
636
- CarbonDioxideConcentrationMeasurement.Cluster.id,
637
- NitrogenDioxideConcentrationMeasurement.Cluster.id,
638
- OzoneConcentrationMeasurement.Cluster.id,
639
- FormaldehydeConcentrationMeasurement.Cluster.id,
640
- Pm1ConcentrationMeasurement.Cluster.id,
641
- Pm25ConcentrationMeasurement.Cluster.id,
642
- Pm10ConcentrationMeasurement.Cluster.id,
643
- RadonConcentrationMeasurement.Cluster.id,
644
- TotalVolatileOrganicCompoundsConcentrationMeasurement.Cluster.id,
645
- ]);
646
- await this.registerDevice(this.airQuality);
647
- this.bridgedDevices.set(this.airQuality.deviceName ?? '', this.airQuality);
806
+ .addClusterServers([TemperatureMeasurement.Cluster.id, RelativeHumidityMeasurement.Cluster.id]);
807
+ if (this.config.enableConcentrationMeasurements === true) {
808
+ this.airQuality.createDefaultCarbonMonoxideConcentrationMeasurementClusterServer(10);
809
+ this.airQuality.createDefaultCarbonDioxideConcentrationMeasurementClusterServer(400);
810
+ this.airQuality.createDefaultNitrogenDioxideConcentrationMeasurementClusterServer(1);
811
+ this.airQuality.createDefaultOzoneConcentrationMeasurementClusterServer(1);
812
+ this.airQuality.createDefaultFormaldehydeConcentrationMeasurementClusterServer(1);
813
+ this.airQuality.createDefaultPm1ConcentrationMeasurementClusterServer(100);
814
+ this.airQuality.createDefaultPm25ConcentrationMeasurementClusterServer(100);
815
+ this.airQuality.createDefaultPm10ConcentrationMeasurementClusterServer(100);
816
+ this.airQuality.createDefaultRadonConcentrationMeasurementClusterServer(100);
817
+ this.airQuality.createDefaultTvocMeasurementClusterServer(100);
818
+ }
819
+ this.setSelectDevice(this.airQuality.serialNumber ?? '', this.airQuality.deviceName ?? '', undefined, 'hub');
820
+ if (this.validateDevice(this.airQuality.deviceName ?? '')) {
821
+ await this.registerDevice(this.airQuality);
822
+ this.bridgedDevices.set(this.airQuality.deviceName ?? '', this.airQuality);
823
+ }
824
+ else {
825
+ this.airQuality = undefined;
826
+ }
648
827
  this.momentarySwitch = new MatterbridgeEndpoint([genericSwitch, bridgedNode, powerSource], { uniqueStorageKey: 'Momentary switch' }, this.config.debug)
649
828
  .createDefaultBridgedDeviceBasicInformationClusterServer('Momentary switch', 'serial_947942331225', 0xfff1, 'Matterbridge', 'Matterbridge MomentarySwitch', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
650
829
  .createDefaultIdentifyClusterServer()
651
830
  .createDefaultSwitchClusterServer()
652
831
  .createDefaultPowerSourceReplaceableBatteryClusterServer(50, PowerSource.BatChargeLevel.Ok, 2900, 'CR2450', 1);
653
- await this.registerDevice(this.momentarySwitch);
654
- this.bridgedDevices.set(this.momentarySwitch.deviceName ?? '', this.momentarySwitch);
832
+ this.setSelectDevice(this.momentarySwitch.serialNumber ?? '', this.momentarySwitch.deviceName ?? '', undefined, 'hub');
833
+ if (this.validateDevice(this.momentarySwitch.deviceName ?? '')) {
834
+ await this.registerDevice(this.momentarySwitch);
835
+ this.bridgedDevices.set(this.momentarySwitch.deviceName ?? '', this.momentarySwitch);
836
+ }
837
+ else {
838
+ this.momentarySwitch = undefined;
839
+ }
655
840
  this.latchingSwitch = new MatterbridgeEndpoint([genericSwitch, bridgedNode, powerSource], { uniqueStorageKey: 'Latching switch' }, this.config.debug)
656
841
  .createDefaultBridgedDeviceBasicInformationClusterServer('Latching switch', 'serial_947442331225', 0xfff1, 'Matterbridge', 'Matterbridge LatchingSwitch', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
657
842
  .createDefaultIdentifyClusterServer()
658
843
  .createDefaultLatchingSwitchClusterServer()
659
844
  .createDefaultPowerSourceReplaceableBatteryClusterServer(10, PowerSource.BatChargeLevel.Critical, 2850, 'CR2032', 1);
660
- await this.registerDevice(this.latchingSwitch);
661
- this.bridgedDevices.set(this.latchingSwitch.deviceName ?? '', this.latchingSwitch);
845
+ this.setSelectDevice(this.latchingSwitch.serialNumber ?? '', this.latchingSwitch.deviceName ?? '', undefined, 'hub');
846
+ if (this.validateDevice(this.latchingSwitch.deviceName ?? '')) {
847
+ await this.registerDevice(this.latchingSwitch);
848
+ this.bridgedDevices.set(this.latchingSwitch.deviceName ?? '', this.latchingSwitch);
849
+ }
850
+ else {
851
+ this.latchingSwitch = undefined;
852
+ }
662
853
  }
663
854
  async onConfigure() {
664
855
  await super.onConfigure();
@@ -877,32 +1068,38 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
877
1068
  }
878
1069
  }, 60 * 1000 + 1000);
879
1070
  }
880
- await this.smoke?.setAttribute(SmokeCoAlarm.Cluster.id, 'smokeState', SmokeCoAlarm.AlarmState.Normal, this.smoke.log);
881
- await this.smoke?.setAttribute(SmokeCoAlarm.Cluster.id, 'coState', SmokeCoAlarm.AlarmState.Normal, this.smoke.log);
1071
+ await this.smokeCo?.setAttribute(SmokeCoAlarm.Cluster.id, 'smokeState', SmokeCoAlarm.AlarmState.Normal, this.smokeCo.log);
1072
+ await this.smokeCo?.setAttribute(SmokeCoAlarm.Cluster.id, 'coState', SmokeCoAlarm.AlarmState.Normal, this.smokeCo.log);
1073
+ await this.smokeOnly?.setAttribute(SmokeCoAlarm.Cluster.id, 'smokeState', SmokeCoAlarm.AlarmState.Normal, this.smokeOnly.log);
1074
+ await this.coOnly?.setAttribute(SmokeCoAlarm.Cluster.id, 'coState', SmokeCoAlarm.AlarmState.Normal, this.coOnly.log);
882
1075
  if (this.config.useInterval) {
883
1076
  this.smokeInterval = setInterval(async () => {
884
- let value = this.smoke?.getAttribute(SmokeCoAlarm.Cluster.id, 'smokeState', this.smoke.log);
1077
+ let value = this.smokeCo?.getAttribute(SmokeCoAlarm.Cluster.id, 'smokeState', this.smokeCo.log);
885
1078
  if (isValidNumber(value, SmokeCoAlarm.AlarmState.Normal, SmokeCoAlarm.AlarmState.Critical)) {
886
1079
  value = value === SmokeCoAlarm.AlarmState.Normal ? SmokeCoAlarm.AlarmState.Critical : SmokeCoAlarm.AlarmState.Normal;
887
- await this.smoke?.setAttribute(SmokeCoAlarm.Cluster.id, 'smokeState', value, this.smoke.log);
888
- await this.smoke?.setAttribute(SmokeCoAlarm.Cluster.id, 'coState', value, this.smoke.log);
889
- this.smoke?.log.info(`Set smoke smokeState and coState to ${value}`);
1080
+ await this.smokeCo?.setAttribute(SmokeCoAlarm.Cluster.id, 'smokeState', value, this.smokeCo.log);
1081
+ await this.smokeCo?.setAttribute(SmokeCoAlarm.Cluster.id, 'coState', value, this.smokeCo.log);
1082
+ await this.smokeOnly?.setAttribute(SmokeCoAlarm.Cluster.id, 'smokeState', value, this.smokeOnly.log);
1083
+ await this.coOnly?.setAttribute(SmokeCoAlarm.Cluster.id, 'coState', value, this.coOnly.log);
1084
+ this.smokeCo?.log.info(`Set smoke smokeState and coState to ${value}`);
890
1085
  }
891
1086
  }, 60 * 1000 + 1100);
892
1087
  }
893
1088
  await this.airQuality?.setAttribute(AirQuality.Cluster.id, 'airQuality', AirQuality.AirQualityEnum.Good, this.airQuality.log);
894
1089
  await this.airQuality?.setAttribute(TemperatureMeasurement.Cluster.id, 'measuredValue', 2150, this.airQuality.log);
895
1090
  await this.airQuality?.setAttribute(RelativeHumidityMeasurement.Cluster.id, 'measuredValue', 5500, this.airQuality.log);
896
- await this.airQuality?.setAttribute(CarbonMonoxideConcentrationMeasurement.Cluster.id, 'measuredValue', 10, this.airQuality.log);
897
- await this.airQuality?.setAttribute(CarbonDioxideConcentrationMeasurement.Cluster.id, 'measuredValue', 400, this.airQuality.log);
898
- await this.airQuality?.setAttribute(NitrogenDioxideConcentrationMeasurement.Cluster.id, 'measuredValue', 1, this.airQuality.log);
899
- await this.airQuality?.setAttribute(OzoneConcentrationMeasurement.Cluster.id, 'measuredValue', 1, this.airQuality.log);
900
- await this.airQuality?.setAttribute(FormaldehydeConcentrationMeasurement.Cluster.id, 'measuredValue', 1, this.airQuality.log);
901
- await this.airQuality?.setAttribute(Pm1ConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
902
- await this.airQuality?.setAttribute(Pm25ConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
903
- await this.airQuality?.setAttribute(Pm10ConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
904
- await this.airQuality?.setAttribute(RadonConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
905
- await this.airQuality?.setAttribute(TotalVolatileOrganicCompoundsConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
1091
+ if (this.config.enableConcentrationMeasurements === true) {
1092
+ await this.airQuality?.setAttribute(CarbonMonoxideConcentrationMeasurement.Cluster.id, 'measuredValue', 10, this.airQuality.log);
1093
+ await this.airQuality?.setAttribute(CarbonDioxideConcentrationMeasurement.Cluster.id, 'measuredValue', 400, this.airQuality.log);
1094
+ await this.airQuality?.setAttribute(NitrogenDioxideConcentrationMeasurement.Cluster.id, 'measuredValue', 1, this.airQuality.log);
1095
+ await this.airQuality?.setAttribute(OzoneConcentrationMeasurement.Cluster.id, 'measuredValue', 1, this.airQuality.log);
1096
+ await this.airQuality?.setAttribute(FormaldehydeConcentrationMeasurement.Cluster.id, 'measuredValue', 1, this.airQuality.log);
1097
+ await this.airQuality?.setAttribute(Pm1ConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
1098
+ await this.airQuality?.setAttribute(Pm25ConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
1099
+ await this.airQuality?.setAttribute(Pm10ConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
1100
+ await this.airQuality?.setAttribute(RadonConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
1101
+ await this.airQuality?.setAttribute(TotalVolatileOrganicCompoundsConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
1102
+ }
906
1103
  if (this.config.useInterval) {
907
1104
  this.airQualityInterval = setInterval(async () => {
908
1105
  let value = this.airQuality?.getAttribute(AirQuality.Cluster.id, 'airQuality', this.airQuality?.log);