@switchbot/homebridge-switchbot 3.5.0-beta.7 → 3.5.0-beta.70

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