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

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