@switchbot/homebridge-switchbot 2.0.0-beta.9 → 2.0.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/CHANGELOG.md +10 -1
  2. package/README.md +3 -2
  3. package/config.schema.json +119 -19
  4. package/dist/device/bot.d.ts +34 -28
  5. package/dist/device/bot.d.ts.map +1 -1
  6. package/dist/device/bot.js +657 -648
  7. package/dist/device/bot.js.map +1 -1
  8. package/dist/device/ceilinglight.d.ts +137 -0
  9. package/dist/device/ceilinglight.d.ts.map +1 -0
  10. package/dist/device/ceilinglight.js +1127 -0
  11. package/dist/device/ceilinglight.js.map +1 -0
  12. package/dist/device/colorbulb.d.ts +36 -14
  13. package/dist/device/colorbulb.d.ts.map +1 -1
  14. package/dist/device/colorbulb.js +472 -297
  15. package/dist/device/colorbulb.js.map +1 -1
  16. package/dist/device/contact.d.ts +18 -8
  17. package/dist/device/contact.d.ts.map +1 -1
  18. package/dist/device/contact.js +306 -237
  19. package/dist/device/contact.js.map +1 -1
  20. package/dist/device/curtain.d.ts +23 -16
  21. package/dist/device/curtain.d.ts.map +1 -1
  22. package/dist/device/curtain.js +566 -502
  23. package/dist/device/curtain.js.map +1 -1
  24. package/dist/device/humidifier.d.ts +24 -18
  25. package/dist/device/humidifier.d.ts.map +1 -1
  26. package/dist/device/humidifier.js +453 -369
  27. package/dist/device/humidifier.js.map +1 -1
  28. package/dist/device/lock.d.ts +27 -8
  29. package/dist/device/lock.d.ts.map +1 -1
  30. package/dist/device/lock.js +305 -148
  31. package/dist/device/lock.js.map +1 -1
  32. package/dist/device/meter.d.ts +22 -16
  33. package/dist/device/meter.d.ts.map +1 -1
  34. package/dist/device/meter.js +367 -267
  35. package/dist/device/meter.js.map +1 -1
  36. package/dist/device/meterplus.d.ts +24 -12
  37. package/dist/device/meterplus.d.ts.map +1 -1
  38. package/dist/device/meterplus.js +381 -213
  39. package/dist/device/meterplus.js.map +1 -1
  40. package/dist/device/motion.d.ts +18 -8
  41. package/dist/device/motion.d.ts.map +1 -1
  42. package/dist/device/motion.js +279 -216
  43. package/dist/device/motion.js.map +1 -1
  44. package/dist/device/plug.d.ts +27 -17
  45. package/dist/device/plug.d.ts.map +1 -1
  46. package/dist/device/plug.js +295 -251
  47. package/dist/device/plug.js.map +1 -1
  48. package/dist/device/striplight.d.ts +43 -19
  49. package/dist/device/striplight.d.ts.map +1 -1
  50. package/dist/device/striplight.js +506 -262
  51. package/dist/device/striplight.js.map +1 -1
  52. package/dist/irdevice/airconditioner.d.ts +12 -12
  53. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  54. package/dist/irdevice/airconditioner.js +316 -234
  55. package/dist/irdevice/airconditioner.js.map +1 -1
  56. package/dist/irdevice/airpurifier.d.ts +5 -3
  57. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  58. package/dist/irdevice/airpurifier.js +154 -104
  59. package/dist/irdevice/airpurifier.js.map +1 -1
  60. package/dist/irdevice/camera.d.ts +11 -8
  61. package/dist/irdevice/camera.d.ts.map +1 -1
  62. package/dist/irdevice/camera.js +133 -86
  63. package/dist/irdevice/camera.js.map +1 -1
  64. package/dist/irdevice/fan.d.ts +10 -7
  65. package/dist/irdevice/fan.d.ts.map +1 -1
  66. package/dist/irdevice/fan.js +160 -109
  67. package/dist/irdevice/fan.js.map +1 -1
  68. package/dist/irdevice/light.d.ts +11 -8
  69. package/dist/irdevice/light.d.ts.map +1 -1
  70. package/dist/irdevice/light.js +137 -103
  71. package/dist/irdevice/light.js.map +1 -1
  72. package/dist/irdevice/other.d.ts +11 -8
  73. package/dist/irdevice/other.d.ts.map +1 -1
  74. package/dist/irdevice/other.js +145 -98
  75. package/dist/irdevice/other.js.map +1 -1
  76. package/dist/irdevice/tv.d.ts +12 -9
  77. package/dist/irdevice/tv.d.ts.map +1 -1
  78. package/dist/irdevice/tv.js +143 -93
  79. package/dist/irdevice/tv.js.map +1 -1
  80. package/dist/irdevice/vacuumcleaner.d.ts +9 -10
  81. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  82. package/dist/irdevice/vacuumcleaner.js +132 -89
  83. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  84. package/dist/irdevice/waterheater.d.ts +8 -9
  85. package/dist/irdevice/waterheater.d.ts.map +1 -1
  86. package/dist/irdevice/waterheater.js +132 -89
  87. package/dist/irdevice/waterheater.js.map +1 -1
  88. package/dist/platform.d.ts +13 -12
  89. package/dist/platform.d.ts.map +1 -1
  90. package/dist/platform.js +530 -421
  91. package/dist/platform.js.map +1 -1
  92. package/dist/settings.d.ts +22 -11
  93. package/dist/settings.d.ts.map +1 -1
  94. package/dist/settings.js.map +1 -1
  95. package/homebridge-ui/public/index.html +1 -0
  96. package/package.json +11 -9
  97. package/src/device/bot.ts +656 -659
  98. package/src/device/ceilinglight.ts +1208 -0
  99. package/src/device/colorbulb.ts +482 -334
  100. package/src/device/contact.ts +309 -241
  101. package/src/device/curtain.ts +571 -516
  102. package/src/device/humidifier.ts +456 -403
  103. package/src/device/lock.ts +314 -149
  104. package/src/device/meter.ts +378 -280
  105. package/src/device/meterplus.ts +391 -219
  106. package/src/device/motion.ts +285 -222
  107. package/src/device/plug.ts +299 -260
  108. package/src/device/striplight.ts +522 -289
  109. package/src/irdevice/airconditioner.ts +322 -245
  110. package/src/irdevice/airpurifier.ts +151 -103
  111. package/src/irdevice/camera.ts +131 -85
  112. package/src/irdevice/fan.ts +157 -106
  113. package/src/irdevice/light.ts +135 -103
  114. package/src/irdevice/other.ts +143 -97
  115. package/src/irdevice/tv.ts +142 -93
  116. package/src/irdevice/vacuumcleaner.ts +131 -89
  117. package/src/irdevice/waterheater.ts +130 -89
  118. package/src/platform.ts +528 -449
  119. package/src/settings.ts +23 -11
@@ -0,0 +1,1127 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.CeilingLight = void 0;
7
+ const https_1 = __importDefault(require("https"));
8
+ const crypto_1 = __importDefault(require("crypto"));
9
+ const super_stringify_1 = __importDefault(require("super-stringify"));
10
+ const rxjs_1 = require("rxjs");
11
+ const operators_1 = require("rxjs/operators");
12
+ const settings_1 = require("../settings");
13
+ /**
14
+ * Platform Accessory
15
+ * An instance of this class is created for each accessory your platform registers
16
+ * Each accessory may expose multiple services of different service types.
17
+ */
18
+ class CeilingLight {
19
+ constructor(platform, accessory, device) {
20
+ this.platform = platform;
21
+ this.accessory = accessory;
22
+ this.device = device;
23
+ // Connection
24
+ this.BLE = (this.device.connectionType === 'BLE' || this.device.connectionType === 'BLE/OpenAPI');
25
+ this.OpenAPI = (this.device.connectionType === 'OpenAPI' || this.device.connectionType === 'BLE/OpenAPI');
26
+ // default placeholders
27
+ this.logs(device);
28
+ this.scan(device);
29
+ this.refreshRate(device);
30
+ this.adaptiveLighting(device);
31
+ this.config(device);
32
+ this.context();
33
+ // this is subject we use to track when we need to POST changes to the SwitchBot API
34
+ this.doCeilingLightUpdate = new rxjs_1.Subject();
35
+ this.ceilingLightUpdateInProgress = false;
36
+ // Retrieve initial values and updateHomekit
37
+ this.refreshStatus();
38
+ // set accessory information
39
+ accessory
40
+ .getService(this.platform.Service.AccessoryInformation)
41
+ .setCharacteristic(this.platform.Characteristic.Manufacturer, 'SwitchBot')
42
+ .setCharacteristic(this.platform.Characteristic.Model, this.model(device))
43
+ .setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceId)
44
+ .setCharacteristic(this.platform.Characteristic.FirmwareRevision, this.FirmwareRevision(accessory, device))
45
+ .getCharacteristic(this.platform.Characteristic.FirmwareRevision)
46
+ .updateValue(this.FirmwareRevision(accessory, device));
47
+ // get the Lightbulb service if it exists, otherwise create a new Lightbulb service
48
+ // you can create multiple services for each accessory
49
+ (this.lightBulbService = accessory.getService(this.platform.Service.Lightbulb) || accessory.addService(this.platform.Service.Lightbulb)),
50
+ `${accessory.displayName} ${device.deviceType}`;
51
+ if (this.adaptiveLightingShift === -1 && this.accessory.context.adaptiveLighting) {
52
+ this.accessory.removeService(this.lightBulbService);
53
+ this.lightBulbService = this.accessory.addService(this.platform.Service.Lightbulb);
54
+ this.accessory.context.adaptiveLighting = false;
55
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} adaptiveLighting: ${this.accessory.context.adaptiveLighting}`);
56
+ }
57
+ // To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error,
58
+ // when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id:
59
+ // accessory.getService('NAME') ?? accessory.addService(this.platform.Service.Outlet, 'NAME', 'USER_DEFINED_SUBTYPE');
60
+ // set the service name, this is what is displayed as the default name on the Home app
61
+ // in this example we are using the name we stored in the `accessory.context` in the `discoverDevices` method.
62
+ this.lightBulbService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
63
+ // handle on / off events using the On characteristic
64
+ this.lightBulbService.getCharacteristic(this.platform.Characteristic.On).onSet(this.OnSet.bind(this));
65
+ // handle Brightness events using the Brightness characteristic
66
+ this.lightBulbService
67
+ .getCharacteristic(this.platform.Characteristic.Brightness)
68
+ .setProps({
69
+ minStep: this.minStep(device),
70
+ minValue: 0,
71
+ maxValue: 100,
72
+ validValueRanges: [0, 100],
73
+ })
74
+ .onGet(() => {
75
+ return this.Brightness;
76
+ })
77
+ .onSet(this.BrightnessSet.bind(this));
78
+ // handle ColorTemperature events using the ColorTemperature characteristic
79
+ this.lightBulbService
80
+ .getCharacteristic(this.platform.Characteristic.ColorTemperature)
81
+ .setProps({
82
+ minValue: 140,
83
+ maxValue: 500,
84
+ validValueRanges: [140, 500],
85
+ })
86
+ .onGet(() => {
87
+ return this.ColorTemperature;
88
+ })
89
+ .onSet(this.ColorTemperatureSet.bind(this));
90
+ // handle Hue events using the Hue characteristic
91
+ this.lightBulbService
92
+ .getCharacteristic(this.platform.Characteristic.Hue)
93
+ .setProps({
94
+ minValue: 0,
95
+ maxValue: 360,
96
+ validValueRanges: [0, 360],
97
+ })
98
+ .onGet(() => {
99
+ return this.Hue;
100
+ })
101
+ .onSet(this.HueSet.bind(this));
102
+ // handle Hue events using the Hue characteristic
103
+ this.lightBulbService
104
+ .getCharacteristic(this.platform.Characteristic.Saturation)
105
+ .setProps({
106
+ minValue: 0,
107
+ maxValue: 100,
108
+ validValueRanges: [0, 100],
109
+ })
110
+ .onGet(() => {
111
+ return this.Saturation;
112
+ })
113
+ .onSet(this.SaturationSet.bind(this));
114
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} adaptiveLightingShift: ${this.adaptiveLightingShift}`);
115
+ if (this.adaptiveLightingShift !== -1) {
116
+ this.AdaptiveLightingController = new platform.api.hap.AdaptiveLightingController(this.lightBulbService, {
117
+ customTemperatureAdjustment: this.adaptiveLightingShift,
118
+ });
119
+ this.accessory.configureController(this.AdaptiveLightingController);
120
+ this.accessory.context.adaptiveLighting = true;
121
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} adaptiveLighting: ${this.accessory.context.adaptiveLighting},` +
122
+ ` adaptiveLightingShift: ${this.adaptiveLightingShift}`);
123
+ }
124
+ // Update Homekit
125
+ this.updateHomeKitCharacteristics();
126
+ // Start an update interval
127
+ (0, rxjs_1.interval)(this.deviceRefreshRate * 1000)
128
+ .pipe((0, operators_1.skipWhile)(() => this.ceilingLightUpdateInProgress))
129
+ .subscribe(async () => {
130
+ await this.refreshStatus();
131
+ });
132
+ // Watch for Bulb change events
133
+ // We put in a debounce of 100ms so we don't make duplicate calls
134
+ this.doCeilingLightUpdate
135
+ .pipe((0, operators_1.tap)(() => {
136
+ this.ceilingLightUpdateInProgress = true;
137
+ }), (0, operators_1.debounceTime)(this.platform.config.options.pushRate * 1000))
138
+ .subscribe(async () => {
139
+ try {
140
+ await this.pushChanges();
141
+ }
142
+ catch (e) {
143
+ this.apiError(e);
144
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with ${this.device.connectionType} Connection,`
145
+ + ` Error Message: ${(0, super_stringify_1.default)(e.message)}`);
146
+ }
147
+ this.ceilingLightUpdateInProgress = false;
148
+ // Refresh the status from the API
149
+ (0, rxjs_1.interval)(15000)
150
+ .pipe((0, operators_1.skipWhile)(() => this.ceilingLightUpdateInProgress))
151
+ .pipe((0, operators_1.take)(1))
152
+ .subscribe(async () => {
153
+ await this.refreshStatus();
154
+ });
155
+ });
156
+ }
157
+ model(device) {
158
+ let model;
159
+ if (device.deviceType === 'Ceiling Light') {
160
+ model = 'W2612230' || 'W2612240';
161
+ }
162
+ else if (device.deviceType === 'Ceiling Light Pro') {
163
+ model = 'W2612210' || 'W2612220';
164
+ }
165
+ else {
166
+ model = 'unknown';
167
+ }
168
+ return model;
169
+ }
170
+ /**
171
+ * Parse the device status from the SwitchBot api
172
+ */
173
+ async parseStatus() {
174
+ /*if (this.BLE) {
175
+ await this.BLEparseStatus();
176
+ } else*/ if (this.OpenAPI && this.platform.config.credentials?.token) {
177
+ await this.openAPIparseStatus();
178
+ }
179
+ else {
180
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
181
+ + ` ${this.device.connectionType}, parseStatus will not happen.`);
182
+ }
183
+ }
184
+ async BLEparseStatus() {
185
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
186
+ // State
187
+ switch (this.state) {
188
+ case 'on':
189
+ this.On = true;
190
+ break;
191
+ default:
192
+ this.On = false;
193
+ }
194
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
195
+ }
196
+ async openAPIparseStatus() {
197
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
198
+ switch (this.power) {
199
+ case 'on':
200
+ this.On = true;
201
+ break;
202
+ default:
203
+ this.On = false;
204
+ }
205
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
206
+ // Brightness
207
+ this.Brightness = Number(this.brightness);
208
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Brightness: ${this.Brightness}`);
209
+ // Color, Hue & Brightness
210
+ if (this.color) {
211
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} color: ${(0, super_stringify_1.default)(this.color)}`);
212
+ const [red, green, blue] = this.color.split(':');
213
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} red: ${(0, super_stringify_1.default)(red)}`);
214
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} green: ${(0, super_stringify_1.default)(green)}`);
215
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} blue: ${(0, super_stringify_1.default)(blue)}`);
216
+ const [hue, saturation] = (0, settings_1.rgb2hs)(Number(red), Number(green), Number(blue));
217
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
218
+ + ` hs: ${(0, super_stringify_1.default)((0, settings_1.rgb2hs)(Number(red), Number(green), Number(blue)))}`);
219
+ // Hue
220
+ this.Hue = hue;
221
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Hue: ${this.Hue}`);
222
+ // Saturation
223
+ this.Saturation = saturation;
224
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Saturation: ${this.Saturation}`);
225
+ }
226
+ // ColorTemperature
227
+ if (!Number.isNaN(this.colorTemperature)) {
228
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} OpenAPI ColorTemperature: ${this.colorTemperature}`);
229
+ const mired = Math.round(1000000 / this.colorTemperature);
230
+ this.ColorTemperature = Number(mired);
231
+ this.ColorTemperature = Math.max(Math.min(this.ColorTemperature, 500), 140);
232
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ColorTemperature: ${this.ColorTemperature}`);
233
+ }
234
+ }
235
+ /**
236
+ * Asks the SwitchBot API for the latest device information
237
+ */
238
+ async refreshStatus() {
239
+ /*if (this.BLE) {
240
+ await this.BLERefreshStatus();
241
+ } else*/ if (this.OpenAPI && this.platform.config.credentials?.token) {
242
+ await this.openAPIRefreshStatus();
243
+ }
244
+ else {
245
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
246
+ + ` ${this.device.connectionType}, refreshStatus will not happen.`);
247
+ }
248
+ }
249
+ async BLERefreshStatus() {
250
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
251
+ const switchbot = await this.platform.connectBLE();
252
+ // Convert to BLE Address
253
+ this.device.bleMac = this.device
254
+ .deviceId.match(/.{1,2}/g)
255
+ .join(':')
256
+ .toLowerCase();
257
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
258
+ this.getCustomBLEAddress(switchbot);
259
+ // Start to monitor advertisement packets
260
+ if (switchbot !== false) {
261
+ switchbot
262
+ .startScan({
263
+ model: 'u',
264
+ id: this.device.bleMac,
265
+ })
266
+ .then(() => {
267
+ // Set an event hander
268
+ switchbot.onadvertisement = (ad) => {
269
+ this.address = ad.address;
270
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac},`
271
+ + ` BLE Address Found: ${this.address}`);
272
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${(0, super_stringify_1.default)(ad.serviceData)}`);
273
+ this.serviceData = ad.serviceData;
274
+ //this.state = ad.serviceData.state;
275
+ //this.delay = ad.serviceData.delay;
276
+ //this.timer = ad.serviceData.timer;
277
+ //this.syncUtcTime = ad.serviceData.syncUtcTime;
278
+ //this.wifiRssi = ad.serviceData.wifiRssi;
279
+ //this.overload = ad.serviceData.overload;
280
+ //this.currentPower = ad.serviceData.currentPower;
281
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${(0, super_stringify_1.default)(ad.serviceData)}`);
282
+ /*this.debugLog(
283
+ `${this.device.deviceType}: ${this.accessory.displayName} state: ${ad.serviceData.state}, ` +
284
+ `delay: ${ad.serviceData.delay}, timer: ${ad.serviceData.timer}, syncUtcTime: ${ad.serviceData.syncUtcTime} ` +
285
+ `wifiRssi: ${ad.serviceData.wifiRssi}, overload: ${ad.serviceData.overload}, currentPower: ${ad.serviceData.currentPower}`,
286
+ );*/
287
+ if (this.serviceData) {
288
+ this.connected = true;
289
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.connected}`);
290
+ }
291
+ else {
292
+ this.connected = false;
293
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.connected}`);
294
+ }
295
+ };
296
+ // Wait 2 seconds
297
+ return switchbot.wait(this.scanDuration * 1000);
298
+ })
299
+ .then(async () => {
300
+ // Stop to monitor
301
+ switchbot.stopScan();
302
+ if (this.connected) {
303
+ this.BLEparseStatus();
304
+ this.updateHomeKitCharacteristics();
305
+ }
306
+ else {
307
+ await this.BLERefreshConnection(switchbot);
308
+ }
309
+ })
310
+ .catch(async (e) => {
311
+ this.apiError(e);
312
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}`
313
+ + ` Connection, Error Message: ${(0, super_stringify_1.default)(e.message)}`);
314
+ await this.BLERefreshConnection(switchbot);
315
+ });
316
+ }
317
+ else {
318
+ await this.BLERefreshConnection(switchbot);
319
+ }
320
+ }
321
+ async openAPIRefreshStatus() {
322
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
323
+ try {
324
+ const t = Date.now();
325
+ const nonce = 'requestID';
326
+ const data = this.platform.config.credentials?.token + t + nonce;
327
+ const signTerm = crypto_1.default.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
328
+ const sign = signTerm.toString('base64');
329
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
330
+ const options = {
331
+ hostname: settings_1.HostDomain,
332
+ port: 443,
333
+ path: `${settings_1.DevicePath}/${this.device.deviceId}/status`,
334
+ method: 'GET',
335
+ headers: {
336
+ Authorization: this.platform.config.credentials?.token,
337
+ sign: sign,
338
+ nonce: nonce,
339
+ t: t,
340
+ 'Content-Type': 'application/json',
341
+ },
342
+ };
343
+ const req = https_1.default.request(options, (res) => {
344
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus statusCode: ${res.statusCode}`);
345
+ this.statusCode({ res });
346
+ let rawData = '';
347
+ res.on('data', (d) => {
348
+ rawData += d;
349
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
350
+ });
351
+ res.on('end', () => {
352
+ try {
353
+ this.deviceStatus = JSON.parse(rawData);
354
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus: ${(0, super_stringify_1.default)(this.deviceStatus)}`);
355
+ this.power = this.deviceStatus.body.power;
356
+ this.color = this.deviceStatus.body.color;
357
+ this.brightness = this.deviceStatus.body.brightness;
358
+ this.colorTemperature = this.deviceStatus.body.colorTemperature;
359
+ this.openAPIparseStatus();
360
+ this.updateHomeKitCharacteristics();
361
+ }
362
+ catch (e) {
363
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
364
+ }
365
+ });
366
+ });
367
+ req.on('error', (e) => {
368
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
369
+ });
370
+ req.end();
371
+ }
372
+ catch (e) {
373
+ this.apiError(e);
374
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
375
+ + ` Connection, Error Message: ${(0, super_stringify_1.default)(e.message)}`);
376
+ }
377
+ }
378
+ /**
379
+ * Pushes the requested changes to the SwitchBot API
380
+ * deviceType commandType Command command parameter Description
381
+ * Color Bulb - "command" "turnOff" "default" = set to OFF state
382
+ * Color Bulb - "command" "turnOn" "default" = set to ON state
383
+ * Color Bulb - "command" "toggle" "default" = toggle state
384
+ * Color Bulb - "command" "setBrightness" "{1-100}" = set brightness
385
+ * Color Bulb - "command" "setColor" "{0-255}:{0-255}:{0-255}" = set RGB color value
386
+ * Color Bulb - "command" "setColorTemperature" "{2700-6500}" = set color temperature
387
+ *
388
+ */
389
+ async pushChanges() {
390
+ /*if (this.BLE) {
391
+ await this.BLEpushChanges();
392
+ } else*/ if (this.OpenAPI && this.platform.config.credentials?.token) {
393
+ await this.openAPIpushChanges();
394
+ }
395
+ else {
396
+ this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
397
+ + ` ${this.device.connectionType}, pushChanges will not happen.`);
398
+ }
399
+ (0, rxjs_1.interval)(5000)
400
+ .pipe((0, operators_1.take)(1))
401
+ .subscribe(async () => {
402
+ await this.refreshStatus();
403
+ });
404
+ }
405
+ async BLEpushChanges() {
406
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
407
+ if (this.On !== this.accessory.context.On) {
408
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges On: ${this.On} OnCached: ${this.accessory.context.On}`);
409
+ const switchbot = await this.platform.connectBLE();
410
+ // Convert to BLE Address
411
+ this.device.bleMac = this.device
412
+ .deviceId.match(/.{1,2}/g)
413
+ .join(':')
414
+ .toLowerCase();
415
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
416
+ switchbot
417
+ .discover({
418
+ model: 'u',
419
+ id: this.device.bleMac,
420
+ })
421
+ .then((device_list) => {
422
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
423
+ return this.turnOnOff(device_list);
424
+ })
425
+ .then(() => {
426
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
427
+ this.On = false;
428
+ })
429
+ .catch(async (e) => {
430
+ this.apiError(e);
431
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
432
+ + ` Connection, Error Message: ${(0, super_stringify_1.default)(e.message)}`);
433
+ await this.BLEPushConnection();
434
+ });
435
+ }
436
+ else {
437
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges.` + `On: ${this.On}, `
438
+ + `OnCached: ${this.accessory.context.On}`);
439
+ }
440
+ }
441
+ async openAPIpushChanges() {
442
+ try {
443
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
444
+ if (this.On !== this.accessory.context.On) {
445
+ // Make Push On request to the API
446
+ const t = Date.now();
447
+ const nonce = 'requestID';
448
+ const data = this.platform.config.credentials?.token + t + nonce;
449
+ const signTerm = crypto_1.default.createHmac('sha256', this.platform.config.credentials?.secret)
450
+ .update(Buffer.from(data, 'utf-8'))
451
+ .digest();
452
+ const sign = signTerm.toString('base64');
453
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
454
+ let command = '';
455
+ if (this.On) {
456
+ command = 'turnOn';
457
+ }
458
+ else {
459
+ command = 'turnOff';
460
+ }
461
+ const body = (0, super_stringify_1.default)({
462
+ 'command': `${command}`,
463
+ 'parameter': 'default',
464
+ 'commandType': 'command',
465
+ });
466
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
467
+ const options = {
468
+ hostname: settings_1.HostDomain,
469
+ port: 443,
470
+ path: `${settings_1.DevicePath}/${this.device.deviceId}/commands`,
471
+ method: 'POST',
472
+ headers: {
473
+ 'Authorization': this.platform.config.credentials?.token,
474
+ 'sign': sign,
475
+ 'nonce': nonce,
476
+ 't': t,
477
+ 'Content-Type': 'application/json',
478
+ 'Content-Length': body.length,
479
+ },
480
+ };
481
+ const req = https_1.default.request(options, res => {
482
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges statusCode: ${res.statusCode}`);
483
+ this.statusCode({ res });
484
+ res.on('data', d => {
485
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
486
+ });
487
+ });
488
+ req.on('error', (e) => {
489
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
490
+ });
491
+ req.write(body);
492
+ req.end();
493
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushChanges: ${(0, super_stringify_1.default)(req)}`);
494
+ }
495
+ else {
496
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges.` + `On: ${this.On}, `
497
+ + `OnCached: ${this.accessory.context.On}`);
498
+ }
499
+ // Push Brightness Update
500
+ if (this.On) {
501
+ await this.pushBrightnessChanges();
502
+ }
503
+ // Push ColorTemperature Update
504
+ if (this.On) {
505
+ await this.pushColorTemperatureChanges();
506
+ }
507
+ // Push Hue & Saturation Update
508
+ if (this.On) {
509
+ await this.pushHueSaturationChanges();
510
+ }
511
+ }
512
+ catch (e) {
513
+ this.apiError(e);
514
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
515
+ + ` Connection, Error Message: ${(0, super_stringify_1.default)(e.message)}`);
516
+ }
517
+ }
518
+ async pushHueSaturationChanges() {
519
+ try {
520
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushHueSaturationChanges`);
521
+ if (this.Hue !== this.accessory.context.Hue || this.Saturation !== this.accessory.context.Saturation) {
522
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Hue: ${(0, super_stringify_1.default)(this.Hue)}`);
523
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Saturation: ${(0, super_stringify_1.default)(this.Saturation)}`);
524
+ const [red, green, blue] = (0, settings_1.hs2rgb)(Number(this.Hue), Number(this.Saturation));
525
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} rgb: ${(0, super_stringify_1.default)([red, green, blue])}`);
526
+ // Make Push Hue/Saturation request to the API
527
+ const t = Date.now();
528
+ const nonce = 'requestID';
529
+ const data = this.platform.config.credentials?.token + t + nonce;
530
+ const signTerm = crypto_1.default.createHmac('sha256', this.platform.config.credentials?.secret)
531
+ .update(Buffer.from(data, 'utf-8'))
532
+ .digest();
533
+ const sign = signTerm.toString('base64');
534
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
535
+ const body = (0, super_stringify_1.default)({
536
+ 'command': 'setColor',
537
+ 'parameter': `${red}:${green}:${blue}`,
538
+ 'commandType': 'command',
539
+ });
540
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
541
+ const options = {
542
+ hostname: settings_1.HostDomain,
543
+ port: 443,
544
+ path: `${settings_1.DevicePath}/${this.device.deviceId}/commands`,
545
+ method: 'POST',
546
+ headers: {
547
+ 'Authorization': this.platform.config.credentials?.token,
548
+ 'sign': sign,
549
+ 'nonce': nonce,
550
+ 't': t,
551
+ 'Content-Type': 'application/json',
552
+ 'Content-Length': body.length,
553
+ },
554
+ };
555
+ const req = https_1.default.request(options, res => {
556
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushHueSaturationChanges statusCode: ${res.statusCode}`);
557
+ res.on('data', d => {
558
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
559
+ });
560
+ });
561
+ req.on('error', (e) => {
562
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
563
+ });
564
+ req.write(body);
565
+ req.end();
566
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushHueSaturationChanges: ${(0, super_stringify_1.default)(req)}`);
567
+ }
568
+ else {
569
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No pushHueSaturationChanges. Hue: ${this.Hue}, `
570
+ + `HueCached: ${this.accessory.context.Hue}, Saturation: ${this.Saturation}, SaturationCached: ${this.accessory.context.Saturation}`);
571
+ }
572
+ }
573
+ catch (e) {
574
+ this.apiError(e);
575
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushHueSaturationChanges with ${this.device.connectionType}`
576
+ + ` Connection, Error Message: ${(0, super_stringify_1.default)(e.message)}`);
577
+ }
578
+ }
579
+ async pushColorTemperatureChanges() {
580
+ try {
581
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushColorTemperatureChanges`);
582
+ if (this.ColorTemperature !== this.accessory.context.ColorTemperature) {
583
+ const kelvin = Math.round(1000000 / Number(this.ColorTemperature));
584
+ this.cacheKelvin = kelvin;
585
+ // Make Push On request to the API
586
+ const t = Date.now();
587
+ const nonce = 'requestID';
588
+ const data = this.platform.config.credentials?.token + t + nonce;
589
+ const signTerm = crypto_1.default.createHmac('sha256', this.platform.config.credentials?.secret)
590
+ .update(Buffer.from(data, 'utf-8'))
591
+ .digest();
592
+ const sign = signTerm.toString('base64');
593
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
594
+ const body = (0, super_stringify_1.default)({
595
+ 'command': 'setColorTemperature',
596
+ 'parameter': `${kelvin}`,
597
+ 'commandType': 'command',
598
+ });
599
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
600
+ const options = {
601
+ hostname: settings_1.HostDomain,
602
+ port: 443,
603
+ path: `${settings_1.DevicePath}/${this.device.deviceId}/commands`,
604
+ method: 'POST',
605
+ headers: {
606
+ 'Authorization': this.platform.config.credentials?.token,
607
+ 'sign': sign,
608
+ 'nonce': nonce,
609
+ 't': t,
610
+ 'Content-Type': 'application/json',
611
+ 'Content-Length': body.length,
612
+ },
613
+ };
614
+ const req = https_1.default.request(options, res => {
615
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
616
+ res.on('data', d => {
617
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
618
+ });
619
+ });
620
+ req.on('error', (e) => {
621
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
622
+ });
623
+ req.write(body);
624
+ req.end();
625
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushColorTemperatureChanges: ${(0, super_stringify_1.default)(req)}`);
626
+ this.accessory.context.ColorTemperature = this.ColorTemperature;
627
+ }
628
+ else {
629
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No pushColorTemperatureChanges.` +
630
+ `ColorTemperature: ${this.ColorTemperature}, ColorTemperatureCached: ${this.accessory.context.ColorTemperature}`);
631
+ }
632
+ }
633
+ catch (e) {
634
+ this.apiError(e);
635
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushColorTemperatureChanges with ${this.device.connectionType}`
636
+ + ` Connection, Error Message: ${(0, super_stringify_1.default)(e.message)}`);
637
+ }
638
+ }
639
+ async pushBrightnessChanges() {
640
+ try {
641
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushBrightnessChanges`);
642
+ if (this.Brightness !== this.accessory.context.Brightness) {
643
+ // Make Push On request to the API
644
+ const t = Date.now();
645
+ const nonce = 'requestID';
646
+ const data = this.platform.config.credentials?.token + t + nonce;
647
+ const signTerm = crypto_1.default.createHmac('sha256', this.platform.config.credentials?.secret)
648
+ .update(Buffer.from(data, 'utf-8'))
649
+ .digest();
650
+ const sign = signTerm.toString('base64');
651
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
652
+ const body = (0, super_stringify_1.default)({
653
+ 'command': 'setBrightness',
654
+ 'parameter': `${this.Brightness}`,
655
+ 'commandType': 'command',
656
+ });
657
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
658
+ const options = {
659
+ hostname: settings_1.HostDomain,
660
+ port: 443,
661
+ path: `${settings_1.DevicePath}/${this.device.deviceId}/commands`,
662
+ method: 'POST',
663
+ headers: {
664
+ 'Authorization': this.platform.config.credentials?.token,
665
+ 'sign': sign,
666
+ 'nonce': nonce,
667
+ 't': t,
668
+ 'Content-Type': 'application/json',
669
+ 'Content-Length': body.length,
670
+ },
671
+ };
672
+ const req = https_1.default.request(options, res => {
673
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushBrightnessChanges statusCode: ${res.statusCode}`);
674
+ res.on('data', d => {
675
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
676
+ });
677
+ });
678
+ req.on('error', (e) => {
679
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
680
+ });
681
+ req.write(body);
682
+ req.end();
683
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushBrightnessChanges: ${(0, super_stringify_1.default)(req)}`);
684
+ }
685
+ else {
686
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No pushBrightnessChanges.` + `Brightness: ${this.Brightness}, `
687
+ + `BrightnessCached: ${this.accessory.context.Brightness}`);
688
+ }
689
+ }
690
+ catch (e) {
691
+ this.apiError(e);
692
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushBrightnessChanges with ${this.device.connectionType}`
693
+ + ` Connection, Error Message: ${(0, super_stringify_1.default)(e.message)}`);
694
+ }
695
+ }
696
+ /**
697
+ * Handle requests to set the value of the "On" characteristic
698
+ */
699
+ async OnSet(value) {
700
+ if (this.On === this.accessory.context.On) {
701
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set On: ${value}`);
702
+ }
703
+ else {
704
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set On: ${value}`);
705
+ }
706
+ this.On = value;
707
+ this.doCeilingLightUpdate.next();
708
+ }
709
+ /**
710
+ * Handle requests to set the value of the "Brightness" characteristic
711
+ */
712
+ async BrightnessSet(value) {
713
+ if (this.Brightness === this.accessory.context.Brightness) {
714
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set Brightness: ${value}`);
715
+ }
716
+ else if (this.On) {
717
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Brightness: ${value}`);
718
+ }
719
+ else {
720
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Brightness: ${value}`);
721
+ }
722
+ this.Brightness = value;
723
+ this.doCeilingLightUpdate.next();
724
+ }
725
+ /**
726
+ * Handle requests to set the value of the "ColorTemperature" characteristic
727
+ */
728
+ async ColorTemperatureSet(value) {
729
+ if (this.ColorTemperature === this.accessory.context.ColorTemperature) {
730
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set ColorTemperature: ${value}`);
731
+ }
732
+ else if (this.On) {
733
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set ColorTemperature: ${value}`);
734
+ }
735
+ else {
736
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Set ColorTemperature: ${value}`);
737
+ }
738
+ // Convert mired to kelvin to nearest 100 (SwitchBot seems to need this)
739
+ const kelvin = Math.round(1000000 / Number(value) / 100) * 100;
740
+ // Check and increase/decrease kelvin to range of device
741
+ const k = Math.min(Math.max(kelvin, this.minKelvin), this.maxKelvin);
742
+ if (!this.accessory.context.On || this.cacheKelvin === k) {
743
+ return;
744
+ }
745
+ // Updating the hue/sat to the corresponding values mimics native adaptive lighting
746
+ const hs = (0, settings_1.m2hs)(value);
747
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Hue, hs[0]);
748
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Saturation, hs[1]);
749
+ this.ColorTemperature = value;
750
+ this.doCeilingLightUpdate.next();
751
+ }
752
+ /**
753
+ * Handle requests to set the value of the "Hue" characteristic
754
+ */
755
+ async HueSet(value) {
756
+ if (this.Hue === this.accessory.context.Hue) {
757
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set Hue: ${value}`);
758
+ }
759
+ else if (this.On) {
760
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Hue: ${value}`);
761
+ }
762
+ else {
763
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Hue: ${value}`);
764
+ }
765
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.ColorTemperature, 140);
766
+ this.Hue = value;
767
+ this.doCeilingLightUpdate.next();
768
+ }
769
+ /**
770
+ * Handle requests to set the value of the "Saturation" characteristic
771
+ */
772
+ async SaturationSet(value) {
773
+ if (this.Saturation === this.accessory.context.Saturation) {
774
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set Saturation: ${value}`);
775
+ }
776
+ else if (this.On) {
777
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Saturation: ${value}`);
778
+ }
779
+ else {
780
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Saturation: ${value}`);
781
+ }
782
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.ColorTemperature, 140);
783
+ this.Saturation = value;
784
+ this.doCeilingLightUpdate.next();
785
+ }
786
+ async updateHomeKitCharacteristics() {
787
+ if (this.On === undefined) {
788
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
789
+ }
790
+ else {
791
+ this.accessory.context.On = this.On;
792
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.On, this.On);
793
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
794
+ }
795
+ if (this.Brightness === undefined) {
796
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Brightness: ${this.Brightness}`);
797
+ }
798
+ else {
799
+ this.accessory.context.Brightness = this.Brightness;
800
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Brightness, this.Brightness);
801
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Brightness: ${this.Brightness}`);
802
+ }
803
+ if (this.ColorTemperature === undefined) {
804
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ColorTemperature: ${this.ColorTemperature}`);
805
+ }
806
+ else {
807
+ this.accessory.context.ColorTemperature = this.ColorTemperature;
808
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.ColorTemperature, this.ColorTemperature);
809
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic ColorTemperature: ${this.ColorTemperature}`);
810
+ }
811
+ if (this.Hue === undefined) {
812
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Hue: ${this.Hue}`);
813
+ }
814
+ else {
815
+ this.accessory.context.Hue = this.Hue;
816
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Hue, this.Hue);
817
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Hue: ${this.Hue}`);
818
+ }
819
+ if (this.Saturation === undefined) {
820
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Saturation: ${this.Saturation}`);
821
+ }
822
+ else {
823
+ this.accessory.context.Saturation = this.Saturation;
824
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Saturation, this.Saturation);
825
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Saturation: ${this.Saturation}`);
826
+ }
827
+ }
828
+ async adaptiveLighting(device) {
829
+ if (device.ceilinglight?.adaptiveLightingShift) {
830
+ this.adaptiveLightingShift = device.ceilinglight.adaptiveLightingShift;
831
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} adaptiveLightingShift: ${this.adaptiveLightingShift}`);
832
+ }
833
+ else {
834
+ this.adaptiveLightingShift = 0;
835
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} adaptiveLightingShift: ${this.adaptiveLightingShift}`);
836
+ }
837
+ }
838
+ async getCustomBLEAddress(switchbot) {
839
+ if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
840
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} customBLEaddress: ${this.device.customBLEaddress}`);
841
+ (async () => {
842
+ // Start to monitor advertisement packets
843
+ await switchbot.startScan({
844
+ model: 'u',
845
+ });
846
+ // Set an event handler
847
+ switchbot.onadvertisement = (ad) => {
848
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${(0, super_stringify_1.default)(ad, null, ' ')}`);
849
+ };
850
+ await switchbot.wait(10000);
851
+ // Stop to monitor
852
+ switchbot.stopScan();
853
+ })();
854
+ }
855
+ }
856
+ async BLEPushConnection() {
857
+ if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
858
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Push Changes`);
859
+ await this.openAPIpushChanges();
860
+ }
861
+ }
862
+ async BLERefreshConnection(switchbot) {
863
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
864
+ if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
865
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Refresh Status`);
866
+ await this.openAPIRefreshStatus();
867
+ }
868
+ }
869
+ async turnOnOff(device_list) {
870
+ return await this.retry({
871
+ max: await this.maxRetry(),
872
+ fn: () => {
873
+ if (this.On) {
874
+ return device_list[0].turnOn({ id: this.device.bleMac });
875
+ }
876
+ else {
877
+ return device_list[0].turnOff({ id: this.device.bleMac });
878
+ }
879
+ },
880
+ });
881
+ }
882
+ async retry({ max, fn }) {
883
+ return fn().catch(async (err) => {
884
+ if (max === 0) {
885
+ throw err;
886
+ }
887
+ this.infoLog(err);
888
+ this.infoLog('Retrying');
889
+ await this.switchbot.wait(1000);
890
+ return this.retry({ max: max - 1, fn });
891
+ });
892
+ }
893
+ async maxRetry() {
894
+ let maxRetry;
895
+ if (this.device.bot?.maxRetry) {
896
+ maxRetry = this.device.bot?.maxRetry;
897
+ }
898
+ else {
899
+ maxRetry = 5;
900
+ }
901
+ return maxRetry;
902
+ }
903
+ minStep(device) {
904
+ if (device.ceilinglight?.set_minStep) {
905
+ this.set_minStep = device.ceilinglight?.set_minStep;
906
+ }
907
+ else {
908
+ this.set_minStep = 1;
909
+ }
910
+ return this.set_minStep;
911
+ }
912
+ async scan(device) {
913
+ if (device.scanDuration) {
914
+ this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
915
+ if (this.BLE) {
916
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
917
+ }
918
+ }
919
+ else {
920
+ this.scanDuration = this.accessory.context.scanDuration = 1;
921
+ if (this.BLE) {
922
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
923
+ }
924
+ }
925
+ }
926
+ async statusCode({ res }) {
927
+ switch (res.statusCode) {
928
+ case 151:
929
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this device type.`);
930
+ break;
931
+ case 152:
932
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found.`);
933
+ break;
934
+ case 160:
935
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported.`);
936
+ break;
937
+ case 161:
938
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline.`);
939
+ this.offlineOff();
940
+ break;
941
+ case 171:
942
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} is offline. Hub: ${this.device.hubDeviceId}`);
943
+ this.offlineOff();
944
+ break;
945
+ case 190:
946
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
947
+ ` Or command: ${(0, super_stringify_1.default)(res)} format is invalid`);
948
+ break;
949
+ case 100:
950
+ if (this.platform.debugMode) {
951
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent.`);
952
+ }
953
+ break;
954
+ default:
955
+ if (this.platform.debugMode) {
956
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode.`);
957
+ }
958
+ }
959
+ }
960
+ async offlineOff() {
961
+ if (this.device.offline) {
962
+ this.On = false;
963
+ this.lightBulbService.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
964
+ await this.updateHomeKitCharacteristics();
965
+ }
966
+ }
967
+ apiError(e) {
968
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.On, e);
969
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Hue, e);
970
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Brightness, e);
971
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Saturation, e);
972
+ this.lightBulbService.updateCharacteristic(this.platform.Characteristic.ColorTemperature, e);
973
+ }
974
+ FirmwareRevision(accessory, device) {
975
+ let FirmwareRevision;
976
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
977
+ + ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
978
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
979
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
980
+ if (accessory.context.FirmwareRevision) {
981
+ FirmwareRevision = accessory.context.FirmwareRevision;
982
+ }
983
+ else if (device.firmware) {
984
+ FirmwareRevision = device.firmware;
985
+ }
986
+ else {
987
+ FirmwareRevision = this.platform.version;
988
+ }
989
+ return FirmwareRevision;
990
+ }
991
+ context() {
992
+ if (this.On === undefined) {
993
+ this.On = false;
994
+ }
995
+ else {
996
+ this.On = this.accessory.context.On;
997
+ }
998
+ if (this.Hue === undefined) {
999
+ this.Hue = 0;
1000
+ }
1001
+ else {
1002
+ this.Hue = this.accessory.context.Hue;
1003
+ }
1004
+ if (this.Brightness === undefined) {
1005
+ this.Brightness = 0;
1006
+ }
1007
+ else {
1008
+ this.Brightness = this.accessory.context.Brightness;
1009
+ }
1010
+ if (this.Brightness === undefined) {
1011
+ this.Saturation = 0;
1012
+ }
1013
+ else {
1014
+ this.Saturation = this.accessory.context.Saturation;
1015
+ }
1016
+ if (this.ColorTemperature === undefined) {
1017
+ this.ColorTemperature = 140;
1018
+ }
1019
+ else {
1020
+ this.ColorTemperature = this.accessory.context.ColorTemperature;
1021
+ }
1022
+ this.minKelvin = 2000;
1023
+ this.maxKelvin = 9000;
1024
+ }
1025
+ async refreshRate(device) {
1026
+ if (device.refreshRate) {
1027
+ this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
1028
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
1029
+ }
1030
+ else if (this.platform.config.options.refreshRate) {
1031
+ this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options.refreshRate;
1032
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
1033
+ }
1034
+ }
1035
+ async config(device) {
1036
+ let config = {};
1037
+ if (device.ceilinglight) {
1038
+ config = device.ceilinglight;
1039
+ }
1040
+ if (device.connectionType !== undefined) {
1041
+ config['connectionType'] = device.connectionType;
1042
+ }
1043
+ if (device.external !== undefined) {
1044
+ config['external'] = device.external;
1045
+ }
1046
+ if (device.logging !== undefined) {
1047
+ config['logging'] = device.logging;
1048
+ }
1049
+ if (device.refreshRate !== undefined) {
1050
+ config['refreshRate'] = device.refreshRate;
1051
+ }
1052
+ if (device.scanDuration !== undefined) {
1053
+ config['scanDuration'] = device.scanDuration;
1054
+ }
1055
+ if (device.offline !== undefined) {
1056
+ config['offline'] = device.offline;
1057
+ }
1058
+ if (Object.entries(config).length !== 0) {
1059
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${(0, super_stringify_1.default)(config)}`);
1060
+ }
1061
+ }
1062
+ async logs(device) {
1063
+ if (this.platform.debugMode) {
1064
+ this.deviceLogging = this.accessory.context.logging = 'debugMode';
1065
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
1066
+ }
1067
+ else if (device.logging) {
1068
+ this.deviceLogging = this.accessory.context.logging = device.logging;
1069
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
1070
+ }
1071
+ else if (this.platform.config.options?.logging) {
1072
+ this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
1073
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
1074
+ }
1075
+ else {
1076
+ this.deviceLogging = this.accessory.context.logging = 'standard';
1077
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
1078
+ }
1079
+ }
1080
+ /**
1081
+ * Logging for Device
1082
+ */
1083
+ infoLog(...log) {
1084
+ if (this.enablingDeviceLogging()) {
1085
+ this.platform.log.info(String(...log));
1086
+ }
1087
+ }
1088
+ warnLog(...log) {
1089
+ if (this.enablingDeviceLogging()) {
1090
+ this.platform.log.warn(String(...log));
1091
+ }
1092
+ }
1093
+ debugWarnLog(...log) {
1094
+ if (this.enablingDeviceLogging()) {
1095
+ if (this.deviceLogging?.includes('debug')) {
1096
+ this.platform.log.warn('[DEBUG]', String(...log));
1097
+ }
1098
+ }
1099
+ }
1100
+ errorLog(...log) {
1101
+ if (this.enablingDeviceLogging()) {
1102
+ this.platform.log.error(String(...log));
1103
+ }
1104
+ }
1105
+ debugErrorLog(...log) {
1106
+ if (this.enablingDeviceLogging()) {
1107
+ if (this.deviceLogging?.includes('debug')) {
1108
+ this.platform.log.error('[DEBUG]', String(...log));
1109
+ }
1110
+ }
1111
+ }
1112
+ debugLog(...log) {
1113
+ if (this.enablingDeviceLogging()) {
1114
+ if (this.deviceLogging === 'debug') {
1115
+ this.platform.log.info('[DEBUG]', String(...log));
1116
+ }
1117
+ else {
1118
+ this.platform.log.debug(String(...log));
1119
+ }
1120
+ }
1121
+ }
1122
+ enablingDeviceLogging() {
1123
+ return this.deviceLogging.includes('debug') || this.deviceLogging === 'standard';
1124
+ }
1125
+ }
1126
+ exports.CeilingLight = CeilingLight;
1127
+ //# sourceMappingURL=ceilinglight.js.map