matterbridge-example-dynamic-platform 1.0.24 → 1.1.0

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