matterbridge-example-dynamic-platform 1.1.8 → 1.2.0-edge.3

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