@switchbot/homebridge-switchbot 3.5.0-beta.9 → 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 +166 -24
  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,143 +1,112 @@
1
+ /* Copyright(C) 2021-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
2
+ *
3
+ * ceilinglight.ts: @switchbot/homebridge-switchbot.
4
+ */
1
5
  import { request } from 'undici';
2
- import { sleep } from '../utils.js';
6
+ import { deviceBase } from './device.js';
3
7
  import { interval, Subject } from 'rxjs';
4
- import { SwitchBotPlatform } from '../platform.js';
8
+ import { Devices } from '../settings.js';
9
+ import { hs2rgb, rgb2hs, m2hs } from '../utils.js';
5
10
  import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
6
- import { device, devicesConfig, deviceStatus, hs2rgb, rgb2hs, m2hs, serviceData, Devices, SwitchBotPlatformConfig } from '../settings.js';
7
- import {
8
- Service, PlatformAccessory, CharacteristicValue, ControllerConstructor, Controller, ControllerServiceMap, API, Logging, HAP,
9
- } from 'homebridge';
11
+
12
+ import type { SwitchBotPlatform } from '../platform.js';
13
+ import type { device, devicesConfig, serviceData, deviceStatus } from '../settings.js';
14
+ import type { Service, PlatformAccessory, CharacteristicValue, ControllerConstructor, Controller, ControllerServiceMap } from 'homebridge';
10
15
 
11
16
  /**
12
17
  * Platform Accessory
13
18
  * An instance of this class is created for each accessory your platform registers
14
19
  * Each accessory may expose multiple services of different service types.
15
20
  */
16
- export class CeilingLight {
17
- public readonly api: API;
18
- public readonly log: Logging;
19
- public readonly config!: SwitchBotPlatformConfig;
20
- protected readonly hap: HAP;
21
+ export class CeilingLight extends deviceBase {
21
22
  // Services
22
- lightBulbService!: Service;
23
-
24
- // Characteristic Values
25
- On!: CharacteristicValue;
26
- Hue!: CharacteristicValue;
27
- Saturation!: CharacteristicValue;
28
- Brightness!: CharacteristicValue;
29
- ColorTemperature?: CharacteristicValue;
30
- FirmwareRevision!: CharacteristicValue;
31
-
32
- // OpenAPI Status
33
- OpenAPI_On: deviceStatus['power'];
34
- OpenAPI_RGB: deviceStatus['color'];
35
- OpenAPI_Brightness: deviceStatus['brightness'];
36
- OpenAPI_FirmwareRevision: deviceStatus['version'];
37
- OpenAPI_ColorTemperature?: deviceStatus['colorTemperature'];
38
-
39
- // BLE Status
40
- BLE_Delay: serviceData['delay'];
41
- BLE_On: serviceData['state'];
42
- BLE_WifiRssi: serviceData['wifiRssi'];
43
-
44
- // BLE Others
45
- BLE_IsConnected?: boolean;
46
-
47
- // Config
48
- set_minStep?: number;
49
- scanDuration!: number;
50
- deviceLogging!: string;
51
- deviceRefreshRate!: number;
52
- adaptiveLightingShift?: number;
23
+ private LightBulb: {
24
+ Name: CharacteristicValue;
25
+ Service: Service;
26
+ On: CharacteristicValue;
27
+ Hue: CharacteristicValue;
28
+ Saturation: CharacteristicValue;
29
+ Brightness: CharacteristicValue;
30
+ ColorTemperature?: CharacteristicValue;
31
+ };
53
32
 
54
33
  // Adaptive Lighting
55
34
  AdaptiveLightingController?: ControllerConstructor | Controller<ControllerServiceMap>;
56
- minKelvin!: number;
57
- maxKelvin!: number;
58
-
59
- // Others
60
- cacheKelvin!: number;
35
+ adaptiveLightingShift?: number;
61
36
 
62
37
  // Updates
63
38
  ceilingLightUpdateInProgress!: boolean;
64
39
  doCeilingLightUpdate!: Subject<void>;
65
40
 
66
- // Connection
67
- private readonly OpenAPI: boolean;
68
- private readonly BLE: boolean;
69
-
70
41
  constructor(
71
- private readonly platform: SwitchBotPlatform,
72
- private accessory: PlatformAccessory,
73
- public device: device & devicesConfig,
42
+ readonly platform: SwitchBotPlatform,
43
+ accessory: PlatformAccessory,
44
+ device: device & devicesConfig,
74
45
  ) {
75
- this.api = this.platform.api;
76
- this.log = this.platform.log;
77
- this.config = this.platform.config;
78
- this.hap = this.api.hap;
79
- // Connection
80
- this.BLE = this.device.connectionType === 'BLE' || this.device.connectionType === 'BLE/OpenAPI';
81
- this.OpenAPI = this.device.connectionType === 'OpenAPI' || this.device.connectionType === 'BLE/OpenAPI';
46
+ super(platform, accessory, device);
82
47
  // default placeholders
83
- this.deviceLogs(device);
84
- this.scan(device);
85
- this.refreshRate(device);
86
48
  this.adaptiveLighting(device);
87
- this.deviceContext();
88
- this.deviceConfig(device);
89
49
 
90
50
  // this is subject we use to track when we need to POST changes to the SwitchBot API
91
51
  this.doCeilingLightUpdate = new Subject();
92
52
  this.ceilingLightUpdateInProgress = false;
93
53
 
94
- // Retrieve initial values and updateHomekit
95
- this.refreshStatus();
96
-
97
- // set accessory information
98
- accessory
99
- .getService(this.hap.Service.AccessoryInformation)!
100
- .setCharacteristic(this.hap.Characteristic.Manufacturer, 'SwitchBot')
101
- .setCharacteristic(this.hap.Characteristic.Model, this.model(device))
102
- .setCharacteristic(this.hap.Characteristic.SerialNumber, device.deviceId)
103
- .setCharacteristic(this.hap.Characteristic.FirmwareRevision, accessory.context.FirmwareRevision);
104
-
105
- // get the Lightbulb service if it exists, otherwise create a new Lightbulb service
106
- // you can create multiple services for each accessory
107
- const lightBulbService = `${accessory.displayName} ${device.deviceType}`;
108
- (this.lightBulbService = accessory.getService(this.hap.Service.Lightbulb)
109
- || accessory.addService(this.hap.Service.Lightbulb)), lightBulbService;
110
-
111
- if (this.adaptiveLightingShift === -1 && this.accessory.context.adaptiveLighting) {
112
- this.accessory.removeService(this.lightBulbService);
113
- this.lightBulbService = this.accessory.addService(this.hap.Service.Lightbulb);
114
- this.accessory.context.adaptiveLighting = false;
115
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} adaptiveLighting: ${this.accessory.context.adaptiveLighting}`);
54
+ // Initialize LightBulb Service
55
+ accessory.context.LightBulb = accessory.context.LightBulb ?? {};
56
+ this.LightBulb = {
57
+ Name: accessory.context.LightBul.bName ?? accessory.displayName,
58
+ Service: accessory.getService(this.hap.Service.Lightbulb) ?? accessory.addService(this.hap.Service.Lightbulb) as Service,
59
+ On: accessory.context.On ?? false,
60
+ Hue: accessory.context.Hue ?? 0,
61
+ Saturation: accessory.context.Saturation ?? 0,
62
+ Brightness: accessory.context.Brightness ?? 0,
63
+ ColorTemperature: accessory.context.ColorTemperature ?? 140,
64
+ };
65
+ accessory.context.LightBulb = this.LightBulb as object;
66
+
67
+ // Adaptive Lighting
68
+ if (this.adaptiveLightingShift === -1 && accessory.context.adaptiveLighting) {
69
+ accessory.removeService(this.LightBulb.Service);
70
+ this.LightBulb.Service = accessory.addService(this.hap.Service.Lightbulb);
71
+ accessory.context.adaptiveLighting = false;
72
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} adaptiveLighting: ${accessory.context.adaptiveLighting}`);
116
73
  }
117
-
118
- this.lightBulbService.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
119
- if (!this.lightBulbService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
120
- this.lightBulbService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
74
+ if (this.adaptiveLightingShift !== -1) {
75
+ this.AdaptiveLightingController = new platform.api.hap.AdaptiveLightingController(this.LightBulb.Service, {
76
+ customTemperatureAdjustment: this.adaptiveLightingShift,
77
+ });
78
+ this.accessory.configureController(this.AdaptiveLightingController);
79
+ this.accessory.context.adaptiveLighting = true;
80
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} adaptiveLighting: ${this.accessory.context.adaptiveLighting},`
81
+ + ` adaptiveLightingShift: ${this.adaptiveLightingShift}`);
121
82
  }
122
- // handle on / off events using the On characteristic
123
- this.lightBulbService.getCharacteristic(this.hap.Characteristic.On).onSet(this.OnSet.bind(this));
83
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} adaptiveLightingShift: ${this.adaptiveLightingShift}`);
124
84
 
125
- // handle Brightness events using the Brightness characteristic
126
- this.lightBulbService
85
+ // Initialize LightBulb Characteristics
86
+ this.LightBulb.Service
87
+ .setCharacteristic(this.hap.Characteristic.Name, this.LightBulb.Name)
88
+ .getCharacteristic(this.hap.Characteristic.On)
89
+ .onGet(() => {
90
+ return this.LightBulb.On;
91
+ })
92
+ .onSet(this.OnSet.bind(this));
93
+
94
+ // Initialize LightBulb Brightness
95
+ this.LightBulb.Service
127
96
  .getCharacteristic(this.hap.Characteristic.Brightness)
128
97
  .setProps({
129
- minStep: this.minStep(device),
98
+ minStep: device.ceilinglight?.set_minStep ?? 1,
130
99
  minValue: 0,
131
100
  maxValue: 100,
132
101
  validValueRanges: [0, 100],
133
102
  })
134
103
  .onGet(() => {
135
- return this.Brightness;
104
+ return this.LightBulb.Brightness;
136
105
  })
137
106
  .onSet(this.BrightnessSet.bind(this));
138
107
 
139
- // handle ColorTemperature events using the ColorTemperature characteristic
140
- this.lightBulbService
108
+ // Initialize LightBulb ColorTemperature
109
+ this.LightBulb.Service
141
110
  .getCharacteristic(this.hap.Characteristic.ColorTemperature)
142
111
  .setProps({
143
112
  minValue: 140,
@@ -145,12 +114,12 @@ export class CeilingLight {
145
114
  validValueRanges: [140, 500],
146
115
  })
147
116
  .onGet(() => {
148
- return this.ColorTemperature!;
117
+ return this.LightBulb.ColorTemperature!;
149
118
  })
150
119
  .onSet(this.ColorTemperatureSet.bind(this));
151
120
 
152
- // handle Hue events using the Hue characteristic
153
- this.lightBulbService
121
+ // Initialize LightBulb Hue
122
+ this.LightBulb.Service
154
123
  .getCharacteristic(this.hap.Characteristic.Hue)
155
124
  .setProps({
156
125
  minValue: 0,
@@ -158,12 +127,12 @@ export class CeilingLight {
158
127
  validValueRanges: [0, 360],
159
128
  })
160
129
  .onGet(() => {
161
- return this.Hue;
130
+ return this.LightBulb.Hue;
162
131
  })
163
132
  .onSet(this.HueSet.bind(this));
164
133
 
165
- // handle Hue events using the Hue characteristic
166
- this.lightBulbService
134
+ // Initialize LightBulb Saturation
135
+ this.LightBulb.Service
167
136
  .getCharacteristic(this.hap.Characteristic.Saturation)
168
137
  .setProps({
169
138
  minValue: 0,
@@ -171,22 +140,12 @@ export class CeilingLight {
171
140
  validValueRanges: [0, 100],
172
141
  })
173
142
  .onGet(() => {
174
- return this.Saturation;
143
+ return this.LightBulb.Saturation;
175
144
  })
176
145
  .onSet(this.SaturationSet.bind(this));
177
146
 
178
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} adaptiveLightingShift: ${this.adaptiveLightingShift}`);
179
- if (this.adaptiveLightingShift !== -1) {
180
- this.AdaptiveLightingController = new platform.api.hap.AdaptiveLightingController(this.lightBulbService, {
181
- customTemperatureAdjustment: this.adaptiveLightingShift,
182
- });
183
- this.accessory.configureController(this.AdaptiveLightingController);
184
- this.accessory.context.adaptiveLighting = true;
185
- this.debugLog(
186
- `${this.device.deviceType}: ${this.accessory.displayName} adaptiveLighting: ${this.accessory.context.adaptiveLighting},` +
187
- ` adaptiveLightingShift: ${this.adaptiveLightingShift}`,
188
- );
189
- }
147
+ // Retrieve initial values and updateHomekit
148
+ this.refreshStatus();
190
149
 
191
150
  // Update Homekit
192
151
  this.updateHomeKitCharacteristics();
@@ -199,27 +158,7 @@ export class CeilingLight {
199
158
  });
200
159
 
201
160
  //regisiter webhook event handler
202
- if (this.device.webhook) {
203
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} is listening webhook.`);
204
- this.platform.webhookEventHandler[this.device.deviceId] = async (context) => {
205
- try {
206
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
207
- const { powerState, brightness, colorTemperature } = context;
208
- const { On, Brightness, ColorTemperature } = this;
209
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ` +
210
- '(powerState, brightness, colorTemperature) = ' +
211
- `Webhook:(${powerState}, ${brightness}, ${colorTemperature}), ` +
212
- `current:(${On}, ${Brightness}, ${ColorTemperature})`);
213
- this.On = powerState === 'ON' ? true : false;
214
- this.Brightness = brightness;
215
- this.ColorTemperature = colorTemperature;
216
- this.updateHomeKitCharacteristics();
217
- } catch (e: any) {
218
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
219
- + `failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
220
- }
221
- };
222
- }
161
+ this.registerWebhook(accessory, device);
223
162
 
224
163
  // Watch for Bulb change events
225
164
  // We put in a debounce of 100ms so we don't make duplicate calls
@@ -228,117 +167,100 @@ export class CeilingLight {
228
167
  tap(() => {
229
168
  this.ceilingLightUpdateInProgress = true;
230
169
  }),
231
- debounceTime(this.platform.config.options!.pushRate! * 1000),
170
+ debounceTime(this.devicePushRate * 1000),
232
171
  )
233
172
  .subscribe(async () => {
234
173
  try {
235
174
  await this.pushChanges();
236
175
  } catch (e: any) {
237
176
  this.apiError(e);
238
- this.errorLog(
239
- `${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with ${this.device.connectionType} Connection,` +
240
- ` Error Message: ${JSON.stringify(e.message)}`,
241
- );
177
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with ${this.device.connectionType} Connection,`
178
+ + ` Error Message: ${JSON.stringify(e.message)}`);
242
179
  }
243
180
  this.ceilingLightUpdateInProgress = false;
244
181
  });
245
182
  }
246
183
 
247
- private model(device): CharacteristicValue {
248
- let model: string;
249
- if (device.deviceType === 'Ceiling Light') {
250
- model = 'W2612230' || 'W2612240';
251
- } else if (device.deviceType === 'Ceiling Light Pro') {
252
- model = 'W2612210' || 'W2612220';
253
- } else {
254
- model = 'unknown';
255
- }
256
- return model;
257
- }
258
-
259
184
  /**
260
- * Parse the device status from the SwitchBot api
185
+ * Parse the device status from the SwitchBotBLE API
261
186
  */
262
- async parseStatus(): Promise<void> {
263
- if (!this.device.enableCloudService && this.OpenAPI) {
264
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} parseStatus enableCloudService: ${this.device.enableCloudService}`);
265
- }
266
- /*if (this.BLE) {
267
- await this.BLEparseStatus();
268
- } else*/ if (this.OpenAPI && this.platform.config.credentials?.token) {
269
- await this.openAPIparseStatus();
270
- } else {
271
- await this.offlineOff();
272
- this.debugWarnLog(
273
- `${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` + ` ${this.device.connectionType}, parseStatus will not happen.`,
274
- );
275
- }
276
- }
277
-
278
- async BLEparseStatus(): Promise<void> {
187
+ async BLEparseStatus(serviceData: serviceData): Promise<void> {
279
188
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
280
189
  // State
281
- switch (this.BLE_On) {
190
+ switch (serviceData.state) {
282
191
  case 'on':
283
- this.On = true;
192
+ this.LightBulb.On = true;
284
193
  break;
285
194
  default:
286
- this.On = false;
195
+ this.LightBulb.On = false;
287
196
  }
288
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
197
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LightBulb.On}`);
289
198
  }
290
199
 
291
- async openAPIparseStatus() {
200
+ /**
201
+ * Parse the device status from the SwitchBot OpenAPI
202
+ */
203
+ async openAPIparseStatus(deviceStatus: deviceStatus) {
292
204
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
293
- switch (this.OpenAPI_On) {
205
+ switch (deviceStatus.body.power) {
294
206
  case 'on':
295
- this.On = true;
207
+ this.LightBulb.On = true;
296
208
  break;
297
209
  default:
298
- this.On = false;
210
+ this.LightBulb.On = false;
299
211
  }
300
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
212
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LightBulb.On}`);
301
213
 
302
214
  // Brightness
303
- this.Brightness = Number(this.OpenAPI_Brightness);
304
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Brightness: ${this.Brightness}`);
215
+ this.LightBulb.Brightness = Number(deviceStatus.body.brightness);
216
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Brightness: ${this.LightBulb.Brightness}`);
305
217
 
306
218
  // Color, Hue & Brightness
307
- if (this.OpenAPI_RGB) {
308
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} color: ${JSON.stringify(this.OpenAPI_RGB)}`);
309
- const [red, green, blue] = this.OpenAPI_RGB!.split(':');
219
+ if (deviceStatus.body.color) {
220
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} color: ${JSON.stringify(deviceStatus.body.color)}`);
221
+ const [red, green, blue] = deviceStatus.body.color!.split(':');
310
222
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} red: ${JSON.stringify(red)}`);
311
223
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} green: ${JSON.stringify(green)}`);
312
224
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} blue: ${JSON.stringify(blue)}`);
313
225
 
314
226
  const [hue, saturation] = rgb2hs(Number(red), Number(green), Number(blue));
315
- this.debugLog(
316
- `${this.device.deviceType}: ${this.accessory.displayName}` + ` hs: ${JSON.stringify(rgb2hs(Number(red), Number(green), Number(blue)))}`,
317
- );
227
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
228
+ + ` hs: ${JSON.stringify(rgb2hs(Number(red), Number(green), Number(blue)))}`);
318
229
 
319
230
  // Hue
320
- this.Hue = hue;
321
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Hue: ${this.Hue}`);
231
+ this.LightBulb.Hue = hue;
232
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Hue: ${this.LightBulb.Hue}`);
322
233
 
323
234
  // Saturation
324
- this.Saturation = saturation;
325
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Saturation: ${this.Saturation}`);
235
+ this.LightBulb.Saturation = saturation;
236
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Saturation: ${this.LightBulb.Saturation}`);
326
237
  }
327
238
 
328
239
  // ColorTemperature
329
- if (!Number.isNaN(this.OpenAPI_ColorTemperature)) {
330
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} OpenAPI ColorTemperature: ${this.OpenAPI_ColorTemperature}`);
331
- const mired = Math.round(1000000 / this.OpenAPI_ColorTemperature!);
240
+ if (!Number.isNaN(deviceStatus.body.colorTemperature)) {
241
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} OpenAPI ColorTemperature: ${deviceStatus.body.colorTemperature}`);
242
+ const mired = Math.round(1000000 / deviceStatus.body.colorTemperature!);
332
243
 
333
- this.ColorTemperature = Number(mired);
244
+ this.LightBulb.ColorTemperature = Number(mired);
334
245
 
335
- this.ColorTemperature = Math.max(Math.min(this.ColorTemperature, 500), 140);
336
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ColorTemperature: ${this.ColorTemperature}`);
246
+ this.LightBulb.ColorTemperature = Math.max(Math.min(this.LightBulb.ColorTemperature, 500), 140);
247
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ColorTemperature: ${this.LightBulb.ColorTemperature}`);
337
248
  }
338
249
 
339
- // FirmwareRevision
340
- this.FirmwareRevision = this.OpenAPI_FirmwareRevision!;
341
- this.accessory.context.FirmwareRevision = this.FirmwareRevision;
250
+ // Firmware Version
251
+ const version = deviceStatus.body.version?.toString();
252
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Firmware Version: ${version?.replace(/^V|-.*$/g, '')}`);
253
+ if (deviceStatus.body.version) {
254
+ const deviceVersion = version?.replace(/^V|-.*$/g, '') ?? '0.0.0';
255
+ this.accessory
256
+ .getService(this.hap.Service.AccessoryInformation)!
257
+ .setCharacteristic(this.hap.Characteristic.HardwareRevision, deviceVersion)
258
+ .setCharacteristic(this.hap.Characteristic.FirmwareRevision, deviceVersion)
259
+ .getCharacteristic(this.hap.Characteristic.FirmwareRevision)
260
+ .updateValue(deviceVersion);
261
+ this.accessory.context.deviceVersion = deviceVersion;
262
+ this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceVersion: ${this.accessory.context.deviceVersion}`);
263
+ }
342
264
  }
343
265
 
344
266
  /**
@@ -353,10 +275,8 @@ export class CeilingLight {
353
275
  await this.openAPIRefreshStatus();
354
276
  } else {
355
277
  await this.offlineOff();
356
- this.debugWarnLog(
357
- `${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` +
358
- ` ${this.device.connectionType}, refreshStatus will not happen.`,
359
- );
278
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
279
+ + ` ${this.device.connectionType}, refreshStatus will not happen.`);
360
280
  }
361
281
  }
362
282
 
@@ -373,110 +293,43 @@ export class CeilingLight {
373
293
  // Start to monitor advertisement packets
374
294
  (async () => {
375
295
  // Start to monitor advertisement packets
376
- await switchbot.startScan({
377
- id: this.device.bleMac,
378
- });
296
+ await switchbot.startScan({ model: this.device.bleModel, id: this.device.bleMac });
379
297
  // Set an event handler
380
298
  switchbot.onadvertisement = (ad: any) => {
381
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
382
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.model}`);
383
- if (this.device.bleMac === ad.address && ad.model === 's') {
299
+ if (this.device.bleMac === ad.address && ad.model === this.device.bleModel) {
300
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
301
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.model}`);
384
302
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
385
- this.BLE_On = ad.serviceData.state;
386
- //this.delay = ad.serviceData.delay;
387
- //this.timer = ad.serviceData.timer;
388
- //this.syncUtcTime = ad.serviceData.syncUtcTime;
389
- //this.wifiRssi = ad.serviceData.wifiRssi;
390
- //this.overload = ad.serviceData.overload;
391
- //this.currentPower = ad.serviceData.currentPower;
392
303
  } else {
393
304
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
394
305
  }
395
306
  };
396
- // Wait 1 seconds
307
+ // Wait 10 seconds
397
308
  await switchbot.wait(this.scanDuration * 1000);
398
309
  // Stop to monitor
399
310
  await switchbot.stopScan();
400
311
  // Update HomeKit
401
- await this.BLEparseStatus();
312
+ await this.BLEparseStatus(switchbot.onadvertisement.serviceData);
402
313
  await this.updateHomeKitCharacteristics();
403
314
  })();
404
- /*if (switchbot !== false) {
405
- switchbot
406
- .startScan({
407
- model: '',
408
- id: this.device.bleMac,
409
- })
410
- .then(async () => {
411
- // Set an event handler
412
- switchbot.onadvertisement = async (ad: ad) => {
413
- this.debugLog(
414
- `${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac},` +
415
- ` BLE Address Found: ${ad.address}`,
416
- );
417
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
418
- this.BLE_On = ad.serviceData.state;
419
- //this.delay = ad.serviceData.delay;
420
- //this.timer = ad.serviceData.timer;
421
- //this.syncUtcTime = ad.serviceData.syncUtcTime;
422
- //this.wifiRssi = ad.serviceData.wifiRssi;
423
- //this.overload = ad.serviceData.overload;
424
- //this.currentPower = ad.serviceData.currentPower;
425
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
426
- this.debugLog(
427
- `${this.device.deviceType}: ${this.accessory.displayName} state: ${ad.serviceData.state}, ` +
428
- `delay: ${ad.serviceData.delay}, timer: ${ad.serviceData.timer}, syncUtcTime: ${ad.serviceData.syncUtcTime} ` +
429
- `wifiRssi: ${ad.serviceData.wifiRssi}, overload: ${ad.serviceData.overload}, currentPower: ${ad.serviceData.currentPower}`,
430
- );
431
-
432
- if (ad.serviceData) {
433
- this.BLE_IsConnected = true;
434
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.BLE_IsConnected}`);
435
- await this.stopScanning(switchbot);
436
- } else {
437
- this.BLE_IsConnected = false;
438
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.BLE_IsConnected}`);
439
- }
440
- };
441
- // Wait
442
- return await sleep(this.scanDuration * 1000);
443
- })
444
- .then(async () => {
445
- // Stop to monitor
446
- await this.stopScanning(switchbot);
447
- })
448
- .catch(async (e: any) => {
449
- this.apiError(e);
450
- this.errorLog(
451
- `${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}` +
452
- ` Connection, Error Message: ${JSON.stringify(e.message)}`,
453
- );
454
- await this.BLERefreshConnection(switchbot);
455
- });
456
- } else {
315
+ if (switchbot === undefined) {
457
316
  await this.BLERefreshConnection(switchbot);
458
- }*/
317
+ }
459
318
  }
460
319
 
461
- async openAPIRefreshStatus() {
320
+ async openAPIRefreshStatus(): Promise<void> {
462
321
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
463
322
  try {
464
- const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/status`, {
465
- headers: this.platform.generateHeaders(),
466
- });
323
+ const { body, statusCode } = await this.platform.retryRequest(this.deviceMaxRetries, this.deviceDelayBetweenRetries,
324
+ `${Devices}/${this.device.deviceId}/status`, { headers: this.platform.generateHeaders() });
467
325
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
468
326
  const deviceStatus: any = await body.json();
469
327
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
470
328
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
471
329
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
472
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
330
+ this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
473
331
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
474
- this.OpenAPI_On = deviceStatus.body.power;
475
- this.OpenAPI_RGB = deviceStatus.body.color;
476
- this.OpenAPI_Brightness = deviceStatus.body.brightness;
477
- this.OpenAPI_ColorTemperature = deviceStatus.body.colorTemperature;
478
- this.OpenAPI_FirmwareRevision = deviceStatus.body.version;
479
- this.openAPIparseStatus();
332
+ this.openAPIparseStatus(deviceStatus);
480
333
  this.updateHomeKitCharacteristics();
481
334
  } else {
482
335
  this.statusCode(statusCode);
@@ -484,10 +337,55 @@ export class CeilingLight {
484
337
  }
485
338
  } catch (e: any) {
486
339
  this.apiError(e);
487
- this.errorLog(
488
- `${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}` +
489
- ` Connection, Error Message: ${JSON.stringify(e.message)}`,
490
- );
340
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
341
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
342
+ }
343
+ }
344
+
345
+ async registerWebhook(accessory: PlatformAccessory, device: device & devicesConfig) {
346
+ if (device.webhook) {
347
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} is listening webhook.`);
348
+ this.platform.webhookEventHandler[device.deviceId] = async (context) => {
349
+ try {
350
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
351
+ const { powerState, brightness, colorTemperature } = context;
352
+ const { On, Brightness, ColorTemperature } = this.LightBulb;
353
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} ` +
354
+ '(powerState, brightness, colorTemperature) = ' +
355
+ `Webhook:(${powerState}, ${brightness}, ${colorTemperature}), `
356
+ + `current:(${On}, ${Brightness}, ${ColorTemperature})`);
357
+
358
+ // On
359
+ this.LightBulb.On = powerState === 'ON' ? true : false;
360
+ if (accessory.context.Brightness !== this.LightBulb.On) {
361
+ this.infoLog(`${device.deviceType}: ${accessory.displayName} On: ${this.LightBulb.On}`);
362
+ } else {
363
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} On: ${this.LightBulb.On}`);
364
+ }
365
+
366
+ // Brightness
367
+ this.LightBulb.Brightness = brightness;
368
+ if (accessory.context.Brightness !== this.LightBulb.Brightness) {
369
+ this.infoLog(`${device.deviceType}: ${accessory.displayName} Brightness: ${this.LightBulb.Brightness}`);
370
+ } else {
371
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} Brightness: ${this.LightBulb.Brightness}`);
372
+ }
373
+
374
+ // ColorTemperature
375
+ this.LightBulb.ColorTemperature = colorTemperature;
376
+ if (accessory.context.ColorTemperature !== this.LightBulb.ColorTemperature) {
377
+ this.infoLog(`${device.deviceType}: ${accessory.displayName} ColorTemperature: ${this.LightBulb.ColorTemperature}`);
378
+ } else {
379
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} ColorTemperature: ${this.LightBulb.ColorTemperature}`);
380
+ }
381
+ this.updateHomeKitCharacteristics();
382
+ } catch (e: any) {
383
+ this.errorLog(`${device.deviceType}: ${accessory.displayName} `
384
+ + `failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
385
+ }
386
+ };
387
+ } else {
388
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} is not listening webhook.`);
491
389
  }
492
390
  }
493
391
 
@@ -511,9 +409,8 @@ export class CeilingLight {
511
409
  await this.openAPIpushChanges();
512
410
  } else {
513
411
  await this.offlineOff();
514
- this.debugWarnLog(
515
- `${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` + ` ${this.device.connectionType}, pushChanges will not happen.`,
516
- );
412
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
413
+ + ` ${this.device.connectionType}, pushChanges will not happen.`);
517
414
  }
518
415
  // Refresh the status from the API
519
416
  interval(15000)
@@ -526,8 +423,9 @@ export class CeilingLight {
526
423
 
527
424
  async BLEpushChanges(): Promise<void> {
528
425
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
529
- if (this.On !== this.accessory.context.On) {
530
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges On: ${this.On} OnCached: ${this.accessory.context.On}`);
426
+ if (this.LightBulb.On !== this.accessory.context.On) {
427
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
428
+ + ` BLEpushChanges On: ${this.LightBulb.On} OnCached: ${this.accessory.context.On}`);
531
429
  const switchbot = await this.platform.connectBLE();
532
430
  // Convert to BLE Address
533
431
  this.device.bleMac = this.device
@@ -541,11 +439,11 @@ export class CeilingLight {
541
439
  id: this.device.bleMac,
542
440
  })
543
441
  .then(async (device_list: any) => {
544
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
545
- return await this.retry({
546
- max: this.maxRetry(),
442
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LightBulb.On}`);
443
+ return await this.retryBLE({
444
+ max: await this.maxRetryBLE(),
547
445
  fn: async () => {
548
- if (this.On) {
446
+ if (this.LightBulb.On) {
549
447
  return await device_list[0].turnOn({ id: this.device.bleMac });
550
448
  } else {
551
449
  return await device_list[0].turnOff({ id: this.device.bleMac });
@@ -555,28 +453,28 @@ export class CeilingLight {
555
453
  })
556
454
  .then(() => {
557
455
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
558
- this.On = false;
456
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
457
+ + `On: ${this.LightBulb.On} sent over BLE, sent successfully`);
458
+ this.LightBulb.On = false;
559
459
  })
560
460
  .catch(async (e: any) => {
561
461
  this.apiError(e);
562
- this.errorLog(
563
- `${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}` +
564
- ` Connection, Error Message: ${JSON.stringify(e.message)}`,
565
- );
462
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
463
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
566
464
  await this.BLEPushConnection();
567
465
  });
568
466
  } else {
569
- this.debugLog(
570
- `${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges.` + `On: ${this.On}, ` + `OnCached: ${this.accessory.context.On}`,
571
- );
467
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
468
+ + ` No BLEpushChanges: On: ${this.LightBulb.On}, `
469
+ + `OnCached: ${this.accessory.context.On}`);
572
470
  }
573
471
  }
574
472
 
575
473
  async openAPIpushChanges(): Promise<void> {
576
474
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
577
- if (this.On !== this.accessory.context.On) {
475
+ if (this.LightBulb.On !== this.accessory.context.On) {
578
476
  let command = '';
579
- if (this.On) {
477
+ if (this.LightBulb.On) {
580
478
  command = 'turnOn';
581
479
  } else {
582
480
  command = 'turnOff';
@@ -599,46 +497,44 @@ export class CeilingLight {
599
497
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
600
498
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
601
499
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
602
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
500
+ this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
603
501
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
502
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
503
+ + `request to SwitchBot API, body: ${JSON.stringify(JSON.parse(bodyChange))} sent successfully`);
604
504
  } else {
605
505
  this.statusCode(statusCode);
606
506
  this.statusCode(deviceStatus.statusCode);
607
507
  }
608
508
  } catch (e: any) {
609
509
  this.apiError(e);
610
- this.errorLog(
611
- `${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}` +
612
- ` Connection, Error Message: ${JSON.stringify(e.message)}`,
613
- );
510
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
511
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
614
512
  }
615
513
  } else {
616
- this.debugLog(
617
- `${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges.` +
618
- `On: ${this.On}, ` +
619
- `OnCached: ${this.accessory.context.On}`,
620
- );
514
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges.`
515
+ + `On: ${this.LightBulb.On}, `
516
+ + `OnCached: ${this.accessory.context.On}`);
621
517
  }
622
518
  // Push Hue & Saturation Update
623
- if (this.On) {
519
+ if (this.LightBulb.On) {
624
520
  await this.pushHueSaturationChanges();
625
521
  }
626
522
  // Push ColorTemperature Update
627
- if (this.On) {
523
+ if (this.LightBulb.On) {
628
524
  await this.pushColorTemperatureChanges();
629
525
  }
630
526
  // Push Brightness Update
631
- if (this.On) {
527
+ if (this.LightBulb.On) {
632
528
  await this.pushBrightnessChanges();
633
529
  }
634
530
  }
635
531
 
636
532
  async pushHueSaturationChanges(): Promise<void> {
637
533
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushHueSaturationChanges`);
638
- if (this.Hue !== this.accessory.context.Hue || this.Saturation !== this.accessory.context.Saturation) {
639
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Hue: ${JSON.stringify(this.Hue)}`);
640
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Saturation: ${JSON.stringify(this.Saturation)}`);
641
- const [red, green, blue] = hs2rgb(Number(this.Hue), Number(this.Saturation));
534
+ if (this.LightBulb.Hue !== this.accessory.context.Hue || this.LightBulb.Saturation !== this.accessory.context.Saturation) {
535
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Hue: ${JSON.stringify(this.LightBulb.Hue)}`);
536
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Saturation: ${JSON.stringify(this.LightBulb.Saturation)}`);
537
+ const [red, green, blue] = hs2rgb(Number(this.LightBulb.Hue), Number(this.LightBulb.Saturation));
642
538
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} rgb: ${JSON.stringify([red, green, blue])}`);
643
539
  const bodyChange = JSON.stringify({
644
540
  command: 'setColor',
@@ -658,32 +554,30 @@ export class CeilingLight {
658
554
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
659
555
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
660
556
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
661
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
557
+ this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
662
558
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
559
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
560
+ + `request to SwitchBot API, body: ${JSON.stringify(JSON.parse(bodyChange))} sent successfully`);
663
561
  } else {
664
562
  this.statusCode(statusCode);
665
563
  this.statusCode(deviceStatus.statusCode);
666
564
  }
667
565
  } catch (e: any) {
668
566
  this.apiError(e);
669
- this.errorLog(
670
- `${this.device.deviceType}: ${this.accessory.displayName} failed pushHueSaturationChanges with ${this.device.connectionType}` +
671
- ` Connection, Error Message: ${JSON.stringify(e.message)}`,
672
- );
567
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushHueSaturationChanges with ${this.device.connectionType}`
568
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
673
569
  }
674
570
  } else {
675
- this.debugLog(
676
- `${this.device.deviceType}: ${this.accessory.displayName} No pushHueSaturationChanges. Hue: ${this.Hue}, ` +
677
- `HueCached: ${this.accessory.context.Hue}, Saturation: ${this.Saturation}, SaturationCached: ${this.accessory.context.Saturation}`,
678
- );
571
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No pushHueSaturationChanges. Hue: ${this.LightBulb.Hue}, HueCached: `
572
+ + `${this.accessory.context.Hue}, Saturation: ${this.LightBulb.Saturation}, SaturationCached: ${this.accessory.context.Saturation}`);
679
573
  }
680
574
  }
681
575
 
682
576
  async pushColorTemperatureChanges(): Promise<void> {
683
577
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushColorTemperatureChanges`);
684
- if (this.ColorTemperature !== this.accessory.context.ColorTemperature) {
685
- const kelvin = Math.round(1000000 / Number(this.ColorTemperature));
686
- this.cacheKelvin = kelvin;
578
+ if (this.LightBulb.ColorTemperature !== this.accessory.context.ColorTemperature) {
579
+ const kelvin = Math.round(1000000 / Number(this.LightBulb.ColorTemperature));
580
+ this.accessory.context.kelvin = kelvin;
687
581
  const bodyChange = JSON.stringify({
688
582
  command: 'setColorTemperature',
689
583
  parameter: `${kelvin}`,
@@ -702,7 +596,7 @@ export class CeilingLight {
702
596
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
703
597
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
704
598
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
705
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
599
+ this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
706
600
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
707
601
  } else {
708
602
  this.statusCode(statusCode);
@@ -710,25 +604,21 @@ export class CeilingLight {
710
604
  }
711
605
  } catch (e: any) {
712
606
  this.apiError(e);
713
- this.errorLog(
714
- `${this.device.deviceType}: ${this.accessory.displayName} failed pushColorTemperatureChanges with ${this.device.connectionType}` +
715
- ` Connection, Error Message: ${JSON.stringify(e.message)}`,
716
- );
607
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushColorTemperatureChanges with`
608
+ + ` ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`);
717
609
  }
718
610
  } else {
719
- this.debugLog(
720
- `${this.device.deviceType}: ${this.accessory.displayName} No pushColorTemperatureChanges.` +
721
- `ColorTemperature: ${this.ColorTemperature}, ColorTemperatureCached: ${this.accessory.context.ColorTemperature}`,
722
- );
611
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No pushColorTemperatureChanges.`
612
+ + `ColorTemperature: ${this.LightBulb.ColorTemperature}, ColorTemperatureCached: ${this.accessory.context.ColorTemperature}`);
723
613
  }
724
614
  }
725
615
 
726
616
  async pushBrightnessChanges(): Promise<void> {
727
617
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushBrightnessChanges`);
728
- if (this.Brightness !== this.accessory.context.Brightness) {
618
+ if (this.LightBulb.Brightness !== this.accessory.context.Brightness) {
729
619
  const bodyChange = JSON.stringify({
730
620
  command: 'setBrightness',
731
- parameter: `${this.Brightness}`,
621
+ parameter: `${this.LightBulb.Brightness}`,
732
622
  commandType: 'command',
733
623
  });
734
624
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
@@ -744,25 +634,23 @@ export class CeilingLight {
744
634
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
745
635
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
746
636
  if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
747
- this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
637
+ this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
748
638
  + `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
639
+ this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
640
+ + `request to SwitchBot API, body: ${JSON.stringify(JSON.parse(bodyChange))} sent successfully`);
749
641
  } else {
750
642
  this.statusCode(statusCode);
751
643
  this.statusCode(deviceStatus.statusCode);
752
644
  }
753
645
  } catch (e: any) {
754
646
  this.apiError(e);
755
- this.errorLog(
756
- `${this.device.deviceType}: ${this.accessory.displayName} failed pushBrightnessChanges with ${this.device.connectionType}` +
757
- ` Connection, Error Message: ${JSON.stringify(e.message)}`,
758
- );
647
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushBrightnessChanges with ${this.device.connectionType}`
648
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
759
649
  }
760
650
  } else {
761
- this.debugLog(
762
- `${this.device.deviceType}: ${this.accessory.displayName} No pushBrightnessChanges.` +
763
- `Brightness: ${this.Brightness}, ` +
764
- `BrightnessCached: ${this.accessory.context.Brightness}`,
765
- );
651
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No pushBrightnessChanges.`
652
+ + `Brightness: ${this.LightBulb.Brightness}, `
653
+ + `BrightnessCached: ${this.accessory.context.Brightness}`);
766
654
  }
767
655
  }
768
656
 
@@ -770,13 +658,13 @@ export class CeilingLight {
770
658
  * Handle requests to set the value of the "On" characteristic
771
659
  */
772
660
  async OnSet(value: CharacteristicValue): Promise<void> {
773
- if (this.On === this.accessory.context.On) {
661
+ if (this.LightBulb.On === this.accessory.context.On) {
774
662
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set On: ${value}`);
775
663
  } else {
776
664
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set On: ${value}`);
777
665
  }
778
666
 
779
- this.On = value;
667
+ this.LightBulb.On = value;
780
668
  this.doCeilingLightUpdate.next();
781
669
  }
782
670
 
@@ -784,15 +672,15 @@ export class CeilingLight {
784
672
  * Handle requests to set the value of the "Brightness" characteristic
785
673
  */
786
674
  async BrightnessSet(value: CharacteristicValue): Promise<void> {
787
- if (this.Brightness === this.accessory.context.Brightness) {
675
+ if (this.LightBulb.Brightness === this.accessory.context.Brightness) {
788
676
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set Brightness: ${value}`);
789
- } else if (this.On) {
677
+ } else if (this.LightBulb.On) {
790
678
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Brightness: ${value}`);
791
679
  } else {
792
680
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Brightness: ${value}`);
793
681
  }
794
682
 
795
- this.Brightness = value;
683
+ this.LightBulb.Brightness = value;
796
684
  this.doCeilingLightUpdate.next();
797
685
  }
798
686
 
@@ -800,30 +688,32 @@ export class CeilingLight {
800
688
  * Handle requests to set the value of the "ColorTemperature" characteristic
801
689
  */
802
690
  async ColorTemperatureSet(value: CharacteristicValue): Promise<void> {
803
- if (this.ColorTemperature === this.accessory.context.ColorTemperature) {
691
+ if (this.LightBulb.ColorTemperature === this.accessory.context.ColorTemperature) {
804
692
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set ColorTemperature: ${value}`);
805
- } else if (this.On) {
693
+ } else if (this.LightBulb.On) {
806
694
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set ColorTemperature: ${value}`);
807
695
  } else {
808
696
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Set ColorTemperature: ${value}`);
809
697
  }
810
698
 
699
+ const minKelvin = 2000;
700
+ const maxKelvin = 9000;
811
701
  // Convert mired to kelvin to nearest 100 (SwitchBot seems to need this)
812
702
  const kelvin = Math.round(1000000 / Number(value) / 100) * 100;
813
703
 
814
704
  // Check and increase/decrease kelvin to range of device
815
- const k = Math.min(Math.max(kelvin, this.minKelvin), this.maxKelvin);
705
+ const k = Math.min(Math.max(kelvin, minKelvin), maxKelvin);
816
706
 
817
- if (!this.accessory.context.On || this.cacheKelvin === k) {
707
+ if (!this.accessory.context.On || this.accessory.context.kelvin === k) {
818
708
  return;
819
709
  }
820
710
 
821
711
  // Updating the hue/sat to the corresponding values mimics native adaptive lighting
822
712
  const hs = m2hs(value);
823
- this.lightBulbService.updateCharacteristic(this.hap.Characteristic.Hue, hs[0]);
824
- this.lightBulbService.updateCharacteristic(this.hap.Characteristic.Saturation, hs[1]);
713
+ this.LightBulb.Service.updateCharacteristic(this.hap.Characteristic.Hue, hs[0]);
714
+ this.LightBulb.Service.updateCharacteristic(this.hap.Characteristic.Saturation, hs[1]);
825
715
 
826
- this.ColorTemperature = value;
716
+ this.LightBulb.ColorTemperature = value;
827
717
  this.doCeilingLightUpdate.next();
828
718
  }
829
719
 
@@ -831,17 +721,17 @@ export class CeilingLight {
831
721
  * Handle requests to set the value of the "Hue" characteristic
832
722
  */
833
723
  async HueSet(value: CharacteristicValue): Promise<void> {
834
- if (this.Hue === this.accessory.context.Hue) {
724
+ if (this.LightBulb.Hue === this.accessory.context.Hue) {
835
725
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set Hue: ${value}`);
836
- } else if (this.On) {
726
+ } else if (this.LightBulb.On) {
837
727
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Hue: ${value}`);
838
728
  } else {
839
729
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Hue: ${value}`);
840
730
  }
841
731
 
842
- this.lightBulbService.updateCharacteristic(this.hap.Characteristic.ColorTemperature, 140);
732
+ this.LightBulb.Service.updateCharacteristic(this.hap.Characteristic.ColorTemperature, 140);
843
733
 
844
- this.Hue = value;
734
+ this.LightBulb.Hue = value;
845
735
  this.doCeilingLightUpdate.next();
846
736
  }
847
737
 
@@ -849,55 +739,56 @@ export class CeilingLight {
849
739
  * Handle requests to set the value of the "Saturation" characteristic
850
740
  */
851
741
  async SaturationSet(value: CharacteristicValue): Promise<void> {
852
- if (this.Saturation === this.accessory.context.Saturation) {
742
+ if (this.LightBulb.Saturation === this.accessory.context.Saturation) {
853
743
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set Saturation: ${value}`);
854
- } else if (this.On) {
744
+ } else if (this.LightBulb.On) {
855
745
  this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Saturation: ${value}`);
856
746
  } else {
857
747
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Saturation: ${value}`);
858
748
  }
859
749
 
860
- this.lightBulbService.updateCharacteristic(this.hap.Characteristic.ColorTemperature, 140);
750
+ this.LightBulb.Service.updateCharacteristic(this.hap.Characteristic.ColorTemperature, 140);
861
751
 
862
- this.Saturation = value;
752
+ this.LightBulb.Saturation = value;
863
753
  this.doCeilingLightUpdate.next();
864
754
  }
865
755
 
866
756
  async updateHomeKitCharacteristics(): Promise<void> {
867
- if (this.On === undefined) {
868
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
757
+ if (this.LightBulb.On === undefined) {
758
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LightBulb.On}`);
869
759
  } else {
870
- this.accessory.context.On = this.On;
871
- this.lightBulbService.updateCharacteristic(this.hap.Characteristic.On, this.On);
872
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
760
+ this.accessory.context.On = this.LightBulb.On;
761
+ this.LightBulb!.Service.updateCharacteristic(this.hap.Characteristic.On, this.LightBulb.On);
762
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.LightBulb.On}`);
873
763
  }
874
- if (this.Brightness === undefined) {
875
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Brightness: ${this.Brightness}`);
764
+ if (this.LightBulb.Brightness === undefined) {
765
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Brightness: ${this.LightBulb.Brightness}`);
876
766
  } else {
877
- this.accessory.context.Brightness = this.Brightness;
878
- this.lightBulbService.updateCharacteristic(this.hap.Characteristic.Brightness, this.Brightness);
879
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Brightness: ${this.Brightness}`);
767
+ this.accessory.context.Brightness = this.LightBulb.Brightness;
768
+ this.LightBulb!.Service.updateCharacteristic(this.hap.Characteristic.Brightness, this.LightBulb.Brightness);
769
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Brightness: ${this.LightBulb.Brightness}`);
880
770
  }
881
- if (this.ColorTemperature === undefined) {
882
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ColorTemperature: ${this.ColorTemperature}`);
771
+ if (this.LightBulb.ColorTemperature === undefined) {
772
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ColorTemperature: ${this.LightBulb.ColorTemperature}`);
883
773
  } else {
884
- this.accessory.context.ColorTemperature = this.ColorTemperature;
885
- this.lightBulbService.updateCharacteristic(this.hap.Characteristic.ColorTemperature, this.ColorTemperature);
886
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic ColorTemperature: ${this.ColorTemperature}`);
774
+ this.accessory.context.ColorTemperature = this.LightBulb.ColorTemperature;
775
+ this.LightBulb!.Service.updateCharacteristic(this.hap.Characteristic.ColorTemperature, this.LightBulb.ColorTemperature);
776
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
777
+ + ` updateCharacteristic ColorTemperature: ${this.LightBulb.ColorTemperature}`);
887
778
  }
888
- if (this.Hue === undefined) {
889
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Hue: ${this.Hue}`);
779
+ if (this.LightBulb.Hue === undefined) {
780
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Hue: ${this.LightBulb.Hue}`);
890
781
  } else {
891
- this.accessory.context.Hue = this.Hue;
892
- this.lightBulbService.updateCharacteristic(this.hap.Characteristic.Hue, this.Hue);
893
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Hue: ${this.Hue}`);
782
+ this.accessory.context.Hue = this.LightBulb.Hue;
783
+ this.LightBulb!.Service.updateCharacteristic(this.hap.Characteristic.Hue, this.LightBulb.Hue);
784
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Hue: ${this.LightBulb.Hue}`);
894
785
  }
895
- if (this.Saturation === undefined) {
896
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Saturation: ${this.Saturation}`);
786
+ if (this.LightBulb.Saturation === undefined) {
787
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Saturation: ${this.LightBulb.Saturation}`);
897
788
  } else {
898
- this.accessory.context.Saturation = this.Saturation;
899
- this.lightBulbService.updateCharacteristic(this.hap.Characteristic.Saturation, this.Saturation);
900
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Saturation: ${this.Saturation}`);
789
+ this.accessory.context.Saturation = this.LightBulb.Saturation;
790
+ this.LightBulb!.Service.updateCharacteristic(this.hap.Characteristic.Saturation, this.LightBulb.Saturation);
791
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Saturation: ${this.LightBulb.Saturation}`);
901
792
  }
902
793
  }
903
794
 
@@ -911,35 +802,6 @@ export class CeilingLight {
911
802
  }
912
803
  }
913
804
 
914
- async stopScanning(switchbot: any) {
915
- switchbot.stopScan();
916
- if (this.BLE_IsConnected) {
917
- await this.BLEparseStatus();
918
- await this.updateHomeKitCharacteristics();
919
- } else {
920
- await this.BLERefreshConnection(switchbot);
921
- }
922
- }
923
-
924
- async getCustomBLEAddress(switchbot: any) {
925
- if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
926
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} customBLEaddress: ${this.device.customBLEaddress}`);
927
- (async () => {
928
- // Start to monitor advertisement packets
929
- await switchbot.startScan({
930
- model: 'u',
931
- });
932
- // Set an event handler
933
- switchbot.onadvertisement = (ad: any) => {
934
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${JSON.stringify(ad, null, ' ')}`);
935
- };
936
- await sleep(10000);
937
- // Stop to monitor
938
- switchbot.stopScan();
939
- })();
940
- }
941
- }
942
-
943
805
  async BLEPushConnection() {
944
806
  if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
945
807
  this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Push Changes`);
@@ -956,284 +818,17 @@ export class CeilingLight {
956
818
  }
957
819
  }
958
820
 
959
- async retry({ max, fn }: { max: number; fn: { (): any; (): Promise<any> } }): Promise<null> {
960
- return fn().catch(async (e: any) => {
961
- if (max === 0) {
962
- throw e;
963
- }
964
- this.infoLog(e);
965
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Retrying`);
966
- await sleep(1000);
967
- return this.retry({ max: max - 1, fn });
968
- });
969
- }
970
-
971
- maxRetry(): number {
972
- if (this.device.maxRetry) {
973
- return this.device.maxRetry;
974
- } else {
975
- return 5;
976
- }
977
- }
978
-
979
- minStep(device: device & devicesConfig): number {
980
- if (device.ceilinglight?.set_minStep) {
981
- this.set_minStep = device.ceilinglight?.set_minStep;
982
- } else {
983
- this.set_minStep = 1;
984
- }
985
- return this.set_minStep;
986
- }
987
-
988
- async scan(device: device & devicesConfig): Promise<void> {
989
- if (device.scanDuration) {
990
- this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
991
- if (this.BLE) {
992
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
993
- }
994
- } else {
995
- this.scanDuration = this.accessory.context.scanDuration = 1;
996
- if (this.BLE) {
997
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
998
- }
999
- }
1000
- }
1001
-
1002
- async statusCode(statusCode: number): Promise<void> {
1003
- switch (statusCode) {
1004
- case 151:
1005
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this deviceType, statusCode: ${statusCode}`);
1006
- break;
1007
- case 152:
1008
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found, statusCode: ${statusCode}`);
1009
- break;
1010
- case 160:
1011
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported, statusCode: ${statusCode}`);
1012
- break;
1013
- case 161:
1014
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline, statusCode: ${statusCode}`);
1015
- this.offlineOff();
1016
- break;
1017
- case 171:
1018
- this.errorLog(
1019
- `${this.device.deviceType}: ${this.accessory.displayName} Hub Device is offline, statusCode: ${statusCode}. ` +
1020
- `Hub: ${this.device.hubDeviceId}`,
1021
- );
1022
- this.offlineOff();
1023
- break;
1024
- case 190:
1025
- this.errorLog(
1026
- `${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
1027
- ` Or command format is invalid, statusCode: ${statusCode}`,
1028
- );
1029
- break;
1030
- case 100:
1031
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent, statusCode: ${statusCode}`);
1032
- break;
1033
- case 200:
1034
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Request successful, statusCode: ${statusCode}`);
1035
- break;
1036
- case 400:
1037
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Bad Request, The client has issued an invalid request. `
1038
- + `This is commonly used to specify validation errors in a request payload, statusCode: ${statusCode}`);
1039
- break;
1040
- case 401:
1041
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unauthorized, Authorization for the API is required, `
1042
- + `but the request has not been authenticated, statusCode: ${statusCode}`);
1043
- break;
1044
- case 403:
1045
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Forbidden, The request has been authenticated but does not `
1046
- + `have appropriate permissions, or a requested resource is not found, statusCode: ${statusCode}`);
1047
- break;
1048
- case 404:
1049
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Not Found, Specifies the requested path does not exist, `
1050
- + `statusCode: ${statusCode}`);
1051
- break;
1052
- case 406:
1053
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Not Acceptable, The client has requested a MIME type via `
1054
- + `the Accept header for a value not supported by the server, statusCode: ${statusCode}`);
1055
- break;
1056
- case 415:
1057
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unsupported Media Type, The client has defined a contentType `
1058
- + `header that is not supported by the server, statusCode: ${statusCode}`);
1059
- break;
1060
- case 422:
1061
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unprocessable Entity, The client has made a valid request, `
1062
- + `but the server cannot process it. This is often used for APIs for which certain limits have been exceeded, statusCode: ${statusCode}`);
1063
- break;
1064
- case 429:
1065
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Too Many Requests, The client has exceeded the number of `
1066
- + `requests allowed for a given time window, statusCode: ${statusCode}`);
1067
- break;
1068
- case 500:
1069
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Internal Server Error, An unexpected error on the SmartThings `
1070
- + `servers has occurred. These errors should be rare, statusCode: ${statusCode}`);
1071
- break;
1072
- default:
1073
- this.infoLog(
1074
- `${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode: ` +
1075
- `${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`,
1076
- );
1077
- }
1078
- }
1079
-
1080
821
  async offlineOff(): Promise<void> {
1081
822
  if (this.device.offline) {
1082
- await this.deviceContext();
1083
- await this.updateHomeKitCharacteristics();
823
+ this.LightBulb.Service.updateCharacteristic(this.hap.Characteristic.On, false);
1084
824
  }
1085
825
  }
1086
826
 
1087
827
  apiError(e: any): void {
1088
- this.lightBulbService.updateCharacteristic(this.hap.Characteristic.On, e);
1089
- this.lightBulbService.updateCharacteristic(this.hap.Characteristic.Hue, e);
1090
- this.lightBulbService.updateCharacteristic(this.hap.Characteristic.Brightness, e);
1091
- this.lightBulbService.updateCharacteristic(this.hap.Characteristic.Saturation, e);
1092
- this.lightBulbService.updateCharacteristic(this.hap.Characteristic.ColorTemperature, e);
1093
- }
1094
-
1095
- async deviceContext() {
1096
- if (this.On === undefined) {
1097
- this.On = false;
1098
- } else {
1099
- this.On = this.accessory.context.On;
1100
- }
1101
- if (this.Hue === undefined) {
1102
- this.Hue = 0;
1103
- } else {
1104
- this.Hue = this.accessory.context.Hue;
1105
- }
1106
- if (this.Brightness === undefined) {
1107
- this.Brightness = 0;
1108
- } else {
1109
- this.Brightness = this.accessory.context.Brightness;
1110
- }
1111
- if (this.Brightness === undefined) {
1112
- this.Saturation = 0;
1113
- } else {
1114
- this.Saturation = this.accessory.context.Saturation;
1115
- }
1116
- if (this.ColorTemperature === undefined) {
1117
- this.ColorTemperature = 140;
1118
- } else {
1119
- this.ColorTemperature = this.accessory.context.ColorTemperature;
1120
- }
1121
- this.minKelvin = 2000;
1122
- this.maxKelvin = 9000;
1123
- if (this.FirmwareRevision === undefined) {
1124
- this.FirmwareRevision = this.platform.version;
1125
- this.accessory.context.FirmwareRevision = this.FirmwareRevision;
1126
- }
1127
- }
1128
-
1129
- async refreshRate(device: device & devicesConfig): Promise<void> {
1130
- if (device.refreshRate) {
1131
- this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
1132
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
1133
- } else if (this.platform.config.options!.refreshRate) {
1134
- this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
1135
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
1136
- }
1137
- }
1138
-
1139
- async deviceConfig(device: device & devicesConfig): Promise<void> {
1140
- let config = {};
1141
- if (device.ceilinglight) {
1142
- config = device.ceilinglight;
1143
- }
1144
- if (device.connectionType !== undefined) {
1145
- config['connectionType'] = device.connectionType;
1146
- }
1147
- if (device.external !== undefined) {
1148
- config['external'] = device.external;
1149
- }
1150
- if (device.logging !== undefined) {
1151
- config['logging'] = device.logging;
1152
- }
1153
- if (device.refreshRate !== undefined) {
1154
- config['refreshRate'] = device.refreshRate;
1155
- }
1156
- if (device.scanDuration !== undefined) {
1157
- config['scanDuration'] = device.scanDuration;
1158
- }
1159
- if (device.offline !== undefined) {
1160
- config['offline'] = device.offline;
1161
- }
1162
- if (device.maxRetry !== undefined) {
1163
- config['maxRetry'] = device.maxRetry;
1164
- }
1165
- if (device.webhook !== undefined) {
1166
- config['webhook'] = device.webhook;
1167
- }
1168
- if (Object.entries(config).length !== 0) {
1169
- this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
1170
- }
1171
- }
1172
-
1173
- async deviceLogs(device: device & devicesConfig): Promise<void> {
1174
- if (this.platform.debugMode) {
1175
- this.deviceLogging = this.accessory.context.logging = 'debugMode';
1176
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
1177
- } else if (device.logging) {
1178
- this.deviceLogging = this.accessory.context.logging = device.logging;
1179
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
1180
- } else if (this.platform.config.options?.logging) {
1181
- this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
1182
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
1183
- } else {
1184
- this.deviceLogging = this.accessory.context.logging = 'standard';
1185
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
1186
- }
1187
- }
1188
-
1189
- /**
1190
- * Logging for Device
1191
- */
1192
- infoLog(...log: any[]): void {
1193
- if (this.enablingDeviceLogging()) {
1194
- this.platform.log.info(String(...log));
1195
- }
1196
- }
1197
-
1198
- warnLog(...log: any[]): void {
1199
- if (this.enablingDeviceLogging()) {
1200
- this.platform.log.warn(String(...log));
1201
- }
1202
- }
1203
-
1204
- debugWarnLog(...log: any[]): void {
1205
- if (this.enablingDeviceLogging()) {
1206
- if (this.deviceLogging?.includes('debug')) {
1207
- this.platform.log.warn('[DEBUG]', String(...log));
1208
- }
1209
- }
1210
- }
1211
-
1212
- errorLog(...log: any[]): void {
1213
- if (this.enablingDeviceLogging()) {
1214
- this.platform.log.error(String(...log));
1215
- }
1216
- }
1217
-
1218
- debugErrorLog(...log: any[]): void {
1219
- if (this.enablingDeviceLogging()) {
1220
- if (this.deviceLogging?.includes('debug')) {
1221
- this.platform.log.error('[DEBUG]', String(...log));
1222
- }
1223
- }
1224
- }
1225
-
1226
- debugLog(...log: any[]): void {
1227
- if (this.enablingDeviceLogging()) {
1228
- if (this.deviceLogging === 'debug') {
1229
- this.platform.log.info('[DEBUG]', String(...log));
1230
- } else {
1231
- this.platform.log.debug(String(...log));
1232
- }
1233
- }
1234
- }
1235
-
1236
- enablingDeviceLogging(): boolean {
1237
- return this.deviceLogging.includes('debug') || this.deviceLogging === 'standard';
828
+ this.LightBulb!.Service.updateCharacteristic(this.hap.Characteristic.On, e);
829
+ this.LightBulb!.Service.updateCharacteristic(this.hap.Characteristic.Hue, e);
830
+ this.LightBulb!.Service.updateCharacteristic(this.hap.Characteristic.Brightness, e);
831
+ this.LightBulb!.Service.updateCharacteristic(this.hap.Characteristic.Saturation, e);
832
+ this.LightBulb!.Service.updateCharacteristic(this.hap.Characteristic.ColorTemperature, e);
1238
833
  }
1239
834
  }