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

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