@switchbot/homebridge-switchbot 3.5.0-beta.9 → 3.5.1-beta.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 (177) hide show
  1. package/.vscode/settings.json +4 -1
  2. package/CHANGELOG.md +4 -1
  3. package/config.schema.json +164 -22
  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 +457 -866
  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 +851 -913
  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 +316 -742
  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 +380 -833
  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 +267 -602
  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 +469 -897
  27. package/dist/device/curtain.js.map +1 -1
  28. package/dist/device/device.d.ts +76 -0
  29. package/dist/device/device.d.ts.map +1 -0
  30. package/dist/device/device.js +846 -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 +645 -0
  35. package/dist/device/fan.js.map +1 -0
  36. package/dist/device/hub.d.ts +19 -58
  37. package/dist/device/hub.d.ts.map +1 -1
  38. package/dist/device/hub.js +304 -640
  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 +300 -710
  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 +225 -643
  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 +371 -742
  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 +309 -642
  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 +223 -638
  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 +216 -644
  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 +209 -588
  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 +141 -532
  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 +252 -609
  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 +179 -521
  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 +337 -482
  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 +108 -333
  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 +47 -299
  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 +95 -364
  102. package/dist/irdevice/fan.js.map +1 -1
  103. package/dist/irdevice/irdevice.d.ts +46 -0
  104. package/dist/irdevice/irdevice.d.ts.map +1 -0
  105. package/dist/irdevice/irdevice.js +393 -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 +121 -376
  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 +441 -584
  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 +94 -353
  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 +48 -299
  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 +50 -305
  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 +66 -18
  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 +95 -0
  136. package/dist/utils.d.ts.map +1 -1
  137. package/dist/utils.js +657 -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 +488 -937
  143. package/src/device/bot.ts +907 -1016
  144. package/src/device/ceilinglight.ts +330 -798
  145. package/src/device/colorbulb.ts +394 -904
  146. package/src/device/contact.ts +298 -637
  147. package/src/device/curtain.ts +496 -954
  148. package/src/device/device.ts +872 -0
  149. package/src/device/fan.ts +692 -0
  150. package/src/device/hub.ts +338 -671
  151. package/src/device/humidifier.ts +330 -777
  152. package/src/device/iosensor.ts +258 -671
  153. package/src/device/lightstrip.ts +394 -809
  154. package/src/device/lock.ts +345 -700
  155. package/src/device/meter.ts +256 -666
  156. package/src/device/meterplus.ts +248 -672
  157. package/src/device/motion.ts +234 -622
  158. package/src/device/plug.ts +152 -572
  159. package/src/device/robotvacuumcleaner.ts +273 -653
  160. package/src/device/waterdetector.ts +198 -549
  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 +368 -540
  165. package/src/irdevice/airpurifier.ts +134 -369
  166. package/src/irdevice/camera.ts +60 -324
  167. package/src/irdevice/fan.ts +111 -392
  168. package/src/irdevice/irdevice.ts +406 -0
  169. package/src/irdevice/light.ts +159 -425
  170. package/src/irdevice/other.ts +509 -661
  171. package/src/irdevice/tv.ts +123 -388
  172. package/src/irdevice/vacuumcleaner.ts +61 -324
  173. package/src/irdevice/waterheater.ts +63 -333
  174. package/src/platform.ts +395 -259
  175. package/src/settings.ts +120 -610
  176. package/src/utils.ts +661 -1
  177. package/src/device/waterdetector.json +0 -11
@@ -1,149 +1,75 @@
1
- import { request } from 'undici';
2
- import { sleep } from '../utils.js';
1
+ /* Copyright(C) 2021-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
2
+ *
3
+ * blindtilt.ts: @switchbot/homebridge-switchbot.
4
+ */
3
5
  import { interval, Subject } from 'rxjs';
4
- import asyncmqtt from 'async-mqtt';
6
+ import { deviceBase } from './device.js';
7
+ import { BlindTiltMappingMode } from '../utils.js';
5
8
  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 {
9
+ export class BlindTilt extends deviceBase {
16
10
  platform;
17
- accessory;
18
- device;
19
- api;
20
- log;
21
- config;
22
- hap;
23
11
  // 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;
12
+ WindowCovering;
13
+ Battery;
14
+ LightSensor;
45
15
  // OpenAPI Others
46
- Mode;
47
- setPositionMode;
48
16
  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
17
  // Target
59
18
  setNewTarget;
60
19
  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
20
  // Updates
74
21
  blindTiltUpdateInProgress;
75
22
  doBlindTiltUpdate;
76
- // Connection
77
- OpenAPI;
78
- BLE;
79
23
  constructor(platform, accessory, device) {
24
+ super(platform, accessory, device);
80
25
  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
26
  // 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
27
  this.mappingMode = device.blindTilt?.mode ?? BlindTiltMappingMode.OnlyUp;
98
28
  this.debugLog(`Mapping mode: ${this.mappingMode}`);
99
29
  // this is subject we use to track when we need to POST changes to the SwitchBot API
100
30
  this.doBlindTiltUpdate = new Subject();
101
31
  this.blindTiltUpdateInProgress = false;
102
32
  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)
33
+ // Initialize WindowCovering Service
34
+ accessory.context.WindowCovering = accessory.context.WindowCovering ?? {};
35
+ this.WindowCovering = {
36
+ Name: accessory.context.WindowCovering.Name ?? accessory.displayName,
37
+ Service: accessory.getService(this.hap.Service.WindowCovering) ?? accessory.addService(this.hap.Service.WindowCovering),
38
+ PositionState: accessory.context.PositionState ?? this.hap.Characteristic.PositionState.STOPPED,
39
+ TargetPosition: accessory.context.TargetPosition ?? 100,
40
+ CurrentPosition: accessory.context.CurrentPosition ?? 100,
41
+ TargetHorizontalTiltAngle: accessory.context.TargetHorizontalTiltAngle ?? 90,
42
+ CurrentHorizontalTiltAngle: accessory.context.CurrentHorizontalTiltAngle ?? 90,
43
+ };
44
+ accessory.context.WindowCovering = this.WindowCovering;
45
+ // Initialize WindowCovering Characteristics
46
+ this.WindowCovering.Service
47
+ .setCharacteristic(this.hap.Characteristic.Name, this.WindowCovering.Name)
48
+ .getCharacteristic(this.hap.Characteristic.TargetPosition)
126
49
  .setProps({
127
- minStep: this.minStep(device),
50
+ minStep: device.blindTilt?.set_minStep ?? 1,
128
51
  minValue: 0,
129
52
  maxValue: 100,
130
53
  validValueRanges: [0, 100],
131
54
  })
132
55
  .onGet(() => {
133
- return this.CurrentPosition;
134
- });
135
- this.windowCoveringService
136
- .getCharacteristic(this.hap.Characteristic.TargetPosition)
56
+ return this.WindowCovering.TargetPosition;
57
+ })
58
+ .onSet(this.TargetPositionSet.bind(this));
59
+ // Initialize WindowCovering CurrentPosition Characteristic
60
+ this.WindowCovering.Service
61
+ .getCharacteristic(this.hap.Characteristic.CurrentPosition)
137
62
  .setProps({
138
- minStep: this.minStep(device),
63
+ minStep: device.blindTilt?.set_minStep ?? 1,
139
64
  minValue: 0,
140
65
  maxValue: 100,
141
66
  validValueRanges: [0, 100],
142
- })
143
- .onSet(this.TargetPositionSet.bind(this));
144
- this.CurrentHorizontalTiltAngle = 90;
145
- this.windowCoveringService
146
- .getCharacteristic(this.hap.Characteristic.CurrentHorizontalTiltAngle)
67
+ }).onGet(() => {
68
+ return this.WindowCovering?.CurrentPosition ?? 0;
69
+ });
70
+ // Initialize WindowCovering TargetHorizontalTiltAngle Characteristic
71
+ this.WindowCovering.Service
72
+ .getCharacteristic(this.hap.Characteristic.TargetHorizontalTiltAngle)
147
73
  .setProps({
148
74
  minStep: 180,
149
75
  minValue: -90,
@@ -151,27 +77,62 @@ export class BlindTilt {
151
77
  validValues: [-90, 90],
152
78
  })
153
79
  .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)
80
+ return this.WindowCovering.TargetHorizontalTiltAngle;
81
+ })
82
+ .onSet(this.TargetHorizontalTiltAngleSet.bind(this));
83
+ // Initialize WindowCovering CurrentHorizontalTiltAngle Characteristic
84
+ this.WindowCovering.Service
85
+ .getCharacteristic(this.hap.Characteristic.CurrentHorizontalTiltAngle)
160
86
  .setProps({
161
87
  minStep: 180,
162
88
  minValue: -90,
163
89
  maxValue: 90,
164
90
  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`);
91
+ }).onGet(() => {
92
+ return this.WindowCovering.CurrentHorizontalTiltAngle ?? 0;
93
+ });
94
+ // Initialize Battery Service
95
+ accessory.context.Battery = accessory.context.Battery ?? {};
96
+ this.Battery = {
97
+ Name: accessory.context.Battery.Name ?? `${accessory.displayName} Battery`,
98
+ Service: accessory.getService(this.hap.Service.Battery) ?? accessory.addService(this.hap.Service.Battery),
99
+ BatteryLevel: accessory.context.BatteryLevel ?? 100,
100
+ StatusLowBattery: this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,
101
+ ChargingState: accessory.context.ChargingState ?? this.hap.Characteristic.ChargingState.NOT_CHARGING,
102
+ };
103
+ accessory.context.Battery = this.Battery;
104
+ // Initialize Battery Name Characteristic
105
+ this.Battery.Service
106
+ .setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name)
107
+ .setCharacteristic(this.hap.Characteristic.ChargingState, this.hap.Characteristic.ChargingState.NOT_CHARGEABLE);
108
+ // Initialize LightSensor Service
109
+ if (device.blindTilt?.hide_lightsensor) {
110
+ if (this.LightSensor?.Service) {
111
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} Removing Light Sensor Service`);
112
+ this.LightSensor.Service = accessory.getService(this.hap.Service.LightSensor);
113
+ accessory.removeService(this.LightSensor.Service);
114
+ accessory.context.LightSensor = {};
115
+ }
174
116
  }
117
+ else {
118
+ accessory.context.LightSensor = accessory.context.LightSensor ?? {};
119
+ this.LightSensor = {
120
+ Name: accessory.context.LightSensor.Name ?? `${accessory.displayName} Light Sensor`,
121
+ Service: accessory.getService(this.hap.Service.LightSensor) ?? accessory.addService(this.hap.Service.LightSensor),
122
+ CurrentAmbientLightLevel: accessory.context.CurrentAmbientLightLevel ?? 0.0001,
123
+ };
124
+ accessory.context.LightSensor = this.LightSensor;
125
+ // Initialize LightSensor Characteristics
126
+ this.LightSensor.Service
127
+ .setCharacteristic(this.hap.Characteristic.Name, this.LightSensor.Name)
128
+ .setCharacteristic(this.hap.Characteristic.StatusActive, true)
129
+ .getCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel)
130
+ .onGet(() => {
131
+ return this.LightSensor?.CurrentAmbientLightLevel ?? 0.0001;
132
+ });
133
+ }
134
+ // Retrieve initial values and updateHomekit
135
+ this.refreshStatus();
175
136
  // Update Homekit
176
137
  this.updateHomeKitCharacteristics();
177
138
  // Start an update interval
@@ -181,36 +142,15 @@ export class BlindTilt {
181
142
  await this.refreshStatus();
182
143
  });
183
144
  //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
- }
145
+ this.registerWebhook(accessory, device);
206
146
  // update slide progress
207
- interval(this.updateRate * 1000)
208
- //.pipe(skipWhile(() => this.blindTiltUpdateInProgress))
147
+ interval(this.deviceUpdateRate * 1000)
209
148
  .subscribe(async () => {
210
- if (this.PositionState === this.hap.Characteristic.PositionState.STOPPED) {
149
+ if (this.WindowCovering.PositionState === this.hap.Characteristic.PositionState.STOPPED) {
211
150
  return;
212
151
  }
213
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Refresh Status When Moving, PositionState: ${this.PositionState}`);
152
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} Refresh Status When Moving,`
153
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
214
154
  await this.refreshStatus();
215
155
  });
216
156
  // Watch for BlindTilt change events
@@ -218,213 +158,235 @@ export class BlindTilt {
218
158
  this.doBlindTiltUpdate
219
159
  .pipe(tap(() => {
220
160
  this.blindTiltUpdateInProgress = true;
221
- }), debounceTime(this.platform.config.options.pushRate * 1000))
161
+ }), debounceTime(this.devicePushRate * 1000))
222
162
  .subscribe(async () => {
223
163
  try {
224
164
  await this.pushChanges();
225
165
  }
226
166
  catch (e) {
227
167
  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)}`);
168
+ this.errorLog(`${device.deviceType}: ${accessory.displayName} failed pushChanges with ${device.connectionType} Connection,`
169
+ + ` Error Message: ${JSON.stringify(e.message)}`);
230
170
  }
231
171
  this.blindTiltUpdateInProgress = false;
232
172
  });
233
173
  }
234
174
  /**
235
- * Parse the device status from the SwitchBot api
175
+ * Parse the device status from the SwitchBotBLE API
236
176
  */
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() {
177
+ async BLEparseStatus(serviceData) {
253
178
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
254
179
  // CurrentPosition
255
- this.CurrentPosition = 100 - Number(this.BLE_CurrentPosition);
180
+ this.WindowCovering.CurrentPosition = 100 - Number(serviceData.position);
256
181
  await this.setMinMax();
257
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition ${this.CurrentPosition}`);
182
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition ${this.WindowCovering.CurrentPosition}`);
258
183
  if (this.setNewTarget) {
259
184
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Checking Status ...`);
260
185
  }
261
- if (this.setNewTarget && this.BLE_InMotion) {
186
+ if (this.setNewTarget && serviceData.inMotion) {
262
187
  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}`);
188
+ if (Number(this.WindowCovering.TargetPosition) > this.WindowCovering.CurrentPosition) {
189
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
190
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
191
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
192
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} INCREASING`
193
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
194
+ }
195
+ else if (Number(this.WindowCovering.TargetPosition) < this.WindowCovering.CurrentPosition) {
196
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Opening, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
197
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
198
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
199
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} DECREASING`
200
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
274
201
  }
275
202
  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}`);
203
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} Standby2,`
204
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
205
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
206
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
207
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} STOPPED`
208
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
280
209
  }
281
210
  }
282
211
  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;
212
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
213
+ this.WindowCovering.TargetPosition = this.WindowCovering.CurrentPosition;
214
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
286
215
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Stopped`);
287
216
  }
288
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition},` +
289
- ` TargetPosition: ${this.TargetPosition}, PositionState: ${this.PositionState},`);
217
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition},`
218
+ + ` TargetPosition: ${this.WindowCovering.TargetPosition}, PositionState: ${this.WindowCovering.PositionState},`);
290
219
  if (!this.device.blindTilt?.hide_lightsensor) {
291
- this.set_minLux = this.minLux();
292
- this.set_maxLux = this.maxLux();
293
- this.spaceBetweenLevels = 9;
220
+ const set_minLux = this.device.blindTilt?.set_minLux ?? 1;
221
+ const set_maxLux = this.device.blindTilt?.set_maxLux ?? 6001;
222
+ const spaceBetweenLevels = 9;
223
+ if (this.LightSensor?.CurrentAmbientLightLevel === 0) {
224
+ this.LightSensor.CurrentAmbientLightLevel = 0.0001;
225
+ }
294
226
  // Brightness
295
- switch (this.BLE_CurrentAmbientLightLevel) {
227
+ switch (serviceData.lightLevel) {
296
228
  case 1:
297
- this.CurrentAmbientLightLevel = this.set_minLux;
298
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.BLE_CurrentAmbientLightLevel}`);
229
+ this.LightSensor.CurrentAmbientLightLevel = set_minLux;
230
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
299
231
  break;
300
232
  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}`);
233
+ this.LightSensor.CurrentAmbientLightLevel = (set_maxLux - set_minLux) / spaceBetweenLevels;
234
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel},`
235
+ + ` Calculation: ${(set_maxLux - set_minLux) / spaceBetweenLevels}`);
304
236
  break;
305
237
  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}`);
238
+ this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 2;
239
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
308
240
  break;
309
241
  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}`);
242
+ this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 3;
243
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
312
244
  break;
313
245
  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}`);
246
+ this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 4;
247
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
316
248
  break;
317
249
  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}`);
250
+ this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 5;
251
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
320
252
  break;
321
253
  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}`);
254
+ this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 6;
255
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
324
256
  break;
325
257
  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}`);
258
+ this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 7;
259
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
328
260
  break;
329
261
  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}`);
262
+ this.LightSensor.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 8;
263
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
332
264
  break;
333
265
  case 10:
334
266
  default:
335
- this.CurrentAmbientLightLevel = this.set_maxLux;
267
+ this.LightSensor.CurrentAmbientLightLevel = set_maxLux;
336
268
  this.debugLog();
337
269
  }
338
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.BLE_CurrentAmbientLightLevel},` +
339
- ` CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
270
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel},`
271
+ + ` CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
340
272
  }
341
273
  // Battery
342
- this.BatteryLevel = Number(this.BLE_BatteryLevel);
343
- if (this.BatteryLevel < 10) {
344
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
274
+ this.Battery.BatteryLevel = Number(serviceData.battery);
275
+ if (this.Battery.BatteryLevel < 10) {
276
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
345
277
  }
346
278
  else {
347
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
279
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
348
280
  }
349
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel},` + ` StatusLowBattery: ${this.StatusLowBattery}`);
281
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
282
+ + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
350
283
  }
351
- async openAPIparseStatus() {
284
+ /**
285
+ * Parse the device status from the SwitchBot OpenAPI
286
+ */
287
+ async openAPIparseStatus(deviceStatus) {
352
288
  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;
289
+ const [homekitPosition, homekitTiltAngle] = this.mapDeviceValuesToHomekitValues(Number(deviceStatus.body.slidePosition), String(deviceStatus.body.direction));
290
+ this.debugLog(` device: ${deviceStatus.body.slidePosition} => HK: ${homekitPosition}`);
291
+ this.WindowCovering.CurrentPosition = homekitPosition;
356
292
  // CurrentPosition
357
293
  await this.setMinMax();
358
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition}`);
294
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
359
295
  if (homekitTiltAngle) {
360
- this.CurrentHorizontalTiltAngle = homekitTiltAngle;
361
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentHorizontalTiltAngle: ${this.CurrentHorizontalTiltAngle}`);
296
+ this.WindowCovering.CurrentHorizontalTiltAngle = homekitTiltAngle;
297
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
298
+ + ` CurrentHorizontalTiltAngle: ${this.WindowCovering.CurrentHorizontalTiltAngle}`);
362
299
  }
363
300
  if (this.setNewTarget) {
364
301
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Checking Status ...`);
365
302
  }
366
- if (this.setNewTarget && this.OpenAPI_InMotion) {
303
+ if (this.setNewTarget && deviceStatus.body.moving) {
367
304
  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}`);
305
+ if (this.WindowCovering.TargetPosition > this.WindowCovering.CurrentPosition
306
+ || (homekitTiltAngle && this.WindowCovering.TargetHorizontalTiltAngle !== this.WindowCovering.CurrentHorizontalTiltAngle)) {
307
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition} `);
308
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
309
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
310
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} INCREASING`
311
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
312
+ }
313
+ else if (this.WindowCovering.TargetPosition < this.WindowCovering.CurrentPosition) {
314
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Opening, CurrentPosition: ${this.WindowCovering.CurrentPosition} `);
315
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
316
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
317
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} DECREASING`
318
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
379
319
  }
380
320
  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}`);
321
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} Standby because reached position,`
322
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
323
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
324
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
325
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} STOPPED`
326
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
385
327
  }
386
328
  }
387
329
  else {
388
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Standby because device not moving,` + ` CurrentPosition: ${this.CurrentPosition}`);
389
- this.TargetPosition = this.CurrentPosition;
330
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Standby because device not moving,`
331
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
332
+ this.WindowCovering.TargetPosition = this.WindowCovering.CurrentPosition;
390
333
  if (homekitTiltAngle) {
391
- this.TargetHorizontalTiltAngle = this.CurrentHorizontalTiltAngle;
334
+ this.WindowCovering.TargetHorizontalTiltAngle = this.WindowCovering.CurrentHorizontalTiltAngle;
392
335
  }
393
- this.PositionState = this.hap.Characteristic.PositionState.STOPPED;
336
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
394
337
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Stopped`);
395
338
  }
396
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition},` +
397
- ` TargetPosition: ${this.TargetPosition}, PositionState: ${this.PositionState},`);
339
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition},`
340
+ + ` TargetPosition: ${this.WindowCovering.TargetPosition}, PositionState: ${this.WindowCovering.PositionState},`);
398
341
  if (!this.device.blindTilt?.hide_lightsensor) {
399
- this.set_minLux = this.minLux();
400
- this.set_maxLux = this.maxLux();
342
+ const set_minLux = this.device.blindTilt?.set_minLux ?? 1;
343
+ const set_maxLux = this.device.blindTilt?.set_maxLux ?? 6001;
401
344
  // Brightness
402
- switch (this.OpenAPI_CurrentAmbientLightLevel) {
345
+ switch (deviceStatus.body.brightness) {
403
346
  case 'dim':
404
- this.CurrentAmbientLightLevel = this.set_minLux;
347
+ this.LightSensor.CurrentAmbientLightLevel = set_minLux;
405
348
  break;
406
349
  case 'bright':
407
350
  default:
408
- this.CurrentAmbientLightLevel = this.set_maxLux;
351
+ this.LightSensor.CurrentAmbientLightLevel = set_maxLux;
409
352
  }
410
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
353
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
354
+ + ` CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
411
355
  }
412
356
  // BatteryLevel
413
- this.BatteryLevel = Number(this.OpenAPI_BatteryLevel);
414
- if (this.BatteryLevel < 10) {
415
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
357
+ this.Battery.BatteryLevel = Number(deviceStatus.body.battery);
358
+ if (this.Battery.BatteryLevel < 10) {
359
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
416
360
  }
417
361
  else {
418
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
362
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
363
+ }
364
+ if (Number.isNaN(this.Battery.BatteryLevel)) {
365
+ this.Battery.BatteryLevel = 100;
366
+ }
367
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
368
+ + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
369
+ // Firmware Version
370
+ const version = deviceStatus.body.version?.toString();
371
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Firmware Version: ${version?.replace(/^V|-.*$/g, '')}`);
372
+ let deviceVersion;
373
+ if (version?.includes('.') === false) {
374
+ const replace = version?.replace(/^V|-.*$/g, '');
375
+ const match = replace?.match(/.{1,1}/g);
376
+ const blindTiltVersion = match?.join('.') ?? '0.0.0';
377
+ deviceVersion = blindTiltVersion;
419
378
  }
420
- if (Number.isNaN(this.BatteryLevel)) {
421
- this.BatteryLevel = 100;
379
+ else {
380
+ deviceVersion = version?.replace(/^V|-.*$/g, '') ?? '0.0.0';
422
381
  }
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;
382
+ this.accessory
383
+ .getService(this.hap.Service.AccessoryInformation)
384
+ .setCharacteristic(this.hap.Characteristic.HardwareRevision, deviceVersion)
385
+ .setCharacteristic(this.hap.Characteristic.FirmwareRevision, deviceVersion)
386
+ .getCharacteristic(this.hap.Characteristic.FirmwareRevision)
387
+ .updateValue(deviceVersion);
388
+ this.accessory.context.deviceVersion = deviceVersion;
389
+ this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceVersion: ${this.accessory.context.deviceVersion}`);
428
390
  }
429
391
  async refreshStatus() {
430
392
  if (!this.device.enableCloudService && this.OpenAPI) {
@@ -438,135 +400,81 @@ export class BlindTilt {
438
400
  }
439
401
  else {
440
402
  await this.offlineOff();
441
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` +
442
- ` ${this.device.connectionType}, refreshStatus will not happen.`);
403
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
404
+ + ` ${this.device.connectionType}, refreshStatus will not happen.`);
443
405
  }
444
406
  }
445
407
  async BLERefreshStatus() {
446
408
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
447
- const switchbot = await this.platform.connectBLE();
448
- // Convert to BLE Address
449
- this.device.bleMac = this.device
450
- .deviceId.match(/.{1,2}/g)
451
- .join(':')
452
- .toLowerCase();
453
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
454
- this.getCustomBLEAddress(switchbot);
455
- // Start to monitor advertisement packets
456
- (async () => {
409
+ const switchbot = await this.switchbotBLE();
410
+ if (switchbot === undefined) {
411
+ await this.BLERefreshConnection(switchbot);
412
+ }
413
+ else {
457
414
  // Start to monitor advertisement packets
458
- await switchbot.startScan({
459
- model: 'x',
460
- id: this.device.bleMac,
461
- });
462
- // Set an event handler
463
- 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') {
467
- 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;
415
+ (async () => {
416
+ // Start to monitor advertisement packets
417
+ const serviceData = await this.monitorAdvertisementPackets(switchbot);
418
+ // Update HomeKit
419
+ if (serviceData.model !== '' && serviceData.modelName !== '') {
420
+ await this.BLEparseStatus(serviceData);
421
+ await this.updateHomeKitCharacteristics();
473
422
  }
474
423
  else {
475
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
476
- }
477
- };
478
- // Wait 10 seconds
479
- await switchbot.wait(this.scanDuration * 1000);
480
- // Stop to monitor
481
- await switchbot.stopScan();
482
- // Update HomeKit
483
- await this.BLEparseStatus();
484
- await this.updateHomeKitCharacteristics();
485
- })();
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}`);
424
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed to get serviceData, serviceData: ${serviceData}`);
425
+ await this.BLERefreshConnection(switchbot);
518
426
  }
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
- }*/
427
+ })();
428
+ }
538
429
  }
539
430
  async openAPIRefreshStatus() {
540
431
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
541
432
  try {
542
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/status`, {
543
- headers: this.platform.generateHeaders(),
544
- });
545
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
433
+ const { body, statusCode } = await this.deviceRefreshStatus();
546
434
  const deviceStatus = await body.json();
547
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
548
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
435
+ await this.refreshStatusCodes(statusCode, deviceStatus);
436
+ ;
549
437
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
550
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
551
- + `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();
559
- this.updateHomeKitCharacteristics();
438
+ await this.successfulRefreshStatus(statusCode, deviceStatus);
439
+ await this.openAPIparseStatus(deviceStatus);
440
+ await this.updateHomeKitCharacteristics();
560
441
  }
561
442
  else {
562
- this.statusCode(statusCode);
563
- this.statusCode(deviceStatus.statusCode);
443
+ await this.statusCodes(statusCode, deviceStatus);
564
444
  }
565
445
  }
566
446
  catch (e) {
567
447
  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)}`);
448
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
449
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
450
+ }
451
+ }
452
+ async registerWebhook(accessory, device) {
453
+ if (device.webhook) {
454
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} is listening webhook.`);
455
+ this.platform.webhookEventHandler[this.device.deviceId] = async (context) => {
456
+ try {
457
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
458
+ const { slidePosition, battery, lightLevel } = context;
459
+ const { CurrentPosition } = this.WindowCovering;
460
+ const { BatteryLevel } = this.Battery;
461
+ const { CurrentAmbientLightLevel } = this.LightSensor ?? {};
462
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} (slidePosition, battery, lightLevel) = Webhook:(${slidePosition}, ${battery},`
463
+ + ` ${lightLevel}), current:(${CurrentPosition}, ${BatteryLevel}, ${CurrentAmbientLightLevel})`);
464
+ this.WindowCovering.CurrentPosition = slidePosition;
465
+ this.Battery.BatteryLevel = battery;
466
+ if (!device.blindTilt?.hide_lightsensor) {
467
+ this.LightSensor.CurrentAmbientLightLevel = lightLevel;
468
+ }
469
+ this.updateHomeKitCharacteristics();
470
+ }
471
+ catch (e) {
472
+ this.errorLog(`${device.deviceType}: ${accessory.displayName} failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
473
+ }
474
+ };
475
+ }
476
+ else {
477
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} is not listening webhook.`);
570
478
  }
571
479
  }
572
480
  async pushChanges() {
@@ -581,7 +489,8 @@ export class BlindTilt {
581
489
  }
582
490
  else {
583
491
  await this.offlineOff();
584
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` + ` ${this.device.connectionType}, pushChanges will not happen.`);
492
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
493
+ + ` ${this.device.connectionType}, pushChanges will not happen.`);
585
494
  }
586
495
  // Refresh the status from the API
587
496
  interval(15000)
@@ -593,39 +502,33 @@ export class BlindTilt {
593
502
  }
594
503
  async BLEpushChanges() {
595
504
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
596
- if (this.TargetPosition !== this.CurrentPosition) {
505
+ if (this.WindowCovering.TargetPosition !== this.WindowCovering.CurrentPosition) {
597
506
  const switchbot = await this.platform.connectBLE();
598
507
  // Convert to BLE Address
599
- this.device.bleMac = this.device
600
- .deviceId.match(/.{1,2}/g)
601
- .join(':')
602
- .toLowerCase();
603
- 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}`);
508
+ await this.convertBLEAddress();
509
+ const { setPositionMode, Mode } = await this.setPerformance();
510
+ this.debugLog(`${this.accessory.displayName} Mode: ${Mode}`);
610
511
  if (switchbot !== false) {
611
512
  switchbot
612
- .discover({ model: 'c', quick: true, id: this.device.bleMac })
513
+ .discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac })
613
514
  .then(async (device_list) => {
614
- this.infoLog(`${this.accessory.displayName} Target Position: ${this.TargetPosition}`);
615
- return await this.retry({
616
- max: this.maxRetry(),
515
+ this.infoLog(`${this.accessory.displayName} Target Position: ${this.WindowCovering.TargetPosition}`);
516
+ return await this.retryBLE({
517
+ max: await this.maxRetryBLE(),
617
518
  fn: async () => {
618
- return await device_list[0].runToPos(100 - Number(this.TargetPosition), adjustedMode);
519
+ return await device_list[0].runToPos(100 - Number(this.WindowCovering.TargetPosition), setPositionMode);
619
520
  },
620
521
  });
621
522
  })
622
523
  .then(() => {
623
524
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
525
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
526
+ + `Target Position: ${this.WindowCovering.TargetPosition} sent over BLE, sent successfully`);
624
527
  })
625
528
  .catch(async (e) => {
626
529
  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)}`);
530
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
531
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
629
532
  await this.BLEPushConnection();
630
533
  });
631
534
  }
@@ -635,46 +538,33 @@ export class BlindTilt {
635
538
  }
636
539
  }
637
540
  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;
541
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges, CurrentPosition & TargetPosition Are the Same.`
542
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition ${this.WindowCovering.TargetPosition}`);
659
543
  }
660
544
  }
661
545
  async openAPIpushChanges() {
662
546
  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}`);
547
+ const hasDifferentAndRelevantHorizontalTiltAngle = this.mappingMode === BlindTiltMappingMode.UseTiltForDirection
548
+ && this.WindowCovering.TargetHorizontalTiltAngle !== this.WindowCovering.CurrentHorizontalTiltAngle;
549
+ if (this.WindowCovering.TargetPosition !== this.WindowCovering.CurrentPosition
550
+ || hasDifferentAndRelevantHorizontalTiltAngle || this.device.disableCaching) {
551
+ const [direction, position] = this.mapHomekitValuesToDeviceValues(Number(this.WindowCovering.TargetPosition), Number(this.WindowCovering.TargetHorizontalTiltAngle));
552
+ const { Mode } = await this.setPerformance();
553
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
554
+ + ` Pushing ${this.WindowCovering.TargetPosition} (device = ${direction};${position})`);
555
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Mode: ${Mode}`);
668
556
  let bodyChange = '';
669
557
  if (position === 100) {
670
558
  bodyChange = JSON.stringify({
671
559
  command: 'fullyOpen',
560
+ parameter: 'default',
672
561
  commandType: 'command',
673
562
  });
674
563
  }
675
564
  else if (position === 0) {
676
565
  bodyChange = JSON.stringify({
677
566
  command: direction === 'up' ? 'closeUp' : 'closeDown',
567
+ parameter: 'default',
678
568
  commandType: 'command',
679
569
  });
680
570
  }
@@ -687,51 +577,45 @@ export class BlindTilt {
687
577
  }
688
578
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
689
579
  try {
690
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/commands`, {
691
- body: bodyChange,
692
- method: 'POST',
693
- headers: this.platform.generateHeaders(),
694
- });
695
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
580
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
696
581
  const deviceStatus = await body.json();
697
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
698
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
699
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
582
+ await this.pushStatusCodes(statusCode, deviceStatus);
700
583
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
701
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
702
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
584
+ await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
585
+ await this.updateHomeKitCharacteristics();
703
586
  }
704
587
  else {
705
- this.statusCode(statusCode);
706
- this.statusCode(deviceStatus.statusCode);
588
+ await this.statusCode(statusCode);
589
+ await this.statusCode(deviceStatus.statusCode);
707
590
  }
708
591
  }
709
592
  catch (e) {
710
593
  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)}`);
594
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
595
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
713
596
  }
714
597
  }
715
598
  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}`);
599
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No OpenAPI Changes, CurrentPosition & TargetPosition Are the Same.`
600
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition ${this.WindowCovering.TargetPosition}`
601
+ + ` CurrentHorizontalTiltAngle: ${this.WindowCovering.CurrentHorizontalTiltAngle},`
602
+ + ` TargetPosition ${this.WindowCovering.TargetHorizontalTiltAngle}`);
719
603
  }
720
604
  }
721
605
  /**
722
606
  * Handle requests to set the value of the "Target Horizontal Tilt" characteristic
723
607
  */
724
608
  async TargetHorizontalTiltAngleSet(value) {
725
- if (this.TargetHorizontalTiltAngle === this.accessory.context.TargetHorizontalTiltAngle) {
609
+ if (this.WindowCovering.TargetHorizontalTiltAngle === this.accessory.context.TargetHorizontalTiltAngle) {
726
610
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set TargetHorizontalTiltAngle: ${value}`);
727
611
  }
728
612
  else {
729
613
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetHorizontalTiltAngle: ${value}`);
730
614
  }
731
615
  //value = value < 0 ? -90 : 90;
732
- this.TargetHorizontalTiltAngle = value;
616
+ this.WindowCovering.TargetHorizontalTiltAngle = value;
733
617
  if (this.device.mqttURL) {
734
- this.mqttPublish('TargetHorizontalTiltAngle', this.TargetHorizontalTiltAngle);
618
+ this.mqttPublish('TargetHorizontalTiltAngle', this.WindowCovering.TargetHorizontalTiltAngle.toString());
735
619
  }
736
620
  this.startUpdatingBlindTiltIfNeeded();
737
621
  }
@@ -739,49 +623,53 @@ export class BlindTilt {
739
623
  * Handle requests to set the value of the "Target Position" characteristic
740
624
  */
741
625
  async TargetPositionSet(value) {
742
- if (this.TargetPosition === this.accessory.context.TargetPosition) {
626
+ if (this.WindowCovering.TargetPosition === this.accessory.context.TargetPosition) {
743
627
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set TargetPosition: ${value}`);
744
628
  }
745
629
  else {
746
630
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetPosition: ${value}`);
747
631
  }
748
- this.TargetPosition = value;
632
+ this.WindowCovering.TargetPosition = value;
749
633
  if (this.device.mqttURL) {
750
- this.mqttPublish('TargetPosition', this.TargetPosition);
634
+ this.mqttPublish('TargetPosition', this.WindowCovering.TargetPosition.toString());
751
635
  }
752
636
  this.startUpdatingBlindTiltIfNeeded();
753
637
  }
754
638
  async startUpdatingBlindTiltIfNeeded() {
755
639
  await this.setMinMax();
756
640
  this.debugLog('setMinMax');
757
- if (this.TargetPosition > this.CurrentPosition || this.TargetHorizontalTiltAngle !== this.CurrentHorizontalTiltAngle) {
758
- this.PositionState = this.hap.Characteristic.PositionState.INCREASING;
641
+ if (this.WindowCovering.TargetPosition > this.WindowCovering.CurrentPosition
642
+ || this.WindowCovering.TargetHorizontalTiltAngle !== this.WindowCovering.CurrentHorizontalTiltAngle) {
643
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
759
644
  this.setNewTarget = true;
760
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${this.CurrentPosition},` + ` CurrentPosition: ${this.CurrentPosition}`);
645
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${this.WindowCovering.CurrentPosition},`
646
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
761
647
  }
762
- else if (this.TargetPosition < this.CurrentPosition) {
763
- this.PositionState = this.hap.Characteristic.PositionState.DECREASING;
648
+ else if (this.WindowCovering.TargetPosition < this.WindowCovering.CurrentPosition) {
649
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
764
650
  this.setNewTarget = true;
765
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${this.CurrentPosition},` + ` CurrentPosition: ${this.CurrentPosition}`);
651
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${this.WindowCovering.CurrentPosition},`
652
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
766
653
  }
767
654
  else {
768
- this.PositionState = this.hap.Characteristic.PositionState.STOPPED;
655
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
769
656
  this.setNewTarget = false;
770
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${this.CurrentPosition},` + ` CurrentPosition: ${this.CurrentPosition}`);
657
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${this.WindowCovering.CurrentPosition},`
658
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
771
659
  }
772
- this.windowCoveringService.setCharacteristic(this.hap.Characteristic.PositionState, this.PositionState);
773
- this.windowCoveringService.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.PositionState);
660
+ this.WindowCovering.Service.setCharacteristic(this.hap.Characteristic.PositionState, this.WindowCovering.PositionState);
661
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
774
662
  /**
775
663
  * If Blind Tilt movement time is short, the moving flag from backend is always false.
776
664
  * The minimum time depends on the network control latency.
777
665
  */
778
666
  clearTimeout(this.setNewTargetTimer);
779
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateRate: ${this.updateRate}`);
667
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateRate: ${this.deviceUpdateRate}`);
780
668
  if (this.setNewTarget) {
781
669
  this.setNewTargetTimer = setTimeout(() => {
782
670
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} setNewTarget ${this.setNewTarget} timeout`);
783
671
  this.setNewTarget = false;
784
- }, this.updateRate * 1000);
672
+ }, this.deviceUpdateRate * 1000);
785
673
  }
786
674
  this.doBlindTiltUpdate.next();
787
675
  }
@@ -789,152 +677,111 @@ export class BlindTilt {
789
677
  await this.setMinMax();
790
678
  // CurrentHorizontalTiltAngle
791
679
  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}`);
680
+ if (this.WindowCovering.CurrentHorizontalTiltAngle === undefined || Number.isNaN(this.WindowCovering.CurrentHorizontalTiltAngle)) {
681
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
682
+ + ` CurrentHorizontalTiltAngle: ${this.WindowCovering.CurrentHorizontalTiltAngle}`);
794
683
  }
795
684
  else {
796
685
  if (this.device.mqttURL) {
797
- this.mqttPublish('CurrentHorizontalTiltAngle', this.CurrentHorizontalTiltAngle);
686
+ this.mqttPublish('CurrentHorizontalTiltAngle', this.WindowCovering.CurrentHorizontalTiltAngle.toString());
798
687
  }
799
- this.accessory.context.CurrentHorizontalTiltAngle = this.CurrentHorizontalTiltAngle;
800
- this.windowCoveringService.updateCharacteristic(this.hap.Characteristic.CurrentHorizontalTiltAngle, Number(this.CurrentHorizontalTiltAngle));
688
+ this.accessory.context.CurrentHorizontalTiltAngle = this.WindowCovering.CurrentHorizontalTiltAngle;
689
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentHorizontalTiltAngle, Number(this.WindowCovering.CurrentHorizontalTiltAngle));
801
690
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}
802
- updateCharacteristic CurrentHorizontalTiltAngle: ${this.CurrentHorizontalTiltAngle}`);
691
+ updateCharacteristic CurrentHorizontalTiltAngle: ${this.WindowCovering.CurrentHorizontalTiltAngle}`);
803
692
  }
804
693
  }
805
694
  // CurrentPosition
806
- if (this.CurrentPosition === undefined || Number.isNaN(this.CurrentPosition)) {
807
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition}`);
695
+ if (this.WindowCovering.CurrentPosition === undefined || Number.isNaN(this.WindowCovering.CurrentPosition)) {
696
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
808
697
  }
809
698
  else {
810
699
  if (this.device.mqttURL) {
811
- this.mqttPublish('CurrentPosition', this.CurrentPosition);
700
+ this.mqttPublish('CurrentPosition', this.WindowCovering.CurrentPosition.toString());
812
701
  }
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}`);
702
+ this.accessory.context.CurrentPosition = this.WindowCovering.CurrentPosition;
703
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, Number(this.WindowCovering.CurrentPosition));
704
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
705
+ + ` updateCharacteristic CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
816
706
  }
817
707
  // PositionState
818
- if (this.PositionState === undefined) {
819
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} PositionState: ${this.PositionState}`);
708
+ if (this.WindowCovering.PositionState === undefined) {
709
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} PositionState: ${this.WindowCovering.PositionState}`);
820
710
  }
821
711
  else {
822
712
  if (this.device.mqttURL) {
823
- this.mqttPublish('PositionState', this.PositionState);
713
+ this.mqttPublish('PositionState', this.WindowCovering.PositionState.toString());
824
714
  }
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}`);
715
+ this.accessory.context.PositionState = this.WindowCovering.PositionState;
716
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, Number(this.WindowCovering.PositionState));
717
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
718
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
828
719
  }
829
720
  // TargetPosition
830
- if (this.TargetPosition === undefined || Number.isNaN(this.TargetPosition)) {
831
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} TargetPosition: ${this.TargetPosition}`);
721
+ if (this.WindowCovering.TargetPosition === undefined || Number.isNaN(this.WindowCovering.TargetPosition)) {
722
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} TargetPosition: ${this.WindowCovering.TargetPosition}`);
832
723
  }
833
724
  else {
834
725
  if (this.device.mqttURL) {
835
- this.mqttPublish('TargetPosition', this.TargetPosition);
726
+ this.mqttPublish('TargetPosition', this.WindowCovering.TargetPosition.toString());
836
727
  }
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}`);
728
+ this.accessory.context.TargetPosition = this.WindowCovering.TargetPosition;
729
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, Number(this.WindowCovering.TargetPosition));
730
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
731
+ + ` TargetPosition: ${this.WindowCovering.TargetPosition}`);
840
732
  }
841
733
  // CurrentAmbientLightLevel
842
734
  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}`);
735
+ if (this.LightSensor.CurrentAmbientLightLevel === undefined || Number.isNaN(this.LightSensor.CurrentAmbientLightLevel)) {
736
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
737
+ + ` CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
845
738
  }
846
739
  else {
847
740
  if (this.device.mqttURL) {
848
- this.mqttPublish('CurrentAmbientLightLevel', this.CurrentAmbientLightLevel);
741
+ this.mqttPublish('CurrentAmbientLightLevel', this.LightSensor.CurrentAmbientLightLevel.toString());
849
742
  }
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}`);
743
+ this.accessory.context.CurrentAmbientLightLevel = this.LightSensor.CurrentAmbientLightLevel;
744
+ this.LightSensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, this.LightSensor.CurrentAmbientLightLevel);
745
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
746
+ + ` updateCharacteristic CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
854
747
  }
855
748
  }
856
749
  // BatteryLevel
857
- if (this.BatteryLevel === undefined) {
858
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
750
+ if (this.Battery.BatteryLevel === undefined) {
751
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}`);
859
752
  }
860
753
  else {
861
754
  if (this.device.mqttURL) {
862
- this.mqttPublish('BatteryLevel', this.BatteryLevel);
755
+ this.mqttPublish('BatteryLevel', this.Battery.BatteryLevel.toString());
863
756
  }
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}`);
757
+ this.accessory.context.BatteryLevel = this.Battery.BatteryLevel;
758
+ this.Battery?.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel);
759
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.Battery.BatteryLevel}`);
867
760
  }
868
761
  // StatusLowBattery
869
- if (this.StatusLowBattery === undefined) {
870
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
762
+ if (this.Battery.StatusLowBattery === undefined) {
763
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.Battery.StatusLowBattery}`);
871
764
  }
872
765
  else {
873
766
  if (this.device.mqttURL) {
874
- this.mqttPublish('StatusLowBattery', this.StatusLowBattery);
767
+ this.mqttPublish('StatusLowBattery', this.Battery.StatusLowBattery.toString());
875
768
  }
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}`);
769
+ this.accessory.context.StatusLowBattery = this.Battery.StatusLowBattery;
770
+ this.Battery?.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery);
771
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
772
+ + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
879
773
  }
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();
774
+ if (this.Battery.ChargingState === undefined) {
775
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ChargingState: ${this.Battery.ChargingState}`);
918
776
  }
919
777
  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
- })();
778
+ if (this.device.mqttURL) {
779
+ this.mqttPublish('ChargingState', this.Battery.ChargingState.toString());
780
+ }
781
+ this.accessory.context.ChargingState = this.Battery.ChargingState;
782
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.ChargingState, this.Battery.ChargingState);
783
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
784
+ + ` ChargingState: ${this.Battery.ChargingState}`);
938
785
  }
939
786
  }
940
787
  async BLEPushConnection() {
@@ -951,210 +798,75 @@ export class BlindTilt {
951
798
  await this.openAPIRefreshStatus();
952
799
  }
953
800
  }
954
- async SilentPerformance() {
955
- if (Number(this.TargetPosition) > 50) {
801
+ async setPerformance() {
802
+ let setPositionMode;
803
+ let Mode;
804
+ if (Number(this.WindowCovering.TargetPosition) > 50) {
956
805
  if (this.device.blindTilt?.setOpenMode === '1') {
957
- this.setPositionMode = 1;
958
- this.Mode = 'Silent Mode';
806
+ setPositionMode = 1;
807
+ Mode = 'Silent Mode';
808
+ }
809
+ else if (this.device.blindTilt?.setOpenMode === '0') {
810
+ setPositionMode = 0;
811
+ Mode = 'Performance Mode';
959
812
  }
960
813
  else {
961
- this.setPositionMode = 0;
962
- this.Mode = 'Performance Mode';
814
+ setPositionMode = 0;
815
+ Mode = 'Default Mode';
963
816
  }
964
817
  }
965
818
  else {
966
819
  if (this.device.blindTilt?.setCloseMode === '1') {
967
- this.setPositionMode = 1;
968
- this.Mode = 'Silent Mode';
820
+ setPositionMode = 1;
821
+ Mode = 'Silent Mode';
822
+ }
823
+ else if (this.device.blindTilt?.setOpenMode === '0') {
824
+ setPositionMode = 0;
825
+ Mode = 'Performance Mode';
969
826
  }
970
827
  else {
971
- this.setPositionMode = 0;
972
- this.Mode = 'Performance Mode';
828
+ setPositionMode = 0;
829
+ Mode = 'Default Mode';
973
830
  }
974
831
  }
832
+ return { setPositionMode, Mode };
975
833
  }
976
834
  async setMinMax() {
977
835
  if (this.device.blindTilt?.set_min) {
978
- if (Number(this.CurrentPosition) <= this.device.blindTilt?.set_min) {
979
- this.CurrentPosition = 0;
836
+ if (Number(this.WindowCovering.CurrentPosition) <= this.device.blindTilt?.set_min) {
837
+ this.WindowCovering.CurrentPosition = 0;
980
838
  }
981
839
  }
982
840
  if (this.device.blindTilt?.set_max) {
983
- if (Number(this.CurrentPosition) >= this.device.blindTilt?.set_max) {
984
- this.CurrentPosition = 100;
841
+ if (Number(this.WindowCovering.CurrentPosition) >= this.device.blindTilt?.set_max) {
842
+ this.WindowCovering.CurrentPosition = 100;
985
843
  }
986
844
  }
987
845
  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`);
846
+ this.WindowCovering.CurrentHorizontalTiltAngle = Number(this.WindowCovering.CurrentHorizontalTiltAngle) < 0 ? -90 : 90;
1115
847
  }
1116
848
  }
1117
849
  async offlineOff() {
1118
850
  if (this.device.offline) {
1119
- await this.deviceContext();
1120
- await this.updateHomeKitCharacteristics();
851
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 100);
852
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
853
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 100);
854
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentHorizontalTiltAngle, 90);
855
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetHorizontalTiltAngle, 90);
1121
856
  }
1122
857
  }
1123
858
  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;
859
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, e);
860
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, e);
861
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, e);
862
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentHorizontalTiltAngle, e);
863
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetHorizontalTiltAngle, e);
864
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e);
865
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e);
866
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.ChargingState, e);
867
+ if (!this.device.blindTilt?.hide_lightsensor) {
868
+ this.LightSensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, e);
869
+ this.LightSensor.Service.updateCharacteristic(this.hap.Characteristic.StatusActive, e);
1158
870
  }
1159
871
  }
1160
872
  /**
@@ -1170,7 +882,8 @@ export class BlindTilt {
1170
882
  // device position 100 => closed up
1171
883
  // homekit position 0 => closed
1172
884
  // homekit position 100 => open
1173
- deviceDirection;
885
+ const direction = deviceDirection === 'up' ? 'up' : 'down';
886
+ this.debugLog(`Mapping device values to homekit values, devicePostion: ${devicePosition}, deviceDirection: ${direction}`);
1174
887
  switch (this.mappingMode) {
1175
888
  case BlindTiltMappingMode.OnlyUp:
1176
889
  // we only close upwards, so we see anything that is tilted downwards(<50) as open
@@ -1271,127 +984,5 @@ export class BlindTilt {
1271
984
  }
1272
985
  }
1273
986
  }
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
987
  }
1397
988
  //# sourceMappingURL=blindtilt.js.map