@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
@@ -2,14 +2,18 @@
2
2
  *
3
3
  * blindtilt.ts: @switchbot/homebridge-switchbot.
4
4
  */
5
- import { interval, Subject } from 'rxjs';
6
5
  import { deviceBase } from './device.js';
7
6
  import { BlindTiltMappingMode } from '../utils.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
 
10
+ import type { devicesConfig } from '../settings.js';
11
+ import type { device } from '../types/devicelist.js';
10
12
  import type { SwitchBotPlatform } from '../platform.js';
13
+ import type { blindTiltServiceData } from '../types/bledevicestatus.js';
14
+ import type { blindTiltStatus } from '../types/devicestatus.js';
15
+ import type { blindTiltWebhookContext } from '../types/devicewebhookstatus.js';
11
16
  import type { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
12
- import type { device, devicesConfig, serviceData, deviceStatus } from '../settings.js';
13
17
 
14
18
 
15
19
  export class BlindTilt extends deviceBase {
@@ -46,8 +50,8 @@ export class BlindTilt extends deviceBase {
46
50
  setNewTargetTimer!: NodeJS.Timeout;
47
51
 
48
52
  // Updates
49
- blindTiltUpdateInProgress!: boolean;
50
- doBlindTiltUpdate!: Subject<void>;
53
+ blindTiltUpdateInProgress;
54
+ doBlindTiltUpdate: Subject<void>;
51
55
 
52
56
  constructor(
53
57
  readonly platform: SwitchBotPlatform,
@@ -101,7 +105,7 @@ export class BlindTilt extends deviceBase {
101
105
  maxValue: 100,
102
106
  validValueRanges: [0, 100],
103
107
  }).onGet(() => {
104
- return this.WindowCovering?.CurrentPosition ?? 0;
108
+ return this.WindowCovering.CurrentPosition ?? 0;
105
109
  });
106
110
 
107
111
  // Initialize WindowCovering TargetHorizontalTiltAngle Characteristic
@@ -149,10 +153,12 @@ export class BlindTilt extends deviceBase {
149
153
  // Initialize LightSensor Service
150
154
  if (device.blindTilt?.hide_lightsensor) {
151
155
  if (this.LightSensor?.Service) {
152
- this.debugLog(`${device.deviceType}: ${accessory.displayName} Removing Light Sensor Service`);
156
+ this.debugLog('Removing Light Sensor Service');
153
157
  this.LightSensor.Service = accessory.getService(this.hap.Service.LightSensor) as Service;
154
158
  accessory.removeService(this.LightSensor.Service);
155
159
  accessory.context.LightSensor = {};
160
+ } else {
161
+ this.debugLog('Light Sensor Service is already removed');
156
162
  }
157
163
  } else {
158
164
  accessory.context.LightSensor = accessory.context.LightSensor ?? {};
@@ -179,6 +185,9 @@ export class BlindTilt extends deviceBase {
179
185
  // Update Homekit
180
186
  this.updateHomeKitCharacteristics();
181
187
 
188
+ //regisiter webhook event handler
189
+ this.registerWebhook();
190
+
182
191
  // Start an update interval
183
192
  interval(this.deviceRefreshRate * 1000)
184
193
  .pipe(skipWhile(() => this.blindTiltUpdateInProgress))
@@ -186,17 +195,13 @@ export class BlindTilt extends deviceBase {
186
195
  await this.refreshStatus();
187
196
  });
188
197
 
189
- //regisiter webhook event handler
190
- this.registerWebhook(accessory, device);
191
-
192
198
  // update slide progress
193
199
  interval(this.deviceUpdateRate * 1000)
194
200
  .subscribe(async () => {
195
201
  if (this.WindowCovering.PositionState === this.hap.Characteristic.PositionState.STOPPED) {
196
202
  return;
197
203
  }
198
- this.debugLog(`${device.deviceType}: ${accessory.displayName} Refresh Status When Moving,`
199
- + ` PositionState: ${this.WindowCovering.PositionState}`);
204
+ this.debugLog(`Refresh Status When Moving, PositionState: ${this.WindowCovering.PositionState}`);
200
205
  await this.refreshStatus();
201
206
  });
202
207
 
@@ -213,9 +218,8 @@ export class BlindTilt extends deviceBase {
213
218
  try {
214
219
  await this.pushChanges();
215
220
  } catch (e: any) {
216
- this.apiError(e);
217
- this.errorLog(`${device.deviceType}: ${accessory.displayName} failed pushChanges with ${device.connectionType} Connection,`
218
- + ` Error Message: ${JSON.stringify(e.message)}`);
221
+ await this.apiError(e);
222
+ await this.errorLog(`failed pushChanges with ${device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`);
219
223
  }
220
224
  this.blindTiltUpdateInProgress = false;
221
225
  });
@@ -224,216 +228,130 @@ export class BlindTilt extends deviceBase {
224
228
  /**
225
229
  * Parse the device status from the SwitchBotBLE API
226
230
  */
227
- async BLEparseStatus(serviceData: serviceData): Promise<void> {
228
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
231
+ async BLEparseStatus(serviceData: blindTiltServiceData): Promise<void> {
232
+ await this.debugLog('BLEparseStatus');
229
233
  // CurrentPosition
230
- this.WindowCovering.CurrentPosition = 100 - Number(serviceData.position);
234
+ this.WindowCovering.CurrentPosition = 100 - Number(serviceData.tilt);
231
235
  await this.setMinMax();
232
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition ${this.WindowCovering.CurrentPosition}`);
236
+ await this.debugLog(`CurrentPosition ${this.WindowCovering.CurrentPosition}`);
233
237
  if (this.setNewTarget) {
234
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Checking Status ...`);
238
+ await this.infoLog('Checking Status ...');
235
239
  }
236
240
 
237
241
  if (this.setNewTarget && serviceData.inMotion) {
238
242
  await this.setMinMax();
239
243
  if (Number(this.WindowCovering.TargetPosition) > this.WindowCovering.CurrentPosition) {
240
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
244
+ await this.debugLog(`Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
241
245
  this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
242
246
  this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
243
- this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} INCREASING`
244
- + ` PositionState: ${this.WindowCovering.PositionState}`);
247
+ await this.debugLog(`Increasing, PositionState: ${this.WindowCovering.PositionState}`);
245
248
  } else if (Number(this.WindowCovering.TargetPosition) < this.WindowCovering.CurrentPosition) {
246
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Opening, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
249
+ await this.debugLog(`Opening, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
247
250
  this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
248
251
  this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
249
- this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} DECREASING`
250
- + ` PositionState: ${this.WindowCovering.PositionState}`);
252
+ await this.debugLog(`Decreasing, PositionState: ${this.WindowCovering.PositionState}`);
251
253
  } else {
252
- this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} Standby2,`
253
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
254
+ await this.debugLog(`Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
254
255
  this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
255
256
  this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
256
- this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} STOPPED`
257
- + ` PositionState: ${this.WindowCovering.PositionState}`);
257
+ await this.debugLog('Stopped, PositionState', this.WindowCovering.PositionState);
258
258
  }
259
259
  } else {
260
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
260
+ await this.debugLog(`Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
261
261
  this.WindowCovering.TargetPosition = this.WindowCovering.CurrentPosition;
262
262
  this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
263
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Stopped`);
263
+ await this.debugLog(`Stopped, PositionState: ${this.WindowCovering.PositionState}`);
264
264
  }
265
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition},`
266
- + ` TargetPosition: ${this.WindowCovering.TargetPosition}, PositionState: ${this.WindowCovering.PositionState},`);
265
+ await this.debugLog(`CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition: ${this.WindowCovering.TargetPosition},`
266
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
267
267
 
268
- if (!this.device.blindTilt?.hide_lightsensor) {
268
+ // CurrentAmbientLightLevel
269
+ if (!this.device.blindTilt?.hide_lightsensor && this.LightSensor?.Service) {
269
270
  const set_minLux = this.device.blindTilt?.set_minLux ?? 1;
270
271
  const set_maxLux = this.device.blindTilt?.set_maxLux ?? 6001;
271
272
  const spaceBetweenLevels = 9;
272
273
 
273
- if (this.LightSensor?.CurrentAmbientLightLevel === 0) {
274
- this.LightSensor!.CurrentAmbientLightLevel = 0.0001;
275
- }
276
274
 
277
- // Brightness
278
- switch (serviceData.lightLevel) {
279
- case 1:
280
- this.LightSensor!.CurrentAmbientLightLevel = set_minLux;
281
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
282
- break;
283
- case 2:
284
- this.LightSensor!.CurrentAmbientLightLevel = (set_maxLux - set_minLux) / spaceBetweenLevels;
285
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel},`
286
- + ` Calculation: ${(set_maxLux - set_minLux) / spaceBetweenLevels}`);
287
- break;
288
- case 3:
289
- this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 2;
290
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
291
- break;
292
- case 4:
293
- this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 3;
294
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
295
- break;
296
- case 5:
297
- this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 4;
298
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
299
- break;
300
- case 6:
301
- this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 5;
302
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
303
- break;
304
- case 7:
305
- this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 6;
306
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
307
- break;
308
- case 8:
309
- this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 7;
310
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
311
- break;
312
- case 9:
313
- this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 8;
314
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
315
- break;
316
- case 10:
317
- default:
318
- this.LightSensor!.CurrentAmbientLightLevel = set_maxLux;
319
- this.debugLog();
320
- }
321
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel},`
322
- + ` CurrentAmbientLightLevel: ${this.LightSensor!.CurrentAmbientLightLevel}`);
275
+ await this.getLightLevel(serviceData.lightLevel, set_minLux, set_maxLux, spaceBetweenLevels);
276
+ await this.debugLog(`LightLevel: ${serviceData.lightLevel}, CurrentAmbientLightLevel: ${this.LightSensor!.CurrentAmbientLightLevel}`);
323
277
  }
324
- // Battery
278
+
279
+ // BatteryLevel
325
280
  this.Battery.BatteryLevel = Number(serviceData.battery);
326
- if (this.Battery.BatteryLevel < 10) {
327
- this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
328
- } else {
329
- this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
330
- }
331
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
332
- + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
333
- }
281
+ await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`);
334
282
 
283
+ // StatusLowBattery
284
+ this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
285
+ ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
286
+ await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`);
287
+ };
335
288
 
336
289
  /**
337
290
  * Parse the device status from the SwitchBot OpenAPI
338
291
  */
339
- async openAPIparseStatus(deviceStatus: deviceStatus): Promise<void> {
340
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
341
-
342
- const [homekitPosition, homekitTiltAngle] = this.mapDeviceValuesToHomekitValues(Number(deviceStatus.body.slidePosition),
343
- String(deviceStatus.body.direction));
344
- this.debugLog(` device: ${deviceStatus.body.slidePosition} => HK: ${homekitPosition}`);
292
+ async openAPIparseStatus(deviceStatus: blindTiltStatus): Promise<void> {
293
+ await this.debugLog('openAPIparseStatus');
345
294
 
346
- this.WindowCovering!.CurrentPosition = homekitPosition;
347
295
  // CurrentPosition
348
- await this.setMinMax();
349
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
296
+ await this.getCurrentPosttionDirection(deviceStatus.direction, deviceStatus.slidePosition);
350
297
 
351
- if (homekitTiltAngle) {
352
- this.WindowCovering.CurrentHorizontalTiltAngle = homekitTiltAngle!;
353
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
354
- + ` CurrentHorizontalTiltAngle: ${this.WindowCovering.CurrentHorizontalTiltAngle}`);
298
+ if (!this.device.blindTilt?.hide_lightsensor && this.LightSensor?.Service) {
299
+ const set_minLux = this.device.blindTilt?.set_minLux ?? 1;
300
+ const set_maxLux = this.device.blindTilt?.set_maxLux ?? 6001;
301
+ const lightLevel = deviceStatus.lightLevel === 'bright' ? set_maxLux : set_minLux;
302
+ this.LightSensor.CurrentAmbientLightLevel = await this.getLightLevel(lightLevel, set_minLux, set_maxLux, 2);
303
+ await this.debugLog(`LightLevel: ${deviceStatus.lightLevel}, CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
355
304
  }
356
305
 
357
- if (this.setNewTarget) {
358
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Checking Status ...`);
359
- }
306
+ // BatteryLevel
307
+ this.Battery.BatteryLevel = Number(deviceStatus.battery);
308
+ await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`);
360
309
 
361
- if (this.setNewTarget && deviceStatus.body.moving) {
362
- await this.setMinMax();
363
- if (this.WindowCovering.TargetPosition > this.WindowCovering.CurrentPosition
364
- || (homekitTiltAngle && this.WindowCovering.TargetHorizontalTiltAngle !== this.WindowCovering.CurrentHorizontalTiltAngle)) {
365
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition} `);
366
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
367
- this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
368
- this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} INCREASING`
369
- + ` PositionState: ${this.WindowCovering.PositionState}`);
370
- } else if (this.WindowCovering.TargetPosition < this.WindowCovering.CurrentPosition) {
371
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Opening, CurrentPosition: ${this.WindowCovering.CurrentPosition} `);
372
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
373
- this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
374
- this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} DECREASING`
375
- + ` PositionState: ${this.WindowCovering.PositionState}`);
310
+ // StatusLowBattery
311
+ this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
312
+ ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
313
+ await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`);
314
+
315
+ // Firmware Version
316
+ const version = deviceStatus.version.toString();
317
+ await this.debugLog(`Firmware Version: ${version.replace(/^V|-.*$/g, '')}`);
318
+ if (deviceStatus.version) {
319
+ let deviceVersion: string;
320
+ if (version?.includes('.') === false) {
321
+ const replace = version?.replace(/^V|-.*$/g, '');
322
+ const match = replace?.match(/.{1,1}/g);
323
+ const blindTiltVersion = match?.join('.') ?? '0.0.0';
324
+ deviceVersion = blindTiltVersion;
376
325
  } else {
377
- this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} Standby because reached position,`
378
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
379
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
380
- this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
381
- this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} STOPPED`
382
- + ` PositionState: ${this.WindowCovering.PositionState}`);
383
- }
384
- } else {
385
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Standby because device not moving,`
386
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
387
- this.WindowCovering.TargetPosition = this.WindowCovering.CurrentPosition;
388
- if (homekitTiltAngle) {
389
- this.WindowCovering.TargetHorizontalTiltAngle = this.WindowCovering.CurrentHorizontalTiltAngle;
326
+ deviceVersion = version.replace(/^V|-.*$/g, '') ?? '0.0.0';
390
327
  }
391
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
392
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Stopped`);
393
- }
394
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition},`
395
- + ` TargetPosition: ${this.WindowCovering.TargetPosition}, PositionState: ${this.WindowCovering.PositionState},`);
396
- if (!this.device.blindTilt?.hide_lightsensor) {
397
- const set_minLux = this.device.blindTilt?.set_minLux ?? 1;
398
- const set_maxLux = this.device.blindTilt?.set_maxLux ?? 6001;
399
- // Brightness
400
- switch (deviceStatus.body.brightness) {
401
- case 'dim':
402
- this.LightSensor!.CurrentAmbientLightLevel = set_minLux;
403
- break;
404
- case 'bright':
405
- default:
406
- this.LightSensor!.CurrentAmbientLightLevel = set_maxLux;
407
- }
408
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
409
- + ` CurrentAmbientLightLevel: ${this.LightSensor!.CurrentAmbientLightLevel}`);
328
+ this.accessory
329
+ .getService(this.hap.Service.AccessoryInformation)!
330
+ .setCharacteristic(this.hap.Characteristic.HardwareRevision, deviceVersion)
331
+ .setCharacteristic(this.hap.Characteristic.FirmwareRevision, deviceVersion)
332
+ .getCharacteristic(this.hap.Characteristic.FirmwareRevision)
333
+ .updateValue(deviceVersion);
334
+ this.accessory.context.deviceVersion = deviceVersion;
335
+ await this.debugLog(`deviceVersion: ${this.accessory.context.deviceVersion}`);
410
336
  }
337
+ }
411
338
 
339
+ async parseStatusWebhook(context: blindTiltWebhookContext): Promise<void> {
340
+ await this.debugLog('parseStatusWebhook');
341
+ await this.debugLog(`(slidePosition, battery, version) = Webhook:(${context.direction}, ${context.slidePosition}, ${context.battery},`
342
+ + `${context.version}, current:(${this.WindowCovering.CurrentHorizontalTiltAngle}, ${this.WindowCovering.CurrentPosition},`
343
+ + ` ${this.Battery.BatteryLevel}, ${this.accessory.context.deviceVersion})`);
344
+ // CurrentPosition and CurrentHorizontalTiltAngle
345
+ await this.getCurrentPosttionDirection(context.direction, context.slidePosition);
412
346
  // BatteryLevel
413
- this.Battery.BatteryLevel = Number(deviceStatus.body.battery);
414
- if (this.Battery.BatteryLevel < 10) {
415
- this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
416
- } else {
417
- this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
418
- }
419
- if (Number.isNaN(this.Battery.BatteryLevel)) {
420
- this.Battery.BatteryLevel = 100;
421
- }
422
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
423
- + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
424
-
347
+ this.Battery.BatteryLevel = context.battery;
348
+ await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`);
349
+ // StatusLowBattery
350
+ this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
351
+ ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
352
+ await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`);
425
353
  // Firmware Version
426
- const version = deviceStatus.body.version?.toString();
427
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Firmware Version: ${version?.replace(/^V|-.*$/g, '')}`);
428
- let deviceVersion: string;
429
- if (version?.includes('.') === false) {
430
- const replace = version?.replace(/^V|-.*$/g, '');
431
- const match = replace?.match(/.{1,1}/g);
432
- const blindTiltVersion = match?.join('.') ?? '0.0.0';
433
- deviceVersion = blindTiltVersion;
434
- } else {
435
- deviceVersion = version?.replace(/^V|-.*$/g, '') ?? '0.0.0';
436
- }
354
+ const deviceVersion = context.version.replace(/^V|-.*$/g, '') ?? '0.0.0';
437
355
  this.accessory
438
356
  .getService(this.hap.Service.AccessoryInformation)!
439
357
  .setCharacteristic(this.hap.Characteristic.HardwareRevision, deviceVersion)
@@ -441,40 +359,42 @@ export class BlindTilt extends deviceBase {
441
359
  .getCharacteristic(this.hap.Characteristic.FirmwareRevision)
442
360
  .updateValue(deviceVersion);
443
361
  this.accessory.context.deviceVersion = deviceVersion;
444
- this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceVersion: ${this.accessory.context.deviceVersion}`);
362
+ await this.debugSuccessLog(`deviceVersion: ${this.accessory.context.deviceVersion}`);
445
363
  }
446
364
 
365
+ /**
366
+ * Asks the SwitchBot API for the latest device information
367
+ */
447
368
  async refreshStatus(): Promise<void> {
448
369
  if (!this.device.enableCloudService && this.OpenAPI) {
449
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} refreshStatus enableCloudService: ${this.device.enableCloudService}`);
370
+ await this.errorLog(`refreshStatus enableCloudService: ${this.device.enableCloudService}`);
450
371
  } else if (this.BLE) {
451
372
  await this.BLERefreshStatus();
452
373
  } else if (this.OpenAPI && this.platform.config.credentials?.token) {
453
374
  await this.openAPIRefreshStatus();
454
375
  } else {
455
376
  await this.offlineOff();
456
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
457
- + ` ${this.device.connectionType}, refreshStatus will not happen.`);
377
+ await this.debugWarnLog(`Connection Type: ${this.device.connectionType}, refreshStatus will not happen.`);
458
378
  }
459
379
  }
460
380
 
461
381
  async BLERefreshStatus(): Promise<void> {
462
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
382
+ await this.debugLog('BLERefreshStatus');
463
383
  const switchbot = await this.switchbotBLE();
464
384
 
465
385
  if (switchbot === undefined) {
466
386
  await this.BLERefreshConnection(switchbot);
467
387
  } else {
468
- // Start to monitor advertisement packets
469
- (async () => {
470
388
  // Start to monitor advertisement packets
471
- const serviceData: serviceData = await this.monitorAdvertisementPackets(switchbot);
389
+ (async () => {
390
+ // Start to monitor advertisement packets
391
+ const serviceData = await this.monitorAdvertisementPackets(switchbot) as unknown as blindTiltServiceData;
472
392
  // Update HomeKit
473
- if (serviceData.model !== '' && serviceData.modelName !== '') {
393
+ if (serviceData.model === SwitchBotBLEModel.BlindTilt && serviceData.modelName === SwitchBotBLEModelName.BlindTilt) {
474
394
  await this.BLEparseStatus(serviceData);
475
395
  await this.updateHomeKitCharacteristics();
476
396
  } else {
477
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed to get serviceData, serviceData: ${serviceData}`);
397
+ await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
478
398
  await this.BLERefreshConnection(switchbot);
479
399
  }
480
400
  })();
@@ -482,63 +402,52 @@ export class BlindTilt extends deviceBase {
482
402
  }
483
403
 
484
404
  async openAPIRefreshStatus(): Promise<void> {
485
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
405
+ await this.debugLog('openAPIRefreshStatus');
486
406
  try {
487
407
  const { body, statusCode } = await this.deviceRefreshStatus();
488
408
  const deviceStatus: any = await body.json();
489
- await this.refreshStatusCodes(statusCode, deviceStatus);;
490
- if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
491
- await this.successfulRefreshStatus(statusCode, deviceStatus);
492
- await this.openAPIparseStatus(deviceStatus);
409
+ await this.debugLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);;
410
+ if (await this.successfulStatusCodes(statusCode, deviceStatus)) {
411
+ await this.debugSuccessLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
412
+ await this.openAPIparseStatus(deviceStatus.body);
493
413
  await this.updateHomeKitCharacteristics();
494
414
  } else {
495
- await this.statusCodes(statusCode, deviceStatus);
415
+ await this.debugWarnLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
416
+ await this.debugWarnLog(statusCode, deviceStatus);
496
417
  }
497
418
  } catch (e: any) {
498
- this.apiError(e);
499
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
500
- + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
419
+ await this.apiError(e);
420
+ await this.errorLog(`failed openAPIRefreshStatus with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`);
501
421
  }
502
422
  }
503
423
 
504
- async registerWebhook(accessory: PlatformAccessory, device: device & devicesConfig) {
505
- if (device.webhook) {
506
- this.debugLog(`${device.deviceType}: ${accessory.displayName} is listening webhook.`);
507
- this.platform.webhookEventHandler[this.device.deviceId] = async (context) => {
424
+ async registerWebhook(): Promise<void> {
425
+ if (this.device.webhook) {
426
+ await this.debugLog('is listening webhook.');
427
+ this.platform.webhookEventHandler[this.device.deviceId] = async (context: blindTiltWebhookContext) => {
508
428
  try {
509
- this.debugLog(`${device.deviceType}: ${accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
510
- const { slidePosition, battery, lightLevel } = context;
511
- const { CurrentPosition } = this.WindowCovering;
512
- const { BatteryLevel } = this.Battery;
513
- const { CurrentAmbientLightLevel } = this.LightSensor ?? {};
514
- this.debugLog(`${device.deviceType}: ${accessory.displayName} (slidePosition, battery, lightLevel) = Webhook:(${slidePosition}, ${battery},`
515
- + ` ${lightLevel}), current:(${CurrentPosition}, ${BatteryLevel}, ${CurrentAmbientLightLevel})`);
516
- this.WindowCovering.CurrentPosition = slidePosition;
517
- this.Battery.BatteryLevel = battery;
518
- if (!device.blindTilt?.hide_lightsensor) {
519
- this.LightSensor!.CurrentAmbientLightLevel = lightLevel;
520
- }
521
- this.updateHomeKitCharacteristics();
429
+ await this.debugLog(`received Webhook: ${JSON.stringify(context)}`);
430
+ await this.parseStatusWebhook(context);
431
+ await this.updateHomeKitCharacteristics();
522
432
  } catch (e: any) {
523
- this.errorLog(`${device.deviceType}: ${accessory.displayName} failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
433
+ await this.errorLog(`failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
524
434
  }
525
435
  };
526
436
  } else {
527
- this.debugLog(`${device.deviceType}: ${accessory.displayName} is not listening webhook.`);
437
+ await this.debugLog('is not listening webhook.');
528
438
  }
529
439
  }
530
440
 
531
441
  async pushChanges(): Promise<void> {
532
442
  if (!this.device.enableCloudService && this.OpenAPI) {
533
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} pushChanges enableCloudService: ${this.device.enableCloudService}`);
443
+ await this.errorLog(`pushChanges enableCloudService: ${this.device.enableCloudService}`);
534
444
  } else if (this.BLE) {
535
445
  await this.BLEpushChanges();
536
446
  } else if (this.OpenAPI && this.platform.config.credentials?.token) {
537
447
  await this.openAPIpushChanges();
538
448
  } else {
539
449
  await this.offlineOff();
540
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
541
- + ` ${this.device.connectionType}, pushChanges will not happen.`);
450
+ await this.debugWarnLog(`Connection Type: ${this.device.connectionType}, pushChanges will not happen.`);
542
451
  }
543
452
  // Refresh the status from the API
544
453
  interval(15000)
@@ -550,18 +459,17 @@ export class BlindTilt extends deviceBase {
550
459
  }
551
460
 
552
461
  async BLEpushChanges(): Promise<void> {
553
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
462
+ await this.debugLog('BLEpushChanges');
554
463
  if (this.WindowCovering.TargetPosition !== this.WindowCovering.CurrentPosition) {
555
- const switchbot = await this.platform.connectBLE();
556
- // Convert to BLE Address
464
+ await this.debugLog(`BLEpushChanges On: ${this.WindowCovering.TargetPosition} OnCached: ${this.WindowCovering.CurrentPosition}`);
465
+ const switchbot = await this.platform.connectBLE(this.accessory, this.device);
557
466
  await this.convertBLEAddress();
558
467
  const { setPositionMode, Mode }: { setPositionMode: number; Mode: string; } = await this.setPerformance();
559
- this.debugLog(`${this.accessory.displayName} Mode: ${Mode}`);
468
+ await this.debugLog(`Mode: ${Mode}, setPositionMode: ${setPositionMode}`);
560
469
  if (switchbot !== false) {
561
470
  switchbot
562
471
  .discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac })
563
472
  .then(async (device_list: any) => {
564
- this.infoLog(`${this.accessory.displayName} Target Position: ${this.WindowCovering.TargetPosition}`);
565
473
  return await this.retryBLE({
566
474
  max: await this.maxRetryBLE(),
567
475
  fn: async () => {
@@ -569,29 +477,27 @@ export class BlindTilt extends deviceBase {
569
477
  },
570
478
  });
571
479
  })
572
- .then(() => {
573
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
574
- this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
575
- + `Target Position: ${this.WindowCovering.TargetPosition} sent over BLE, sent successfully`);
480
+ .then(async () => {
481
+ await this.successLog(`TargetPostion: ${this.WindowCovering.TargetPosition} sent over SwitchBot BLE, sent successfully`);
482
+ await this.updateHomeKitCharacteristics();
576
483
  })
577
484
  .catch(async (e: any) => {
578
- this.apiError(e);
579
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
580
- + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
485
+ await this.apiError(e);
486
+ await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`);
581
487
  await this.BLEPushConnection();
582
488
  });
583
489
  } else {
584
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection`);
490
+ await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
585
491
  await this.BLEPushConnection();
586
492
  }
587
493
  } else {
588
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges, CurrentPosition & TargetPosition Are the Same.`
589
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition ${this.WindowCovering.TargetPosition}`);
494
+ await this.debugLog(`No changes (BLEpushChanges), TargetPosition: ${this.WindowCovering.TargetPosition},`
495
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
590
496
  }
591
497
  }
592
498
 
593
499
  async openAPIpushChanges(): Promise<void> {
594
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
500
+ await this.debugLog('openAPIpushChanges');
595
501
  const hasDifferentAndRelevantHorizontalTiltAngle =
596
502
  this.mappingMode === BlindTiltMappingMode.UseTiltForDirection
597
503
  && this.WindowCovering.TargetHorizontalTiltAngle !== this.WindowCovering.CurrentHorizontalTiltAngle;
@@ -599,11 +505,10 @@ export class BlindTilt extends deviceBase {
599
505
  || hasDifferentAndRelevantHorizontalTiltAngle || this.device.disableCaching) {
600
506
  const [direction, position] = this.mapHomekitValuesToDeviceValues(Number(this.WindowCovering.TargetPosition),
601
507
  Number(this.WindowCovering.TargetHorizontalTiltAngle));
602
- const { Mode }: { setPositionMode: number; Mode: string; } = await this.setPerformance();
603
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
604
- + ` Pushing ${this.WindowCovering.TargetPosition} (device = ${direction};${position})`);
605
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Mode: ${Mode}`);
606
- let bodyChange = '';
508
+ const { Mode, setPositionMode }: { setPositionMode: number; Mode: string; } = await this.setPerformance();
509
+ await this.debugLog(`Pushing ${this.WindowCovering.TargetPosition} (device = ${direction};${position})`);
510
+ await this.debugLog(`Mode: ${Mode}, setPositionMode: ${setPositionMode}`);
511
+ let bodyChange: string;
607
512
  if (position === 100) {
608
513
  bodyChange = JSON.stringify({
609
514
  command: 'fullyOpen',
@@ -623,28 +528,27 @@ export class BlindTilt extends deviceBase {
623
528
  commandType: 'command',
624
529
  });
625
530
  }
626
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
531
+ await this.debugLog(`SwitchBot OpenAPI bodyChange: ${JSON.stringify(bodyChange)}`);
627
532
  try {
628
533
  const { body, statusCode } = await this.pushChangeRequest(bodyChange);
629
534
  const deviceStatus: any = await body.json();
630
- await this.pushStatusCodes(statusCode, deviceStatus);
631
- if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
632
- await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
535
+ await this.debugLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
536
+ if (await this.successfulStatusCodes(statusCode, deviceStatus)) {
537
+ await this.debugSuccessLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
633
538
  await this.updateHomeKitCharacteristics();
634
539
  } else {
635
540
  await this.statusCode(statusCode);
636
541
  await this.statusCode(deviceStatus.statusCode);
637
542
  }
638
543
  } catch (e: any) {
639
- this.apiError(e);
640
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
641
- + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
544
+ await this.apiError(e);
545
+ await this.errorLog(`failed openAPIpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`);
642
546
  }
643
547
  } else {
644
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No OpenAPI Changes, CurrentPosition & TargetPosition Are the Same.`
645
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition ${this.WindowCovering.TargetPosition}`
646
- + ` CurrentHorizontalTiltAngle: ${this.WindowCovering.CurrentHorizontalTiltAngle},`
647
- + ` TargetPosition ${this.WindowCovering.TargetHorizontalTiltAngle}`);
548
+ await this.debugLog(`No changes (openAPIpushChanges), TargetPosition: ${this.WindowCovering.TargetPosition},`
549
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
550
+ await this.debugLog(`No changes (openAPIpushChanges), TargetHorizontalTiltAngle: ${this.WindowCovering.TargetHorizontalTiltAngle},`
551
+ + ` CurrentHorizontalTiltAngle: ${this.WindowCovering.CurrentHorizontalTiltAngle}`);
648
552
  }
649
553
  }
650
554
 
@@ -652,57 +556,49 @@ export class BlindTilt extends deviceBase {
652
556
  * Handle requests to set the value of the "Target Horizontal Tilt" characteristic
653
557
  */
654
558
  async TargetHorizontalTiltAngleSet(value: CharacteristicValue): Promise<void> {
655
- if (this.WindowCovering.TargetHorizontalTiltAngle === this.accessory.context.TargetHorizontalTiltAngle) {
656
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set TargetHorizontalTiltAngle: ${value}`);
559
+ if (this.WindowCovering.TargetHorizontalTiltAngle !== this.accessory.context.TargetHorizontalTiltAngle) {
560
+ await this.debugLog(`Set TargetHorizontalTiltAngle: ${value}`);
657
561
  } else {
658
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetHorizontalTiltAngle: ${value}`);
562
+ await this.debugLog(`No changes, TargetHorizontalTiltAngle: ${value}`);
659
563
  }
660
564
 
661
565
  //value = value < 0 ? -90 : 90;
662
566
  this.WindowCovering.TargetHorizontalTiltAngle = value;
663
- if (this.device.mqttURL) {
664
- this.mqttPublish('TargetHorizontalTiltAngle', this.WindowCovering.TargetHorizontalTiltAngle.toString());
665
- }
666
-
667
- this.startUpdatingBlindTiltIfNeeded();
567
+ await this.mqtt('TargetHorizontalTiltAngle', this.WindowCovering.TargetHorizontalTiltAngle);
568
+ await this.startUpdatingBlindTiltIfNeeded();
668
569
  }
669
570
 
670
571
  /**
671
572
  * Handle requests to set the value of the "Target Position" characteristic
672
573
  */
673
574
  async TargetPositionSet(value: CharacteristicValue): Promise<void> {
674
- if (this.WindowCovering.TargetPosition === this.accessory.context.TargetPosition) {
675
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set TargetPosition: ${value}`);
575
+ if (this.WindowCovering.TargetPosition !== this.accessory.context.TargetPosition) {
576
+ await this.debugLog(`Set TargetPosition: ${value}`);
676
577
  } else {
677
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetPosition: ${value}`);
578
+ await this.debugLog(`No changes, TargetPosition: ${value}`);
678
579
  }
679
580
 
680
581
  this.WindowCovering.TargetPosition = value;
681
- if (this.device.mqttURL) {
682
- this.mqttPublish('TargetPosition', this.WindowCovering.TargetPosition.toString());
683
- }
684
- this.startUpdatingBlindTiltIfNeeded();
582
+ await this.mqtt('TargetPosition', this.WindowCovering.TargetPosition);
583
+ await this.startUpdatingBlindTiltIfNeeded();
685
584
  }
686
585
 
687
586
  async startUpdatingBlindTiltIfNeeded(): Promise<void> {
688
587
  await this.setMinMax();
689
- this.debugLog('setMinMax');
588
+ await this.debugLog('setMinMax');
690
589
  if (this.WindowCovering.TargetPosition > this.WindowCovering.CurrentPosition
691
590
  || this.WindowCovering.TargetHorizontalTiltAngle !== this.WindowCovering.CurrentHorizontalTiltAngle) {
692
591
  this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
693
592
  this.setNewTarget = true;
694
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${this.WindowCovering.CurrentPosition},`
695
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
593
+ await this.debugLog(`value: ${this.WindowCovering.CurrentPosition}, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
696
594
  } else if (this.WindowCovering.TargetPosition < this.WindowCovering.CurrentPosition) {
697
595
  this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
698
596
  this.setNewTarget = true;
699
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${this.WindowCovering.CurrentPosition},`
700
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
597
+ await this.debugLog(`value: ${this.WindowCovering.CurrentPosition}, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
701
598
  } else {
702
599
  this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
703
600
  this.setNewTarget = false;
704
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${this.WindowCovering.CurrentPosition},`
705
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
601
+ await this.debugLog(`value: ${this.WindowCovering.CurrentPosition}, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
706
602
  }
707
603
  this.WindowCovering.Service.setCharacteristic(this.hap.Characteristic.PositionState, this.WindowCovering.PositionState);
708
604
  this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
@@ -712,10 +608,10 @@ export class BlindTilt extends deviceBase {
712
608
  * The minimum time depends on the network control latency.
713
609
  */
714
610
  clearTimeout(this.setNewTargetTimer);
715
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateRate: ${this.deviceUpdateRate}`);
611
+ await this.debugLog(`deviceUpdateRate: ${this.deviceUpdateRate}`);
716
612
  if (this.setNewTarget) {
717
- this.setNewTargetTimer = setTimeout(() => {
718
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} setNewTarget ${this.setNewTarget} timeout`);
613
+ this.setNewTargetTimer = setTimeout(async () => {
614
+ await this.debugLog(`setNewTarget ${this.setNewTarget} timeout`);
719
615
  this.setNewTarget = false;
720
616
  }, this.deviceUpdateRate * 1000);
721
617
  }
@@ -726,120 +622,46 @@ export class BlindTilt extends deviceBase {
726
622
  await this.setMinMax();
727
623
  // CurrentHorizontalTiltAngle
728
624
  if (this.mappingMode === BlindTiltMappingMode.UseTiltForDirection) {
729
- if (this.WindowCovering.CurrentHorizontalTiltAngle === undefined || Number.isNaN(this.WindowCovering.CurrentHorizontalTiltAngle)) {
730
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
731
- + ` CurrentHorizontalTiltAngle: ${this.WindowCovering.CurrentHorizontalTiltAngle}`);
732
- } else {
733
- if (this.device.mqttURL) {
734
- this.mqttPublish('CurrentHorizontalTiltAngle', this.WindowCovering.CurrentHorizontalTiltAngle.toString());
735
- }
736
- this.accessory.context.CurrentHorizontalTiltAngle = this.WindowCovering.CurrentHorizontalTiltAngle;
737
- this.WindowCovering.Service.updateCharacteristic(
738
- this.hap.Characteristic.CurrentHorizontalTiltAngle,
739
- Number(this.WindowCovering.CurrentHorizontalTiltAngle));
740
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}
741
- updateCharacteristic CurrentHorizontalTiltAngle: ${this.WindowCovering.CurrentHorizontalTiltAngle}`);
742
- }
625
+ await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.CurrentHorizontalTiltAngle,
626
+ this.WindowCovering.CurrentHorizontalTiltAngle, 'CurrentHorizontalTiltAngle');
743
627
  }
744
628
  // CurrentPosition
745
- if (this.WindowCovering.CurrentPosition === undefined || Number.isNaN(this.WindowCovering.CurrentPosition)) {
746
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
747
- } else {
748
- if (this.device.mqttURL) {
749
- this.mqttPublish('CurrentPosition', this.WindowCovering.CurrentPosition.toString());
750
- }
751
- this.accessory.context.CurrentPosition = this.WindowCovering.CurrentPosition;
752
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, Number(this.WindowCovering.CurrentPosition));
753
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
754
- + ` updateCharacteristic CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
755
- }
629
+ await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.CurrentPosition,
630
+ this.WindowCovering.CurrentPosition, 'CurrentPosition');
756
631
  // PositionState
757
- if (this.WindowCovering.PositionState === undefined) {
758
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} PositionState: ${this.WindowCovering.PositionState}`);
759
- } else {
760
- if (this.device.mqttURL) {
761
- this.mqttPublish('PositionState', this.WindowCovering.PositionState.toString());
762
- }
763
- this.accessory.context.PositionState = this.WindowCovering.PositionState;
764
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, Number(this.WindowCovering.PositionState));
765
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
766
- + ` PositionState: ${this.WindowCovering.PositionState}`);
767
- }
632
+ await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.PositionState,
633
+ this.WindowCovering.PositionState, 'PositionState');
768
634
  // TargetPosition
769
- if (this.WindowCovering.TargetPosition === undefined || Number.isNaN(this.WindowCovering.TargetPosition)) {
770
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} TargetPosition: ${this.WindowCovering.TargetPosition}`);
771
- } else {
772
- if (this.device.mqttURL) {
773
- this.mqttPublish('TargetPosition', this.WindowCovering.TargetPosition.toString());
774
- }
775
- this.accessory.context.TargetPosition = this.WindowCovering.TargetPosition;
776
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, Number(this.WindowCovering.TargetPosition));
777
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
778
- + ` TargetPosition: ${this.WindowCovering.TargetPosition}`);
779
- }
635
+ await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.TargetPosition,
636
+ this.WindowCovering.TargetPosition, 'TargetPosition');
780
637
  // CurrentAmbientLightLevel
781
- if (!this.device.blindTilt?.hide_lightsensor) {
782
- if (this.LightSensor!.CurrentAmbientLightLevel === undefined || Number.isNaN(this.LightSensor!.CurrentAmbientLightLevel)) {
783
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
784
- + ` CurrentAmbientLightLevel: ${this.LightSensor!.CurrentAmbientLightLevel}`);
785
- } else {
786
- if (this.device.mqttURL) {
787
- this.mqttPublish('CurrentAmbientLightLevel', this.LightSensor!.CurrentAmbientLightLevel.toString());
788
- }
789
- this.accessory.context.CurrentAmbientLightLevel = this.LightSensor!.CurrentAmbientLightLevel;
790
- this.LightSensor!.Service.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, this.LightSensor!.CurrentAmbientLightLevel);
791
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
792
- + ` updateCharacteristic CurrentAmbientLightLevel: ${this.LightSensor!.CurrentAmbientLightLevel}`);
793
- }
638
+ if (!this.device.blindTilt?.hide_lightsensor && this.LightSensor?.Service) {
639
+ const history = { time: Math.round(new Date().valueOf() / 1000), lux: this.LightSensor.CurrentAmbientLightLevel };
640
+ await this.updateCharacteristic(this.LightSensor?.Service, this.hap.Characteristic.CurrentAmbientLightLevel,
641
+ this.LightSensor?.CurrentAmbientLightLevel, 'CurrentAmbientLightLevel', history);
794
642
  }
795
643
  // BatteryLevel
796
- if (this.Battery.BatteryLevel === undefined) {
797
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}`);
798
- } else {
799
- if (this.device.mqttURL) {
800
- this.mqttPublish('BatteryLevel', this.Battery.BatteryLevel.toString());
801
- }
802
- this.accessory.context.BatteryLevel = this.Battery.BatteryLevel;
803
- this.Battery?.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel);
804
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.Battery.BatteryLevel}`);
805
- }
644
+ await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.BatteryLevel,
645
+ this.Battery.BatteryLevel, 'BatteryLevel');
806
646
  // StatusLowBattery
807
- if (this.Battery.StatusLowBattery === undefined) {
808
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.Battery.StatusLowBattery}`);
809
- } else {
810
- if (this.device.mqttURL) {
811
- this.mqttPublish('StatusLowBattery', this.Battery.StatusLowBattery.toString());
812
- }
813
- this.accessory.context.StatusLowBattery = this.Battery.StatusLowBattery;
814
- this.Battery?.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery);
815
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
816
- + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
817
- }
818
- if (this.Battery.ChargingState === undefined) {
819
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ChargingState: ${this.Battery.ChargingState}`);
820
- } else {
821
- if (this.device.mqttURL) {
822
- this.mqttPublish('ChargingState', this.Battery.ChargingState.toString());
823
- }
824
- this.accessory.context.ChargingState = this.Battery.ChargingState;
825
- this.Battery.Service.updateCharacteristic(this.hap.Characteristic.ChargingState, this.Battery.ChargingState);
826
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
827
- + ` ChargingState: ${this.Battery.ChargingState}`);
828
- }
647
+ await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.StatusLowBattery,
648
+ this.Battery.StatusLowBattery, 'StatusLowBattery');
649
+ // ChargingState
650
+ await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.ChargingState,
651
+ this.Battery.ChargingState, 'ChargingState');
829
652
  }
830
653
 
831
654
  async BLEPushConnection() {
832
655
  if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
833
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Push Changes`);
656
+ await this.warnLog('Using OpenAPI Connection to Push Changes');
834
657
  await this.openAPIpushChanges();
835
658
  }
836
659
  }
837
660
 
838
661
  async BLERefreshConnection(switchbot: any): Promise<void> {
839
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot:`
840
- + ` ${JSON.stringify(switchbot)}`);
662
+ await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${JSON.stringify(switchbot)}`);
841
663
  if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
842
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Refresh Status`);
664
+ await this.warnLog('Using OpenAPI Connection to Refresh Status');
843
665
  await this.openAPIRefreshStatus();
844
666
  }
845
667
  }
@@ -884,6 +706,11 @@ export class BlindTilt extends deviceBase {
884
706
  this.WindowCovering.CurrentPosition = 100;
885
707
  }
886
708
  }
709
+ if (this.device.history) {
710
+ const motion = this.accessory.getService(this.hap.Service.MotionSensor);
711
+ const state = Number(this.WindowCovering.CurrentPosition) > 0 ? 1 : 0;
712
+ motion?.updateCharacteristic(this.hap.Characteristic.MotionDetected, state);
713
+ }
887
714
 
888
715
  if (this.mappingMode === BlindTiltMappingMode.UseTiltForDirection) {
889
716
  this.WindowCovering.CurrentHorizontalTiltAngle = Number(this.WindowCovering.CurrentHorizontalTiltAngle) < 0 ? -90 : 90;
@@ -909,10 +736,61 @@ export class BlindTilt extends deviceBase {
909
736
  this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e);
910
737
  this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e);
911
738
  this.Battery.Service.updateCharacteristic(this.hap.Characteristic.ChargingState, e);
912
- if (!this.device.blindTilt?.hide_lightsensor) {
913
- this.LightSensor!.Service.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, e);
914
- this.LightSensor!.Service.updateCharacteristic(this.hap.Characteristic.StatusActive, e);
739
+ if (!this.device.blindTilt?.hide_lightsensor && this.LightSensor?.Service) {
740
+ this.LightSensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, e);
741
+ this.LightSensor.Service.updateCharacteristic(this.hap.Characteristic.StatusActive, e);
742
+ }
743
+ }
744
+
745
+ async getCurrentPosttionDirection(
746
+ direction: blindTiltStatus['direction'] | blindTiltWebhookContext['direction'],
747
+ slidePosition: blindTiltStatus['slidePosition'] | blindTiltWebhookContext['slidePosition'],
748
+ ) {
749
+ const [homekitPosition, homekitTiltAngle] = this.mapDeviceValuesToHomekitValues(Number(slidePosition),
750
+ String(direction));
751
+ await this.debugLog(`Slide Position: ${slidePosition}`);
752
+ await this.debugLog(`Homekit Position: ${homekitPosition}`);
753
+
754
+ this.WindowCovering.CurrentPosition = homekitPosition;
755
+ await this.setMinMax();
756
+ await this.debugLog(`CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
757
+
758
+ if (homekitTiltAngle) {
759
+ this.WindowCovering.CurrentHorizontalTiltAngle = homekitTiltAngle!;
760
+ await this.debugLog(`CurrentHorizontalTiltAngle: ${this.WindowCovering.CurrentHorizontalTiltAngle}`);
761
+ }
762
+
763
+ if (this.setNewTarget) {
764
+ await this.infoLog('Checking Status ...');
765
+ await this.setMinMax();
766
+ if (this.WindowCovering.TargetPosition > this.WindowCovering.CurrentPosition
767
+ || (homekitTiltAngle && this.WindowCovering.TargetHorizontalTiltAngle !== this.WindowCovering.CurrentHorizontalTiltAngle)) {
768
+ await this.debugLog(`Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
769
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
770
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
771
+ await this.debugLog(`Increasing, PositionState: ${this.WindowCovering.PositionState}`);
772
+ } else if (this.WindowCovering.TargetPosition < this.WindowCovering.CurrentPosition) {
773
+ await this.debugLog(`Opening, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
774
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
775
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
776
+ await this.debugLog(`Decreasing, PositionState: ${this.WindowCovering.PositionState}`);
777
+ } else {
778
+ await this.debugLog(`Standby because reached position, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
779
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
780
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
781
+ await this.debugLog(`Stopped, PositionState: ${this.WindowCovering.PositionState}`);
782
+ }
783
+ } else {
784
+ await this.debugLog(`Standby because device not moving, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
785
+ this.WindowCovering.TargetPosition = this.WindowCovering.CurrentPosition;
786
+ if (homekitTiltAngle) {
787
+ this.WindowCovering.TargetHorizontalTiltAngle = this.WindowCovering.CurrentHorizontalTiltAngle;
788
+ }
789
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
790
+ await this.debugLog(`Stopped, PositionState: ${this.WindowCovering.PositionState}`);
915
791
  }
792
+ await this.debugLog(`CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition: ${this.WindowCovering.TargetPosition},`
793
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
916
794
  }
917
795
 
918
796
  /**