@switchbot/homebridge-switchbot 2.0.0-beta.19 → 2.0.0-beta.20
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.
- package/CHANGELOG.md +6 -1
- package/README.md +1 -2
- package/config.schema.json +51 -32
- package/dist/device/bot.d.ts +32 -29
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +549 -575
- package/dist/device/bot.js.map +1 -1
- package/dist/device/colorbulb.d.ts +33 -15
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +426 -341
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts +16 -9
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +246 -208
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts +21 -18
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +449 -449
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/humidifier.d.ts +22 -20
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +346 -324
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/lock.d.ts +22 -10
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +257 -178
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +21 -14
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +287 -239
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +23 -10
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +308 -190
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts +17 -10
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +225 -193
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +24 -17
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +270 -267
- package/dist/device/plug.js.map +1 -1
- package/dist/device/striplight.d.ts +36 -14
- package/dist/device/striplight.d.ts.map +1 -1
- package/dist/device/striplight.js +447 -299
- package/dist/device/striplight.js.map +1 -1
- package/dist/irdevice/airconditioner.d.ts +7 -14
- package/dist/irdevice/airconditioner.d.ts.map +1 -1
- package/dist/irdevice/airconditioner.js +177 -169
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts +3 -5
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +72 -57
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts +3 -4
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +47 -33
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts +3 -4
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +66 -48
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/light.d.ts +3 -4
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +48 -47
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts +3 -4
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +47 -33
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts +10 -11
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +64 -48
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts +7 -12
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +52 -41
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts +6 -11
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +52 -42
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +0 -4
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +44 -66
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +3 -3
- package/dist/settings.d.ts.map +1 -1
- package/package.json +7 -6
- package/src/device/bot.ts +551 -589
- package/src/device/colorbulb.ts +441 -375
- package/src/device/contact.ts +249 -213
- package/src/device/curtain.ts +452 -461
- package/src/device/humidifier.ts +358 -365
- package/src/device/lock.ts +263 -179
- package/src/device/meter.ts +302 -253
- package/src/device/meterplus.ts +319 -194
- package/src/device/motion.ts +230 -199
- package/src/device/plug.ts +273 -274
- package/src/device/striplight.ts +460 -316
- package/src/irdevice/airconditioner.ts +181 -183
- package/src/irdevice/airpurifier.ts +70 -60
- package/src/irdevice/camera.ts +46 -36
- package/src/irdevice/fan.ts +64 -49
- package/src/irdevice/light.ts +47 -51
- package/src/irdevice/other.ts +46 -36
- package/src/irdevice/tv.ts +64 -51
- package/src/irdevice/vacuumcleaner.ts +52 -45
- package/src/irdevice/waterheater.ts +50 -45
- package/src/platform.ts +44 -68
- package/src/settings.ts +3 -3
package/src/device/colorbulb.ts
CHANGED
|
@@ -48,7 +48,6 @@ export class ColorBulb {
|
|
|
48
48
|
deviceLogging!: string;
|
|
49
49
|
deviceRefreshRate!: number;
|
|
50
50
|
adaptiveLightingShift?: number;
|
|
51
|
-
OpenAPI?: boolean;
|
|
52
51
|
|
|
53
52
|
// Adaptive Lighting
|
|
54
53
|
AdaptiveLightingController?: ControllerConstructor | Controller<ControllerServiceMap>;
|
|
@@ -62,25 +61,18 @@ export class ColorBulb {
|
|
|
62
61
|
colorBulbUpdateInProgress!: boolean;
|
|
63
62
|
doColorBulbUpdate!: Subject<void>;
|
|
64
63
|
|
|
64
|
+
// Connection
|
|
65
|
+
private readonly BLE = (this.device.connectionType === 'BLE' || this.device.connectionType === 'Both');
|
|
66
|
+
private readonly OpenAPI = (this.device.connectionType === 'OpenAPI' || this.device.connectionType === 'Both');
|
|
67
|
+
|
|
65
68
|
constructor(private readonly platform: SwitchBotPlatform, private accessory: PlatformAccessory, public device: device & devicesConfig) {
|
|
66
69
|
// default placeholders
|
|
67
70
|
this.logs(device);
|
|
68
|
-
this.openAPI();
|
|
69
71
|
this.scan(device);
|
|
70
72
|
this.refreshRate(device);
|
|
71
73
|
this.adaptiveLighting(device);
|
|
72
74
|
this.config(device);
|
|
73
|
-
|
|
74
|
-
this.On = false;
|
|
75
|
-
} else {
|
|
76
|
-
this.On = this.accessory.context.On;
|
|
77
|
-
}
|
|
78
|
-
this.Hue = 0;
|
|
79
|
-
this.Brightness = 0;
|
|
80
|
-
this.Saturation = 0;
|
|
81
|
-
this.ColorTemperature = 140;
|
|
82
|
-
this.minKelvin = 2000;
|
|
83
|
-
this.maxKelvin = 9000;
|
|
75
|
+
this.context();
|
|
84
76
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
85
77
|
this.doColorBulbUpdate = new Subject();
|
|
86
78
|
this.colorBulbUpdateInProgress = false;
|
|
@@ -211,12 +203,9 @@ export class ColorBulb {
|
|
|
211
203
|
try {
|
|
212
204
|
await this.pushChanges();
|
|
213
205
|
} catch (e: any) {
|
|
214
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges`);
|
|
215
|
-
if (this.deviceLogging.includes('debug')) {
|
|
216
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges,`
|
|
217
|
-
+ ` Error Message: ${superStringify(e.message)}`);
|
|
218
|
-
}
|
|
219
206
|
this.apiError(e);
|
|
207
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with ${this.device.connectionType} Connection,`
|
|
208
|
+
+ ` Error Message: ${superStringify(e.message)}`);
|
|
220
209
|
}
|
|
221
210
|
this.colorBulbUpdateInProgress = false;
|
|
222
211
|
// Refresh the status from the API
|
|
@@ -229,16 +218,23 @@ export class ColorBulb {
|
|
|
229
218
|
});
|
|
230
219
|
}
|
|
231
220
|
|
|
221
|
+
/**
|
|
222
|
+
* Parse the device status from the SwitchBot api
|
|
223
|
+
*/
|
|
232
224
|
async parseStatus(): Promise<void> {
|
|
233
|
-
if (this.
|
|
225
|
+
/*if (this.BLE && !this.SwitchToOpenAPI) {
|
|
226
|
+
await this.BLEparseStatus();
|
|
227
|
+
} else*/ if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
228
|
+
this.SwitchToOpenAPI = false;
|
|
234
229
|
await this.openAPIparseStatus();
|
|
235
230
|
} else {
|
|
236
|
-
|
|
231
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
232
|
+
+ ` ${this.device.connectionType}, parseStatus will not happen.`);
|
|
237
233
|
}
|
|
238
234
|
}
|
|
239
235
|
|
|
240
236
|
async BLEparseStatus(): Promise<void> {
|
|
241
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}
|
|
237
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
|
|
242
238
|
// State
|
|
243
239
|
switch (this.state) {
|
|
244
240
|
case 'on':
|
|
@@ -251,6 +247,7 @@ export class ColorBulb {
|
|
|
251
247
|
}
|
|
252
248
|
|
|
253
249
|
async openAPIparseStatus() {
|
|
250
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
|
|
254
251
|
switch (this.power) {
|
|
255
252
|
case 'on':
|
|
256
253
|
this.On = true;
|
|
@@ -297,16 +294,22 @@ export class ColorBulb {
|
|
|
297
294
|
}
|
|
298
295
|
}
|
|
299
296
|
|
|
297
|
+
/**
|
|
298
|
+
* Asks the SwitchBot API for the latest device information
|
|
299
|
+
*/
|
|
300
300
|
async refreshStatus(): Promise<void> {
|
|
301
|
-
if (this.
|
|
301
|
+
/*if (this.BLE) {
|
|
302
302
|
await this.BLERefreshStatus();
|
|
303
|
-
} else {
|
|
303
|
+
} else*/ if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
304
304
|
await this.openAPIRefreshStatus();
|
|
305
|
+
} else {
|
|
306
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
307
|
+
+ ` ${this.device.connectionType}, refreshStatus will not happen.`);
|
|
305
308
|
}
|
|
306
309
|
}
|
|
307
310
|
|
|
308
311
|
async BLERefreshStatus(): Promise<void> {
|
|
309
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}
|
|
312
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
|
|
310
313
|
const switchbot = await this.platform.connectBLE();
|
|
311
314
|
// Convert to BLE Address
|
|
312
315
|
this.device.bleMac = this.device
|
|
@@ -366,228 +369,232 @@ export class ColorBulb {
|
|
|
366
369
|
this.parseStatus();
|
|
367
370
|
this.updateHomeKitCharacteristics();
|
|
368
371
|
} else {
|
|
369
|
-
this.
|
|
370
|
-
if (this.platform.config.credentials?.token) {
|
|
371
|
-
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
372
|
-
this.SwitchToOpenAPI = true;
|
|
373
|
-
await this.openAPIRefreshStatus();
|
|
374
|
-
}
|
|
372
|
+
await this.BLEconnection(switchbot);
|
|
375
373
|
}
|
|
376
374
|
})
|
|
377
375
|
.catch(async (e: any) => {
|
|
378
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed refreshStatus with BLE Connection`);
|
|
379
|
-
if (this.deviceLogging.includes('debug')) {
|
|
380
|
-
this.errorLog(
|
|
381
|
-
`${this.device.deviceType}: ${this.accessory.displayName} failed refreshStatus with BLE Connection,`
|
|
382
|
-
+ ` Error Message: ${superStringify(e.message)}`,
|
|
383
|
-
);
|
|
384
|
-
}
|
|
385
|
-
if (this.platform.config.credentials?.token) {
|
|
386
|
-
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
387
|
-
this.SwitchToOpenAPI = true;
|
|
388
|
-
await this.openAPIRefreshStatus();
|
|
389
|
-
}
|
|
390
376
|
this.apiError(e);
|
|
377
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}`
|
|
378
|
+
+ ` Connection, Error Message: ${superStringify(e.message)}`);
|
|
379
|
+
await this.BLEconnection(switchbot);
|
|
391
380
|
});
|
|
392
381
|
} else {
|
|
393
382
|
await this.BLEconnection(switchbot);
|
|
394
383
|
}
|
|
395
384
|
}
|
|
396
385
|
|
|
397
|
-
async
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
386
|
+
async openAPIRefreshStatus() {
|
|
387
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
|
|
388
|
+
try {
|
|
389
|
+
const t = Date.now();
|
|
390
|
+
const nonce = 'requestID';
|
|
391
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
392
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
393
|
+
const sign = signTerm.toString('base64');
|
|
394
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
395
|
+
const options = {
|
|
396
|
+
hostname: HostDomain,
|
|
397
|
+
port: 443,
|
|
398
|
+
path: `${DevicePath}/${this.device.deviceId}/status`,
|
|
399
|
+
method: 'GET',
|
|
400
|
+
headers: {
|
|
401
|
+
Authorization: this.platform.config.credentials?.token,
|
|
402
|
+
sign: sign,
|
|
403
|
+
nonce: nonce,
|
|
404
|
+
t: t,
|
|
405
|
+
'Content-Type': 'application/json',
|
|
406
|
+
},
|
|
407
|
+
};
|
|
408
|
+
const req = https.request(options, (res) => {
|
|
409
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus statusCode: ${res.statusCode}`);
|
|
410
|
+
this.statusCode({ res });
|
|
411
|
+
let rawData = '';
|
|
412
|
+
res.on('data', (d) => {
|
|
413
|
+
rawData += d;
|
|
414
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
|
|
404
415
|
});
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
416
|
+
res.on('end', () => {
|
|
417
|
+
try {
|
|
418
|
+
this.deviceStatus = JSON.parse(rawData);
|
|
419
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus: ${superStringify(this.deviceStatus)}`);
|
|
420
|
+
this.power = this.deviceStatus.body.power;
|
|
421
|
+
this.color = this.deviceStatus.body.color;
|
|
422
|
+
this.brightness = this.deviceStatus.body.brightness;
|
|
423
|
+
this.colorTemperature = this.deviceStatus.body.colorTemperature;
|
|
424
|
+
this.parseStatus();
|
|
425
|
+
this.updateHomeKitCharacteristics();
|
|
426
|
+
} catch (e: any) {
|
|
427
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
req.on('error', (e: any) => {
|
|
432
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
433
|
+
});
|
|
434
|
+
req.end();
|
|
435
|
+
} catch (e: any) {
|
|
436
|
+
this.apiError(e);
|
|
437
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
|
|
438
|
+
+ ` Connection, Error Message: ${superStringify(e.message)}`);
|
|
413
439
|
}
|
|
414
440
|
}
|
|
415
441
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
442
|
+
/**
|
|
443
|
+
* Pushes the requested changes to the SwitchBot API
|
|
444
|
+
* deviceType commandType Command command parameter Description
|
|
445
|
+
* Color Bulb - "command" "turnOff" "default" = set to OFF state
|
|
446
|
+
* Color Bulb - "command" "turnOn" "default" = set to ON state
|
|
447
|
+
* Color Bulb - "command" "toggle" "default" = toggle state
|
|
448
|
+
* Color Bulb - "command" "setBrightness" "{1-100}" = set brightness
|
|
449
|
+
* Color Bulb - "command" "setColor" "{0-255}:{0-255}:{0-255}" = set RGB color value
|
|
450
|
+
* Color Bulb - "command" "setColorTemperature" "{2700-6500}" = set color temperature
|
|
451
|
+
*
|
|
452
|
+
*/
|
|
453
|
+
async pushChanges(): Promise<void> {
|
|
454
|
+
/*if (this.BLE) {
|
|
455
|
+
await this.BLERefreshStatus();
|
|
456
|
+
} else*/ if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
457
|
+
await this.openAPIpushChanges();
|
|
458
|
+
} else {
|
|
459
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
460
|
+
+ ` ${this.device.connectionType}, pushChanges will not happen.`);
|
|
422
461
|
}
|
|
462
|
+
interval(5000)
|
|
463
|
+
.pipe(take(1))
|
|
464
|
+
.subscribe(async () => {
|
|
465
|
+
await this.refreshStatus();
|
|
466
|
+
});
|
|
423
467
|
}
|
|
424
468
|
|
|
425
|
-
async
|
|
426
|
-
|
|
427
|
-
|
|
469
|
+
async BLEpushChanges(): Promise<void> {
|
|
470
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
|
|
471
|
+
if (this.On !== this.accessory.context.On) {
|
|
472
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges On: ${this.On} OnCached: ${this.accessory.context.On}`);
|
|
473
|
+
const switchbot = await this.platform.connectBLE();
|
|
474
|
+
// Convert to BLE Address
|
|
475
|
+
this.device.bleMac = this.device
|
|
476
|
+
.deviceId!.match(/.{1,2}/g)!
|
|
477
|
+
.join(':')
|
|
478
|
+
.toLowerCase();
|
|
479
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
480
|
+
switchbot
|
|
481
|
+
.discover({
|
|
482
|
+
model: 'u',
|
|
483
|
+
id: this.device.bleMac,
|
|
484
|
+
})
|
|
485
|
+
.then((device_list: any) => {
|
|
486
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
487
|
+
return this.turnOnOff(device_list);
|
|
488
|
+
})
|
|
489
|
+
.then(() => {
|
|
490
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
|
|
491
|
+
this.On = false;
|
|
492
|
+
})
|
|
493
|
+
.catch(async (e: any) => {
|
|
494
|
+
this.apiError(e);
|
|
495
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
|
|
496
|
+
+ ` Connection, Error Message: ${superStringify(e.message)}`);
|
|
497
|
+
if (this.platform.config.credentials?.token && this.device.connectionType !== 'Both') {
|
|
498
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
499
|
+
await this.openAPIpushChanges();
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
} else {
|
|
503
|
+
this.debugLog(
|
|
504
|
+
`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges.` + `On: ${this.On}, `
|
|
505
|
+
+`OnCached: ${this.accessory.context.On}`,
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
async openAPIpushChanges(): Promise<void> {
|
|
511
|
+
try {
|
|
512
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
|
|
513
|
+
if (this.On !== this.accessory.context.On) {
|
|
514
|
+
// Make Push On request to the API
|
|
428
515
|
const t = Date.now();
|
|
429
516
|
const nonce = 'requestID';
|
|
430
517
|
const data = this.platform.config.credentials?.token + t + nonce;
|
|
431
|
-
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
518
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
519
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
520
|
+
.digest();
|
|
432
521
|
const sign = signTerm.toString('base64');
|
|
433
522
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
523
|
+
|
|
524
|
+
let command = '';
|
|
525
|
+
if (this.On) {
|
|
526
|
+
command = 'turnOn';
|
|
527
|
+
} else {
|
|
528
|
+
command = 'turnOff';
|
|
529
|
+
}
|
|
530
|
+
const body = superStringify({
|
|
531
|
+
'command': `${command}`,
|
|
532
|
+
'parameter': 'default',
|
|
533
|
+
'commandType': 'command',
|
|
534
|
+
});
|
|
535
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
434
536
|
const options = {
|
|
435
537
|
hostname: HostDomain,
|
|
436
538
|
port: 443,
|
|
437
|
-
path: `${DevicePath}/${this.device.deviceId}/
|
|
438
|
-
method: '
|
|
539
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
540
|
+
method: 'POST',
|
|
439
541
|
headers: {
|
|
440
|
-
Authorization: this.platform.config.credentials?.token,
|
|
441
|
-
sign: sign,
|
|
442
|
-
nonce: nonce,
|
|
443
|
-
t: t,
|
|
542
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
543
|
+
'sign': sign,
|
|
544
|
+
'nonce': nonce,
|
|
545
|
+
't': t,
|
|
444
546
|
'Content-Type': 'application/json',
|
|
547
|
+
'Content-Length': body.length,
|
|
445
548
|
},
|
|
446
549
|
};
|
|
447
|
-
const req = https.request(options,
|
|
448
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}
|
|
449
|
-
|
|
450
|
-
res.on('data',
|
|
451
|
-
rawData += d;
|
|
550
|
+
const req = https.request(options, res => {
|
|
551
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges statusCode: ${res.statusCode}`);
|
|
552
|
+
this.statusCode({ res });
|
|
553
|
+
res.on('data', d => {
|
|
452
554
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
|
|
453
555
|
});
|
|
454
|
-
res.on('end', () => {
|
|
455
|
-
try {
|
|
456
|
-
this.deviceStatus = JSON.parse(rawData);
|
|
457
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} refreshStatus: ${superStringify(this.deviceStatus)}`);
|
|
458
|
-
this.power = this.deviceStatus.body.power;
|
|
459
|
-
this.color = this.deviceStatus.body.color;
|
|
460
|
-
this.brightness = this.deviceStatus.body.brightness;
|
|
461
|
-
this.colorTemperature = this.deviceStatus.body.colorTemperature;
|
|
462
|
-
this.parseStatus();
|
|
463
|
-
this.updateHomeKitCharacteristics();
|
|
464
|
-
} catch (e: any) {
|
|
465
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
466
|
-
}
|
|
467
|
-
});
|
|
468
556
|
});
|
|
469
557
|
req.on('error', (e: any) => {
|
|
470
558
|
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
471
559
|
});
|
|
560
|
+
req.write(body);
|
|
472
561
|
req.end();
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
this.
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
);
|
|
480
|
-
}
|
|
481
|
-
this.apiError(e);
|
|
562
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushChanges: ${superStringify(req)}`);
|
|
563
|
+
} else {
|
|
564
|
+
this.debugLog(
|
|
565
|
+
`${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges.` + `On: ${this.On}, `
|
|
566
|
+
+`OnCached: ${this.accessory.context.On}`,
|
|
567
|
+
);
|
|
482
568
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
/**
|
|
489
|
-
* Pushes the requested changes to the SwitchBot API
|
|
490
|
-
* deviceType commandType Command command parameter Description
|
|
491
|
-
* Color Bulb - "command" "turnOff" "default" = set to OFF state
|
|
492
|
-
* Color Bulb - "command" "turnOn" "default" = set to ON state
|
|
493
|
-
* Color Bulb - "command" "toggle" "default" = toggle state
|
|
494
|
-
* Color Bulb - "command" "setBrightness" "{1-100}" = set brightness
|
|
495
|
-
* Color Bulb - "command" "setColor" "{0-255}:{0-255}:{0-255}" = set RGB color value
|
|
496
|
-
* Color Bulb - "command" "setColorTemperature" "{2700-6500}" = set color temperature
|
|
497
|
-
*
|
|
498
|
-
*/
|
|
499
|
-
async pushChanges(): Promise<void> {
|
|
500
|
-
if (this.OpenAPI) {
|
|
501
|
-
try {
|
|
502
|
-
if (this.On !== this.accessory.context.On) {
|
|
503
|
-
// Make Push On request to the API
|
|
504
|
-
const t = Date.now();
|
|
505
|
-
const nonce = 'requestID';
|
|
506
|
-
const data = this.platform.config.credentials?.token + t + nonce;
|
|
507
|
-
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
508
|
-
.update(Buffer.from(data, 'utf-8'))
|
|
509
|
-
.digest();
|
|
510
|
-
const sign = signTerm.toString('base64');
|
|
511
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
512
|
-
|
|
513
|
-
let command = '';
|
|
514
|
-
if (this.On) {
|
|
515
|
-
command = 'turnOn';
|
|
516
|
-
} else {
|
|
517
|
-
command = 'turnOff';
|
|
518
|
-
}
|
|
519
|
-
const body = superStringify({
|
|
520
|
-
'command': `${command}`,
|
|
521
|
-
'parameter': 'default',
|
|
522
|
-
'commandType': 'command',
|
|
523
|
-
});
|
|
524
|
-
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
525
|
-
const options = {
|
|
526
|
-
hostname: HostDomain,
|
|
527
|
-
port: 443,
|
|
528
|
-
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
529
|
-
method: 'POST',
|
|
530
|
-
headers: {
|
|
531
|
-
'Authorization': this.platform.config.credentials?.token,
|
|
532
|
-
'sign': sign,
|
|
533
|
-
'nonce': nonce,
|
|
534
|
-
't': t,
|
|
535
|
-
'Content-Type': 'application/json',
|
|
536
|
-
'Content-Length': body.length,
|
|
537
|
-
},
|
|
538
|
-
};
|
|
539
|
-
const req = https.request(options, res => {
|
|
540
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
541
|
-
this.statusCode({ res });
|
|
542
|
-
res.on('data', d => {
|
|
543
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
|
|
544
|
-
});
|
|
545
|
-
});
|
|
546
|
-
req.on('error', (e: any) => {
|
|
547
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
548
|
-
});
|
|
549
|
-
req.write(body);
|
|
550
|
-
req.end();
|
|
551
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushChanges: ${superStringify(req)}`);
|
|
552
|
-
}
|
|
553
|
-
// Push Brightness Update
|
|
554
|
-
if (this.On) {
|
|
555
|
-
await this.pushBrightnessChanges();
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
// Push ColorTemperature Update
|
|
559
|
-
if (this.On) {
|
|
560
|
-
await this.pushColorTemperatureChanges();
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
// Push Hue & Saturation Update
|
|
564
|
-
if (this.On) {
|
|
565
|
-
await this.pushHueSaturationChanges();
|
|
566
|
-
}
|
|
567
|
-
} catch (e: any) {
|
|
568
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
|
|
569
|
-
if (this.deviceLogging.includes('debug')) {
|
|
570
|
-
this.errorLog(
|
|
571
|
-
`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
|
|
572
|
-
+ ` Error Message: ${superStringify(e.message)}`,
|
|
573
|
-
);
|
|
574
|
-
}
|
|
575
|
-
this.apiError(e);
|
|
569
|
+
// Push Brightness Update
|
|
570
|
+
if (this.On) {
|
|
571
|
+
await this.pushBrightnessChanges();
|
|
576
572
|
}
|
|
577
|
-
|
|
578
|
-
|
|
573
|
+
// Push ColorTemperature Update
|
|
574
|
+
if (this.On) {
|
|
575
|
+
await this.pushColorTemperatureChanges();
|
|
576
|
+
}
|
|
577
|
+
// Push Hue & Saturation Update
|
|
578
|
+
if (this.On) {
|
|
579
|
+
await this.pushHueSaturationChanges();
|
|
580
|
+
}
|
|
581
|
+
} catch (e: any) {
|
|
582
|
+
this.apiError(e);
|
|
583
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
|
|
584
|
+
+ ` Connection, Error Message: ${superStringify(e.message)}`,
|
|
585
|
+
);
|
|
579
586
|
}
|
|
580
587
|
}
|
|
581
588
|
|
|
582
589
|
async pushHueSaturationChanges(): Promise<void> {
|
|
583
590
|
try {
|
|
591
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushHueSaturationChanges`);
|
|
584
592
|
if (this.Hue !== this.accessory.context.Hue || this.Saturation !== this.accessory.context.Saturation) {
|
|
585
593
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Hue: ${superStringify(this.Hue)}`);
|
|
586
594
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Saturation: ${superStringify(this.Saturation)}`);
|
|
587
595
|
|
|
588
596
|
const [red, green, blue] = hs2rgb(Number(this.Hue), Number(this.Saturation));
|
|
589
597
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} rgb: ${superStringify([red, green, blue])}`);
|
|
590
|
-
|
|
591
598
|
// Make Push Hue/Saturation request to the API
|
|
592
599
|
const t = Date.now();
|
|
593
600
|
const nonce = 'requestID';
|
|
@@ -618,7 +625,7 @@ export class ColorBulb {
|
|
|
618
625
|
},
|
|
619
626
|
};
|
|
620
627
|
const req = https.request(options, res => {
|
|
621
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
628
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushHueSaturationChanges statusCode: ${res.statusCode}`);
|
|
622
629
|
res.on('data', d => {
|
|
623
630
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
|
|
624
631
|
});
|
|
@@ -630,26 +637,19 @@ export class ColorBulb {
|
|
|
630
637
|
req.end();
|
|
631
638
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushHueSaturationChanges: ${superStringify(req)}`);
|
|
632
639
|
} else {
|
|
633
|
-
this.debugLog(
|
|
634
|
-
|
|
635
|
-
`Hue: ${this.Hue}, HueCached: ${this.accessory.context.Hue}, Saturation: ${this.Saturation},`
|
|
636
|
-
+` SaturationCached: ${this.accessory.context.Saturation}`,
|
|
637
|
-
);
|
|
640
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No pushHueSaturationChanges. Hue: ${this.Hue}, `
|
|
641
|
+
+ `HueCached: ${this.accessory.context.Hue}, Saturation: ${this.Saturation}, SaturationCached: ${this.accessory.context.Saturation}`);
|
|
638
642
|
}
|
|
639
643
|
} catch (e: any) {
|
|
640
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
|
|
641
|
-
if (this.deviceLogging.includes('debug')) {
|
|
642
|
-
this.errorLog(
|
|
643
|
-
`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
|
|
644
|
-
+ ` Error Message: ${superStringify(e.message)}`,
|
|
645
|
-
);
|
|
646
|
-
}
|
|
647
644
|
this.apiError(e);
|
|
645
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushHueSaturationChanges with ${this.device.connectionType}`
|
|
646
|
+
+ ` Connection, Error Message: ${superStringify(e.message)}`);
|
|
648
647
|
}
|
|
649
648
|
}
|
|
650
649
|
|
|
651
650
|
async pushColorTemperatureChanges(): Promise<void> {
|
|
652
651
|
try {
|
|
652
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushColorTemperatureChanges`);
|
|
653
653
|
if (this.ColorTemperature !== this.accessory.context.ColorTemperature) {
|
|
654
654
|
const kelvin = Math.round(1000000 / Number(this.ColorTemperature));
|
|
655
655
|
this.cacheKelvin = kelvin;
|
|
@@ -694,29 +694,22 @@ export class ColorBulb {
|
|
|
694
694
|
});
|
|
695
695
|
req.write(body);
|
|
696
696
|
req.end();
|
|
697
|
-
|
|
698
697
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushColorTemperatureChanges: ${superStringify(req)}`);
|
|
699
698
|
this.accessory.context.ColorTemperature = this.ColorTemperature;
|
|
700
699
|
} else {
|
|
701
|
-
this.debugLog(
|
|
702
|
-
|
|
703
|
-
`ColorTemperature: ${this.ColorTemperature}, ColorTemperatureCached: ${this.accessory.context.ColorTemperature}`,
|
|
704
|
-
);
|
|
700
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No pushColorTemperatureChanges.` +
|
|
701
|
+
`ColorTemperature: ${this.ColorTemperature}, ColorTemperatureCached: ${this.accessory.context.ColorTemperature}`);
|
|
705
702
|
}
|
|
706
703
|
} catch (e: any) {
|
|
707
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
|
|
708
|
-
if (this.deviceLogging.includes('debug')) {
|
|
709
|
-
this.errorLog(
|
|
710
|
-
`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
|
|
711
|
-
+ ` Error Message: ${superStringify(e.message)}`,
|
|
712
|
-
);
|
|
713
|
-
}
|
|
714
704
|
this.apiError(e);
|
|
705
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushColorTemperatureChanges with ${this.device.connectionType}`
|
|
706
|
+
+ ` Connection, Error Message: ${superStringify(e.message)}`);
|
|
715
707
|
}
|
|
716
708
|
}
|
|
717
709
|
|
|
718
710
|
async pushBrightnessChanges(): Promise<void> {
|
|
719
711
|
try {
|
|
712
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushBrightnessChanges`);
|
|
720
713
|
if (this.Brightness !== this.accessory.context.Brightness) {
|
|
721
714
|
// Make Push On request to the API
|
|
722
715
|
const t = Date.now();
|
|
@@ -748,7 +741,7 @@ export class ColorBulb {
|
|
|
748
741
|
},
|
|
749
742
|
};
|
|
750
743
|
const req = https.request(options, res => {
|
|
751
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
744
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushBrightnessChanges statusCode: ${res.statusCode}`);
|
|
752
745
|
res.on('data', d => {
|
|
753
746
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
|
|
754
747
|
});
|
|
@@ -760,21 +753,83 @@ export class ColorBulb {
|
|
|
760
753
|
req.end();
|
|
761
754
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} pushBrightnessChanges: ${superStringify(req)}`);
|
|
762
755
|
} else {
|
|
763
|
-
this.debugLog(
|
|
764
|
-
|
|
765
|
-
+`BrightnessCached: ${this.accessory.context.Brightness}`,
|
|
766
|
-
);
|
|
756
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No pushBrightnessChanges.` + `Brightness: ${this.Brightness}, `
|
|
757
|
+
+`BrightnessCached: ${this.accessory.context.Brightness}`);
|
|
767
758
|
}
|
|
768
759
|
} catch (e: any) {
|
|
769
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
|
|
770
|
-
if (this.deviceLogging.includes('debug')) {
|
|
771
|
-
this.errorLog(
|
|
772
|
-
`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
|
|
773
|
-
+ ` Error Message: ${superStringify(e.message)}`,
|
|
774
|
-
);
|
|
775
|
-
}
|
|
776
760
|
this.apiError(e);
|
|
761
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushBrightnessChanges with ${this.device.connectionType}`
|
|
762
|
+
+ ` Connection, Error Message: ${superStringify(e.message)}`);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
/**
|
|
767
|
+
* Handle requests to set the value of the "On" characteristic
|
|
768
|
+
*/
|
|
769
|
+
async OnSet(value: CharacteristicValue): Promise<void> {
|
|
770
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set On: ${value}`);
|
|
771
|
+
|
|
772
|
+
this.On = value;
|
|
773
|
+
this.doColorBulbUpdate.next();
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
/**
|
|
777
|
+
* Handle requests to set the value of the "Brightness" characteristic
|
|
778
|
+
*/
|
|
779
|
+
async BrightnessSet(value: CharacteristicValue): Promise<void> {
|
|
780
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Brightness: ${value}`);
|
|
781
|
+
|
|
782
|
+
this.Brightness = value;
|
|
783
|
+
this.doColorBulbUpdate.next();
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
/**
|
|
787
|
+
* Handle requests to set the value of the "ColorTemperature" characteristic
|
|
788
|
+
*/
|
|
789
|
+
async ColorTemperatureSet(value: CharacteristicValue): Promise<void> {
|
|
790
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set ColorTemperature: ${value}`);
|
|
791
|
+
|
|
792
|
+
// Convert mired to kelvin to nearest 100 (SwitchBot seems to need this)
|
|
793
|
+
const kelvin = Math.round(1000000 / Number(value) / 100) * 100;
|
|
794
|
+
|
|
795
|
+
// Check and increase/decrease kelvin to range of device
|
|
796
|
+
const k = Math.min(Math.max(kelvin, this.minKelvin), this.maxKelvin);
|
|
797
|
+
|
|
798
|
+
if (!this.accessory.context.On || this.cacheKelvin === k) {
|
|
799
|
+
return;
|
|
777
800
|
}
|
|
801
|
+
|
|
802
|
+
// Updating the hue/sat to the corresponding values mimics native adaptive lighting
|
|
803
|
+
const hs = m2hs(value);
|
|
804
|
+
this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Hue, hs[0]);
|
|
805
|
+
this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Saturation, hs[1]);
|
|
806
|
+
|
|
807
|
+
this.ColorTemperature = value;
|
|
808
|
+
this.doColorBulbUpdate.next();
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
/**
|
|
812
|
+
* Handle requests to set the value of the "Hue" characteristic
|
|
813
|
+
*/
|
|
814
|
+
async HueSet(value: CharacteristicValue): Promise<void> {
|
|
815
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Hue: ${value}`);
|
|
816
|
+
|
|
817
|
+
this.lightBulbService.updateCharacteristic(this.platform.Characteristic.ColorTemperature, 140);
|
|
818
|
+
|
|
819
|
+
this.Hue = value;
|
|
820
|
+
this.doColorBulbUpdate.next();
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* Handle requests to set the value of the "Saturation" characteristic
|
|
825
|
+
*/
|
|
826
|
+
async SaturationSet(value: CharacteristicValue): Promise<void> {
|
|
827
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Saturation: ${value}`);
|
|
828
|
+
|
|
829
|
+
this.lightBulbService.updateCharacteristic(this.platform.Characteristic.ColorTemperature, 140);
|
|
830
|
+
|
|
831
|
+
this.Saturation = value;
|
|
832
|
+
this.doColorBulbUpdate.next();
|
|
778
833
|
}
|
|
779
834
|
|
|
780
835
|
async updateHomeKitCharacteristics(): Promise<void> {
|
|
@@ -795,7 +850,6 @@ export class ColorBulb {
|
|
|
795
850
|
if (this.ColorTemperature === undefined) {
|
|
796
851
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ColorTemperature: ${this.ColorTemperature}`);
|
|
797
852
|
} else {
|
|
798
|
-
|
|
799
853
|
this.accessory.context.ColorTemperature = this.ColorTemperature;
|
|
800
854
|
this.lightBulbService.updateCharacteristic(this.platform.Characteristic.ColorTemperature, this.ColorTemperature);
|
|
801
855
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic ColorTemperature: ${this.ColorTemperature}`);
|
|
@@ -816,13 +870,100 @@ export class ColorBulb {
|
|
|
816
870
|
}
|
|
817
871
|
}
|
|
818
872
|
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
873
|
+
async adaptiveLighting(device: device & devicesConfig): Promise<void> {
|
|
874
|
+
if (device.colorbulb?.adaptiveLightingShift) {
|
|
875
|
+
this.adaptiveLightingShift = device.colorbulb.adaptiveLightingShift;
|
|
876
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} adaptiveLightingShift: ${this.adaptiveLightingShift}`);
|
|
877
|
+
} else {
|
|
878
|
+
this.adaptiveLightingShift = 0;
|
|
879
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} adaptiveLightingShift: ${this.adaptiveLightingShift}`);
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
async getCustomBLEAddress(switchbot: any) {
|
|
884
|
+
if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
|
|
885
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} customBLEaddress: ${this.device.customBLEaddress}`);
|
|
886
|
+
(async () => {
|
|
887
|
+
// Start to monitor advertisement packets
|
|
888
|
+
await switchbot.startScan({
|
|
889
|
+
model: 'u',
|
|
890
|
+
});
|
|
891
|
+
// Set an event handler
|
|
892
|
+
switchbot.onadvertisement = (ad: any) => {
|
|
893
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${superStringify(ad, null, ' ')}`);
|
|
894
|
+
};
|
|
895
|
+
await switchbot.wait(10000);
|
|
896
|
+
// Stop to monitor
|
|
897
|
+
switchbot.stopScan();
|
|
898
|
+
})();
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
async BLEconnection(switchbot: any): Promise<void> {
|
|
903
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
|
|
904
|
+
if (this.platform.config.credentials?.token) {
|
|
905
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
906
|
+
this.SwitchToOpenAPI = true;
|
|
907
|
+
await this.openAPIRefreshStatus();
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
async turnOnOff(device_list: any): Promise<any> {
|
|
912
|
+
return await this.retry({
|
|
913
|
+
max: await this.maxRetry(),
|
|
914
|
+
fn: () => {
|
|
915
|
+
if (this.On) {
|
|
916
|
+
return device_list[0].turnOn({ id: this.device.bleMac });
|
|
917
|
+
} else {
|
|
918
|
+
return device_list[0].turnOff({ id: this.device.bleMac });
|
|
919
|
+
}
|
|
920
|
+
},
|
|
921
|
+
});
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
async retry({ max, fn }: { max: number; fn: { (): any; (): Promise<any> } }): Promise<null> {
|
|
925
|
+
return fn().catch(async (err: any) => {
|
|
926
|
+
if (max === 0) {
|
|
927
|
+
throw err;
|
|
928
|
+
}
|
|
929
|
+
this.infoLog(err);
|
|
930
|
+
this.infoLog('Retrying');
|
|
931
|
+
await this.switchbot.wait(1000);
|
|
932
|
+
return this.retry({ max: max - 1, fn });
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
async maxRetry(): Promise<number> {
|
|
937
|
+
let maxRetry: number;
|
|
938
|
+
if (this.device.bot?.maxRetry) {
|
|
939
|
+
maxRetry = this.device.bot?.maxRetry;
|
|
940
|
+
} else {
|
|
941
|
+
maxRetry = 5;
|
|
942
|
+
}
|
|
943
|
+
return maxRetry;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
minStep(device: device & devicesConfig): number {
|
|
947
|
+
if (device.colorbulb?.set_minStep) {
|
|
948
|
+
this.set_minStep = device.colorbulb?.set_minStep;
|
|
949
|
+
} else {
|
|
950
|
+
this.set_minStep = 1;
|
|
951
|
+
}
|
|
952
|
+
return this.set_minStep;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
async scan(device: device & devicesConfig): Promise<void> {
|
|
956
|
+
if (device.scanDuration) {
|
|
957
|
+
this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
|
|
958
|
+
if (this.BLE) {
|
|
959
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
|
|
960
|
+
}
|
|
961
|
+
} else {
|
|
962
|
+
this.scanDuration = this.accessory.context.scanDuration = 1;
|
|
963
|
+
if (this.BLE) {
|
|
964
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
|
|
965
|
+
}
|
|
966
|
+
}
|
|
826
967
|
}
|
|
827
968
|
|
|
828
969
|
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
@@ -866,76 +1007,72 @@ export class ColorBulb {
|
|
|
866
1007
|
if (this.device.offline) {
|
|
867
1008
|
this.On = false;
|
|
868
1009
|
this.lightBulbService.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
|
|
1010
|
+
await this.updateHomeKitCharacteristics();
|
|
869
1011
|
}
|
|
870
1012
|
}
|
|
871
1013
|
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
this.
|
|
877
|
-
|
|
878
|
-
this.On = value;
|
|
879
|
-
this.doColorBulbUpdate.next();
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
/**
|
|
883
|
-
* Handle requests to set the value of the "Brightness" characteristic
|
|
884
|
-
*/
|
|
885
|
-
async BrightnessSet(value: CharacteristicValue): Promise<void> {
|
|
886
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Brightness: ${value}`);
|
|
887
|
-
|
|
888
|
-
this.Brightness = value;
|
|
889
|
-
this.doColorBulbUpdate.next();
|
|
1014
|
+
apiError(e: any): void {
|
|
1015
|
+
this.lightBulbService.updateCharacteristic(this.platform.Characteristic.On, e);
|
|
1016
|
+
this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Hue, e);
|
|
1017
|
+
this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Brightness, e);
|
|
1018
|
+
this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Saturation, e);
|
|
1019
|
+
this.lightBulbService.updateCharacteristic(this.platform.Characteristic.ColorTemperature, e);
|
|
890
1020
|
}
|
|
891
1021
|
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
if (!this.accessory.context.On || this.cacheKelvin === k) {
|
|
905
|
-
return;
|
|
1022
|
+
FirmwareRevision(accessory: PlatformAccessory<Context>, device: device & devicesConfig): CharacteristicValue {
|
|
1023
|
+
let FirmwareRevision: string;
|
|
1024
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
|
|
1025
|
+
+ ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
|
|
1026
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
|
|
1027
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
|
|
1028
|
+
if (accessory.context.FirmwareRevision) {
|
|
1029
|
+
FirmwareRevision = accessory.context.FirmwareRevision;
|
|
1030
|
+
} else if (device.firmware) {
|
|
1031
|
+
FirmwareRevision = device.firmware;
|
|
1032
|
+
} else {
|
|
1033
|
+
FirmwareRevision = this.platform.version;
|
|
906
1034
|
}
|
|
907
|
-
|
|
908
|
-
// Updating the hue/sat to the corresponding values mimics native adaptive lighting
|
|
909
|
-
const hs = m2hs(value);
|
|
910
|
-
this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Hue, hs[0]);
|
|
911
|
-
this.lightBulbService.updateCharacteristic(this.platform.Characteristic.Saturation, hs[1]);
|
|
912
|
-
|
|
913
|
-
this.ColorTemperature = value;
|
|
914
|
-
this.doColorBulbUpdate.next();
|
|
1035
|
+
return FirmwareRevision;
|
|
915
1036
|
}
|
|
916
1037
|
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
1038
|
+
private context() {
|
|
1039
|
+
if (this.On === undefined) {
|
|
1040
|
+
this.On = false;
|
|
1041
|
+
} else {
|
|
1042
|
+
this.On = this.accessory.context.On;
|
|
1043
|
+
}
|
|
1044
|
+
if (this.Hue === undefined) {
|
|
1045
|
+
this.Hue = 0;
|
|
1046
|
+
} else {
|
|
1047
|
+
this.Hue = this.accessory.context.Hue;
|
|
1048
|
+
}
|
|
1049
|
+
if (this.Brightness === undefined) {
|
|
1050
|
+
this.Brightness = 0;
|
|
1051
|
+
} else {
|
|
1052
|
+
this.Brightness = this.accessory.context.Brightness;
|
|
1053
|
+
}
|
|
1054
|
+
if (this.Brightness === undefined) {
|
|
1055
|
+
this.Saturation = 0;
|
|
1056
|
+
} else {
|
|
1057
|
+
this.Saturation = this.accessory.context.Saturation;
|
|
1058
|
+
}
|
|
1059
|
+
if (this.ColorTemperature === undefined) {
|
|
1060
|
+
this.ColorTemperature = 140;
|
|
1061
|
+
} else {
|
|
1062
|
+
this.ColorTemperature = this.accessory.context.ColorTemperature;
|
|
1063
|
+
}
|
|
1064
|
+
this.minKelvin = 2000;
|
|
1065
|
+
this.maxKelvin = 9000;
|
|
927
1066
|
}
|
|
928
1067
|
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
this.Saturation = value;
|
|
938
|
-
this.doColorBulbUpdate.next();
|
|
1068
|
+
async refreshRate(device: device & devicesConfig): Promise<void> {
|
|
1069
|
+
if (device.refreshRate) {
|
|
1070
|
+
this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
|
|
1071
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
|
|
1072
|
+
} else if (this.platform.config.options!.refreshRate) {
|
|
1073
|
+
this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
|
|
1074
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
1075
|
+
}
|
|
939
1076
|
}
|
|
940
1077
|
|
|
941
1078
|
async config(device: device & devicesConfig): Promise<void> {
|
|
@@ -943,11 +1080,8 @@ export class ColorBulb {
|
|
|
943
1080
|
if (device.colorbulb) {
|
|
944
1081
|
config = device.colorbulb;
|
|
945
1082
|
}
|
|
946
|
-
if (device.
|
|
947
|
-
config['
|
|
948
|
-
}
|
|
949
|
-
if (device.openAPI !== undefined) {
|
|
950
|
-
config['openAPI'] = device.openAPI;
|
|
1083
|
+
if (device.connectionType !== undefined) {
|
|
1084
|
+
config['connectionType'] = device.connectionType;
|
|
951
1085
|
}
|
|
952
1086
|
if (device.logging !== undefined) {
|
|
953
1087
|
config['logging'] = device.logging;
|
|
@@ -966,39 +1100,6 @@ export class ColorBulb {
|
|
|
966
1100
|
}
|
|
967
1101
|
}
|
|
968
1102
|
|
|
969
|
-
async refreshRate(device: device & devicesConfig): Promise<void> {
|
|
970
|
-
if (device.refreshRate) {
|
|
971
|
-
this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
|
|
972
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
|
|
973
|
-
} else if (this.platform.config.options!.refreshRate) {
|
|
974
|
-
this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
|
|
975
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
async openAPI() {
|
|
980
|
-
if (!this.device.openAPI) {
|
|
981
|
-
this.OpenAPI = true;
|
|
982
|
-
} else {
|
|
983
|
-
this.OpenAPI = this.device.openAPI;
|
|
984
|
-
}
|
|
985
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI: ${this.OpenAPI}`);
|
|
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 (device.ble) {
|
|
992
|
-
this.debugLog(`Bot: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
|
|
993
|
-
}
|
|
994
|
-
} else {
|
|
995
|
-
this.scanDuration = this.accessory.context.scanDuration = 1;
|
|
996
|
-
if (this.device.ble) {
|
|
997
|
-
this.debugLog(`Bot: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
1103
|
async logs(device: device & devicesConfig): Promise<void> {
|
|
1003
1104
|
if (this.platform.debugMode) {
|
|
1004
1105
|
this.deviceLogging = this.accessory.context.logging = 'debugMode';
|
|
@@ -1015,41 +1116,6 @@ export class ColorBulb {
|
|
|
1015
1116
|
}
|
|
1016
1117
|
}
|
|
1017
1118
|
|
|
1018
|
-
FirmwareRevision(accessory: PlatformAccessory<Context>, device: device & devicesConfig): CharacteristicValue {
|
|
1019
|
-
let FirmwareRevision: string;
|
|
1020
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
|
|
1021
|
-
+ ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
|
|
1022
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
|
|
1023
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
|
|
1024
|
-
if (accessory.context.FirmwareRevision) {
|
|
1025
|
-
FirmwareRevision = accessory.context.FirmwareRevision;
|
|
1026
|
-
} else if (device.firmware) {
|
|
1027
|
-
FirmwareRevision = device.firmware;
|
|
1028
|
-
} else {
|
|
1029
|
-
FirmwareRevision = this.platform.version;
|
|
1030
|
-
}
|
|
1031
|
-
return FirmwareRevision;
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
async adaptiveLighting(device: device & devicesConfig): Promise<void> {
|
|
1035
|
-
if (device.colorbulb?.adaptiveLightingShift) {
|
|
1036
|
-
this.adaptiveLightingShift = device.colorbulb.adaptiveLightingShift;
|
|
1037
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} adaptiveLightingShift: ${this.adaptiveLightingShift}`);
|
|
1038
|
-
} else {
|
|
1039
|
-
this.adaptiveLightingShift = 0;
|
|
1040
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} adaptiveLightingShift: ${this.adaptiveLightingShift}`);
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1043
|
-
|
|
1044
|
-
minStep(device: device & devicesConfig): number {
|
|
1045
|
-
if (device.colorbulb?.set_minStep) {
|
|
1046
|
-
this.set_minStep = device.colorbulb?.set_minStep;
|
|
1047
|
-
} else {
|
|
1048
|
-
this.set_minStep = 1;
|
|
1049
|
-
}
|
|
1050
|
-
return this.set_minStep;
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
1119
|
/**
|
|
1054
1120
|
* Logging for Device
|
|
1055
1121
|
*/
|