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