@switchbot/homebridge-switchbot 3.5.0-beta.6 → 3.5.0-beta.60

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 +408 -779
  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 +696 -822
  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 +237 -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 +279 -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 +242 -544
  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 +402 -805
  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 +684 -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 +535 -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 +246 -613
  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 +232 -593
  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 +185 -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 +277 -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 +241 -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 +181 -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 +170 -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 +178 -531
  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 +92 -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 +197 -521
  75. package/dist/device/robotvacuumcleaner.js.map +1 -1
  76. package/dist/device/waterdetector.d.ts +10 -65
  77. package/dist/device/waterdetector.d.ts.map +1 -1
  78. package/dist/device/waterdetector.js +139 -495
  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 +9 -49
  88. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  89. package/dist/irdevice/airconditioner.js +309 -419
  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 +72 -304
  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 +34 -278
  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 +100 -338
  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 +87 -357
  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 +352 -546
  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 +82 -321
  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 +41 -284
  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 +42 -287
  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 -169
  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 +442 -814
  143. package/src/device/bot.ts +754 -915
  144. package/src/device/ceilinglight.ts +255 -633
  145. package/src/device/colorbulb.ts +294 -685
  146. package/src/device/contact.ts +277 -571
  147. package/src/device/curtain.ts +431 -835
  148. package/src/device/device.ts +709 -0
  149. package/src/device/fan.ts +591 -0
  150. package/src/device/hub.ts +286 -644
  151. package/src/device/humidifier.ts +266 -646
  152. package/src/device/iosensor.ts +220 -625
  153. package/src/device/lightstrip.ts +305 -620
  154. package/src/device/lock.ts +280 -600
  155. package/src/device/meter.ts +216 -617
  156. package/src/device/meterplus.ts +205 -619
  157. package/src/device/motion.ts +206 -556
  158. package/src/device/plug.ts +107 -490
  159. package/src/device/robotvacuumcleaner.ts +223 -550
  160. package/src/device/waterdetector.ts +160 -519
  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 +333 -447
  165. package/src/irdevice/airpurifier.ts +92 -322
  166. package/src/irdevice/camera.ts +45 -294
  167. package/src/irdevice/fan.ts +115 -353
  168. package/src/irdevice/irdevice.ts +346 -0
  169. package/src/irdevice/light.ts +110 -385
  170. package/src/irdevice/other.ts +399 -616
  171. package/src/irdevice/tv.ts +103 -340
  172. package/src/irdevice/vacuumcleaner.ts +52 -306
  173. package/src/irdevice/waterheater.ts +53 -311
  174. package/src/platform.ts +355 -216
  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,175 @@
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 LightBulb property
63
+ this.WindowCovering = {
64
+ Name: accessory.context.WindowCoveringName ?? accessory.displayName,
65
+ Service: accessory.getService(this.hap.Service.WindowCovering) ?? accessory.addService(this.hap.Service.WindowCovering) as Service,
66
+ PositionState: accessory.context.PositionState ?? this.hap.Characteristic.PositionState.STOPPED,
67
+ TargetPosition: accessory.context.TargetPosition ?? 100,
68
+ CurrentPosition: accessory.context.CurrentPosition ?? 100,
69
+ HoldPosition: accessory.context.HoldPosition ?? false,
70
+ };
71
+
72
+ // Initialize WindowCovering Service
73
+ this.WindowCovering.Service.
74
+ setCharacteristic(this.hap.Characteristic.Name, this.WindowCovering.Name)
75
+ .setCharacteristic(this.hap.Characteristic.ObstructionDetected, false)
76
+ .getCharacteristic(this.hap.Characteristic.PositionState)
77
+ .onGet(() => {
78
+ return this.WindowCovering.PositionState;
79
+ });
80
+ accessory.context.WindowCoveringName = this.WindowCovering.Name;
135
81
 
136
- this.windowCoveringService
82
+ // Initialize WindowCovering CurrentPosition
83
+ this.WindowCovering.Service
137
84
  .getCharacteristic(this.hap.Characteristic.CurrentPosition)
138
85
  .setProps({
139
- minStep: this.minStep(device),
86
+ minStep: Number(this.minStep(device)),
140
87
  minValue: 0,
141
88
  maxValue: 100,
142
89
  validValueRanges: [0, 100],
143
90
  })
144
91
  .onGet(() => {
145
- return this.CurrentPosition;
92
+ return this.WindowCovering.CurrentPosition;
146
93
  });
147
94
 
148
- this.windowCoveringService
95
+ // Initialize WindowCovering TargetPosition
96
+ this.WindowCovering.Service
149
97
  .getCharacteristic(this.hap.Characteristic.TargetPosition)
150
98
  .setProps({
151
- minStep: this.minStep(device),
99
+ minStep: Number(this.minStep(device)),
152
100
  minValue: 0,
153
101
  maxValue: 100,
154
102
  validValueRanges: [0, 100],
155
103
  })
104
+ .onGet(() => {
105
+ return this.WindowCovering.TargetPosition;
106
+ })
156
107
  .onSet(this.TargetPositionSet.bind(this));
157
108
 
158
- this.windowCoveringService
109
+ // Initialize WindowCovering TargetPosition
110
+ this.WindowCovering.Service
159
111
  .getCharacteristic(this.hap.Characteristic.HoldPosition)
112
+ .onGet(() => {
113
+ return this.WindowCovering.HoldPosition;
114
+ })
160
115
  .onSet(this.HoldPositionSet.bind(this));
161
116
 
162
- // Light Sensor Service
117
+ // Initialize Battery property
118
+ this.Battery = {
119
+ Name: accessory.context.BatteryName ?? `${accessory.displayName} Battery`,
120
+ Service: accessory.getService(this.hap.Service.Battery) ?? accessory.addService(this.hap.Service.Battery) as Service,
121
+ BatteryLevel: accessory.context.BatteryLevel ?? 100,
122
+ StatusLowBattery: accessory.context.StatusLowBattery ?? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,
123
+ ChargingState: accessory.context.ChargingState ?? this.hap.Characteristic.ChargingState.NOT_CHARGING,
124
+ };
125
+
126
+ // Initialize Battery Service
127
+ this.Battery.Service
128
+ .setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name)
129
+ .getCharacteristic(this.hap.Characteristic.BatteryLevel)
130
+ .onGet(() => {
131
+ return this.Battery.BatteryLevel;
132
+ });
133
+ accessory.context.BatteryName = this.Battery.Name;
134
+
135
+ this.Battery.Service
136
+ .getCharacteristic(this.hap.Characteristic.StatusLowBattery)
137
+ .onGet(() => {
138
+ return this.Battery.StatusLowBattery;
139
+ });
140
+
141
+ this.Battery.Service
142
+ .getCharacteristic(this.hap.Characteristic.ChargingState)
143
+ .onGet(() => {
144
+ return this.Battery.ChargingState;
145
+ });
146
+
147
+ // Initialize LightSensor Service
163
148
  if (device.curtain?.hide_lightsensor) {
164
149
  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;
172
-
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
- }
150
+ this.LightSensor!.Service = this.accessory.getService(this.hap.Service.LightSensor) as Service;
151
+ accessory.removeService(this.LightSensor!.Service);
177
152
  } else {
178
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Light Sensor Service Not Added`);
179
- }
180
-
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;
153
+ this.LightSensor = {
154
+ Name: accessory.context.LightSensorName ?? `${accessory.displayName} Light Sensor`,
155
+ Service: accessory.getService(this.hap.Service.LightSensor) ?? this.accessory.addService(this.hap.Service.LightSensor) as Service,
156
+ CurrentAmbientLightLevel: accessory.context.CurrentAmbientLightLevel ?? 0.0001,
157
+ };
185
158
 
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`);
159
+ // Initialize LightSensor Characteristic
160
+ this.LightSensor.Service
161
+ .setCharacteristic(this.hap.Characteristic.Name, this.LightSensor.Name)
162
+ .setCharacteristic(this.hap.Characteristic.StatusActive, true)
163
+ .getCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel)
164
+ .onGet(() => {
165
+ return this.LightSensor!.CurrentAmbientLightLevel!;
166
+ });
167
+ accessory.context.LightSensorName = this.LightSensor.Name;
189
168
  }
190
169
 
170
+ // Retrieve initial values and updateHomekit
171
+ this.refreshStatus();
172
+
191
173
  // Update Homekit
192
174
  this.updateHomeKitCharacteristics();
193
175
 
@@ -199,19 +181,18 @@ export class Curtain {
199
181
  });
200
182
 
201
183
  //regisiter webhook event handler
202
- if (this.device.webhook) {
203
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} is listening webhook.`);
184
+ if (device.webhook) {
185
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} is listening webhook.`);
204
186
  this.platform.webhookEventHandler[this.device.deviceId] = async (context) => {
205
187
  try {
206
188
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
207
189
  const { slidePosition, battery } = context;
208
- const { CurrentPosition, BatteryLevel } = this;
209
190
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ` +
210
191
  '(slidePosition, battery) = ' +
211
192
  `Webhook:(${slidePosition}, ${battery}), ` +
212
- `current:(${CurrentPosition}, ${BatteryLevel})`);
213
- this.CurrentPosition = slidePosition;
214
- this.BatteryLevel = battery;
193
+ `current:(${this.WindowCovering.CurrentPosition}, ${this.Battery.BatteryLevel})`);
194
+ this.WindowCovering.CurrentPosition = slidePosition;
195
+ this.Battery.BatteryLevel = battery;
215
196
  this.updateHomeKitCharacteristics();
216
197
  } catch (e: any) {
217
198
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
@@ -221,13 +202,14 @@ export class Curtain {
221
202
  }
222
203
 
223
204
  // update slide progress
224
- interval(this.updateRate * 1000)
205
+ interval(this.deviceUpdateRate * 1000)
225
206
  //.pipe(skipWhile(() => this.curtainUpdateInProgress))
226
207
  .subscribe(async () => {
227
- if (this.PositionState === this.hap.Characteristic.PositionState.STOPPED) {
208
+ if (this.WindowCovering.PositionState === this.hap.Characteristic.PositionState.STOPPED) {
228
209
  return;
229
210
  }
230
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Refresh Status When Moving, PositionState: ${this.PositionState}`);
211
+ this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Refresh Status When Moving,`
212
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
231
213
  await this.refreshStatus();
232
214
  });
233
215
 
@@ -257,6 +239,16 @@ export class Curtain {
257
239
  this.setupHistoryService(device);
258
240
  }
259
241
 
242
+ private history(device: device & devicesConfig) {
243
+ if (device.history === true) {
244
+ // initialize when this accessory is newly created.
245
+ this.accessory.context.lastActivation = this.accessory.context.lastActivation ?? 0;
246
+ } else {
247
+ // removes cached values if history is turned off
248
+ delete this.accessory.context.lastActivation;
249
+ }
250
+ }
251
+
260
252
  /*
261
253
  * Setup EVE history features for curtain devices.
262
254
  */
@@ -304,7 +296,7 @@ export class Curtain {
304
296
  }
305
297
 
306
298
  async updateHistory(): Promise<void> {
307
- const motion = Number(this.CurrentPosition) > 0 ? 1 : 0;
299
+ const motion = Number(this.WindowCovering.CurrentPosition) > 0 ? 1 : 0;
308
300
  this.historyService.addEntry({
309
301
  time: Math.round(new Date().valueOf() / 1000),
310
302
  motion: motion,
@@ -317,198 +309,206 @@ export class Curtain {
317
309
  );
318
310
  }
319
311
 
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> {
312
+ async BLEparseStatus(serviceData: serviceData): Promise<void> {
339
313
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
340
314
  // CurrentPosition
341
- this.CurrentPosition = 100 - Number(this.BLE_CurrentPosition);
315
+ this.WindowCovering.CurrentPosition = 100 - Number(serviceData.position);
342
316
  await this.setMinMax();
343
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition ${this.CurrentPosition}`);
317
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition ${this.WindowCovering.CurrentPosition}`);
344
318
  if (this.setNewTarget) {
345
319
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Checking Status ...`);
346
320
  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}`);
321
+ if (Number(this.WindowCovering.TargetPosition) > this.WindowCovering.CurrentPosition) {
322
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
323
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
324
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
325
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} INCREASING`
326
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
327
+ } else if (Number(this.WindowCovering.TargetPosition) < this.WindowCovering.CurrentPosition) {
328
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Opening, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
329
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
330
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
331
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} DECREASING`
332
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
357
333
  } 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}`);
334
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} Standby,`
335
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
336
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
337
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
338
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} STOPPED`
339
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
362
340
  }
363
341
  } 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;
342
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
343
+ this.WindowCovering.TargetPosition = this.WindowCovering.CurrentPosition;
344
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
367
345
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Stopped`);
368
346
  }
369
347
  this.debugLog(
370
- `${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition},` +
371
- ` TargetPosition: ${this.TargetPosition}, PositionState: ${this.PositionState},`,
348
+ `${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition},` +
349
+ ` TargetPosition: ${this.WindowCovering.TargetPosition}, PositionState: ${this.WindowCovering.PositionState},`,
372
350
  );
373
351
 
374
352
  if (!this.device.curtain?.hide_lightsensor) {
375
- this.set_minLux = this.minLux();
376
- this.set_maxLux = this.maxLux();
377
- this.spaceBetweenLevels = 9;
353
+ const set_minLux = await this.minLux();
354
+ const set_maxLux = await this.maxLux();
355
+ const spaceBetweenLevels = 9;
378
356
 
379
357
  // Brightness
380
- switch (this.BLE_CurrentAmbientLightLevel) {
358
+ switch (serviceData.lightLevel) {
381
359
  case 1:
382
- this.CurrentAmbientLightLevel = this.set_minLux;
383
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.BLE_CurrentAmbientLightLevel}`);
360
+ this.LightSensor!.CurrentAmbientLightLevel = set_minLux;
361
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
384
362
  break;
385
363
  case 2:
386
- this.CurrentAmbientLightLevel = (this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels;
364
+ this.LightSensor!.CurrentAmbientLightLevel = (set_maxLux - set_minLux) / spaceBetweenLevels;
387
365
  this.debugLog(
388
- `${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.BLE_CurrentAmbientLightLevel},` +
389
- ` Calculation: ${(this.set_maxLux - this.set_minLux) / this.spaceBetweenLevels}`,
366
+ `${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel},` +
367
+ ` Calculation: ${(set_maxLux - set_minLux) / spaceBetweenLevels}`,
390
368
  );
391
369
  break;
392
370
  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}`);
371
+ this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 2;
372
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
373
+ this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
395
374
  break;
396
375
  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}`);
376
+ this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 3;
377
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
378
+ this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
399
379
  break;
400
380
  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}`);
381
+ this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 4;
382
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
383
+ this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
403
384
  break;
404
385
  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}`);
386
+ this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 5;
387
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
388
+ this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
407
389
  break;
408
390
  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}`);
391
+ this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 6;
392
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
393
+ this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
411
394
  break;
412
395
  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}`);
396
+ this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 7;
397
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
398
+ this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
415
399
  break;
416
400
  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}`);
401
+ this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 8;
402
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
403
+ this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
419
404
  break;
420
405
  case 10:
421
406
  default:
422
- this.CurrentAmbientLightLevel = this.set_maxLux;
407
+ this.LightSensor!.CurrentAmbientLightLevel = set_maxLux;
423
408
  this.debugLog();
424
409
  }
425
410
  this.debugLog(
426
- `${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${this.BLE_CurrentAmbientLightLevel},` +
427
- ` CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`,
411
+ `${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel},` +
412
+ ` CurrentAmbientLightLevel: ${this.LightSensor!.CurrentAmbientLightLevel}`,
428
413
  );
429
414
  }
430
415
  // Battery
431
- this.BatteryLevel = Number(this.BLE_BatteryLevel);
432
- if (this.BatteryLevel < 10) {
433
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
416
+ this.Battery.BatteryLevel = Number(serviceData.battery);
417
+ if (this.Battery.BatteryLevel < 10) {
418
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
434
419
  } else {
435
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
420
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
436
421
  }
437
422
  this.debugLog(
438
- `${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel},` + ` StatusLowBattery: ${this.StatusLowBattery}`,
423
+ `${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
424
+ + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`,
439
425
  );
440
426
  }
441
427
 
442
- async openAPIparseStatus(): Promise<void> {
428
+ async openAPIparseStatus(deviceStatus: deviceStatus): Promise<void> {
443
429
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
444
430
  // CurrentPosition
445
- this.CurrentPosition = 100 - Number(this.OpenAPI_CurrentPosition);
431
+ this.WindowCovering!.CurrentPosition = 100 - Number(deviceStatus.body.slidePosition);
446
432
  await this.setMinMax();
447
- this.debugLog(`Curtain ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition}`);
433
+ this.debugLog(`Curtain ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
448
434
  if (this.setNewTarget) {
449
435
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Checking Status ...`);
450
436
  }
451
437
 
452
- if (this.setNewTarget && this.OpenAPI_InMotion) {
438
+ if (this.setNewTarget && deviceStatus.body.moving) {
453
439
  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}`);
440
+ if (Number(this.WindowCovering.TargetPosition) > this.WindowCovering.CurrentPosition) {
441
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition} `);
442
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
443
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
444
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} INCREASING`
445
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
446
+ } else if (Number(this.WindowCovering.TargetPosition) < this.WindowCovering.CurrentPosition) {
447
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Opening, CurrentPosition: ${this.WindowCovering.CurrentPosition} `);
448
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
449
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
450
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} DECREASING`
451
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
464
452
  } 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}`);
453
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} Standby,`
454
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
455
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
456
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
457
+ this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} STOPPED`
458
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
469
459
  }
470
460
  } 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;
461
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
462
+ this.WindowCovering.TargetPosition = this.WindowCovering.CurrentPosition;
463
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
474
464
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Stopped`);
475
465
  }
476
466
  this.debugLog(
477
- `${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition},` +
478
- ` TargetPosition: ${this.TargetPosition}, PositionState: ${this.PositionState},`,
467
+ `${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition},` +
468
+ ` TargetPosition: ${this.WindowCovering.TargetPosition}, PositionState: ${this.WindowCovering.PositionState},`,
479
469
  );
480
470
 
481
471
  // Brightness
482
472
  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;
473
+ const set_minLux = await this.minLux();
474
+ const set_maxLux = await this.maxLux();
475
+ switch (deviceStatus.body.brightness) {
489
476
  case 'bright':
477
+ this.LightSensor!.CurrentAmbientLightLevel = set_maxLux;
478
+ this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
479
+ break;
480
+ case 'dim':
490
481
  default:
491
- this.CurrentAmbientLightLevel = this.set_maxLux;
482
+ this.LightSensor!.CurrentAmbientLightLevel = set_minLux;
492
483
  }
493
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
484
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
485
+ + ` CurrentAmbientLightLevel: ${this.LightSensor!.CurrentAmbientLightLevel}`);
494
486
  }
495
487
 
496
488
  // BatteryLevel
497
- this.BatteryLevel = Number(this.OpenAPI_BatteryLevel);
498
- if (this.BatteryLevel < 10) {
499
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
489
+ this.Battery.BatteryLevel = Number(deviceStatus.body.battery);
490
+ if (this.Battery.BatteryLevel < 10) {
491
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
500
492
  } else {
501
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
493
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
502
494
  }
503
- if (Number.isNaN(this.BatteryLevel)) {
504
- this.BatteryLevel = 100;
495
+ if (Number.isNaN(this.Battery.BatteryLevel)) {
496
+ this.Battery.BatteryLevel = 100;
505
497
  }
506
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel},`
507
- + ` StatusLowBattery: ${this.StatusLowBattery}`);
498
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
499
+ + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
508
500
 
509
- // FirmwareRevision
510
- this.FirmwareRevision = this.OpenAPI_FirmwareRevision!;
511
- this.accessory.context.FirmwareRevision = this.FirmwareRevision;
501
+ // Firmware Version
502
+ const version = deviceStatus.body.version?.toString();
503
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Firmware Version: ${version?.replace(/^V|-.*$/g, '')}`);
504
+ if (deviceStatus.body.version) {
505
+ this.accessory.context.version = version?.replace(/^V|-.*$/g, '');
506
+ this.accessory
507
+ .getService(this.hap.Service.AccessoryInformation)!
508
+ .setCharacteristic(this.hap.Characteristic.FirmwareRevision, this.accessory.context.version)
509
+ .getCharacteristic(this.hap.Characteristic.FirmwareRevision)
510
+ .updateValue(this.accessory.context.version);
511
+ }
512
512
  }
513
513
 
514
514
  async refreshStatus(): Promise<void> {
@@ -538,118 +538,45 @@ export class Curtain {
538
538
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
539
539
  this.getCustomBLEAddress(switchbot);
540
540
  // 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
541
  (async () => {
550
542
  // Start to monitor advertisement packets
551
- await switchbot.startScan({
552
- model: model,
553
- id: this.device.bleMac,
554
- });
543
+ await switchbot.startScan({ model: this.device.bleModel, id: this.device.bleMac });
555
544
  // Set an event handler
556
545
  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') {
546
+ if (this.device.bleMac === ad.address && ad.model === this.device.bleModel) {
547
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
548
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.model}`);
560
549
  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
550
  } else {
567
551
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
568
552
  }
569
553
  };
570
- // Wait 1 seconds
554
+ // Wait 10 seconds
571
555
  await switchbot.wait(this.scanDuration * 1000);
572
556
  // Stop to monitor
573
557
  await switchbot.stopScan();
574
558
  // Update HomeKit
575
- await this.BLEparseStatus();
559
+ await this.BLEparseStatus(switchbot.onadvertisement.serviceData);
576
560
  await this.updateHomeKitCharacteristics();
577
561
  })();
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 {
562
+ if (switchbot === undefined) {
630
563
  await this.BLERefreshConnection(switchbot);
631
- }*/
564
+ }
632
565
  }
633
566
 
634
567
  async openAPIRefreshStatus(): Promise<void> {
635
568
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
636
569
  try {
637
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/status`, {
638
- headers: this.platform.generateHeaders(),
639
- });
570
+ const { body, statusCode } = await this.platform.retryRequest(this.deviceMaxRetries, this.deviceDelayBetweenRetries,
571
+ `${Devices}/${this.device.deviceId}/status`, { headers: this.platform.generateHeaders() });
640
572
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
641
573
  const deviceStatus: any = await body.json();
642
574
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
643
575
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
644
576
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
645
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
577
+ this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
646
578
  + `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();
579
+ this.openAPIparseStatus(deviceStatus);
653
580
  this.updateHomeKitCharacteristics();
654
581
  } else {
655
582
  this.statusCode(statusCode);
@@ -688,7 +615,7 @@ export class Curtain {
688
615
 
689
616
  async BLEpushChanges(): Promise<void> {
690
617
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
691
- if (this.TargetPosition !== this.CurrentPosition) {
618
+ if (this.WindowCovering.TargetPosition !== this.WindowCovering.CurrentPosition) {
692
619
  const switchbot = await this.platform.connectBLE();
693
620
  // Convert to BLE Address
694
621
  this.device.bleMac = this.device
@@ -696,27 +623,29 @@ export class Curtain {
696
623
  .join(':')
697
624
  .toLowerCase();
698
625
  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}`);
626
+ const { setPositionMode, Mode }: { setPositionMode: number; Mode: string; } = await this.setPerformance();
627
+ const adjustedMode = setPositionMode === 1 ? 0x01 : 0xff;
628
+ this.debugLog(`${this.accessory.displayName} Mode: ${Mode}`);
702
629
  if (switchbot !== false) {
703
630
  try {
704
631
  const device_list = await switchbot.discover({ model: 'c', quick: true, id: this.device.bleMac });
705
- this.infoLog(`${this.accessory.displayName} Target Position: ${this.TargetPosition}`);
632
+ this.infoLog(`${this.accessory.displayName} Target Position: ${this.WindowCovering.TargetPosition}`);
706
633
 
707
- await this.retry({
708
- max: this.maxRetry(),
634
+ await this.retryBLE({
635
+ max: await this.maxRetryBLE(),
709
636
  fn: async () => {
710
- await device_list[0].runToPos(100 - Number(this.TargetPosition), adjustedMode);
637
+ await device_list[0].runToPos(100 - Number(this.WindowCovering.TargetPosition), adjustedMode);
711
638
  },
712
639
  });
713
640
 
714
641
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
642
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
643
+ + `TargetPosition: ${this.WindowCovering.TargetPosition} sent over BLE, sent successfully`);
715
644
  } catch (e) {
716
645
  this.apiError(e);
717
646
  this.errorLog(
718
647
  `${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}` +
719
- ` Connection, Error Message: ${JSON.stringify((e as Error).message)}`,
648
+ ` Connection, Error Message: ${JSON.stringify((e as Error).message)}`,
720
649
  );
721
650
  await this.BLEPushConnection();
722
651
  throw new Error('Connection error');
@@ -728,54 +657,23 @@ export class Curtain {
728
657
  } else {
729
658
  this.debugLog(
730
659
  `${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges, CurrentPosition & TargetPosition Are the Same.` +
731
- ` CurrentPosition: ${this.CurrentPosition}, TargetPosition ${this.TargetPosition}`,
660
+ ` CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition ${this.WindowCovering.TargetPosition}`,
732
661
  );
733
662
  }
734
663
  }
735
664
 
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
665
  async openAPIpushChanges(): Promise<void> {
757
666
  let command: string;
758
667
  let parameter: string;
759
668
  let commandType: string;
760
669
  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) {
670
+ if (this.WindowCovering.TargetPosition !== this.WindowCovering.CurrentPosition || this.device.disableCaching) {
671
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Pushing ${this.WindowCovering.TargetPosition}`);
672
+ const adjustedTargetPosition = 100 - Number(this.WindowCovering.TargetPosition);
673
+ const { setPositionMode, Mode }: { setPositionMode: number; Mode: string; } = await this.setPerformance();
674
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Mode: ${Mode}`);
675
+ const adjustedMode = setPositionMode || 'ff';
676
+ if (this.WindowCovering.HoldPosition) {
779
677
  command = 'pause';
780
678
  parameter = 'default';
781
679
  commandType = 'command';
@@ -804,6 +702,8 @@ export class Curtain {
804
702
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
805
703
  this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
806
704
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
705
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
706
+ + `request to SwitchBot API, body: ${JSON.stringify(deviceStatus)} sent successfully`);
807
707
  } else {
808
708
  this.statusCode(statusCode);
809
709
  this.statusCode(deviceStatus.statusCode);
@@ -818,7 +718,7 @@ export class Curtain {
818
718
  } else {
819
719
  this.debugLog(
820
720
  `${this.device.deviceType}: ${this.accessory.displayName} No OpenAPI Changes, CurrentPosition & TargetPosition Are the Same.` +
821
- ` CurrentPosition: ${this.CurrentPosition}, TargetPosition ${this.TargetPosition}`,
721
+ ` CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition ${this.WindowCovering.TargetPosition}`,
822
722
  );
823
723
  }
824
724
  }
@@ -827,50 +727,53 @@ export class Curtain {
827
727
  * Handle requests to set the value of the "Target Position" characteristic
828
728
  */
829
729
  async TargetPositionSet(value: CharacteristicValue): Promise<void> {
830
- if (this.TargetPosition === this.accessory.context.TargetPosition) {
730
+ if (this.WindowCovering.TargetPosition === this.accessory.context.TargetPosition) {
831
731
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set TargetPosition: ${value}`);
832
732
  } else {
833
733
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetPosition: ${value}`);
834
734
  }
835
735
 
836
736
  // Set HoldPosition to false when TargetPosition is changed
837
- this.HoldPosition = false;
838
- this.windowCoveringService.updateCharacteristic(this.hap.Characteristic.HoldPosition, this.HoldPosition);
737
+ this.WindowCovering.HoldPosition = false;
738
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.HoldPosition, this.WindowCovering.HoldPosition);
839
739
 
840
- this.TargetPosition = value;
740
+ this.WindowCovering.TargetPosition = value;
841
741
  if (this.device.mqttURL) {
842
- this.mqttPublish('TargetPosition', this.TargetPosition);
843
- this.mqttPublish('HoldPosition', this.HoldPosition);
742
+ this.mqttPublish('TargetPosition', this.WindowCovering.TargetPosition.toString());
743
+ this.mqttPublish('HoldPosition', this.WindowCovering.HoldPosition.toString()); // Convert boolean to string
844
744
  }
845
745
 
846
746
  await this.setMinMax();
847
- if (value > this.CurrentPosition) {
848
- this.PositionState = this.hap.Characteristic.PositionState.INCREASING;
747
+ if (value > this.WindowCovering.CurrentPosition) {
748
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
849
749
  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;
750
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${value},`
751
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
752
+ } else if (value < this.WindowCovering.CurrentPosition) {
753
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
853
754
  this.setNewTarget = true;
854
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${value}, CurrentPosition: ${this.CurrentPosition}`);
755
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${value},`
756
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
855
757
  } else {
856
- this.PositionState = this.hap.Characteristic.PositionState.STOPPED;
758
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
857
759
  this.setNewTarget = false;
858
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${value}, CurrentPosition: ${this.CurrentPosition}`);
760
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${value},`
761
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
859
762
  }
860
- this.windowCoveringService.setCharacteristic(this.hap.Characteristic.PositionState, this.PositionState);
861
- this.windowCoveringService.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.PositionState);
763
+ this.WindowCovering.Service.setCharacteristic(this.hap.Characteristic.PositionState, this.WindowCovering.PositionState);
764
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
862
765
 
863
766
  /**
864
767
  * If Curtain movement time is short, the moving flag from backend is always false.
865
768
  * The minimum time depends on the network control latency.
866
769
  */
867
770
  clearTimeout(this.setNewTargetTimer);
868
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateRate: ${this.updateRate}`);
771
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateRate: ${this.deviceUpdateRate}`);
869
772
  if (this.setNewTarget) {
870
773
  this.setNewTargetTimer = setTimeout(() => {
871
774
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} setNewTarget ${this.setNewTarget} timeout`);
872
775
  this.setNewTarget = false;
873
- }, this.updateRate * 1000);
776
+ }, this.deviceUpdateRate * 1000);
874
777
  }
875
778
  this.doCurtainUpdate.next();
876
779
  }
@@ -880,153 +783,109 @@ export class Curtain {
880
783
  */
881
784
  async HoldPositionSet(value: CharacteristicValue): Promise<void> {
882
785
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} HoldPosition: ${value}`);
883
- this.HoldPosition = value;
786
+ this.WindowCovering.HoldPosition = value;
884
787
  this.doCurtainUpdate.next();
885
788
  }
886
789
 
887
790
  async updateHomeKitCharacteristics(): Promise<void> {
888
791
  await this.setMinMax();
889
- if (this.CurrentPosition === undefined || Number.isNaN(this.CurrentPosition)) {
890
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition}`);
792
+ if (this.WindowCovering.CurrentPosition === undefined || Number.isNaN(this.WindowCovering.CurrentPosition)) {
793
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
891
794
  } else {
795
+ this.accessory.context.CurrentPosition = this.WindowCovering.CurrentPosition;
796
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, Number(this.WindowCovering.CurrentPosition));
797
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
798
+ + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
892
799
  if (this.device.mqttURL) {
893
- this.mqttPublish('CurrentPosition', this.CurrentPosition);
800
+ this.mqttPublish('CurrentPosition', this.WindowCovering.CurrentPosition.toString()); // Convert to string
894
801
  }
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
802
  }
899
- if (this.PositionState === undefined) {
900
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} PositionState: ${this.PositionState}`);
803
+ if (this.WindowCovering.PositionState === undefined) {
804
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} PositionState: ${this.WindowCovering.PositionState}`);
901
805
  } else {
902
806
  if (this.device.mqttURL) {
903
- this.mqttPublish('PositionState', this.PositionState);
807
+ this.mqttPublish('PositionState', this.WindowCovering.PositionState.toString());
904
808
  }
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}`);
809
+ this.accessory.context.PositionState = this.WindowCovering.PositionState;
810
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, Number(this.WindowCovering.PositionState));
811
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
812
+ + ` PositionState: ${this.WindowCovering.PositionState}`);
908
813
  }
909
- if (this.TargetPosition === undefined || Number.isNaN(this.TargetPosition)) {
910
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} TargetPosition: ${this.TargetPosition}`);
814
+ if (this.WindowCovering.TargetPosition === undefined || Number.isNaN(this.WindowCovering.TargetPosition)) {
815
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} TargetPosition: ${this.WindowCovering.TargetPosition}`);
911
816
  } else {
912
817
  if (this.device.mqttURL) {
913
- this.mqttPublish('TargetPosition', this.TargetPosition);
818
+ this.mqttPublish('TargetPosition', this.WindowCovering.TargetPosition.toString());
914
819
  }
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}`);
820
+ this.accessory.context.TargetPosition = this.WindowCovering.TargetPosition;
821
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, Number(this.WindowCovering.TargetPosition));
822
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
823
+ + ` TargetPosition: ${this.WindowCovering.TargetPosition}`);
918
824
  }
919
- if (this.HoldPosition === undefined) {
920
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} HoldPosition: ${this.HoldPosition}`);
825
+ if (this.WindowCovering.HoldPosition === undefined) {
826
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} HoldPosition: ${this.WindowCovering.HoldPosition}`);
921
827
  } else {
922
828
  if (this.device.mqttURL) {
923
- this.mqttPublish('HoldPosition', this.HoldPosition);
829
+ this.mqttPublish('HoldPosition', this.WindowCovering.HoldPosition.toString());
924
830
  }
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}`);
831
+ this.accessory.context.HoldPosition = this.WindowCovering.HoldPosition;
832
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.HoldPosition, this.WindowCovering.HoldPosition);
833
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
834
+ + ` HoldPosition: ${this.WindowCovering.HoldPosition}`);
928
835
  }
929
836
  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}`);
837
+ if (this.LightSensor!.CurrentAmbientLightLevel === undefined || Number.isNaN(this.LightSensor!.CurrentAmbientLightLevel)) {
838
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
839
+ + ` CurrentAmbientLightLevel: ${this.LightSensor!.CurrentAmbientLightLevel}`);
932
840
  } else {
933
841
  if (this.device.mqttURL) {
934
- this.mqttPublish('CurrentAmbientLightLevel', this.CurrentAmbientLightLevel);
842
+ this.mqttPublish('CurrentAmbientLightLevel', this.LightSensor!.CurrentAmbientLightLevel.toString());
935
843
  }
936
- this.accessory.context.CurrentAmbientLightLevel = this.CurrentAmbientLightLevel;
937
- this.lightSensorService?.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, this.CurrentAmbientLightLevel);
844
+ this.accessory.context.CurrentAmbientLightLevel = this.LightSensor!.CurrentAmbientLightLevel;
845
+ this.LightSensor!.Service.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, this.LightSensor!.CurrentAmbientLightLevel);
938
846
  this.debugLog(
939
847
  `${this.device.deviceType}: ${this.accessory.displayName}` +
940
- ` updateCharacteristic CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`,
848
+ ` updateCharacteristic CurrentAmbientLightLevel: ${this.LightSensor!.CurrentAmbientLightLevel}`,
941
849
  );
942
850
  if (this.device.history) {
943
851
  this.historyService?.addEntry({
944
852
  time: Math.round(new Date().valueOf() / 1000),
945
- lux: this.CurrentAmbientLightLevel,
853
+ lux: this.LightSensor!.CurrentAmbientLightLevel,
946
854
  });
947
855
  }
948
856
  }
949
857
  }
950
- if (this.BatteryLevel === undefined) {
951
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
858
+ if (this.Battery.BatteryLevel === undefined) {
859
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}`);
952
860
  } else {
953
861
  if (this.device.mqttURL) {
954
- this.mqttPublish('BatteryLevel', this.BatteryLevel);
862
+ this.mqttPublish('BatteryLevel', this.Battery.BatteryLevel.toString());
955
863
  }
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}`);
864
+ this.accessory.context.BatteryLevel = this.Battery.BatteryLevel;
865
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel);
866
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.Battery.BatteryLevel}`);
959
867
  }
960
- if (this.StatusLowBattery === undefined) {
961
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
868
+ if (this.Battery.StatusLowBattery === undefined) {
869
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.Battery.StatusLowBattery}`);
962
870
  } else {
963
871
  if (this.device.mqttURL) {
964
- this.mqttPublish('StatusLowBattery', this.StatusLowBattery);
872
+ this.mqttPublish('StatusLowBattery', this.Battery.StatusLowBattery.toString());
965
873
  }
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}`);
874
+ this.accessory.context.StatusLowBattery = this.Battery.StatusLowBattery;
875
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery);
876
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
877
+ + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
969
878
  }
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();
879
+ if (this.Battery.ChargingState === undefined) {
880
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ChargingState: ${this.Battery.ChargingState}`);
1010
881
  } 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
- })();
882
+ if (this.device.mqttURL) {
883
+ this.mqttPublish('ChargingState', this.Battery.ChargingState.toString());
884
+ }
885
+ this.accessory.context.ChargingState = this.Battery.ChargingState;
886
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.ChargingState, this.Battery.ChargingState);
887
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
888
+ + ` ChargingState: ${this.Battery.ChargingState}`);
1030
889
  }
1031
890
  }
1032
891
 
@@ -1046,364 +905,101 @@ export class Curtain {
1046
905
  }
1047
906
  }
1048
907
 
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';
908
+ async setPerformance() {
909
+ let setPositionMode: number;
910
+ let Mode: string;
911
+ if (Number(this.WindowCovering.TargetPosition) > 50) {
912
+ if (this.device.blindTilt?.setOpenMode === '1') {
913
+ setPositionMode = 1;
914
+ Mode = 'Silent Mode';
915
+ } else if (this.device.blindTilt?.setOpenMode === '0') {
916
+ setPositionMode = 0;
917
+ Mode = 'Performance Mode';
1054
918
  } else {
1055
- this.setPositionMode = '0';
1056
- this.Mode = 'Performance Mode';
919
+ setPositionMode = 0;
920
+ Mode = 'Default Mode';
1057
921
  }
1058
922
  } else {
1059
- if (this.device.curtain?.setCloseMode === '1') {
1060
- this.setPositionMode = '1';
1061
- this.Mode = 'Silent Mode';
923
+ if (this.device.blindTilt?.setCloseMode === '1') {
924
+ setPositionMode = 1;
925
+ Mode = 'Silent Mode';
926
+ } else if (this.device.blindTilt?.setOpenMode === '0') {
927
+ setPositionMode = 0;
928
+ Mode = 'Performance Mode';
1062
929
  } else {
1063
- this.setPositionMode = '0';
1064
- this.Mode = 'Performance Mode';
930
+ setPositionMode = 0;
931
+ Mode = 'Default Mode';
1065
932
  }
1066
933
  }
934
+ return { setPositionMode, Mode };
1067
935
  }
1068
936
 
1069
937
  async setMinMax(): Promise<void> {
1070
938
  if (this.device.curtain?.set_min) {
1071
- if (Number(this.CurrentPosition) <= this.device.curtain?.set_min) {
1072
- this.CurrentPosition = 0;
939
+ if (Number(this.WindowCovering.CurrentPosition) <= this.device.curtain?.set_min) {
940
+ this.WindowCovering.CurrentPosition = 0;
1073
941
  }
1074
942
  }
1075
943
  if (this.device.curtain?.set_max) {
1076
- if (Number(this.CurrentPosition) >= this.device.curtain?.set_max) {
1077
- this.CurrentPosition = 100;
944
+ if (Number(this.WindowCovering.CurrentPosition) >= this.device.curtain?.set_max) {
945
+ this.WindowCovering.CurrentPosition = 100;
1078
946
  }
1079
947
  }
1080
948
  if (this.device.history) {
1081
949
  const motion = this.accessory.getService(this.hap.Service.MotionSensor);
1082
- const state = Number(this.CurrentPosition) > 0 ? 1 : 0;
950
+ const state = Number(this.WindowCovering.CurrentPosition) > 0 ? 1 : 0;
1083
951
  motion?.updateCharacteristic(this.hap.Characteristic.MotionDetected, state);
1084
952
  }
1085
953
  }
1086
954
 
1087
- minStep(device: device & devicesConfig): number {
955
+ async minStep(device: device & devicesConfig): Promise<number> {
956
+ let set_minStep: number;
1088
957
  if (device.curtain?.set_minStep) {
1089
- this.set_minStep = device.curtain?.set_minStep;
958
+ set_minStep = device.curtain?.set_minStep;
1090
959
  } else {
1091
- this.set_minStep = 1;
960
+ set_minStep = 1;
1092
961
  }
1093
- return this.set_minStep;
962
+ return set_minStep;
1094
963
  }
1095
964
 
1096
- minLux(): number {
965
+ async minLux(): Promise<number> {
966
+ let set_minLux: number;
1097
967
  if (this.device.curtain?.set_minLux) {
1098
- this.set_minLux = this.device.curtain?.set_minLux;
968
+ set_minLux = this.device.curtain?.set_minLux;
1099
969
  } else {
1100
- this.set_minLux = 1;
970
+ set_minLux = 1;
1101
971
  }
1102
- return this.set_minLux;
972
+ return set_minLux;
1103
973
  }
1104
974
 
1105
- maxLux(): number {
975
+ async maxLux(): Promise<number> {
976
+ let set_maxLux: number;
1106
977
  if (this.device.curtain?.set_maxLux) {
1107
- this.set_maxLux = this.device.curtain?.set_maxLux;
978
+ set_maxLux = this.device.curtain?.set_maxLux;
1108
979
  } 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
- );
980
+ set_maxLux = 6001;
1217
981
  }
982
+ return set_maxLux;
1218
983
  }
1219
984
 
1220
985
  async offlineOff(): Promise<void> {
1221
986
  if (this.device.offline) {
1222
- await this.deviceContext();
1223
- await this.updateHomeKitCharacteristics();
987
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 100);
988
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 100);
989
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
1224
990
  }
1225
991
  }
1226
992
 
1227
993
  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
-
994
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, e);
995
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, e);
996
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, e);
997
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e);
998
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e);
999
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.ChargingState, e);
1258
1000
  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}`);
1001
+ this.LightSensor!.Service.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, e);
1002
+ this.LightSensor!.Service.updateCharacteristic(this.hap.Characteristic.StatusActive, e);
1356
1003
  }
1357
1004
  }
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
1005
  }