@switchbot/homebridge-switchbot 3.5.0-beta.9 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/.vscode/settings.json +4 -1
  2. package/CHANGELOG.md +4 -1
  3. package/config.schema.json +166 -24
  4. package/dist/device/blindtilt.d.ts +21 -96
  5. package/dist/device/blindtilt.d.ts.map +1 -1
  6. package/dist/device/blindtilt.js +439 -817
  7. package/dist/device/blindtilt.js.map +1 -1
  8. package/dist/device/bot.d.ts +27 -72
  9. package/dist/device/bot.d.ts.map +1 -1
  10. package/dist/device/bot.js +835 -865
  11. package/dist/device/bot.js.map +1 -1
  12. package/dist/device/ceilinglight.d.ts +15 -69
  13. package/dist/device/ceilinglight.d.ts.map +1 -1
  14. package/dist/device/ceilinglight.js +287 -653
  15. package/dist/device/ceilinglight.js.map +1 -1
  16. package/dist/device/colorbulb.d.ts +15 -76
  17. package/dist/device/colorbulb.d.ts.map +1 -1
  18. package/dist/device/colorbulb.js +354 -732
  19. package/dist/device/colorbulb.js.map +1 -1
  20. package/dist/device/contact.d.ts +14 -66
  21. package/dist/device/contact.d.ts.map +1 -1
  22. package/dist/device/contact.js +268 -576
  23. package/dist/device/contact.js.map +1 -1
  24. package/dist/device/curtain.d.ts +18 -89
  25. package/dist/device/curtain.d.ts.map +1 -1
  26. package/dist/device/curtain.js +431 -851
  27. package/dist/device/curtain.js.map +1 -1
  28. package/dist/device/device.d.ts +60 -0
  29. package/dist/device/device.d.ts.map +1 -0
  30. package/dist/device/device.js +739 -0
  31. package/dist/device/device.js.map +1 -0
  32. package/dist/device/fan.d.ts +63 -0
  33. package/dist/device/fan.d.ts.map +1 -0
  34. package/dist/device/fan.js +698 -0
  35. package/dist/device/fan.js.map +1 -0
  36. package/dist/device/hub.d.ts +15 -60
  37. package/dist/device/hub.d.ts.map +1 -1
  38. package/dist/device/hub.js +257 -631
  39. package/dist/device/hub.js.map +1 -1
  40. package/dist/device/humidifier.d.ts +11 -66
  41. package/dist/device/humidifier.d.ts.map +1 -1
  42. package/dist/device/humidifier.js +266 -629
  43. package/dist/device/humidifier.js.map +1 -1
  44. package/dist/device/iosensor.d.ts +12 -64
  45. package/dist/device/iosensor.d.ts.map +1 -1
  46. package/dist/device/iosensor.js +215 -615
  47. package/dist/device/iosensor.js.map +1 -1
  48. package/dist/device/lightstrip.d.ts +12 -70
  49. package/dist/device/lightstrip.d.ts.map +1 -1
  50. package/dist/device/lightstrip.js +336 -645
  51. package/dist/device/lightstrip.js.map +1 -1
  52. package/dist/device/lock.d.ts +17 -63
  53. package/dist/device/lock.d.ts.map +1 -1
  54. package/dist/device/lock.js +290 -595
  55. package/dist/device/lock.js.map +1 -1
  56. package/dist/device/meter.d.ts +15 -64
  57. package/dist/device/meter.d.ts.map +1 -1
  58. package/dist/device/meter.js +211 -608
  59. package/dist/device/meter.js.map +1 -1
  60. package/dist/device/meterplus.d.ts +15 -65
  61. package/dist/device/meterplus.d.ts.map +1 -1
  62. package/dist/device/meterplus.js +205 -615
  63. package/dist/device/meterplus.js.map +1 -1
  64. package/dist/device/motion.d.ts +12 -69
  65. package/dist/device/motion.d.ts.map +1 -1
  66. package/dist/device/motion.js +202 -563
  67. package/dist/device/motion.js.map +1 -1
  68. package/dist/device/plug.d.ts +10 -57
  69. package/dist/device/plug.d.ts.map +1 -1
  70. package/dist/device/plug.js +125 -484
  71. package/dist/device/plug.js.map +1 -1
  72. package/dist/device/robotvacuumcleaner.d.ts +13 -63
  73. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  74. package/dist/device/robotvacuumcleaner.js +233 -549
  75. package/dist/device/robotvacuumcleaner.js.map +1 -1
  76. package/dist/device/waterdetector.d.ts +11 -63
  77. package/dist/device/waterdetector.d.ts.map +1 -1
  78. package/dist/device/waterdetector.js +170 -493
  79. package/dist/device/waterdetector.js.map +1 -1
  80. package/dist/homebridge-ui/public/index.html +22 -16
  81. package/dist/homebridge-ui/server.js +1 -1
  82. package/dist/homebridge-ui/server.js.map +1 -1
  83. package/dist/index.d.ts +1 -1
  84. package/dist/index.d.ts.map +1 -1
  85. package/dist/index.js +2 -2
  86. package/dist/index.js.map +1 -1
  87. package/dist/irdevice/airconditioner.d.ts +10 -50
  88. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  89. package/dist/irdevice/airconditioner.js +340 -468
  90. package/dist/irdevice/airconditioner.js.map +1 -1
  91. package/dist/irdevice/airpurifier.d.ts +8 -39
  92. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  93. package/dist/irdevice/airpurifier.js +105 -319
  94. package/dist/irdevice/airpurifier.js.map +1 -1
  95. package/dist/irdevice/camera.d.ts +7 -36
  96. package/dist/irdevice/camera.d.ts.map +1 -1
  97. package/dist/irdevice/camera.js +44 -285
  98. package/dist/irdevice/camera.js.map +1 -1
  99. package/dist/irdevice/fan.d.ts +7 -43
  100. package/dist/irdevice/fan.d.ts.map +1 -1
  101. package/dist/irdevice/fan.js +92 -350
  102. package/dist/irdevice/fan.js.map +1 -1
  103. package/dist/irdevice/irdevice.d.ts +40 -0
  104. package/dist/irdevice/irdevice.d.ts.map +1 -0
  105. package/dist/irdevice/irdevice.js +369 -0
  106. package/dist/irdevice/irdevice.js.map +1 -0
  107. package/dist/irdevice/light.d.ts +12 -45
  108. package/dist/irdevice/light.d.ts.map +1 -1
  109. package/dist/irdevice/light.js +118 -362
  110. package/dist/irdevice/light.js.map +1 -1
  111. package/dist/irdevice/other.d.ts +19 -48
  112. package/dist/irdevice/other.d.ts.map +1 -1
  113. package/dist/irdevice/other.js +438 -570
  114. package/dist/irdevice/other.js.map +1 -1
  115. package/dist/irdevice/tv.d.ts +8 -40
  116. package/dist/irdevice/tv.d.ts.map +1 -1
  117. package/dist/irdevice/tv.js +91 -339
  118. package/dist/irdevice/tv.js.map +1 -1
  119. package/dist/irdevice/vacuumcleaner.d.ts +7 -36
  120. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  121. package/dist/irdevice/vacuumcleaner.js +45 -285
  122. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  123. package/dist/irdevice/waterheater.d.ts +7 -36
  124. package/dist/irdevice/waterheater.d.ts.map +1 -1
  125. package/dist/irdevice/waterheater.js +47 -291
  126. package/dist/irdevice/waterheater.js.map +1 -1
  127. package/dist/platform.d.ts +22 -8
  128. package/dist/platform.d.ts.map +1 -1
  129. package/dist/platform.js +342 -191
  130. package/dist/platform.js.map +1 -1
  131. package/dist/settings.d.ts +64 -17
  132. package/dist/settings.d.ts.map +1 -1
  133. package/dist/settings.js +16 -552
  134. package/dist/settings.js.map +1 -1
  135. package/dist/utils.d.ts +77 -0
  136. package/dist/utils.d.ts.map +1 -1
  137. package/dist/utils.js +638 -1
  138. package/dist/utils.js.map +1 -1
  139. package/eslint.config.js +96 -0
  140. package/package.json +20 -16
  141. package/src/custom.d.ts +2 -1
  142. package/src/device/blindtilt.ts +472 -888
  143. package/src/device/bot.ts +893 -968
  144. package/src/device/ceilinglight.ts +304 -709
  145. package/src/device/colorbulb.ts +370 -803
  146. package/src/device/contact.ts +301 -611
  147. package/src/device/curtain.ts +460 -908
  148. package/src/device/device.ts +755 -0
  149. package/src/device/fan.ts +749 -0
  150. package/src/device/hub.ts +294 -664
  151. package/src/device/humidifier.ts +299 -696
  152. package/src/device/iosensor.ts +251 -644
  153. package/src/device/lightstrip.ts +362 -712
  154. package/src/device/lock.ts +328 -653
  155. package/src/device/meter.ts +247 -637
  156. package/src/device/meterplus.ts +240 -644
  157. package/src/device/motion.ts +230 -598
  158. package/src/device/plug.ts +139 -525
  159. package/src/device/robotvacuumcleaner.ts +258 -593
  160. package/src/device/waterdetector.ts +191 -522
  161. package/src/homebridge-ui/public/index.html +22 -16
  162. package/src/homebridge-ui/server.ts +1 -1
  163. package/src/index.ts +4 -3
  164. package/src/irdevice/airconditioner.ts +370 -527
  165. package/src/irdevice/airpurifier.ts +132 -356
  166. package/src/irdevice/camera.ts +58 -311
  167. package/src/irdevice/fan.ts +109 -379
  168. package/src/irdevice/irdevice.ts +382 -0
  169. package/src/irdevice/light.ts +157 -412
  170. package/src/irdevice/other.ts +507 -648
  171. package/src/irdevice/tv.ts +121 -375
  172. package/src/irdevice/vacuumcleaner.ts +59 -311
  173. package/src/irdevice/waterheater.ts +61 -320
  174. package/src/platform.ts +395 -259
  175. package/src/settings.ts +118 -609
  176. package/src/utils.ts +642 -1
  177. package/.github/npm-version-script.cjs +0 -81
  178. package/src/device/waterdetector.json +0 -11
@@ -1,149 +1,77 @@
1
+ /* Copyright(C) 2021-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
2
+ *
3
+ * blindtilt.ts: @switchbot/homebridge-switchbot.
4
+ */
1
5
  import { request } from 'undici';
2
- import { sleep } from '../utils.js';
6
+ import { Devices } from '../settings.js';
3
7
  import { interval, Subject } from 'rxjs';
4
- import asyncmqtt from 'async-mqtt';
8
+ import { deviceBase } from './device.js';
9
+ import { BlindTiltMappingMode } from '../utils.js';
5
10
  import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
6
- import { Devices } from '../settings.js';
7
- var BlindTiltMappingMode;
8
- (function (BlindTiltMappingMode) {
9
- BlindTiltMappingMode["OnlyUp"] = "only_up";
10
- BlindTiltMappingMode["OnlyDown"] = "only_down";
11
- BlindTiltMappingMode["DownAndUp"] = "down_and_up";
12
- BlindTiltMappingMode["UpAndDown"] = "up_and_down";
13
- BlindTiltMappingMode["UseTiltForDirection"] = "use_tilt_for_direction";
14
- })(BlindTiltMappingMode || (BlindTiltMappingMode = {}));
15
- export class BlindTilt {
11
+ export class BlindTilt extends deviceBase {
16
12
  platform;
17
- accessory;
18
- device;
19
- api;
20
- log;
21
- config;
22
- hap;
23
13
  // Services
24
- batteryService;
25
- lightSensorService;
26
- windowCoveringService;
27
- // Characteristic Values
28
- BatteryLevel;
29
- PositionState;
30
- TargetPosition;
31
- CurrentPosition;
32
- StatusLowBattery;
33
- FirmwareRevision;
34
- CurrentAmbientLightLevel;
35
- TargetHorizontalTiltAngle;
36
- CurrentHorizontalTiltAngle;
37
- // OpenAPI Status
38
- OpenAPI_InMotion;
39
- OpenAPI_BatteryLevel;
40
- OpenAPI_Direction;
41
- OpenAPI_Calibration;
42
- OpenAPI_CurrentPosition;
43
- OpenAPI_FirmwareRevision;
44
- OpenAPI_CurrentAmbientLightLevel;
14
+ WindowCovering;
15
+ Battery;
16
+ LightSensor;
45
17
  // OpenAPI Others
46
- Mode;
47
- setPositionMode;
48
18
  mappingMode = BlindTiltMappingMode.OnlyUp;
49
- // BLE Status
50
- BLE_InMotion;
51
- BLE_BatteryLevel;
52
- BLE_Calibration;
53
- BLE_CurrentPosition;
54
- BLE_CurrentAmbientLightLevel;
55
- // BLE Others
56
- BLE_IsConnected;
57
- spaceBetweenLevels;
58
19
  // Target
59
20
  setNewTarget;
60
21
  setNewTargetTimer;
61
- //MQTT stuff
62
- mqttClient = null;
63
- // Config
64
- set_minStep;
65
- updateRate;
66
- set_minLux;
67
- set_maxLux;
68
- scanDuration;
69
- deviceLogging;
70
- deviceRefreshRate;
71
- setCloseMode;
72
- setOpenMode;
73
22
  // Updates
74
23
  blindTiltUpdateInProgress;
75
24
  doBlindTiltUpdate;
76
- // Connection
77
- OpenAPI;
78
- BLE;
79
25
  constructor(platform, accessory, device) {
26
+ super(platform, accessory, device);
80
27
  this.platform = platform;
81
- this.accessory = accessory;
82
- this.device = device;
83
- this.api = this.platform.api;
84
- this.log = this.platform.log;
85
- this.config = this.platform.config;
86
- this.hap = this.api.hap;
87
- // Connection
88
- this.BLE = this.device.connectionType === 'BLE' || this.device.connectionType === 'BLE/OpenAPI';
89
- this.OpenAPI = this.device.connectionType === 'OpenAPI' || this.device.connectionType === 'BLE/OpenAPI';
90
28
  // default placeholders
91
- this.deviceLogs(device);
92
- this.refreshRate(device);
93
- this.scan(device);
94
- this.setupMqtt(device);
95
- this.deviceContext();
96
- this.deviceConfig(device);
97
29
  this.mappingMode = device.blindTilt?.mode ?? BlindTiltMappingMode.OnlyUp;
98
30
  this.debugLog(`Mapping mode: ${this.mappingMode}`);
99
31
  // this is subject we use to track when we need to POST changes to the SwitchBot API
100
32
  this.doBlindTiltUpdate = new Subject();
101
33
  this.blindTiltUpdateInProgress = false;
102
34
  this.setNewTarget = false;
103
- // Retrieve initial values and updateHomekit
104
- this.refreshStatus();
105
- // set accessory information
106
- accessory
107
- .getService(this.hap.Service.AccessoryInformation)
108
- .setCharacteristic(this.hap.Characteristic.Manufacturer, 'SwitchBot')
109
- .setCharacteristic(this.hap.Characteristic.Model, 'W2701600')
110
- .setCharacteristic(this.hap.Characteristic.SerialNumber, device.deviceId)
111
- .setCharacteristic(this.hap.Characteristic.FirmwareRevision, accessory.context.FirmwareRevision);
112
- // get the WindowCovering service if it exists, otherwise create a new WindowCovering service
113
- // you can create multiple services for each accessory
114
- const windowCoveringService = `${device.deviceName} ${device.deviceType}`;
115
- (this.windowCoveringService =
116
- accessory.getService(this.hap.Service.WindowCovering)
117
- || accessory.addService(this.hap.Service.WindowCovering)), windowCoveringService;
118
- this.windowCoveringService.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
119
- if (!this.windowCoveringService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
120
- this.windowCoveringService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
121
- }
122
- // create handlers for required characteristics
123
- this.windowCoveringService.setCharacteristic(this.hap.Characteristic.PositionState, this.PositionState);
124
- this.windowCoveringService
125
- .getCharacteristic(this.hap.Characteristic.CurrentPosition)
35
+ // Initialize WindowCovering Service
36
+ accessory.context.WindowCovering = accessory.context.WindowCovering ?? {};
37
+ this.WindowCovering = {
38
+ Name: accessory.context.WindowCovering.Name ?? accessory.displayName,
39
+ Service: accessory.getService(this.hap.Service.WindowCovering) ?? accessory.addService(this.hap.Service.WindowCovering),
40
+ PositionState: accessory.context.PositionState ?? this.hap.Characteristic.PositionState.STOPPED,
41
+ TargetPosition: accessory.context.TargetPosition ?? 100,
42
+ CurrentPosition: accessory.context.CurrentPosition ?? 100,
43
+ TargetHorizontalTiltAngle: accessory.context.TargetHorizontalTiltAngle ?? 90,
44
+ CurrentHorizontalTiltAngle: accessory.context.CurrentHorizontalTiltAngle ?? 90,
45
+ };
46
+ accessory.context.WindowCovering = this.WindowCovering;
47
+ // Initialize WindowCovering Characteristics
48
+ this.WindowCovering.Service
49
+ .setCharacteristic(this.hap.Characteristic.Name, this.WindowCovering.Name)
50
+ .getCharacteristic(this.hap.Characteristic.TargetPosition)
126
51
  .setProps({
127
- minStep: this.minStep(device),
52
+ minStep: device.blindTilt?.set_minStep ?? 1,
128
53
  minValue: 0,
129
54
  maxValue: 100,
130
55
  validValueRanges: [0, 100],
131
56
  })
132
57
  .onGet(() => {
133
- return this.CurrentPosition;
134
- });
135
- this.windowCoveringService
136
- .getCharacteristic(this.hap.Characteristic.TargetPosition)
58
+ return this.WindowCovering.TargetPosition;
59
+ })
60
+ .onSet(this.TargetPositionSet.bind(this));
61
+ // Initialize WindowCovering CurrentPosition Characteristic
62
+ this.WindowCovering.Service
63
+ .getCharacteristic(this.hap.Characteristic.CurrentPosition)
137
64
  .setProps({
138
- minStep: this.minStep(device),
65
+ minStep: device.blindTilt?.set_minStep ?? 1,
139
66
  minValue: 0,
140
67
  maxValue: 100,
141
68
  validValueRanges: [0, 100],
142
- })
143
- .onSet(this.TargetPositionSet.bind(this));
144
- this.CurrentHorizontalTiltAngle = 90;
145
- this.windowCoveringService
146
- .getCharacteristic(this.hap.Characteristic.CurrentHorizontalTiltAngle)
69
+ }).onGet(() => {
70
+ return this.WindowCovering?.CurrentPosition ?? 0;
71
+ });
72
+ // Initialize WindowCovering TargetHorizontalTiltAngle Characteristic
73
+ this.WindowCovering.Service
74
+ .getCharacteristic(this.hap.Characteristic.TargetHorizontalTiltAngle)
147
75
  .setProps({
148
76
  minStep: 180,
149
77
  minValue: -90,
@@ -151,27 +79,62 @@ export class BlindTilt {
151
79
  validValues: [-90, 90],
152
80
  })
153
81
  .onGet(() => {
154
- // this.debugLog(`requested CurrentHorizontalTiltAngle: ${this.CurrentHorizontalTiltAngle}`);
155
- return this.CurrentHorizontalTiltAngle;
156
- });
157
- this.TargetHorizontalTiltAngle = 90;
158
- this.windowCoveringService
159
- .getCharacteristic(this.hap.Characteristic.TargetHorizontalTiltAngle)
82
+ return this.WindowCovering.TargetHorizontalTiltAngle;
83
+ })
84
+ .onSet(this.TargetHorizontalTiltAngleSet.bind(this));
85
+ // Initialize WindowCovering CurrentHorizontalTiltAngle Characteristic
86
+ this.WindowCovering.Service
87
+ .getCharacteristic(this.hap.Characteristic.CurrentHorizontalTiltAngle)
160
88
  .setProps({
161
89
  minStep: 180,
162
90
  minValue: -90,
163
91
  maxValue: 90,
164
92
  validValues: [-90, 90],
165
- })
166
- .onSet(this.TargetHorizontalTiltAngleSet.bind(this));
167
- // Battery Service
168
- const batteryService = `${accessory.displayName} Battery`;
169
- (this.batteryService = this.accessory.getService(this.hap.Service.Battery)
170
- || accessory.addService(this.hap.Service.Battery)), batteryService;
171
- this.batteryService.setCharacteristic(this.hap.Characteristic.Name, `${accessory.displayName} Battery`);
172
- if (!this.batteryService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
173
- this.batteryService.addCharacteristic(this.hap.Characteristic.ConfiguredName, `${accessory.displayName} Battery`);
93
+ }).onGet(() => {
94
+ return this.WindowCovering.CurrentHorizontalTiltAngle ?? 0;
95
+ });
96
+ // Initialize Battery Service
97
+ accessory.context.Battery = accessory.context.Battery ?? {};
98
+ this.Battery = {
99
+ Name: accessory.context.Battery.Name ?? `${accessory.displayName} Battery`,
100
+ Service: accessory.getService(this.hap.Service.Battery) ?? accessory.addService(this.hap.Service.Battery),
101
+ BatteryLevel: accessory.context.BatteryLevel ?? 100,
102
+ StatusLowBattery: this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,
103
+ ChargingState: accessory.context.ChargingState ?? this.hap.Characteristic.ChargingState.NOT_CHARGING,
104
+ };
105
+ accessory.context.Battery = this.Battery;
106
+ // Initialize Battery Name Characteristic
107
+ this.Battery.Service
108
+ .setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name)
109
+ .setCharacteristic(this.hap.Characteristic.ChargingState, this.hap.Characteristic.ChargingState.NOT_CHARGEABLE);
110
+ // Initialize LightSensor Service
111
+ if (device.blindTilt?.hide_lightsensor) {
112
+ if (this.LightSensor?.Service) {
113
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} Removing Light Sensor Service`);
114
+ this.LightSensor.Service = accessory.getService(this.hap.Service.LightSensor);
115
+ accessory.removeService(this.LightSensor.Service);
116
+ accessory.context.LightSensor = {};
117
+ }
118
+ }
119
+ else {
120
+ accessory.context.LightSensor = accessory.context.LightSensor ?? {};
121
+ this.LightSensor = {
122
+ Name: accessory.context.LightSensor.Name ?? `${accessory.displayName} Light Sensor`,
123
+ Service: accessory.getService(this.hap.Service.LightSensor) ?? accessory.addService(this.hap.Service.LightSensor),
124
+ CurrentAmbientLightLevel: accessory.context.CurrentAmbientLightLevel ?? 0.0001,
125
+ };
126
+ accessory.context.LightSensor = this.LightSensor;
127
+ // Initialize LightSensor Characteristics
128
+ this.LightSensor.Service
129
+ .setCharacteristic(this.hap.Characteristic.Name, this.LightSensor.Name)
130
+ .setCharacteristic(this.hap.Characteristic.StatusActive, true)
131
+ .getCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel)
132
+ .onGet(() => {
133
+ return this.LightSensor?.CurrentAmbientLightLevel ?? 0.0001;
134
+ });
174
135
  }
136
+ // Retrieve initial values and updateHomekit
137
+ this.refreshStatus();
175
138
  // Update Homekit
176
139
  this.updateHomeKitCharacteristics();
177
140
  // Start an update interval
@@ -181,36 +144,15 @@ export class BlindTilt {
181
144
  await this.refreshStatus();
182
145
  });
183
146
  //regisiter webhook event handler
184
- if (this.device.webhook) {
185
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} is listening webhook.`);
186
- this.platform.webhookEventHandler[this.device.deviceId] = async (context) => {
187
- try {
188
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
189
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Please Submit Logs: ` + 'https://tinyurl.com/SwitchBotBug');
190
- /*const { temperature, humidity } = context;
191
- const { CurrentTemperature, CurrentRelativeHumidity } = this;
192
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ` +
193
- '(temperature, humidity) = ' +
194
- `Webhook:(${temperature}, ${humidity}), ` +
195
- `current:(${CurrentTemperature}, ${CurrentRelativeHumidity})`);
196
- this.CurrentRelativeHumidity = humidity;
197
- this.CurrentTemperature = temperature;
198
- this.updateHomeKitCharacteristics();*/
199
- }
200
- catch (e) {
201
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
202
- + `failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
203
- }
204
- };
205
- }
147
+ this.registerWebhook(accessory, device);
206
148
  // update slide progress
207
- interval(this.updateRate * 1000)
208
- //.pipe(skipWhile(() => this.blindTiltUpdateInProgress))
149
+ interval(this.deviceUpdateRate * 1000)
209
150
  .subscribe(async () => {
210
- if (this.PositionState === this.hap.Characteristic.PositionState.STOPPED) {
151
+ if (this.WindowCovering.PositionState === this.hap.Characteristic.PositionState.STOPPED) {
211
152
  return;
212
153
  }
213
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Refresh Status When Moving, PositionState: ${this.PositionState}`);
154
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} Refresh Status When Moving,`
155
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
214
156
  await this.refreshStatus();
215
157
  });
216
158
  // Watch for BlindTilt change events
@@ -218,213 +160,235 @@ export class BlindTilt {
218
160
  this.doBlindTiltUpdate
219
161
  .pipe(tap(() => {
220
162
  this.blindTiltUpdateInProgress = true;
221
- }), debounceTime(this.platform.config.options.pushRate * 1000))
163
+ }), debounceTime(this.devicePushRate * 1000))
222
164
  .subscribe(async () => {
223
165
  try {
224
166
  await this.pushChanges();
225
167
  }
226
168
  catch (e) {
227
169
  this.apiError(e);
228
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with ${this.device.connectionType} Connection,` +
229
- ` Error Message: ${JSON.stringify(e.message)}`);
170
+ this.errorLog(`${device.deviceType}: ${accessory.displayName} failed pushChanges with ${device.connectionType} Connection,`
171
+ + ` Error Message: ${JSON.stringify(e.message)}`);
230
172
  }
231
173
  this.blindTiltUpdateInProgress = false;
232
174
  });
233
175
  }
234
176
  /**
235
- * Parse the device status from the SwitchBot api
177
+ * Parse the device status from the SwitchBotBLE API
236
178
  */
237
- async parseStatus() {
238
- if (!this.device.enableCloudService && this.OpenAPI) {
239
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} parseStatus enableCloudService: ${this.device.enableCloudService}`);
240
- }
241
- else if (this.BLE) {
242
- await this.BLEparseStatus();
243
- }
244
- else if (this.OpenAPI && this.platform.config.credentials?.token) {
245
- await this.openAPIparseStatus();
246
- }
247
- else {
248
- await this.offlineOff();
249
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` + ` ${this.device.connectionType}, parseStatus will not happen.`);
250
- }
251
- }
252
- async BLEparseStatus() {
179
+ async BLEparseStatus(serviceData) {
253
180
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
254
181
  // CurrentPosition
255
- this.CurrentPosition = 100 - Number(this.BLE_CurrentPosition);
182
+ this.WindowCovering.CurrentPosition = 100 - Number(serviceData.position);
256
183
  await this.setMinMax();
257
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition ${this.CurrentPosition}`);
184
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition ${this.WindowCovering.CurrentPosition}`);
258
185
  if (this.setNewTarget) {
259
186
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Checking Status ...`);
260
187
  }
261
- if (this.setNewTarget && this.BLE_InMotion) {
188
+ if (this.setNewTarget && serviceData.inMotion) {
262
189
  await this.setMinMax();
263
- if (Number(this.TargetPosition) > this.CurrentPosition) {
264
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Closing, CurrentPosition: ${this.CurrentPosition}`);
265
- this.PositionState = this.hap.Characteristic.PositionState.INCREASING;
266
- this.windowCoveringService.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.PositionState);
267
- this.debugLog(`${this.device.deviceType}: ${this.CurrentPosition} INCREASING PositionState: ${this.PositionState}`);
268
- }
269
- else if (Number(this.TargetPosition) < this.CurrentPosition) {
270
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Opening, CurrentPosition: ${this.CurrentPosition}`);
271
- this.PositionState = this.hap.Characteristic.PositionState.DECREASING;
272
- this.windowCoveringService.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.PositionState);
273
- this.debugLog(`${this.device.deviceType}: ${this.CurrentPosition} DECREASING PositionState: ${this.PositionState}`);
190
+ if (Number(this.WindowCovering.TargetPosition) > this.WindowCovering.CurrentPosition) {
191
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
192
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
193
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
194
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} INCREASING`
195
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
196
+ }
197
+ else if (Number(this.WindowCovering.TargetPosition) < this.WindowCovering.CurrentPosition) {
198
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Opening, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
199
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
200
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
201
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} DECREASING`
202
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
274
203
  }
275
204
  else {
276
- this.debugLog(`${this.device.deviceType}: ${this.CurrentPosition} Standby2, CurrentPosition: ${this.CurrentPosition}`);
277
- this.PositionState = this.hap.Characteristic.PositionState.STOPPED;
278
- this.windowCoveringService.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.PositionState);
279
- this.debugLog(`${this.device.deviceType}: ${this.CurrentPosition} STOPPED PositionState: ${this.PositionState}`);
205
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} Standby2,`
206
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
207
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
208
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
209
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} STOPPED`
210
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
280
211
  }
281
212
  }
282
213
  else {
283
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Standby, CurrentPosition: ${this.CurrentPosition}`);
284
- this.TargetPosition = this.CurrentPosition;
285
- this.PositionState = this.hap.Characteristic.PositionState.STOPPED;
214
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
215
+ this.WindowCovering.TargetPosition = this.WindowCovering.CurrentPosition;
216
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
286
217
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Stopped`);
287
218
  }
288
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition},` +
289
- ` TargetPosition: ${this.TargetPosition}, PositionState: ${this.PositionState},`);
219
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition},`
220
+ + ` TargetPosition: ${this.WindowCovering.TargetPosition}, PositionState: ${this.WindowCovering.PositionState},`);
290
221
  if (!this.device.blindTilt?.hide_lightsensor) {
291
- this.set_minLux = this.minLux();
292
- this.set_maxLux = this.maxLux();
293
- this.spaceBetweenLevels = 9;
222
+ const set_minLux = this.device.blindTilt?.set_minLux ?? 1;
223
+ const set_maxLux = this.device.blindTilt?.set_maxLux ?? 6001;
224
+ const spaceBetweenLevels = 9;
225
+ if (this.LightSensor?.CurrentAmbientLightLevel === 0) {
226
+ this.LightSensor.CurrentAmbientLightLevel = 0.0001;
227
+ }
294
228
  // Brightness
295
- switch (this.BLE_CurrentAmbientLightLevel) {
229
+ switch (serviceData.lightLevel) {
296
230
  case 1:
297
- this.CurrentAmbientLightLevel = this.set_minLux;
298
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.BLE_CurrentAmbientLightLevel}`);
231
+ this.LightSensor.CurrentAmbientLightLevel = set_minLux;
232
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
299
233
  break;
300
234
  case 2:
301
- this.CurrentAmbientLightLevel = (this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels;
302
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.BLE_CurrentAmbientLightLevel},` +
303
- ` Calculation: ${(this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels}`);
235
+ this.LightSensor.CurrentAmbientLightLevel = (set_maxLux - set_minLux) / spaceBetweenLevels;
236
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel},`
237
+ + ` Calculation: ${(set_maxLux - set_minLux) / spaceBetweenLevels}`);
304
238
  break;
305
239
  case 3:
306
- this.CurrentAmbientLightLevel = ((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels) * 2;
307
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.BLE_CurrentAmbientLightLevel}`);
240
+ this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 2;
241
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
308
242
  break;
309
243
  case 4:
310
- this.CurrentAmbientLightLevel = ((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels) * 3;
311
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.BLE_CurrentAmbientLightLevel}`);
244
+ this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 3;
245
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
312
246
  break;
313
247
  case 5:
314
- this.CurrentAmbientLightLevel = ((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels) * 4;
315
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.BLE_CurrentAmbientLightLevel}`);
248
+ this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 4;
249
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
316
250
  break;
317
251
  case 6:
318
- this.CurrentAmbientLightLevel = ((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels) * 5;
319
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.BLE_CurrentAmbientLightLevel}`);
252
+ this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 5;
253
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
320
254
  break;
321
255
  case 7:
322
- this.CurrentAmbientLightLevel = ((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels) * 6;
323
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.BLE_CurrentAmbientLightLevel}`);
256
+ this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 6;
257
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
324
258
  break;
325
259
  case 8:
326
- this.CurrentAmbientLightLevel = ((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels) * 7;
327
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.BLE_CurrentAmbientLightLevel}`);
260
+ this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 7;
261
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
328
262
  break;
329
263
  case 9:
330
- this.CurrentAmbientLightLevel = ((this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels) * 8;
331
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.BLE_CurrentAmbientLightLevel}`);
264
+ this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 8;
265
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
332
266
  break;
333
267
  case 10:
334
268
  default:
335
- this.CurrentAmbientLightLevel = this.set_maxLux;
269
+ this.LightSensor.CurrentAmbientLightLevel = set_maxLux;
336
270
  this.debugLog();
337
271
  }
338
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.BLE_CurrentAmbientLightLevel},` +
339
- ` CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
272
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel},`
273
+ + ` CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
340
274
  }
341
275
  // Battery
342
- this.BatteryLevel = Number(this.BLE_BatteryLevel);
343
- if (this.BatteryLevel < 10) {
344
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
276
+ this.Battery.BatteryLevel = Number(serviceData.battery);
277
+ if (this.Battery.BatteryLevel < 10) {
278
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
345
279
  }
346
280
  else {
347
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
281
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
348
282
  }
349
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel},` + ` StatusLowBattery: ${this.StatusLowBattery}`);
283
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
284
+ + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
350
285
  }
351
- async openAPIparseStatus() {
286
+ /**
287
+ * Parse the device status from the SwitchBot OpenAPI
288
+ */
289
+ async openAPIparseStatus(deviceStatus) {
352
290
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
353
- const [homekitPosition, homekitTiltAngle] = this.mapDeviceValuesToHomekitValues(Number(this.OpenAPI_CurrentPosition), String(this.OpenAPI_Direction));
354
- this.debugLog(` device: ${this.OpenAPI_CurrentPosition} => HK: ${homekitPosition}`);
355
- this.CurrentPosition = homekitPosition;
291
+ const [homekitPosition, homekitTiltAngle] = this.mapDeviceValuesToHomekitValues(Number(deviceStatus.body.slidePosition), String(deviceStatus.body.direction));
292
+ this.debugLog(` device: ${deviceStatus.body.slidePosition} => HK: ${homekitPosition}`);
293
+ this.WindowCovering.CurrentPosition = homekitPosition;
356
294
  // CurrentPosition
357
295
  await this.setMinMax();
358
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition}`);
296
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
359
297
  if (homekitTiltAngle) {
360
- this.CurrentHorizontalTiltAngle = homekitTiltAngle;
361
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentHorizontalTiltAngle: ${this.CurrentHorizontalTiltAngle}`);
298
+ this.WindowCovering.CurrentHorizontalTiltAngle = homekitTiltAngle;
299
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
300
+ + ` CurrentHorizontalTiltAngle: ${this.WindowCovering.CurrentHorizontalTiltAngle}`);
362
301
  }
363
302
  if (this.setNewTarget) {
364
303
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Checking Status ...`);
365
304
  }
366
- if (this.setNewTarget && this.OpenAPI_InMotion) {
305
+ if (this.setNewTarget && deviceStatus.body.moving) {
367
306
  await this.setMinMax();
368
- if (this.TargetPosition > this.CurrentPosition || (homekitTiltAngle && this.TargetHorizontalTiltAngle !== this.CurrentHorizontalTiltAngle)) {
369
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Closing, CurrentPosition: ${this.CurrentPosition} `);
370
- this.PositionState = this.hap.Characteristic.PositionState.INCREASING;
371
- this.windowCoveringService.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.PositionState);
372
- this.debugLog(`${this.device.deviceType}: ${this.CurrentPosition} INCREASING PositionState: ${this.PositionState}`);
373
- }
374
- else if (this.TargetPosition < this.CurrentPosition) {
375
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Opening, CurrentPosition: ${this.CurrentPosition} `);
376
- this.PositionState = this.hap.Characteristic.PositionState.DECREASING;
377
- this.windowCoveringService.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.PositionState);
378
- this.debugLog(`${this.device.deviceType}: ${this.CurrentPosition} DECREASING PositionState: ${this.PositionState}`);
307
+ if (this.WindowCovering.TargetPosition > this.WindowCovering.CurrentPosition
308
+ || (homekitTiltAngle && this.WindowCovering.TargetHorizontalTiltAngle !== this.WindowCovering.CurrentHorizontalTiltAngle)) {
309
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition} `);
310
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
311
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
312
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} INCREASING`
313
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
314
+ }
315
+ else if (this.WindowCovering.TargetPosition < this.WindowCovering.CurrentPosition) {
316
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Opening, CurrentPosition: ${this.WindowCovering.CurrentPosition} `);
317
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
318
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
319
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} DECREASING`
320
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
379
321
  }
380
322
  else {
381
- this.debugLog(`${this.device.deviceType}: ${this.CurrentPosition} Standby because reached position,` + ` CurrentPosition: ${this.CurrentPosition}`);
382
- this.PositionState = this.hap.Characteristic.PositionState.STOPPED;
383
- this.windowCoveringService.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.PositionState);
384
- this.debugLog(`${this.device.deviceType}: ${this.CurrentPosition} STOPPED PositionState: ${this.PositionState}`);
323
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} Standby because reached position,`
324
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
325
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
326
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
327
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} STOPPED`
328
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
385
329
  }
386
330
  }
387
331
  else {
388
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Standby because device not moving,` + ` CurrentPosition: ${this.CurrentPosition}`);
389
- this.TargetPosition = this.CurrentPosition;
332
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Standby because device not moving,`
333
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
334
+ this.WindowCovering.TargetPosition = this.WindowCovering.CurrentPosition;
390
335
  if (homekitTiltAngle) {
391
- this.TargetHorizontalTiltAngle = this.CurrentHorizontalTiltAngle;
336
+ this.WindowCovering.TargetHorizontalTiltAngle = this.WindowCovering.CurrentHorizontalTiltAngle;
392
337
  }
393
- this.PositionState = this.hap.Characteristic.PositionState.STOPPED;
338
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
394
339
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Stopped`);
395
340
  }
396
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition},` +
397
- ` TargetPosition: ${this.TargetPosition}, PositionState: ${this.PositionState},`);
341
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition},`
342
+ + ` TargetPosition: ${this.WindowCovering.TargetPosition}, PositionState: ${this.WindowCovering.PositionState},`);
398
343
  if (!this.device.blindTilt?.hide_lightsensor) {
399
- this.set_minLux = this.minLux();
400
- this.set_maxLux = this.maxLux();
344
+ const set_minLux = this.device.blindTilt?.set_minLux ?? 1;
345
+ const set_maxLux = this.device.blindTilt?.set_maxLux ?? 6001;
401
346
  // Brightness
402
- switch (this.OpenAPI_CurrentAmbientLightLevel) {
347
+ switch (deviceStatus.body.brightness) {
403
348
  case 'dim':
404
- this.CurrentAmbientLightLevel = this.set_minLux;
349
+ this.LightSensor.CurrentAmbientLightLevel = set_minLux;
405
350
  break;
406
351
  case 'bright':
407
352
  default:
408
- this.CurrentAmbientLightLevel = this.set_maxLux;
353
+ this.LightSensor.CurrentAmbientLightLevel = set_maxLux;
409
354
  }
410
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
355
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
356
+ + ` CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
411
357
  }
412
358
  // BatteryLevel
413
- this.BatteryLevel = Number(this.OpenAPI_BatteryLevel);
414
- if (this.BatteryLevel < 10) {
415
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
359
+ this.Battery.BatteryLevel = Number(deviceStatus.body.battery);
360
+ if (this.Battery.BatteryLevel < 10) {
361
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
416
362
  }
417
363
  else {
418
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
364
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
365
+ }
366
+ if (Number.isNaN(this.Battery.BatteryLevel)) {
367
+ this.Battery.BatteryLevel = 100;
368
+ }
369
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
370
+ + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
371
+ // Firmware Version
372
+ const version = deviceStatus.body.version?.toString();
373
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Firmware Version: ${version?.replace(/^V|-.*$/g, '')}`);
374
+ let deviceVersion;
375
+ if (version?.includes('.') === false) {
376
+ const replace = version?.replace(/^V|-.*$/g, '');
377
+ const match = replace?.match(/.{1,1}/g);
378
+ const blindTiltVersion = match?.join('.') ?? '0.0.0';
379
+ deviceVersion = blindTiltVersion;
419
380
  }
420
- if (Number.isNaN(this.BatteryLevel)) {
421
- this.BatteryLevel = 100;
381
+ else {
382
+ deviceVersion = version?.replace(/^V|-.*$/g, '') ?? '0.0.0';
422
383
  }
423
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel},`
424
- + ` StatusLowBattery: ${this.StatusLowBattery}`);
425
- // FirmwareRevision
426
- this.FirmwareRevision = this.OpenAPI_FirmwareRevision;
427
- this.accessory.context.FirmwareRevision = this.FirmwareRevision;
384
+ this.accessory
385
+ .getService(this.hap.Service.AccessoryInformation)
386
+ .setCharacteristic(this.hap.Characteristic.HardwareRevision, deviceVersion)
387
+ .setCharacteristic(this.hap.Characteristic.FirmwareRevision, deviceVersion)
388
+ .getCharacteristic(this.hap.Characteristic.FirmwareRevision)
389
+ .updateValue(deviceVersion);
390
+ this.accessory.context.deviceVersion = deviceVersion;
391
+ this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceVersion: ${this.accessory.context.deviceVersion}`);
428
392
  }
429
393
  async refreshStatus() {
430
394
  if (!this.device.enableCloudService && this.OpenAPI) {
@@ -438,8 +402,8 @@ export class BlindTilt {
438
402
  }
439
403
  else {
440
404
  await this.offlineOff();
441
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` +
442
- ` ${this.device.connectionType}, refreshStatus will not happen.`);
405
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
406
+ + ` ${this.device.connectionType}, refreshStatus will not happen.`);
443
407
  }
444
408
  }
445
409
  async BLERefreshStatus() {
@@ -455,21 +419,13 @@ export class BlindTilt {
455
419
  // Start to monitor advertisement packets
456
420
  (async () => {
457
421
  // Start to monitor advertisement packets
458
- await switchbot.startScan({
459
- model: 'x',
460
- id: this.device.bleMac,
461
- });
422
+ await switchbot.startScan({ model: this.device.bleModel, id: this.device.bleMac });
462
423
  // Set an event handler
463
424
  switchbot.onadvertisement = (ad) => {
464
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
465
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.model}`);
466
- if (this.device.bleMac === ad.address && ad.model === 'x') {
425
+ if (this.device.bleMac === ad.address && ad.model === this.device.bleModel) {
426
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
427
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.model}`);
467
428
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
468
- this.BLE_Calibration = ad.serviceData.calibration;
469
- this.BLE_BatteryLevel = ad.serviceData.battery;
470
- this.BLE_InMotion = ad.serviceData.inMotion;
471
- this.BLE_CurrentPosition = ad.serviceData.position;
472
- this.BLE_CurrentAmbientLightLevel = ad.serviceData.lightLevel;
473
429
  }
474
430
  else {
475
431
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
@@ -480,82 +436,25 @@ export class BlindTilt {
480
436
  // Stop to monitor
481
437
  await switchbot.stopScan();
482
438
  // Update HomeKit
483
- await this.BLEparseStatus();
439
+ await this.BLEparseStatus(switchbot.onadvertisement.serviceData);
484
440
  await this.updateHomeKitCharacteristics();
485
441
  })();
486
- /*if (switchbot !== false) {
487
- switchbot
488
- .startScan({
489
- model: 'c',
490
- id: this.device.bleMac,
491
- })
492
- .then(async () => {
493
- // Set an event handler
494
- switchbot.onadvertisement = async (ad: ad) => {
495
- this.debugLog(
496
- `${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac},` +
497
- ` BLE Address Found: ${ad.address}`,
498
- );
499
- this.BLE_Calibration = ad.serviceData.calibration;
500
- this.BLE_BatteryLevel = ad.serviceData.battery;
501
- this.BLE_InMotion = ad.serviceData.inMotion;
502
- this.BLE_CurrentPosition = ad.serviceData.position;
503
- this.BLE_CurrentAmbientLightLevel = ad.serviceData.lightLevel;
504
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
505
- this.debugLog(
506
- `${this.device.deviceType}: ${this.accessory.displayName} calibration: ${ad.serviceData.calibration}, ` +
507
- `position: ${ad.serviceData.position}, lightLevel: ${ad.serviceData.lightLevel}, battery: ${ad.serviceData.battery}, ` +
508
- `inMotion: ${ad.serviceData.inMotion}`,
509
- );
510
-
511
- if (ad.serviceData) {
512
- this.BLE_IsConnected = true;
513
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.BLE_IsConnected}`);
514
- await this.stopScanning(switchbot);
515
- } else {
516
- this.BLE_IsConnected = false;
517
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.BLE_IsConnected}`);
518
- }
519
- };
520
- // Wait
521
- return await sleep(this.scanDuration * 1000);
522
- })
523
- .then(async () => {
524
- // Stop to monitor
525
- await this.stopScanning(switchbot);
526
- })
527
- .catch(async (e: any) => {
528
- this.apiError(e);
529
- this.errorLog(
530
- `${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}` +
531
- ` Connection, Error Message: ${JSON.stringify(e.message)}`,
532
- );
533
- await this.BLERefreshConnection(switchbot);
534
- });
535
- } else {
536
- await this.BLERefreshConnection(switchbot);
537
- }*/
442
+ if (switchbot === undefined) {
443
+ await this.BLERefreshConnection(switchbot);
444
+ }
538
445
  }
539
446
  async openAPIRefreshStatus() {
540
447
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
541
448
  try {
542
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/status`, {
543
- headers: this.platform.generateHeaders(),
544
- });
449
+ const { body, statusCode } = await this.platform.retryRequest(this.deviceMaxRetries, this.deviceDelayBetweenRetries, `${Devices}/${this.device.deviceId}/status`, { headers: this.platform.generateHeaders() });
545
450
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
546
451
  const deviceStatus = await body.json();
547
452
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
548
453
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
549
454
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
550
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
455
+ this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
551
456
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
552
- this.OpenAPI_CurrentPosition = deviceStatus.body.slidePosition;
553
- this.OpenAPI_Direction = deviceStatus.body.direction;
554
- this.OpenAPI_InMotion = deviceStatus.body.moving;
555
- this.OpenAPI_CurrentAmbientLightLevel = deviceStatus.body.brightness;
556
- this.OpenAPI_BatteryLevel = deviceStatus.body.battery;
557
- this.OpenAPI_FirmwareRevision = deviceStatus.body.version;
558
- this.openAPIparseStatus();
457
+ this.openAPIparseStatus(deviceStatus);
559
458
  this.updateHomeKitCharacteristics();
560
459
  }
561
460
  else {
@@ -565,8 +464,36 @@ export class BlindTilt {
565
464
  }
566
465
  catch (e) {
567
466
  this.apiError(e);
568
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}` +
569
- ` Connection, Error Message: ${JSON.stringify(e.message)}`);
467
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
468
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
469
+ }
470
+ }
471
+ async registerWebhook(accessory, device) {
472
+ if (device.webhook) {
473
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} is listening webhook.`);
474
+ this.platform.webhookEventHandler[this.device.deviceId] = async (context) => {
475
+ try {
476
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
477
+ const { slidePosition, battery, lightLevel } = context;
478
+ const { CurrentPosition } = this.WindowCovering;
479
+ const { BatteryLevel } = this.Battery;
480
+ const { CurrentAmbientLightLevel } = this.LightSensor ?? {};
481
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} (slidePosition, battery, lightLevel) = Webhook:(${slidePosition}, ${battery},`
482
+ + ` ${lightLevel}), current:(${CurrentPosition}, ${BatteryLevel}, ${CurrentAmbientLightLevel})`);
483
+ this.WindowCovering.CurrentPosition = slidePosition;
484
+ this.Battery.BatteryLevel = battery;
485
+ if (!device.blindTilt?.hide_lightsensor) {
486
+ this.LightSensor.CurrentAmbientLightLevel = lightLevel;
487
+ }
488
+ this.updateHomeKitCharacteristics();
489
+ }
490
+ catch (e) {
491
+ this.errorLog(`${device.deviceType}: ${accessory.displayName} failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
492
+ }
493
+ };
494
+ }
495
+ else {
496
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} is not listening webhook.`);
570
497
  }
571
498
  }
572
499
  async pushChanges() {
@@ -581,7 +508,8 @@ export class BlindTilt {
581
508
  }
582
509
  else {
583
510
  await this.offlineOff();
584
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` + ` ${this.device.connectionType}, pushChanges will not happen.`);
511
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
512
+ + ` ${this.device.connectionType}, pushChanges will not happen.`);
585
513
  }
586
514
  // Refresh the status from the API
587
515
  interval(15000)
@@ -593,7 +521,7 @@ export class BlindTilt {
593
521
  }
594
522
  async BLEpushChanges() {
595
523
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
596
- if (this.TargetPosition !== this.CurrentPosition) {
524
+ if (this.WindowCovering.TargetPosition !== this.WindowCovering.CurrentPosition) {
597
525
  const switchbot = await this.platform.connectBLE();
598
526
  // Convert to BLE Address
599
527
  this.device.bleMac = this.device
@@ -601,31 +529,29 @@ export class BlindTilt {
601
529
  .join(':')
602
530
  .toLowerCase();
603
531
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
604
- this.SilentPerformance();
605
- const adjustedMode = this.setPositionMode || null;
606
- if (adjustedMode === null) {
607
- this.Mode = 'Default Mode';
608
- }
609
- this.debugLog(`${this.accessory.displayName} Mode: ${this.Mode}`);
532
+ const { setPositionMode, Mode } = await this.setPerformance();
533
+ this.debugLog(`${this.accessory.displayName} Mode: ${Mode}`);
610
534
  if (switchbot !== false) {
611
535
  switchbot
612
536
  .discover({ model: 'c', quick: true, id: this.device.bleMac })
613
537
  .then(async (device_list) => {
614
- this.infoLog(`${this.accessory.displayName} Target Position: ${this.TargetPosition}`);
615
- return await this.retry({
616
- max: this.maxRetry(),
538
+ this.infoLog(`${this.accessory.displayName} Target Position: ${this.WindowCovering.TargetPosition}`);
539
+ return await this.retryBLE({
540
+ max: await this.maxRetryBLE(),
617
541
  fn: async () => {
618
- return await device_list[0].runToPos(100 - Number(this.TargetPosition), adjustedMode);
542
+ return await device_list[0].runToPos(100 - Number(this.WindowCovering.TargetPosition), setPositionMode);
619
543
  },
620
544
  });
621
545
  })
622
546
  .then(() => {
623
547
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
548
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
549
+ + `Target Position: ${this.WindowCovering.TargetPosition} sent over BLE, sent successfully`);
624
550
  })
625
551
  .catch(async (e) => {
626
552
  this.apiError(e);
627
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}` +
628
- ` Connection, Error Message: ${JSON.stringify(e.message)}`);
553
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
554
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
629
555
  await this.BLEPushConnection();
630
556
  });
631
557
  }
@@ -635,46 +561,33 @@ export class BlindTilt {
635
561
  }
636
562
  }
637
563
  else {
638
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges, CurrentPosition & TargetPosition Are the Same.` +
639
- ` CurrentPosition: ${this.CurrentPosition}, TargetPosition ${this.TargetPosition}`);
640
- }
641
- }
642
- async retry({ max, fn }) {
643
- return fn().catch(async (e) => {
644
- if (max === 0) {
645
- throw e;
646
- }
647
- this.infoLog(e);
648
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Retrying`);
649
- await sleep(1000);
650
- return this.retry({ max: max - 1, fn });
651
- });
652
- }
653
- maxRetry() {
654
- if (this.device.maxRetry) {
655
- return this.device.maxRetry;
656
- }
657
- else {
658
- return 5;
564
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges, CurrentPosition & TargetPosition Are the Same.`
565
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition ${this.WindowCovering.TargetPosition}`);
659
566
  }
660
567
  }
661
568
  async openAPIpushChanges() {
662
569
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
663
- const hasDifferentAndRelevantHorizontalTiltAngle = this.mappingMode === BlindTiltMappingMode.UseTiltForDirection && this.TargetHorizontalTiltAngle !== this.CurrentHorizontalTiltAngle;
664
- if (this.TargetPosition !== this.CurrentPosition || hasDifferentAndRelevantHorizontalTiltAngle || this.device.disableCaching) {
665
- const [direction, position] = this.mapHomekitValuesToDeviceValues(Number(this.TargetPosition), Number(this.TargetHorizontalTiltAngle));
666
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Pushing ${this.TargetPosition} (device = ${direction};${position})`);
667
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Mode: ${this.Mode}`);
570
+ const hasDifferentAndRelevantHorizontalTiltAngle = this.mappingMode === BlindTiltMappingMode.UseTiltForDirection
571
+ && this.WindowCovering.TargetHorizontalTiltAngle !== this.WindowCovering.CurrentHorizontalTiltAngle;
572
+ if (this.WindowCovering.TargetPosition !== this.WindowCovering.CurrentPosition
573
+ || hasDifferentAndRelevantHorizontalTiltAngle || this.device.disableCaching) {
574
+ const [direction, position] = this.mapHomekitValuesToDeviceValues(Number(this.WindowCovering.TargetPosition), Number(this.WindowCovering.TargetHorizontalTiltAngle));
575
+ const { Mode } = await this.setPerformance();
576
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
577
+ + ` Pushing ${this.WindowCovering.TargetPosition} (device = ${direction};${position})`);
578
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Mode: ${Mode}`);
668
579
  let bodyChange = '';
669
580
  if (position === 100) {
670
581
  bodyChange = JSON.stringify({
671
582
  command: 'fullyOpen',
583
+ parameter: 'default',
672
584
  commandType: 'command',
673
585
  });
674
586
  }
675
587
  else if (position === 0) {
676
588
  bodyChange = JSON.stringify({
677
589
  command: direction === 'up' ? 'closeUp' : 'closeDown',
590
+ parameter: 'default',
678
591
  commandType: 'command',
679
592
  });
680
593
  }
@@ -698,8 +611,10 @@ export class BlindTilt {
698
611
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
699
612
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
700
613
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
701
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
614
+ this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
702
615
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
616
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
617
+ + `request to SwitchBot API, body: ${JSON.stringify(JSON.parse(bodyChange))} sent successfully`);
703
618
  }
704
619
  else {
705
620
  this.statusCode(statusCode);
@@ -708,30 +623,31 @@ export class BlindTilt {
708
623
  }
709
624
  catch (e) {
710
625
  this.apiError(e);
711
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}` +
712
- ` Connection, Error Message: ${JSON.stringify(e.message)}`);
626
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
627
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
713
628
  }
714
629
  }
715
630
  else {
716
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No OpenAPI Changes, CurrentPosition & TargetPosition Are the Same.` +
717
- ` CurrentPosition: ${this.CurrentPosition}, TargetPosition ${this.TargetPosition}` +
718
- ` CurrentHorizontalTiltAngle: ${this.CurrentHorizontalTiltAngle}, TargetPosition ${this.TargetHorizontalTiltAngle}`);
631
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No OpenAPI Changes, CurrentPosition & TargetPosition Are the Same.`
632
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition ${this.WindowCovering.TargetPosition}`
633
+ + ` CurrentHorizontalTiltAngle: ${this.WindowCovering.CurrentHorizontalTiltAngle},`
634
+ + ` TargetPosition ${this.WindowCovering.TargetHorizontalTiltAngle}`);
719
635
  }
720
636
  }
721
637
  /**
722
638
  * Handle requests to set the value of the "Target Horizontal Tilt" characteristic
723
639
  */
724
640
  async TargetHorizontalTiltAngleSet(value) {
725
- if (this.TargetHorizontalTiltAngle === this.accessory.context.TargetHorizontalTiltAngle) {
641
+ if (this.WindowCovering.TargetHorizontalTiltAngle === this.accessory.context.TargetHorizontalTiltAngle) {
726
642
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set TargetHorizontalTiltAngle: ${value}`);
727
643
  }
728
644
  else {
729
645
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetHorizontalTiltAngle: ${value}`);
730
646
  }
731
647
  //value = value < 0 ? -90 : 90;
732
- this.TargetHorizontalTiltAngle = value;
648
+ this.WindowCovering.TargetHorizontalTiltAngle = value;
733
649
  if (this.device.mqttURL) {
734
- this.mqttPublish('TargetHorizontalTiltAngle', this.TargetHorizontalTiltAngle);
650
+ this.mqttPublish('TargetHorizontalTiltAngle', this.WindowCovering.TargetHorizontalTiltAngle.toString());
735
651
  }
736
652
  this.startUpdatingBlindTiltIfNeeded();
737
653
  }
@@ -739,49 +655,53 @@ export class BlindTilt {
739
655
  * Handle requests to set the value of the "Target Position" characteristic
740
656
  */
741
657
  async TargetPositionSet(value) {
742
- if (this.TargetPosition === this.accessory.context.TargetPosition) {
658
+ if (this.WindowCovering.TargetPosition === this.accessory.context.TargetPosition) {
743
659
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set TargetPosition: ${value}`);
744
660
  }
745
661
  else {
746
662
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetPosition: ${value}`);
747
663
  }
748
- this.TargetPosition = value;
664
+ this.WindowCovering.TargetPosition = value;
749
665
  if (this.device.mqttURL) {
750
- this.mqttPublish('TargetPosition', this.TargetPosition);
666
+ this.mqttPublish('TargetPosition', this.WindowCovering.TargetPosition.toString());
751
667
  }
752
668
  this.startUpdatingBlindTiltIfNeeded();
753
669
  }
754
670
  async startUpdatingBlindTiltIfNeeded() {
755
671
  await this.setMinMax();
756
672
  this.debugLog('setMinMax');
757
- if (this.TargetPosition > this.CurrentPosition || this.TargetHorizontalTiltAngle !== this.CurrentHorizontalTiltAngle) {
758
- this.PositionState = this.hap.Characteristic.PositionState.INCREASING;
673
+ if (this.WindowCovering.TargetPosition > this.WindowCovering.CurrentPosition
674
+ || this.WindowCovering.TargetHorizontalTiltAngle !== this.WindowCovering.CurrentHorizontalTiltAngle) {
675
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
759
676
  this.setNewTarget = true;
760
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${this.CurrentPosition},` + ` CurrentPosition: ${this.CurrentPosition}`);
677
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${this.WindowCovering.CurrentPosition},`
678
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
761
679
  }
762
- else if (this.TargetPosition < this.CurrentPosition) {
763
- this.PositionState = this.hap.Characteristic.PositionState.DECREASING;
680
+ else if (this.WindowCovering.TargetPosition < this.WindowCovering.CurrentPosition) {
681
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
764
682
  this.setNewTarget = true;
765
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${this.CurrentPosition},` + ` CurrentPosition: ${this.CurrentPosition}`);
683
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${this.WindowCovering.CurrentPosition},`
684
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
766
685
  }
767
686
  else {
768
- this.PositionState = this.hap.Characteristic.PositionState.STOPPED;
687
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
769
688
  this.setNewTarget = false;
770
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${this.CurrentPosition},` + ` CurrentPosition: ${this.CurrentPosition}`);
689
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${this.WindowCovering.CurrentPosition},`
690
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
771
691
  }
772
- this.windowCoveringService.setCharacteristic(this.hap.Characteristic.PositionState, this.PositionState);
773
- this.windowCoveringService.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.PositionState);
692
+ this.WindowCovering.Service.setCharacteristic(this.hap.Characteristic.PositionState, this.WindowCovering.PositionState);
693
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
774
694
  /**
775
695
  * If Blind Tilt movement time is short, the moving flag from backend is always false.
776
696
  * The minimum time depends on the network control latency.
777
697
  */
778
698
  clearTimeout(this.setNewTargetTimer);
779
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateRate: ${this.updateRate}`);
699
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateRate: ${this.deviceUpdateRate}`);
780
700
  if (this.setNewTarget) {
781
701
  this.setNewTargetTimer = setTimeout(() => {
782
702
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} setNewTarget ${this.setNewTarget} timeout`);
783
703
  this.setNewTarget = false;
784
- }, this.updateRate * 1000);
704
+ }, this.deviceUpdateRate * 1000);
785
705
  }
786
706
  this.doBlindTiltUpdate.next();
787
707
  }
@@ -789,152 +709,111 @@ export class BlindTilt {
789
709
  await this.setMinMax();
790
710
  // CurrentHorizontalTiltAngle
791
711
  if (this.mappingMode === BlindTiltMappingMode.UseTiltForDirection) {
792
- if (this.CurrentHorizontalTiltAngle === undefined || Number.isNaN(this.CurrentHorizontalTiltAngle)) {
793
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentHorizontalTiltAngle: ${this.CurrentHorizontalTiltAngle}`);
712
+ if (this.WindowCovering.CurrentHorizontalTiltAngle === undefined || Number.isNaN(this.WindowCovering.CurrentHorizontalTiltAngle)) {
713
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
714
+ + ` CurrentHorizontalTiltAngle: ${this.WindowCovering.CurrentHorizontalTiltAngle}`);
794
715
  }
795
716
  else {
796
717
  if (this.device.mqttURL) {
797
- this.mqttPublish('CurrentHorizontalTiltAngle', this.CurrentHorizontalTiltAngle);
718
+ this.mqttPublish('CurrentHorizontalTiltAngle', this.WindowCovering.CurrentHorizontalTiltAngle.toString());
798
719
  }
799
- this.accessory.context.CurrentHorizontalTiltAngle = this.CurrentHorizontalTiltAngle;
800
- this.windowCoveringService.updateCharacteristic(this.hap.Characteristic.CurrentHorizontalTiltAngle, Number(this.CurrentHorizontalTiltAngle));
720
+ this.accessory.context.CurrentHorizontalTiltAngle = this.WindowCovering.CurrentHorizontalTiltAngle;
721
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentHorizontalTiltAngle, Number(this.WindowCovering.CurrentHorizontalTiltAngle));
801
722
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}
802
- updateCharacteristic CurrentHorizontalTiltAngle: ${this.CurrentHorizontalTiltAngle}`);
723
+ updateCharacteristic CurrentHorizontalTiltAngle: ${this.WindowCovering.CurrentHorizontalTiltAngle}`);
803
724
  }
804
725
  }
805
726
  // CurrentPosition
806
- if (this.CurrentPosition === undefined || Number.isNaN(this.CurrentPosition)) {
807
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition}`);
727
+ if (this.WindowCovering.CurrentPosition === undefined || Number.isNaN(this.WindowCovering.CurrentPosition)) {
728
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
808
729
  }
809
730
  else {
810
731
  if (this.device.mqttURL) {
811
- this.mqttPublish('CurrentPosition', this.CurrentPosition);
732
+ this.mqttPublish('CurrentPosition', this.WindowCovering.CurrentPosition.toString());
812
733
  }
813
- this.accessory.context.CurrentPosition = this.CurrentPosition;
814
- this.windowCoveringService.updateCharacteristic(this.hap.Characteristic.CurrentPosition, Number(this.CurrentPosition));
815
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic CurrentPosition: ${this.CurrentPosition}`);
734
+ this.accessory.context.CurrentPosition = this.WindowCovering.CurrentPosition;
735
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, Number(this.WindowCovering.CurrentPosition));
736
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
737
+ + ` updateCharacteristic CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
816
738
  }
817
739
  // PositionState
818
- if (this.PositionState === undefined) {
819
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} PositionState: ${this.PositionState}`);
740
+ if (this.WindowCovering.PositionState === undefined) {
741
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} PositionState: ${this.WindowCovering.PositionState}`);
820
742
  }
821
743
  else {
822
744
  if (this.device.mqttURL) {
823
- this.mqttPublish('PositionState', this.PositionState);
745
+ this.mqttPublish('PositionState', this.WindowCovering.PositionState.toString());
824
746
  }
825
- this.accessory.context.PositionState = this.PositionState;
826
- this.windowCoveringService.updateCharacteristic(this.hap.Characteristic.PositionState, Number(this.PositionState));
827
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic PositionState: ${this.PositionState}`);
747
+ this.accessory.context.PositionState = this.WindowCovering.PositionState;
748
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, Number(this.WindowCovering.PositionState));
749
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
750
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
828
751
  }
829
752
  // TargetPosition
830
- if (this.TargetPosition === undefined || Number.isNaN(this.TargetPosition)) {
831
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} TargetPosition: ${this.TargetPosition}`);
753
+ if (this.WindowCovering.TargetPosition === undefined || Number.isNaN(this.WindowCovering.TargetPosition)) {
754
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} TargetPosition: ${this.WindowCovering.TargetPosition}`);
832
755
  }
833
756
  else {
834
757
  if (this.device.mqttURL) {
835
- this.mqttPublish('TargetPosition', this.TargetPosition);
758
+ this.mqttPublish('TargetPosition', this.WindowCovering.TargetPosition.toString());
836
759
  }
837
- this.accessory.context.TargetPosition = this.TargetPosition;
838
- this.windowCoveringService.updateCharacteristic(this.hap.Characteristic.TargetPosition, Number(this.TargetPosition));
839
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic TargetPosition: ${this.TargetPosition}`);
760
+ this.accessory.context.TargetPosition = this.WindowCovering.TargetPosition;
761
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, Number(this.WindowCovering.TargetPosition));
762
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
763
+ + ` TargetPosition: ${this.WindowCovering.TargetPosition}`);
840
764
  }
841
765
  // CurrentAmbientLightLevel
842
766
  if (!this.device.blindTilt?.hide_lightsensor) {
843
- if (this.CurrentAmbientLightLevel === undefined || Number.isNaN(this.CurrentAmbientLightLevel)) {
844
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
767
+ if (this.LightSensor.CurrentAmbientLightLevel === undefined || Number.isNaN(this.LightSensor.CurrentAmbientLightLevel)) {
768
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
769
+ + ` CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
845
770
  }
846
771
  else {
847
772
  if (this.device.mqttURL) {
848
- this.mqttPublish('CurrentAmbientLightLevel', this.CurrentAmbientLightLevel);
773
+ this.mqttPublish('CurrentAmbientLightLevel', this.LightSensor.CurrentAmbientLightLevel.toString());
849
774
  }
850
- this.accessory.context.CurrentAmbientLightLevel = this.CurrentAmbientLightLevel;
851
- this.lightSensorService?.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, this.CurrentAmbientLightLevel);
852
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}` +
853
- ` updateCharacteristic CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
775
+ this.accessory.context.CurrentAmbientLightLevel = this.LightSensor.CurrentAmbientLightLevel;
776
+ this.LightSensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, this.LightSensor.CurrentAmbientLightLevel);
777
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
778
+ + ` updateCharacteristic CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
854
779
  }
855
780
  }
856
781
  // BatteryLevel
857
- if (this.BatteryLevel === undefined) {
858
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
782
+ if (this.Battery.BatteryLevel === undefined) {
783
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}`);
859
784
  }
860
785
  else {
861
786
  if (this.device.mqttURL) {
862
- this.mqttPublish('BatteryLevel', this.BatteryLevel);
787
+ this.mqttPublish('BatteryLevel', this.Battery.BatteryLevel.toString());
863
788
  }
864
- this.accessory.context.BatteryLevel = this.BatteryLevel;
865
- this.batteryService?.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.BatteryLevel);
866
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
789
+ this.accessory.context.BatteryLevel = this.Battery.BatteryLevel;
790
+ this.Battery?.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel);
791
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.Battery.BatteryLevel}`);
867
792
  }
868
793
  // StatusLowBattery
869
- if (this.StatusLowBattery === undefined) {
870
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
794
+ if (this.Battery.StatusLowBattery === undefined) {
795
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.Battery.StatusLowBattery}`);
871
796
  }
872
797
  else {
873
798
  if (this.device.mqttURL) {
874
- this.mqttPublish('StatusLowBattery', this.StatusLowBattery);
799
+ this.mqttPublish('StatusLowBattery', this.Battery.StatusLowBattery.toString());
875
800
  }
876
- this.accessory.context.StatusLowBattery = this.StatusLowBattery;
877
- this.batteryService?.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.StatusLowBattery);
878
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
801
+ this.accessory.context.StatusLowBattery = this.Battery.StatusLowBattery;
802
+ this.Battery?.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery);
803
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
804
+ + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
879
805
  }
880
- }
881
- /*
882
- * Publish MQTT message for topics of
883
- * 'homebridge-switchbot/blindtilt/xx:xx:xx:xx:xx:xx'
884
- */
885
- mqttPublish(topic, message) {
886
- const mac = this.device.deviceId
887
- ?.toLowerCase()
888
- .match(/[\s\S]{1,2}/g)
889
- ?.join(':');
890
- const options = this.device.mqttPubOptions || {};
891
- this.mqttClient?.publish(`homebridge-switchbot/blindtilt/${mac}/${topic}`, `${message}`, options);
892
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT message: ${topic}/${message} options:${JSON.stringify(options)}`);
893
- }
894
- /*
895
- * Setup MQTT hadler if URL is specified.
896
- */
897
- async setupMqtt(device) {
898
- if (device.mqttURL) {
899
- try {
900
- const { connectAsync } = asyncmqtt;
901
- this.mqttClient = await connectAsync(device.mqttURL, device.mqttOptions || {});
902
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT connection has been established successfully.`);
903
- this.mqttClient.on('error', (e) => {
904
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Failed to publish MQTT messages. ${e}`);
905
- });
906
- }
907
- catch (e) {
908
- this.mqttClient = null;
909
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Failed to establish MQTT connection. ${e}`);
910
- }
911
- }
912
- }
913
- async stopScanning(switchbot) {
914
- switchbot.stopScan();
915
- if (this.BLE_IsConnected) {
916
- await this.BLEparseStatus();
917
- await this.updateHomeKitCharacteristics();
806
+ if (this.Battery.ChargingState === undefined) {
807
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ChargingState: ${this.Battery.ChargingState}`);
918
808
  }
919
809
  else {
920
- await this.BLERefreshConnection(switchbot);
921
- }
922
- }
923
- async getCustomBLEAddress(switchbot) {
924
- if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
925
- (async () => {
926
- // Start to monitor advertisement packets
927
- await switchbot.startScan({
928
- model: 'c',
929
- });
930
- // Set an event handler
931
- switchbot.onadvertisement = (ad) => {
932
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${JSON.stringify(ad, null, ' ')}`);
933
- };
934
- await sleep(10000);
935
- // Stop to monitor
936
- switchbot.stopScan();
937
- })();
810
+ if (this.device.mqttURL) {
811
+ this.mqttPublish('ChargingState', this.Battery.ChargingState.toString());
812
+ }
813
+ this.accessory.context.ChargingState = this.Battery.ChargingState;
814
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.ChargingState, this.Battery.ChargingState);
815
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
816
+ + ` ChargingState: ${this.Battery.ChargingState}`);
938
817
  }
939
818
  }
940
819
  async BLEPushConnection() {
@@ -951,210 +830,75 @@ export class BlindTilt {
951
830
  await this.openAPIRefreshStatus();
952
831
  }
953
832
  }
954
- async SilentPerformance() {
955
- if (Number(this.TargetPosition) > 50) {
833
+ async setPerformance() {
834
+ let setPositionMode;
835
+ let Mode;
836
+ if (Number(this.WindowCovering.TargetPosition) > 50) {
956
837
  if (this.device.blindTilt?.setOpenMode === '1') {
957
- this.setPositionMode = 1;
958
- this.Mode = 'Silent Mode';
838
+ setPositionMode = 1;
839
+ Mode = 'Silent Mode';
840
+ }
841
+ else if (this.device.blindTilt?.setOpenMode === '0') {
842
+ setPositionMode = 0;
843
+ Mode = 'Performance Mode';
959
844
  }
960
845
  else {
961
- this.setPositionMode = 0;
962
- this.Mode = 'Performance Mode';
846
+ setPositionMode = 0;
847
+ Mode = 'Default Mode';
963
848
  }
964
849
  }
965
850
  else {
966
851
  if (this.device.blindTilt?.setCloseMode === '1') {
967
- this.setPositionMode = 1;
968
- this.Mode = 'Silent Mode';
852
+ setPositionMode = 1;
853
+ Mode = 'Silent Mode';
854
+ }
855
+ else if (this.device.blindTilt?.setOpenMode === '0') {
856
+ setPositionMode = 0;
857
+ Mode = 'Performance Mode';
969
858
  }
970
859
  else {
971
- this.setPositionMode = 0;
972
- this.Mode = 'Performance Mode';
860
+ setPositionMode = 0;
861
+ Mode = 'Default Mode';
973
862
  }
974
863
  }
864
+ return { setPositionMode, Mode };
975
865
  }
976
866
  async setMinMax() {
977
867
  if (this.device.blindTilt?.set_min) {
978
- if (Number(this.CurrentPosition) <= this.device.blindTilt?.set_min) {
979
- this.CurrentPosition = 0;
868
+ if (Number(this.WindowCovering.CurrentPosition) <= this.device.blindTilt?.set_min) {
869
+ this.WindowCovering.CurrentPosition = 0;
980
870
  }
981
871
  }
982
872
  if (this.device.blindTilt?.set_max) {
983
- if (Number(this.CurrentPosition) >= this.device.blindTilt?.set_max) {
984
- this.CurrentPosition = 100;
873
+ if (Number(this.WindowCovering.CurrentPosition) >= this.device.blindTilt?.set_max) {
874
+ this.WindowCovering.CurrentPosition = 100;
985
875
  }
986
876
  }
987
877
  if (this.mappingMode === BlindTiltMappingMode.UseTiltForDirection) {
988
- this.CurrentHorizontalTiltAngle = Number(this.CurrentHorizontalTiltAngle) < 0 ? -90 : 90;
989
- }
990
- }
991
- minStep(device) {
992
- if (device.blindTilt?.set_minStep) {
993
- this.set_minStep = device.blindTilt?.set_minStep;
994
- }
995
- else {
996
- this.set_minStep = 1;
997
- }
998
- return this.set_minStep;
999
- }
1000
- minLux() {
1001
- if (this.device.blindTilt?.set_minLux) {
1002
- this.set_minLux = this.device.blindTilt?.set_minLux;
1003
- }
1004
- else {
1005
- this.set_minLux = 1;
1006
- }
1007
- return this.set_minLux;
1008
- }
1009
- maxLux() {
1010
- if (this.device.blindTilt?.set_maxLux) {
1011
- this.set_maxLux = this.device.blindTilt?.set_maxLux;
1012
- }
1013
- else {
1014
- this.set_maxLux = 6001;
1015
- }
1016
- return this.set_maxLux;
1017
- }
1018
- async scan(device) {
1019
- if (device.scanDuration) {
1020
- if (this.updateRate > device.scanDuration) {
1021
- this.scanDuration = this.updateRate;
1022
- if (this.BLE) {
1023
- this.warnLog(`${this.device.deviceType}: ` +
1024
- `${this.accessory.displayName} scanDuration is less than updateRate, overriding scanDuration with updateRate`);
1025
- }
1026
- }
1027
- else {
1028
- this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
1029
- }
1030
- if (this.BLE) {
1031
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
1032
- }
1033
- }
1034
- else {
1035
- if (this.updateRate > 1) {
1036
- this.scanDuration = this.updateRate;
1037
- }
1038
- else {
1039
- this.scanDuration = this.accessory.context.scanDuration = 1;
1040
- }
1041
- if (this.BLE) {
1042
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
1043
- }
1044
- }
1045
- }
1046
- async statusCode(statusCode) {
1047
- switch (statusCode) {
1048
- case 151:
1049
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this deviceType, statusCode: ${statusCode}`);
1050
- break;
1051
- case 152:
1052
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found, statusCode: ${statusCode}`);
1053
- break;
1054
- case 160:
1055
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported, statusCode: ${statusCode}`);
1056
- break;
1057
- case 161:
1058
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline, statusCode: ${statusCode}`);
1059
- this.offlineOff();
1060
- break;
1061
- case 171:
1062
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Hub Device is offline, statusCode: ${statusCode}. ` +
1063
- `Hub: ${this.device.hubDeviceId}`);
1064
- this.offlineOff();
1065
- break;
1066
- case 190:
1067
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
1068
- ` Or command format is invalid, statusCode: ${statusCode}`);
1069
- break;
1070
- case 100:
1071
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent, statusCode: ${statusCode}`);
1072
- break;
1073
- case 200:
1074
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Request successful, statusCode: ${statusCode}`);
1075
- break;
1076
- case 400:
1077
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Bad Request, The client has issued an invalid request. `
1078
- + `This is commonly used to specify validation errors in a request payload, statusCode: ${statusCode}`);
1079
- break;
1080
- case 401:
1081
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unauthorized, Authorization for the API is required, `
1082
- + `but the request has not been authenticated, statusCode: ${statusCode}`);
1083
- break;
1084
- case 403:
1085
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Forbidden, The request has been authenticated but does not `
1086
- + `have appropriate permissions, or a requested resource is not found, statusCode: ${statusCode}`);
1087
- break;
1088
- case 404:
1089
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Not Found, Specifies the requested path does not exist, `
1090
- + `statusCode: ${statusCode}`);
1091
- break;
1092
- case 406:
1093
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Not Acceptable, The client has requested a MIME type via `
1094
- + `the Accept header for a value not supported by the server, statusCode: ${statusCode}`);
1095
- break;
1096
- case 415:
1097
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unsupported Media Type, The client has defined a contentType `
1098
- + `header that is not supported by the server, statusCode: ${statusCode}`);
1099
- break;
1100
- case 422:
1101
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unprocessable Entity, The client has made a valid request, `
1102
- + `but the server cannot process it. This is often used for APIs for which certain limits have been exceeded, statusCode: ${statusCode}`);
1103
- break;
1104
- case 429:
1105
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Too Many Requests, The client has exceeded the number of `
1106
- + `requests allowed for a given time window, statusCode: ${statusCode}`);
1107
- break;
1108
- case 500:
1109
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Internal Server Error, An unexpected error on the SmartThings `
1110
- + `servers has occurred. These errors should be rare, statusCode: ${statusCode}`);
1111
- break;
1112
- default:
1113
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode: ` +
1114
- `${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`);
878
+ this.WindowCovering.CurrentHorizontalTiltAngle = Number(this.WindowCovering.CurrentHorizontalTiltAngle) < 0 ? -90 : 90;
1115
879
  }
1116
880
  }
1117
881
  async offlineOff() {
1118
882
  if (this.device.offline) {
1119
- await this.deviceContext();
1120
- await this.updateHomeKitCharacteristics();
883
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 100);
884
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
885
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 100);
886
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentHorizontalTiltAngle, 90);
887
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetHorizontalTiltAngle, 90);
1121
888
  }
1122
889
  }
1123
890
  async apiError(e) {
1124
- this.windowCoveringService.updateCharacteristic(this.hap.Characteristic.CurrentPosition, e);
1125
- this.windowCoveringService.updateCharacteristic(this.hap.Characteristic.PositionState, e);
1126
- this.windowCoveringService.updateCharacteristic(this.hap.Characteristic.TargetPosition, e);
1127
- if (!this.device.curtain?.hide_lightsensor) {
1128
- this.lightSensorService?.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, e);
1129
- }
1130
- if (this.BLE) {
1131
- this.batteryService?.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e);
1132
- this.batteryService?.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e);
1133
- }
1134
- //throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
1135
- }
1136
- async deviceContext() {
1137
- if (this.CurrentPosition === undefined) {
1138
- this.CurrentPosition = 0;
1139
- }
1140
- else {
1141
- this.CurrentPosition = this.accessory.context.CurrentPosition;
1142
- }
1143
- if (this.TargetPosition === undefined) {
1144
- this.TargetPosition = 0;
1145
- }
1146
- else {
1147
- this.TargetPosition = this.accessory.context.TargetPosition;
1148
- }
1149
- if (this.PositionState === undefined) {
1150
- this.PositionState = this.hap.Characteristic.PositionState.STOPPED;
1151
- }
1152
- else {
1153
- this.PositionState = this.accessory.context.PositionState;
1154
- }
1155
- if (this.FirmwareRevision === undefined) {
1156
- this.FirmwareRevision = this.platform.version;
1157
- this.accessory.context.FirmwareRevision = this.FirmwareRevision;
891
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, e);
892
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, e);
893
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, e);
894
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentHorizontalTiltAngle, e);
895
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetHorizontalTiltAngle, e);
896
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e);
897
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e);
898
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.ChargingState, e);
899
+ if (!this.device.blindTilt?.hide_lightsensor) {
900
+ this.LightSensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, e);
901
+ this.LightSensor.Service.updateCharacteristic(this.hap.Characteristic.StatusActive, e);
1158
902
  }
1159
903
  }
1160
904
  /**
@@ -1271,127 +1015,5 @@ export class BlindTilt {
1271
1015
  }
1272
1016
  }
1273
1017
  }
1274
- async refreshRate(device) {
1275
- // refreshRate
1276
- if (device.refreshRate) {
1277
- this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
1278
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
1279
- }
1280
- else if (this.platform.config.options.refreshRate) {
1281
- this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options.refreshRate;
1282
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
1283
- }
1284
- // updateRate
1285
- if (device?.blindTilt?.updateRate) {
1286
- this.updateRate = device?.blindTilt?.updateRate;
1287
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Blind Tilt updateRate: ${this.updateRate}`);
1288
- }
1289
- else {
1290
- this.updateRate = 2;
1291
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default Blind Tilt updateRate: ${this.updateRate}`);
1292
- }
1293
- }
1294
- async deviceConfig(device) {
1295
- let config = {};
1296
- if (device.blindTilt) {
1297
- config = device.blindTilt;
1298
- }
1299
- if (device.connectionType !== undefined) {
1300
- config['connectionType'] = device.connectionType;
1301
- }
1302
- if (device.external !== undefined) {
1303
- config['external'] = device.external;
1304
- }
1305
- if (device.mqttURL !== undefined) {
1306
- config['mqttURL'] = device.mqttURL;
1307
- }
1308
- if (device.logging !== undefined) {
1309
- config['logging'] = device.logging;
1310
- }
1311
- if (device.refreshRate !== undefined) {
1312
- config['refreshRate'] = device.refreshRate;
1313
- }
1314
- if (device.scanDuration !== undefined) {
1315
- config['scanDuration'] = device.scanDuration;
1316
- }
1317
- if (device.maxRetry !== undefined) {
1318
- config['maxRetry'] = device.maxRetry;
1319
- }
1320
- if (device.webhook !== undefined) {
1321
- config['webhook'] = device.webhook;
1322
- }
1323
- if (device.blindTilt?.mode === undefined) {
1324
- config['mode'] = BlindTiltMappingMode.OnlyUp;
1325
- }
1326
- else {
1327
- config['mode'] = device.blindTilt?.mode;
1328
- }
1329
- if (Object.entries(config).length !== 0) {
1330
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
1331
- }
1332
- }
1333
- async deviceLogs(device) {
1334
- if (this.platform.debugMode) {
1335
- this.deviceLogging = this.accessory.context.logging = 'debugMode';
1336
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
1337
- }
1338
- else if (device.logging) {
1339
- this.deviceLogging = this.accessory.context.logging = device.logging;
1340
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
1341
- }
1342
- else if (this.platform.config.options?.logging) {
1343
- this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
1344
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
1345
- }
1346
- else {
1347
- this.deviceLogging = this.accessory.context.logging = 'standard';
1348
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
1349
- }
1350
- }
1351
- /**
1352
- * Logging for Device
1353
- */
1354
- infoLog(...log) {
1355
- if (this.enablingDeviceLogging()) {
1356
- this.platform.log.info(String(...log));
1357
- }
1358
- }
1359
- warnLog(...log) {
1360
- if (this.enablingDeviceLogging()) {
1361
- this.platform.log.warn(String(...log));
1362
- }
1363
- }
1364
- debugWarnLog(...log) {
1365
- if (this.enablingDeviceLogging()) {
1366
- if (this.deviceLogging?.includes('debug')) {
1367
- this.platform.log.warn('[DEBUG]', String(...log));
1368
- }
1369
- }
1370
- }
1371
- errorLog(...log) {
1372
- if (this.enablingDeviceLogging()) {
1373
- this.platform.log.error(String(...log));
1374
- }
1375
- }
1376
- debugErrorLog(...log) {
1377
- if (this.enablingDeviceLogging()) {
1378
- if (this.deviceLogging?.includes('debug')) {
1379
- this.platform.log.error('[DEBUG]', String(...log));
1380
- }
1381
- }
1382
- }
1383
- debugLog(...log) {
1384
- if (this.enablingDeviceLogging()) {
1385
- if (this.deviceLogging === 'debug') {
1386
- this.platform.log.info('[DEBUG]', String(...log));
1387
- }
1388
- else {
1389
- this.platform.log.debug(String(...log));
1390
- }
1391
- }
1392
- }
1393
- enablingDeviceLogging() {
1394
- return this.deviceLogging.includes('debug') || this.deviceLogging === 'standard';
1395
- }
1396
1018
  }
1397
1019
  //# sourceMappingURL=blindtilt.js.map