@switchbot/homebridge-switchbot 3.5.1-beta.2 → 3.5.1-beta.3

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 (187) hide show
  1. package/dist/device/blindtilt.d.ts +15 -6
  2. package/dist/device/blindtilt.d.ts.map +1 -1
  3. package/dist/device/blindtilt.js +203 -255
  4. package/dist/device/blindtilt.js.map +1 -1
  5. package/dist/device/bot.d.ts +9 -4
  6. package/dist/device/bot.d.ts.map +1 -1
  7. package/dist/device/bot.js +196 -218
  8. package/dist/device/bot.js.map +1 -1
  9. package/dist/device/ceilinglight.d.ts +9 -4
  10. package/dist/device/ceilinglight.d.ts.map +1 -1
  11. package/dist/device/ceilinglight.js +202 -247
  12. package/dist/device/ceilinglight.js.map +1 -1
  13. package/dist/device/colorbulb.d.ts +10 -5
  14. package/dist/device/colorbulb.d.ts.map +1 -1
  15. package/dist/device/colorbulb.js +329 -378
  16. package/dist/device/colorbulb.js.map +1 -1
  17. package/dist/device/contact.d.ts +9 -4
  18. package/dist/device/contact.d.ts.map +1 -1
  19. package/dist/device/contact.js +99 -142
  20. package/dist/device/contact.js.map +1 -1
  21. package/dist/device/curtain.d.ts +19 -7
  22. package/dist/device/curtain.d.ts.map +1 -1
  23. package/dist/device/curtain.js +203 -264
  24. package/dist/device/curtain.js.map +1 -1
  25. package/dist/device/device.d.ts +28 -32
  26. package/dist/device/device.d.ts.map +1 -1
  27. package/dist/device/device.js +186 -225
  28. package/dist/device/device.js.map +1 -1
  29. package/dist/device/fan.d.ts +9 -4
  30. package/dist/device/fan.d.ts.map +1 -1
  31. package/dist/device/fan.js +198 -227
  32. package/dist/device/fan.js.map +1 -1
  33. package/dist/device/hub.d.ts +9 -5
  34. package/dist/device/hub.d.ts.map +1 -1
  35. package/dist/device/hub.js +106 -231
  36. package/dist/device/hub.js.map +1 -1
  37. package/dist/device/humidifier.d.ts +12 -4
  38. package/dist/device/humidifier.d.ts.map +1 -1
  39. package/dist/device/humidifier.js +192 -232
  40. package/dist/device/humidifier.js.map +1 -1
  41. package/dist/device/iosensor.d.ts +9 -4
  42. package/dist/device/iosensor.d.ts.map +1 -1
  43. package/dist/device/iosensor.js +91 -157
  44. package/dist/device/iosensor.js.map +1 -1
  45. package/dist/device/lightstrip.d.ts +10 -5
  46. package/dist/device/lightstrip.d.ts.map +1 -1
  47. package/dist/device/lightstrip.js +287 -367
  48. package/dist/device/lightstrip.js.map +1 -1
  49. package/dist/device/lock.d.ts +10 -5
  50. package/dist/device/lock.d.ts.map +1 -1
  51. package/dist/device/lock.js +171 -216
  52. package/dist/device/lock.js.map +1 -1
  53. package/dist/device/meter.d.ts +9 -4
  54. package/dist/device/meter.d.ts.map +1 -1
  55. package/dist/device/meter.js +93 -158
  56. package/dist/device/meter.js.map +1 -1
  57. package/dist/device/meterplus.d.ts +9 -4
  58. package/dist/device/meterplus.d.ts.map +1 -1
  59. package/dist/device/meterplus.js +94 -155
  60. package/dist/device/meterplus.js.map +1 -1
  61. package/dist/device/motion.d.ts +9 -4
  62. package/dist/device/motion.d.ts.map +1 -1
  63. package/dist/device/motion.js +84 -142
  64. package/dist/device/motion.js.map +1 -1
  65. package/dist/device/plug.d.ts +9 -4
  66. package/dist/device/plug.d.ts.map +1 -1
  67. package/dist/device/plug.js +99 -124
  68. package/dist/device/plug.js.map +1 -1
  69. package/dist/device/robotvacuumcleaner.d.ts +9 -6
  70. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  71. package/dist/device/robotvacuumcleaner.js +170 -253
  72. package/dist/device/robotvacuumcleaner.js.map +1 -1
  73. package/dist/device/waterdetector.d.ts +12 -4
  74. package/dist/device/waterdetector.d.ts.map +1 -1
  75. package/dist/device/waterdetector.js +102 -128
  76. package/dist/device/waterdetector.js.map +1 -1
  77. package/dist/irdevice/airconditioner.d.ts +2 -1
  78. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  79. package/dist/irdevice/airconditioner.js.map +1 -1
  80. package/dist/irdevice/airpurifier.d.ts +2 -1
  81. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  82. package/dist/irdevice/airpurifier.js.map +1 -1
  83. package/dist/irdevice/camera.d.ts +2 -1
  84. package/dist/irdevice/camera.d.ts.map +1 -1
  85. package/dist/irdevice/camera.js.map +1 -1
  86. package/dist/irdevice/fan.d.ts +2 -1
  87. package/dist/irdevice/fan.d.ts.map +1 -1
  88. package/dist/irdevice/fan.js.map +1 -1
  89. package/dist/irdevice/irdevice.d.ts +2 -1
  90. package/dist/irdevice/irdevice.d.ts.map +1 -1
  91. package/dist/irdevice/irdevice.js +1 -1
  92. package/dist/irdevice/irdevice.js.map +1 -1
  93. package/dist/irdevice/light.d.ts +2 -1
  94. package/dist/irdevice/light.d.ts.map +1 -1
  95. package/dist/irdevice/light.js.map +1 -1
  96. package/dist/irdevice/other.d.ts +2 -1
  97. package/dist/irdevice/other.d.ts.map +1 -1
  98. package/dist/irdevice/other.js.map +1 -1
  99. package/dist/irdevice/tv.d.ts +2 -1
  100. package/dist/irdevice/tv.d.ts.map +1 -1
  101. package/dist/irdevice/tv.js.map +1 -1
  102. package/dist/irdevice/vacuumcleaner.d.ts +2 -1
  103. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  104. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  105. package/dist/irdevice/waterheater.d.ts +2 -1
  106. package/dist/irdevice/waterheater.d.ts.map +1 -1
  107. package/dist/irdevice/waterheater.js.map +1 -1
  108. package/dist/platform.d.ts +5 -7
  109. package/dist/platform.d.ts.map +1 -1
  110. package/dist/platform.js +51 -34
  111. package/dist/platform.js.map +1 -1
  112. package/dist/settings.d.ts +49 -191
  113. package/dist/settings.d.ts.map +1 -1
  114. package/dist/settings.js +19 -0
  115. package/dist/settings.js.map +1 -1
  116. package/dist/types/bledevicestatus.d.ts +279 -0
  117. package/dist/types/bledevicestatus.d.ts.map +1 -0
  118. package/dist/types/bledevicestatus.js +2 -0
  119. package/dist/types/bledevicestatus.js.map +1 -0
  120. package/dist/types/devicelist.d.ts +89 -0
  121. package/dist/types/devicelist.d.ts.map +1 -0
  122. package/dist/types/devicelist.js +6 -0
  123. package/dist/types/devicelist.js.map +1 -0
  124. package/dist/types/deviceresponse.d.ts +13 -0
  125. package/dist/types/deviceresponse.d.ts.map +1 -0
  126. package/dist/types/deviceresponse.js +2 -0
  127. package/dist/types/deviceresponse.js.map +1 -0
  128. package/dist/types/devicestatus.d.ts +149 -0
  129. package/dist/types/devicestatus.d.ts.map +1 -0
  130. package/dist/types/devicestatus.js +3 -0
  131. package/dist/types/devicestatus.js.map +1 -0
  132. package/dist/types/devicewebhookstatus.d.ts +156 -0
  133. package/dist/types/devicewebhookstatus.d.ts.map +1 -0
  134. package/dist/types/devicewebhookstatus.js +2 -0
  135. package/dist/types/devicewebhookstatus.js.map +1 -0
  136. package/dist/types/irdevicelist.d.ts +10 -0
  137. package/dist/types/irdevicelist.d.ts.map +1 -0
  138. package/dist/types/irdevicelist.js +2 -0
  139. package/dist/types/irdevicelist.js.map +1 -0
  140. package/dist/types/pushbody.d.ts +6 -0
  141. package/dist/types/pushbody.d.ts.map +1 -0
  142. package/dist/types/pushbody.js +2 -0
  143. package/dist/types/pushbody.js.map +1 -0
  144. package/dist/utils.d.ts +25 -0
  145. package/dist/utils.d.ts.map +1 -1
  146. package/dist/utils.js +28 -0
  147. package/dist/utils.js.map +1 -1
  148. package/package.json +10 -10
  149. package/src/device/blindtilt.ts +223 -263
  150. package/src/device/bot.ts +208 -221
  151. package/src/device/ceilinglight.ts +210 -257
  152. package/src/device/colorbulb.ts +334 -397
  153. package/src/device/contact.ts +111 -146
  154. package/src/device/curtain.ts +220 -283
  155. package/src/device/device.ts +194 -245
  156. package/src/device/fan.ts +214 -230
  157. package/src/device/hub.ts +126 -246
  158. package/src/device/humidifier.ts +216 -243
  159. package/src/device/iosensor.ts +114 -166
  160. package/src/device/lightstrip.ts +302 -377
  161. package/src/device/lock.ts +187 -221
  162. package/src/device/meter.ts +116 -177
  163. package/src/device/meterplus.ts +117 -174
  164. package/src/device/motion.ts +99 -144
  165. package/src/device/plug.ts +110 -128
  166. package/src/device/robotvacuumcleaner.ts +189 -252
  167. package/src/device/waterdetector.ts +120 -138
  168. package/src/irdevice/airconditioner.ts +2 -1
  169. package/src/irdevice/airpurifier.ts +2 -1
  170. package/src/irdevice/camera.ts +2 -1
  171. package/src/irdevice/fan.ts +2 -1
  172. package/src/irdevice/irdevice.ts +3 -2
  173. package/src/irdevice/light.ts +2 -1
  174. package/src/irdevice/other.ts +2 -1
  175. package/src/irdevice/tv.ts +2 -1
  176. package/src/irdevice/vacuumcleaner.ts +2 -1
  177. package/src/irdevice/waterheater.ts +2 -1
  178. package/src/platform.ts +52 -34
  179. package/src/settings.ts +30 -239
  180. package/src/types/bledevicestatus.ts +305 -0
  181. package/src/types/devicelist.ts +124 -0
  182. package/src/types/deviceresponse.ts +15 -0
  183. package/src/types/devicestatus.ts +178 -0
  184. package/src/types/devicewebhookstatus.ts +196 -0
  185. package/src/types/irdevicelist.ts +15 -0
  186. package/src/types/pushbody.ts +9 -0
  187. 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,215 +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
+ // CurrentAmbientLightLevel
268
269
  if (!this.device.blindTilt?.hide_lightsensor && this.LightSensor?.Service) {
269
- if (this.LightSensor?.CurrentAmbientLightLevel === 0) {
270
- this.LightSensor!.CurrentAmbientLightLevel = 0.0001;
271
- }
272
270
  const set_minLux = this.device.blindTilt?.set_minLux ?? 1;
273
271
  const set_maxLux = this.device.blindTilt?.set_maxLux ?? 6001;
274
272
  const spaceBetweenLevels = 9;
275
273
 
276
- // Brightness
277
- switch (serviceData.lightLevel) {
278
- case 1:
279
- this.LightSensor!.CurrentAmbientLightLevel = set_minLux;
280
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
281
- break;
282
- case 2:
283
- this.LightSensor!.CurrentAmbientLightLevel = (set_maxLux - set_minLux) / spaceBetweenLevels;
284
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel},`
285
- + ` Calculation: ${(set_maxLux - set_minLux) / spaceBetweenLevels}`);
286
- break;
287
- case 3:
288
- this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 2;
289
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
290
- break;
291
- case 4:
292
- this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 3;
293
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
294
- break;
295
- case 5:
296
- this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 4;
297
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
298
- break;
299
- case 6:
300
- this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 5;
301
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
302
- break;
303
- case 7:
304
- this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 6;
305
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
306
- break;
307
- case 8:
308
- this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 7;
309
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
310
- break;
311
- case 9:
312
- this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 8;
313
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
314
- break;
315
- case 10:
316
- default:
317
- this.LightSensor!.CurrentAmbientLightLevel = set_maxLux;
318
- this.debugLog();
319
- }
320
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel},`
321
- + ` CurrentAmbientLightLevel: ${this.LightSensor!.CurrentAmbientLightLevel}`);
274
+
275
+ await this.getLightLevel(serviceData.lightLevel, set_minLux, set_maxLux, spaceBetweenLevels);
276
+ await this.debugLog(`LightLevel: ${serviceData.lightLevel}, CurrentAmbientLightLevel: ${this.LightSensor!.CurrentAmbientLightLevel}`);
322
277
  }
323
- // Battery
278
+
279
+ // BatteryLevel
324
280
  this.Battery.BatteryLevel = Number(serviceData.battery);
325
- if (this.Battery.BatteryLevel < 10) {
326
- this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
327
- } else {
328
- this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
329
- }
330
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
331
- + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
332
- }
281
+ await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`);
333
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
+ };
334
288
 
335
289
  /**
336
290
  * Parse the device status from the SwitchBot OpenAPI
337
291
  */
338
- async openAPIparseStatus(deviceStatus: deviceStatus): Promise<void> {
339
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
292
+ async openAPIparseStatus(deviceStatus: blindTiltStatus): Promise<void> {
293
+ await this.debugLog('openAPIparseStatus');
340
294
 
341
- const [homekitPosition, homekitTiltAngle] = this.mapDeviceValuesToHomekitValues(Number(deviceStatus.body.slidePosition),
342
- String(deviceStatus.body.direction));
343
- this.debugLog(` device: ${deviceStatus.body.slidePosition} => HK: ${homekitPosition}`);
344
-
345
- this.WindowCovering!.CurrentPosition = homekitPosition;
346
295
  // CurrentPosition
347
- await this.setMinMax();
348
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
296
+ await this.getCurrentPosttionDirection(deviceStatus.direction, deviceStatus.slidePosition);
349
297
 
350
- if (homekitTiltAngle) {
351
- this.WindowCovering.CurrentHorizontalTiltAngle = homekitTiltAngle!;
352
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
353
- + ` 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}`);
354
304
  }
355
305
 
356
- if (this.setNewTarget) {
357
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Checking Status ...`);
358
- }
306
+ // BatteryLevel
307
+ this.Battery.BatteryLevel = Number(deviceStatus.battery);
308
+ await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`);
359
309
 
360
- if (this.setNewTarget && deviceStatus.body.moving) {
361
- await this.setMinMax();
362
- if (this.WindowCovering.TargetPosition > this.WindowCovering.CurrentPosition
363
- || (homekitTiltAngle && this.WindowCovering.TargetHorizontalTiltAngle !== this.WindowCovering.CurrentHorizontalTiltAngle)) {
364
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition} `);
365
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
366
- this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
367
- this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} INCREASING`
368
- + ` PositionState: ${this.WindowCovering.PositionState}`);
369
- } else if (this.WindowCovering.TargetPosition < this.WindowCovering.CurrentPosition) {
370
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Opening, CurrentPosition: ${this.WindowCovering.CurrentPosition} `);
371
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
372
- this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
373
- this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} DECREASING`
374
- + ` 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;
375
325
  } else {
376
- this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} Standby because reached position,`
377
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
378
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
379
- this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
380
- this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} STOPPED`
381
- + ` PositionState: ${this.WindowCovering.PositionState}`);
382
- }
383
- } else {
384
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Standby because device not moving,`
385
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
386
- this.WindowCovering.TargetPosition = this.WindowCovering.CurrentPosition;
387
- if (homekitTiltAngle) {
388
- this.WindowCovering.TargetHorizontalTiltAngle = this.WindowCovering.CurrentHorizontalTiltAngle;
326
+ deviceVersion = version.replace(/^V|-.*$/g, '') ?? '0.0.0';
389
327
  }
390
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
391
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Stopped`);
392
- }
393
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition},`
394
- + ` TargetPosition: ${this.WindowCovering.TargetPosition}, PositionState: ${this.WindowCovering.PositionState},`);
395
- if (!this.device.blindTilt?.hide_lightsensor) {
396
- const set_minLux = this.device.blindTilt?.set_minLux ?? 1;
397
- const set_maxLux = this.device.blindTilt?.set_maxLux ?? 6001;
398
- // Brightness
399
- switch (deviceStatus.body.brightness) {
400
- case 'dim':
401
- this.LightSensor!.CurrentAmbientLightLevel = set_minLux;
402
- break;
403
- case 'bright':
404
- default:
405
- this.LightSensor!.CurrentAmbientLightLevel = set_maxLux;
406
- }
407
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
408
- + ` 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}`);
409
336
  }
337
+ }
410
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);
411
346
  // BatteryLevel
412
- this.Battery.BatteryLevel = Number(deviceStatus.body.battery);
413
- if (this.Battery.BatteryLevel < 10) {
414
- this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
415
- } else {
416
- this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
417
- }
418
- if (Number.isNaN(this.Battery.BatteryLevel)) {
419
- this.Battery.BatteryLevel = 100;
420
- }
421
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
422
- + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
423
-
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}`);
424
353
  // Firmware Version
425
- const version = deviceStatus.body.version?.toString();
426
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Firmware Version: ${version?.replace(/^V|-.*$/g, '')}`);
427
- let deviceVersion: string;
428
- if (version?.includes('.') === false) {
429
- const replace = version?.replace(/^V|-.*$/g, '');
430
- const match = replace?.match(/.{1,1}/g);
431
- const blindTiltVersion = match?.join('.') ?? '0.0.0';
432
- deviceVersion = blindTiltVersion;
433
- } else {
434
- deviceVersion = version?.replace(/^V|-.*$/g, '') ?? '0.0.0';
435
- }
354
+ const deviceVersion = context.version.replace(/^V|-.*$/g, '') ?? '0.0.0';
436
355
  this.accessory
437
356
  .getService(this.hap.Service.AccessoryInformation)!
438
357
  .setCharacteristic(this.hap.Characteristic.HardwareRevision, deviceVersion)
@@ -440,25 +359,27 @@ export class BlindTilt extends deviceBase {
440
359
  .getCharacteristic(this.hap.Characteristic.FirmwareRevision)
441
360
  .updateValue(deviceVersion);
442
361
  this.accessory.context.deviceVersion = deviceVersion;
443
- this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceVersion: ${this.accessory.context.deviceVersion}`);
362
+ await this.debugSuccessLog(`deviceVersion: ${this.accessory.context.deviceVersion}`);
444
363
  }
445
364
 
365
+ /**
366
+ * Asks the SwitchBot API for the latest device information
367
+ */
446
368
  async refreshStatus(): Promise<void> {
447
369
  if (!this.device.enableCloudService && this.OpenAPI) {
448
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} refreshStatus enableCloudService: ${this.device.enableCloudService}`);
370
+ await this.errorLog(`refreshStatus enableCloudService: ${this.device.enableCloudService}`);
449
371
  } else if (this.BLE) {
450
372
  await this.BLERefreshStatus();
451
373
  } else if (this.OpenAPI && this.platform.config.credentials?.token) {
452
374
  await this.openAPIRefreshStatus();
453
375
  } else {
454
376
  await this.offlineOff();
455
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
456
- + ` ${this.device.connectionType}, refreshStatus will not happen.`);
377
+ await this.debugWarnLog(`Connection Type: ${this.device.connectionType}, refreshStatus will not happen.`);
457
378
  }
458
379
  }
459
380
 
460
381
  async BLERefreshStatus(): Promise<void> {
461
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
382
+ await this.debugLog('BLERefreshStatus');
462
383
  const switchbot = await this.switchbotBLE();
463
384
 
464
385
  if (switchbot === undefined) {
@@ -467,13 +388,13 @@ export class BlindTilt extends deviceBase {
467
388
  // Start to monitor advertisement packets
468
389
  (async () => {
469
390
  // Start to monitor advertisement packets
470
- const serviceData: serviceData = await this.monitorAdvertisementPackets(switchbot);
391
+ const serviceData = await this.monitorAdvertisementPackets(switchbot) as unknown as blindTiltServiceData;
471
392
  // Update HomeKit
472
- if (serviceData.model !== '' && serviceData.modelName !== '') {
393
+ if (serviceData.model === SwitchBotBLEModel.BlindTilt && serviceData.modelName === SwitchBotBLEModelName.BlindTilt) {
473
394
  await this.BLEparseStatus(serviceData);
474
395
  await this.updateHomeKitCharacteristics();
475
396
  } else {
476
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed to get serviceData, serviceData: ${serviceData}`);
397
+ await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
477
398
  await this.BLERefreshConnection(switchbot);
478
399
  }
479
400
  })();
@@ -481,61 +402,52 @@ export class BlindTilt extends deviceBase {
481
402
  }
482
403
 
483
404
  async openAPIRefreshStatus(): Promise<void> {
484
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
405
+ await this.debugLog('openAPIRefreshStatus');
485
406
  try {
486
407
  const { body, statusCode } = await this.deviceRefreshStatus();
487
408
  const deviceStatus: any = await body.json();
488
- await this.refreshStatusCodes(statusCode, deviceStatus);;
489
- if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
490
- await this.successfulRefreshStatus(statusCode, deviceStatus);
491
- 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);
492
413
  await this.updateHomeKitCharacteristics();
493
414
  } else {
494
- await this.statusCodes(statusCode, deviceStatus);
415
+ await this.debugWarnLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
416
+ await this.debugWarnLog(statusCode, deviceStatus);
495
417
  }
496
418
  } catch (e: any) {
497
419
  await this.apiError(e);
498
- await this.openAPIRefreshError(e);
420
+ await this.errorLog(`failed openAPIRefreshStatus with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`);
499
421
  }
500
422
  }
501
423
 
502
- async registerWebhook(accessory: PlatformAccessory, device: device & devicesConfig) {
503
- if (device.webhook) {
504
- this.debugLog(`${device.deviceType}: ${accessory.displayName} is listening webhook.`);
424
+ async registerWebhook(): Promise<void> {
425
+ if (this.device.webhook) {
426
+ await this.debugLog('is listening webhook.');
505
427
  this.platform.webhookEventHandler[this.device.deviceId] = async (context) => {
506
428
  try {
507
- this.debugLog(`${device.deviceType}: ${accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
508
- const { slidePosition, battery, lightLevel } = context;
509
- const { CurrentPosition } = this.WindowCovering;
510
- const { BatteryLevel } = this.Battery;
511
- const { CurrentAmbientLightLevel } = this.LightSensor ?? {};
512
- this.debugLog(`${device.deviceType}: ${accessory.displayName} (slidePosition, battery, lightLevel) = Webhook:(${slidePosition}, ${battery},`
513
- + ` ${lightLevel}), current:(${CurrentPosition}, ${BatteryLevel}, ${CurrentAmbientLightLevel})`);
514
- this.WindowCovering.CurrentPosition = slidePosition;
515
- this.Battery.BatteryLevel = battery;
516
- if (!device.blindTilt?.hide_lightsensor) {
517
- this.LightSensor!.CurrentAmbientLightLevel = lightLevel;
518
- }
429
+ await this.debugLog(`received Webhook: ${JSON.stringify(context)}`);
430
+ await this.parseStatusWebhook(context);
519
431
  await this.updateHomeKitCharacteristics();
520
432
  } catch (e: any) {
521
- 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}`);
522
434
  }
523
435
  };
524
436
  } else {
525
- this.debugLog(`${device.deviceType}: ${accessory.displayName} is not listening webhook.`);
437
+ await this.debugLog('is not listening webhook.');
526
438
  }
527
439
  }
528
440
 
529
441
  async pushChanges(): Promise<void> {
530
442
  if (!this.device.enableCloudService && this.OpenAPI) {
531
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} pushChanges enableCloudService: ${this.device.enableCloudService}`);
443
+ await this.errorLog(`pushChanges enableCloudService: ${this.device.enableCloudService}`);
532
444
  } else if (this.BLE) {
533
445
  await this.BLEpushChanges();
534
446
  } else if (this.OpenAPI && this.platform.config.credentials?.token) {
535
447
  await this.openAPIpushChanges();
536
448
  } else {
537
449
  await this.offlineOff();
538
- await this.pushChangeDisabled();
450
+ await this.debugWarnLog(`Connection Type: ${this.device.connectionType}, pushChanges will not happen.`);
539
451
  }
540
452
  // Refresh the status from the API
541
453
  interval(15000)
@@ -547,18 +459,17 @@ export class BlindTilt extends deviceBase {
547
459
  }
548
460
 
549
461
  async BLEpushChanges(): Promise<void> {
550
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
462
+ await this.debugLog('BLEpushChanges');
551
463
  if (this.WindowCovering.TargetPosition !== this.WindowCovering.CurrentPosition) {
552
- const switchbot = await this.platform.connectBLE();
553
- // 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);
554
466
  await this.convertBLEAddress();
555
467
  const { setPositionMode, Mode }: { setPositionMode: number; Mode: string; } = await this.setPerformance();
556
- this.debugLog(`${this.accessory.displayName} Mode: ${Mode}`);
468
+ await this.debugLog(`Mode: ${Mode}, setPositionMode: ${setPositionMode}`);
557
469
  if (switchbot !== false) {
558
470
  switchbot
559
471
  .discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac })
560
472
  .then(async (device_list: any) => {
561
- this.infoLog(`${this.accessory.displayName} Target Position: ${this.WindowCovering.TargetPosition}`);
562
473
  return await this.retryBLE({
563
474
  max: await this.maxRetryBLE(),
564
475
  fn: async () => {
@@ -566,28 +477,27 @@ export class BlindTilt extends deviceBase {
566
477
  },
567
478
  });
568
479
  })
569
- .then(() => {
570
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
571
- this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
572
- + `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();
573
483
  })
574
484
  .catch(async (e: any) => {
575
485
  await this.apiError(e);
576
- await this.failedBLEChanges(e);
486
+ await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`);
577
487
  await this.BLEPushConnection();
578
488
  });
579
489
  } else {
580
- 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}`);
581
491
  await this.BLEPushConnection();
582
492
  }
583
493
  } else {
584
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges, CurrentPosition & TargetPosition Are the Same.`
585
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition ${this.WindowCovering.TargetPosition}`);
494
+ await this.debugLog(`No changes (BLEpushChanges), TargetPosition: ${this.WindowCovering.TargetPosition},`
495
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
586
496
  }
587
497
  }
588
498
 
589
499
  async openAPIpushChanges(): Promise<void> {
590
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
500
+ await this.debugLog('openAPIpushChanges');
591
501
  const hasDifferentAndRelevantHorizontalTiltAngle =
592
502
  this.mappingMode === BlindTiltMappingMode.UseTiltForDirection
593
503
  && this.WindowCovering.TargetHorizontalTiltAngle !== this.WindowCovering.CurrentHorizontalTiltAngle;
@@ -595,11 +505,10 @@ export class BlindTilt extends deviceBase {
595
505
  || hasDifferentAndRelevantHorizontalTiltAngle || this.device.disableCaching) {
596
506
  const [direction, position] = this.mapHomekitValuesToDeviceValues(Number(this.WindowCovering.TargetPosition),
597
507
  Number(this.WindowCovering.TargetHorizontalTiltAngle));
598
- const { Mode }: { setPositionMode: number; Mode: string; } = await this.setPerformance();
599
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
600
- + ` Pushing ${this.WindowCovering.TargetPosition} (device = ${direction};${position})`);
601
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Mode: ${Mode}`);
602
- 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;
603
512
  if (position === 100) {
604
513
  bodyChange = JSON.stringify({
605
514
  command: 'fullyOpen',
@@ -619,28 +528,27 @@ export class BlindTilt extends deviceBase {
619
528
  commandType: 'command',
620
529
  });
621
530
  }
622
- 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)}`);
623
532
  try {
624
533
  const { body, statusCode } = await this.pushChangeRequest(bodyChange);
625
534
  const deviceStatus: any = await body.json();
626
- await this.pushStatusCodes(statusCode, deviceStatus);
627
- if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
628
- 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)}`);
629
538
  await this.updateHomeKitCharacteristics();
630
539
  } else {
631
540
  await this.statusCode(statusCode);
632
541
  await this.statusCode(deviceStatus.statusCode);
633
542
  }
634
543
  } catch (e: any) {
635
- this.apiError(e);
636
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
637
- + ` 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)}`);
638
546
  }
639
547
  } else {
640
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No OpenAPI Changes, CurrentPosition & TargetPosition Are the Same.`
641
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition ${this.WindowCovering.TargetPosition}`
642
- + ` CurrentHorizontalTiltAngle: ${this.WindowCovering.CurrentHorizontalTiltAngle},`
643
- + ` 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}`);
644
552
  }
645
553
  }
646
554
 
@@ -649,9 +557,9 @@ export class BlindTilt extends deviceBase {
649
557
  */
650
558
  async TargetHorizontalTiltAngleSet(value: CharacteristicValue): Promise<void> {
651
559
  if (this.WindowCovering.TargetHorizontalTiltAngle !== this.accessory.context.TargetHorizontalTiltAngle) {
652
- await this.changeSet(value, 'TargetHorizontalTiltAngle');
560
+ await this.debugLog(`Set TargetHorizontalTiltAngle: ${value}`);
653
561
  } else {
654
- await this.noChangeSet(value, 'TargetHorizontalTiltAngle');
562
+ await this.debugLog(`No changes, TargetHorizontalTiltAngle: ${value}`);
655
563
  }
656
564
 
657
565
  //value = value < 0 ? -90 : 90;
@@ -665,9 +573,9 @@ export class BlindTilt extends deviceBase {
665
573
  */
666
574
  async TargetPositionSet(value: CharacteristicValue): Promise<void> {
667
575
  if (this.WindowCovering.TargetPosition !== this.accessory.context.TargetPosition) {
668
- await this.changeSet(value, 'TargetPosition');
576
+ await this.debugLog(`Set TargetPosition: ${value}`);
669
577
  } else {
670
- await this.noChangeSet(value, 'TargetPosition');
578
+ await this.debugLog(`No changes, TargetPosition: ${value}`);
671
579
  }
672
580
 
673
581
  this.WindowCovering.TargetPosition = value;
@@ -677,23 +585,20 @@ export class BlindTilt extends deviceBase {
677
585
 
678
586
  async startUpdatingBlindTiltIfNeeded(): Promise<void> {
679
587
  await this.setMinMax();
680
- this.debugLog('setMinMax');
588
+ await this.debugLog('setMinMax');
681
589
  if (this.WindowCovering.TargetPosition > this.WindowCovering.CurrentPosition
682
590
  || this.WindowCovering.TargetHorizontalTiltAngle !== this.WindowCovering.CurrentHorizontalTiltAngle) {
683
591
  this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
684
592
  this.setNewTarget = true;
685
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${this.WindowCovering.CurrentPosition},`
686
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
593
+ await this.debugLog(`value: ${this.WindowCovering.CurrentPosition}, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
687
594
  } else if (this.WindowCovering.TargetPosition < this.WindowCovering.CurrentPosition) {
688
595
  this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
689
596
  this.setNewTarget = true;
690
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${this.WindowCovering.CurrentPosition},`
691
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
597
+ await this.debugLog(`value: ${this.WindowCovering.CurrentPosition}, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
692
598
  } else {
693
599
  this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
694
600
  this.setNewTarget = false;
695
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${this.WindowCovering.CurrentPosition},`
696
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
601
+ await this.debugLog(`value: ${this.WindowCovering.CurrentPosition}, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
697
602
  }
698
603
  this.WindowCovering.Service.setCharacteristic(this.hap.Characteristic.PositionState, this.WindowCovering.PositionState);
699
604
  this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
@@ -703,10 +608,10 @@ export class BlindTilt extends deviceBase {
703
608
  * The minimum time depends on the network control latency.
704
609
  */
705
610
  clearTimeout(this.setNewTargetTimer);
706
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateRate: ${this.deviceUpdateRate}`);
611
+ await this.debugLog(`deviceUpdateRate: ${this.deviceUpdateRate}`);
707
612
  if (this.setNewTarget) {
708
- this.setNewTargetTimer = setTimeout(() => {
709
- 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`);
710
615
  this.setNewTarget = false;
711
616
  }, this.deviceUpdateRate * 1000);
712
617
  }
@@ -748,16 +653,15 @@ export class BlindTilt extends deviceBase {
748
653
 
749
654
  async BLEPushConnection() {
750
655
  if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
751
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Push Changes`);
656
+ await this.warnLog('Using OpenAPI Connection to Push Changes');
752
657
  await this.openAPIpushChanges();
753
658
  }
754
659
  }
755
660
 
756
661
  async BLERefreshConnection(switchbot: any): Promise<void> {
757
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot:`
758
- + ` ${JSON.stringify(switchbot)}`);
662
+ await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${JSON.stringify(switchbot)}`);
759
663
  if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
760
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Refresh Status`);
664
+ await this.warnLog('Using OpenAPI Connection to Refresh Status');
761
665
  await this.openAPIRefreshStatus();
762
666
  }
763
667
  }
@@ -802,6 +706,11 @@ export class BlindTilt extends deviceBase {
802
706
  this.WindowCovering.CurrentPosition = 100;
803
707
  }
804
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
+ }
805
714
 
806
715
  if (this.mappingMode === BlindTiltMappingMode.UseTiltForDirection) {
807
716
  this.WindowCovering.CurrentHorizontalTiltAngle = Number(this.WindowCovering.CurrentHorizontalTiltAngle) < 0 ? -90 : 90;
@@ -827,10 +736,61 @@ export class BlindTilt extends deviceBase {
827
736
  this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e);
828
737
  this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e);
829
738
  this.Battery.Service.updateCharacteristic(this.hap.Characteristic.ChargingState, e);
830
- if (!this.device.blindTilt?.hide_lightsensor) {
831
- this.LightSensor!.Service.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, e);
832
- 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}`);
833
791
  }
792
+ await this.debugLog(`CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition: ${this.WindowCovering.TargetPosition},`
793
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
834
794
  }
835
795
 
836
796
  /**