matterbridge-example-dynamic-platform 1.0.24 → 1.1.1-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/platform.js CHANGED
@@ -1,4 +1,4 @@
1
- import { AirQuality, AirQualityCluster, BooleanStateCluster, BooleanStateConfiguration, CarbonDioxideConcentrationMeasurement, CarbonMonoxideConcentrationMeasurement, ColorControl, ColorControlCluster, DeviceTypes, DoorLock, DoorLockCluster, FanControl, FanControlCluster, FlowMeasurement, FlowMeasurementCluster, FormaldehydeConcentrationMeasurement, LevelControlCluster, NitrogenDioxideConcentrationMeasurement, OnOffCluster, OzoneConcentrationMeasurement, Pm10ConcentrationMeasurement, Pm1ConcentrationMeasurement, Pm25ConcentrationMeasurement, RadonConcentrationMeasurement, RelativeHumidityMeasurement, RelativeHumidityMeasurementCluster, SmokeCoAlarm, SmokeCoAlarmCluster, TemperatureMeasurement, TemperatureMeasurementCluster, Thermostat, ThermostatCluster, TotalVolatileOrganicCompoundsConcentrationMeasurement, WindowCovering, WindowCoveringCluster, airQualitySensor, bridgedNode, onOffSwitch, powerSource, rainSensor, smokeCoAlarm, waterFreezeDetector, waterLeakDetector, } from 'matterbridge';
1
+ import { AirQuality, AirQualityCluster, BooleanStateCluster, BooleanStateConfiguration, CarbonDioxideConcentrationMeasurement, CarbonMonoxideConcentrationMeasurement, ColorControl, ColorControlCluster, DeviceTypes, DoorLock, DoorLockCluster, FanControl, FanControlCluster, FlowMeasurement, FlowMeasurementCluster, FormaldehydeConcentrationMeasurement, LevelControlCluster, MatterbridgeEndpoint, NitrogenDioxideConcentrationMeasurement, OnOffCluster, OzoneConcentrationMeasurement, Pm10ConcentrationMeasurement, Pm1ConcentrationMeasurement, Pm25ConcentrationMeasurement, RadonConcentrationMeasurement, RelativeHumidityMeasurement, RelativeHumidityMeasurementCluster, SmokeCoAlarm, SmokeCoAlarmCluster, TemperatureMeasurement, TemperatureMeasurementCluster, Thermostat, ThermostatCluster, TotalVolatileOrganicCompoundsConcentrationMeasurement, WindowCovering, WindowCoveringCluster, airConditioner, airQualitySensor, bridgedNode, onOffSwitch, powerSource, rainSensor, smokeCoAlarm, waterFreezeDetector, waterLeakDetector, } from 'matterbridge';
2
2
  import { /* MatterbridgeEndpoint as */ MatterbridgeDevice, MatterbridgeDynamicPlatform } from 'matterbridge';
3
3
  import { isValidBoolean, isValidNumber } from 'matterbridge/utils';
4
4
  export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatform {
@@ -19,6 +19,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
19
19
  rain;
20
20
  smoke;
21
21
  airQuality;
22
+ airConditioner;
22
23
  switchInterval;
23
24
  lightInterval;
24
25
  outletInterval;
@@ -31,300 +32,319 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
31
32
  rainInterval;
32
33
  smokeInterval;
33
34
  airQualityInterval;
35
+ airConditionerInterval;
36
+ bridgedDevices = new Map();
37
+ async createMutableDevice(definition, options = {}, debug = false) {
38
+ let device;
39
+ if (this.matterbridge.edge === true)
40
+ device = new MatterbridgeEndpoint(definition, options, debug);
41
+ else
42
+ device = new MatterbridgeDevice(definition, options, debug);
43
+ return device;
44
+ }
34
45
  constructor(matterbridge, log, config) {
35
46
  super(matterbridge, log, config);
36
47
  // Verify that Matterbridge is the correct version
37
- if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('1.6.0')) {
38
- throw new Error(`This plugin requires Matterbridge version >= "1.6.0". Please update Matterbridge from ${this.matterbridge.matterbridgeVersion} to the latest version in the frontend."`);
48
+ if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('1.6.6')) {
49
+ throw new Error(`This plugin requires Matterbridge version >= "1.6.6". Please update Matterbridge from ${this.matterbridge.matterbridgeVersion} to the latest version in the frontend.`);
39
50
  }
40
51
  this.log.info('Initializing platform:', this.config.name);
41
52
  }
42
53
  async onStart(reason) {
43
54
  this.log.info('onStart called with reason:', reason ?? 'none');
44
55
  // Create a switch device
45
- this.switch = new MatterbridgeDevice([onOffSwitch, bridgedNode], { uniqueStorageKey: 'Switch' }, this.config.debug);
56
+ this.switch = await this.createMutableDevice([onOffSwitch, bridgedNode], { uniqueStorageKey: 'Switch' }, this.config.debug);
46
57
  this.switch.log.logName = 'Switch';
47
58
  this.switch.createDefaultIdentifyClusterServer();
48
59
  this.switch.createDefaultGroupsClusterServer();
49
60
  this.switch.createDefaultScenesClusterServer();
50
- this.switch.createDefaultBridgedDeviceBasicInformationClusterServer('Switch', '0x23452164', 0xfff1, 'Luligu', 'Matterbridge Switch');
61
+ this.switch.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);
51
62
  this.switch.createDefaultOnOffClusterServer();
52
63
  this.switch.addDeviceType(powerSource);
53
64
  this.switch.createDefaultPowerSourceRechargeableBatteryClusterServer(70);
54
65
  await this.registerDevice(this.switch);
66
+ this.bridgedDevices.set(this.switch.deviceName ?? '', this.switch);
55
67
  this.switch.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
56
68
  this.log.info(`Command identify called identifyTime:${identifyTime}`);
57
69
  });
58
70
  this.switch.addCommandHandler('on', async () => {
59
- this.switch?.setAttribute(OnOffCluster.id, 'onOff', true, this.switch.log, this.switch);
71
+ await this.switch?.setAttribute(OnOffCluster.id, 'onOff', true, this.switch.log, this.switch);
60
72
  this.switch?.log.info('Command on called');
61
73
  });
62
74
  this.switch.addCommandHandler('off', async () => {
63
- this.switch?.setAttribute(OnOffCluster.id, 'onOff', false, this.switch.log, this.switch);
75
+ await this.switch?.setAttribute(OnOffCluster.id, 'onOff', false, this.switch.log, this.switch);
64
76
  this.switch?.log.info('Command off called');
65
77
  });
66
78
  // Create a on off light device
67
- this.lightOnOff = new MatterbridgeDevice([DeviceTypes.ON_OFF_LIGHT, bridgedNode], { uniqueStorageKey: 'Light (on/off)' }, this.config.debug);
79
+ this.lightOnOff = await this.createMutableDevice([DeviceTypes.ON_OFF_LIGHT, bridgedNode], { uniqueStorageKey: 'Light (on/off)' }, this.config.debug);
68
80
  this.lightOnOff.log.logName = 'Light (on/off)';
69
81
  this.lightOnOff.createDefaultIdentifyClusterServer();
70
82
  this.lightOnOff.createDefaultGroupsClusterServer();
71
83
  this.lightOnOff.createDefaultScenesClusterServer();
72
- this.lightOnOff.createDefaultBridgedDeviceBasicInformationClusterServer('Light (on/off)', '0x2342375564', 0xfff1, 'Luligu', 'Matterbridge Light on/off');
84
+ this.lightOnOff.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);
73
85
  this.lightOnOff.createDefaultOnOffClusterServer();
74
86
  this.lightOnOff.addDeviceType(powerSource);
75
87
  this.lightOnOff.createDefaultPowerSourceWiredClusterServer();
76
88
  await this.registerDevice(this.lightOnOff);
89
+ this.bridgedDevices.set(this.lightOnOff.deviceName ?? '', this.lightOnOff);
77
90
  this.lightOnOff.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
78
91
  this.lightOnOff?.log.info(`Command identify called identifyTime:${identifyTime}`);
79
92
  });
80
93
  this.lightOnOff.addCommandHandler('on', async () => {
81
- this.light?.setAttribute(OnOffCluster.id, 'onOff', true, this.lightOnOff?.log, this.lightOnOff);
94
+ await this.light?.setAttribute(OnOffCluster.id, 'onOff', true, this.lightOnOff?.log, this.lightOnOff);
82
95
  this.lightOnOff?.log.info('Command on called');
83
96
  });
84
97
  this.lightOnOff.addCommandHandler('off', async () => {
85
- this.light?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightOnOff?.log, this.lightOnOff);
98
+ await this.light?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightOnOff?.log, this.lightOnOff);
86
99
  this.lightOnOff?.log.info('Command off called');
87
100
  });
88
101
  // Create a dimmer device
89
- this.dimmer = new MatterbridgeDevice([DeviceTypes.DIMMABLE_LIGHT, bridgedNode], { uniqueStorageKey: 'Dimmer' }, this.config.debug);
102
+ this.dimmer = await this.createMutableDevice([DeviceTypes.DIMMABLE_LIGHT, bridgedNode], { uniqueStorageKey: 'Dimmer' }, this.config.debug);
90
103
  this.dimmer.log.logName = 'Dimmer';
91
104
  this.dimmer.createDefaultIdentifyClusterServer();
92
105
  this.dimmer.createDefaultGroupsClusterServer();
93
106
  this.dimmer.createDefaultScenesClusterServer();
94
- this.dimmer.createDefaultBridgedDeviceBasicInformationClusterServer('Dimmer', '0x234554564', 0xfff1, 'Luligu', 'Matterbridge Dimmer');
107
+ this.dimmer.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);
95
108
  this.dimmer.createDefaultOnOffClusterServer();
96
109
  this.dimmer.createDefaultLevelControlClusterServer();
97
110
  this.dimmer.addDeviceType(powerSource);
98
111
  this.dimmer.createDefaultPowerSourceReplaceableBatteryClusterServer(70);
99
112
  await this.registerDevice(this.dimmer);
113
+ this.bridgedDevices.set(this.dimmer.deviceName ?? '', this.dimmer);
100
114
  this.dimmer.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
101
115
  this.dimmer?.log.info(`Command identify called identifyTime:${identifyTime}`);
102
116
  });
103
117
  this.dimmer.addCommandHandler('on', async () => {
104
- this.dimmer?.setAttribute(OnOffCluster.id, 'onOff', true, this.dimmer.log, this.dimmer);
118
+ await this.dimmer?.setAttribute(OnOffCluster.id, 'onOff', true, this.dimmer.log, this.dimmer);
105
119
  this.dimmer?.log.info('Command on called');
106
120
  });
107
121
  this.dimmer.addCommandHandler('off', async () => {
108
- this.dimmer?.setAttribute(OnOffCluster.id, 'onOff', false, this.dimmer.log, this.dimmer);
122
+ await this.dimmer?.setAttribute(OnOffCluster.id, 'onOff', false, this.dimmer.log, this.dimmer);
109
123
  this.dimmer?.log.info('Command off called');
110
124
  });
111
125
  this.dimmer.addCommandHandler('moveToLevel', async ({ request: { level } }) => {
112
- this.dimmer?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.dimmer.log, this.dimmer);
126
+ await this.dimmer?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.dimmer.log, this.dimmer);
113
127
  this.dimmer?.log.debug(`Command moveToLevel called request: ${level}`);
114
128
  });
115
129
  this.dimmer.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level } }) => {
116
- this.dimmer?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.dimmer.log, this.dimmer);
130
+ await this.dimmer?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.dimmer.log, this.dimmer);
117
131
  this.dimmer?.log.debug(`Command moveToLevelWithOnOff called request: ${level}`);
118
132
  });
119
133
  // Create a light device
120
- this.light = new MatterbridgeDevice([DeviceTypes.COLOR_TEMPERATURE_LIGHT, bridgedNode], { uniqueStorageKey: 'Light (XY, HS and CT)' }, this.config.debug);
134
+ this.light = await this.createMutableDevice([DeviceTypes.COLOR_TEMPERATURE_LIGHT, bridgedNode], { uniqueStorageKey: 'Light (XY, HS and CT)' }, this.config.debug);
121
135
  this.light.log.logName = 'Light (XY, HS and CT)';
122
136
  this.light.createDefaultIdentifyClusterServer();
123
137
  this.light.createDefaultGroupsClusterServer();
124
138
  this.light.createDefaultScenesClusterServer();
125
- this.light.createDefaultBridgedDeviceBasicInformationClusterServer('Light (XY, HS and CT)', '0x23480564', 0xfff1, 'Luligu', 'Matterbridge Light');
139
+ this.light.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);
126
140
  this.light.createDefaultOnOffClusterServer();
127
141
  this.light.createDefaultLevelControlClusterServer();
128
142
  this.light.createDefaultColorControlClusterServer();
129
143
  this.light.addDeviceType(powerSource);
130
144
  this.light.createDefaultPowerSourceReplaceableBatteryClusterServer(70);
131
145
  await this.registerDevice(this.light);
146
+ this.bridgedDevices.set(this.light.deviceName ?? '', this.light);
132
147
  this.light.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
133
148
  this.light?.log.info(`Command identify called identifyTime:${identifyTime}`);
134
149
  });
135
150
  this.light.addCommandHandler('on', async () => {
136
- this.light?.setAttribute(OnOffCluster.id, 'onOff', true, this.light?.log, this.light);
151
+ await this.light?.setAttribute(OnOffCluster.id, 'onOff', true, this.light?.log, this.light);
137
152
  this.light?.log.info('Command on called');
138
153
  });
139
154
  this.light.addCommandHandler('off', async () => {
140
- this.light?.setAttribute(OnOffCluster.id, 'onOff', false, this.light?.log, this.light);
155
+ await this.light?.setAttribute(OnOffCluster.id, 'onOff', false, this.light?.log, this.light);
141
156
  this.light?.log.info('Command off called');
142
157
  });
143
158
  this.light.addCommandHandler('moveToLevel', async ({ request: { level } }) => {
144
- this.light?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.light?.log, this.light);
159
+ await this.light?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.light?.log, this.light);
145
160
  this.light?.log.debug(`Command moveToLevel called request: ${level}`);
146
161
  });
147
162
  this.light.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level } }) => {
148
- this.light?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.light?.log, this.light);
163
+ await this.light?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.light?.log, this.light);
149
164
  this.light?.log.debug(`Command moveToLevelWithOnOff called request: ${level}`);
150
165
  });
151
166
  this.light.addCommandHandler('moveToColor', async ({ request: { colorX, colorY } }) => {
152
- this.light?.setAttribute(ColorControlCluster.id, 'currentX', colorX, this.light?.log, this.light);
153
- this.light?.setAttribute(ColorControlCluster.id, 'currentY', colorY, this.light?.log, this.light);
167
+ await this.light?.setAttribute(ColorControlCluster.id, 'currentX', colorX, this.light?.log, this.light);
168
+ await this.light?.setAttribute(ColorControlCluster.id, 'currentY', colorY, this.light?.log, this.light);
154
169
  this.light?.log.debug(`Command moveToColor called request: X ${colorX / 65536} Y ${colorY / 65536}`);
155
170
  });
156
171
  this.light.addCommandHandler('moveToHueAndSaturation', async ({ request: { hue, saturation }, attributes: { currentHue, currentSaturation } }) => {
157
- this.light?.setAttribute(ColorControlCluster.id, 'currentHue', hue, this.light?.log, this.light);
158
- this.light?.setAttribute(ColorControlCluster.id, 'currentSaturation', saturation, this.light?.log, this.light);
172
+ await this.light?.setAttribute(ColorControlCluster.id, 'currentHue', hue, this.light?.log, this.light);
173
+ await this.light?.setAttribute(ColorControlCluster.id, 'currentSaturation', saturation, this.light?.log, this.light);
159
174
  this.light?.log.debug(`Command moveToHueAndSaturation called request: hue ${hue} saturation ${saturation} attributes: hue ${currentHue?.getLocal()} saturation ${currentSaturation?.getLocal()}`);
160
175
  });
161
176
  this.light.addCommandHandler('moveToHue', async ({ request: { hue }, attributes: { currentHue, currentSaturation } }) => {
162
- this.light?.setAttribute(ColorControlCluster.id, 'currentHue', hue, this.light?.log, this.light);
177
+ await this.light?.setAttribute(ColorControlCluster.id, 'currentHue', hue, this.light?.log, this.light);
163
178
  this.light?.log.debug(`Command moveToHue called request: hue ${hue} attributes: hue ${currentHue?.getLocal()} saturation ${currentSaturation?.getLocal()}`);
164
179
  });
165
180
  this.light.addCommandHandler('moveToSaturation', async ({ request: { saturation }, attributes: { currentHue, currentSaturation } }) => {
166
- this.light?.setAttribute(ColorControlCluster.id, 'currentSaturation', saturation, this.light?.log, this.light);
181
+ await this.light?.setAttribute(ColorControlCluster.id, 'currentSaturation', saturation, this.light?.log, this.light);
167
182
  this.light?.log.debug(`Command moveToSaturation called request: saturation ${saturation} attributes: hue ${currentHue?.getLocal()} saturation ${currentSaturation?.getLocal()}`);
168
183
  });
169
184
  this.light.addCommandHandler('moveToColorTemperature', async ({ request, attributes }) => {
170
- this.light?.setAttribute(ColorControlCluster.id, 'colorTemperatureMireds', request.colorTemperatureMireds, this.light?.log, this.light);
185
+ await this.light?.setAttribute(ColorControlCluster.id, 'colorTemperatureMireds', request.colorTemperatureMireds, this.light?.log, this.light);
171
186
  this.light?.log.debug(`Command moveToColorTemperature called request: ${request.colorTemperatureMireds} attributes: ${attributes.colorTemperatureMireds?.getLocal()}`);
172
187
  });
173
188
  // Create a light device with HS color control
174
- this.lightHS = new MatterbridgeDevice([DeviceTypes.COLOR_TEMPERATURE_LIGHT, bridgedNode], { uniqueStorageKey: 'Light (HS)' }, this.config.debug);
189
+ this.lightHS = await this.createMutableDevice([DeviceTypes.COLOR_TEMPERATURE_LIGHT, bridgedNode], { uniqueStorageKey: 'Light (HS)' }, this.config.debug);
175
190
  this.lightHS.log.logName = 'Light (HS)';
176
191
  this.lightHS.createDefaultIdentifyClusterServer();
177
192
  this.lightHS.createDefaultGroupsClusterServer();
178
193
  this.lightHS.createDefaultScenesClusterServer();
179
- this.lightHS.createDefaultBridgedDeviceBasicInformationClusterServer('Light (HS)', '0x25097564', 0xfff1, 'Luligu', 'Matterbridge Light');
194
+ this.lightHS.createDefaultBridgedDeviceBasicInformationClusterServer('Light (HS)', '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);
180
195
  this.lightHS.createDefaultOnOffClusterServer();
181
196
  this.lightHS.createDefaultLevelControlClusterServer();
182
- this.lightHS.createDefaultColorControlClusterServer();
183
- this.lightHS.configureColorControlCluster(true, false, false, ColorControl.ColorMode.CurrentHueAndCurrentSaturation);
197
+ this.lightHS.createHsColorControlClusterServer();
198
+ // await this.lightHS.configureColorControlCluster(true, false, false, ColorControl.ColorMode.CurrentHueAndCurrentSaturation);
184
199
  this.lightHS.addDeviceType(powerSource);
185
200
  this.lightHS.createDefaultPowerSourceWiredClusterServer();
186
201
  await this.registerDevice(this.lightHS);
202
+ this.bridgedDevices.set(this.lightHS.deviceName ?? '', this.lightHS);
187
203
  this.lightHS.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
188
204
  this.lightHS?.log.info(`Command identify called identifyTime:${identifyTime}`);
189
205
  });
190
206
  this.lightHS.addCommandHandler('on', async () => {
191
- this.lightHS?.setAttribute(OnOffCluster.id, 'onOff', true, this.lightHS?.log, this.lightHS);
207
+ await this.lightHS?.setAttribute(OnOffCluster.id, 'onOff', true, this.lightHS?.log, this.lightHS);
192
208
  this.lightHS?.log.info('Command on called');
193
209
  });
194
210
  this.lightHS.addCommandHandler('off', async () => {
195
- this.lightHS?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightHS?.log, this.lightHS);
211
+ await this.lightHS?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightHS?.log, this.lightHS);
196
212
  this.lightHS?.log.info('Command off called');
197
213
  });
198
214
  this.lightHS.addCommandHandler('moveToLevel', async ({ request: { level }, attributes: { currentLevel } }) => {
199
- this.lightHS?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightHS?.log, this.lightHS);
215
+ await this.lightHS?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightHS?.log, this.lightHS);
200
216
  this.lightHS?.log.debug(`Command moveToLevel called request: ${level} attributes: ${currentLevel?.getLocal()}`);
201
217
  });
202
218
  this.lightHS.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level }, attributes: { currentLevel } }) => {
203
- this.lightHS?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightHS?.log, this.lightHS);
219
+ await this.lightHS?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightHS?.log, this.lightHS);
204
220
  this.lightHS?.log.debug(`Command moveToLevelWithOnOff called request: ${level} attributes: ${currentLevel?.getLocal()}`);
205
221
  });
206
222
  this.lightHS.addCommandHandler('moveToHueAndSaturation', async ({ request: { hue, saturation }, attributes: { currentHue, currentSaturation } }) => {
207
- this.lightHS?.setAttribute(ColorControlCluster.id, 'currentHue', hue, this.lightHS?.log, this.lightHS);
208
- this.lightHS?.setAttribute(ColorControlCluster.id, 'currentSaturation', saturation, this.lightHS?.log, this.lightHS);
223
+ await this.lightHS?.setAttribute(ColorControlCluster.id, 'currentHue', hue, this.lightHS?.log, this.lightHS);
224
+ await this.lightHS?.setAttribute(ColorControlCluster.id, 'currentSaturation', saturation, this.lightHS?.log, this.lightHS);
209
225
  this.lightHS?.log.debug(`Command moveToHueAndSaturation called request: hue ${hue} saturation ${saturation} attributes: hue ${currentHue?.getLocal()} saturation ${currentSaturation?.getLocal()}`);
210
226
  });
211
227
  this.lightHS.addCommandHandler('moveToHue', async ({ request: { hue }, attributes: { currentHue, currentSaturation } }) => {
212
- this.lightHS?.setAttribute(ColorControlCluster.id, 'currentHue', hue, this.lightHS?.log, this.lightHS);
228
+ await this.lightHS?.setAttribute(ColorControlCluster.id, 'currentHue', hue, this.lightHS?.log, this.lightHS);
213
229
  this.lightHS?.log.debug(`Command moveToHue called request: hue ${hue} attributes: hue ${currentHue?.getLocal()} saturation ${currentSaturation?.getLocal()}`);
214
230
  });
215
231
  this.lightHS.addCommandHandler('moveToSaturation', async ({ request: { saturation }, attributes: { currentHue, currentSaturation } }) => {
216
- this.lightHS?.setAttribute(ColorControlCluster.id, 'currentSaturation', saturation, this.lightHS?.log, this.lightHS);
232
+ await this.lightHS?.setAttribute(ColorControlCluster.id, 'currentSaturation', saturation, this.lightHS?.log, this.lightHS);
217
233
  this.lightHS?.log.debug(`Command moveToSaturation called request: saturation ${saturation} attributes: hue ${currentHue?.getLocal()} saturation ${currentSaturation?.getLocal()}`);
218
234
  });
219
235
  // Create a light device with XY color control
220
- this.lightXY = new MatterbridgeDevice([DeviceTypes.COLOR_TEMPERATURE_LIGHT, bridgedNode], { uniqueStorageKey: 'Light (XY)' }, this.config.debug);
236
+ this.lightXY = await this.createMutableDevice([DeviceTypes.COLOR_TEMPERATURE_LIGHT, bridgedNode], { uniqueStorageKey: 'Light (XY)' }, this.config.debug);
221
237
  this.lightXY.log.logName = 'Light (XY)';
222
238
  this.lightXY.createDefaultIdentifyClusterServer();
223
239
  this.lightXY.createDefaultGroupsClusterServer();
224
240
  this.lightXY.createDefaultScenesClusterServer();
225
- this.lightXY.createDefaultBridgedDeviceBasicInformationClusterServer('Light (XY)', '0x23497564', 0xfff1, 'Luligu', 'Matterbridge Light');
241
+ this.lightXY.createDefaultBridgedDeviceBasicInformationClusterServer('Light (XY)', '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);
226
242
  this.lightXY.createDefaultOnOffClusterServer();
227
243
  this.lightXY.createDefaultLevelControlClusterServer();
228
- this.lightXY.createDefaultColorControlClusterServer();
229
- this.lightXY.configureColorControlCluster(false, true, false, ColorControl.ColorMode.CurrentXAndCurrentY);
244
+ this.lightXY.createXyColorControlClusterServer();
245
+ // await this.lightXY.configureColorControlCluster(false, true, false, ColorControl.ColorMode.CurrentXAndCurrentY);
230
246
  this.lightXY.addDeviceType(powerSource);
231
247
  this.lightXY.createDefaultPowerSourceWiredClusterServer();
232
248
  await this.registerDevice(this.lightXY);
249
+ this.bridgedDevices.set(this.lightXY.deviceName ?? '', this.lightXY);
233
250
  this.lightXY.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
234
251
  this.lightXY?.log.info(`Command identify called identifyTime:${identifyTime}`);
235
252
  });
236
253
  this.lightXY.addCommandHandler('on', async () => {
237
- this.lightXY?.setAttribute(OnOffCluster.id, 'onOff', true, this.lightXY?.log, this.lightXY);
254
+ await this.lightXY?.setAttribute(OnOffCluster.id, 'onOff', true, this.lightXY?.log, this.lightXY);
238
255
  this.lightXY?.log.info('Command on called');
239
256
  });
240
257
  this.lightXY.addCommandHandler('off', async () => {
241
- this.lightXY?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightXY?.log, this.lightXY);
258
+ await this.lightXY?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightXY?.log, this.lightXY);
242
259
  this.lightXY?.log.info('Command off called');
243
260
  });
244
261
  this.lightXY.addCommandHandler('moveToLevel', async ({ request: { level } }) => {
245
- this.lightXY?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightXY?.log, this.lightXY);
262
+ await this.lightXY?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightXY?.log, this.lightXY);
246
263
  this.lightXY?.log.debug(`Command moveToLevel called request: ${level}`);
247
264
  });
248
265
  this.lightXY.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level } }) => {
249
- this.lightXY?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightXY?.log, this.lightXY);
266
+ await this.lightXY?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightXY?.log, this.lightXY);
250
267
  this.lightXY?.log.debug(`Command moveToLevelWithOnOff called request: ${level}`);
251
268
  });
252
269
  this.lightXY.addCommandHandler('moveToColor', async ({ request: { colorX, colorY } }) => {
253
- this.lightXY?.setAttribute(ColorControlCluster.id, 'currentX', colorX, this.light?.log, this.light);
254
- this.lightXY?.setAttribute(ColorControlCluster.id, 'currentY', colorY, this.light?.log, this.light);
270
+ await this.lightXY?.setAttribute(ColorControlCluster.id, 'currentX', colorX, this.light?.log, this.light);
271
+ await this.lightXY?.setAttribute(ColorControlCluster.id, 'currentY', colorY, this.light?.log, this.light);
255
272
  this.lightXY?.log.debug(`Command moveToColor called request: X ${colorX / 65536} Y ${colorY / 65536}`);
256
273
  });
257
274
  // Create a light device with CT color control
258
- this.lightCT = new MatterbridgeDevice([DeviceTypes.COLOR_TEMPERATURE_LIGHT, bridgedNode], { uniqueStorageKey: 'Light (CT)' }, this.config.debug);
275
+ this.lightCT = await this.createMutableDevice([DeviceTypes.COLOR_TEMPERATURE_LIGHT, bridgedNode], { uniqueStorageKey: 'Light (CT)' }, this.config.debug);
259
276
  this.lightCT.log.logName = 'Light (CT)';
260
277
  this.lightCT.createDefaultIdentifyClusterServer();
261
278
  this.lightCT.createDefaultGroupsClusterServer();
262
279
  this.lightCT.createDefaultScenesClusterServer();
263
- this.lightCT.createDefaultBridgedDeviceBasicInformationClusterServer('Light (CT)', '0x23480749', 0xfff1, 'Luligu', 'Matterbridge Light');
280
+ this.lightCT.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);
264
281
  this.lightCT.createDefaultOnOffClusterServer();
265
282
  this.lightCT.createDefaultLevelControlClusterServer();
266
- this.lightCT.createDefaultColorControlClusterServer();
267
- this.lightCT.configureColorControlCluster(false, false, true, ColorControl.ColorMode.ColorTemperatureMireds);
283
+ this.lightCT.createCtColorControlClusterServer();
284
+ // await this.lightCT.configureColorControlCluster(false, false, true, ColorControl.ColorMode.ColorTemperatureMireds);
268
285
  this.lightCT.addDeviceType(powerSource);
269
286
  this.lightCT.createDefaultPowerSourceReplaceableBatteryClusterServer(70);
270
287
  await this.registerDevice(this.lightCT);
288
+ this.bridgedDevices.set(this.lightCT.deviceName ?? '', this.lightCT);
271
289
  this.lightCT.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
272
290
  this.lightCT?.log.info(`Command identify called identifyTime:${identifyTime}`);
273
291
  });
274
292
  this.lightCT.addCommandHandler('on', async () => {
275
- this.lightCT?.setAttribute(OnOffCluster.id, 'onOff', true, this.lightCT?.log, this.lightCT);
293
+ await this.lightCT?.setAttribute(OnOffCluster.id, 'onOff', true, this.lightCT?.log, this.lightCT);
276
294
  this.lightCT?.log.info('Command on called');
277
295
  });
278
296
  this.lightCT.addCommandHandler('off', async () => {
279
- this.lightCT?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightCT?.log, this.lightCT);
297
+ await this.lightCT?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightCT?.log, this.lightCT);
280
298
  this.lightCT?.log.info('Command off called');
281
299
  });
282
300
  this.lightCT.addCommandHandler('moveToLevel', async ({ request: { level } }) => {
283
- this.lightCT?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightCT?.log, this.lightCT);
301
+ await this.lightCT?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightCT?.log, this.lightCT);
284
302
  this.lightCT?.log.debug(`Command moveToLevel called request: ${level}`);
285
303
  });
286
304
  this.lightCT.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level } }) => {
287
- this.lightCT?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightCT?.log, this.lightCT);
305
+ await this.lightCT?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightCT?.log, this.lightCT);
288
306
  this.lightCT?.log.debug(`Command moveToLevelWithOnOff called request: ${level}`);
289
307
  });
290
308
  this.lightCT.addCommandHandler('moveToColorTemperature', async ({ request }) => {
291
- this.lightCT?.setAttribute(ColorControlCluster.id, 'colorTemperatureMireds', request.colorTemperatureMireds, this.lightCT?.log, this.lightCT);
309
+ await this.lightCT?.setAttribute(ColorControlCluster.id, 'colorTemperatureMireds', request.colorTemperatureMireds, this.lightCT?.log, this.lightCT);
292
310
  this.lightCT?.log.debug(`Command moveToColorTemperature called request: ${request.colorTemperatureMireds}`);
293
311
  });
294
312
  // Create an outlet device
295
- this.outlet = new MatterbridgeDevice([DeviceTypes.ON_OFF_PLUGIN_UNIT, bridgedNode], { uniqueStorageKey: 'Outlet' }, this.config.debug);
313
+ this.outlet = await this.createMutableDevice([DeviceTypes.ON_OFF_PLUGIN_UNIT, bridgedNode], { uniqueStorageKey: 'Outlet' }, this.config.debug);
296
314
  this.outlet.log.logName = 'Outlet';
297
315
  this.outlet.createDefaultIdentifyClusterServer();
298
316
  this.outlet.createDefaultGroupsClusterServer();
299
317
  this.outlet.createDefaultScenesClusterServer();
300
- this.outlet.createDefaultBridgedDeviceBasicInformationClusterServer('Outlet', '0x29252164', 0xfff1, 'Luligu', 'Matterbridge Outlet');
318
+ this.outlet.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);
301
319
  this.outlet.createDefaultOnOffClusterServer();
302
320
  this.outlet.addDeviceType(powerSource);
303
321
  this.outlet.createDefaultPowerSourceWiredClusterServer();
304
322
  await this.registerDevice(this.outlet);
323
+ this.bridgedDevices.set(this.outlet.deviceName ?? '', this.outlet);
305
324
  this.outlet.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
306
325
  this.outlet?.log.info(`Command identify called identifyTime:${identifyTime}`);
307
326
  });
308
327
  this.outlet.addCommandHandler('on', async () => {
309
- this.outlet?.setAttribute(OnOffCluster.id, 'onOff', true, this.outlet?.log, this.outlet);
328
+ await this.outlet?.setAttribute(OnOffCluster.id, 'onOff', true, this.outlet?.log, this.outlet);
310
329
  this.outlet?.log.info('Command on called');
311
330
  });
312
331
  this.outlet.addCommandHandler('off', async () => {
313
- this.outlet?.setAttribute(OnOffCluster.id, 'onOff', false, this.outlet?.log, this.outlet);
332
+ await this.outlet?.setAttribute(OnOffCluster.id, 'onOff', false, this.outlet?.log, this.outlet);
314
333
  this.outlet?.log.info('Command off called');
315
334
  });
316
335
  // Create a window covering device
317
336
  // Matter uses 10000 = fully closed 0 = fully opened
318
- this.cover = new MatterbridgeDevice([DeviceTypes.WINDOW_COVERING, bridgedNode], { uniqueStorageKey: 'Cover' }, this.config.debug);
337
+ this.cover = await this.createMutableDevice([DeviceTypes.WINDOW_COVERING, bridgedNode], { uniqueStorageKey: 'Cover' }, this.config.debug);
319
338
  this.cover.log.logName = 'Cover';
320
339
  this.cover.createDefaultIdentifyClusterServer();
321
340
  this.cover.createDefaultGroupsClusterServer();
322
341
  this.cover.createDefaultScenesClusterServer();
323
- this.cover.createDefaultBridgedDeviceBasicInformationClusterServer('Cover', '0x01020564', 0xfff1, 'Luligu', 'Matterbridge Cover');
342
+ 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);
324
343
  this.cover.createDefaultWindowCoveringClusterServer();
325
344
  this.cover.addDeviceType(powerSource);
326
345
  this.cover.createDefaultPowerSourceRechargeableBatteryClusterServer(86);
327
346
  await this.registerDevice(this.cover);
347
+ this.bridgedDevices.set(this.cover.deviceName ?? '', this.cover);
328
348
  this.cover.subscribeAttribute(WindowCoveringCluster.id, 'mode', (newValue, oldValue) => {
329
349
  this.cover?.log.info(`Attribute mode changed from ${oldValue} to ${newValue}. Reverse: ${newValue.motorDirectionReversed}. Calibration: ${newValue.calibrationMode}. Maintenance: ${newValue.maintenanceMode}. LED: ${newValue.ledFeedback}`);
330
350
  }, this.cover.log);
@@ -332,48 +352,49 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
332
352
  this.cover?.log.info(`Command identify called identifyTime:${identifyTime}`);
333
353
  });
334
354
  this.cover.addCommandHandler('stopMotion', async () => {
335
- this.cover?.setWindowCoveringTargetAsCurrentAndStopped();
355
+ await this.cover?.setWindowCoveringTargetAsCurrentAndStopped();
336
356
  this.cover?.log.info(`Command stopMotion called`);
337
357
  });
338
358
  this.cover.addCommandHandler('downOrClose', async () => {
339
- this.cover?.setWindowCoveringCurrentTargetStatus(10000, 10000, WindowCovering.MovementStatus.Stopped);
359
+ await this.cover?.setWindowCoveringCurrentTargetStatus(10000, 10000, WindowCovering.MovementStatus.Stopped);
340
360
  this.cover?.log.info(`Command downOrClose called`);
341
361
  });
342
362
  this.cover.addCommandHandler('upOrOpen', async () => {
343
- this.cover?.setWindowCoveringCurrentTargetStatus(0, 0, WindowCovering.MovementStatus.Stopped);
363
+ await this.cover?.setWindowCoveringCurrentTargetStatus(0, 0, WindowCovering.MovementStatus.Stopped);
344
364
  this.cover?.log.info(`Command upOrOpen called`);
345
365
  });
346
366
  this.cover.addCommandHandler('goToLiftPercentage', async ({ request: { liftPercent100thsValue } }) => {
347
- this.cover?.setWindowCoveringCurrentTargetStatus(liftPercent100thsValue, liftPercent100thsValue, WindowCovering.MovementStatus.Stopped);
367
+ await this.cover?.setWindowCoveringCurrentTargetStatus(liftPercent100thsValue, liftPercent100thsValue, WindowCovering.MovementStatus.Stopped);
348
368
  this.cover?.log.info(`Command goToLiftPercentage ${liftPercent100thsValue} called`);
349
369
  });
350
370
  // Create a lock device
351
- this.lock = new MatterbridgeDevice([DeviceTypes.DOOR_LOCK, bridgedNode], { uniqueStorageKey: 'Lock' }, this.config.debug);
371
+ this.lock = await this.createMutableDevice([DeviceTypes.DOOR_LOCK, bridgedNode], { uniqueStorageKey: 'Lock' }, this.config.debug);
352
372
  this.lock.log.logName = 'Lock';
353
373
  this.lock.createDefaultIdentifyClusterServer();
354
- this.lock.createDefaultBridgedDeviceBasicInformationClusterServer('Lock', '0x96352164', 0xfff1, 'Luligu', 'Matterbridge Lock');
374
+ this.lock.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);
355
375
  this.lock.createDefaultDoorLockClusterServer();
356
376
  this.lock.addDeviceType(powerSource);
357
377
  this.lock.createDefaultPowerSourceRechargeableBatteryClusterServer(30);
358
378
  await this.registerDevice(this.lock);
379
+ this.bridgedDevices.set(this.lock.deviceName ?? '', this.lock);
359
380
  this.lock.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
360
381
  this.lock?.log.info(`Command identify called identifyTime:${identifyTime}`);
361
382
  });
362
383
  this.lock.addCommandHandler('lockDoor', async () => {
363
- this.lock?.setAttribute(DoorLockCluster.id, 'lockState', DoorLock.LockState.Locked, this.lock?.log, this.lock);
384
+ await this.lock?.setAttribute(DoorLockCluster.id, 'lockState', DoorLock.LockState.Locked, this.lock?.log, this.lock);
364
385
  this.lock?.log.info('Command lockDoor called');
365
386
  });
366
387
  this.lock.addCommandHandler('unlockDoor', async () => {
367
- this.lock?.setAttribute(DoorLockCluster.id, 'lockState', DoorLock.LockState.Unlocked, this.lock?.log, this.lock);
388
+ await this.lock?.setAttribute(DoorLockCluster.id, 'lockState', DoorLock.LockState.Unlocked, this.lock?.log, this.lock);
368
389
  this.lock?.log.info('Command unlockDoor called');
369
390
  });
370
391
  // Create a thermostat device
371
- this.thermo = new MatterbridgeDevice([DeviceTypes.THERMOSTAT, bridgedNode], { uniqueStorageKey: 'Thermostat' }, this.config.debug);
392
+ this.thermo = await this.createMutableDevice([DeviceTypes.THERMOSTAT, bridgedNode], { uniqueStorageKey: 'Thermostat' }, this.config.debug);
372
393
  this.thermo.log.logName = 'Thermostat';
373
394
  this.thermo.createDefaultIdentifyClusterServer();
374
395
  this.thermo.createDefaultGroupsClusterServer();
375
396
  this.thermo.createDefaultScenesClusterServer();
376
- this.thermo.createDefaultBridgedDeviceBasicInformationClusterServer('Thermostat', '0x96382164', 0xfff1, 'Luligu', 'Matterbridge Thermostat');
397
+ this.thermo.createDefaultBridgedDeviceBasicInformationClusterServer('Thermostat', '0x96382164', 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);
377
398
  this.thermo.createDefaultThermostatClusterServer(20, 18, 22);
378
399
  this.thermo.addDeviceType(powerSource);
379
400
  this.thermo.createDefaultPowerSourceRechargeableBatteryClusterServer(70);
@@ -384,6 +405,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
384
405
  const humidityChild = this.thermo.addChildDeviceTypeWithClusterServer('Humidity', [DeviceTypes.HUMIDITY_SENSOR], [RelativeHumidityMeasurement.Cluster.id]);
385
406
  humidityChild.getClusterServer(RelativeHumidityMeasurement.Cluster)?.setMeasuredValueAttribute(80 * 100);
386
407
  await this.registerDevice(this.thermo);
408
+ this.bridgedDevices.set(this.thermo.deviceName ?? '', this.thermo);
387
409
  this.thermo.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
388
410
  this.thermo?.log.info(`Command identify called identifyTime:${identifyTime}`);
389
411
  });
@@ -392,12 +414,12 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
392
414
  this.thermo?.log.info(`Command setpointRaiseLower called with mode: ${lookupSetpointAdjustMode[mode]} amount: ${amount / 10}`);
393
415
  if (mode === Thermostat.SetpointRaiseLowerMode.Heat || mode === Thermostat.SetpointRaiseLowerMode.Both) {
394
416
  const setpoint = this.thermo?.getAttribute(ThermostatCluster.id, 'occupiedHeatingSetpoint', this.thermo?.log) / 100 + amount / 10;
395
- this.thermo?.setAttribute(ThermostatCluster.id, 'occupiedHeatingSetpoint', setpoint * 100, this.thermo?.log);
417
+ await this.thermo?.setAttribute(ThermostatCluster.id, 'occupiedHeatingSetpoint', setpoint * 100, this.thermo?.log);
396
418
  this.thermo?.log.info('Set occupiedHeatingSetpoint:', setpoint);
397
419
  }
398
420
  if (mode === Thermostat.SetpointRaiseLowerMode.Cool || mode === Thermostat.SetpointRaiseLowerMode.Both) {
399
421
  const setpoint = this.thermo?.getAttribute(ThermostatCluster.id, 'occupiedCoolingSetpoint', this.thermo?.log) / 100 + amount / 10;
400
- this.thermo?.setAttribute(ThermostatCluster.id, 'occupiedCoolingSetpoint', setpoint * 100, this.thermo?.log);
422
+ await this.thermo?.setAttribute(ThermostatCluster.id, 'occupiedCoolingSetpoint', setpoint * 100, this.thermo?.log);
401
423
  this.thermo?.log.info('Set occupiedCoolingSetpoint:', setpoint);
402
424
  }
403
425
  });
@@ -411,74 +433,103 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
411
433
  this.thermo.subscribeAttribute(ThermostatCluster.id, 'occupiedCoolingSetpoint', async (value) => {
412
434
  this.thermo?.log.info('Subscribe occupiedCoolingSetpoint called with:', value / 100);
413
435
  }, this.thermo.log, this.thermo);
436
+ // Create a airConditioning device
437
+ this.airConditioner = await this.createMutableDevice([airConditioner, bridgedNode], { uniqueStorageKey: 'Air conditioner' }, this.config.debug);
438
+ this.airConditioner.log.logName = 'Air conditioner';
439
+ this.airConditioner.createDefaultBridgedDeviceBasicInformationClusterServer('Air conditioner', '0x96382864', 0xfff1, 'Matterbridge', 'Matterbridge Air conditioner', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion);
440
+ this.airConditioner.createDefaultIdentifyClusterServer();
441
+ this.airConditioner.createDefaultOnOffClusterServer(true);
442
+ this.airConditioner.createDefaultThermostatClusterServer(20, 18, 22);
443
+ this.airConditioner.createDefaultFanControlClusterServer();
444
+ this.airConditioner.createDefaultTemperatureMeasurementClusterServer(20);
445
+ this.airConditioner.createDefaultRelativeHumidityMeasurementClusterServer(50);
446
+ this.airConditioner.addDeviceType(powerSource);
447
+ this.airConditioner.createDefaultPowerSourceWiredClusterServer();
448
+ await this.registerDevice(this.airConditioner);
449
+ this.bridgedDevices.set(this.airConditioner.deviceName ?? '', this.airConditioner);
450
+ this.airConditioner.addCommandHandler('identify', async ({ request: { identifyTime } }) => {
451
+ this.airConditioner?.log.info(`Command identify called identifyTime:${identifyTime}`);
452
+ });
453
+ this.airConditioner.addCommandHandler('on', async () => {
454
+ await this.airConditioner?.setAttribute(OnOffCluster.id, 'onOff', true, this.airConditioner?.log);
455
+ this.outlet?.log.info('Command on called');
456
+ });
457
+ this.airConditioner.addCommandHandler('off', async () => {
458
+ await this.airConditioner?.setAttribute(OnOffCluster.id, 'onOff', false, this.airConditioner?.log);
459
+ this.outlet?.log.info('Command off called');
460
+ });
414
461
  // Create a fan device
415
- this.fan = new MatterbridgeDevice([DeviceTypes.FAN, bridgedNode], { uniqueStorageKey: 'Fan' }, this.config.debug);
462
+ this.fan = await this.createMutableDevice([DeviceTypes.FAN, bridgedNode], { uniqueStorageKey: 'Fan' }, this.config.debug);
416
463
  this.fan.log.logName = 'Fan';
417
- this.fan.createDefaultBridgedDeviceBasicInformationClusterServer('Fan', 'serial_980545631228', 0xfff1, 'Luligu', 'Matterbridge Fan', 2, '2.1.1');
464
+ this.fan.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);
418
465
  this.fan.addDeviceTypeWithClusterServer([DeviceTypes.FAN], []);
419
466
  await this.registerDevice(this.fan);
467
+ this.bridgedDevices.set(this.fan.deviceName ?? '', this.fan);
420
468
  const fanModeLookup = ['Off', 'Low', 'Medium', 'High', 'On', 'Auto', 'Smart'];
421
- this.thermo.subscribeAttribute(FanControlCluster.id, 'fanMode', (newValue, oldValue) => {
469
+ this.fan.subscribeAttribute(FanControlCluster.id, 'fanMode', async (newValue, oldValue) => {
422
470
  this.fan?.log.info(`Fan mode changed from ${fanModeLookup[oldValue]} to ${fanModeLookup[newValue]}`);
423
471
  if (newValue === FanControl.FanMode.Off) {
424
- this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', 0, this.fan?.log);
472
+ await this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', 0, this.fan?.log);
425
473
  }
426
474
  else if (newValue === FanControl.FanMode.Low) {
427
- this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', 33, this.fan?.log);
475
+ await this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', 33, this.fan?.log);
428
476
  }
429
477
  else if (newValue === FanControl.FanMode.Medium) {
430
- this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', 66, this.fan?.log);
478
+ await this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', 66, this.fan?.log);
431
479
  }
432
480
  else if (newValue === FanControl.FanMode.High) {
433
- this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', 100, this.fan?.log);
481
+ await this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', 100, this.fan?.log);
434
482
  }
435
483
  else if (newValue === FanControl.FanMode.On) {
436
- this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', 100, this.fan?.log);
484
+ await this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', 100, this.fan?.log);
437
485
  }
438
486
  else if (newValue === FanControl.FanMode.Auto) {
439
- this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', 50, this.fan?.log);
487
+ await this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', 50, this.fan?.log);
440
488
  }
441
489
  }, this.fan.log, this.fan);
442
- this.thermo.subscribeAttribute(FanControlCluster.id, 'percentSetting', (newValue, oldValue) => {
490
+ this.fan.subscribeAttribute(FanControlCluster.id, 'percentSetting', async (newValue, oldValue) => {
443
491
  this.fan?.log.info(`Percent setting changed from ${oldValue} to ${newValue}`);
444
492
  if (isValidNumber(newValue, 0, 100))
445
- this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', newValue, this.fan?.log);
493
+ await this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', newValue, this.fan?.log);
446
494
  }, this.fan.log, this.fan);
447
- this.thermo.subscribeAttribute(FanControlCluster.id, 'speedSetting', (newValue, oldValue) => {
495
+ this.fan.subscribeAttribute(FanControlCluster.id, 'speedSetting', async (newValue, oldValue) => {
448
496
  this.fan?.log.info(`Speed setting changed from ${oldValue} to ${newValue}`);
449
497
  if (isValidNumber(newValue, 0, 100))
450
- this.fan?.setAttribute(FanControlCluster.id, 'speedCurrent', newValue, this.fan?.log);
498
+ await this.fan?.setAttribute(FanControlCluster.id, 'speedCurrent', newValue, this.fan?.log);
451
499
  }, this.fan.log, this.fan);
452
- this.waterLeak = new MatterbridgeDevice([waterLeakDetector, bridgedNode], { uniqueStorageKey: 'Water leak detector' }, this.config.debug);
500
+ this.waterLeak = await this.createMutableDevice([waterLeakDetector, bridgedNode], { uniqueStorageKey: 'Water leak detector' }, this.config.debug);
453
501
  this.waterLeak.log.logName = 'Water leak detector';
454
- this.waterLeak.createDefaultBridgedDeviceBasicInformationClusterServer('Water leak detector', 'serial_98745631222', 0xfff1, 'Luligu', 'Matterbridge WaterLeakDetector');
502
+ this.waterLeak.createDefaultBridgedDeviceBasicInformationClusterServer('Water leak detector', 'serial_98745631222', 0xfff1, 'Matterbridge', 'Matterbridge WaterLeakDetector', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion);
455
503
  this.waterLeak.addDeviceTypeWithClusterServer([waterLeakDetector], [BooleanStateConfiguration.Cluster.id]);
456
504
  await this.registerDevice(this.waterLeak);
457
- this.waterLeak.setAttribute(BooleanStateCluster.id, 'stateValue', false, this.waterLeak.log);
458
- this.waterFreeze = new MatterbridgeDevice([waterFreezeDetector, bridgedNode], { uniqueStorageKey: 'Water freeze detector' }, this.config.debug);
505
+ await this.waterLeak.setAttribute(BooleanStateCluster.id, 'stateValue', false, this.waterLeak.log);
506
+ this.waterFreeze = await this.createMutableDevice([waterFreezeDetector, bridgedNode], { uniqueStorageKey: 'Water freeze detector' }, this.config.debug);
459
507
  this.waterFreeze.log.logName = 'Water freeze detector';
460
- this.waterFreeze.createDefaultBridgedDeviceBasicInformationClusterServer('Water freeze detector', 'serial_98745631223', 0xfff1, 'Luligu', 'Matterbridge WaterFreezeDetector');
508
+ this.waterFreeze.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);
461
509
  this.waterFreeze.addDeviceTypeWithClusterServer([waterFreezeDetector], [BooleanStateConfiguration.Cluster.id]);
462
510
  await this.registerDevice(this.waterFreeze);
463
- this.waterFreeze.setAttribute(BooleanStateCluster.id, 'stateValue', false, this.waterFreeze.log);
464
- this.rain = new MatterbridgeDevice([rainSensor, bridgedNode], { uniqueStorageKey: 'Rain sensor' }, this.config.debug);
511
+ this.bridgedDevices.set(this.waterFreeze.deviceName ?? '', this.waterFreeze);
512
+ await this.waterFreeze.setAttribute(BooleanStateCluster.id, 'stateValue', false, this.waterFreeze.log);
513
+ this.rain = await this.createMutableDevice([rainSensor, bridgedNode], { uniqueStorageKey: 'Rain sensor' }, this.config.debug);
465
514
  this.rain.log.logName = 'Rain sensor';
466
- this.rain.createDefaultBridgedDeviceBasicInformationClusterServer('Rain sensor', 'serial_98745631224', 0xfff1, 'Luligu', 'Matterbridge RainSensor');
515
+ this.rain.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);
467
516
  this.rain.addDeviceTypeWithClusterServer([rainSensor], [BooleanStateConfiguration.Cluster.id]);
468
517
  await this.registerDevice(this.rain);
469
- this.rain.setAttribute(BooleanStateCluster.id, 'stateValue', false, this.rain.log);
470
- this.smoke = new MatterbridgeDevice([smokeCoAlarm, bridgedNode], { uniqueStorageKey: 'Smoke alarm sensor' }, this.config.debug);
518
+ this.bridgedDevices.set(this.rain.deviceName ?? '', this.rain);
519
+ await this.rain.setAttribute(BooleanStateCluster.id, 'stateValue', false, this.rain.log);
520
+ this.smoke = await this.createMutableDevice([smokeCoAlarm, bridgedNode], { uniqueStorageKey: 'Smoke alarm sensor' }, this.config.debug);
471
521
  this.smoke.log.logName = 'Smoke alarm sensor';
472
- this.smoke.createDefaultBridgedDeviceBasicInformationClusterServer('Smoke alarm sensor', 'serial_94745631225', 0xfff1, 'Luligu', 'Matterbridge SmokeCoAlarm');
522
+ this.smoke.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);
473
523
  this.smoke.addDeviceTypeWithClusterServer([smokeCoAlarm], [CarbonMonoxideConcentrationMeasurement.Cluster.id]);
474
524
  await this.registerDevice(this.smoke);
475
- this.smoke.setAttribute(SmokeCoAlarmCluster.id, 'smokeState', SmokeCoAlarm.AlarmState.Normal, this.smoke.log);
476
- this.smoke.setAttribute(SmokeCoAlarmCluster.id, 'coState', SmokeCoAlarm.AlarmState.Normal, this.smoke.log);
477
- this.smoke.setAttribute(CarbonMonoxideConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.smoke.log);
525
+ this.bridgedDevices.set(this.smoke.deviceName ?? '', this.smoke);
526
+ await this.smoke.setAttribute(SmokeCoAlarmCluster.id, 'smokeState', SmokeCoAlarm.AlarmState.Normal, this.smoke.log);
527
+ await this.smoke.setAttribute(SmokeCoAlarmCluster.id, 'coState', SmokeCoAlarm.AlarmState.Normal, this.smoke.log);
528
+ await this.smoke.setAttribute(CarbonMonoxideConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.smoke.log);
478
529
  // Create an airQuality device
479
- this.airQuality = new MatterbridgeDevice([airQualitySensor, bridgedNode], { uniqueStorageKey: 'Air quality sensor' }, this.config.debug);
530
+ this.airQuality = await this.createMutableDevice([airQualitySensor, bridgedNode], { uniqueStorageKey: 'Air quality sensor' }, this.config.debug);
480
531
  this.airQuality.log.logName = 'Air quality Sensor';
481
- this.airQuality.createDefaultBridgedDeviceBasicInformationClusterServer('Air quality sensor', 'serial_987484318322', 0xfff1, 'Luligu', 'Matterbridge Air Quality Sensor');
532
+ this.airQuality.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);
482
533
  this.airQuality.addDeviceTypeWithClusterServer([airQualitySensor], [
483
534
  TemperatureMeasurement.Cluster.id,
484
535
  RelativeHumidityMeasurement.Cluster.id,
@@ -494,236 +545,254 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
494
545
  TotalVolatileOrganicCompoundsConcentrationMeasurement.Cluster.id,
495
546
  ]);
496
547
  await this.registerDevice(this.airQuality);
497
- this.airQuality.setAttribute(AirQuality.Cluster.id, 'airQuality', AirQuality.AirQualityEnum.Good, this.airQuality.log);
498
- this.airQuality.setAttribute(TemperatureMeasurement.Cluster.id, 'measuredValue', 2150, this.airQuality.log);
499
- this.airQuality.setAttribute(RelativeHumidityMeasurement.Cluster.id, 'measuredValue', 5500, this.airQuality.log);
500
- this.airQuality.setAttribute(CarbonMonoxideConcentrationMeasurement.Cluster.id, 'measuredValue', 10, this.airQuality.log);
501
- this.airQuality.setAttribute(CarbonDioxideConcentrationMeasurement.Cluster.id, 'measuredValue', 400, this.airQuality.log);
502
- this.airQuality.setAttribute(NitrogenDioxideConcentrationMeasurement.Cluster.id, 'measuredValue', 1, this.airQuality.log);
503
- this.airQuality.setAttribute(OzoneConcentrationMeasurement.Cluster.id, 'measuredValue', 1, this.airQuality.log);
504
- this.airQuality.setAttribute(FormaldehydeConcentrationMeasurement.Cluster.id, 'measuredValue', 1, this.airQuality.log);
505
- this.airQuality.setAttribute(Pm1ConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
506
- this.airQuality.setAttribute(Pm25ConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
507
- this.airQuality.setAttribute(Pm10ConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
508
- this.airQuality.setAttribute(RadonConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
509
- this.airQuality.setAttribute(TotalVolatileOrganicCompoundsConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
548
+ this.bridgedDevices.set(this.airQuality.deviceName ?? '', this.airQuality);
549
+ await this.airQuality.setAttribute(AirQuality.Cluster.id, 'airQuality', AirQuality.AirQualityEnum.Good, this.airQuality.log);
550
+ await this.airQuality.setAttribute(TemperatureMeasurement.Cluster.id, 'measuredValue', 2150, this.airQuality.log);
551
+ await this.airQuality.setAttribute(RelativeHumidityMeasurement.Cluster.id, 'measuredValue', 5500, this.airQuality.log);
552
+ await this.airQuality.setAttribute(CarbonMonoxideConcentrationMeasurement.Cluster.id, 'measuredValue', 10, this.airQuality.log);
553
+ await this.airQuality.setAttribute(CarbonDioxideConcentrationMeasurement.Cluster.id, 'measuredValue', 400, this.airQuality.log);
554
+ await this.airQuality.setAttribute(NitrogenDioxideConcentrationMeasurement.Cluster.id, 'measuredValue', 1, this.airQuality.log);
555
+ await this.airQuality.setAttribute(OzoneConcentrationMeasurement.Cluster.id, 'measuredValue', 1, this.airQuality.log);
556
+ await this.airQuality.setAttribute(FormaldehydeConcentrationMeasurement.Cluster.id, 'measuredValue', 1, this.airQuality.log);
557
+ await this.airQuality.setAttribute(Pm1ConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
558
+ await this.airQuality.setAttribute(Pm25ConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
559
+ await this.airQuality.setAttribute(Pm10ConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
560
+ await this.airQuality.setAttribute(RadonConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
561
+ await this.airQuality.setAttribute(TotalVolatileOrganicCompoundsConcentrationMeasurement.Cluster.id, 'measuredValue', 100, this.airQuality.log);
510
562
  }
511
563
  async onConfigure() {
512
564
  this.log.info('onConfigure called');
513
565
  // Set switch to off
514
- this.switch?.setAttribute(OnOffCluster.id, 'onOff', false, this.switch.log);
566
+ await this.switch?.setAttribute(OnOffCluster.id, 'onOff', false, this.switch.log);
515
567
  this.switch?.log.info('Set switch initial onOff to false');
516
568
  // Toggle switch onOff every minute
517
- this.switchInterval = setInterval(() => {
569
+ this.switchInterval = setInterval(async () => {
518
570
  const status = this.switch?.getAttribute(OnOffCluster.id, 'onOff', this.switch.log);
519
571
  if (isValidBoolean(status)) {
520
- this.switch?.setAttribute(OnOffCluster.id, 'onOff', !status, this.switch.log);
572
+ await this.switch?.setAttribute(OnOffCluster.id, 'onOff', !status, this.switch.log);
521
573
  this.switch?.log.info(`Set switch onOff to ${!status}`);
522
574
  }
523
575
  }, 60 * 1000 + 100);
524
576
  // Set light on/off to off
525
- this.lightOnOff?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightOnOff.log);
577
+ await this.lightOnOff?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightOnOff.log);
526
578
  this.lightOnOff?.log.info('Set light initial onOff to false.');
527
579
  // Set light on/off to off
528
- this.dimmer?.setAttribute(OnOffCluster.id, 'onOff', false, this.dimmer.log);
529
- this.dimmer?.setAttribute(LevelControlCluster.id, 'currentLevel', 0, this.dimmer.log);
530
- this.dimmer?.log.info('Set dimmer initial onOff to false, currentLevel to 0.');
580
+ await this.dimmer?.setAttribute(OnOffCluster.id, 'onOff', false, this.dimmer.log);
581
+ const minLevel = this.dimmer?.getAttribute(LevelControlCluster.id, 'minLevel', this.dimmer.log) | 0;
582
+ await this.dimmer?.setAttribute(LevelControlCluster.id, 'currentLevel', minLevel, this.dimmer.log);
583
+ this.dimmer?.log.info(`Set dimmer initial onOff to false, currentLevel to ${minLevel}.`);
531
584
  // Set light to off, level to 0 and hue to 0 and saturation to 50% (pink color)
532
- this.light?.setAttribute(OnOffCluster.id, 'onOff', false, this.light.log);
533
- this.light?.setAttribute(LevelControlCluster.id, 'currentLevel', 0, this.light.log);
534
- this.light?.setAttribute(ColorControlCluster.id, 'currentHue', 0, this.light.log);
535
- this.light?.setAttribute(ColorControlCluster.id, 'currentSaturation', 128, this.light.log);
536
- this.light?.configureColorControlMode(ColorControl.ColorMode.CurrentHueAndCurrentSaturation);
585
+ await this.light?.setAttribute(OnOffCluster.id, 'onOff', false, this.light.log);
586
+ await this.light?.setAttribute(LevelControlCluster.id, 'currentLevel', 0, this.light.log);
587
+ await this.light?.setAttribute(ColorControlCluster.id, 'currentHue', 0, this.light.log);
588
+ await this.light?.setAttribute(ColorControlCluster.id, 'currentSaturation', 128, this.light.log);
589
+ await this.light?.configureColorControlMode(ColorControl.ColorMode.CurrentHueAndCurrentSaturation);
537
590
  this.light?.log.info('Set light initial onOff to false, currentLevel to 0, hue to 0 and saturation to 50%.');
538
591
  // Set light XY to true, level to 100% and XY to red
539
- this.lightXY?.setAttribute(OnOffCluster.id, 'onOff', true, this.lightXY.log);
540
- this.lightXY?.setAttribute(LevelControlCluster.id, 'currentLevel', 254, this.lightXY.log);
541
- this.lightXY?.setAttribute(ColorControlCluster.id, 'currentX', 0.7006 * 65536, this.lightXY.log);
542
- this.lightXY?.setAttribute(ColorControlCluster.id, 'currentY', 0.2993 * 65536, this.lightXY.log);
543
- this.lightXY?.configureColorControlMode(ColorControl.ColorMode.CurrentXAndCurrentY);
592
+ await this.lightXY?.setAttribute(OnOffCluster.id, 'onOff', true, this.lightXY.log);
593
+ await this.lightXY?.setAttribute(LevelControlCluster.id, 'currentLevel', 254, this.lightXY.log);
594
+ await this.lightXY?.setAttribute(ColorControlCluster.id, 'currentX', 0.7006 * 65536, this.lightXY.log);
595
+ await this.lightXY?.setAttribute(ColorControlCluster.id, 'currentY', 0.2993 * 65536, this.lightXY.log);
596
+ await this.lightXY?.configureColorControlMode(ColorControl.ColorMode.CurrentXAndCurrentY);
544
597
  this.lightXY?.log.info('Set light XY initial onOff to true, currentLevel to 254, X to 0.7006 and Y to 0.2993.');
545
598
  // Set light HS to off, level to 0 and hue to 0 and saturation to 50% (pink color)
546
- this.lightHS?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightHS.log);
547
- this.lightHS?.setAttribute(LevelControlCluster.id, 'currentLevel', 0, this.lightHS.log);
548
- this.lightHS?.setAttribute(ColorControlCluster.id, 'currentHue', 0, this.lightHS.log);
549
- this.lightHS?.setAttribute(ColorControlCluster.id, 'currentSaturation', 128, this.lightHS.log);
550
- this.lightHS?.configureColorControlMode(ColorControl.ColorMode.CurrentHueAndCurrentSaturation);
599
+ await this.lightHS?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightHS.log);
600
+ await this.lightHS?.setAttribute(LevelControlCluster.id, 'currentLevel', 0, this.lightHS.log);
601
+ await this.lightHS?.setAttribute(ColorControlCluster.id, 'currentHue', 0, this.lightHS.log);
602
+ await this.lightHS?.setAttribute(ColorControlCluster.id, 'currentSaturation', 128, this.lightHS.log);
603
+ await this.lightHS?.configureColorControlMode(ColorControl.ColorMode.CurrentHueAndCurrentSaturation);
551
604
  this.lightHS?.log.info('Set light HS initial onOff to false, currentLevel to 0, hue to 0 and saturation to 50%.');
552
605
  // Set light CT to true, level to 50% and colorTemperatureMireds to 250
553
- this.lightCT?.setAttribute(OnOffCluster.id, 'onOff', true, this.lightCT.log);
554
- this.lightCT?.setAttribute(LevelControlCluster.id, 'currentLevel', 128, this.lightCT.log);
555
- this.lightCT?.setAttribute(ColorControlCluster.id, 'colorTemperatureMireds', 250, this.lightCT.log);
556
- this.lightCT?.configureColorControlMode(ColorControl.ColorMode.ColorTemperatureMireds);
606
+ await this.lightCT?.setAttribute(OnOffCluster.id, 'onOff', true, this.lightCT.log);
607
+ await this.lightCT?.setAttribute(LevelControlCluster.id, 'currentLevel', 128, this.lightCT.log);
608
+ await this.lightCT?.setAttribute(ColorControlCluster.id, 'colorTemperatureMireds', 250, this.lightCT.log);
609
+ await this.lightCT?.configureColorControlMode(ColorControl.ColorMode.ColorTemperatureMireds);
557
610
  this.lightCT?.log.info('Set light CT initial onOff to true, currentLevel to 128, colorTemperatureMireds to 250.');
558
- this.lightInterval = setInterval(() => {
611
+ this.lightInterval = setInterval(async () => {
559
612
  const state = this.light?.getAttribute(OnOffCluster.id, 'onOff', this.light.log);
560
613
  let level = this.light?.getAttribute(LevelControlCluster.id, 'currentLevel', this.light.log);
561
614
  if (isValidBoolean(state) && isValidNumber(level, 0, 254)) {
562
615
  level += 10;
563
- if (level > 254) {
616
+ if (level >= 250) {
564
617
  level = 0;
565
- this.lightOnOff?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightOnOff.log);
566
- this.dimmer?.setAttribute(OnOffCluster.id, 'onOff', false, this.dimmer.log);
567
- this.light?.setAttribute(OnOffCluster.id, 'onOff', false, this.light.log);
568
- this.lightXY?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightXY.log);
569
- this.lightHS?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightHS.log);
570
- this.lightCT?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightCT.log);
618
+ await this.lightOnOff?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightOnOff.log);
619
+ await this.dimmer?.setAttribute(OnOffCluster.id, 'onOff', false, this.dimmer.log);
620
+ await this.light?.setAttribute(OnOffCluster.id, 'onOff', false, this.light.log);
621
+ await this.lightXY?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightXY.log);
622
+ await this.lightHS?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightHS.log);
623
+ await this.lightCT?.setAttribute(OnOffCluster.id, 'onOff', false, this.lightCT.log);
571
624
  this.log.info('Set lights onOff to false');
572
- this.dimmer?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.dimmer.log);
573
- this.light?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.light.log);
574
- this.lightXY?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightXY.log);
575
- this.lightHS?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightHS.log);
576
- this.lightCT?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightCT.log);
625
+ await this.dimmer?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.dimmer.log);
626
+ await this.light?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.light.log);
627
+ await this.lightXY?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightXY.log);
628
+ await this.lightHS?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightHS.log);
629
+ await this.lightCT?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightCT.log);
577
630
  this.log.info(`Set lights currentLevel to ${level}`);
578
631
  }
579
632
  else {
580
- this.lightOnOff?.setAttribute(OnOffCluster.id, 'onOff', true, this.lightOnOff?.log);
581
- this.dimmer?.setAttribute(OnOffCluster.id, 'onOff', true, this.dimmer.log);
582
- this.light?.setAttribute(OnOffCluster.id, 'onOff', true, this.light.log);
583
- this.lightXY?.setAttribute(OnOffCluster.id, 'onOff', true, this.lightXY.log);
584
- this.lightHS?.setAttribute(OnOffCluster.id, 'onOff', true, this.lightHS.log);
585
- this.lightCT?.setAttribute(OnOffCluster.id, 'onOff', true, this.lightCT.log);
633
+ await this.lightOnOff?.setAttribute(OnOffCluster.id, 'onOff', true, this.lightOnOff?.log);
634
+ await this.dimmer?.setAttribute(OnOffCluster.id, 'onOff', true, this.dimmer.log);
635
+ await this.light?.setAttribute(OnOffCluster.id, 'onOff', true, this.light.log);
636
+ await this.lightXY?.setAttribute(OnOffCluster.id, 'onOff', true, this.lightXY.log);
637
+ await this.lightHS?.setAttribute(OnOffCluster.id, 'onOff', true, this.lightHS.log);
638
+ await this.lightCT?.setAttribute(OnOffCluster.id, 'onOff', true, this.lightCT.log);
586
639
  this.log.info('Set lights onOff to true');
587
- this.dimmer?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.dimmer.log);
588
- this.light?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.light.log);
589
- this.lightXY?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightXY.log);
590
- this.lightHS?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightHS.log);
591
- this.lightCT?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightCT.log);
640
+ await this.dimmer?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.dimmer.log);
641
+ await this.light?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.light.log);
642
+ await this.lightXY?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightXY.log);
643
+ await this.lightHS?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightHS.log);
644
+ await this.lightCT?.setAttribute(LevelControlCluster.id, 'currentLevel', level, this.lightCT.log);
592
645
  this.log.info(`Set lights currentLevel to ${level}`);
593
646
  }
594
647
  }
595
648
  }, 60 * 1000 + 200);
596
649
  // Set outlet to off
597
- this.outlet?.setAttribute(OnOffCluster.id, 'onOff', false, this.outlet.log);
650
+ await this.outlet?.setAttribute(OnOffCluster.id, 'onOff', false, this.outlet.log);
598
651
  this.outlet?.log.info('Set outlet initial onOff to false');
599
652
  // Toggle outlet onOff every minute
600
- this.outletInterval = setInterval(() => {
653
+ this.outletInterval = setInterval(async () => {
601
654
  const state = this.outlet?.getAttribute(OnOffCluster.id, 'onOff', this.outlet.log);
602
655
  if (isValidBoolean(state)) {
603
- this.outlet?.setAttribute(OnOffCluster.id, 'onOff', !state, this.outlet.log);
656
+ await this.outlet?.setAttribute(OnOffCluster.id, 'onOff', !state, this.outlet.log);
604
657
  this.outlet?.log.info(`Set outlet onOff to ${!state}`);
605
658
  }
606
659
  }, 60 * 1000 + 300);
607
660
  // Set cover to target = current position and status to stopped (current position is persisted in the cluster)
608
- this.cover?.setWindowCoveringTargetAsCurrentAndStopped();
661
+ await this.cover?.setWindowCoveringTargetAsCurrentAndStopped();
609
662
  this.cover?.log.info('Set cover initial targetPositionLiftPercent100ths = currentPositionLiftPercent100ths and operationalStatus to Stopped.');
610
663
  // Increment cover position every minute
611
- this.coverInterval = setInterval(() => {
664
+ this.coverInterval = setInterval(async () => {
612
665
  let position = this.cover?.getAttribute(WindowCoveringCluster.id, 'currentPositionLiftPercent100ths', this.cover.log);
613
666
  if (isValidNumber(position, 0, 10000)) {
614
667
  position = position > 9000 ? 0 : position + 1000;
615
- this.cover?.setAttribute(WindowCoveringCluster.id, 'targetPositionLiftPercent100ths', position, this.cover.log);
616
- this.cover?.setAttribute(WindowCoveringCluster.id, 'currentPositionLiftPercent100ths', position, this.cover.log);
617
- this.cover?.setAttribute(WindowCoveringCluster.id, 'operationalStatus', { global: WindowCovering.MovementStatus.Stopped, lift: WindowCovering.MovementStatus.Stopped, tilt: WindowCovering.MovementStatus.Stopped }, this.cover.log);
668
+ await this.cover?.setAttribute(WindowCoveringCluster.id, 'targetPositionLiftPercent100ths', position, this.cover.log);
669
+ await this.cover?.setAttribute(WindowCoveringCluster.id, 'currentPositionLiftPercent100ths', position, this.cover.log);
670
+ await this.cover?.setAttribute(WindowCoveringCluster.id, 'operationalStatus', { global: WindowCovering.MovementStatus.Stopped, lift: WindowCovering.MovementStatus.Stopped, tilt: WindowCovering.MovementStatus.Stopped }, this.cover.log);
618
671
  this.cover?.log.info(`Set cover current and target positionLiftPercent100ths to ${position} and operationalStatus to Stopped`);
619
672
  }
620
673
  }, 60 * 1000 + 400);
621
674
  // Set lock to Locked
622
- this.lock?.setAttribute(DoorLockCluster.id, 'lockState', DoorLock.LockState.Locked, this.lock.log);
675
+ await this.lock?.setAttribute(DoorLockCluster.id, 'lockState', DoorLock.LockState.Locked, this.lock.log);
623
676
  this.lock?.log.info('Set lock initial lockState to Locked');
624
677
  // Toggle lock every minute
625
- this.lockInterval = setInterval(() => {
678
+ this.lockInterval = setInterval(async () => {
626
679
  const status = this.lock?.getAttribute(DoorLockCluster.id, 'lockState', this.lock.log);
627
680
  if (isValidNumber(status, DoorLock.LockState.Locked, DoorLock.LockState.Unlocked)) {
628
- this.lock?.setAttribute(DoorLockCluster.id, 'lockState', status === DoorLock.LockState.Locked ? DoorLock.LockState.Unlocked : DoorLock.LockState.Locked, this.lock.log);
681
+ await this.lock?.setAttribute(DoorLockCluster.id, 'lockState', status === DoorLock.LockState.Locked ? DoorLock.LockState.Unlocked : DoorLock.LockState.Locked, this.lock.log);
629
682
  this.lock?.log.info(`Set lock lockState to ${status === DoorLock.LockState.Locked ? 'Unlocked' : 'Locked'}`);
630
683
  }
631
684
  }, 60 * 1000 + 500);
632
685
  // Set local to 16°C
633
- this.thermo?.setAttribute(ThermostatCluster.id, 'localTemperature', 16 * 100, this.thermo.log);
634
- this.thermo?.setAttribute(ThermostatCluster.id, 'systemMode', Thermostat.SystemMode.Auto, this.thermo.log);
686
+ await this.thermo?.setAttribute(ThermostatCluster.id, 'localTemperature', 16 * 100, this.thermo.log);
687
+ await this.thermo?.setAttribute(ThermostatCluster.id, 'systemMode', Thermostat.SystemMode.Auto, this.thermo.log);
635
688
  this.thermo?.log.info('Set thermostat initial localTemperature to 16°C and mode Auto');
636
689
  const temperature = this.thermo?.getChildEndpointByName('Temperature');
637
- this.thermo?.setAttribute(TemperatureMeasurementCluster.id, 'measuredValue', 16 * 100, this.thermo.log, temperature);
690
+ await this.thermo?.setAttribute(TemperatureMeasurementCluster.id, 'measuredValue', 16 * 100, this.thermo.log, temperature);
638
691
  const humidity = this.thermo?.getChildEndpointByName('Humidity');
639
- this.thermo?.setAttribute(RelativeHumidityMeasurementCluster.id, 'measuredValue', 50 * 100, this.thermo.log, humidity);
692
+ await this.thermo?.setAttribute(RelativeHumidityMeasurementCluster.id, 'measuredValue', 50 * 100, this.thermo.log, humidity);
640
693
  const flow = this.thermo?.getChildEndpointByName('Flow');
641
- this.thermo?.setAttribute(FlowMeasurementCluster.id, 'measuredValue', 10, this.thermo.log, flow);
694
+ await this.thermo?.setAttribute(FlowMeasurementCluster.id, 'measuredValue', 10, this.thermo.log, flow);
642
695
  this.thermo?.log.info('Set thermostat ext temperature to 16°C, ext humidity to 50% and ext valve flow to 10');
643
696
  // Increment localTemperature every minute
644
- this.thermoInterval = setInterval(() => {
697
+ this.thermoInterval = setInterval(async () => {
645
698
  let temperature = this.thermo?.getAttribute(ThermostatCluster.id, 'localTemperature', this.thermo.log);
646
699
  if (isValidNumber(temperature, 1600, 2400)) {
647
700
  temperature = temperature + 100 > 2400 ? 1600 : temperature + 100;
648
- this.thermo?.setAttribute(ThermostatCluster.id, 'localTemperature', temperature, this.thermo.log);
701
+ await this.thermo?.setAttribute(ThermostatCluster.id, 'localTemperature', temperature, this.thermo.log);
649
702
  const temp = this.thermo?.getChildEndpointByName('Temperature');
650
- this.thermo?.setAttribute(TemperatureMeasurementCluster.id, 'measuredValue', temperature, this.thermo.log, temp);
703
+ await this.thermo?.setAttribute(TemperatureMeasurementCluster.id, 'measuredValue', temperature, this.thermo.log, temp);
651
704
  const humidity = this.thermo?.getChildEndpointByName('Humidity');
652
- this.thermo?.setAttribute(RelativeHumidityMeasurementCluster.id, 'measuredValue', 50 * 100, this.thermo.log, humidity);
705
+ await this.thermo?.setAttribute(RelativeHumidityMeasurementCluster.id, 'measuredValue', 50 * 100, this.thermo.log, humidity);
653
706
  const flow = this.thermo?.getChildEndpointByName('Flow');
654
- this.thermo?.setAttribute(FlowMeasurementCluster.id, 'measuredValue', 10, this.thermo.log, flow);
707
+ await this.thermo?.setAttribute(FlowMeasurementCluster.id, 'measuredValue', 10, this.thermo.log, flow);
655
708
  this.thermo?.log.info(`Set thermostat localTemperature to ${temperature / 100}°C`);
656
709
  }
657
710
  }, 60 * 1000 + 600);
711
+ // Set airConditioner to on
712
+ await this.airConditioner?.setAttribute(OnOffCluster.id, 'onOff', true, this.airConditioner.log);
713
+ // Increment airConditioner localTemperature every minute
714
+ this.airConditionerInterval = setInterval(async () => {
715
+ let temperature = this.airConditioner?.getAttribute(ThermostatCluster.id, 'localTemperature', this.airConditioner.log);
716
+ if (isValidNumber(temperature, 1600, 2400)) {
717
+ temperature = temperature + 100 > 2400 ? 1600 : temperature + 100;
718
+ await this.airConditioner?.setAttribute(ThermostatCluster.id, 'localTemperature', temperature, this.airConditioner.log);
719
+ await this.airConditioner?.setAttribute(TemperatureMeasurementCluster.id, 'measuredValue', temperature, this.airConditioner.log);
720
+ await this.airConditioner?.setAttribute(RelativeHumidityMeasurementCluster.id, 'measuredValue', 50 * 100, this.airConditioner.log);
721
+ this.airConditioner?.log.info(`Set airConditioner localTemperature to ${temperature / 100}°C`);
722
+ }
723
+ }, 60 * 1000 + 550);
658
724
  // Set fan to auto
659
- this.fan?.log.info('Set fan initial fanMode to Auto, percentCurrent to 50 and speedCurrent to 50');
660
- this.fan?.setAttribute(FanControlCluster.id, 'fanMode', FanControl.FanMode.Auto, this.fan.log);
661
- this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', 50, this.fan.log);
662
- this.fan?.setAttribute(FanControlCluster.id, 'speedCurrent', 50, this.fan.log);
725
+ this.fan?.log.info('Set fan initial fanMode to Auto, percentCurrent and percentSetting to 50 and speedCurrent and speedSetting to 50');
726
+ await this.fan?.setAttribute(FanControlCluster.id, 'fanMode', FanControl.FanMode.Auto, this.fan.log);
727
+ await this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', 50, this.fan.log);
728
+ await this.fan?.setAttribute(FanControlCluster.id, 'percentSetting', 50, this.fan.log);
729
+ await this.fan?.setAttribute(FanControlCluster.id, 'speedCurrent', 50, this.fan.log);
730
+ await this.fan?.setAttribute(FanControlCluster.id, 'speedSetting', 50, this.fan.log);
663
731
  // Increment fan percentCurrent every minute
664
- this.fanInterval = setInterval(() => {
732
+ this.fanInterval = setInterval(async () => {
665
733
  const mode = this.fan?.getAttribute(FanControlCluster.id, 'fanMode', this.fan.log);
666
734
  let value = this.fan?.getAttribute(FanControlCluster.id, 'percentCurrent', this.fan.log);
667
735
  if (isValidNumber(mode, FanControl.FanMode.Off, FanControl.FanMode.Auto) && mode === FanControl.FanMode.Auto && isValidNumber(value, 0, 100)) {
668
736
  value = value + 10 >= 100 ? 0 : value + 10;
669
- this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', value, this.fan.log);
670
- this.fan?.log.info(`Set fan percentCurrent to ${value}`);
737
+ await this.fan?.setAttribute(FanControlCluster.id, 'percentCurrent', value, this.fan.log);
738
+ await this.fan?.setAttribute(FanControlCluster.id, 'percentSetting', value, this.fan.log);
739
+ this.fan?.log.info(`Set fan percentCurrent and percentSetting to ${value}`);
671
740
  }
672
741
  }, 60 * 1000 + 700);
673
742
  // Set waterLeak to false
674
- this.waterLeak?.setAttribute(BooleanStateCluster.id, 'stateValue', false, this.waterLeak.log);
743
+ await this.waterLeak?.setAttribute(BooleanStateCluster.id, 'stateValue', false, this.waterLeak.log);
675
744
  // Toggle waterLeak every minute
676
- this.waterLeakInterval = setInterval(() => {
745
+ this.waterLeakInterval = setInterval(async () => {
677
746
  let value = this.waterLeak?.getAttribute(BooleanStateCluster.id, 'stateValue', this.waterLeak.log);
678
747
  if (isValidBoolean(value)) {
679
748
  value = !value;
680
- this.waterLeak?.setAttribute(BooleanStateCluster.id, 'stateValue', value, this.waterLeak.log);
749
+ await this.waterLeak?.setAttribute(BooleanStateCluster.id, 'stateValue', value, this.waterLeak.log);
681
750
  this.waterLeak?.log.info(`Set waterLeak stateValue to ${value}`);
682
751
  }
683
752
  }, 60 * 1000 + 800);
684
753
  // Set waterFreeze to false
685
- this.waterFreeze?.setAttribute(BooleanStateCluster.id, 'stateValue', false, this.waterFreeze.log);
754
+ await this.waterFreeze?.setAttribute(BooleanStateCluster.id, 'stateValue', false, this.waterFreeze.log);
686
755
  // Toggle waterFreeze every minute
687
- this.waterFreezeInterval = setInterval(() => {
756
+ this.waterFreezeInterval = setInterval(async () => {
688
757
  let value = this.waterFreeze?.getAttribute(BooleanStateCluster.id, 'stateValue', this.waterFreeze.log);
689
758
  if (isValidBoolean(value)) {
690
759
  value = !value;
691
- this.waterFreeze?.setAttribute(BooleanStateCluster.id, 'stateValue', value, this.waterFreeze.log);
760
+ await this.waterFreeze?.setAttribute(BooleanStateCluster.id, 'stateValue', value, this.waterFreeze.log);
692
761
  this.waterFreeze?.log.info(`Set waterFreeze stateValue to ${value}`);
693
762
  }
694
763
  }, 60 * 1000 + 900);
695
764
  // Set rain to false
696
- this.rain?.setAttribute(BooleanStateCluster.id, 'stateValue', false, this.rain.log);
765
+ await this.rain?.setAttribute(BooleanStateCluster.id, 'stateValue', false, this.rain.log);
697
766
  // Toggle rain every minute
698
- this.rainInterval = setInterval(() => {
767
+ this.rainInterval = setInterval(async () => {
699
768
  let value = this.rain?.getAttribute(BooleanStateCluster.id, 'stateValue', this.rain.log);
700
769
  if (isValidBoolean(value)) {
701
770
  value = !value;
702
- this.rain?.setAttribute(BooleanStateCluster.id, 'stateValue', value, this.rain.log);
771
+ await this.rain?.setAttribute(BooleanStateCluster.id, 'stateValue', value, this.rain.log);
703
772
  this.rain?.log.info(`Set rain stateValue to ${value}`);
704
773
  }
705
774
  }, 60 * 1000 + 1000);
706
775
  // Set smoke to Normal
707
- this.smoke?.setAttribute(SmokeCoAlarmCluster.id, 'smokeState', SmokeCoAlarm.AlarmState.Normal, this.smoke.log);
708
- this.smoke?.setAttribute(SmokeCoAlarmCluster.id, 'coState', SmokeCoAlarm.AlarmState.Normal, this.smoke.log);
776
+ await this.smoke?.setAttribute(SmokeCoAlarmCluster.id, 'smokeState', SmokeCoAlarm.AlarmState.Normal, this.smoke.log);
777
+ await this.smoke?.setAttribute(SmokeCoAlarmCluster.id, 'coState', SmokeCoAlarm.AlarmState.Normal, this.smoke.log);
709
778
  // Toggle smoke every minute
710
- this.smokeInterval = setInterval(() => {
779
+ this.smokeInterval = setInterval(async () => {
711
780
  let value = this.smoke?.getAttribute(SmokeCoAlarmCluster.id, 'smokeState', this.smoke.log);
712
781
  if (isValidNumber(value, SmokeCoAlarm.AlarmState.Normal, SmokeCoAlarm.AlarmState.Critical)) {
713
782
  value = value === SmokeCoAlarm.AlarmState.Normal ? SmokeCoAlarm.AlarmState.Critical : SmokeCoAlarm.AlarmState.Normal;
714
- this.smoke?.setAttribute(SmokeCoAlarmCluster.id, 'smokeState', value, this.smoke.log);
715
- this.smoke?.setAttribute(SmokeCoAlarmCluster.id, 'coState', value, this.smoke.log);
783
+ await this.smoke?.setAttribute(SmokeCoAlarmCluster.id, 'smokeState', value, this.smoke.log);
784
+ await this.smoke?.setAttribute(SmokeCoAlarmCluster.id, 'coState', value, this.smoke.log);
716
785
  this.smoke?.log.info(`Set smoke smokeState and coState to ${value}`);
717
786
  }
718
787
  }, 60 * 1000 + 1100);
719
788
  // Set air quality to Normal
720
789
  this.airQuality?.setAttribute(AirQualityCluster.id, 'airQuality', AirQuality.AirQualityEnum.Good, this.airQuality.log);
721
790
  // Toggle air quality every minute
722
- this.airQualityInterval = setInterval(() => {
791
+ this.airQualityInterval = setInterval(async () => {
723
792
  let value = this.airQuality?.getAttribute(AirQualityCluster.id, 'airQuality', this.airQuality?.log);
724
793
  if (isValidNumber(value, AirQuality.AirQualityEnum.Good, AirQuality.AirQualityEnum.ExtremelyPoor)) {
725
794
  value = value >= AirQuality.AirQualityEnum.ExtremelyPoor ? AirQuality.AirQualityEnum.Good : value + 1;
726
- this.airQuality?.setAttribute(AirQualityCluster.id, 'airQuality', value, this.airQuality.log);
795
+ await this.airQuality?.setAttribute(AirQualityCluster.id, 'airQuality', value, this.airQuality.log);
727
796
  this.smoke?.log.info(`Set air quality to ${value}`);
728
797
  }
729
798
  }, 60 * 1000 + 1100);
@@ -742,6 +811,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
742
811
  clearInterval(this.rainInterval);
743
812
  clearInterval(this.smokeInterval);
744
813
  clearInterval(this.airQualityInterval);
814
+ clearInterval(this.airConditionerInterval);
745
815
  if (this.config.unregisterOnShutdown === true)
746
816
  await this.unregisterAllDevices();
747
817
  }