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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/.vscode/settings.json +4 -1
  2. package/CHANGELOG.md +4 -1
  3. package/config.schema.json +164 -22
  4. package/dist/device/blindtilt.d.ts +21 -96
  5. package/dist/device/blindtilt.d.ts.map +1 -1
  6. package/dist/device/blindtilt.js +457 -866
  7. package/dist/device/blindtilt.js.map +1 -1
  8. package/dist/device/bot.d.ts +27 -72
  9. package/dist/device/bot.d.ts.map +1 -1
  10. package/dist/device/bot.js +851 -913
  11. package/dist/device/bot.js.map +1 -1
  12. package/dist/device/ceilinglight.d.ts +15 -69
  13. package/dist/device/ceilinglight.d.ts.map +1 -1
  14. package/dist/device/ceilinglight.js +316 -742
  15. package/dist/device/ceilinglight.js.map +1 -1
  16. package/dist/device/colorbulb.d.ts +15 -76
  17. package/dist/device/colorbulb.d.ts.map +1 -1
  18. package/dist/device/colorbulb.js +380 -833
  19. package/dist/device/colorbulb.js.map +1 -1
  20. package/dist/device/contact.d.ts +14 -66
  21. package/dist/device/contact.d.ts.map +1 -1
  22. package/dist/device/contact.js +267 -602
  23. package/dist/device/contact.js.map +1 -1
  24. package/dist/device/curtain.d.ts +18 -89
  25. package/dist/device/curtain.d.ts.map +1 -1
  26. package/dist/device/curtain.js +469 -897
  27. package/dist/device/curtain.js.map +1 -1
  28. package/dist/device/device.d.ts +76 -0
  29. package/dist/device/device.d.ts.map +1 -0
  30. package/dist/device/device.js +846 -0
  31. package/dist/device/device.js.map +1 -0
  32. package/dist/device/fan.d.ts +63 -0
  33. package/dist/device/fan.d.ts.map +1 -0
  34. package/dist/device/fan.js +645 -0
  35. package/dist/device/fan.js.map +1 -0
  36. package/dist/device/hub.d.ts +19 -58
  37. package/dist/device/hub.d.ts.map +1 -1
  38. package/dist/device/hub.js +304 -640
  39. package/dist/device/hub.js.map +1 -1
  40. package/dist/device/humidifier.d.ts +11 -66
  41. package/dist/device/humidifier.d.ts.map +1 -1
  42. package/dist/device/humidifier.js +300 -710
  43. package/dist/device/humidifier.js.map +1 -1
  44. package/dist/device/iosensor.d.ts +12 -64
  45. package/dist/device/iosensor.d.ts.map +1 -1
  46. package/dist/device/iosensor.js +225 -643
  47. package/dist/device/iosensor.js.map +1 -1
  48. package/dist/device/lightstrip.d.ts +12 -70
  49. package/dist/device/lightstrip.d.ts.map +1 -1
  50. package/dist/device/lightstrip.js +371 -742
  51. package/dist/device/lightstrip.js.map +1 -1
  52. package/dist/device/lock.d.ts +17 -63
  53. package/dist/device/lock.d.ts.map +1 -1
  54. package/dist/device/lock.js +309 -642
  55. package/dist/device/lock.js.map +1 -1
  56. package/dist/device/meter.d.ts +15 -64
  57. package/dist/device/meter.d.ts.map +1 -1
  58. package/dist/device/meter.js +223 -638
  59. package/dist/device/meter.js.map +1 -1
  60. package/dist/device/meterplus.d.ts +15 -65
  61. package/dist/device/meterplus.d.ts.map +1 -1
  62. package/dist/device/meterplus.js +216 -644
  63. package/dist/device/meterplus.js.map +1 -1
  64. package/dist/device/motion.d.ts +12 -69
  65. package/dist/device/motion.d.ts.map +1 -1
  66. package/dist/device/motion.js +209 -588
  67. package/dist/device/motion.js.map +1 -1
  68. package/dist/device/plug.d.ts +10 -57
  69. package/dist/device/plug.d.ts.map +1 -1
  70. package/dist/device/plug.js +141 -532
  71. package/dist/device/plug.js.map +1 -1
  72. package/dist/device/robotvacuumcleaner.d.ts +13 -63
  73. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  74. package/dist/device/robotvacuumcleaner.js +252 -609
  75. package/dist/device/robotvacuumcleaner.js.map +1 -1
  76. package/dist/device/waterdetector.d.ts +11 -63
  77. package/dist/device/waterdetector.d.ts.map +1 -1
  78. package/dist/device/waterdetector.js +179 -521
  79. package/dist/device/waterdetector.js.map +1 -1
  80. package/dist/homebridge-ui/public/index.html +22 -16
  81. package/dist/homebridge-ui/server.js +1 -1
  82. package/dist/homebridge-ui/server.js.map +1 -1
  83. package/dist/index.d.ts +1 -1
  84. package/dist/index.d.ts.map +1 -1
  85. package/dist/index.js +2 -2
  86. package/dist/index.js.map +1 -1
  87. package/dist/irdevice/airconditioner.d.ts +10 -50
  88. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  89. package/dist/irdevice/airconditioner.js +337 -482
  90. package/dist/irdevice/airconditioner.js.map +1 -1
  91. package/dist/irdevice/airpurifier.d.ts +8 -39
  92. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  93. package/dist/irdevice/airpurifier.js +108 -333
  94. package/dist/irdevice/airpurifier.js.map +1 -1
  95. package/dist/irdevice/camera.d.ts +7 -36
  96. package/dist/irdevice/camera.d.ts.map +1 -1
  97. package/dist/irdevice/camera.js +47 -299
  98. package/dist/irdevice/camera.js.map +1 -1
  99. package/dist/irdevice/fan.d.ts +7 -43
  100. package/dist/irdevice/fan.d.ts.map +1 -1
  101. package/dist/irdevice/fan.js +95 -364
  102. package/dist/irdevice/fan.js.map +1 -1
  103. package/dist/irdevice/irdevice.d.ts +46 -0
  104. package/dist/irdevice/irdevice.d.ts.map +1 -0
  105. package/dist/irdevice/irdevice.js +393 -0
  106. package/dist/irdevice/irdevice.js.map +1 -0
  107. package/dist/irdevice/light.d.ts +12 -45
  108. package/dist/irdevice/light.d.ts.map +1 -1
  109. package/dist/irdevice/light.js +121 -376
  110. package/dist/irdevice/light.js.map +1 -1
  111. package/dist/irdevice/other.d.ts +19 -48
  112. package/dist/irdevice/other.d.ts.map +1 -1
  113. package/dist/irdevice/other.js +441 -584
  114. package/dist/irdevice/other.js.map +1 -1
  115. package/dist/irdevice/tv.d.ts +8 -40
  116. package/dist/irdevice/tv.d.ts.map +1 -1
  117. package/dist/irdevice/tv.js +94 -353
  118. package/dist/irdevice/tv.js.map +1 -1
  119. package/dist/irdevice/vacuumcleaner.d.ts +7 -36
  120. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  121. package/dist/irdevice/vacuumcleaner.js +48 -299
  122. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  123. package/dist/irdevice/waterheater.d.ts +7 -36
  124. package/dist/irdevice/waterheater.d.ts.map +1 -1
  125. package/dist/irdevice/waterheater.js +50 -305
  126. package/dist/irdevice/waterheater.js.map +1 -1
  127. package/dist/platform.d.ts +22 -8
  128. package/dist/platform.d.ts.map +1 -1
  129. package/dist/platform.js +342 -191
  130. package/dist/platform.js.map +1 -1
  131. package/dist/settings.d.ts +66 -18
  132. package/dist/settings.d.ts.map +1 -1
  133. package/dist/settings.js +16 -552
  134. package/dist/settings.js.map +1 -1
  135. package/dist/utils.d.ts +95 -0
  136. package/dist/utils.d.ts.map +1 -1
  137. package/dist/utils.js +657 -1
  138. package/dist/utils.js.map +1 -1
  139. package/eslint.config.js +96 -0
  140. package/package.json +20 -16
  141. package/src/custom.d.ts +2 -1
  142. package/src/device/blindtilt.ts +488 -937
  143. package/src/device/bot.ts +907 -1016
  144. package/src/device/ceilinglight.ts +330 -798
  145. package/src/device/colorbulb.ts +394 -904
  146. package/src/device/contact.ts +298 -637
  147. package/src/device/curtain.ts +496 -954
  148. package/src/device/device.ts +872 -0
  149. package/src/device/fan.ts +692 -0
  150. package/src/device/hub.ts +338 -671
  151. package/src/device/humidifier.ts +330 -777
  152. package/src/device/iosensor.ts +258 -671
  153. package/src/device/lightstrip.ts +394 -809
  154. package/src/device/lock.ts +345 -700
  155. package/src/device/meter.ts +256 -666
  156. package/src/device/meterplus.ts +248 -672
  157. package/src/device/motion.ts +234 -622
  158. package/src/device/plug.ts +152 -572
  159. package/src/device/robotvacuumcleaner.ts +273 -653
  160. package/src/device/waterdetector.ts +198 -549
  161. package/src/homebridge-ui/public/index.html +22 -16
  162. package/src/homebridge-ui/server.ts +1 -1
  163. package/src/index.ts +4 -3
  164. package/src/irdevice/airconditioner.ts +368 -540
  165. package/src/irdevice/airpurifier.ts +134 -369
  166. package/src/irdevice/camera.ts +60 -324
  167. package/src/irdevice/fan.ts +111 -392
  168. package/src/irdevice/irdevice.ts +406 -0
  169. package/src/irdevice/light.ts +159 -425
  170. package/src/irdevice/other.ts +509 -661
  171. package/src/irdevice/tv.ts +123 -388
  172. package/src/irdevice/vacuumcleaner.ts +61 -324
  173. package/src/irdevice/waterheater.ts +63 -333
  174. package/src/platform.ts +395 -259
  175. package/src/settings.ts +120 -610
  176. package/src/utils.ts +661 -1
  177. package/src/device/waterdetector.json +0 -11
package/src/device/bot.ts CHANGED
@@ -1,114 +1,153 @@
1
- import { request } from 'undici';
2
- import { sleep } from '../utils.js';
1
+ /* Copyright(C) 2021-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
2
+ *
3
+ * bot.ts: @switchbot/homebridge-switchbot.
4
+ */
5
+ import { deviceBase } from './device.js';
3
6
  import { interval, Subject } from 'rxjs';
4
- import { SwitchBotPlatform } from '../platform.js';
5
7
  import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
6
- import { Service, PlatformAccessory, CharacteristicValue, API, Logging, HAP } from 'homebridge';
7
- import { device, devicesConfig, deviceStatus, serviceData, Devices, SwitchBotPlatformConfig } from '../settings.js';
8
+
9
+ import type { SwitchBotPlatform } from '../platform.js';
10
+ import type { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
11
+ import type { device, devicesConfig, serviceData, deviceStatus } from '../settings.js';
8
12
 
9
13
  /**
10
14
  * Platform Accessory
11
15
  * An instance of this class is created for each accessory your platform registers
12
16
  * Each accessory may expose multiple services of different service types.
13
17
  */
14
- export class Bot {
15
- public readonly api: API;
16
- public readonly log: Logging;
17
- public readonly config!: SwitchBotPlatformConfig;
18
- protected readonly hap: HAP;
18
+ export class Bot extends deviceBase {
19
19
  // Services
20
- fanService?: Service;
21
- doorService?: Service;
22
- lockService?: Service;
23
- faucetService?: Service;
24
- windowService?: Service;
25
- switchService?: Service;
26
- outletService?: Service;
27
- batteryService: Service;
28
- garageDoorService?: Service;
29
- windowCoveringService?: Service;
30
- statefulProgrammableSwitchService?: Service;
31
-
32
- // Characteristic Values
33
- On!: CharacteristicValue;
34
- BatteryLevel!: CharacteristicValue;
35
- FirmwareRevision!: CharacteristicValue;
36
- StatusLowBattery!: CharacteristicValue;
37
-
38
- // OpenAPI Status
39
- OpenAPI_On: deviceStatus['power'];
40
- OpenAPI_BatteryLevel: deviceStatus['battery'];
41
- OpenAPI_FirmwareRevision: deviceStatus['version'];
42
-
43
- // BLE Status
44
- BLE_On!: serviceData['state'];
45
- BLE_Mode!: serviceData['mode'];
46
- BLE_BatteryLevel!: serviceData['battery'];
47
-
48
- //BLE Others
49
- BLE_IsConnected?: boolean;
20
+ private Battery: {
21
+ Name: CharacteristicValue;
22
+ Service: Service;
23
+ BatteryLevel: CharacteristicValue;
24
+ StatusLowBattery: CharacteristicValue;
25
+ };
26
+
27
+ private Switch?: {
28
+ Name: CharacteristicValue;
29
+ Service: Service;
30
+ On: CharacteristicValue;
31
+ };
32
+
33
+ private GarageDoor?: {
34
+ Name: CharacteristicValue;
35
+ Service: Service;
36
+ On: CharacteristicValue;
37
+ };
38
+
39
+ private Door?: {
40
+ Name: CharacteristicValue;
41
+ Service: Service;
42
+ On: CharacteristicValue;
43
+ };
44
+
45
+ private Window?: {
46
+ Name: CharacteristicValue;
47
+ Service: Service;
48
+ On: CharacteristicValue;
49
+ };
50
+
51
+ private WindowCovering?: {
52
+ Name: CharacteristicValue;
53
+ Service: Service;
54
+ On: CharacteristicValue;
55
+ };
56
+
57
+ private LockMechanism?: {
58
+ Name: CharacteristicValue;
59
+ Service: Service;
60
+ On: CharacteristicValue;
61
+ };
62
+
63
+ private Faucet?: {
64
+ Name: CharacteristicValue;
65
+ Service: Service;
66
+ On: CharacteristicValue;
67
+ };
68
+
69
+ private Fan?: {
70
+ Name: CharacteristicValue;
71
+ Service: Service;
72
+ On: CharacteristicValue;
73
+ };
74
+
75
+ private StatefulProgrammableSwitch?: {
76
+ Name: CharacteristicValue;
77
+ Service: Service;
78
+ On: CharacteristicValue;
79
+ };
80
+
81
+ private Outlet?: {
82
+ Name: CharacteristicValue;
83
+ Service: Service;
84
+ On: CharacteristicValue;
85
+ };
50
86
 
51
87
  // Config
52
88
  botMode!: string;
53
89
  allowPush?: boolean;
54
90
  doublePress!: number;
55
- scanDuration!: number;
56
91
  botDeviceType!: string;
57
92
  pushRatePress!: number;
58
- deviceLogging!: string;
59
93
  multiPressCount!: number;
60
- deviceRefreshRate!: number;
61
94
 
62
95
  // Updates
63
96
  botUpdateInProgress!: boolean;
64
97
  doBotUpdate!: Subject<void>;
65
98
 
66
- // Connection
67
- private readonly OpenAPI: boolean;
68
- private readonly BLE: boolean;
69
-
70
99
  constructor(
71
- private readonly platform: SwitchBotPlatform,
72
- private accessory: PlatformAccessory,
73
- public device: device & devicesConfig,
100
+ readonly platform: SwitchBotPlatform,
101
+ accessory: PlatformAccessory,
102
+ device: device & devicesConfig,
74
103
  ) {
75
- this.api = this.platform.api;
76
- this.log = this.platform.log;
77
- this.config = this.platform.config;
78
- this.hap = this.api.hap;
79
- // Connection
80
- this.BLE = this.device.connectionType === 'BLE' || this.device.connectionType === 'BLE/OpenAPI';
81
- this.OpenAPI = this.device.connectionType === 'OpenAPI' || this.device.connectionType === 'BLE/OpenAPI';
104
+ super(platform, accessory, device);
82
105
  // default placeholders
83
- this.deviceLogs(device);
84
- this.deviceType(device);
85
- this.scan(device);
86
- this.refreshRate(device);
87
- this.PressOrSwitch(device);
88
- this.allowPushChanges(device);
89
- this.deviceContext();
90
- this.DoublePress(device);
91
- this.deviceConfig(device);
92
-
93
- this.multiPressCount = 0;
106
+ this.getBotConfigSettings(device);
94
107
 
95
108
  // this is subject we use to track when we need to POST changes to the SwitchBot API
96
109
  this.doBotUpdate = new Subject();
97
110
  this.botUpdateInProgress = false;
98
111
 
99
- // Retrieve initial values and updateHomekit
100
- this.refreshStatus();
101
-
102
- // set accessory information
103
- accessory
104
- .getService(this.hap.Service.AccessoryInformation)!
105
- .setCharacteristic(this.hap.Characteristic.Manufacturer, 'SwitchBot')
106
- .setCharacteristic(this.hap.Characteristic.Model, 'SWITCHBOT-BOT-S1')
107
- .setCharacteristic(this.hap.Characteristic.SerialNumber, device.deviceId)
108
- .setCharacteristic(this.hap.Characteristic.FirmwareRevision, accessory.context.FirmwareRevision);
112
+ accessory.context.Battery = accessory.context.Battery ?? {};
113
+ // Initialize Battery property
114
+ this.Battery = {
115
+ Name: accessory.context.Battery.Name ?? `${accessory.displayName} Battery`,
116
+ Service: accessory.getService(this.hap.Service.Battery) ?? accessory.addService(this.hap.Service.Battery) as Service,
117
+ BatteryLevel: accessory.context.BatteryLevel ?? 100,
118
+ StatusLowBattery: accessory.context.StatusLowBattery ?? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,
119
+ };
120
+ accessory.context.Battery = this.Battery as object;
121
+
122
+ // Initialize Battery Characteristics
123
+ this.Battery.Service
124
+ .setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name)
125
+ .setCharacteristic(this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery)
126
+ .setCharacteristic(this.hap.Characteristic.ChargingState, this.hap.Characteristic.ChargingState.NOT_CHARGEABLE);
109
127
 
110
128
  // deviceType
111
129
  if (this.botDeviceType === 'switch') {
130
+ // Initialize Switch Service
131
+ accessory.context.Switch = accessory.context.Switch ?? {};
132
+ this.Switch = {
133
+ Name: accessory.context.Switch.Name ?? accessory.displayName,
134
+ Service: accessory.getService(this.hap.Service.Switch) ?? accessory.addService(this.hap.Service.Switch) as Service,
135
+ On: accessory.context.On ?? false,
136
+ };
137
+ accessory.context.Switch = this.Switch as object;
138
+ this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Switch`);
139
+
140
+ // Initialize Switch Characteristics
141
+ this.Switch.Service
142
+ .setCharacteristic(this.hap.Characteristic.Name, this.Switch.Name)
143
+ .setCharacteristic(this.hap.Characteristic.On, this.Switch.On)
144
+ .getCharacteristic(this.hap.Characteristic.On)
145
+ .onGet(() => {
146
+ return this.Switch!.On;
147
+ })
148
+ .onSet(this.OnSet.bind(this));
149
+
150
+ // Remove other services
112
151
  this.removeFanService(accessory);
113
152
  this.removeLockService(accessory);
114
153
  this.removeDoorService(accessory);
@@ -118,19 +157,33 @@ export class Bot {
118
157
  this.removeGarageDoorService(accessory);
119
158
  this.removeWindowCoveringService(accessory);
120
159
  this.removeStatefulProgrammableSwitchService(accessory);
160
+ } else if (this.botDeviceType === 'garagedoor') {
161
+ // Initialize GarageDoor Service
162
+ accessory.context.GarageDoor = accessory.context.GarageDoor ?? {};
163
+ this.GarageDoor = {
164
+ Name: accessory.context.GarageDoor.Name ?? accessory.displayName,
165
+ Service: accessory.getService(this.hap.Service.GarageDoorOpener) ?? accessory.addService(this.hap.Service.GarageDoorOpener) as Service,
166
+ On: accessory.context.On ?? false,
167
+ };
168
+ accessory.context.GarageDoor = this.GarageDoor as object;
169
+ this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Garage Door Opener`);
121
170
 
122
- // Add switchService
123
- const switchService = `${accessory.displayName} Switch`;
124
- (this.switchService = accessory.getService(this.hap.Service.Switch)
125
- || accessory.addService(this.hap.Service.Switch)), switchService;
126
- this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Switch`);
171
+ // Initialize GarageDoor Characteristics
172
+ this.GarageDoor.Service
173
+ .setCharacteristic(this.hap.Characteristic.Name, this.GarageDoor.Name)
174
+ .setCharacteristic(this.hap.Characteristic.ObstructionDetected, false)
175
+ .getCharacteristic(this.hap.Characteristic.TargetDoorState).setProps({
176
+ validValues: [0, 100],
177
+ minValue: 0,
178
+ maxValue: 100,
179
+ minStep: 100,
180
+ })
181
+ .onGet(() => {
182
+ return this.GarageDoor!.On;
183
+ })
184
+ .onSet(this.OnSet.bind(this));
127
185
 
128
- this.switchService.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
129
- if (!this.switchService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
130
- this.switchService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
131
- }
132
- this.switchService.getCharacteristic(this.hap.Characteristic.On).onSet(this.OnSet.bind(this));
133
- } else if (this.botDeviceType === 'garagedoor') {
186
+ // Remove other services
134
187
  this.removeFanService(accessory);
135
188
  this.removeLockService(accessory);
136
189
  this.removeDoorService(accessory);
@@ -140,20 +193,33 @@ export class Bot {
140
193
  this.removeWindowService(accessory);
141
194
  this.removeWindowCoveringService(accessory);
142
195
  this.removeStatefulProgrammableSwitchService(accessory);
196
+ } else if (this.botDeviceType === 'door') {
197
+ // Initialize Door Service
198
+ accessory.context.Door = accessory.context.Door ?? {};
199
+ this.Door = {
200
+ Name: accessory.context.Door.Name ?? accessory.displayName,
201
+ Service: accessory.getService(this.hap.Service.Door) ?? accessory.addService(this.hap.Service.Door) as Service,
202
+ On: accessory.context.On ?? false,
203
+ };
204
+ accessory.context.Door = this.Door as object;
205
+ this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Door`);
143
206
 
144
- // Add garageDoorService
145
- const garageDoorService = `${accessory.displayName} Garage Door Opener`;
146
- (this.garageDoorService = accessory.getService(this.hap.Service.GarageDoorOpener)
147
- || accessory.addService(this.hap.Service.GarageDoorOpener)), garageDoorService;
148
- this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Garage Door Opener`);
207
+ // Initialize Door Characteristics
208
+ this.Door.Service
209
+ .setCharacteristic(this.hap.Characteristic.Name, this.Door.Name)
210
+ .setCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED)
211
+ .getCharacteristic(this.hap.Characteristic.TargetPosition).setProps({
212
+ validValues: [0, 100],
213
+ minValue: 0,
214
+ maxValue: 100,
215
+ minStep: 100,
216
+ })
217
+ .onGet(() => {
218
+ return this.Door!.On;
219
+ })
220
+ .onSet(this.OnSet.bind(this));
149
221
 
150
- this.garageDoorService.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
151
- if (!this.garageDoorService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
152
- this.garageDoorService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
153
- }
154
- this.garageDoorService.getCharacteristic(this.hap.Characteristic.TargetDoorState).onSet(this.OnSet.bind(this));
155
- this.garageDoorService.setCharacteristic(this.hap.Characteristic.ObstructionDetected, false);
156
- } else if (this.botDeviceType === 'door') {
222
+ // Remove other services
157
223
  this.removeFanService(accessory);
158
224
  this.removeLockService(accessory);
159
225
  this.removeOutletService(accessory);
@@ -163,28 +229,33 @@ export class Bot {
163
229
  this.removeGarageDoorService(accessory);
164
230
  this.removeWindowCoveringService(accessory);
165
231
  this.removeStatefulProgrammableSwitchService(accessory);
232
+ } else if (this.botDeviceType === 'window') {
233
+ // Initialize Window Service
234
+ accessory.context.Window = accessory.context.Window ?? {};
235
+ this.Window = {
236
+ Name: accessory.context.Window.Name ?? accessory.displayName,
237
+ Service: accessory.getService(this.hap.Service.Window) ?? accessory.addService(this.hap.Service.Window) as Service,
238
+ On: accessory.context.On ?? false,
239
+ };
240
+ accessory.context.Window = this.Window as object;
241
+ this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Window`);
166
242
 
167
- // Add doorService
168
- const doorService = `${accessory.displayName} Door`;
169
- (this.doorService = accessory.getService(this.hap.Service.Door)
170
- || accessory.addService(this.hap.Service.Door)), doorService;
171
- this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Door`);
172
-
173
- this.doorService.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
174
- if (!this.doorService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
175
- this.doorService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
176
- }
177
- this.doorService
178
- .getCharacteristic(this.hap.Characteristic.TargetPosition)
179
- .setProps({
243
+ // Initialize Window Characteristics
244
+ this.Window.Service
245
+ .setCharacteristic(this.hap.Characteristic.Name, this.Window.Name)
246
+ .setCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED)
247
+ .getCharacteristic(this.hap.Characteristic.TargetPosition).setProps({
180
248
  validValues: [0, 100],
181
249
  minValue: 0,
182
250
  maxValue: 100,
183
251
  minStep: 100,
184
252
  })
253
+ .onGet(() => {
254
+ return this.Window!.On;
255
+ })
185
256
  .onSet(this.OnSet.bind(this));
186
- this.doorService.setCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
187
- } else if (this.botDeviceType === 'window') {
257
+
258
+ // Remove other services
188
259
  this.removeFanService(accessory);
189
260
  this.removeLockService(accessory);
190
261
  this.removeDoorService(accessory);
@@ -194,28 +265,33 @@ export class Bot {
194
265
  this.removeGarageDoorService(accessory);
195
266
  this.removeWindowCoveringService(accessory);
196
267
  this.removeStatefulProgrammableSwitchService(accessory);
268
+ } else if (this.botDeviceType === 'windowcovering') {
269
+ // Initialize WindowCovering Service
270
+ accessory.context.WindowCovering = accessory.context.WindowCovering ?? {};
271
+ this.WindowCovering = {
272
+ Name: accessory.context.WindowCovering.Name ?? accessory.displayName,
273
+ Service: accessory.getService(this.hap.Service.WindowCovering) ?? accessory.addService(this.hap.Service.WindowCovering) as Service,
274
+ On: accessory.context.On ?? false,
275
+ };
276
+ accessory.context.WindowCovering = this.WindowCovering as object;
277
+ this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Window Covering`);
197
278
 
198
- // Add windowService
199
- const windowService = `${accessory.displayName} Window`;
200
- (this.windowService = accessory.getService(this.hap.Service.Window)
201
- || accessory.addService(this.hap.Service.Window)), windowService;
202
- this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Window`);
203
-
204
- this.windowService.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
205
- if (!this.windowService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
206
- this.windowService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
207
- }
208
- this.windowService
209
- .getCharacteristic(this.hap.Characteristic.TargetPosition)
210
- .setProps({
279
+ // Initialize WindowCovering Characteristics
280
+ this.WindowCovering.Service
281
+ .setCharacteristic(this.hap.Characteristic.Name, this.WindowCovering.Name)
282
+ .setCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED)
283
+ .getCharacteristic(this.hap.Characteristic.TargetPosition).setProps({
211
284
  validValues: [0, 100],
212
285
  minValue: 0,
213
286
  maxValue: 100,
214
287
  minStep: 100,
215
288
  })
289
+ .onGet(() => {
290
+ return this.WindowCovering!.On;
291
+ })
216
292
  .onSet(this.OnSet.bind(this));
217
- this.windowService.setCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
218
- } else if (this.botDeviceType === 'windowcovering') {
293
+
294
+ // Remove other services
219
295
  this.removeFanService(accessory);
220
296
  this.removeLockService(accessory);
221
297
  this.removeDoorService(accessory);
@@ -225,28 +301,27 @@ export class Bot {
225
301
  this.removeWindowService(accessory);
226
302
  this.removeGarageDoorService(accessory);
227
303
  this.removeStatefulProgrammableSwitchService(accessory);
304
+ } else if (this.botDeviceType === 'lock') {
305
+ // Initialize Lock Service
306
+ accessory.context.LockMechanism = accessory.context.LockMechanism ?? {};
307
+ this.LockMechanism = {
308
+ Name: accessory.context.LockMechanism.Name ?? accessory.displayName,
309
+ Service: accessory.getService(this.hap.Service.LockMechanism) ?? accessory.addService(this.hap.Service.LockMechanism) as Service,
310
+ On: accessory.context.On ?? false,
311
+ };
312
+ accessory.context.LockMechanism = this.LockMechanism as object;
313
+ this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Lock`);
228
314
 
229
- // Add windowCoveringService
230
- const windowCoveringService = `${accessory.displayName} Window Covering`;
231
- (this.windowCoveringService = accessory.getService(this.hap.Service.WindowCovering)
232
- || accessory.addService(this.hap.Service.WindowCovering)), windowCoveringService;
233
- this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Window Covering`);
234
-
235
- this.windowCoveringService.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
236
- if (!this.windowCoveringService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
237
- this.windowCoveringService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
238
- }
239
- this.windowCoveringService
240
- .getCharacteristic(this.hap.Characteristic.TargetPosition)
241
- .setProps({
242
- validValues: [0, 100],
243
- minValue: 0,
244
- maxValue: 100,
245
- minStep: 100,
315
+ // Initialize Lock Characteristics
316
+ this.LockMechanism.Service
317
+ .setCharacteristic(this.hap.Characteristic.Name, this.LockMechanism.Name)
318
+ .getCharacteristic(this.hap.Characteristic.LockTargetState)
319
+ .onGet(() => {
320
+ return this.LockMechanism!.On;
246
321
  })
247
322
  .onSet(this.OnSet.bind(this));
248
- this.windowCoveringService.setCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
249
- } else if (this.botDeviceType === 'lock') {
323
+
324
+ // Remove other services
250
325
  this.removeFanService(accessory);
251
326
  this.removeDoorService(accessory);
252
327
  this.removeOutletService(accessory);
@@ -256,19 +331,27 @@ export class Bot {
256
331
  this.removeGarageDoorService(accessory);
257
332
  this.removeWindowCoveringService(accessory);
258
333
  this.removeStatefulProgrammableSwitchService(accessory);
334
+ } else if (this.botDeviceType === 'faucet') {
335
+ // Initialize Faucet Service
336
+ accessory.context.Faucet = accessory.context.Faucet ?? {};
337
+ this.Faucet = {
338
+ Name: accessory.context.Faucet.Name ?? accessory.displayName,
339
+ Service: accessory.getService(this.hap.Service.Faucet) ?? accessory.addService(this.hap.Service.Faucet) as Service,
340
+ On: accessory.context.On ?? false,
341
+ };
342
+ accessory.context.Faucet = this.Faucet as object;
343
+ this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Faucet`);
259
344
 
260
- // Add lockService
261
- const lockService = `${accessory.displayName} Lock`;
262
- (this.lockService = accessory.getService(this.hap.Service.LockMechanism)
263
- || accessory.addService(this.hap.Service.LockMechanism)), lockService;
264
- this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Lock`);
345
+ // Initialize Faucet Characteristics
346
+ this.Faucet.Service
347
+ .setCharacteristic(this.hap.Characteristic.Name, this.Faucet.Name)
348
+ .getCharacteristic(this.hap.Characteristic.Active)
349
+ .onGet(() => {
350
+ return this.Faucet!.On;
351
+ })
352
+ .onSet(this.OnSet.bind(this));
265
353
 
266
- this.lockService.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
267
- if (!this.lockService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
268
- this.lockService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
269
- }
270
- this.lockService.getCharacteristic(this.hap.Characteristic.LockTargetState).onSet(this.OnSet.bind(this));
271
- } else if (this.botDeviceType === 'faucet') {
354
+ // Remove other services
272
355
  this.removeFanService(accessory);
273
356
  this.removeLockService(accessory);
274
357
  this.removeDoorService(accessory);
@@ -278,19 +361,27 @@ export class Bot {
278
361
  this.removeGarageDoorService(accessory);
279
362
  this.removeWindowCoveringService(accessory);
280
363
  this.removeStatefulProgrammableSwitchService(accessory);
364
+ } else if (this.botDeviceType === 'fan') {
365
+ // Initialize Fan Service
366
+ accessory.context.Fan = accessory.context.Fan ?? {};
367
+ this.Fan = {
368
+ Name: accessory.context.Fan.Name ?? accessory.displayName,
369
+ Service: accessory.getService(this.hap.Service.Fanv2) ?? accessory.addService(this.hap.Service.Fanv2) as Service,
370
+ On: accessory.context.On ?? false,
371
+ };
372
+ accessory.context.Fan = this.Fan as object;
373
+ this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Fan`);
281
374
 
282
- // Add faucetService
283
- const faucetService = `${accessory.displayName} Faucet`;
284
- (this.faucetService = accessory.getService(this.hap.Service.Faucet)
285
- || accessory.addService(this.hap.Service.Faucet)), faucetService;
286
- this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Faucet`);
375
+ // Initialize Fan Characteristics
376
+ this.Fan.Service
377
+ .setCharacteristic(this.hap.Characteristic.Name, this.Fan.Name)
378
+ .getCharacteristic(this.hap.Characteristic.On)
379
+ .onGet(() => {
380
+ return this.Fan!.On;
381
+ })
382
+ .onSet(this.OnSet.bind(this));
287
383
 
288
- this.faucetService.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
289
- if (!this.faucetService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
290
- this.faucetService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
291
- }
292
- this.faucetService.getCharacteristic(this.hap.Characteristic.Active).onSet(this.OnSet.bind(this));
293
- } else if (this.botDeviceType === 'fan') {
384
+ // Remove other services
294
385
  this.removeLockService(accessory);
295
386
  this.removeDoorService(accessory);
296
387
  this.removeFaucetService(accessory);
@@ -300,19 +391,28 @@ export class Bot {
300
391
  this.removeGarageDoorService(accessory);
301
392
  this.removeWindowCoveringService(accessory);
302
393
  this.removeStatefulProgrammableSwitchService(accessory);
394
+ } else if (this.botDeviceType === 'stateful') {
395
+ // Initialize StatefulProgrammableSwitch Service
396
+ accessory.context.StatefulProgrammableSwitch = accessory.context.StatefulProgrammableSwitch ?? {};
397
+ this.StatefulProgrammableSwitch = {
398
+ Name: accessory.context.StatefulProgrammableSwitch.Name ?? accessory.displayName,
399
+ Service: accessory.getService(this.hap.Service.StatefulProgrammableSwitch)
400
+ ?? accessory.addService(this.hap.Service.StatefulProgrammableSwitch) as Service,
401
+ On: accessory.context.On ?? false,
402
+ };
403
+ accessory.context.StatefulProgrammableSwitch = this.StatefulProgrammableSwitch as object;
404
+ this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Stateful Programmable Switch`);
303
405
 
304
- // Add fanService
305
- const fanService = `${accessory.displayName} Fan`;
306
- (this.fanService = accessory.getService(this.hap.Service.Fan)
307
- || accessory.addService(this.hap.Service.Fan)), fanService;
308
- this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Fan`);
406
+ // Initialize StatefulProgrammableSwitch Characteristics
407
+ this.StatefulProgrammableSwitch.Service
408
+ .setCharacteristic(this.hap.Characteristic.Name, this.StatefulProgrammableSwitch.Name)
409
+ .getCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState)
410
+ .onGet(() => {
411
+ return this.StatefulProgrammableSwitch!.On;
412
+ })
413
+ .onSet(this.OnSet.bind(this));
309
414
 
310
- this.fanService.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
311
- if (!this.fanService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
312
- this.fanService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
313
- }
314
- this.fanService.getCharacteristic(this.hap.Characteristic.On).onSet(this.OnSet.bind(this));
315
- } else if (this.botDeviceType === 'stateful') {
415
+ // Remove other services
316
416
  this.removeFanService(accessory);
317
417
  this.removeLockService(accessory);
318
418
  this.removeDoorService(accessory);
@@ -322,21 +422,27 @@ export class Bot {
322
422
  this.removeWindowService(accessory);
323
423
  this.removeGarageDoorService(accessory);
324
424
  this.removeWindowCoveringService(accessory);
425
+ } else {
426
+ // Initialize Switch property
427
+ accessory.context.Outlet = accessory.context.Outlet ?? {};
428
+ this.Outlet = {
429
+ Name: accessory.context.Outlet.Name ?? accessory.displayName,
430
+ Service: accessory.getService(this.hap.Service.Outlet) ?? accessory.addService(this.hap.Service.Outlet) as Service,
431
+ On: accessory.context.On ?? false,
432
+ };
433
+ accessory.context.Outlet = this.Outlet as object;
434
+ this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Outlet`);
325
435
 
326
- // Add statefulProgrammableSwitchService
327
- const statefulProgrammableSwitchService = `${accessory.displayName} Stateful Programmable Switch`;
328
- (this.statefulProgrammableSwitchService = accessory.getService(this.hap.Service.StatefulProgrammableSwitch) ||
329
- accessory.addService(this.hap.Service.StatefulProgrammableSwitch)), statefulProgrammableSwitchService;
330
- this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Stateful Programmable Switch`);
331
-
332
- this.statefulProgrammableSwitchService.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
333
- if (!this.statefulProgrammableSwitchService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
334
- this.statefulProgrammableSwitchService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
335
- }
336
- this.statefulProgrammableSwitchService
337
- .getCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState)
436
+ // Initialize Outlet Characteristics
437
+ this.Outlet.Service
438
+ .setCharacteristic(this.hap.Characteristic.Name, this.Outlet.Name)
439
+ .getCharacteristic(this.hap.Characteristic.On)
440
+ .onGet(() => {
441
+ return this.Outlet!.On;
442
+ })
338
443
  .onSet(this.OnSet.bind(this));
339
- } else {
444
+
445
+ // Remove other services
340
446
  this.removeFanService(accessory);
341
447
  this.removeLockService(accessory);
342
448
  this.removeDoorService(accessory);
@@ -346,30 +452,10 @@ export class Bot {
346
452
  this.removeGarageDoorService(accessory);
347
453
  this.removeWindowCoveringService(accessory);
348
454
  this.removeStatefulProgrammableSwitchService(accessory);
349
-
350
- // Add outletService
351
- const outletService = `${accessory.displayName} Outlet`;
352
- (this.outletService = accessory.getService(this.hap.Service.Outlet)
353
- || accessory.addService(this.hap.Service.Outlet)), outletService;
354
- this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Outlet`);
355
-
356
- this.outletService.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
357
- if (!this.outletService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
358
- this.outletService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
359
- }
360
- this.outletService.getCharacteristic(this.hap.Characteristic.On).onSet(this.OnSet.bind(this));
361
455
  }
362
456
 
363
- // batteryService
364
- const batteryService = `${accessory.displayName} Battery`;
365
- (this.batteryService = this.accessory.getService(this.hap.Service.Battery)
366
- || accessory.addService(this.hap.Service.Battery)), batteryService;
367
-
368
- this.batteryService.setCharacteristic(this.hap.Characteristic.Name, `${accessory.displayName} Battery`);
369
- if (!this.batteryService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
370
- this.batteryService.addCharacteristic(this.hap.Characteristic.ConfiguredName, `${accessory.displayName} Battery`);
371
- }
372
- this.batteryService.setCharacteristic(this.hap.Characteristic.ChargingState, this.hap.Characteristic.ChargingState.NOT_CHARGEABLE);
457
+ // Retrieve initial values and updateHomekit
458
+ this.refreshStatus();
373
459
 
374
460
  // Retrieve initial values and updateHomekit
375
461
  this.updateHomeKitCharacteristics();
@@ -381,28 +467,8 @@ export class Bot {
381
467
  await this.refreshStatus();
382
468
  });
383
469
 
384
- //regisiter webhook event handler
385
- if (this.device.webhook) {
386
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} is listening webhook.`);
387
- this.platform.webhookEventHandler[this.device.deviceId] = async (context) => {
388
- try {
389
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
390
- const { power, battery, deviceMode } = context;
391
- const { On, BatteryLevel, botMode } = this;
392
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ` +
393
- '(power, battery, deviceMode) = ' +
394
- `Webhook:(${power}, ${battery}, ${deviceMode}), ` +
395
- `current:(${On}, ${BatteryLevel}, ${botMode})`);
396
- this.On = power;
397
- this.BatteryLevel = battery;
398
- this.botMode = deviceMode;
399
- this.updateHomeKitCharacteristics();
400
- } catch (e: any) {
401
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
402
- + `failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
403
- }
404
- };
405
- }
470
+ // regisiter webhook event handler
471
+ this.registerWebhook(accessory, device);
406
472
 
407
473
  // Watch for Bot change events
408
474
  // We put in a debounce of 1000ms so we don't make duplicate calls
@@ -411,7 +477,7 @@ export class Bot {
411
477
  tap(() => {
412
478
  this.botUpdateInProgress = true;
413
479
  }),
414
- debounceTime(this.platform.config.options!.pushRate! * 1000),
480
+ debounceTime(this.devicePushRate * 1000),
415
481
  )
416
482
  .subscribe(async () => {
417
483
  try {
@@ -426,90 +492,90 @@ export class Bot {
426
492
  }
427
493
  } catch (e: any) {
428
494
  this.apiError(e);
429
- this.errorLog(
430
- `${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with ${this.device.connectionType} Connection,` +
431
- ` Error Message: ${JSON.stringify(e.message)}`,
432
- );
495
+ this.errorLog(`${device.deviceType}: ${accessory.displayName} failed pushChanges with ${device.connectionType} Connection,`
496
+ + ` Error Message: ${JSON.stringify(e.message)}`);
433
497
  }
434
498
  this.botUpdateInProgress = false;
435
499
  });
436
500
  }
437
501
 
438
502
  /**
439
- * Parse the device status from the SwitchBot api
503
+ * Parse the device status from the SwitchBotBLE API
440
504
  */
441
- async parseStatus(): Promise<void> {
442
- if (!this.device.enableCloudService && this.OpenAPI) {
443
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} parseStatus enableCloudService: ${this.device.enableCloudService}`);
444
- } else if (this.BLE) {
445
- await this.BLEparseStatus();
446
- } else if (this.OpenAPI && this.platform.config.credentials?.token) {
447
- await this.openAPIparseStatus();
448
- } else {
449
- await this.offlineOff();
450
- this.debugWarnLog(
451
- `${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` + ` ${this.device.connectionType}, parseStatus will not happen.`,
452
- );
453
- }
454
- }
455
-
456
- async BLEparseStatus(): Promise<void> {
505
+ async BLEparseStatus(serviceData: serviceData): Promise<void> {
457
506
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
458
507
  // BLEmode (true if Switch Mode) | (false if Press Mode)
459
- if (this.BLE_Mode) {
460
- this.accessory.context.On = this.On;
461
- if (this.On === undefined) {
462
- this.On = Boolean(this.BLE_On);
508
+ if (serviceData.mode) {
509
+ this.accessory.context.On = await this.getOn();
510
+ if (this.getOn() === undefined) {
511
+ this.setOn(Boolean(serviceData.state));
463
512
  }
464
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Switch Mode, mode: ${this.BLE_Mode}, On: ${this.On}`);
513
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Switch Mode,`
514
+ + ` mode: ${serviceData.mode}, On: ${this.accessory.context.On}`);
465
515
  } else {
466
- this.On = false;
467
- this.accessory.context.On = this.On;
468
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Press Mode, mode: ${this.BLE_Mode}, On: ${this.On}`);
516
+ this.setOn(false);
517
+ this.accessory.context.On = await this.getOn();
518
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Press Mode,`
519
+ + ` mode: ${serviceData.mode}, On: ${this.accessory.context.On}`);
469
520
  }
470
521
 
471
- this.BatteryLevel = Number(this.BLE_BatteryLevel);
472
- if (this.BatteryLevel < 10) {
473
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
522
+ this.Battery.BatteryLevel = Number(serviceData.battery);
523
+ if (this.Battery.BatteryLevel < 10) {
524
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
474
525
  } else {
475
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
526
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
476
527
  }
477
- if (Number.isNaN(this.BatteryLevel)) {
478
- this.BatteryLevel = 100;
528
+ if (Number.isNaN(this.Battery.BatteryLevel)) {
529
+ this.Battery.BatteryLevel = 100;
479
530
  }
480
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel},`
481
- + ` StatusLowBattery: ${this.StatusLowBattery}`);
531
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
532
+ + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
482
533
  }
483
534
 
484
- async openAPIparseStatus(): Promise<void> {
535
+
536
+ /**
537
+ * Parse the device status from the SwitchBot OpenAPI
538
+ */
539
+ async openAPIparseStatus(deviceStatus: deviceStatus): Promise<void> {
485
540
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
486
541
  if (this.botMode === 'press') {
487
- this.On = false;
488
- this.accessory.context.On = this.On;
542
+ this.setOn(false);
543
+ this.accessory.context.On = await this.getOn();
489
544
  } else {
490
- this.accessory.context.On = this.On;
491
- if (this.On === undefined) {
492
- this.On = false;
545
+ this.accessory.context.On = await this.getOn();
546
+ if (this.getOn() === undefined) {
547
+ this.setOn(false);
493
548
  }
494
549
  }
495
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
550
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.accessory.context.On}`);
496
551
 
497
552
  // Battery
498
- this.BatteryLevel = Number(this.OpenAPI_BatteryLevel);
499
- if (this.BatteryLevel < 10) {
500
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
553
+ this.Battery.BatteryLevel = Number(deviceStatus.body.battery);
554
+ if (this.Battery.BatteryLevel < 10) {
555
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
501
556
  } else {
502
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
557
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
558
+ }
559
+ if (Number.isNaN(this.Battery.BatteryLevel)) {
560
+ this.Battery.BatteryLevel = 100;
561
+ }
562
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
563
+ + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
564
+
565
+ // Firmware Version
566
+ const version = deviceStatus.body.version?.toString();
567
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Firmware Version: ${version?.replace(/^V|-.*$/g, '')}`);
568
+ if (deviceStatus.body.version) {
569
+ const deviceVersion = version?.replace(/^V|-.*$/g, '') ?? '0.0.0';
570
+ this.accessory
571
+ .getService(this.hap.Service.AccessoryInformation)!
572
+ .setCharacteristic(this.hap.Characteristic.HardwareRevision, deviceVersion)
573
+ .setCharacteristic(this.hap.Characteristic.FirmwareRevision, deviceVersion)
574
+ .getCharacteristic(this.hap.Characteristic.FirmwareRevision)
575
+ .updateValue(deviceVersion);
576
+ this.accessory.context.deviceVersion = deviceVersion;
577
+ this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceVersion: ${this.accessory.context.deviceVersion}`);
503
578
  }
504
- if (Number.isNaN(this.BatteryLevel)) {
505
- this.BatteryLevel = 100;
506
- }
507
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel},`
508
- + ` StatusLowBattery: ${this.StatusLowBattery}`);
509
-
510
- // FirmwareRevision
511
- this.FirmwareRevision = this.OpenAPI_FirmwareRevision!;
512
- this.accessory.context.FirmwareRevision = this.FirmwareRevision;
513
579
  }
514
580
 
515
581
  /**
@@ -524,130 +590,76 @@ export class Bot {
524
590
  await this.openAPIRefreshStatus();
525
591
  } else {
526
592
  await this.offlineOff();
527
- this.debugWarnLog(
528
- `${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` +
529
- ` ${this.device.connectionType}, refreshStatus will not happen.`,
530
- );
593
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
594
+ + ` ${this.device.connectionType}, refreshStatus will not happen.`);
531
595
  }
532
596
  }
533
597
 
534
598
  async BLERefreshStatus(): Promise<void> {
535
599
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
536
- const switchbot = await this.platform.connectBLE();
537
- // Convert to BLE Address
538
- this.device.bleMac = this.device
539
- .deviceId!.match(/.{1,2}/g)!
540
- .join(':')
541
- .toLowerCase();
542
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
543
- this.getCustomBLEAddress(switchbot);
600
+ const switchbot = await this.switchbotBLE();
601
+
602
+ if (switchbot === undefined) {
603
+ await this.BLERefreshConnection(switchbot);
604
+ } else {
544
605
  // Start to monitor advertisement packets
545
- (async () => {
606
+ (async () => {
546
607
  // Start to monitor advertisement packets
547
- await switchbot.startScan({
548
- model: 'H',
549
- id: this.device.bleMac,
550
- });
551
- // Set an event handler
552
- switchbot.onadvertisement = (ad: any) => {
553
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
554
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.model}`);
555
- if (this.device.bleMac === ad.address && ad.model === 'H') {
556
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
557
- this.BLE_Mode = ad.serviceData.mode;
558
- this.BLE_On = ad.serviceData.state;
559
- this.BLE_BatteryLevel = ad.serviceData.battery;
608
+ const serviceData: serviceData = await this.monitorAdvertisementPackets(switchbot);
609
+ // Update HomeKit
610
+ if (serviceData.model !== '' && serviceData.modelName !== '') {
611
+ await this.BLEparseStatus(serviceData);
612
+ await this.updateHomeKitCharacteristics();
560
613
  } else {
561
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
562
- }
563
- };
564
- // Wait 1 seconds
565
- await switchbot.wait(this.scanDuration * 1000);
566
- // Stop to monitor
567
- await switchbot.stopScan();
568
- // Update HomeKit
569
- await this.BLEparseStatus();
570
- await this.updateHomeKitCharacteristics();
571
- })();
572
- /*if (switchbot !== false) {
573
- switchbot
574
- .startScan({
575
- model: 'H',
576
- id: this.device.bleMac,
577
- })
578
- .then(async () => {
579
- // Set an event handler
580
- switchbot.onadvertisement = async (ad: ad) => {
581
- this.debugLog(
582
- `${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac},` +
583
- ` BLE Address Found: ${ad.address}`,
584
- );
585
- this.BLE_Mode = ad.serviceData.mode;
586
- this.BLE_On = ad.serviceData.state;
587
- this.BLE_BatteryLevel = ad.serviceData.battery;
588
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
589
- this.debugLog(
590
- `${this.device.deviceType}: ${this.accessory.displayName}, model: ${ad.serviceData.model}, modelName: ` +
591
- `${ad.serviceData.modelName}, mode: ${ad.serviceData.mode}, state: ${ad.serviceData.state}, battery: ${ad.serviceData.battery}`,
592
- );
593
-
594
- if (ad.serviceData) {
595
- this.BLE_IsConnected = true;
596
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.BLE_IsConnected}`);
597
- await this.stopScanning(switchbot);
598
- } else {
599
- this.BLE_IsConnected = false;
600
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.BLE_IsConnected}`);
601
- }
602
- };
603
- // Wait
604
- return await sleep(this.scanDuration * 1000);
605
- })
606
- .then(async () => {
607
- // Stop to monitor
608
- await this.stopScanning(switchbot);
609
- })
610
- .catch(async (e: any) => {
611
- this.apiError(e);
612
- this.errorLog(
613
- `${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}` +
614
- ` Connection, Error Message: ${JSON.stringify(e.message)}`,
615
- );
614
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed to get serviceData, serviceData: ${serviceData}`);
616
615
  await this.BLERefreshConnection(switchbot);
617
- });
618
- } else {
619
- await this.BLERefreshConnection(switchbot);
620
- }*/
616
+ }
617
+ })();
618
+ }
621
619
  }
622
620
 
623
621
  async openAPIRefreshStatus(): Promise<void> {
624
622
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
625
623
  try {
626
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/status`, {
627
- headers: this.platform.generateHeaders(),
628
- });
629
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
624
+ const { body, statusCode } = await this.deviceRefreshStatus();
630
625
  const deviceStatus: any = await body.json();
631
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
632
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
626
+ await this.refreshStatusCodes(statusCode, deviceStatus);;
633
627
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
634
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
635
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
636
- this.OpenAPI_On = deviceStatus.body.power;
637
- this.OpenAPI_BatteryLevel = deviceStatus.body.battery;
638
- this.OpenAPI_FirmwareRevision = deviceStatus.body.version;
639
- this.openAPIparseStatus();
640
- this.updateHomeKitCharacteristics();
628
+ await this.successfulRefreshStatus(statusCode, deviceStatus);
629
+ await this.openAPIparseStatus(deviceStatus);
630
+ await this.updateHomeKitCharacteristics();
641
631
  } else {
642
- this.statusCode(statusCode);
643
- this.statusCode(deviceStatus.statusCode);
632
+ await this.statusCodes(statusCode, deviceStatus);
644
633
  }
645
634
  } catch (e: any) {
646
635
  this.apiError(e);
647
- this.errorLog(
648
- `${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}` +
649
- ` Connection, Error Message: ${JSON.stringify(e.message)}`,
650
- );
636
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
637
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
638
+ }
639
+ }
640
+
641
+ async registerWebhook(accessory: PlatformAccessory, device: device & devicesConfig) {
642
+ if (device.webhook) {
643
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} is listening webhook.`);
644
+ this.platform.webhookEventHandler[device.deviceId] = async (context) => {
645
+ try {
646
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
647
+ const { power, battery, deviceMode } = context;
648
+ const { botMode } = this;
649
+ const On = await this.getOn();
650
+ const { BatteryLevel } = this.Battery;
651
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} (power, battery, deviceMode) = Webhook:(${power}, ${battery}, ${deviceMode}),`
652
+ + ` current:(${On}, ${BatteryLevel}, ${botMode})`);
653
+ await this.setOn(power);
654
+ this.Battery.BatteryLevel = battery;
655
+ this.botMode = deviceMode;
656
+ this.updateHomeKitCharacteristics();
657
+ } catch (e: any) {
658
+ this.errorLog(`${device.deviceType}: ${accessory.displayName} failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
659
+ }
660
+ };
661
+ } else {
662
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} is not listening webhook.`);
651
663
  }
652
664
  }
653
665
 
@@ -663,13 +675,12 @@ export class Bot {
663
675
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} pushChanges enableCloudService: ${this.device.enableCloudService}`);
664
676
  } else if (this.BLE) {
665
677
  await this.BLEpushChanges();
666
- } else if (this.OpenAPI) {
678
+ } else if (this.OpenAPI && this.platform.config.credentials?.token) {
667
679
  await this.openAPIpushChanges();
668
680
  } else {
669
681
  await this.offlineOff();
670
- this.debugWarnLog(
671
- `${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` + ` ${this.device.connectionType}, pushChanges will not happen.`,
672
- );
682
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
683
+ + ` ${this.device.connectionType}, pushChanges will not happen.`);
673
684
  }
674
685
  // Refresh the status from the API
675
686
  interval(15000)
@@ -682,54 +693,51 @@ export class Bot {
682
693
 
683
694
  async BLEpushChanges(): Promise<void> {
684
695
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
685
- if (this.On !== this.accessory.context.On || this.allowPush) {
686
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges On: ${this.On} OnCached: ${this.accessory.context.On}`);
696
+ const On = await this.getOn();
697
+ if (On !== this.accessory.context.On || this.allowPush) {
698
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges On: ${On} OnCached: ${this.accessory.context.On}`);
687
699
  const switchbot = await this.platform.connectBLE();
688
700
  // Convert to BLE Address
689
- this.device.bleMac = this.device
690
- .deviceId!.match(/.{1,2}/g)!
691
- .join(':')
692
- .toLowerCase();
693
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
701
+ await this.convertBLEAddress();
694
702
  //if (switchbot !== false) {
695
703
  if (this.botMode === 'press') {
696
704
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Bot Mode: ${this.botMode}`);
697
705
  switchbot
698
706
  .discover({ model: 'H', quick: true, id: this.device.bleMac })
699
707
  .then(async (device_list: { press: (arg0: { id: string | undefined }) => any }[]) => {
700
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
708
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${On}`);
701
709
  return await device_list[0].press({ id: this.device.bleMac });
702
710
  })
703
711
  .then(() => {
704
712
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
705
- this.accessory.context.On = this.On;
713
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
714
+ + `On: ${On} sent over BLE, sent successfully`);
715
+ this.accessory.context.On = On;
706
716
  setTimeout(() => {
707
717
  if (this.botDeviceType === 'switch') {
708
- this.switchService?.getCharacteristic(this.hap.Characteristic.On).updateValue(this.On);
718
+ this.Switch?.Service.getCharacteristic(this.hap.Characteristic.On).updateValue(On);
709
719
  } else {
710
- this.outletService?.getCharacteristic(this.hap.Characteristic.On).updateValue(this.On);
720
+ this.Outlet?.Service.getCharacteristic(this.hap.Characteristic.On).updateValue(On);
711
721
  }
712
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}, Switch Timeout`);
722
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${On}, Switch Timeout`);
713
723
  }, 500);
714
724
  })
715
725
  .catch(async (e: any) => {
716
726
  this.apiError(e);
717
- this.errorLog(
718
- `${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}` +
719
- ` Connection & botMode: ${this.botMode}, Error Message: ${JSON.stringify(e.message)}`,
720
- );
727
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
728
+ + ` Connection & botMode: ${this.botMode}, Error Message: ${JSON.stringify(e.message)}`);
721
729
  await this.BLEPushConnection();
722
730
  });
723
731
  } else if (this.botMode === 'switch') {
724
732
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Press Mode: ${this.botMode}`);
725
733
  switchbot
726
- .discover({ model: 'H', quick: true, id: this.device.bleMac })
734
+ .discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac })
727
735
  .then(async (device_list: any) => {
728
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
729
- return await this.retry({
730
- max: this.maxRetry(),
736
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${On}`);
737
+ return await this.retryBLE({
738
+ max: await this.maxRetryBLE(),
731
739
  fn: async () => {
732
- if (this.On) {
740
+ if (On) {
733
741
  return await device_list[0].turnOn({ id: this.device.bleMac });
734
742
  } else {
735
743
  return await device_list[0].turnOff({ id: this.device.bleMac });
@@ -739,46 +747,43 @@ export class Bot {
739
747
  })
740
748
  .then(() => {
741
749
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
742
- this.accessory.context.On = this.On;
750
+ this.accessory.context.On = On;
743
751
  })
744
752
  .catch(async (e: any) => {
745
753
  this.apiError(e);
746
- this.errorLog(
747
- `${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}` +
748
- ` Connection & botMode: ${this.botMode}, Error Message: ${JSON.stringify(e.message)}`,
749
- );
754
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
755
+ + ` Connection & botMode: ${this.botMode}, Error Message: ${JSON.stringify(e.message)}`);
750
756
  await this.BLEPushConnection();
751
757
  });
752
758
  } else {
753
759
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Bot Mode: ${this.botMode}`);
754
760
  }
755
761
  } else {
756
- this.debugLog(
757
- `${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges.` + `On: ${this.On}, ` + `OnCached: ${this.accessory.context.On}`,
758
- );
762
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges, On: ${On}, OnCached: ${this.accessory.context.On}`);
759
763
  }
760
764
  }
761
765
 
762
766
  async openAPIpushChanges(): Promise<void> {
763
767
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
768
+ let On = await this.getOn();
764
769
  if (this.multiPressCount > 0) {
765
770
  this.debugLog(`${this.device.deviceType}: ${this.multiPressCount} request(s) queued.`);
766
- this.On = true;
771
+ On = true;
767
772
  }
768
- if (this.On !== this.accessory.context.On || this.allowPush || this.multiPressCount > 0) {
773
+ if (On !== this.accessory.context.On || this.allowPush || this.multiPressCount > 0) {
769
774
  let command = '';
770
- if (this.botMode === 'switch' && this.On) {
775
+ if (this.botMode === 'switch' && On) {
771
776
  command = 'turnOn';
772
- this.On = true;
773
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
774
- } else if (this.botMode === 'switch' && !this.On) {
777
+ On = true;
778
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Switch Mode, Turning ${On}`);
779
+ } else if (this.botMode === 'switch' && !On) {
775
780
  command = 'turnOff';
776
- this.On = false;
777
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
781
+ On = false;
782
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Switch Mode, Turning ${On}`);
778
783
  } else if (this.botMode === 'press' || this.botMode === 'multipress') {
779
784
  command = 'press';
780
785
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Press Mode`);
781
- this.On = false;
786
+ On = false;
782
787
  } else {
783
788
  throw new Error(`${this.device.deviceType}: ${this.accessory.displayName} Device Parameters not set for this Bot.`);
784
789
  }
@@ -789,44 +794,32 @@ export class Bot {
789
794
  });
790
795
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
791
796
  try {
792
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/commands`, {
793
- body: bodyChange,
794
- method: 'POST',
795
- headers: this.platform.generateHeaders(),
796
- });
797
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
797
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
798
798
  const deviceStatus: any = await body.json();
799
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
800
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
801
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
799
+ await this.pushStatusCodes(statusCode, deviceStatus);
802
800
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
803
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
804
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
801
+ await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
802
+ await this.updateHomeKitCharacteristics();
805
803
  } else {
806
- this.statusCode(statusCode);
807
- this.statusCode(deviceStatus.statusCode);
804
+ await this.statusCode(statusCode);
805
+ await this.statusCode(deviceStatus.statusCode);
808
806
  }
809
807
  if (this.device.bot?.mode === 'multipress') {
810
808
  this.multiPressCount--;
811
809
  if (this.multiPressCount > 0) {
812
810
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Multi Press Count: ${this.multiPressCount}`);
813
- this.On = true;
811
+ On = true;
814
812
  this.openAPIpushChanges();
815
813
  }
816
814
  }
817
815
  } catch (e: any) {
818
816
  this.apiError(e);
819
- this.errorLog(
820
- `${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}` +
821
- ` Connection, Error Message: ${JSON.stringify(e.message)}`,
822
- );
817
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
818
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
823
819
  }
824
820
  } else {
825
- this.debugLog(
826
- `${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges.` +
827
- `On: ${this.On}, ` +
828
- `OnCached: ${this.accessory.context.On}`,
829
- );
821
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges,`
822
+ + ` On: ${On}, OnCached: ${this.accessory.context.On}`);
830
823
  }
831
824
  }
832
825
 
@@ -835,53 +828,105 @@ export class Bot {
835
828
  */
836
829
  async OnSet(value: CharacteristicValue): Promise<void> {
837
830
  if (this.botDeviceType === 'garagedoor') {
838
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetDoorState: ${value}`);
839
- if (value === this.hap.Characteristic.TargetDoorState.CLOSED) {
840
- this.On = false;
841
- } else {
842
- this.On = true;
831
+ if (this.GarageDoor) {
832
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetDoorState: ${value}`);
833
+ if (value === this.hap.Characteristic.TargetDoorState.CLOSED) {
834
+ await this.setOn(false);
835
+ this.GarageDoor.On = false;
836
+ } else {
837
+ await this.setOn(true);
838
+ this.GarageDoor.On = true;
839
+ }
843
840
  }
844
- } else if (
845
- this.botDeviceType === 'door' ||
846
- this.botDeviceType === 'window' ||
847
- this.botDeviceType === 'windowcovering'
848
- ) {
849
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetPosition: ${value}`);
850
- if (value === 0) {
851
- this.On = false;
852
- } else {
853
- this.On = true;
841
+ } else if (this.botDeviceType === 'door') {
842
+ if (this.Door) {
843
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetPosition: ${value}`);
844
+ if (value === 0) {
845
+ await this.setOn(false);
846
+ this.Door.On = false;
847
+ } else {
848
+ await this.setOn(true);
849
+ this.Door.On = true;
850
+ }
851
+ }
852
+ } else if (this.botDeviceType === 'window') {
853
+ if (this.Window) {
854
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetPosition: ${value}`);
855
+ if (value === 0) {
856
+ await this.setOn(false);
857
+ this.Window.On = false;
858
+ } else {
859
+ await this.setOn(true);
860
+ this.Window.On = true;
861
+ }
862
+ }
863
+ } else if (this.botDeviceType === 'windowcovering') {
864
+ if (this.WindowCovering) {
865
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetPosition: ${value}`);
866
+ if (value === 0) {
867
+ await this.setOn(false);
868
+ this.WindowCovering.On = false;
869
+ } else {
870
+ await this.setOn(true);
871
+ this.WindowCovering.On = true;
872
+ }
854
873
  }
855
874
  } else if (this.botDeviceType === 'lock') {
856
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set LockTargetState: ${value}`);
857
- if (value === this.hap.Characteristic.LockTargetState.SECURED) {
858
- this.On = false;
859
- } else {
860
- this.On = true;
875
+ if (this.LockMechanism) {
876
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set LockTargetState: ${value}`);
877
+ if (value === this.hap.Characteristic.LockTargetState.SECURED) {
878
+ await this.setOn(false);
879
+ this.LockMechanism.On = false;
880
+ } else {
881
+ await this.setOn(true);
882
+ this.LockMechanism.On = true;
883
+ }
861
884
  }
862
885
  } else if (this.botDeviceType === 'faucet') {
863
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Active: ${value}`);
864
- if (value === this.hap.Characteristic.Active.INACTIVE) {
865
- this.On = false;
866
- } else {
867
- this.On = true;
886
+ if (this.Faucet) {
887
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Active: ${value}`);
888
+ if (value === this.hap.Characteristic.Active.INACTIVE) {
889
+ await this.setOn(false);
890
+ this.Faucet.On = false;
891
+ } else {
892
+ await this.setOn(true);
893
+ this.Faucet.On = true;
894
+ }
868
895
  }
869
896
  } else if (this.botDeviceType === 'stateful') {
870
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set ProgrammableSwitchOutputState: ${value}`);
871
- if (value === 0) {
872
- this.On = false;
873
- } else {
874
- this.On = true;
897
+ if (this.StatefulProgrammableSwitch) {
898
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set ProgrammableSwitchOutputState: ${value}`);
899
+ if (value === 0) {
900
+ await this.setOn(false);
901
+ this.StatefulProgrammableSwitch.On = false;
902
+ } else {
903
+ await this.setOn(true);
904
+ this.StatefulProgrammableSwitch.On = true;
905
+ }
875
906
  }
876
- } else {
877
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set On: ${value}`);
878
- if (this.device.bot?.mode === 'multipress') {
879
- if (value === true) {
880
- this.multiPressCount++;
881
- this.debugLog(`${this.device.deviceType} set to Multi-Press. Multi-Press count: ${this.multiPressCount}`);
907
+ } else if (this.botDeviceType === 'switch') {
908
+ if (this.Switch) {
909
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set ProgrammableSwitchOutputState: ${value}`);
910
+ if (value === 0) {
911
+ await this.setOn(false);
912
+ this.Switch.On = false;
913
+ } else {
914
+ await this.setOn(true);
915
+ this.Switch.On = true;
882
916
  }
883
917
  }
884
- this.On = value;
918
+ } else {
919
+ if (this.Outlet) {
920
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set On: ${value}`);
921
+ await this.setOn(Boolean(value));
922
+ this.Outlet.On = value;
923
+ }
924
+ }
925
+ if (this.device.bot?.mode === 'multipress') {
926
+ if (value === true) {
927
+ this.multiPressCount++;
928
+ this.debugLog(`${this.device.deviceType} set to Multi-Press. Multi-Press count: ${this.multiPressCount}`);
929
+ }
885
930
  }
886
931
  this.doBotUpdate.next();
887
932
  }
@@ -892,536 +937,352 @@ export class Bot {
892
937
  async updateHomeKitCharacteristics(): Promise<void> {
893
938
  // State
894
939
  if (this.botDeviceType === 'garagedoor') {
895
- if (this.On === undefined) {
896
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
940
+ if (this.GarageDoor?.On === undefined) {
941
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.GarageDoor?.On}`);
897
942
  } else {
898
- if (this.On) {
899
- this.garageDoorService?.updateCharacteristic(
900
- this.hap.Characteristic.TargetDoorState,
901
- this.hap.Characteristic.TargetDoorState.OPEN,
902
- );
903
- this.garageDoorService?.updateCharacteristic(
904
- this.hap.Characteristic.CurrentDoorState,
905
- this.hap.Characteristic.CurrentDoorState.OPEN,
906
- );
907
- this.debugLog(
908
- `${this.device.deviceType}: ` + `${this.accessory.displayName} updateCharacteristic TargetDoorState: Open, CurrentDoorState: Open`,
909
- );
943
+ if (this.GarageDoor.On) {
944
+ this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.TargetDoorState, this.hap.Characteristic.TargetDoorState.OPEN);
945
+ this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.CurrentDoorState, this.hap.Characteristic.CurrentDoorState.OPEN);
946
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
947
+ + ` TargetDoorState: Open, CurrentDoorState: Open (${this.GarageDoor.On})`);
910
948
  } else {
911
- this.garageDoorService?.updateCharacteristic(
912
- this.hap.Characteristic.TargetDoorState,
913
- this.hap.Characteristic.TargetDoorState.CLOSED,
914
- );
915
- this.garageDoorService?.updateCharacteristic(
916
- this.hap.Characteristic.CurrentDoorState,
917
- this.hap.Characteristic.CurrentDoorState.CLOSED,
918
- );
919
- this.debugLog(
920
- `${this.device.deviceType}: ` + `${this.accessory.displayName} updateCharacteristic TargetDoorState: Open, CurrentDoorState: Open`,
921
- );
949
+ this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.TargetDoorState, this.hap.Characteristic.TargetDoorState.CLOSED);
950
+ this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.CurrentDoorState, this.hap.Characteristic.CurrentDoorState.CLOSED);
951
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristicc`
952
+ + ` TargetDoorState: Open, CurrentDoorState: Open (${this.GarageDoor.On})`);
922
953
  }
923
954
  }
924
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Garage Door On: ${this.On}`);
955
+ await this.setOn(Boolean(this.GarageDoor?.On));
956
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Garage Door On: ${this.GarageDoor?.On}`);
925
957
  } else if (this.botDeviceType === 'door') {
926
- if (this.On === undefined) {
927
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
958
+ if (this.Door?.On === undefined) {
959
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.Door?.On}`);
928
960
  } else {
929
- if (this.On) {
930
- this.doorService?.updateCharacteristic(this.hap.Characteristic.TargetPosition, 100);
931
- this.doorService?.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 100);
932
- this.doorService?.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
933
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic TargetPosition: 100, CurrentPosition: 100`);
961
+ if (this.Door.On) {
962
+ this.Door.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 100);
963
+ this.Door.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 100);
964
+ this.Door.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
965
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristicc`
966
+ + ` TargetPosition: 100, CurrentPosition: 100 (${this.Door.On})`);
934
967
  } else {
935
- this.doorService?.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
936
- this.doorService?.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
937
- this.doorService?.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
938
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic TargetPosition: 0, CurrentPosition: 0`);
968
+ this.Door.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
969
+ this.Door.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
970
+ this.Door.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
971
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristicc`
972
+ + ` TargetPosition: 0, CurrentPosition: 0 (${this.Door.On})`);
939
973
  }
940
974
  }
941
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Door On: ${this.On}`);
975
+ await this.setOn(Boolean(this.Door?.On));
976
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Door On: ${this.Door?.On}`);
942
977
  } else if (this.botDeviceType === 'window') {
943
- if (this.On === undefined) {
944
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
978
+ if (this.Window?.On === undefined) {
979
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.Window?.On}`);
945
980
  } else {
946
- if (this.On) {
947
- this.windowService?.updateCharacteristic(this.hap.Characteristic.TargetPosition, 100);
948
- this.windowService?.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 100);
949
- this.windowService?.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
950
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic TargetPosition: 100, CurrentPosition: 100`);
981
+ if (this.Window.On) {
982
+ this.Window.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 100);
983
+ this.Window.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 100);
984
+ this.Window.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
985
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristicc`
986
+ + ` TargetPosition: 100, CurrentPosition: 100 (${this.Window.On})`);
951
987
  } else {
952
- this.windowService?.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
953
- this.windowService?.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
954
- this.windowService?.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
955
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic TargetPosition: 0, CurrentPosition: 0`);
988
+ this.Window.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
989
+ this.Window.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
990
+ this.Window.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
991
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristicc`
992
+ + ` TargetPosition: 0, CurrentPosition: 0 (${this.Window.On})`);
956
993
  }
957
994
  }
958
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Window On: ${this.On}`);
995
+ await this.setOn(Boolean(this.Window?.On));
996
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Window On: ${this.Window?.On}`);
959
997
  } else if (this.botDeviceType === 'windowcovering') {
960
- if (this.On === undefined) {
961
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
998
+ if (this.WindowCovering?.On === undefined) {
999
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.WindowCovering?.On}`);
962
1000
  } else {
963
- if (this.On) {
964
- this.windowCoveringService?.updateCharacteristic(this.hap.Characteristic.TargetPosition, 100);
965
- this.windowCoveringService?.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 100);
966
- this.windowCoveringService?.updateCharacteristic(
967
- this.hap.Characteristic.PositionState,
968
- this.hap.Characteristic.PositionState.STOPPED,
969
- );
970
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic TargetPosition: 100, CurrentPosition: 100`);
1001
+ if (this.WindowCovering.On) {
1002
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 100);
1003
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 100);
1004
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
1005
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristicc`
1006
+ + ` TargetPosition: 100, CurrentPosition: 100 (${this.WindowCovering.On})`);
971
1007
  } else {
972
- this.windowCoveringService?.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
973
- this.windowCoveringService?.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
974
- this.windowCoveringService?.updateCharacteristic(
975
- this.hap.Characteristic.PositionState,
976
- this.hap.Characteristic.PositionState.STOPPED,
977
- );
978
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic TargetPosition: 0, CurrentPosition: 0`);
1008
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
1009
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
1010
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
1011
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristicc`
1012
+ + ` TargetPosition: 0, CurrentPosition: 0 (${this.WindowCovering.On})`);
979
1013
  }
980
1014
  }
981
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Window Covering On: ${this.On}`);
1015
+ await this.setOn(Boolean(this.WindowCovering?.On));
1016
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Window Covering On: ${this.WindowCovering?.On}`);
982
1017
  } else if (this.botDeviceType === 'lock') {
983
- if (this.On === undefined) {
984
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
1018
+ if (this.LockMechanism?.On === undefined) {
1019
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LockMechanism?.On}`);
985
1020
  } else {
986
- if (this.On) {
987
- this.lockService?.updateCharacteristic(
988
- this.hap.Characteristic.LockTargetState,
989
- this.hap.Characteristic.LockTargetState.UNSECURED,
990
- );
991
- this.lockService?.updateCharacteristic(
992
- this.hap.Characteristic.LockCurrentState,
993
- this.hap.Characteristic.LockCurrentState.UNSECURED,
994
- );
995
- this.debugLog(
996
- `${this.device.deviceType}: ` +
997
- `${this.accessory.displayName} updateCharacteristic LockTargetState: UNSECURED, LockCurrentState: UNSECURED`,
998
- );
1021
+ if (this.LockMechanism.On) {
1022
+ this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState,
1023
+ this.hap.Characteristic.LockTargetState.UNSECURED);
1024
+ this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState,
1025
+ this.hap.Characteristic.LockCurrentState.UNSECURED);
1026
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristicc`
1027
+ + ` LockTargetState: UNSECURED, LockCurrentState: UNSECURED (${this.LockMechanism.On})`);
999
1028
  } else {
1000
- this.lockService?.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.hap.Characteristic.LockTargetState.SECURED);
1001
- this.lockService?.updateCharacteristic(
1002
- this.hap.Characteristic.LockCurrentState,
1003
- this.hap.Characteristic.LockCurrentState.SECURED,
1004
- );
1005
- this.debugLog(
1006
- `${this.device.deviceType}: ` + `${this.accessory.displayName} updateCharacteristic LockTargetState: SECURED, LockCurrentState: SECURED`,
1007
- );
1029
+ this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState,
1030
+ this.hap.Characteristic.LockTargetState.SECURED);
1031
+ this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState,
1032
+ this.hap.Characteristic.LockCurrentState.SECURED);
1033
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
1034
+ + ` LockTargetState: SECURED, LockCurrentState: SECURED (${this.LockMechanism.On})`);
1008
1035
  }
1009
1036
  }
1010
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Lock On: ${this.On}`);
1037
+ await this.setOn(Boolean(this.LockMechanism?.On));
1038
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Lock On: ${this.LockMechanism?.On}`);
1011
1039
  } else if (this.botDeviceType === 'faucet') {
1012
- if (this.On === undefined) {
1013
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
1040
+ if (this.Faucet?.On === undefined) {
1041
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.Faucet?.On}`);
1014
1042
  } else {
1015
- if (this.On) {
1016
- this.faucetService?.updateCharacteristic(this.hap.Characteristic.Active, this.hap.Characteristic.Active.ACTIVE);
1017
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Active: ${this.On}`);
1043
+ if (this.Faucet.On) {
1044
+ this.Faucet.Service.updateCharacteristic(this.hap.Characteristic.Active, this.hap.Characteristic.Active.ACTIVE);
1045
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Active: ${this.Faucet.On}`);
1018
1046
  } else {
1019
- this.faucetService?.updateCharacteristic(this.hap.Characteristic.Active, this.hap.Characteristic.Active.INACTIVE);
1020
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Active: ${this.On}`);
1047
+ this.Faucet.Service.updateCharacteristic(this.hap.Characteristic.Active, this.hap.Characteristic.Active.INACTIVE);
1048
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Active: ${this.Faucet.On}`);
1021
1049
  }
1022
1050
  }
1023
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Faucet On: ${this.On}`);
1051
+ await this.setOn(Boolean(this.Faucet?.On));
1052
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Faucet On: ${this.Faucet?.On}`);
1024
1053
  } else if (this.botDeviceType === 'fan') {
1025
- if (this.On === undefined) {
1026
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
1054
+ if (this.Fan?.On === undefined) {
1055
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.Fan?.On}`);
1027
1056
  } else {
1028
- if (this.On) {
1029
- this.fanService?.updateCharacteristic(this.hap.Characteristic.On, this.On);
1030
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
1057
+ if (this.Fan.On) {
1058
+ this.Fan.Service.updateCharacteristic(this.hap.Characteristic.On, this.Fan.On);
1059
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.Fan.On}`);
1031
1060
  } else {
1032
- this.fanService?.updateCharacteristic(this.hap.Characteristic.On, this.On);
1033
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
1061
+ this.Fan.Service.updateCharacteristic(this.hap.Characteristic.On, this.Fan.On);
1062
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.Fan.On}`);
1034
1063
  }
1035
1064
  }
1036
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Fan On: ${this.On}`);
1065
+ await this.setOn(Boolean(this.Fan?.On));
1066
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Fan On: ${this.Fan?.On}`);
1037
1067
  } else if (this.botDeviceType === 'stateful') {
1038
- if (this.On === undefined) {
1039
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
1068
+ if (this.StatefulProgrammableSwitch?.On === undefined) {
1069
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.StatefulProgrammableSwitch?.On}`);
1040
1070
  } else {
1041
- if (this.On) {
1042
- this.statefulProgrammableSwitchService?.updateCharacteristic(
1043
- this.hap.Characteristic.ProgrammableSwitchEvent,
1044
- this.hap.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,
1045
- );
1046
- this.statefulProgrammableSwitchService?.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState, 1);
1047
- this.debugLog(
1048
- `${this.device.deviceType}: ` +
1049
- `${this.accessory.displayName} updateCharacteristic ProgrammableSwitchEvent: SINGLE, ProgrammableSwitchOutputState: 1`,
1050
- );
1071
+ if (this.StatefulProgrammableSwitch.On) {
1072
+ this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchEvent,
1073
+ this.hap.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS);
1074
+ this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState, 1);
1075
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
1076
+ + ` ProgrammableSwitchEvent: SINGLE, ProgrammableSwitchOutputState: 1 (${this.StatefulProgrammableSwitch.On})`);
1051
1077
  } else {
1052
- this.statefulProgrammableSwitchService?.updateCharacteristic(
1053
- this.hap.Characteristic.ProgrammableSwitchEvent,
1054
- this.hap.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,
1055
- );
1056
- this.statefulProgrammableSwitchService?.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState, 0);
1057
- this.debugLog(
1058
- `${this.device.deviceType}: ` +
1059
- `${this.accessory.displayName} updateCharacteristic ProgrammableSwitchEvent: SINGLE, ProgrammableSwitchOutputState: 0`,
1060
- );
1078
+ this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchEvent,
1079
+ this.hap.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS);
1080
+ this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState, 0);
1081
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
1082
+ + ` ProgrammableSwitchEvent: SINGLE, ProgrammableSwitchOutputState: 0 (${this.StatefulProgrammableSwitch.On})`);
1061
1083
  }
1062
1084
  }
1063
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatefulProgrammableSwitch On: ${this.On}`);
1085
+ await this.setOn(Boolean(this.StatefulProgrammableSwitch?.On));
1086
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatefulProgrammableSwitch On: ${this.StatefulProgrammableSwitch?.On}`);
1064
1087
  } else if (this.botDeviceType === 'switch') {
1065
- if (this.On === undefined) {
1066
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
1088
+ if (this.Switch?.On === undefined) {
1089
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.Switch?.On}`);
1067
1090
  } else {
1068
- this.switchService?.updateCharacteristic(this.hap.Characteristic.On, this.On);
1069
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
1091
+ this.Switch.Service.updateCharacteristic(this.hap.Characteristic.On, this.Switch.On);
1092
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.Switch.On}`);
1070
1093
  }
1094
+ await this.setOn(Boolean(this.Switch?.On));
1071
1095
  } else {
1072
- if (this.On === undefined) {
1073
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
1096
+ if (this.Outlet?.On === undefined) {
1097
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.Outlet?.On}`);
1074
1098
  } else {
1075
- this.outletService?.updateCharacteristic(this.hap.Characteristic.On, this.On);
1076
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
1099
+ this.Outlet.Service.updateCharacteristic(this.hap.Characteristic.On, this.Outlet.On);
1100
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.Outlet.On}`);
1077
1101
  }
1102
+ await this.setOn(Boolean(this.Outlet?.On));
1078
1103
  }
1079
- this.accessory.context.On = this.On;
1104
+ this.accessory.context.On = await this.getOn();
1080
1105
  // BatteryLevel
1081
- if (this.BatteryLevel === undefined) {
1082
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
1106
+ if (this.Battery.BatteryLevel === undefined) {
1107
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}`);
1083
1108
  } else {
1084
- this.accessory.context.BatteryLevel = this.BatteryLevel;
1085
- this.batteryService?.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.BatteryLevel);
1086
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
1109
+ this.accessory.context.BatteryLevel = this.Battery.BatteryLevel;
1110
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel);
1111
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.Battery.BatteryLevel}`);
1087
1112
  }
1088
1113
  // StatusLowBattery
1089
- if (this.StatusLowBattery === undefined) {
1090
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
1114
+ if (this.Battery.StatusLowBattery === undefined) {
1115
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.Battery.StatusLowBattery}`);
1091
1116
  } else {
1092
- this.accessory.context.StatusLowBattery = this.StatusLowBattery;
1093
- this.batteryService?.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.StatusLowBattery);
1094
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
1117
+ this.accessory.context.StatusLowBattery = this.Battery.StatusLowBattery;
1118
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery);
1119
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
1120
+ + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
1095
1121
  }
1096
1122
  }
1097
1123
 
1098
1124
  async removeOutletService(accessory: PlatformAccessory): Promise<void> {
1099
1125
  // If outletService still present, then remove first
1100
- this.outletService = this.accessory.getService(this.hap.Service.Outlet);
1101
- if (this.outletService) {
1126
+ if (this.Outlet?.Service) {
1127
+ this.Outlet.Service = this.accessory.getService(this.hap.Service.Outlet) as Service;
1102
1128
  this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Outlet Service`);
1129
+ accessory.removeService(this.Outlet.Service);
1103
1130
  }
1104
- accessory.removeService(this.outletService!);
1105
1131
  }
1106
1132
 
1107
1133
  async removeGarageDoorService(accessory: PlatformAccessory): Promise<void> {
1108
1134
  // If garageDoorService still present, then remove first
1109
- this.garageDoorService = this.accessory.getService(this.hap.Service.GarageDoorOpener);
1110
- if (this.garageDoorService) {
1135
+ if (this.GarageDoor?.Service) {
1136
+ this.GarageDoor.Service = this.accessory.getService(this.hap.Service.GarageDoorOpener) as Service;
1111
1137
  this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Garage Door Service`);
1138
+ accessory.removeService(this.GarageDoor.Service);
1112
1139
  }
1113
- accessory.removeService(this.garageDoorService!);
1114
1140
  }
1115
1141
 
1116
1142
  async removeDoorService(accessory: PlatformAccessory): Promise<void> {
1117
1143
  // If doorService still present, then remove first
1118
- this.doorService = this.accessory.getService(this.hap.Service.Door);
1119
- if (this.doorService) {
1144
+ if (this.Door?.Service) {
1145
+ this.Door.Service = this.accessory.getService(this.hap.Service.Door) as Service;
1120
1146
  this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Door Service`);
1147
+ accessory.removeService(this.Door.Service);
1121
1148
  }
1122
- accessory.removeService(this.doorService!);
1123
1149
  }
1124
1150
 
1125
1151
  async removeLockService(accessory: PlatformAccessory): Promise<void> {
1126
1152
  // If lockService still present, then remove first
1127
- this.lockService = this.accessory.getService(this.hap.Service.LockMechanism);
1128
- if (this.lockService) {
1153
+ if (this.LockMechanism?.Service) {
1154
+ this.LockMechanism.Service = this.accessory.getService(this.hap.Service.LockMechanism) as Service;
1129
1155
  this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Lock Service`);
1156
+ accessory.removeService(this.LockMechanism.Service);
1130
1157
  }
1131
- accessory.removeService(this.lockService!);
1132
1158
  }
1133
1159
 
1134
1160
  async removeFaucetService(accessory: PlatformAccessory): Promise<void> {
1135
1161
  // If faucetService still present, then remove first
1136
- this.faucetService = this.accessory.getService(this.hap.Service.Faucet);
1137
- if (this.faucetService) {
1162
+ if (this.Faucet?.Service) {
1163
+ this.Faucet.Service = this.accessory.getService(this.hap.Service.Faucet) as Service;
1138
1164
  this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Faucet Service`);
1165
+ accessory.removeService(this.Faucet.Service);
1139
1166
  }
1140
- accessory.removeService(this.faucetService!);
1141
1167
  }
1142
1168
 
1143
1169
  async removeFanService(accessory: PlatformAccessory): Promise<void> {
1144
1170
  // If fanService still present, then remove first
1145
- this.fanService = this.accessory.getService(this.hap.Service.Fan);
1146
- if (this.fanService) {
1171
+ if (this.Fan?.Service) {
1172
+ this.Fan.Service = this.accessory.getService(this.hap.Service.Fanv2) as Service;
1147
1173
  this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Fan Service`);
1174
+ accessory.removeService(this.Fan.Service);
1148
1175
  }
1149
- accessory.removeService(this.fanService!);
1150
1176
  }
1151
1177
 
1152
1178
  async removeWindowService(accessory: PlatformAccessory): Promise<void> {
1153
1179
  // If windowService still present, then remove first
1154
- this.windowService = this.accessory.getService(this.hap.Service.Window);
1155
- if (this.windowService) {
1180
+ if (this.Window?.Service) {
1181
+ this.Window.Service = this.accessory.getService(this.hap.Service.Window) as Service;
1156
1182
  this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Window Service`);
1183
+ accessory.removeService(this.Window.Service);
1157
1184
  }
1158
- accessory.removeService(this.windowService!);
1159
1185
  }
1160
1186
 
1161
1187
  async removeWindowCoveringService(accessory: PlatformAccessory): Promise<void> {
1162
1188
  // If windowCoveringService still present, then remove first
1163
- this.windowCoveringService = this.accessory.getService(this.hap.Service.WindowCovering);
1164
- if (this.windowCoveringService) {
1189
+ if (this.WindowCovering?.Service) {
1190
+ this.WindowCovering.Service = this.accessory.getService(this.hap.Service.WindowCovering) as Service;
1165
1191
  this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Window Covering Service`);
1192
+ accessory.removeService(this.WindowCovering.Service);
1166
1193
  }
1167
- accessory.removeService(this.windowCoveringService!);
1168
1194
  }
1169
1195
 
1170
1196
  async removeStatefulProgrammableSwitchService(accessory: PlatformAccessory): Promise<void> {
1171
1197
  // If statefulProgrammableSwitchService still present, then remove first
1172
- this.statefulProgrammableSwitchService = this.accessory.getService(this.hap.Service.StatefulProgrammableSwitch);
1173
- if (this.statefulProgrammableSwitchService) {
1198
+ if (this.StatefulProgrammableSwitch?.Service) {
1199
+ this.StatefulProgrammableSwitch.Service = this.accessory.getService(this.hap.Service.StatefulProgrammableSwitch) as Service;
1174
1200
  this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Stateful Programmable Switch Service`);
1201
+ accessory.removeService(this.StatefulProgrammableSwitch.Service);
1175
1202
  }
1176
- accessory.removeService(this.statefulProgrammableSwitchService!);
1177
1203
  }
1178
1204
 
1179
1205
  async removeSwitchService(accessory: PlatformAccessory): Promise<void> {
1180
1206
  // If switchService still present, then remove first
1181
- this.switchService = this.accessory.getService(this.hap.Service.Switch);
1182
- if (this.switchService) {
1207
+ if (this.Switch?.Service) {
1208
+ this.Switch.Service = this.accessory.getService(this.hap.Service.Switch) as Service;
1183
1209
  this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Switch Service`);
1210
+ accessory.removeService(this.Switch.Service);
1184
1211
  }
1185
- accessory.removeService(this.switchService!);
1186
1212
  }
1187
1213
 
1188
- private DoublePress(device: device & devicesConfig) {
1189
- if (device.bot?.doublePress) {
1190
- this.doublePress = device.bot?.doublePress;
1191
- this.accessory.context.doublePress = this.doublePress;
1192
- } else {
1193
- this.doublePress = 1;
1194
- }
1195
- }
1196
-
1197
- async stopScanning(switchbot: any) {
1198
- switchbot.stopScan();
1199
- if (this.BLE_IsConnected) {
1200
- await this.BLEparseStatus();
1201
- await this.updateHomeKitCharacteristics();
1202
- } else {
1203
- await this.BLERefreshConnection(switchbot);
1204
- }
1205
- }
1206
-
1207
- async getCustomBLEAddress(switchbot: any) {
1208
- if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
1209
- (async () => {
1210
- // Start to monitor advertisement packets
1211
- await switchbot.startScan({
1212
- model: 'H',
1213
- });
1214
- // Set an event handler
1215
- switchbot.onadvertisement = (ad: any) => {
1216
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${JSON.stringify(ad, null, ' ')}`);
1217
- };
1218
- await sleep(10000);
1219
- // Stop to monitor
1220
- switchbot.stopScan();
1221
- })();
1222
- }
1223
- }
1224
-
1225
- async BLEPushConnection() {
1226
- if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
1227
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Push Changes`);
1228
- await this.openAPIpushChanges();
1229
- }
1230
- }
1231
-
1232
- async BLERefreshConnection(switchbot: any): Promise<void> {
1233
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot:`
1234
- + ` ${JSON.stringify(switchbot)}`);
1235
- if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
1236
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Refresh Status`);
1237
- await this.openAPIRefreshStatus();
1238
- }
1239
- }
1240
-
1241
- async retry({ max, fn }: { max: number; fn: { (): any; (): Promise<any> } }): Promise<null> {
1242
- return fn().catch(async (e: any) => {
1243
- if (max === 0) {
1244
- throw e;
1245
- }
1246
- this.infoLog(e);
1247
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Retrying`);
1248
- await sleep(1000);
1249
- return this.retry({ max: max - 1, fn });
1250
- });
1251
- }
1252
-
1253
- maxRetry(): number {
1254
- if (this.device.maxRetry) {
1255
- return this.device.maxRetry;
1256
- } else {
1257
- return 5;
1258
- }
1259
- }
1260
-
1261
- async PressOrSwitch(device: device & devicesConfig): Promise<void> {
1262
- if (!device.bot?.mode) {
1263
- this.botMode = 'switch';
1264
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} does not have bot mode set in the Plugin's SwitchBot Device Settings,`);
1265
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} is defaulting to "${this.botMode}" mode, you may experience issues.`);
1266
- } else if (device.bot?.mode === 'switch') {
1267
- this.botMode = 'switch';
1268
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Bot Mode: ${this.botMode}`);
1269
- } else if (device.bot?.mode === 'press') {
1270
- this.botMode = 'press';
1271
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Bot Mode: ${this.botMode}`);
1272
- } else if (device.bot?.mode === 'multipress') {
1273
- this.botMode = 'multipress';
1274
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Bot Mode: ${this.botMode}`);
1275
- } else {
1276
- throw new Error(`${this.device.deviceType}: ${this.accessory.displayName} Bot Mode: ${this.botMode}`);
1277
- }
1278
- }
1279
-
1280
- async allowPushChanges(device: device & devicesConfig): Promise<void> {
1281
- if (device.bot?.allowPush) {
1282
- this.allowPush = true;
1283
- } else {
1284
- this.allowPush = false;
1285
- }
1286
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Allowing Push Changes: ${this.allowPush}`);
1287
- }
1288
-
1289
- async scan(device: device & devicesConfig): Promise<void> {
1290
- if (device.scanDuration) {
1291
- this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
1292
- if (this.BLE) {
1293
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
1294
- }
1214
+ async getOn(): Promise<boolean> {
1215
+ let On: boolean;
1216
+ if (this.botDeviceType === 'garagedoor') {
1217
+ On = this.GarageDoor?.On ? true : false;
1218
+ } else if (this.botDeviceType === 'door') {
1219
+ On = this.Door?.On ? true : false;
1220
+ } else if (this.botDeviceType === 'window') {
1221
+ On = this.Window?.On ? true : false;
1222
+ } else if (this.botDeviceType === 'windowcovering') {
1223
+ On = this.WindowCovering?.On ? true : false;
1224
+ } else if (this.botDeviceType === 'lock') {
1225
+ On = this.LockMechanism?.On ? true : false;
1226
+ } else if (this.botDeviceType === 'faucet') {
1227
+ On = this.Faucet?.On ? true : false;
1228
+ } else if (this.botDeviceType === 'fan') {
1229
+ On = this.Fan?.On ? true : false;
1230
+ } else if (this.botDeviceType === 'stateful') {
1231
+ On = this.StatefulProgrammableSwitch?.On ? true : false;
1232
+ } else if (this.botDeviceType === 'switch') {
1233
+ On = this.Switch?.On ? true : false;
1295
1234
  } else {
1296
- this.scanDuration = this.accessory.context.scanDuration = 1;
1297
- if (this.BLE) {
1298
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
1299
- }
1300
- }
1301
- }
1302
-
1303
- async statusCode(statusCode: number): Promise<void> {
1304
- switch (statusCode) {
1305
- case 151:
1306
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this deviceType, statusCode: ${statusCode}`);
1307
- break;
1308
- case 152:
1309
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found, statusCode: ${statusCode}`);
1310
- break;
1311
- case 160:
1312
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported, statusCode: ${statusCode}`);
1313
- break;
1314
- case 161:
1315
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline, statusCode: ${statusCode}`);
1316
- this.offlineOff();
1317
- break;
1318
- case 171:
1319
- this.errorLog(
1320
- `${this.device.deviceType}: ${this.accessory.displayName} Hub Device is offline, statusCode: ${statusCode}. ` +
1321
- `Hub: ${this.device.hubDeviceId}`,
1322
- );
1323
- this.offlineOff();
1324
- break;
1325
- case 190:
1326
- this.errorLog(
1327
- `${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
1328
- ` Or command format is invalid, statusCode: ${statusCode}`,
1329
- );
1330
- break;
1331
- case 100:
1332
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent, statusCode: ${statusCode}`);
1333
- break;
1334
- case 200:
1335
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Request successful, statusCode: ${statusCode}`);
1336
- break;
1337
- case 400:
1338
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Bad Request, The client has issued an invalid request. `
1339
- + `This is commonly used to specify validation errors in a request payload, statusCode: ${statusCode}`);
1340
- break;
1341
- case 401:
1342
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unauthorized, Authorization for the API is required, `
1343
- + `but the request has not been authenticated, statusCode: ${statusCode}`);
1344
- break;
1345
- case 403:
1346
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Forbidden, The request has been authenticated but does not `
1347
- + `have appropriate permissions, or a requested resource is not found, statusCode: ${statusCode}`);
1348
- break;
1349
- case 404:
1350
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Not Found, Specifies the requested path does not exist, `
1351
- + `statusCode: ${statusCode}`);
1352
- break;
1353
- case 406:
1354
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Not Acceptable, The client has requested a MIME type via `
1355
- + `the Accept header for a value not supported by the server, statusCode: ${statusCode}`);
1356
- break;
1357
- case 415:
1358
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unsupported Media Type, The client has defined a contentType `
1359
- + `header that is not supported by the server, statusCode: ${statusCode}`);
1360
- break;
1361
- case 422:
1362
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unprocessable Entity, The client has made a valid request, `
1363
- + `but the server cannot process it. This is often used for APIs for which certain limits have been exceeded, statusCode: ${statusCode}`);
1364
- break;
1365
- case 429:
1366
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Too Many Requests, The client has exceeded the number of `
1367
- + `requests allowed for a given time window, statusCode: ${statusCode}`);
1368
- break;
1369
- case 500:
1370
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Internal Server Error, An unexpected error on the SmartThings `
1371
- + `servers has occurred. These errors should be rare, statusCode: ${statusCode}`);
1372
- break;
1373
- default:
1374
- this.infoLog(
1375
- `${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode: ` +
1376
- `${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`,
1377
- );
1378
- }
1379
- }
1380
-
1381
- async offlineOff(): Promise<void> {
1382
- if (this.device.offline) {
1383
- await this.deviceContext();
1384
- await this.updateHomeKitCharacteristics();
1235
+ On = this.Outlet?.On ? true : false;
1385
1236
  }
1237
+ return On;
1386
1238
  }
1387
1239
 
1388
- async apiError(e: any): Promise<void> {
1240
+ async setOn(On: boolean): Promise<void> {
1389
1241
  if (this.botDeviceType === 'garagedoor') {
1390
- this.garageDoorService?.updateCharacteristic(this.hap.Characteristic.TargetDoorState, e);
1391
- this.garageDoorService?.updateCharacteristic(this.hap.Characteristic.CurrentDoorState, e);
1392
- this.garageDoorService?.updateCharacteristic(this.hap.Characteristic.ObstructionDetected, e);
1242
+ if (this.GarageDoor) {
1243
+ this.GarageDoor.On = On;
1244
+ }
1393
1245
  } else if (this.botDeviceType === 'door') {
1394
- this.doorService?.updateCharacteristic(this.hap.Characteristic.TargetPosition, e);
1395
- this.doorService?.updateCharacteristic(this.hap.Characteristic.CurrentPosition, e);
1396
- this.doorService?.updateCharacteristic(this.hap.Characteristic.PositionState, e);
1246
+ if (this.Door) {
1247
+ this.Door.On = On;
1248
+ }
1397
1249
  } else if (this.botDeviceType === 'window') {
1398
- this.windowService?.updateCharacteristic(this.hap.Characteristic.TargetPosition, e);
1399
- this.windowService?.updateCharacteristic(this.hap.Characteristic.CurrentPosition, e);
1400
- this.windowService?.updateCharacteristic(this.hap.Characteristic.PositionState, e);
1250
+ if (this.Window) {
1251
+ this.Window.On = On;
1252
+ }
1401
1253
  } else if (this.botDeviceType === 'windowcovering') {
1402
- this.windowCoveringService?.updateCharacteristic(this.hap.Characteristic.TargetPosition, e);
1403
- this.windowCoveringService?.updateCharacteristic(this.hap.Characteristic.CurrentPosition, e);
1404
- this.windowCoveringService?.updateCharacteristic(this.hap.Characteristic.PositionState, e);
1254
+ if (this.WindowCovering) {
1255
+ this.WindowCovering.On = On;
1256
+ }
1405
1257
  } else if (this.botDeviceType === 'lock') {
1406
- this.doorService?.updateCharacteristic(this.hap.Characteristic.LockTargetState, e);
1407
- this.doorService?.updateCharacteristic(this.hap.Characteristic.LockCurrentState, e);
1258
+ if (this.LockMechanism) {
1259
+ this.LockMechanism.On = On;
1260
+ }
1408
1261
  } else if (this.botDeviceType === 'faucet') {
1409
- this.faucetService?.updateCharacteristic(this.hap.Characteristic.Active, e);
1262
+ if (this.Faucet) {
1263
+ this.Faucet.On = On;
1264
+ }
1410
1265
  } else if (this.botDeviceType === 'fan') {
1411
- this.fanService?.updateCharacteristic(this.hap.Characteristic.On, e);
1266
+ if (this.Fan) {
1267
+ this.Fan.On = On;
1268
+ }
1412
1269
  } else if (this.botDeviceType === 'stateful') {
1413
- this.statefulProgrammableSwitchService?.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchEvent, e);
1414
- this.statefulProgrammableSwitchService?.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState, e);
1270
+ if (this.StatefulProgrammableSwitch) {
1271
+ this.StatefulProgrammableSwitch.On = On;
1272
+ }
1415
1273
  } else if (this.botDeviceType === 'switch') {
1416
- this.switchService?.updateCharacteristic(this.hap.Characteristic.On, e);
1274
+ if (this.Switch) {
1275
+ this.Switch.On = On;
1276
+ }
1417
1277
  } else {
1418
- this.outletService?.updateCharacteristic(this.hap.Characteristic.On, e);
1278
+ if (this.Outlet) {
1279
+ this.Outlet.On = On;
1280
+ }
1419
1281
  }
1420
- this.batteryService?.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e);
1421
- this.batteryService?.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e);
1422
1282
  }
1423
1283
 
1424
- async deviceType(device: device & devicesConfig): Promise<void> {
1284
+ async getBotConfigSettings(device: device & devicesConfig) {
1285
+ //Bot Device Type
1425
1286
  if (!device.bot?.deviceType && this.accessory.context.deviceType) {
1426
1287
  this.botDeviceType = this.accessory.context.deviceType;
1427
1288
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Type: ${this.botDeviceType}, from Accessory Cache.`);
@@ -1435,41 +1296,33 @@ export class Bot {
1435
1296
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} No Device Type Set, deviceType: ${this.device.bot?.deviceType}`);
1436
1297
  this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using default deviceType: ${this.botDeviceType}`);
1437
1298
  }
1438
- }
1439
-
1440
- async deviceContext() {
1441
- if (this.On === undefined) {
1442
- this.On = false;
1443
- this.accessory.context.On = this.On;
1444
- } else {
1445
- this.On = this.accessory.context.On;
1446
- }
1447
- if (this.BatteryLevel === undefined) {
1448
- this.BatteryLevel = 100;
1299
+ // Bot Mode
1300
+ if (!device.bot?.mode) {
1301
+ this.botMode = 'switch';
1302
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} does not have bot mode set in the Plugin's SwitchBot Device Settings,`);
1303
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} is defaulting to "${this.botMode}" mode, you may experience issues.`);
1304
+ } else if (device.bot?.mode === 'switch') {
1305
+ this.botMode = 'switch';
1306
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Bot Mode: ${this.botMode}`);
1307
+ } else if (device.bot?.mode === 'press') {
1308
+ this.botMode = 'press';
1309
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Bot Mode: ${this.botMode}`);
1310
+ } else if (device.bot?.mode === 'multipress') {
1311
+ this.botMode = 'multipress';
1312
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Bot Mode: ${this.botMode}`);
1449
1313
  } else {
1450
- this.BatteryLevel = this.accessory.context.BatteryLevel;
1314
+ throw new Error(`${this.device.deviceType}: ${this.accessory.displayName} Bot Mode: ${this.botMode}`);
1451
1315
  }
1452
- if (this.StatusLowBattery === undefined) {
1453
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
1454
- this.accessory.context.StatusLowBattery = this.StatusLowBattery;
1316
+
1317
+ // Bot Double Press
1318
+ if (device.bot?.doublePress) {
1319
+ this.doublePress = device.bot?.doublePress;
1320
+ this.accessory.context.doublePress = this.doublePress;
1455
1321
  } else {
1456
- this.StatusLowBattery = this.accessory.context.StatusLowBattery;
1457
- }
1458
- if (this.FirmwareRevision === undefined) {
1459
- this.FirmwareRevision = this.platform.version;
1460
- this.accessory.context.FirmwareRevision = this.FirmwareRevision;
1322
+ this.doublePress = 1;
1461
1323
  }
1462
- }
1463
1324
 
1464
- async refreshRate(device: device & devicesConfig): Promise<void> {
1465
- if (device.refreshRate) {
1466
- this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
1467
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
1468
- } else if (this.platform.config.options!.refreshRate) {
1469
- this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
1470
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
1471
- }
1472
- // pushRatePress
1325
+ // Bot Press PushRate
1473
1326
  if (device?.bot?.pushRatePress) {
1474
1327
  this.pushRatePress = device?.bot?.pushRatePress;
1475
1328
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Bot pushRatePress: ${this.pushRatePress}`);
@@ -1477,106 +1330,144 @@ export class Bot {
1477
1330
  this.pushRatePress = 15;
1478
1331
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default Bot pushRatePress: ${this.pushRatePress}`);
1479
1332
  }
1480
- }
1481
-
1482
- async deviceConfig(device: device & devicesConfig): Promise<void> {
1483
- let config = {};
1484
- if (device.bot) {
1485
- config = device.bot;
1486
- }
1487
- if (device.connectionType !== undefined) {
1488
- config['connectionType'] = device.connectionType;
1489
- }
1490
- if (device.external !== undefined) {
1491
- config['external'] = device.external;
1492
- }
1493
- if (device.logging !== undefined) {
1494
- config['logging'] = device.logging;
1495
- }
1496
- if (device.refreshRate !== undefined) {
1497
- config['refreshRate'] = device.refreshRate;
1498
- }
1499
- if (device.scanDuration !== undefined) {
1500
- config['scanDuration'] = device.scanDuration;
1501
- }
1502
- if (device.offline !== undefined) {
1503
- config['offline'] = device.offline;
1504
- }
1505
- if (device.maxRetry !== undefined) {
1506
- config['maxRetry'] = device.maxRetry;
1507
- }
1508
- if (device.webhook !== undefined) {
1509
- config['webhook'] = device.webhook;
1510
- }
1511
- if (Object.entries(config).length !== 0) {
1512
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
1513
- }
1514
- }
1515
1333
 
1516
- async deviceLogs(device: device & devicesConfig): Promise<void> {
1517
- if (this.platform.debugMode) {
1518
- this.deviceLogging = this.accessory.context.logging = 'debugMode';
1519
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
1520
- } else if (device.logging) {
1521
- this.deviceLogging = this.accessory.context.logging = device.logging;
1522
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
1523
- } else if (this.platform.config.options?.logging) {
1524
- this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
1525
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
1334
+ // Bot Allow Push
1335
+ if (device.bot?.allowPush) {
1336
+ this.allowPush = true;
1526
1337
  } else {
1527
- this.deviceLogging = this.accessory.context.logging = 'standard';
1528
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
1338
+ this.allowPush = false;
1529
1339
  }
1340
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Allowing Push Changes: ${this.allowPush}`);
1341
+ // Bot Multi Press Count
1342
+ this.multiPressCount = 0;
1530
1343
  }
1531
1344
 
1532
- /**
1533
- * Logging for Device
1534
- */
1535
- infoLog(...log: any[]): void {
1536
- if (this.enablingDeviceLogging()) {
1537
- this.platform.log.info(String(...log));
1345
+ async BLEPushConnection() {
1346
+ if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
1347
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Push Changes`);
1348
+ await this.openAPIpushChanges();
1538
1349
  }
1539
1350
  }
1540
1351
 
1541
- warnLog(...log: any[]): void {
1542
- if (this.enablingDeviceLogging()) {
1543
- this.platform.log.warn(String(...log));
1352
+ async BLERefreshConnection(switchbot: any): Promise<void> {
1353
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot:`
1354
+ + ` ${JSON.stringify(switchbot)}`);
1355
+ if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
1356
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Refresh Status`);
1357
+ await this.openAPIRefreshStatus();
1544
1358
  }
1545
1359
  }
1546
1360
 
1547
- debugWarnLog(...log: any[]): void {
1548
- if (this.enablingDeviceLogging()) {
1549
- if (this.deviceLogging?.includes('debug')) {
1550
- this.platform.log.warn('[DEBUG]', String(...log));
1361
+ async offlineOff(): Promise<void> {
1362
+ if (this.device.offline) {
1363
+ if (this.botDeviceType === 'garagedoor') {
1364
+ if (this.GarageDoor) {
1365
+ this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.TargetDoorState, this.hap.Characteristic.TargetDoorState.CLOSED);
1366
+ this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.CurrentDoorState, this.hap.Characteristic.CurrentDoorState.CLOSED);
1367
+ this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.ObstructionDetected, false);
1368
+ }
1369
+ } else if (this.botDeviceType === 'door') {
1370
+ if (this.Door) {
1371
+ this.Door.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
1372
+ this.Door.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
1373
+ this.Door.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
1374
+ }
1375
+ } else if (this.botDeviceType === 'window') {
1376
+ if (this.Window) {
1377
+ this.Window.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
1378
+ this.Window.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
1379
+ this.Window.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
1380
+ }
1381
+ } else if (this.botDeviceType === 'windowcovering') {
1382
+ if (this.WindowCovering) {
1383
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
1384
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
1385
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
1386
+ }
1387
+ } else if (this.botDeviceType === 'lock') {
1388
+ if (this.LockMechanism) {
1389
+ this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.hap.Characteristic.LockTargetState.SECURED);
1390
+ this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.hap.Characteristic.LockCurrentState.SECURED);
1391
+ }
1392
+ } else if (this.botDeviceType === 'faucet') {
1393
+ if (this.Faucet) {
1394
+ this.Faucet.Service.updateCharacteristic(this.hap.Characteristic.Active, this.hap.Characteristic.Active.INACTIVE);
1395
+ }
1396
+ } else if (this.botDeviceType === 'fan') {
1397
+ if (this.Fan) {
1398
+ this.Fan.Service.updateCharacteristic(this.hap.Characteristic.On, false);
1399
+ }
1400
+ } else if (this.botDeviceType === 'stateful') {
1401
+ if (this.StatefulProgrammableSwitch) {
1402
+ this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchEvent,
1403
+ this.hap.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS);
1404
+ this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState, 0);
1405
+ }
1406
+ } else if (this.botDeviceType === 'switch') {
1407
+ if (this.Switch) {
1408
+ this.Switch.Service.updateCharacteristic(this.hap.Characteristic.On, false);
1409
+ }
1410
+ } else {
1411
+ if (this.Outlet) {
1412
+ this.Outlet.Service.updateCharacteristic(this.hap.Characteristic.On, false);
1413
+ }
1551
1414
  }
1552
1415
  }
1553
1416
  }
1554
1417
 
1555
- errorLog(...log: any[]): void {
1556
- if (this.enablingDeviceLogging()) {
1557
- this.platform.log.error(String(...log));
1558
- }
1559
- }
1560
-
1561
- debugErrorLog(...log: any[]): void {
1562
- if (this.enablingDeviceLogging()) {
1563
- if (this.deviceLogging?.includes('debug')) {
1564
- this.platform.log.error('[DEBUG]', String(...log));
1418
+ async apiError(e: any): Promise<void> {
1419
+ if (this.botDeviceType === 'garagedoor') {
1420
+ if (this.GarageDoor) {
1421
+ this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.TargetDoorState, e);
1422
+ this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.CurrentDoorState, e);
1423
+ this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.ObstructionDetected, e);
1565
1424
  }
1566
- }
1567
- }
1568
-
1569
- debugLog(...log: any[]): void {
1570
- if (this.enablingDeviceLogging()) {
1571
- if (this.deviceLogging === 'debug') {
1572
- this.platform.log.info('[DEBUG]', String(...log));
1573
- } else {
1574
- this.platform.log.debug(String(...log));
1425
+ } else if (this.botDeviceType === 'door') {
1426
+ if (this.Door) {
1427
+ this.Door.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, e);
1428
+ this.Door.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, e);
1429
+ this.Door.Service.updateCharacteristic(this.hap.Characteristic.PositionState, e);
1430
+ }
1431
+ } else if (this.botDeviceType === 'window') {
1432
+ if (this.Window) {
1433
+ this.Window.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, e);
1434
+ this.Window.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, e);
1435
+ this.Window.Service.updateCharacteristic(this.hap.Characteristic.PositionState, e);
1436
+ }
1437
+ } else if (this.botDeviceType === 'windowcovering') {
1438
+ if (this.WindowCovering) {
1439
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, e);
1440
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, e);
1441
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, e);
1442
+ }
1443
+ } else if (this.botDeviceType === 'lock') {
1444
+ if (this.LockMechanism) {
1445
+ this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState, e);
1446
+ this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, e);
1447
+ }
1448
+ } else if (this.botDeviceType === 'faucet') {
1449
+ if (this.Faucet) {
1450
+ this.Faucet.Service.updateCharacteristic(this.hap.Characteristic.Active, e);
1451
+ }
1452
+ } else if (this.botDeviceType === 'fan') {
1453
+ if (this.Fan) {
1454
+ this.Fan.Service.updateCharacteristic(this.hap.Characteristic.On, e);
1455
+ }
1456
+ } else if (this.botDeviceType === 'stateful') {
1457
+ if (this.StatefulProgrammableSwitch) {
1458
+ this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchEvent, e);
1459
+ this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState, e);
1460
+ }
1461
+ } else if (this.botDeviceType === 'switch') {
1462
+ if (this.Switch) {
1463
+ this.Switch.Service.updateCharacteristic(this.hap.Characteristic.On, e);
1464
+ }
1465
+ } else {
1466
+ if (this.Outlet) {
1467
+ this.Outlet.Service.updateCharacteristic(this.hap.Characteristic.On, e);
1575
1468
  }
1576
1469
  }
1577
- }
1578
-
1579
- enablingDeviceLogging(): boolean {
1580
- return this.deviceLogging.includes('debug') || this.deviceLogging === 'standard';
1470
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e);
1471
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e);
1581
1472
  }
1582
1473
  }