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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/.vscode/settings.json +4 -1
  2. package/CHANGELOG.md +4 -1
  3. package/config.schema.json +170 -26
  4. package/dist/device/blindtilt.d.ts +21 -96
  5. package/dist/device/blindtilt.d.ts.map +1 -1
  6. package/dist/device/blindtilt.js +439 -817
  7. package/dist/device/blindtilt.js.map +1 -1
  8. package/dist/device/bot.d.ts +27 -72
  9. package/dist/device/bot.d.ts.map +1 -1
  10. package/dist/device/bot.js +835 -865
  11. package/dist/device/bot.js.map +1 -1
  12. package/dist/device/ceilinglight.d.ts +15 -69
  13. package/dist/device/ceilinglight.d.ts.map +1 -1
  14. package/dist/device/ceilinglight.js +287 -653
  15. package/dist/device/ceilinglight.js.map +1 -1
  16. package/dist/device/colorbulb.d.ts +15 -76
  17. package/dist/device/colorbulb.d.ts.map +1 -1
  18. package/dist/device/colorbulb.js +354 -732
  19. package/dist/device/colorbulb.js.map +1 -1
  20. package/dist/device/contact.d.ts +14 -66
  21. package/dist/device/contact.d.ts.map +1 -1
  22. package/dist/device/contact.js +268 -576
  23. package/dist/device/contact.js.map +1 -1
  24. package/dist/device/curtain.d.ts +18 -89
  25. package/dist/device/curtain.d.ts.map +1 -1
  26. package/dist/device/curtain.js +431 -851
  27. package/dist/device/curtain.js.map +1 -1
  28. package/dist/device/device.d.ts +60 -0
  29. package/dist/device/device.d.ts.map +1 -0
  30. package/dist/device/device.js +739 -0
  31. package/dist/device/device.js.map +1 -0
  32. package/dist/device/fan.d.ts +63 -0
  33. package/dist/device/fan.d.ts.map +1 -0
  34. package/dist/device/fan.js +698 -0
  35. package/dist/device/fan.js.map +1 -0
  36. package/dist/device/hub.d.ts +15 -60
  37. package/dist/device/hub.d.ts.map +1 -1
  38. package/dist/device/hub.js +257 -631
  39. package/dist/device/hub.js.map +1 -1
  40. package/dist/device/humidifier.d.ts +11 -66
  41. package/dist/device/humidifier.d.ts.map +1 -1
  42. package/dist/device/humidifier.js +266 -629
  43. package/dist/device/humidifier.js.map +1 -1
  44. package/dist/device/iosensor.d.ts +12 -64
  45. package/dist/device/iosensor.d.ts.map +1 -1
  46. package/dist/device/iosensor.js +215 -615
  47. package/dist/device/iosensor.js.map +1 -1
  48. package/dist/device/lightstrip.d.ts +12 -70
  49. package/dist/device/lightstrip.d.ts.map +1 -1
  50. package/dist/device/lightstrip.js +336 -645
  51. package/dist/device/lightstrip.js.map +1 -1
  52. package/dist/device/lock.d.ts +17 -63
  53. package/dist/device/lock.d.ts.map +1 -1
  54. package/dist/device/lock.js +290 -595
  55. package/dist/device/lock.js.map +1 -1
  56. package/dist/device/meter.d.ts +15 -64
  57. package/dist/device/meter.d.ts.map +1 -1
  58. package/dist/device/meter.js +211 -608
  59. package/dist/device/meter.js.map +1 -1
  60. package/dist/device/meterplus.d.ts +15 -65
  61. package/dist/device/meterplus.d.ts.map +1 -1
  62. package/dist/device/meterplus.js +205 -615
  63. package/dist/device/meterplus.js.map +1 -1
  64. package/dist/device/motion.d.ts +12 -69
  65. package/dist/device/motion.d.ts.map +1 -1
  66. package/dist/device/motion.js +202 -563
  67. package/dist/device/motion.js.map +1 -1
  68. package/dist/device/plug.d.ts +10 -57
  69. package/dist/device/plug.d.ts.map +1 -1
  70. package/dist/device/plug.js +125 -484
  71. package/dist/device/plug.js.map +1 -1
  72. package/dist/device/robotvacuumcleaner.d.ts +13 -63
  73. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  74. package/dist/device/robotvacuumcleaner.js +233 -549
  75. package/dist/device/robotvacuumcleaner.js.map +1 -1
  76. package/dist/device/waterdetector.d.ts +11 -63
  77. package/dist/device/waterdetector.d.ts.map +1 -1
  78. package/dist/device/waterdetector.js +170 -493
  79. package/dist/device/waterdetector.js.map +1 -1
  80. package/dist/homebridge-ui/public/index.html +22 -16
  81. package/dist/homebridge-ui/server.js +1 -1
  82. package/dist/homebridge-ui/server.js.map +1 -1
  83. package/dist/index.d.ts +1 -1
  84. package/dist/index.d.ts.map +1 -1
  85. package/dist/index.js +2 -2
  86. package/dist/index.js.map +1 -1
  87. package/dist/irdevice/airconditioner.d.ts +10 -50
  88. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  89. package/dist/irdevice/airconditioner.js +340 -468
  90. package/dist/irdevice/airconditioner.js.map +1 -1
  91. package/dist/irdevice/airpurifier.d.ts +8 -39
  92. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  93. package/dist/irdevice/airpurifier.js +105 -319
  94. package/dist/irdevice/airpurifier.js.map +1 -1
  95. package/dist/irdevice/camera.d.ts +7 -36
  96. package/dist/irdevice/camera.d.ts.map +1 -1
  97. package/dist/irdevice/camera.js +44 -285
  98. package/dist/irdevice/camera.js.map +1 -1
  99. package/dist/irdevice/fan.d.ts +7 -43
  100. package/dist/irdevice/fan.d.ts.map +1 -1
  101. package/dist/irdevice/fan.js +92 -350
  102. package/dist/irdevice/fan.js.map +1 -1
  103. package/dist/irdevice/irdevice.d.ts +40 -0
  104. package/dist/irdevice/irdevice.d.ts.map +1 -0
  105. package/dist/irdevice/irdevice.js +369 -0
  106. package/dist/irdevice/irdevice.js.map +1 -0
  107. package/dist/irdevice/light.d.ts +12 -45
  108. package/dist/irdevice/light.d.ts.map +1 -1
  109. package/dist/irdevice/light.js +118 -362
  110. package/dist/irdevice/light.js.map +1 -1
  111. package/dist/irdevice/other.d.ts +19 -48
  112. package/dist/irdevice/other.d.ts.map +1 -1
  113. package/dist/irdevice/other.js +438 -570
  114. package/dist/irdevice/other.js.map +1 -1
  115. package/dist/irdevice/tv.d.ts +8 -40
  116. package/dist/irdevice/tv.d.ts.map +1 -1
  117. package/dist/irdevice/tv.js +91 -339
  118. package/dist/irdevice/tv.js.map +1 -1
  119. package/dist/irdevice/vacuumcleaner.d.ts +7 -36
  120. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  121. package/dist/irdevice/vacuumcleaner.js +45 -285
  122. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  123. package/dist/irdevice/waterheater.d.ts +7 -36
  124. package/dist/irdevice/waterheater.d.ts.map +1 -1
  125. package/dist/irdevice/waterheater.js +47 -291
  126. package/dist/irdevice/waterheater.js.map +1 -1
  127. package/dist/platform.d.ts +22 -8
  128. package/dist/platform.d.ts.map +1 -1
  129. package/dist/platform.js +342 -191
  130. package/dist/platform.js.map +1 -1
  131. package/dist/settings.d.ts +64 -17
  132. package/dist/settings.d.ts.map +1 -1
  133. package/dist/settings.js +16 -552
  134. package/dist/settings.js.map +1 -1
  135. package/dist/utils.d.ts +77 -0
  136. package/dist/utils.d.ts.map +1 -1
  137. package/dist/utils.js +638 -1
  138. package/dist/utils.js.map +1 -1
  139. package/eslint.config.js +96 -0
  140. package/package.json +20 -16
  141. package/src/custom.d.ts +2 -1
  142. package/src/device/blindtilt.ts +472 -888
  143. package/src/device/bot.ts +893 -968
  144. package/src/device/ceilinglight.ts +304 -709
  145. package/src/device/colorbulb.ts +370 -803
  146. package/src/device/contact.ts +301 -611
  147. package/src/device/curtain.ts +460 -908
  148. package/src/device/device.ts +755 -0
  149. package/src/device/fan.ts +749 -0
  150. package/src/device/hub.ts +294 -664
  151. package/src/device/humidifier.ts +299 -696
  152. package/src/device/iosensor.ts +251 -644
  153. package/src/device/lightstrip.ts +362 -712
  154. package/src/device/lock.ts +328 -653
  155. package/src/device/meter.ts +247 -637
  156. package/src/device/meterplus.ts +240 -644
  157. package/src/device/motion.ts +230 -598
  158. package/src/device/plug.ts +139 -525
  159. package/src/device/robotvacuumcleaner.ts +258 -593
  160. package/src/device/waterdetector.ts +191 -522
  161. package/src/homebridge-ui/public/index.html +22 -16
  162. package/src/homebridge-ui/server.ts +1 -1
  163. package/src/index.ts +4 -3
  164. package/src/irdevice/airconditioner.ts +370 -527
  165. package/src/irdevice/airpurifier.ts +132 -356
  166. package/src/irdevice/camera.ts +58 -311
  167. package/src/irdevice/fan.ts +109 -379
  168. package/src/irdevice/irdevice.ts +382 -0
  169. package/src/irdevice/light.ts +157 -412
  170. package/src/irdevice/other.ts +507 -648
  171. package/src/irdevice/tv.ts +121 -375
  172. package/src/irdevice/vacuumcleaner.ts +59 -311
  173. package/src/irdevice/waterheater.ts +61 -320
  174. package/src/platform.ts +395 -259
  175. package/src/settings.ts +118 -609
  176. package/src/utils.ts +642 -1
  177. package/.github/npm-version-script.cjs +0 -81
  178. package/src/device/waterdetector.json +0 -11
@@ -1,87 +1,45 @@
1
+ /* Copyright(C) 2021-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
2
+ *
3
+ * robotvacuumcleaner.ts: @switchbot/homebridge-switchbot.
4
+ */
1
5
  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
6
  import { Devices } from '../settings.js';
6
- export class RobotVacuumCleaner {
7
+ import { deviceBase } from './device.js';
8
+ import { Subject, interval, skipWhile } from 'rxjs';
9
+ import { debounceTime, take, tap } from 'rxjs/operators';
10
+ export class RobotVacuumCleaner extends deviceBase {
7
11
  platform;
8
- accessory;
9
- device;
10
- api;
11
- log;
12
- config;
13
- hap;
14
12
  // 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;
13
+ LightBulb;
14
+ Battery;
35
15
  // Updates
36
16
  robotVacuumCleanerUpdateInProgress;
37
17
  doRobotVacuumCleanerUpdate;
38
- // Connection
39
- OpenAPI;
40
- BLE;
41
18
  constructor(platform, accessory, device) {
19
+ super(platform, accessory, device);
42
20
  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
21
  // this is subject we use to track when we need to POST changes to the SwitchBot API
59
22
  this.doRobotVacuumCleanerUpdate = new Subject();
60
23
  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
24
+ // Initialize Lightbulb Service
25
+ accessory.context.LightBulb = accessory.context.LightBulb ?? {};
26
+ this.LightBulb = {
27
+ Name: accessory.context.LightBulb.Name ?? accessory.displayName,
28
+ Service: accessory.getService(this.hap.Service.Lightbulb) ?? accessory.addService(this.hap.Service.Lightbulb),
29
+ On: accessory.context.On ?? false,
30
+ Brightness: accessory.context.Brightness ?? 0,
31
+ };
32
+ accessory.context.LightBulb = this.LightBulb;
33
+ // Initialize LightBulb Characteristics
34
+ this.LightBulb.Service
35
+ .setCharacteristic(this.hap.Characteristic.Name, accessory.displayName)
36
+ .getCharacteristic(this.hap.Characteristic.On)
37
+ .onGet(() => {
38
+ return this.LightBulb.On;
39
+ })
40
+ .onSet(this.OnSet.bind(this));
41
+ // Initialize LightBulb Brightness Characteristic
42
+ this.LightBulb.Service
85
43
  .getCharacteristic(this.hap.Characteristic.Brightness)
86
44
  .setProps({
87
45
  minStep: 25,
@@ -91,17 +49,38 @@ export class RobotVacuumCleaner {
91
49
  validValueRanges: [0, 100],
92
50
  })
93
51
  .onGet(() => {
94
- return this.Brightness;
52
+ return this.LightBulb.Brightness;
95
53
  })
96
54
  .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
- }
55
+ // Initialize Battery Service
56
+ accessory.context.Battery = accessory.context.Battery ?? {};
57
+ this.Battery = {
58
+ Name: accessory.context.Battery.Name ?? `${accessory.displayName} Battery`,
59
+ Service: accessory.getService(this.hap.Service.Battery) ?? accessory.addService(this.hap.Service.Battery),
60
+ BatteryLevel: accessory.context.BatteryLevel ?? 100,
61
+ StatusLowBattery: accessory.context.StatusLowBattery ?? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,
62
+ ChargingState: accessory.context.ChargingState ?? this.hap.Characteristic.ChargingState.NOT_CHARGING,
63
+ };
64
+ accessory.context.Battery = this.Battery;
65
+ // Initialize Battery Characteristics
66
+ this.Battery.Service
67
+ .setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name)
68
+ .getCharacteristic(this.hap.Characteristic.BatteryLevel)
69
+ .onGet(() => {
70
+ return this.Battery.BatteryLevel;
71
+ });
72
+ this.Battery.Service
73
+ .getCharacteristic(this.hap.Characteristic.StatusLowBattery)
74
+ .onGet(() => {
75
+ return this.Battery.StatusLowBattery;
76
+ });
77
+ this.Battery.Service
78
+ .getCharacteristic(this.hap.Characteristic.ChargingState)
79
+ .onGet(() => {
80
+ return this.Battery.ChargingState;
81
+ });
82
+ // Retrieve initial values and updateHomekit
83
+ this.refreshStatus();
105
84
  // Update Homekit
106
85
  this.updateHomeKitCharacteristics();
107
86
  // Start an update interval
@@ -111,101 +90,92 @@ export class RobotVacuumCleaner {
111
90
  await this.refreshStatus();
112
91
  });
113
92
  //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
- }
93
+ this.registerWebhook(accessory, device);
135
94
  // Watch for Plug change events
136
95
  // We put in a debounce of 100ms so we don't make duplicate calls
137
96
  this.doRobotVacuumCleanerUpdate
138
97
  .pipe(tap(() => {
139
98
  this.robotVacuumCleanerUpdateInProgress = true;
140
- }), debounceTime(this.platform.config.options.pushRate * 1000))
99
+ }), debounceTime(this.devicePushRate * 1000))
141
100
  .subscribe(async () => {
142
101
  try {
143
- if (this.On !== this.accessory.context.On) {
102
+ if (this.LightBulb.On !== accessory.context.On) {
144
103
  await this.pushChanges();
145
104
  }
146
- if (this.On && this.Brightness !== this.accessory.context.Brightness) {
105
+ if (this.LightBulb.On && this.LightBulb.Brightness !== accessory.context.Brightness) {
147
106
  await this.openAPIpushBrightnessChanges();
148
107
  }
149
108
  }
150
109
  catch (e) {
151
110
  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)}`);
111
+ this.errorLog(`${device.deviceType}: ${accessory.displayName} failed pushChanges with ${device.connectionType} Connection,`
112
+ + ` Error Message: ${JSON.stringify(e.message)}`);
154
113
  }
155
114
  this.robotVacuumCleanerUpdateInProgress = false;
156
115
  });
157
116
  }
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();
117
+ async BLEparseStatus(serviceData) {
118
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
119
+ // Battery
120
+ this.Battery.BatteryLevel = Number(serviceData.battery);
121
+ if (this.Battery.BatteryLevel < 10) {
122
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
169
123
  }
170
124
  else {
171
- await this.offlineOff();
172
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` + ` ${this.device.connectionType}, parseStatus will not happen.`);
125
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
173
126
  }
174
- }
175
- async BLEparseStatus() {
176
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
127
+ this.debugLog(`${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}, StatusLowBattery: ${this.Battery.StatusLowBattery}`);
177
128
  // State
178
- switch (this.BLE_On) {
129
+ switch (serviceData.state) {
179
130
  case 'on':
180
- this.On = true;
131
+ this.LightBulb.On = true;
181
132
  break;
182
133
  default:
183
- this.On = false;
134
+ this.LightBulb.On = false;
184
135
  }
185
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
136
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LightBulb.On}`);
186
137
  }
187
- async openAPIparseStatus() {
138
+ async openAPIparseStatus(deviceStatus) {
188
139
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
189
- switch (this.OpenAPI_On) {
140
+ switch (deviceStatus.body.power) {
190
141
  case 'on':
191
- this.On = true;
142
+ this.LightBulb.On = true;
192
143
  break;
193
144
  default:
194
- this.On = false;
145
+ this.LightBulb.On = false;
195
146
  }
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;
147
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LightBulb.On}`);
148
+ // BatteryLevel
149
+ this.Battery.BatteryLevel = Number(deviceStatus.body.battery);
150
+ // StatusLowBattery
151
+ if (this.Battery.BatteryLevel < 10) {
152
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
201
153
  }
202
154
  else {
203
- this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
155
+ this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
156
+ }
157
+ if (Number.isNaN(this.Battery.BatteryLevel)) {
158
+ this.Battery.BatteryLevel = 100;
159
+ }
160
+ // ChargingState
161
+ this.Battery.ChargingState = deviceStatus.body.workingStatus === 'Charging'
162
+ ? this.hap.Characteristic.ChargingState.CHARGING : this.hap.Characteristic.ChargingState.NOT_CHARGING;
163
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
164
+ + ` StatusLowBattery: ${this.Battery.StatusLowBattery}, ChargingState: ${this.Battery.ChargingState}`);
165
+ // Firmware Version
166
+ const version = deviceStatus.body.version?.toString();
167
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Firmware Version: ${version?.replace(/^V|-.*$/g, '')}`);
168
+ if (deviceStatus.body.version) {
169
+ const deviceVersion = version?.replace(/^V|-.*$/g, '') ?? '0.0.0';
170
+ this.accessory
171
+ .getService(this.hap.Service.AccessoryInformation)
172
+ .setCharacteristic(this.hap.Characteristic.HardwareRevision, deviceVersion)
173
+ .setCharacteristic(this.hap.Characteristic.FirmwareRevision, deviceVersion)
174
+ .getCharacteristic(this.hap.Characteristic.FirmwareRevision)
175
+ .updateValue(deviceVersion);
176
+ this.accessory.context.deviceVersion = deviceVersion;
177
+ this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceVersion: ${this.accessory.context.deviceVersion}`);
204
178
  }
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
179
  }
210
180
  /**
211
181
  * Asks the SwitchBot API for the latest device information
@@ -213,16 +183,17 @@ export class RobotVacuumCleaner {
213
183
  async refreshStatus() {
214
184
  if (!this.device.enableCloudService && this.OpenAPI) {
215
185
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} refreshStatus enableCloudService: ${this.device.enableCloudService}`);
216
- /*} else if (this.BLE) {
217
- await this.BLERefreshStatus();*/
186
+ }
187
+ else if (this.BLE) {
188
+ await this.BLERefreshStatus();
218
189
  }
219
190
  else if (this.OpenAPI && this.platform.config.credentials?.token) {
220
191
  await this.openAPIRefreshStatus();
221
192
  }
222
193
  else {
223
194
  await this.offlineOff();
224
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` +
225
- ` ${this.device.connectionType}, refreshStatus will not happen.`);
195
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
196
+ + ` ${this.device.connectionType}, refreshStatus will not happen.`);
226
197
  }
227
198
  }
228
199
  async BLERefreshStatus() {
@@ -237,96 +208,43 @@ export class RobotVacuumCleaner {
237
208
  this.getCustomBLEAddress(switchbot);
238
209
  // Start to monitor advertisement packets
239
210
  (async () => {
240
- await switchbot.startScan({
241
- model: '?',
242
- id: this.device.bleMac,
243
- });
211
+ // Start to monitor advertisement packets
212
+ await switchbot.startScan({ model: this.device.bleModel, id: this.device.bleMac });
244
213
  // Set an event handler
245
214
  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 === '?') {
215
+ if (this.device.bleMac === ad.address && ad.model === this.device.bleModel) {
216
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
217
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.model}`);
249
218
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
250
- this.BLE_On = ad.serviceData.state;
251
219
  }
252
220
  else {
253
221
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
254
222
  }
255
223
  };
256
- // Wait 1 seconds
224
+ // Wait 10 seconds
257
225
  await switchbot.wait(this.scanDuration * 1000);
258
226
  // Stop to monitor
259
227
  await switchbot.stopScan();
260
228
  // Update HomeKit
261
- await this.BLEparseStatus();
229
+ await this.BLEparseStatus(switchbot.onadvertisement.serviceData);
262
230
  await this.updateHomeKitCharacteristics();
263
231
  })();
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}`);
292
- }
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
- }*/
232
+ if (switchbot === undefined) {
233
+ await this.BLERefreshConnection(switchbot);
234
+ }
312
235
  }
313
236
  async openAPIRefreshStatus() {
314
237
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
315
238
  try {
316
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/status`, {
317
- headers: this.platform.generateHeaders(),
318
- });
239
+ const { body, statusCode } = await this.platform.retryRequest(this.deviceMaxRetries, this.deviceDelayBetweenRetries, `${Devices}/${this.device.deviceId}/status`, { headers: this.platform.generateHeaders() });
319
240
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
320
241
  const deviceStatus = await body.json();
321
242
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
322
243
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
323
244
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
324
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
245
+ this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
325
246
  + `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();
247
+ this.openAPIparseStatus(deviceStatus);
330
248
  this.updateHomeKitCharacteristics();
331
249
  }
332
250
  else {
@@ -336,8 +254,34 @@ export class RobotVacuumCleaner {
336
254
  }
337
255
  catch (e) {
338
256
  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)}`);
257
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
258
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
259
+ }
260
+ }
261
+ async registerWebhook(accessory, device) {
262
+ if (device.webhook) {
263
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} is listening webhook.`);
264
+ this.platform.webhookEventHandler[device.deviceId] = async (context) => {
265
+ try {
266
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
267
+ const { onlineStatus, battery, workingStatus } = context;
268
+ const { On } = this.LightBulb;
269
+ const { BatteryLevel, ChargingState } = this.Battery;
270
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} (onlineStatus, battery, workingStatus) = `
271
+ + `Webhook: (${onlineStatus}, ${battery}, ${workingStatus}), current: (${On}, ${BatteryLevel}, ${ChargingState})`);
272
+ this.LightBulb.On = onlineStatus === 'online' ? true : false;
273
+ this.Battery.ChargingState = workingStatus === 'Charging'
274
+ ? this.hap.Characteristic.ChargingState.CHARGING : this.hap.Characteristic.ChargingState.NOT_CHARGING;
275
+ this.Battery.BatteryLevel = battery;
276
+ this.updateHomeKitCharacteristics();
277
+ }
278
+ catch (e) {
279
+ this.errorLog(`${device.deviceType}: ${accessory.displayName} failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
280
+ }
281
+ };
282
+ }
283
+ else {
284
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} is not listening webhook.`);
341
285
  }
342
286
  }
343
287
  /**
@@ -359,7 +303,8 @@ export class RobotVacuumCleaner {
359
303
  }
360
304
  else {
361
305
  await this.offlineOff();
362
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` + ` ${this.device.connectionType}, pushChanges will not happen.`);
306
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
307
+ + ` ${this.device.connectionType}, pushChanges will not happen.`);
363
308
  }
364
309
  // Refresh the status from the API
365
310
  interval(15000)
@@ -371,8 +316,9 @@ export class RobotVacuumCleaner {
371
316
  }
372
317
  async BLEpushChanges() {
373
318
  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}`);
319
+ if (this.LightBulb.On !== this.accessory.context.On) {
320
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`
321
+ + ` On: ${this.LightBulb.On} OnCached: ${this.accessory.context.On}`);
376
322
  const switchbot = await this.platform.connectBLE();
377
323
  // Convert to BLE Address
378
324
  this.device.bleMac = this.device
@@ -386,11 +332,11 @@ export class RobotVacuumCleaner {
386
332
  id: this.device.bleMac,
387
333
  })
388
334
  .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(),
335
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LightBulb.On}`);
336
+ return await this.retryBLE({
337
+ max: await this.maxRetryBLE(),
392
338
  fn: async () => {
393
- if (this.On) {
339
+ if (this.LightBulb.On) {
394
340
  return await device_list[0].turnOn({ id: this.device.bleMac });
395
341
  }
396
342
  else {
@@ -401,34 +347,26 @@ export class RobotVacuumCleaner {
401
347
  })
402
348
  .then(() => {
403
349
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
404
- this.On = false;
350
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
351
+ + `On: ${this.LightBulb.On} sent over BLE, sent successfully`);
352
+ this.LightBulb.On = false;
405
353
  })
406
354
  .catch(async (e) => {
407
355
  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)}`);
356
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
357
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
410
358
  await this.BLEPushConnection();
411
359
  });
412
360
  }
413
361
  else {
414
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges.` + `On: ${this.On}, ` + `OnCached: ${this.accessory.context.On}`);
362
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges,`
363
+ + ` On: ${this.LightBulb.On}, OnCached: ${this.accessory.context.On}`);
415
364
  }
416
365
  }
417
366
  async openAPIpushChanges() {
418
367
  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
- });
368
+ if (this.LightBulb.On !== this.accessory.context.On) {
369
+ const bodyChange = await this.commands();
432
370
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
433
371
  try {
434
372
  const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/commands`, {
@@ -444,6 +382,8 @@ export class RobotVacuumCleaner {
444
382
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
445
383
  this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
446
384
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
385
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
386
+ + `request to SwitchBot API, body: ${JSON.stringify(JSON.parse(bodyChange))} sent successfully`);
447
387
  }
448
388
  else {
449
389
  this.statusCode(statusCode);
@@ -452,22 +392,22 @@ export class RobotVacuumCleaner {
452
392
  }
453
393
  catch (e) {
454
394
  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)}`);
395
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
396
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
457
397
  }
458
398
  }
459
399
  else {
460
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges.` +
461
- `On: ${this.On}, ` +
462
- `OnCached: ${this.accessory.context.On}`);
400
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges, On: ${this.LightBulb.On}, `
401
+ + `OnCached: ${this.accessory.context.On}`);
463
402
  }
464
403
  }
465
404
  async openAPIpushBrightnessChanges() {
466
405
  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},`);
406
+ const bodyChange = await this.brightnessCommands();
407
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
469
408
  try {
470
409
  const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/commands`, {
410
+ body: bodyChange,
471
411
  method: 'POST',
472
412
  headers: this.platform.generateHeaders(),
473
413
  });
@@ -476,8 +416,10 @@ export class RobotVacuumCleaner {
476
416
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
477
417
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
478
418
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
479
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
419
+ this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
480
420
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
421
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
422
+ + `request to SwitchBot API, body: ${JSON.stringify(JSON.parse(bodyChange))} sent successfully`);
481
423
  }
482
424
  else {
483
425
  this.statusCode(statusCode);
@@ -486,14 +428,14 @@ export class RobotVacuumCleaner {
486
428
  }
487
429
  catch (e) {
488
430
  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)}`);
431
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
432
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
491
433
  }
492
434
  }
493
- commands() {
435
+ async commands() {
494
436
  let command;
495
437
  let parameter;
496
- if (this.On) {
438
+ if (this.LightBulb.On) {
497
439
  command = 'start';
498
440
  parameter = 'default';
499
441
  }
@@ -508,22 +450,22 @@ export class RobotVacuumCleaner {
508
450
  });
509
451
  return body;
510
452
  }
511
- brightnessCommands() {
453
+ async brightnessCommands() {
512
454
  let command;
513
455
  let parameter;
514
- if (this.Brightness === 25) {
456
+ if (this.LightBulb.Brightness === 25) {
515
457
  command = 'PowLevel';
516
458
  parameter = '0';
517
459
  }
518
- else if (this.Brightness === 50) {
460
+ else if (this.LightBulb.Brightness === 50) {
519
461
  command = 'PowLevel';
520
462
  parameter = '1';
521
463
  }
522
- else if (this.Brightness === 75) {
464
+ else if (this.LightBulb.Brightness === 75) {
523
465
  command = 'PowLevel';
524
466
  parameter = '2';
525
467
  }
526
- else if (this.Brightness === 100) {
468
+ else if (this.LightBulb.Brightness === 100) {
527
469
  command = 'PowLevel';
528
470
  parameter = '3';
529
471
  }
@@ -531,105 +473,89 @@ export class RobotVacuumCleaner {
531
473
  command = 'dock';
532
474
  parameter = 'default';
533
475
  }
534
- const body = JSON.stringify({
476
+ const bodyChange = JSON.stringify({
535
477
  command: `${command}`,
536
478
  parameter: `${parameter}`,
537
479
  commandType: 'command',
538
480
  });
539
- return body;
481
+ return bodyChange;
540
482
  }
541
483
  /**
542
484
  * Handle requests to set the value of the "On" characteristic
543
485
  */
544
486
  async OnSet(value) {
545
- if (this.On === this.accessory.context.On) {
487
+ if (this.LightBulb.On === this.accessory.context.On) {
546
488
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set On: ${value}`);
547
489
  }
548
490
  else {
549
491
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set On: ${value}`);
550
492
  }
551
- this.On = value;
493
+ this.LightBulb.On = value;
552
494
  this.doRobotVacuumCleanerUpdate.next();
553
495
  }
554
496
  /**
555
497
  * Handle requests to set the value of the "Brightness" characteristic
556
498
  */
557
499
  async BrightnessSet(value) {
558
- if (this.Brightness === this.accessory.context.Brightness) {
500
+ if (this.LightBulb.Brightness === this.accessory.context.Brightness) {
559
501
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set Brightness: ${value}`);
560
502
  }
561
- else if (this.On) {
503
+ else if (this.LightBulb.On) {
562
504
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Brightness: ${value}`);
563
505
  }
564
506
  else {
565
507
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Brightness: ${value}`);
566
508
  }
567
- this.Brightness = value;
509
+ this.LightBulb.Brightness = value;
568
510
  this.doRobotVacuumCleanerUpdate.next();
569
511
  }
570
512
  async updateHomeKitCharacteristics() {
571
513
  // On
572
- if (this.On === undefined) {
573
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
514
+ if (this.LightBulb.On === undefined) {
515
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LightBulb.On}`);
574
516
  }
575
517
  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}`);
518
+ this.accessory.context.On = this.LightBulb.On;
519
+ this.LightBulb.Service.updateCharacteristic(this.hap.Characteristic.On, this.LightBulb.On);
520
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.LightBulb.On}`);
579
521
  }
580
522
  // Brightness
581
- if (this.Brightness === undefined) {
582
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Brightness: ${this.Brightness}`);
523
+ if (this.LightBulb.Brightness === undefined) {
524
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Brightness: ${this.LightBulb.Brightness}`);
583
525
  }
584
526
  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}`);
527
+ this.accessory.context.Brightness = this.LightBulb.Brightness;
528
+ this.LightBulb.Service.updateCharacteristic(this.hap.Characteristic.Brightness, this.LightBulb.Brightness);
529
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Brightness: ${this.LightBulb.Brightness}`);
588
530
  }
589
531
  // BatteryLevel
590
- if (this.BatteryLevel === undefined) {
591
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
532
+ if (this.Battery.BatteryLevel === undefined) {
533
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}`);
592
534
  }
593
535
  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}`);
536
+ this.accessory.context.BatteryLevel = this.Battery.BatteryLevel;
537
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel);
538
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.Battery.BatteryLevel}`);
597
539
  }
598
540
  // StatusLowBattery
599
- if (this.StatusLowBattery === undefined) {
600
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
541
+ if (this.Battery.StatusLowBattery === undefined) {
542
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.Battery.StatusLowBattery}`);
601
543
  }
602
544
  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}`);
545
+ this.accessory.context.StatusLowBattery = this.Battery.StatusLowBattery;
546
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery);
547
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
548
+ + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
606
549
  }
607
- }
608
- async stopScanning(switchbot) {
609
- switchbot.stopScan();
610
- if (this.BLE_IsConnected) {
611
- await this.BLEparseStatus();
612
- await this.updateHomeKitCharacteristics();
550
+ // ChargingState
551
+ if (this.Battery.ChargingState === undefined) {
552
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ChargingState: ${this.Battery.ChargingState}`);
613
553
  }
614
554
  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
- })();
555
+ this.accessory.context.ChargingState = this.Battery.ChargingState;
556
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.ChargingState, this.Battery.ChargingState);
557
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
558
+ + ` ChargingState: ${this.Battery.ChargingState}`);
633
559
  }
634
560
  }
635
561
  async BLEPushConnection() {
@@ -646,255 +572,13 @@ export class RobotVacuumCleaner {
646
572
  await this.openAPIRefreshStatus();
647
573
  }
648
574
  }
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
575
  async offlineOff() {
767
576
  if (this.device.offline) {
768
- await this.deviceContext();
769
- await this.updateHomeKitCharacteristics();
577
+ this.LightBulb.Service.updateCharacteristic(this.hap.Characteristic.On, false);
770
578
  }
771
579
  }
772
580
  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';
581
+ this.LightBulb.Service.updateCharacteristic(this.hap.Characteristic.On, e);
898
582
  }
899
583
  }
900
584
  //# sourceMappingURL=robotvacuumcleaner.js.map