@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,87 +1,43 @@
1
- import { request } from 'undici';
2
- import { sleep } from '../utils.js';
3
- import { interval, Subject } from 'rxjs';
4
- import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
5
- import { Devices } from '../settings.js';
6
- export class RobotVacuumCleaner {
1
+ /* Copyright(C) 2021-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
2
+ *
3
+ * robotvacuumcleaner.ts: @switchbot/homebridge-switchbot.
4
+ */
5
+ import { deviceBase } from './device.js';
6
+ import { Subject, interval, skipWhile } from 'rxjs';
7
+ import { debounceTime, take, tap } from 'rxjs/operators';
8
+ export class RobotVacuumCleaner extends deviceBase {
7
9
  platform;
8
- accessory;
9
- device;
10
- api;
11
- log;
12
- config;
13
- hap;
14
10
  // Services
15
- batteryService;
16
- robotVacuumCleanerService;
17
- // Characteristic Values
18
- On;
19
- Brightness;
20
- BatteryLevel;
21
- StatusLowBattery;
22
- FirmwareRevision;
23
- // OpenAPI Status
24
- OpenAPI_On;
25
- OpenAPI_BatteryLevel;
26
- OpenAPI_FirmwareRevision;
27
- // BLE Status
28
- BLE_On;
29
- // BLE Others
30
- BLE_IsConnected;
31
- // Config
32
- scanDuration;
33
- deviceLogging;
34
- deviceRefreshRate;
11
+ LightBulb;
12
+ Battery;
35
13
  // Updates
36
14
  robotVacuumCleanerUpdateInProgress;
37
15
  doRobotVacuumCleanerUpdate;
38
- // Connection
39
- OpenAPI;
40
- BLE;
41
16
  constructor(platform, accessory, device) {
17
+ super(platform, accessory, device);
42
18
  this.platform = platform;
43
- this.accessory = accessory;
44
- this.device = device;
45
- this.api = this.platform.api;
46
- this.log = this.platform.log;
47
- this.config = this.platform.config;
48
- this.hap = this.api.hap;
49
- // Connection
50
- this.BLE = this.device.connectionType === 'BLE' || this.device.connectionType === 'BLE/OpenAPI';
51
- this.OpenAPI = this.device.connectionType === 'OpenAPI' || this.device.connectionType === 'BLE/OpenAPI';
52
- // default placeholders
53
- this.deviceLogs(device);
54
- this.scan(device);
55
- this.refreshRate(device);
56
- this.deviceContext();
57
- this.deviceConfig(device);
58
19
  // this is subject we use to track when we need to POST changes to the SwitchBot API
59
20
  this.doRobotVacuumCleanerUpdate = new Subject();
60
21
  this.robotVacuumCleanerUpdateInProgress = false;
61
- // Retrieve initial values and updateHomekit
62
- this.refreshStatus();
63
- // set accessory information
64
- accessory
65
- .getService(this.hap.Service.AccessoryInformation)
66
- .setCharacteristic(this.hap.Characteristic.Manufacturer, 'SwitchBot')
67
- .setCharacteristic(this.hap.Characteristic.Model, this.model(device))
68
- .setCharacteristic(this.hap.Characteristic.SerialNumber, device.deviceId)
69
- .setCharacteristic(this.hap.Characteristic.FirmwareRevision, accessory.context.FirmwareRevision);
70
- // get the Lightbulb service if it exists, otherwise create a new Lightbulb service
71
- // you can create multiple services for each accessory
72
- const robotVacuumCleanerService = `${accessory.displayName} ${device.deviceType}`;
73
- (this.robotVacuumCleanerService = accessory.getService(this.hap.Service.Lightbulb)
74
- || accessory.addService(this.hap.Service.Lightbulb)), robotVacuumCleanerService;
75
- this.robotVacuumCleanerService.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
76
- if (!this.robotVacuumCleanerService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
77
- this.robotVacuumCleanerService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
78
- }
79
- // each service must implement at-minimum the "required characteristics" for the given service type
80
- // see https://developers.homebridge.io/#/service/Lightbulb
81
- // create handlers for required characteristics
82
- this.robotVacuumCleanerService.getCharacteristic(this.hap.Characteristic.On).onSet(this.OnSet.bind(this));
83
- // handle Brightness events using the Brightness characteristic
84
- this.robotVacuumCleanerService
22
+ // Initialize Lightbulb Service
23
+ accessory.context.LightBulb = accessory.context.LightBulb ?? {};
24
+ this.LightBulb = {
25
+ Name: accessory.context.LightBulb.Name ?? accessory.displayName,
26
+ Service: accessory.getService(this.hap.Service.Lightbulb) ?? accessory.addService(this.hap.Service.Lightbulb),
27
+ On: accessory.context.On ?? false,
28
+ Brightness: accessory.context.Brightness ?? 0,
29
+ };
30
+ accessory.context.LightBulb = this.LightBulb;
31
+ // Initialize LightBulb Characteristics
32
+ this.LightBulb.Service
33
+ .setCharacteristic(this.hap.Characteristic.Name, accessory.displayName)
34
+ .getCharacteristic(this.hap.Characteristic.On)
35
+ .onGet(() => {
36
+ return this.LightBulb.On;
37
+ })
38
+ .onSet(this.OnSet.bind(this));
39
+ // Initialize LightBulb Brightness Characteristic
40
+ this.LightBulb.Service
85
41
  .getCharacteristic(this.hap.Characteristic.Brightness)
86
42
  .setProps({
87
43
  minStep: 25,
@@ -91,17 +47,38 @@ export class RobotVacuumCleaner {
91
47
  validValueRanges: [0, 100],
92
48
  })
93
49
  .onGet(() => {
94
- return this.Brightness;
50
+ return this.LightBulb.Brightness;
95
51
  })
96
52
  .onSet(this.BrightnessSet.bind(this));
97
- // Battery Service
98
- const batteryService = `${accessory.displayName} Battery`;
99
- (this.batteryService = this.accessory.getService(this.hap.Service.Battery)
100
- || accessory.addService(this.hap.Service.Battery)), batteryService;
101
- this.batteryService.setCharacteristic(this.hap.Characteristic.Name, `${accessory.displayName} Battery`);
102
- if (!this.batteryService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
103
- this.batteryService.addCharacteristic(this.hap.Characteristic.ConfiguredName, `${accessory.displayName} Battery`);
104
- }
53
+ // Initialize Battery Service
54
+ accessory.context.Battery = accessory.context.Battery ?? {};
55
+ this.Battery = {
56
+ Name: accessory.context.Battery.Name ?? `${accessory.displayName} Battery`,
57
+ Service: accessory.getService(this.hap.Service.Battery) ?? accessory.addService(this.hap.Service.Battery),
58
+ BatteryLevel: accessory.context.BatteryLevel ?? 100,
59
+ StatusLowBattery: accessory.context.StatusLowBattery ?? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,
60
+ ChargingState: accessory.context.ChargingState ?? this.hap.Characteristic.ChargingState.NOT_CHARGING,
61
+ };
62
+ accessory.context.Battery = this.Battery;
63
+ // Initialize Battery Characteristics
64
+ this.Battery.Service
65
+ .setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name)
66
+ .getCharacteristic(this.hap.Characteristic.BatteryLevel)
67
+ .onGet(() => {
68
+ return this.Battery.BatteryLevel;
69
+ });
70
+ this.Battery.Service
71
+ .getCharacteristic(this.hap.Characteristic.StatusLowBattery)
72
+ .onGet(() => {
73
+ return this.Battery.StatusLowBattery;
74
+ });
75
+ this.Battery.Service
76
+ .getCharacteristic(this.hap.Characteristic.ChargingState)
77
+ .onGet(() => {
78
+ return this.Battery.ChargingState;
79
+ });
80
+ // Retrieve initial values and updateHomekit
81
+ this.refreshStatus();
105
82
  // Update Homekit
106
83
  this.updateHomeKitCharacteristics();
107
84
  // Start an update interval
@@ -111,101 +88,87 @@ export class RobotVacuumCleaner {
111
88
  await this.refreshStatus();
112
89
  });
113
90
  //regisiter webhook event handler
114
- if (this.device.webhook) {
115
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} is listening webhook.`);
116
- this.platform.webhookEventHandler[this.device.deviceId] = async (context) => {
117
- try {
118
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
119
- const { onlineStatus, battery } = context;
120
- const { On, BatteryLevel } = this;
121
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ` +
122
- '(onlineStatus, battery) = ' +
123
- `Webhook:(${onlineStatus}, ${battery}), ` +
124
- `current:(${On}, ${BatteryLevel})`);
125
- this.On = onlineStatus === 'online' ? true : false;
126
- this.BatteryLevel = battery;
127
- this.updateHomeKitCharacteristics();
128
- }
129
- catch (e) {
130
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
131
- + `failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
132
- }
133
- };
134
- }
91
+ this.registerWebhook(accessory, device);
135
92
  // Watch for Plug change events
136
93
  // We put in a debounce of 100ms so we don't make duplicate calls
137
94
  this.doRobotVacuumCleanerUpdate
138
95
  .pipe(tap(() => {
139
96
  this.robotVacuumCleanerUpdateInProgress = true;
140
- }), debounceTime(this.platform.config.options.pushRate * 1000))
97
+ }), debounceTime(this.devicePushRate * 1000))
141
98
  .subscribe(async () => {
142
99
  try {
143
- if (this.On !== this.accessory.context.On) {
144
- await this.pushChanges();
145
- }
146
- if (this.On && this.Brightness !== this.accessory.context.Brightness) {
147
- await this.openAPIpushBrightnessChanges();
148
- }
100
+ await this.pushChanges();
149
101
  }
150
102
  catch (e) {
151
103
  this.apiError(e);
152
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with ${this.device.connectionType} Connection,` +
153
- ` Error Message: ${JSON.stringify(e.message)}`);
104
+ this.errorLog(`${device.deviceType}: ${accessory.displayName} failed pushChanges with ${device.connectionType} Connection,`
105
+ + ` Error Message: ${JSON.stringify(e.message)}`);
154
106
  }
155
107
  this.robotVacuumCleanerUpdateInProgress = false;
156
108
  });
157
109
  }
158
- /**
159
- * Parse the device status from the SwitchBot api
160
- */
161
- async parseStatus() {
162
- if (!this.device.enableCloudService && this.OpenAPI) {
163
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} parseStatus enableCloudService: ${this.device.enableCloudService}`);
164
- /*} else if (this.BLE) {
165
- await this.BLEparseStatus();*/
166
- }
167
- else if (this.OpenAPI && this.platform.config.credentials?.token) {
168
- await this.openAPIparseStatus();
110
+ async BLEparseStatus(serviceData) {
111
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
112
+ // Battery
113
+ this.Battery.BatteryLevel = Number(serviceData.battery);
114
+ if (this.Battery.BatteryLevel < 10) {
115
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
169
116
  }
170
117
  else {
171
- await this.offlineOff();
172
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` + ` ${this.device.connectionType}, parseStatus will not happen.`);
118
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
173
119
  }
174
- }
175
- async BLEparseStatus() {
176
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
120
+ this.debugLog(`${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}, StatusLowBattery: ${this.Battery.StatusLowBattery}`);
177
121
  // State
178
- switch (this.BLE_On) {
122
+ switch (serviceData.state) {
179
123
  case 'on':
180
- this.On = true;
124
+ this.LightBulb.On = true;
181
125
  break;
182
126
  default:
183
- this.On = false;
127
+ this.LightBulb.On = false;
184
128
  }
185
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
129
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LightBulb.On}`);
186
130
  }
187
- async openAPIparseStatus() {
131
+ async openAPIparseStatus(deviceStatus) {
188
132
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
189
- switch (this.OpenAPI_On) {
133
+ switch (deviceStatus.body.power) {
190
134
  case 'on':
191
- this.On = true;
135
+ this.LightBulb.On = true;
192
136
  break;
193
137
  default:
194
- this.On = false;
138
+ this.LightBulb.On = false;
195
139
  }
196
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
197
- // Battery
198
- this.BatteryLevel = Number(this.OpenAPI_BatteryLevel);
199
- if (this.BatteryLevel < 15) {
200
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
140
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LightBulb.On}`);
141
+ // BatteryLevel
142
+ this.Battery.BatteryLevel = Number(deviceStatus.body.battery);
143
+ // StatusLowBattery
144
+ if (this.Battery.BatteryLevel < 10) {
145
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
201
146
  }
202
147
  else {
203
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
148
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
149
+ }
150
+ if (Number.isNaN(this.Battery.BatteryLevel)) {
151
+ this.Battery.BatteryLevel = 100;
152
+ }
153
+ // ChargingState
154
+ this.Battery.ChargingState = deviceStatus.body.workingStatus === 'Charging'
155
+ ? this.hap.Characteristic.ChargingState.CHARGING : this.hap.Characteristic.ChargingState.NOT_CHARGING;
156
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
157
+ + ` StatusLowBattery: ${this.Battery.StatusLowBattery}, ChargingState: ${this.Battery.ChargingState}`);
158
+ // Firmware Version
159
+ const version = deviceStatus.body.version?.toString();
160
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Firmware Version: ${version?.replace(/^V|-.*$/g, '')}`);
161
+ if (deviceStatus.body.version) {
162
+ const deviceVersion = version?.replace(/^V|-.*$/g, '') ?? '0.0.0';
163
+ this.accessory
164
+ .getService(this.hap.Service.AccessoryInformation)
165
+ .setCharacteristic(this.hap.Characteristic.HardwareRevision, deviceVersion)
166
+ .setCharacteristic(this.hap.Characteristic.FirmwareRevision, deviceVersion)
167
+ .getCharacteristic(this.hap.Characteristic.FirmwareRevision)
168
+ .updateValue(deviceVersion);
169
+ this.accessory.context.deviceVersion = deviceVersion;
170
+ this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceVersion: ${this.accessory.context.deviceVersion}`);
204
171
  }
205
- this.debugLog(`${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}, StatusLowBattery: ${this.StatusLowBattery}`);
206
- // FirmwareRevision
207
- this.FirmwareRevision = this.OpenAPI_FirmwareRevision;
208
- this.accessory.context.FirmwareRevision = this.FirmwareRevision;
209
172
  }
210
173
  /**
211
174
  * Asks the SwitchBot API for the latest device information
@@ -213,131 +176,88 @@ export class RobotVacuumCleaner {
213
176
  async refreshStatus() {
214
177
  if (!this.device.enableCloudService && this.OpenAPI) {
215
178
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} refreshStatus enableCloudService: ${this.device.enableCloudService}`);
216
- /*} else if (this.BLE) {
217
- await this.BLERefreshStatus();*/
179
+ }
180
+ else if (this.BLE) {
181
+ await this.BLERefreshStatus();
218
182
  }
219
183
  else if (this.OpenAPI && this.platform.config.credentials?.token) {
220
184
  await this.openAPIRefreshStatus();
221
185
  }
222
186
  else {
223
187
  await this.offlineOff();
224
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` +
225
- ` ${this.device.connectionType}, refreshStatus will not happen.`);
188
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
189
+ + ` ${this.device.connectionType}, refreshStatus will not happen.`);
226
190
  }
227
191
  }
228
192
  async BLERefreshStatus() {
229
193
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
230
- const switchbot = await this.platform.connectBLE();
231
- // Convert to BLE Address
232
- this.device.bleMac = this.device
233
- .deviceId.match(/.{1,2}/g)
234
- .join(':')
235
- .toLowerCase();
236
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
237
- this.getCustomBLEAddress(switchbot);
238
- // Start to monitor advertisement packets
239
- (async () => {
240
- await switchbot.startScan({
241
- model: '?',
242
- id: this.device.bleMac,
243
- });
244
- // Set an event handler
245
- switchbot.onadvertisement = (ad) => {
246
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
247
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.serviceData.model}`);
248
- if (this.device.bleMac === ad.address && ad.serviceData.model === '?') {
249
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
250
- this.BLE_On = ad.serviceData.state;
194
+ const switchbot = await this.switchbotBLE();
195
+ if (switchbot === undefined) {
196
+ await this.BLERefreshConnection(switchbot);
197
+ }
198
+ else {
199
+ // Start to monitor advertisement packets
200
+ (async () => {
201
+ // Start to monitor advertisement packets
202
+ const serviceData = await this.monitorAdvertisementPackets(switchbot);
203
+ // Update HomeKit
204
+ if (serviceData.model !== '' && serviceData.modelName !== '') {
205
+ await this.BLEparseStatus(serviceData);
206
+ await this.updateHomeKitCharacteristics();
251
207
  }
252
208
  else {
253
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
254
- }
255
- };
256
- // Wait 1 seconds
257
- await switchbot.wait(this.scanDuration * 1000);
258
- // Stop to monitor
259
- await switchbot.stopScan();
260
- // Update HomeKit
261
- await this.BLEparseStatus();
262
- await this.updateHomeKitCharacteristics();
263
- })();
264
- /*if (switchbot !== false) {
265
- switchbot
266
- .startScan({
267
- model: this.BLEmodel(),
268
- id: this.device.bleMac,
269
- })
270
- .then(async () => {
271
- // Set an event handler
272
- switchbot.onadvertisement = async (ad: ad) => {
273
- this.debugLog(
274
- `${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac},` +
275
- ` BLE Address Found: ${ad.address}`,
276
- );
277
- this.BLE_On = ad.serviceData.state;
278
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
279
- this.debugLog(
280
- `${this.device.deviceType}: ${this.accessory.displayName} state: ${ad.serviceData.state}, ` +
281
- `delay: ${ad.serviceData.delay}, timer: ${ad.serviceData.timer}, syncUtcTime: ${ad.serviceData.syncUtcTime} ` +
282
- `wifiRssi: ${ad.serviceData.wifiRssi}, overload: ${ad.serviceData.overload}, currentPower: ${ad.serviceData.currentPower}`,
283
- );
284
-
285
- if (ad.serviceData) {
286
- this.BLE_IsConnected = true;
287
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.BLE_IsConnected}`);
288
- await this.stopScanning(switchbot);
289
- } else {
290
- this.BLE_IsConnected = false;
291
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.BLE_IsConnected}`);
209
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed to get serviceData, serviceData: ${serviceData}`);
210
+ await this.BLERefreshConnection(switchbot);
292
211
  }
293
- };
294
- // Wait
295
- return await sleep(this.scanDuration * 1000);
296
- })
297
- .then(async () => {
298
- // Stop to monitor
299
- await this.stopScanning(switchbot);
300
- })
301
- .catch(async (e: any) => {
302
- this.apiError(e);
303
- this.errorLog(
304
- `${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}` +
305
- ` Connection, Error Message: ${JSON.stringify(e.message)}`,
306
- );
307
- await this.BLERefreshConnection(switchbot);
308
- });
309
- } else {
310
- await this.BLERefreshConnection(switchbot);
311
- }*/
212
+ })();
213
+ }
312
214
  }
313
215
  async openAPIRefreshStatus() {
314
216
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
315
217
  try {
316
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/status`, {
317
- headers: this.platform.generateHeaders(),
318
- });
319
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
218
+ const { body, statusCode } = await this.deviceRefreshStatus();
320
219
  const deviceStatus = await body.json();
321
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
322
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
220
+ await this.refreshStatusCodes(statusCode, deviceStatus);
221
+ ;
323
222
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
324
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
325
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
326
- this.OpenAPI_On = deviceStatus.body.power;
327
- this.OpenAPI_BatteryLevel = deviceStatus.body.battery;
328
- this.OpenAPI_FirmwareRevision = deviceStatus.body.version;
329
- this.openAPIparseStatus();
330
- this.updateHomeKitCharacteristics();
223
+ await this.successfulRefreshStatus(statusCode, deviceStatus);
224
+ await this.openAPIparseStatus(deviceStatus);
225
+ await this.updateHomeKitCharacteristics();
331
226
  }
332
227
  else {
333
- this.statusCode(statusCode);
334
- this.statusCode(deviceStatus.statusCode);
228
+ await this.statusCodes(statusCode, deviceStatus);
335
229
  }
336
230
  }
337
231
  catch (e) {
338
232
  this.apiError(e);
339
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}` +
340
- ` Connection, Error Message: ${JSON.stringify(e.message)}`);
233
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
234
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
235
+ }
236
+ }
237
+ async registerWebhook(accessory, device) {
238
+ if (device.webhook) {
239
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} is listening webhook.`);
240
+ this.platform.webhookEventHandler[device.deviceId] = async (context) => {
241
+ try {
242
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
243
+ const { onlineStatus, battery, workingStatus } = context;
244
+ const { On } = this.LightBulb;
245
+ const { BatteryLevel, ChargingState } = this.Battery;
246
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} (onlineStatus, battery, workingStatus) = `
247
+ + `Webhook: (${onlineStatus}, ${battery}, ${workingStatus}), current: (${On}, ${BatteryLevel}, ${ChargingState})`);
248
+ this.LightBulb.On = onlineStatus === 'online' ? true : false;
249
+ this.Battery.ChargingState = workingStatus === 'Charging'
250
+ ? this.hap.Characteristic.ChargingState.CHARGING : this.hap.Characteristic.ChargingState.NOT_CHARGING;
251
+ this.Battery.BatteryLevel = battery;
252
+ this.updateHomeKitCharacteristics();
253
+ }
254
+ catch (e) {
255
+ this.errorLog(`${device.deviceType}: ${accessory.displayName} failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
256
+ }
257
+ };
258
+ }
259
+ else {
260
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} is not listening webhook.`);
341
261
  }
342
262
  }
343
263
  /**
@@ -351,15 +271,17 @@ export class RobotVacuumCleaner {
351
271
  async pushChanges() {
352
272
  if (!this.device.enableCloudService && this.OpenAPI) {
353
273
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} pushChanges enableCloudService: ${this.device.enableCloudService}`);
354
- /*} else if (this.BLE) {
355
- await this.BLEpushChanges();*/
274
+ }
275
+ else if (this.BLE) {
276
+ await this.BLEpushChanges();
356
277
  }
357
278
  else if (this.OpenAPI && this.platform.config.credentials?.token) {
358
279
  await this.openAPIpushChanges();
359
280
  }
360
281
  else {
361
282
  await this.offlineOff();
362
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` + ` ${this.device.connectionType}, pushChanges will not happen.`);
283
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
284
+ + ` ${this.device.connectionType}, pushChanges will not happen.`);
363
285
  }
364
286
  // Refresh the status from the API
365
287
  interval(15000)
@@ -371,26 +293,23 @@ export class RobotVacuumCleaner {
371
293
  }
372
294
  async BLEpushChanges() {
373
295
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
374
- if (this.On !== this.accessory.context.On) {
375
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges On: ${this.On} OnCached: ${this.accessory.context.On}`);
296
+ if (this.LightBulb.On !== this.accessory.context.On) {
297
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`
298
+ + ` On: ${this.LightBulb.On} OnCached: ${this.accessory.context.On}`);
376
299
  const switchbot = await this.platform.connectBLE();
377
300
  // Convert to BLE Address
378
- this.device.bleMac = this.device
379
- .deviceId.match(/.{1,2}/g)
380
- .join(':')
381
- .toLowerCase();
382
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
301
+ await this.convertBLEAddress();
383
302
  switchbot
384
303
  .discover({
385
304
  model: '?',
386
305
  id: this.device.bleMac,
387
306
  })
388
307
  .then(async (device_list) => {
389
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
390
- return await this.retry({
391
- max: this.maxRetry(),
308
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LightBulb.On}`);
309
+ return await this.retryBLE({
310
+ max: await this.maxRetryBLE(),
392
311
  fn: async () => {
393
- if (this.On) {
312
+ if (this.LightBulb.On) {
394
313
  return await device_list[0].turnOn({ id: this.device.bleMac });
395
314
  }
396
315
  else {
@@ -401,49 +320,36 @@ export class RobotVacuumCleaner {
401
320
  })
402
321
  .then(() => {
403
322
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
404
- this.On = false;
323
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
324
+ + `On: ${this.LightBulb.On} sent over BLE, sent successfully`);
325
+ this.LightBulb.On = false;
405
326
  })
406
327
  .catch(async (e) => {
407
328
  this.apiError(e);
408
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}` +
409
- ` Connection, Error Message: ${JSON.stringify(e.message)}`);
329
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
330
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
410
331
  await this.BLEPushConnection();
411
332
  });
412
333
  }
413
334
  else {
414
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges.` + `On: ${this.On}, ` + `OnCached: ${this.accessory.context.On}`);
335
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges,`
336
+ + ` On: ${this.LightBulb.On}, OnCached: ${this.accessory.context.On}`);
415
337
  }
416
338
  }
417
339
  async openAPIpushChanges() {
418
340
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
419
- if (this.On !== this.accessory.context.On) {
420
- let command = '';
421
- if (this.On) {
422
- command = 'turnOn';
423
- }
424
- else {
425
- command = 'turnOff';
426
- }
427
- const bodyChange = JSON.stringify({
428
- command: `${command}`,
429
- parameter: 'default',
430
- commandType: 'command',
431
- });
341
+ if (this.LightBulb.On !== this.accessory.context.On) {
342
+ const bodyChange = await this.commands();
432
343
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
433
344
  try {
434
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/commands`, {
435
- body: bodyChange,
436
- method: 'POST',
437
- headers: this.platform.generateHeaders(),
438
- });
439
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
345
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
440
346
  const deviceStatus = await body.json();
441
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
442
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
443
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
347
+ await this.pushStatusCodes(statusCode, deviceStatus);
444
348
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
445
349
  this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
446
350
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
351
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
352
+ + `request to SwitchBot API, body: ${JSON.stringify(JSON.parse(bodyChange))} sent successfully`);
447
353
  }
448
354
  else {
449
355
  this.statusCode(statusCode);
@@ -452,48 +358,43 @@ export class RobotVacuumCleaner {
452
358
  }
453
359
  catch (e) {
454
360
  this.apiError(e);
455
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}` +
456
- ` Connection, Error Message: ${JSON.stringify(e.message)}`);
361
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
362
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
457
363
  }
458
364
  }
459
365
  else {
460
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges.` +
461
- `On: ${this.On}, ` +
462
- `OnCached: ${this.accessory.context.On}`);
366
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges, On: ${this.LightBulb.On}, `
367
+ + `OnCached: ${this.accessory.context.On}`);
463
368
  }
464
369
  }
465
370
  async openAPIpushBrightnessChanges() {
466
371
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushBrightnessChanges`);
467
- const body = await this.brightnessCommands();
468
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${body},`);
372
+ const bodyChange = await this.brightnessCommands();
373
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
469
374
  try {
470
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/commands`, {
471
- method: 'POST',
472
- headers: this.platform.generateHeaders(),
473
- });
474
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
375
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange);
475
376
  const deviceStatus = await body.json();
476
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
477
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
377
+ await this.refreshStatusCodes(statusCode, deviceStatus);
378
+ ;
478
379
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
479
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
480
- + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
380
+ await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
381
+ await this.updateHomeKitCharacteristics();
481
382
  }
482
383
  else {
483
- this.statusCode(statusCode);
484
- this.statusCode(deviceStatus.statusCode);
384
+ await this.statusCode(statusCode);
385
+ await this.statusCode(deviceStatus.statusCode);
485
386
  }
486
387
  }
487
388
  catch (e) {
488
389
  this.apiError(e);
489
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}` +
490
- ` Connection, Error Message: ${JSON.stringify(e.message)}`);
390
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
391
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
491
392
  }
492
393
  }
493
- commands() {
394
+ async commands() {
494
395
  let command;
495
396
  let parameter;
496
- if (this.On) {
397
+ if (this.LightBulb.On) {
497
398
  command = 'start';
498
399
  parameter = 'default';
499
400
  }
@@ -508,22 +409,22 @@ export class RobotVacuumCleaner {
508
409
  });
509
410
  return body;
510
411
  }
511
- brightnessCommands() {
412
+ async brightnessCommands() {
512
413
  let command;
513
414
  let parameter;
514
- if (this.Brightness === 25) {
415
+ if (this.LightBulb.Brightness === 25) {
515
416
  command = 'PowLevel';
516
417
  parameter = '0';
517
418
  }
518
- else if (this.Brightness === 50) {
419
+ else if (this.LightBulb.Brightness === 50) {
519
420
  command = 'PowLevel';
520
421
  parameter = '1';
521
422
  }
522
- else if (this.Brightness === 75) {
423
+ else if (this.LightBulb.Brightness === 75) {
523
424
  command = 'PowLevel';
524
425
  parameter = '2';
525
426
  }
526
- else if (this.Brightness === 100) {
427
+ else if (this.LightBulb.Brightness === 100) {
527
428
  command = 'PowLevel';
528
429
  parameter = '3';
529
430
  }
@@ -531,105 +432,89 @@ export class RobotVacuumCleaner {
531
432
  command = 'dock';
532
433
  parameter = 'default';
533
434
  }
534
- const body = JSON.stringify({
435
+ const bodyChange = JSON.stringify({
535
436
  command: `${command}`,
536
437
  parameter: `${parameter}`,
537
438
  commandType: 'command',
538
439
  });
539
- return body;
440
+ return bodyChange;
540
441
  }
541
442
  /**
542
443
  * Handle requests to set the value of the "On" characteristic
543
444
  */
544
445
  async OnSet(value) {
545
- if (this.On === this.accessory.context.On) {
446
+ if (this.LightBulb.On === this.accessory.context.On) {
546
447
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set On: ${value}`);
547
448
  }
548
449
  else {
549
450
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set On: ${value}`);
550
451
  }
551
- this.On = value;
452
+ this.LightBulb.On = value;
552
453
  this.doRobotVacuumCleanerUpdate.next();
553
454
  }
554
455
  /**
555
456
  * Handle requests to set the value of the "Brightness" characteristic
556
457
  */
557
458
  async BrightnessSet(value) {
558
- if (this.Brightness === this.accessory.context.Brightness) {
459
+ if (this.LightBulb.Brightness === this.accessory.context.Brightness) {
559
460
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set Brightness: ${value}`);
560
461
  }
561
- else if (this.On) {
462
+ else if (this.LightBulb.On) {
562
463
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Brightness: ${value}`);
563
464
  }
564
465
  else {
565
466
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Brightness: ${value}`);
566
467
  }
567
- this.Brightness = value;
468
+ this.LightBulb.Brightness = value;
568
469
  this.doRobotVacuumCleanerUpdate.next();
569
470
  }
570
471
  async updateHomeKitCharacteristics() {
571
472
  // On
572
- if (this.On === undefined) {
573
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
473
+ if (this.LightBulb.On === undefined) {
474
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LightBulb.On}`);
574
475
  }
575
476
  else {
576
- this.accessory.context.On = this.On;
577
- this.robotVacuumCleanerService.updateCharacteristic(this.hap.Characteristic.On, this.On);
578
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
477
+ this.accessory.context.On = this.LightBulb.On;
478
+ this.LightBulb.Service.updateCharacteristic(this.hap.Characteristic.On, this.LightBulb.On);
479
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.LightBulb.On}`);
579
480
  }
580
481
  // Brightness
581
- if (this.Brightness === undefined) {
582
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Brightness: ${this.Brightness}`);
482
+ if (this.LightBulb.Brightness === undefined) {
483
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Brightness: ${this.LightBulb.Brightness}`);
583
484
  }
584
485
  else {
585
- this.accessory.context.Brightness = this.Brightness;
586
- this.robotVacuumCleanerService.updateCharacteristic(this.hap.Characteristic.Brightness, this.Brightness);
587
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Brightness: ${this.Brightness}`);
486
+ this.accessory.context.Brightness = this.LightBulb.Brightness;
487
+ this.LightBulb.Service.updateCharacteristic(this.hap.Characteristic.Brightness, this.LightBulb.Brightness);
488
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Brightness: ${this.LightBulb.Brightness}`);
588
489
  }
589
490
  // BatteryLevel
590
- if (this.BatteryLevel === undefined) {
591
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
491
+ if (this.Battery.BatteryLevel === undefined) {
492
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}`);
592
493
  }
593
494
  else {
594
- this.accessory.context.BatteryLevel = this.BatteryLevel;
595
- this.batteryService?.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.BatteryLevel);
596
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
495
+ this.accessory.context.BatteryLevel = this.Battery.BatteryLevel;
496
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel);
497
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.Battery.BatteryLevel}`);
597
498
  }
598
499
  // StatusLowBattery
599
- if (this.StatusLowBattery === undefined) {
600
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
500
+ if (this.Battery.StatusLowBattery === undefined) {
501
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.Battery.StatusLowBattery}`);
601
502
  }
602
503
  else {
603
- this.accessory.context.StatusLowBattery = this.StatusLowBattery;
604
- this.batteryService?.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.StatusLowBattery);
605
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
504
+ this.accessory.context.StatusLowBattery = this.Battery.StatusLowBattery;
505
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery);
506
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
507
+ + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
606
508
  }
607
- }
608
- async stopScanning(switchbot) {
609
- switchbot.stopScan();
610
- if (this.BLE_IsConnected) {
611
- await this.BLEparseStatus();
612
- await this.updateHomeKitCharacteristics();
509
+ // ChargingState
510
+ if (this.Battery.ChargingState === undefined) {
511
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ChargingState: ${this.Battery.ChargingState}`);
613
512
  }
614
513
  else {
615
- await this.BLERefreshConnection(switchbot);
616
- }
617
- }
618
- async getCustomBLEAddress(switchbot) {
619
- if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
620
- (async () => {
621
- // Start to monitor advertisement packets
622
- await switchbot.startScan({
623
- model: '?',
624
- });
625
- // Set an event handler
626
- switchbot.onadvertisement = (ad) => {
627
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${JSON.stringify(ad, null, ' ')}`);
628
- };
629
- await sleep(10000);
630
- // Stop to monitor
631
- switchbot.stopScan();
632
- })();
514
+ this.accessory.context.ChargingState = this.Battery.ChargingState;
515
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.ChargingState, this.Battery.ChargingState);
516
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
517
+ + ` ChargingState: ${this.Battery.ChargingState}`);
633
518
  }
634
519
  }
635
520
  async BLEPushConnection() {
@@ -646,255 +531,13 @@ export class RobotVacuumCleaner {
646
531
  await this.openAPIRefreshStatus();
647
532
  }
648
533
  }
649
- async retry({ max, fn }) {
650
- return fn().catch(async (e) => {
651
- if (max === 0) {
652
- throw e;
653
- }
654
- this.infoLog(e);
655
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Retrying`);
656
- await sleep(1000);
657
- return this.retry({ max: max - 1, fn });
658
- });
659
- }
660
- maxRetry() {
661
- if (this.device.maxRetry) {
662
- return this.device.maxRetry;
663
- }
664
- else {
665
- return 5;
666
- }
667
- }
668
- model(device) {
669
- let model;
670
- if (device.deviceType === 'Robot Vacuum Cleaner S1 Plus') {
671
- model = 'W3011010';
672
- }
673
- else if (device.deviceType === 'Robot Vacuum Cleaner S1') {
674
- model = 'W3011000';
675
- }
676
- else {
677
- model = 'N/A';
678
- }
679
- return model;
680
- }
681
- async scan(device) {
682
- if (device.scanDuration) {
683
- this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
684
- if (this.BLE) {
685
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
686
- }
687
- }
688
- else {
689
- this.scanDuration = this.accessory.context.scanDuration = 1;
690
- if (this.BLE) {
691
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
692
- }
693
- }
694
- }
695
- async statusCode(statusCode) {
696
- switch (statusCode) {
697
- case 151:
698
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this deviceType, statusCode: ${statusCode}`);
699
- break;
700
- case 152:
701
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found, statusCode: ${statusCode}`);
702
- break;
703
- case 160:
704
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported, statusCode: ${statusCode}`);
705
- break;
706
- case 161:
707
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline, statusCode: ${statusCode}`);
708
- this.offlineOff();
709
- break;
710
- case 171:
711
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Hub Device is offline, statusCode: ${statusCode}. ` +
712
- `Hub: ${this.device.hubDeviceId}`);
713
- this.offlineOff();
714
- break;
715
- case 190:
716
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
717
- ` Or command format is invalid, statusCode: ${statusCode}`);
718
- break;
719
- case 100:
720
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent, statusCode: ${statusCode}`);
721
- break;
722
- case 200:
723
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Request successful, statusCode: ${statusCode}`);
724
- break;
725
- case 400:
726
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Bad Request, The client has issued an invalid request. `
727
- + `This is commonly used to specify validation errors in a request payload, statusCode: ${statusCode}`);
728
- break;
729
- case 401:
730
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unauthorized, Authorization for the API is required, `
731
- + `but the request has not been authenticated, statusCode: ${statusCode}`);
732
- break;
733
- case 403:
734
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Forbidden, The request has been authenticated but does not `
735
- + `have appropriate permissions, or a requested resource is not found, statusCode: ${statusCode}`);
736
- break;
737
- case 404:
738
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Not Found, Specifies the requested path does not exist, `
739
- + `statusCode: ${statusCode}`);
740
- break;
741
- case 406:
742
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Not Acceptable, The client has requested a MIME type via `
743
- + `the Accept header for a value not supported by the server, statusCode: ${statusCode}`);
744
- break;
745
- case 415:
746
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unsupported Media Type, The client has defined a contentType `
747
- + `header that is not supported by the server, statusCode: ${statusCode}`);
748
- break;
749
- case 422:
750
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unprocessable Entity, The client has made a valid request, `
751
- + `but the server cannot process it. This is often used for APIs for which certain limits have been exceeded, statusCode: ${statusCode}`);
752
- break;
753
- case 429:
754
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Too Many Requests, The client has exceeded the number of `
755
- + `requests allowed for a given time window, statusCode: ${statusCode}`);
756
- break;
757
- case 500:
758
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Internal Server Error, An unexpected error on the SmartThings `
759
- + `servers has occurred. These errors should be rare, statusCode: ${statusCode}`);
760
- break;
761
- default:
762
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode: ` +
763
- `${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`);
764
- }
765
- }
766
534
  async offlineOff() {
767
535
  if (this.device.offline) {
768
- await this.deviceContext();
769
- await this.updateHomeKitCharacteristics();
536
+ this.LightBulb.Service.updateCharacteristic(this.hap.Characteristic.On, false);
770
537
  }
771
538
  }
772
539
  async apiError(e) {
773
- this.robotVacuumCleanerService.updateCharacteristic(this.hap.Characteristic.On, e);
774
- }
775
- async deviceContext() {
776
- if (this.On === undefined) {
777
- this.On = false;
778
- }
779
- else {
780
- this.On = this.accessory.context.On;
781
- }
782
- if (this.Brightness === undefined) {
783
- this.Brightness = 0;
784
- }
785
- else {
786
- this.Brightness = this.accessory.context.Brightness;
787
- }
788
- if (this.FirmwareRevision === undefined) {
789
- this.FirmwareRevision = this.platform.version;
790
- this.accessory.context.FirmwareRevision = this.FirmwareRevision;
791
- }
792
- }
793
- async refreshRate(device) {
794
- if (device.refreshRate) {
795
- this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
796
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
797
- }
798
- else if (this.platform.config.options.refreshRate) {
799
- this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options.refreshRate;
800
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
801
- }
802
- }
803
- async deviceConfig(device) {
804
- let config = {};
805
- if (device.plug) {
806
- config = device.plug;
807
- }
808
- if (device.connectionType !== undefined) {
809
- config['connectionType'] = device.connectionType;
810
- }
811
- if (device.external !== undefined) {
812
- config['external'] = device.external;
813
- }
814
- if (device.logging !== undefined) {
815
- config['logging'] = device.logging;
816
- }
817
- if (device.refreshRate !== undefined) {
818
- config['refreshRate'] = device.refreshRate;
819
- }
820
- if (device.scanDuration !== undefined) {
821
- config['scanDuration'] = device.scanDuration;
822
- }
823
- if (device.offline !== undefined) {
824
- config['offline'] = device.offline;
825
- }
826
- if (device.maxRetry !== undefined) {
827
- config['maxRetry'] = device.maxRetry;
828
- }
829
- if (device.webhook !== undefined) {
830
- config['webhook'] = device.webhook;
831
- }
832
- if (Object.entries(config).length !== 0) {
833
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
834
- }
835
- }
836
- async deviceLogs(device) {
837
- if (this.platform.debugMode) {
838
- this.deviceLogging = this.accessory.context.logging = 'debugMode';
839
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
840
- }
841
- else if (device.logging) {
842
- this.deviceLogging = this.accessory.context.logging = device.logging;
843
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
844
- }
845
- else if (this.platform.config.options?.logging) {
846
- this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
847
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
848
- }
849
- else {
850
- this.deviceLogging = this.accessory.context.logging = 'standard';
851
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
852
- }
853
- }
854
- /**
855
- * Logging for Device
856
- */
857
- infoLog(...log) {
858
- if (this.enablingDeviceLogging()) {
859
- this.platform.log.info(String(...log));
860
- }
861
- }
862
- warnLog(...log) {
863
- if (this.enablingDeviceLogging()) {
864
- this.platform.log.warn(String(...log));
865
- }
866
- }
867
- debugWarnLog(...log) {
868
- if (this.enablingDeviceLogging()) {
869
- if (this.deviceLogging?.includes('debug')) {
870
- this.platform.log.warn('[DEBUG]', String(...log));
871
- }
872
- }
873
- }
874
- errorLog(...log) {
875
- if (this.enablingDeviceLogging()) {
876
- this.platform.log.error(String(...log));
877
- }
878
- }
879
- debugErrorLog(...log) {
880
- if (this.enablingDeviceLogging()) {
881
- if (this.deviceLogging?.includes('debug')) {
882
- this.platform.log.error('[DEBUG]', String(...log));
883
- }
884
- }
885
- }
886
- debugLog(...log) {
887
- if (this.enablingDeviceLogging()) {
888
- if (this.deviceLogging === 'debug') {
889
- this.platform.log.info('[DEBUG]', String(...log));
890
- }
891
- else {
892
- this.platform.log.debug(String(...log));
893
- }
894
- }
895
- }
896
- enablingDeviceLogging() {
897
- return this.deviceLogging.includes('debug') || this.deviceLogging === 'standard';
540
+ this.LightBulb.Service.updateCharacteristic(this.hap.Characteristic.On, e);
898
541
  }
899
542
  }
900
543
  //# sourceMappingURL=robotvacuumcleaner.js.map