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

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