@switchbot/homebridge-switchbot 3.5.1-beta.0 → 3.5.1-beta.10

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.
Files changed (197) hide show
  1. package/README.md +16 -0
  2. package/dist/device/blindtilt.d.ts +15 -6
  3. package/dist/device/blindtilt.d.ts.map +1 -1
  4. package/dist/device/blindtilt.js +224 -370
  5. package/dist/device/blindtilt.js.map +1 -1
  6. package/dist/device/bot.d.ts +9 -4
  7. package/dist/device/bot.d.ts.map +1 -1
  8. package/dist/device/bot.js +197 -221
  9. package/dist/device/bot.js.map +1 -1
  10. package/dist/device/ceilinglight.d.ts +10 -5
  11. package/dist/device/ceilinglight.d.ts.map +1 -1
  12. package/dist/device/ceilinglight.js +214 -292
  13. package/dist/device/ceilinglight.js.map +1 -1
  14. package/dist/device/colorbulb.d.ts +10 -5
  15. package/dist/device/colorbulb.d.ts.map +1 -1
  16. package/dist/device/colorbulb.js +335 -421
  17. package/dist/device/colorbulb.js.map +1 -1
  18. package/dist/device/contact.d.ts +9 -4
  19. package/dist/device/contact.d.ts.map +1 -1
  20. package/dist/device/contact.js +121 -200
  21. package/dist/device/contact.js.map +1 -1
  22. package/dist/device/curtain.d.ts +20 -7
  23. package/dist/device/curtain.d.ts.map +1 -1
  24. package/dist/device/curtain.js +229 -403
  25. package/dist/device/curtain.js.map +1 -1
  26. package/dist/device/device.d.ts +41 -22
  27. package/dist/device/device.d.ts.map +1 -1
  28. package/dist/device/device.js +212 -181
  29. package/dist/device/device.js.map +1 -1
  30. package/dist/device/fan.d.ts +9 -4
  31. package/dist/device/fan.d.ts.map +1 -1
  32. package/dist/device/fan.js +204 -249
  33. package/dist/device/fan.js.map +1 -1
  34. package/dist/device/hub.d.ts +9 -5
  35. package/dist/device/hub.d.ts.map +1 -1
  36. package/dist/device/hub.js +107 -233
  37. package/dist/device/hub.js.map +1 -1
  38. package/dist/device/humidifier.d.ts +12 -4
  39. package/dist/device/humidifier.d.ts.map +1 -1
  40. package/dist/device/humidifier.js +193 -235
  41. package/dist/device/humidifier.js.map +1 -1
  42. package/dist/device/iosensor.d.ts +9 -4
  43. package/dist/device/iosensor.d.ts.map +1 -1
  44. package/dist/device/iosensor.js +92 -159
  45. package/dist/device/iosensor.js.map +1 -1
  46. package/dist/device/lightstrip.d.ts +10 -5
  47. package/dist/device/lightstrip.d.ts.map +1 -1
  48. package/dist/device/lightstrip.js +288 -370
  49. package/dist/device/lightstrip.js.map +1 -1
  50. package/dist/device/lock.d.ts +10 -5
  51. package/dist/device/lock.d.ts.map +1 -1
  52. package/dist/device/lock.js +172 -219
  53. package/dist/device/lock.js.map +1 -1
  54. package/dist/device/meter.d.ts +9 -4
  55. package/dist/device/meter.d.ts.map +1 -1
  56. package/dist/device/meter.js +94 -160
  57. package/dist/device/meter.js.map +1 -1
  58. package/dist/device/meterplus.d.ts +9 -4
  59. package/dist/device/meterplus.d.ts.map +1 -1
  60. package/dist/device/meterplus.js +95 -157
  61. package/dist/device/meterplus.js.map +1 -1
  62. package/dist/device/motion.d.ts +9 -4
  63. package/dist/device/motion.d.ts.map +1 -1
  64. package/dist/device/motion.js +85 -144
  65. package/dist/device/motion.js.map +1 -1
  66. package/dist/device/plug.d.ts +9 -4
  67. package/dist/device/plug.d.ts.map +1 -1
  68. package/dist/device/plug.js +100 -127
  69. package/dist/device/plug.js.map +1 -1
  70. package/dist/device/robotvacuumcleaner.d.ts +9 -6
  71. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  72. package/dist/device/robotvacuumcleaner.js +172 -259
  73. package/dist/device/robotvacuumcleaner.js.map +1 -1
  74. package/dist/device/waterdetector.d.ts +12 -4
  75. package/dist/device/waterdetector.d.ts.map +1 -1
  76. package/dist/device/waterdetector.js +106 -131
  77. package/dist/device/waterdetector.js.map +1 -1
  78. package/dist/irdevice/airconditioner.d.ts +2 -1
  79. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  80. package/dist/irdevice/airconditioner.js +2 -3
  81. package/dist/irdevice/airconditioner.js.map +1 -1
  82. package/dist/irdevice/airpurifier.d.ts +2 -1
  83. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  84. package/dist/irdevice/airpurifier.js +2 -3
  85. package/dist/irdevice/airpurifier.js.map +1 -1
  86. package/dist/irdevice/camera.d.ts +2 -1
  87. package/dist/irdevice/camera.d.ts.map +1 -1
  88. package/dist/irdevice/camera.js +2 -3
  89. package/dist/irdevice/camera.js.map +1 -1
  90. package/dist/irdevice/fan.d.ts +2 -1
  91. package/dist/irdevice/fan.d.ts.map +1 -1
  92. package/dist/irdevice/fan.js +2 -3
  93. package/dist/irdevice/fan.js.map +1 -1
  94. package/dist/irdevice/irdevice.d.ts +3 -1
  95. package/dist/irdevice/irdevice.d.ts.map +1 -1
  96. package/dist/irdevice/irdevice.js +5 -1
  97. package/dist/irdevice/irdevice.js.map +1 -1
  98. package/dist/irdevice/light.d.ts +2 -1
  99. package/dist/irdevice/light.d.ts.map +1 -1
  100. package/dist/irdevice/light.js +2 -3
  101. package/dist/irdevice/light.js.map +1 -1
  102. package/dist/irdevice/other.d.ts +2 -1
  103. package/dist/irdevice/other.d.ts.map +1 -1
  104. package/dist/irdevice/other.js +2 -3
  105. package/dist/irdevice/other.js.map +1 -1
  106. package/dist/irdevice/tv.d.ts +2 -1
  107. package/dist/irdevice/tv.d.ts.map +1 -1
  108. package/dist/irdevice/tv.js +2 -3
  109. package/dist/irdevice/tv.js.map +1 -1
  110. package/dist/irdevice/vacuumcleaner.d.ts +2 -1
  111. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  112. package/dist/irdevice/vacuumcleaner.js +2 -3
  113. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  114. package/dist/irdevice/waterheater.d.ts +2 -1
  115. package/dist/irdevice/waterheater.d.ts.map +1 -1
  116. package/dist/irdevice/waterheater.js +2 -3
  117. package/dist/irdevice/waterheater.js.map +1 -1
  118. package/dist/platform.d.ts +14 -14
  119. package/dist/platform.d.ts.map +1 -1
  120. package/dist/platform.js +102 -86
  121. package/dist/platform.js.map +1 -1
  122. package/dist/settings.d.ts +49 -190
  123. package/dist/settings.d.ts.map +1 -1
  124. package/dist/settings.js +19 -0
  125. package/dist/settings.js.map +1 -1
  126. package/dist/types/bledevicestatus.d.ts +279 -0
  127. package/dist/types/bledevicestatus.d.ts.map +1 -0
  128. package/dist/types/bledevicestatus.js +2 -0
  129. package/dist/types/bledevicestatus.js.map +1 -0
  130. package/dist/types/devicelist.d.ts +89 -0
  131. package/dist/types/devicelist.d.ts.map +1 -0
  132. package/dist/types/devicelist.js +6 -0
  133. package/dist/types/devicelist.js.map +1 -0
  134. package/dist/types/deviceresponse.d.ts +13 -0
  135. package/dist/types/deviceresponse.d.ts.map +1 -0
  136. package/dist/types/deviceresponse.js +2 -0
  137. package/dist/types/deviceresponse.js.map +1 -0
  138. package/dist/types/devicestatus.d.ts +149 -0
  139. package/dist/types/devicestatus.d.ts.map +1 -0
  140. package/dist/types/devicestatus.js +3 -0
  141. package/dist/types/devicestatus.js.map +1 -0
  142. package/dist/types/devicewebhookstatus.d.ts +156 -0
  143. package/dist/types/devicewebhookstatus.d.ts.map +1 -0
  144. package/dist/types/devicewebhookstatus.js +2 -0
  145. package/dist/types/devicewebhookstatus.js.map +1 -0
  146. package/dist/types/irdevicelist.d.ts +10 -0
  147. package/dist/types/irdevicelist.d.ts.map +1 -0
  148. package/dist/types/irdevicelist.js +2 -0
  149. package/dist/types/irdevicelist.js.map +1 -0
  150. package/dist/types/pushbody.d.ts +6 -0
  151. package/dist/types/pushbody.d.ts.map +1 -0
  152. package/dist/types/pushbody.js +2 -0
  153. package/dist/types/pushbody.js.map +1 -0
  154. package/dist/utils.d.ts +25 -0
  155. package/dist/utils.d.ts.map +1 -1
  156. package/dist/utils.js +28 -0
  157. package/dist/utils.js.map +1 -1
  158. package/package.json +11 -11
  159. package/src/device/blindtilt.ts +254 -376
  160. package/src/device/bot.ts +209 -224
  161. package/src/device/ceilinglight.ts +227 -297
  162. package/src/device/colorbulb.ts +345 -435
  163. package/src/device/contact.ts +139 -200
  164. package/src/device/curtain.ts +254 -414
  165. package/src/device/device.ts +221 -190
  166. package/src/device/fan.ts +222 -253
  167. package/src/device/hub.ts +127 -248
  168. package/src/device/humidifier.ts +217 -246
  169. package/src/device/iosensor.ts +115 -168
  170. package/src/device/lightstrip.ts +303 -380
  171. package/src/device/lock.ts +188 -224
  172. package/src/device/meter.ts +117 -179
  173. package/src/device/meterplus.ts +118 -176
  174. package/src/device/motion.ts +100 -146
  175. package/src/device/plug.ts +111 -131
  176. package/src/device/robotvacuumcleaner.ts +191 -258
  177. package/src/device/waterdetector.ts +124 -141
  178. package/src/irdevice/airconditioner.ts +4 -4
  179. package/src/irdevice/airpurifier.ts +4 -4
  180. package/src/irdevice/camera.ts +4 -4
  181. package/src/irdevice/fan.ts +4 -4
  182. package/src/irdevice/irdevice.ts +8 -2
  183. package/src/irdevice/light.ts +4 -4
  184. package/src/irdevice/other.ts +4 -4
  185. package/src/irdevice/tv.ts +4 -4
  186. package/src/irdevice/vacuumcleaner.ts +4 -4
  187. package/src/irdevice/waterheater.ts +4 -4
  188. package/src/platform.ts +104 -87
  189. package/src/settings.ts +30 -238
  190. package/src/types/bledevicestatus.ts +305 -0
  191. package/src/types/devicelist.ts +124 -0
  192. package/src/types/deviceresponse.ts +15 -0
  193. package/src/types/devicestatus.ts +178 -0
  194. package/src/types/devicewebhookstatus.ts +196 -0
  195. package/src/types/irdevicelist.ts +15 -0
  196. package/src/types/pushbody.ts +9 -0
  197. package/src/utils.ts +33 -0
@@ -3,9 +3,9 @@
3
3
  * curtain.ts: @switchbot/homebridge-switchbot.
4
4
  */
5
5
  import { hostname } from 'os';
6
- import { interval, Subject } from 'rxjs';
7
6
  import { deviceBase } from './device.js';
8
- import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
7
+ import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot';
8
+ import { Subject, debounceTime, interval, skipWhile, take, tap } from 'rxjs';
9
9
  export class Curtain extends deviceBase {
10
10
  platform;
11
11
  // Services
@@ -21,8 +21,6 @@ export class Curtain extends deviceBase {
21
21
  constructor(platform, accessory, device) {
22
22
  super(platform, accessory, device);
23
23
  this.platform = platform;
24
- // default placeholder
25
- this.history(device);
26
24
  // this is subject we use to track when we need to POST changes to the SwitchBot API
27
25
  this.doCurtainUpdate = new Subject();
28
26
  this.curtainUpdateInProgress = false;
@@ -108,7 +106,7 @@ export class Curtain extends deviceBase {
108
106
  // Initialize LightSensor Service
109
107
  if (device.curtain?.hide_lightsensor) {
110
108
  if (this.LightSensor?.Service) {
111
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Light Sensor Service`);
109
+ this.debugLog('Removing Light Sensor Service');
112
110
  this.LightSensor.Service = this.accessory.getService(this.hap.Service.LightSensor);
113
111
  accessory.removeService(this.LightSensor.Service);
114
112
  accessory.context.LightSensor = {};
@@ -135,14 +133,16 @@ export class Curtain extends deviceBase {
135
133
  this.refreshStatus();
136
134
  // Update Homekit
137
135
  this.updateHomeKitCharacteristics();
136
+ //regisiter webhook event handler
137
+ this.registerWebhook();
138
+ // History
139
+ this.history();
138
140
  // Start an update interval
139
141
  interval(this.deviceRefreshRate * 1000)
140
142
  .pipe(skipWhile(() => this.curtainUpdateInProgress))
141
143
  .subscribe(async () => {
142
144
  await this.refreshStatus();
143
145
  });
144
- //regisiter webhook event handler
145
- this.registerWebhook(accessory, device);
146
146
  // update slide progress
147
147
  interval(this.deviceUpdateRate * 1000)
148
148
  //.pipe(skipWhile(() => this.curtainUpdateInProgress))
@@ -150,8 +150,7 @@ export class Curtain extends deviceBase {
150
150
  if (this.WindowCovering.PositionState === this.hap.Characteristic.PositionState.STOPPED) {
151
151
  return;
152
152
  }
153
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Refresh Status When Moving,`
154
- + ` PositionState: ${this.WindowCovering.PositionState}`);
153
+ await this.debugLog(`Refresh Status When Moving, PositionState: ${this.WindowCovering.PositionState}`);
155
154
  await this.refreshStatus();
156
155
  });
157
156
  // Watch for Curtain change events
@@ -165,17 +164,16 @@ export class Curtain extends deviceBase {
165
164
  await this.pushChanges();
166
165
  }
167
166
  catch (e) {
168
- this.apiError(e);
169
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with ${this.device.connectionType} Connection,`
170
- + ` Error Message: ${JSON.stringify(e.message)}`);
167
+ await this.apiError(e);
168
+ await this.errorLog(`failed pushChanges with ${device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`);
171
169
  }
172
170
  this.curtainUpdateInProgress = false;
173
171
  });
174
172
  // Setup EVE history features
175
- this.setupHistoryService(accessory, device);
173
+ this.setupHistoryService();
176
174
  }
177
- history(device) {
178
- if (device.history === true) {
175
+ async history() {
176
+ if (this.device.history === true) {
179
177
  // initialize when this accessory is newly created.
180
178
  this.accessory.context.lastActivation = this.accessory.context.lastActivation ?? 0;
181
179
  }
@@ -187,8 +185,8 @@ export class Curtain extends deviceBase {
187
185
  /*
188
186
  * Setup EVE history features for curtain devices.
189
187
  */
190
- async setupHistoryService(accessory, device) {
191
- if (device.history !== true) {
188
+ async setupHistoryService() {
189
+ if (this.device.history !== true) {
192
190
  return;
193
191
  }
194
192
  const mac = this.device
@@ -230,216 +228,91 @@ export class Curtain extends deviceBase {
230
228
  time: Math.round(new Date().valueOf() / 1000),
231
229
  motion: motion,
232
230
  });
233
- setTimeout(() => {
234
- this.updateHistory();
231
+ setTimeout(async () => {
232
+ await this.updateHistory();
235
233
  }, 10 * 60 * 1000);
236
234
  }
237
235
  async BLEparseStatus(serviceData) {
238
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
239
- this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(serviceData)}`);
236
+ await this.debugLog('BLEparseStatus');
240
237
  // CurrentPosition
241
- this.WindowCovering.CurrentPosition = 100 - Number(serviceData.position);
242
- await this.setMinMax();
243
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition ${this.WindowCovering.CurrentPosition}`);
244
- if (this.setNewTarget) {
245
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Checking Status ...`);
246
- await this.setMinMax();
247
- if (Number(this.WindowCovering.TargetPosition) > this.WindowCovering.CurrentPosition) {
248
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
249
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
250
- this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
251
- this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} INCREASING`
252
- + ` PositionState: ${this.WindowCovering.PositionState}`);
253
- }
254
- else if (Number(this.WindowCovering.TargetPosition) < this.WindowCovering.CurrentPosition) {
255
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Opening, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
256
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
257
- this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
258
- this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} DECREASING`
259
- + ` PositionState: ${this.WindowCovering.PositionState}`);
260
- }
261
- else {
262
- this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} Standby,`
263
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
264
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
265
- this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
266
- this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} STOPPED`
267
- + ` PositionState: ${this.WindowCovering.PositionState}`);
268
- }
269
- }
270
- else {
271
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
272
- this.WindowCovering.TargetPosition = this.WindowCovering.CurrentPosition;
273
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
274
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Stopped`);
275
- }
276
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition},`
277
- + ` TargetPosition: ${this.WindowCovering.TargetPosition}, PositionState: ${this.WindowCovering.PositionState},`);
278
- if (!this.device.curtain?.hide_lightsensor) {
238
+ this.WindowCovering.CurrentPosition = 100 - serviceData.position;
239
+ await this.getCurrentPostion();
240
+ // CurrentAmbientLightLevel
241
+ if (!this.device.curtain?.hide_lightsensor && this.LightSensor?.Service) {
279
242
  const set_minLux = this.device.curtain?.set_minLux ?? 1;
280
243
  const set_maxLux = this.device.curtain?.set_maxLux ?? 6001;
281
- const spaceBetweenLevels = 9;
282
- serviceData.lightLevel = 1;
283
- // Brightness
284
- switch (serviceData.lightLevel) {
285
- case 1:
286
- this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * (serviceData.lightLevel === 1
287
- ? set_minLux : 2);
288
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} 1 LightLevel: ${serviceData.lightLevel},`
289
- + ` CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
290
- this.LightSensor.CurrentAmbientLightLevel = set_minLux;
291
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} 2 LightLevel: ${serviceData.lightLevel},`
292
- + ` CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
293
- break;
294
- case 2:
295
- this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * (Number(serviceData.lightLevel) - 1);
296
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} 1 LightLevel: ${serviceData.lightLevel},`
297
- + ` CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
298
- this.LightSensor.CurrentAmbientLightLevel = (set_maxLux - set_minLux) / spaceBetweenLevels;
299
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} 2 LightLevel: ${serviceData.lightLevel},`
300
- + ` CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
301
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} 3 LightLevel: ${serviceData.lightLevel},`
302
- + ` Calculation: ${(set_maxLux - set_minLux) / spaceBetweenLevels}`);
303
- break;
304
- case 3:
305
- this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * (Number(serviceData.lightLevel) - 1);
306
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} 1 LightLevel: ${serviceData.lightLevel},`
307
- + ` CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
308
- this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 2;
309
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} 2 LightLevel: ${serviceData.lightLevel},`
310
- + ` CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
311
- this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
312
- break;
313
- case 4:
314
- this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 3;
315
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
316
- this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
317
- break;
318
- case 5:
319
- this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 4;
320
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
321
- this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
322
- break;
323
- case 6:
324
- this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 5;
325
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
326
- this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
327
- break;
328
- case 7:
329
- this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 6;
330
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
331
- this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
332
- break;
333
- case 8:
334
- this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 7;
335
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
336
- this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
337
- break;
338
- case 9:
339
- this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 8;
340
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
341
- this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
342
- break;
343
- case 10:
344
- default:
345
- this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * (Number(serviceData.lightLevel) - 1);
346
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} 1 LightLevel: ${serviceData.lightLevel},`
347
- + ` CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
348
- this.LightSensor.CurrentAmbientLightLevel = set_maxLux;
349
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} 2 LightLevel: ${serviceData.lightLevel},`
350
- + ` CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
351
- this.debugLog();
352
- }
353
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel},`
244
+ const lightLevel = Number(serviceData.lightLevel);
245
+ this.LightSensor.CurrentAmbientLightLevel = await this.getLightLevel(lightLevel, set_minLux, set_maxLux, 19);
246
+ this.debugLog(`LightLevel: ${serviceData.lightLevel},`
354
247
  + ` CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
355
248
  }
356
- // Battery
249
+ // BatteryLevel
357
250
  this.Battery.BatteryLevel = Number(serviceData.battery);
358
- if (this.Battery.BatteryLevel < 10) {
359
- this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
360
- }
361
- else {
362
- this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
363
- }
364
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
365
- + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
251
+ await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`);
252
+ // StatusLowBattery
253
+ this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
254
+ ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
255
+ await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`);
366
256
  }
367
257
  async openAPIparseStatus(deviceStatus) {
368
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
258
+ await this.debugLog('openAPIparseStatus');
369
259
  // CurrentPosition
370
- this.WindowCovering.CurrentPosition = 100 - Number(deviceStatus.body.slidePosition);
260
+ this.WindowCovering.CurrentPosition = 100 - deviceStatus.slidePosition;
371
261
  await this.setMinMax();
372
- this.debugLog(`Curtain ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
262
+ await this.debugLog(`Curtain ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
373
263
  if (this.setNewTarget) {
374
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Checking Status ...`);
264
+ await this.infoLog('Checking Status ...');
375
265
  }
376
- if (this.setNewTarget && deviceStatus.body.moving) {
266
+ if (this.setNewTarget && deviceStatus.moving) {
377
267
  await this.setMinMax();
378
268
  if (Number(this.WindowCovering.TargetPosition) > this.WindowCovering.CurrentPosition) {
379
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition} `);
269
+ await this.debugLog(`Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
380
270
  this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
381
271
  this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
382
- this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} INCREASING`
383
- + ` PositionState: ${this.WindowCovering.PositionState}`);
272
+ await this.debugLog(`Increasing, PositionState: ${this.WindowCovering.PositionState}`);
384
273
  }
385
274
  else if (Number(this.WindowCovering.TargetPosition) < this.WindowCovering.CurrentPosition) {
386
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Opening, CurrentPosition: ${this.WindowCovering.CurrentPosition} `);
275
+ await this.debugLog(`Opening, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
387
276
  this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
388
277
  this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
389
- this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} DECREASING`
390
- + ` PositionState: ${this.WindowCovering.PositionState}`);
278
+ await this.debugLog(`Decreasing, PositionState: ${this.WindowCovering.PositionState}`);
391
279
  }
392
280
  else {
393
- this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} Standby,`
394
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
281
+ await this.debugLog(`Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
395
282
  this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
396
283
  this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
397
- this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} STOPPED`
398
- + ` PositionState: ${this.WindowCovering.PositionState}`);
284
+ await this.debugLog(`Stopped, PositionState: ${this.WindowCovering.PositionState}`);
399
285
  }
400
286
  }
401
287
  else {
402
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
288
+ await this.debugLog(`Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
403
289
  this.WindowCovering.TargetPosition = this.WindowCovering.CurrentPosition;
404
290
  this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
405
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Stopped`);
291
+ await this.debugLog(`Stopped, PositionState: ${this.WindowCovering.PositionState}`);
406
292
  }
407
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition},`
408
- + ` TargetPosition: ${this.WindowCovering.TargetPosition}, PositionState: ${this.WindowCovering.PositionState},`);
293
+ await this.debugLog(`CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition: ${this.WindowCovering.TargetPosition},`
294
+ + ` PositionState: ${this.WindowCovering.PositionState},`);
409
295
  // Brightness
410
- if (!this.device.curtain?.hide_lightsensor) {
296
+ if (!this.device.curtain?.hide_lightsensor && this.LightSensor?.Service) {
411
297
  const set_minLux = this.device.curtain?.set_minLux ?? 1;
412
298
  const set_maxLux = this.device.curtain?.set_maxLux ?? 6001;
413
- switch (deviceStatus.body.brightness) {
414
- case 'bright':
415
- this.LightSensor.CurrentAmbientLightLevel = set_maxLux;
416
- this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
417
- break;
418
- case 'dim':
419
- default:
420
- this.LightSensor.CurrentAmbientLightLevel = set_minLux;
421
- }
422
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
299
+ const lightLevel = deviceStatus.lightLevel === 'bright' ? set_maxLux : set_minLux;
300
+ this.LightSensor.CurrentAmbientLightLevel = await this.getLightLevel(lightLevel, set_minLux, set_maxLux, 2);
301
+ await this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
423
302
  + ` CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
424
303
  }
425
304
  // BatteryLevel
426
- this.Battery.BatteryLevel = Number(deviceStatus.body.battery);
427
- if (this.Battery.BatteryLevel < 10) {
428
- this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
429
- }
430
- else {
431
- this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
432
- }
433
- if (Number.isNaN(this.Battery.BatteryLevel)) {
434
- this.Battery.BatteryLevel = 100;
435
- }
436
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
437
- + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
305
+ this.Battery.BatteryLevel = Number(deviceStatus.battery);
306
+ await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`);
307
+ // StatusLowBattery
308
+ this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
309
+ ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
310
+ await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`);
438
311
  // Firmware Version
439
- const version = deviceStatus.body.version?.toString();
440
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Firmware Version: ${version?.replace(/^V|-.*$/g, '')}`);
441
- if (deviceStatus.body.version) {
442
- const deviceVersion = version?.replace(/^V|-.*$/g, '') ?? '0.0.0';
312
+ if (deviceStatus.version) {
313
+ const version = deviceStatus.version.toString();
314
+ await this.debugLog(`Firmware Version: ${version.replace(/^V|-.*$/g, '')}`);
315
+ const deviceVersion = version.replace(/^V|-.*$/g, '') ?? '0.0.0';
443
316
  this.accessory
444
317
  .getService(this.hap.Service.AccessoryInformation)
445
318
  .setCharacteristic(this.hap.Characteristic.HardwareRevision, deviceVersion)
@@ -447,12 +320,30 @@ export class Curtain extends deviceBase {
447
320
  .getCharacteristic(this.hap.Characteristic.FirmwareRevision)
448
321
  .updateValue(deviceVersion);
449
322
  this.accessory.context.deviceVersion = deviceVersion;
450
- this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceVersion: ${this.accessory.context.deviceVersion}`);
323
+ await this.debugSuccessLog(`deviceVersion: ${this.accessory.context.deviceVersion}`);
451
324
  }
452
325
  }
326
+ async parseStatusWebhook(context) {
327
+ await this.debugLog('parseStatusWebhook');
328
+ await this.debugLog(`(slidePosition, battery) = Webhook:(${context.slidePosition}, ${context.battery}),`
329
+ + ` current:(${this.WindowCovering.CurrentPosition}, ${this.Battery.BatteryLevel})`);
330
+ // CurrentPosition
331
+ this.WindowCovering.CurrentPosition = 100 - context.slidePosition;
332
+ await this.getCurrentPostion();
333
+ // BatteryLevel
334
+ this.Battery.BatteryLevel = context.battery;
335
+ await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`);
336
+ // StatusLowBattery
337
+ this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
338
+ ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
339
+ await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`);
340
+ }
341
+ /**
342
+ * Asks the SwitchBot API for the latest device information
343
+ */
453
344
  async refreshStatus() {
454
345
  if (!this.device.enableCloudService && this.OpenAPI) {
455
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} refreshStatus enableCloudService: ${this.device.enableCloudService}`);
346
+ await this.errorLog(`refreshStatus enableCloudService: ${this.device.enableCloudService}`);
456
347
  }
457
348
  else if (this.BLE) {
458
349
  await this.BLERefreshStatus();
@@ -462,12 +353,11 @@ export class Curtain extends deviceBase {
462
353
  }
463
354
  else {
464
355
  await this.offlineOff();
465
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
466
- + ` ${this.device.connectionType}, refreshStatus will not happen.`);
356
+ await this.debugWarnLog(`Connection Type: ${this.device.connectionType}, refreshStatus will not happen.`);
467
357
  }
468
358
  }
469
359
  async BLERefreshStatus() {
470
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
360
+ await this.debugLog('BLERefreshStatus');
471
361
  const switchbot = await this.switchbotBLE();
472
362
  if (switchbot === undefined) {
473
363
  await this.BLERefreshConnection(switchbot);
@@ -478,63 +368,64 @@ export class Curtain extends deviceBase {
478
368
  // Start to monitor advertisement packets
479
369
  const serviceData = await this.monitorAdvertisementPackets(switchbot);
480
370
  // Update HomeKit
481
- if (serviceData.model !== '' && serviceData.modelName !== '') {
371
+ if ((serviceData.model === SwitchBotBLEModel.Curtain || SwitchBotBLEModel.Curtain3)
372
+ && (serviceData.modelName === SwitchBotBLEModelName.Curtain || SwitchBotBLEModelName.Curtain3)) {
482
373
  await this.BLEparseStatus(serviceData);
483
374
  await this.updateHomeKitCharacteristics();
484
375
  }
485
376
  else {
486
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed to get serviceData, serviceData: ${serviceData}`);
377
+ await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
487
378
  await this.BLERefreshConnection(switchbot);
488
379
  }
489
380
  })();
490
381
  }
491
382
  }
492
383
  async openAPIRefreshStatus() {
493
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
384
+ await this.debugLog('openAPIRefreshStatus');
494
385
  try {
495
386
  const { body, statusCode } = await this.deviceRefreshStatus();
496
387
  const deviceStatus = await body.json();
497
- await this.refreshStatusCodes(statusCode, deviceStatus);
498
- if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
499
- await this.successfulRefreshStatus(statusCode, deviceStatus);
500
- await this.openAPIparseStatus(deviceStatus);
388
+ await this.debugLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
389
+ ;
390
+ if (await this.successfulStatusCodes(statusCode, deviceStatus)) {
391
+ await this.debugSuccessLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
392
+ await this.openAPIparseStatus(deviceStatus.body);
501
393
  await this.updateHomeKitCharacteristics();
502
394
  }
503
395
  else {
504
- await this.statusCodes(statusCode, deviceStatus);
396
+ await this.debugWarnLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
397
+ await this.debugWarnLog(statusCode, deviceStatus);
505
398
  }
506
399
  }
507
400
  catch (e) {
508
- this.apiError(e);
509
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
510
- + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
401
+ await this.apiError(e);
402
+ await this.errorLog(`failed openAPIRefreshStatus with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`);
511
403
  }
512
404
  }
513
- async registerWebhook(accessory, device) {
514
- if (device.webhook) {
515
- this.debugLog(`${device.deviceType}: ${accessory.displayName} is listening webhook.`);
516
- this.platform.webhookEventHandler[device.deviceId] = async (context) => {
405
+ async registerWebhook() {
406
+ if (this.device.webhook) {
407
+ await this.debugLog('is listening webhook.');
408
+ this.platform.webhookEventHandler[this.device.deviceId] = async (context) => {
517
409
  try {
518
- this.debugLog(`${device.deviceType}: ${accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
519
- const { slidePosition, battery } = context;
520
- this.debugLog(`${device.deviceType}: ${accessory.displayName} ` +
521
- '(slidePosition, battery) = ' +
522
- `Webhook:(${slidePosition}, ${battery}), `
523
- + `current:(${this.WindowCovering.CurrentPosition}, ${this.Battery.BatteryLevel})`);
524
- this.WindowCovering.CurrentPosition = slidePosition;
525
- this.Battery.BatteryLevel = battery;
526
- this.updateHomeKitCharacteristics();
410
+ await this.debugLog(`received Webhook: ${JSON.stringify(context)}`);
411
+ await this.parseStatusWebhook(context);
412
+ await this.updateHomeKitCharacteristics();
527
413
  }
528
414
  catch (e) {
529
- this.errorLog(`${device.deviceType}: ${accessory.displayName} `
530
- + `failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
415
+ await this.errorLog(`failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
531
416
  }
532
417
  };
533
418
  }
419
+ else {
420
+ await this.debugLog('is not listening webhook.');
421
+ }
534
422
  }
423
+ /**
424
+ * Pushes the requested changes to the SwitchBot API
425
+ */
535
426
  async pushChanges() {
536
427
  if (!this.device.enableCloudService && this.OpenAPI) {
537
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} pushChanges enableCloudService: ${this.device.enableCloudService}`);
428
+ await this.errorLog(`pushChanges enableCloudService: ${this.device.enableCloudService}`);
538
429
  }
539
430
  else if (this.BLE) {
540
431
  await this.BLEpushChanges();
@@ -544,8 +435,7 @@ export class Curtain extends deviceBase {
544
435
  }
545
436
  else {
546
437
  await this.offlineOff();
547
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
548
- + ` ${this.device.connectionType}, pushChanges will not happen.`);
438
+ await this.debugWarnLog(`Connection Type: ${this.device.connectionType}, pushChanges will not happen.`);
549
439
  }
550
440
  // Refresh the status from the API
551
441
  interval(15000)
@@ -556,135 +446,125 @@ export class Curtain extends deviceBase {
556
446
  });
557
447
  }
558
448
  async BLEpushChanges() {
559
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
449
+ await this.debugLog('BLEpushChanges');
560
450
  if (this.WindowCovering.TargetPosition !== this.WindowCovering.CurrentPosition) {
561
- const switchbot = await this.platform.connectBLE();
562
- // Convert to BLE Address
451
+ const switchbot = await this.platform.connectBLE(this.accessory, this.device);
563
452
  await this.convertBLEAddress();
564
453
  const { setPositionMode, Mode } = await this.setPerformance();
565
454
  const adjustedMode = setPositionMode === 1 ? 0x01 : 0xff;
566
- this.debugLog(`${this.accessory.displayName} Mode: ${Mode}`);
455
+ await this.debugLog(`Mode: ${Mode}, setPositionMode: ${setPositionMode}`);
567
456
  if (switchbot !== false) {
568
- try {
569
- const device_list = await switchbot.discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac });
570
- this.infoLog(`${this.accessory.displayName} Target Position: ${this.WindowCovering.TargetPosition}`);
571
- await this.retryBLE({
457
+ switchbot
458
+ .discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac })
459
+ .then(async (device_list) => {
460
+ return await this.retryBLE({
572
461
  max: await this.maxRetryBLE(),
573
462
  fn: async () => {
574
- await device_list[0].runToPos(100 - Number(this.WindowCovering.TargetPosition), adjustedMode);
463
+ return await device_list[0].runToPos(100 - Number(this.WindowCovering.TargetPosition), adjustedMode);
575
464
  },
576
465
  });
577
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
578
- this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
579
- + `TargetPosition: ${this.WindowCovering.TargetPosition} sent over BLE, sent successfully`);
580
- }
581
- catch (e) {
582
- this.apiError(e);
583
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
584
- + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
466
+ })
467
+ .then(async () => {
468
+ await this.successLog(`TargetPostion: ${this.WindowCovering.TargetPosition} sent over SwitchBot BLE, sent successfully`);
469
+ await this.updateHomeKitCharacteristics();
470
+ })
471
+ .catch(async (e) => {
472
+ await this.apiError(e);
473
+ await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`);
585
474
  await this.BLEPushConnection();
586
- throw new Error('Connection error');
587
- }
475
+ });
588
476
  }
589
477
  else {
590
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection`);
478
+ await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
591
479
  await this.BLEPushConnection();
592
480
  }
593
481
  }
594
482
  else {
595
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges, CurrentPosition & TargetPosition Are the Same.`
596
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition ${this.WindowCovering.TargetPosition}`);
483
+ await this.debugLog(`No changes (BLEpushChanges), TargetPosition: ${this.WindowCovering.TargetPosition},`
484
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
597
485
  }
598
486
  }
599
487
  async openAPIpushChanges() {
600
- let command;
601
- let parameter;
602
- let commandType;
603
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
488
+ await this.debugLog('openAPIpushChanges');
604
489
  if (this.WindowCovering.TargetPosition !== this.WindowCovering.CurrentPosition || this.device.disableCaching) {
605
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Pushing ${this.WindowCovering.TargetPosition}`);
490
+ await this.debugLog(`Pushing ${this.WindowCovering.TargetPosition}`);
606
491
  const adjustedTargetPosition = 100 - Number(this.WindowCovering.TargetPosition);
607
492
  const { setPositionMode, Mode } = await this.setPerformance();
608
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Mode: ${Mode}`);
493
+ await this.debugLog(`Mode: ${Mode}, setPositionMode: ${setPositionMode}`);
609
494
  const adjustedMode = setPositionMode || 'ff';
495
+ let bodyChange;
610
496
  if (this.WindowCovering.HoldPosition) {
611
- command = 'pause';
612
- parameter = 'default';
613
- commandType = 'command';
497
+ bodyChange = JSON.stringify({
498
+ command: 'pause',
499
+ parameter: 'default',
500
+ commandType: 'command',
501
+ });
614
502
  }
615
503
  else {
616
- command = 'setPosition';
617
- parameter = `0,${adjustedMode},${adjustedTargetPosition}`;
618
- commandType = 'command';
504
+ bodyChange = JSON.stringify({
505
+ command: 'setPosition',
506
+ parameter: `0,${adjustedMode},${adjustedTargetPosition}`,
507
+ commandType: 'command',
508
+ });
619
509
  }
620
- const bodyChange = JSON.stringify({
621
- command: command,
622
- parameter: parameter,
623
- commandType: commandType,
624
- });
625
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
510
+ await this.debugLog(`SwitchBot OpenAPI bodyChange: ${JSON.stringify(bodyChange)}`);
626
511
  try {
627
512
  const { body, statusCode } = await this.pushChangeRequest(bodyChange);
628
513
  const deviceStatus = await body.json();
629
- await this.pushStatusCodes(statusCode, deviceStatus);
630
- if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
631
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
632
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
633
- this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
634
- + `request to SwitchBot API, body: ${JSON.stringify(JSON.parse(bodyChange))} sent successfully`);
514
+ await this.debugLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
515
+ if (await this.successfulStatusCodes(statusCode, deviceStatus)) {
516
+ await this.debugSuccessLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
517
+ await this.updateHomeKitCharacteristics();
635
518
  }
636
519
  else {
637
- this.statusCode(statusCode);
638
- this.statusCode(deviceStatus.statusCode);
520
+ await this.statusCode(statusCode);
521
+ await this.statusCode(deviceStatus.statusCode);
639
522
  }
640
523
  }
641
524
  catch (e) {
642
- this.apiError(e);
643
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
644
- + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
525
+ await this.apiError(e);
526
+ await this.errorLog(`failed openAPIpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`);
645
527
  }
646
528
  }
647
529
  else {
648
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No OpenAPI Changes, CurrentPosition & TargetPosition Are the Same.`
649
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition ${this.WindowCovering.TargetPosition}`);
530
+ await this.debugLog(`No changes (openAPIpushChanges), CurrentPosition: ${this.WindowCovering.CurrentPosition},`
531
+ + ` TargetPosition: ${this.WindowCovering.TargetPosition}`);
650
532
  }
651
533
  }
652
534
  /**
653
535
  * Handle requests to set the value of the "Target Position" characteristic
654
536
  */
655
537
  async TargetPositionSet(value) {
656
- if (this.WindowCovering.TargetPosition === this.accessory.context.TargetPosition) {
657
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set TargetPosition: ${value}`);
538
+ if (this.WindowCovering.TargetPosition !== this.accessory.context.TargetPosition) {
539
+ await this.infoLog(`Set TargetPosition: ${value}`);
658
540
  }
659
541
  else {
660
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetPosition: ${value}`);
542
+ await this.debugLog(`No Changes, TargetPosition: ${value}`);
661
543
  }
662
544
  // Set HoldPosition to false when TargetPosition is changed
663
545
  this.WindowCovering.HoldPosition = false;
664
546
  this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.HoldPosition, this.WindowCovering.HoldPosition);
665
547
  this.WindowCovering.TargetPosition = value;
666
- if (this.device.mqttURL) {
667
- this.mqttPublish('TargetPosition', this.WindowCovering.TargetPosition.toString());
668
- this.mqttPublish('HoldPosition', this.WindowCovering.HoldPosition.toString()); // Convert boolean to string
669
- }
548
+ await this.mqtt('TargetPosition', this.WindowCovering.TargetPosition);
549
+ await this.mqtt('HoldPosition', this.WindowCovering.HoldPosition);
550
+ await this.startUpdatingCurtainIfNeeded();
551
+ }
552
+ async startUpdatingCurtainIfNeeded() {
670
553
  await this.setMinMax();
671
- if (value > this.WindowCovering.CurrentPosition) {
554
+ if (this.WindowCovering.TargetPosition > this.WindowCovering.CurrentPosition) {
672
555
  this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
673
556
  this.setNewTarget = true;
674
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${value},`
675
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
557
+ await this.debugLog(`value: ${this.WindowCovering.TargetPosition}, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
676
558
  }
677
- else if (value < this.WindowCovering.CurrentPosition) {
559
+ else if (this.WindowCovering.TargetPosition < this.WindowCovering.CurrentPosition) {
678
560
  this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
679
561
  this.setNewTarget = true;
680
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${value},`
681
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
562
+ await this.debugLog(`value: ${this.WindowCovering.TargetPosition}, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
682
563
  }
683
564
  else {
684
565
  this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
685
566
  this.setNewTarget = false;
686
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${value},`
687
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
567
+ await this.debugLog(`value: ${this.WindowCovering.TargetPosition}, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
688
568
  }
689
569
  this.WindowCovering.Service.setCharacteristic(this.hap.Characteristic.PositionState, this.WindowCovering.PositionState);
690
570
  this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
@@ -693,10 +573,10 @@ export class Curtain extends deviceBase {
693
573
  * The minimum time depends on the network control latency.
694
574
  */
695
575
  clearTimeout(this.setNewTargetTimer);
696
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateRate: ${this.deviceUpdateRate}`);
576
+ await this.debugLog(`deviceUpdateRate: ${this.deviceUpdateRate}`);
697
577
  if (this.setNewTarget) {
698
- this.setNewTargetTimer = setTimeout(() => {
699
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} setNewTarget ${this.setNewTarget} timeout`);
578
+ this.setNewTargetTimer = setTimeout(async () => {
579
+ await this.debugLog(`setNewTarget ${this.setNewTarget} timeout`);
700
580
  this.setNewTarget = false;
701
581
  }, this.deviceUpdateRate * 1000);
702
582
  }
@@ -706,130 +586,42 @@ export class Curtain extends deviceBase {
706
586
  * Handle requests to set the value of the "Target Position" characteristic
707
587
  */
708
588
  async HoldPositionSet(value) {
709
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} HoldPosition: ${value}`);
589
+ this.debugLog(`HoldPosition: ${value}`);
710
590
  this.WindowCovering.HoldPosition = value;
711
591
  this.doCurtainUpdate.next();
712
592
  }
713
593
  async updateHomeKitCharacteristics() {
714
594
  await this.setMinMax();
715
- if (this.WindowCovering.CurrentPosition === undefined || Number.isNaN(this.WindowCovering.CurrentPosition)) {
716
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
717
- }
718
- else {
719
- this.accessory.context.CurrentPosition = this.WindowCovering.CurrentPosition;
720
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, Number(this.WindowCovering.CurrentPosition));
721
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
722
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
723
- if (this.device.mqttURL) {
724
- this.mqttPublish('CurrentPosition', this.WindowCovering.CurrentPosition.toString()); // Convert to string
725
- }
726
- }
727
- if (this.WindowCovering.PositionState === undefined) {
728
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} PositionState: ${this.WindowCovering.PositionState}`);
729
- }
730
- else {
731
- if (this.device.mqttURL) {
732
- this.mqttPublish('PositionState', this.WindowCovering.PositionState.toString());
733
- }
734
- this.accessory.context.PositionState = this.WindowCovering.PositionState;
735
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, Number(this.WindowCovering.PositionState));
736
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
737
- + ` PositionState: ${this.WindowCovering.PositionState}`);
738
- }
739
- if (this.WindowCovering.TargetPosition === undefined || Number.isNaN(this.WindowCovering.TargetPosition)) {
740
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} TargetPosition: ${this.WindowCovering.TargetPosition}`);
741
- }
742
- else {
743
- if (this.device.mqttURL) {
744
- this.mqttPublish('TargetPosition', this.WindowCovering.TargetPosition.toString());
745
- }
746
- this.accessory.context.TargetPosition = this.WindowCovering.TargetPosition;
747
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, Number(this.WindowCovering.TargetPosition));
748
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
749
- + ` TargetPosition: ${this.WindowCovering.TargetPosition}`);
750
- }
751
- if (this.WindowCovering.HoldPosition === undefined) {
752
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} HoldPosition: ${this.WindowCovering.HoldPosition}`);
753
- }
754
- else {
755
- if (this.device.mqttURL) {
756
- this.mqttPublish('HoldPosition', this.WindowCovering.HoldPosition.toString());
757
- }
758
- this.accessory.context.HoldPosition = this.WindowCovering.HoldPosition;
759
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.HoldPosition, this.WindowCovering.HoldPosition);
760
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
761
- + ` HoldPosition: ${this.WindowCovering.HoldPosition}`);
762
- }
763
- if (!this.device.curtain?.hide_lightsensor) {
764
- if (this.LightSensor.CurrentAmbientLightLevel === undefined || Number.isNaN(this.LightSensor.CurrentAmbientLightLevel)) {
765
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
766
- + ` CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
767
- }
768
- else {
769
- if (this.device.mqttURL) {
770
- this.mqttPublish('CurrentAmbientLightLevel', this.LightSensor.CurrentAmbientLightLevel.toString());
771
- }
772
- this.accessory.context.CurrentAmbientLightLevel = this.LightSensor.CurrentAmbientLightLevel;
773
- this.LightSensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, this.LightSensor.CurrentAmbientLightLevel);
774
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
775
- + ` updateCharacteristic CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
776
- if (this.device.history) {
777
- this.historyService?.addEntry({
778
- time: Math.round(new Date().valueOf() / 1000),
779
- lux: this.LightSensor.CurrentAmbientLightLevel,
780
- });
781
- }
782
- }
783
- }
784
- if (this.Battery.BatteryLevel === undefined) {
785
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}`);
786
- }
787
- else {
788
- if (this.device.mqttURL) {
789
- this.mqttPublish('BatteryLevel', this.Battery.BatteryLevel.toString());
790
- }
791
- this.accessory.context.BatteryLevel = this.Battery.BatteryLevel;
792
- this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel);
793
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.Battery.BatteryLevel}`);
794
- }
795
- if (this.Battery.StatusLowBattery === undefined) {
796
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.Battery.StatusLowBattery}`);
797
- }
798
- else {
799
- if (this.device.mqttURL) {
800
- this.mqttPublish('StatusLowBattery', this.Battery.StatusLowBattery.toString());
801
- }
802
- this.accessory.context.StatusLowBattery = this.Battery.StatusLowBattery;
803
- this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery);
804
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
805
- + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
806
- }
807
- if (this.Battery.ChargingState === undefined) {
808
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ChargingState: ${this.Battery.ChargingState}`);
809
- }
810
- else {
811
- if (this.device.mqttURL) {
812
- this.mqttPublish('ChargingState', this.Battery.ChargingState.toString());
813
- }
814
- this.accessory.context.ChargingState = this.Battery.ChargingState;
815
- this.Battery.Service.updateCharacteristic(this.hap.Characteristic.ChargingState, this.Battery.ChargingState);
816
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
817
- + ` ChargingState: ${this.Battery.ChargingState}`);
595
+ // CurrentPosition
596
+ await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.CurrentPosition, this.WindowCovering.CurrentPosition, 'CurrentPosition');
597
+ // PositionState
598
+ await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.PositionState, this.WindowCovering.PositionState, 'PositionState');
599
+ // TargetPosition
600
+ await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.TargetPosition, this.WindowCovering.TargetPosition, 'TargetPosition');
601
+ // HoldPosition
602
+ await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.HoldPosition, this.WindowCovering.HoldPosition, 'HoldPosition');
603
+ // CurrentAmbientLightLevel
604
+ if (!this.device.curtain?.hide_lightsensor && this.LightSensor?.Service) {
605
+ const history = { time: Math.round(new Date().valueOf() / 1000), lux: this.LightSensor.CurrentAmbientLightLevel };
606
+ await this.updateCharacteristic(this.LightSensor?.Service, this.hap.Characteristic.CurrentAmbientLightLevel, this.LightSensor?.CurrentAmbientLightLevel, 'CurrentAmbientLightLevel', history);
818
607
  }
608
+ // BatteryLevel
609
+ await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel, 'BatteryLevel');
610
+ // StatusLowBattery
611
+ await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery, 'StatusLowBattery');
612
+ // ChargingState
613
+ await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.ChargingState, this.Battery.ChargingState, 'ChargingState');
819
614
  }
820
615
  async BLEPushConnection() {
821
616
  if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
822
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Push Changes`);
617
+ await this.warnLog('Using OpenAPI Connection to Push Changes');
823
618
  await this.openAPIpushChanges();
824
619
  }
825
620
  }
826
621
  async BLERefreshConnection(switchbot) {
827
- if (switchbot !== undefined) {
828
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot:`
829
- + ` ${JSON.stringify(switchbot)}`);
830
- }
622
+ await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${JSON.stringify(switchbot)}`);
831
623
  if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
832
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Refresh Status`);
624
+ await this.warnLog('Using OpenAPI Connection to Refresh Status');
833
625
  await this.openAPIRefreshStatus();
834
626
  }
835
627
  }
@@ -866,6 +658,40 @@ export class Curtain extends deviceBase {
866
658
  }
867
659
  return { setPositionMode, Mode };
868
660
  }
661
+ async getCurrentPostion() {
662
+ await this.setMinMax();
663
+ await this.debugLog(`CurrentPosition ${this.WindowCovering.CurrentPosition}`);
664
+ if (this.setNewTarget) {
665
+ this.infoLog('Checking Status ...');
666
+ await this.setMinMax();
667
+ if (this.WindowCovering.TargetPosition > this.WindowCovering.CurrentPosition) {
668
+ await this.debugLog(`Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
669
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
670
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
671
+ await this.debugLog(`Increasing, PositionState: ${this.WindowCovering.PositionState}`);
672
+ }
673
+ else if (this.WindowCovering.TargetPosition < this.WindowCovering.CurrentPosition) {
674
+ await this.debugLog(`Opening, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
675
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
676
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
677
+ await this.debugLog(`Decreasing, PositionState: ${this.WindowCovering.PositionState}`);
678
+ }
679
+ else {
680
+ await this.debugLog(`Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
681
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
682
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
683
+ await this.debugLog(`Stopped, PositionState: ${this.WindowCovering.PositionState}`);
684
+ }
685
+ }
686
+ else {
687
+ await this.debugLog(`Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
688
+ this.WindowCovering.TargetPosition = this.WindowCovering.CurrentPosition;
689
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
690
+ await this.debugLog(`Stopped, PositionState: ${this.WindowCovering.PositionState}`);
691
+ }
692
+ await this.debugLog(`CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition: ${this.WindowCovering.TargetPosition},`
693
+ + ` PositionState: ${this.WindowCovering.PositionState},`);
694
+ }
869
695
  async setMinMax() {
870
696
  if (this.device.curtain?.set_min) {
871
697
  if (Number(this.WindowCovering.CurrentPosition) <= this.device.curtain?.set_min) {
@@ -897,7 +723,7 @@ export class Curtain extends deviceBase {
897
723
  this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e);
898
724
  this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e);
899
725
  this.Battery.Service.updateCharacteristic(this.hap.Characteristic.ChargingState, e);
900
- if (!this.device.curtain?.hide_lightsensor) {
726
+ if (!this.device.curtain?.hide_lightsensor && this.LightSensor?.Service) {
901
727
  this.LightSensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, e);
902
728
  this.LightSensor.Service.updateCharacteristic(this.hap.Characteristic.StatusActive, e);
903
729
  }