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

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