@switchbot/homebridge-switchbot 1.15.1-beta.0 → 1.15.1-beta.10
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/.github/ISSUE_TEMPLATE/bug-report.yml +1 -0
- package/.github/ISSUE_TEMPLATE/feature-request.yml +1 -0
- package/.github/ISSUE_TEMPLATE/support-request.yml +1 -0
- package/.prettierrc +1 -1
- package/CHANGELOG.md +9 -0
- package/config.schema.json +11 -4
- package/dist/device/bot.d.ts +8 -7
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +104 -28
- package/dist/device/bot.js.map +1 -1
- package/dist/device/colorbulb.d.ts +8 -7
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +223 -58
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts +3 -3
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +54 -11
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts +9 -8
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +102 -28
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/humidifier.d.ts +8 -7
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +187 -66
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/lock.d.ts +8 -7
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +98 -22
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +4 -4
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +55 -12
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +3 -3
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +53 -10
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts +3 -3
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +53 -13
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +8 -7
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +100 -24
- package/dist/device/plug.js.map +1 -1
- package/dist/device/striplight.d.ts +8 -7
- package/dist/device/striplight.d.ts.map +1 -1
- package/dist/device/striplight.js +186 -47
- package/dist/device/striplight.js.map +1 -1
- package/dist/irdevice/airconditioner.d.ts +7 -6
- package/dist/irdevice/airconditioner.d.ts.map +1 -1
- package/dist/irdevice/airconditioner.js +40 -6
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts +7 -6
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +46 -11
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts +7 -6
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +40 -6
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts +8 -7
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +40 -6
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/light.d.ts +7 -6
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +40 -6
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts +7 -6
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +40 -6
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts +8 -7
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +40 -6
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts +7 -6
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +40 -6
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts +7 -6
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +40 -6
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +10 -6
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +211 -93
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +4 -21
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +3 -3
- package/dist/settings.js.map +1 -1
- package/package.json +12 -12
- package/src/device/bot.ts +104 -37
- package/src/device/colorbulb.ts +227 -95
- package/src/device/contact.ts +53 -14
- package/src/device/curtain.ts +105 -38
- package/src/device/humidifier.ts +189 -84
- package/src/device/lock.ts +97 -30
- package/src/device/meter.ts +55 -16
- package/src/device/meterplus.ts +52 -13
- package/src/device/motion.ts +52 -16
- package/src/device/plug.ts +101 -33
- package/src/device/striplight.ts +189 -68
- package/src/irdevice/airconditioner.ts +44 -9
- package/src/irdevice/airpurifier.ts +52 -17
- package/src/irdevice/camera.ts +46 -11
- package/src/irdevice/fan.ts +50 -15
- package/src/irdevice/light.ts +48 -13
- package/src/irdevice/other.ts +46 -11
- package/src/irdevice/tv.ts +56 -21
- package/src/irdevice/vacuumcleaner.ts +46 -11
- package/src/irdevice/waterheater.ts +46 -11
- package/src/platform.ts +232 -107
- package/src/settings.ts +4 -25
package/src/device/striplight.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import https from 'https';
|
|
2
|
+
import crypto from 'crypto';
|
|
3
|
+
import { Context } from 'vm';
|
|
4
|
+
import { IncomingMessage } from 'http';
|
|
2
5
|
import { interval, Subject } from 'rxjs';
|
|
3
6
|
import { SwitchBotPlatform } from '../platform';
|
|
4
7
|
import { debounceTime, skipWhile, tap } from 'rxjs/operators';
|
|
5
8
|
import { Service, PlatformAccessory, CharacteristicValue, ControllerConstructor, Controller, ControllerServiceMap } from 'homebridge';
|
|
6
|
-
import {
|
|
7
|
-
import { Context } from 'vm';
|
|
9
|
+
import { device, devicesConfig, switchbot, hs2rgb, rgb2hs, deviceStatus, HostDomain, DevicePath } from '../settings';
|
|
8
10
|
|
|
9
11
|
/**
|
|
10
12
|
* Platform Accessory
|
|
@@ -29,7 +31,7 @@ export class StripLight {
|
|
|
29
31
|
power: deviceStatus['power'];
|
|
30
32
|
color: deviceStatus['color'];
|
|
31
33
|
brightness: deviceStatus['brightness'];
|
|
32
|
-
deviceStatus!: deviceStatusResponse;
|
|
34
|
+
deviceStatus!: any; //deviceStatusResponse;
|
|
33
35
|
|
|
34
36
|
// BLE Others
|
|
35
37
|
switchbot!: switchbot;
|
|
@@ -210,14 +212,50 @@ export class StripLight {
|
|
|
210
212
|
|
|
211
213
|
async refreshStatus(): Promise<void> {
|
|
212
214
|
try {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
215
|
+
const t = Date.now();
|
|
216
|
+
const nonce = 'requestID';
|
|
217
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
218
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
219
|
+
const sign = signTerm.toString('base64');
|
|
220
|
+
this.debugLog(`Strip Light: ${this.accessory.displayName} sign: ${sign}`);
|
|
221
|
+
const options = {
|
|
222
|
+
hostname: HostDomain,
|
|
223
|
+
port: 443,
|
|
224
|
+
path: `${DevicePath}/${this.device.deviceId}/status`,
|
|
225
|
+
method: 'GET',
|
|
226
|
+
headers: {
|
|
227
|
+
Authorization: this.platform.config.credentials?.token,
|
|
228
|
+
sign: sign,
|
|
229
|
+
nonce: nonce,
|
|
230
|
+
t: t,
|
|
231
|
+
'Content-Type': 'application/json',
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
const req = https.request(options, (res) => {
|
|
235
|
+
this.debugLog(`Strip Light: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
236
|
+
let rawData = '';
|
|
237
|
+
res.on('data', (d) => {
|
|
238
|
+
rawData += d;
|
|
239
|
+
this.debugLog(`Strip Light: ${this.accessory.displayName} d: ${d}`);
|
|
240
|
+
});
|
|
241
|
+
res.on('end', () => {
|
|
242
|
+
try {
|
|
243
|
+
this.deviceStatus = JSON.parse(rawData);
|
|
244
|
+
this.debugLog(`Strip Light: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
|
|
245
|
+
this.power = this.deviceStatus.body.power;
|
|
246
|
+
this.color = this.deviceStatus.body.color;
|
|
247
|
+
this.brightness = this.deviceStatus.body.brightness;
|
|
248
|
+
this.parseStatus();
|
|
249
|
+
this.updateHomeKitCharacteristics();
|
|
250
|
+
} catch (e: any) {
|
|
251
|
+
this.errorLog(`Strip Light: ${this.accessory.displayName} error message: ${e.message}`);
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
req.on('error', (e: any) => {
|
|
256
|
+
this.errorLog(`Strip Light: ${this.accessory.displayName} error message: ${e.message}`);
|
|
257
|
+
});
|
|
258
|
+
req.end();
|
|
221
259
|
} catch (e: any) {
|
|
222
260
|
this.errorLog(`Strip Light: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
|
|
223
261
|
if (this.deviceLogging.includes('debug')) {
|
|
@@ -242,27 +280,55 @@ export class StripLight {
|
|
|
242
280
|
async pushChanges(): Promise<void> {
|
|
243
281
|
try {
|
|
244
282
|
if (this.On !== this.OnCached) {
|
|
245
|
-
// Push On
|
|
246
|
-
const
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
283
|
+
// Make Push On request to the API
|
|
284
|
+
const t = Date.now();
|
|
285
|
+
const nonce = 'requestID';
|
|
286
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
287
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
288
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
289
|
+
.digest();
|
|
290
|
+
const sign = signTerm.toString('base64');
|
|
291
|
+
this.debugLog(`Strip Light: ${this.accessory.displayName} sign: ${sign}`);
|
|
292
|
+
|
|
293
|
+
let command = '';
|
|
251
294
|
if (this.On) {
|
|
252
|
-
|
|
295
|
+
command = 'turnOn';
|
|
253
296
|
} else {
|
|
254
|
-
|
|
297
|
+
command = 'turnOff';
|
|
255
298
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
);
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
299
|
+
const body = JSON.stringify({
|
|
300
|
+
'command': `${command}`,
|
|
301
|
+
'parameter': 'default',
|
|
302
|
+
'commandType': 'command',
|
|
303
|
+
});
|
|
304
|
+
this.infoLog(`Strip Light: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
305
|
+
const options = {
|
|
306
|
+
hostname: HostDomain,
|
|
307
|
+
port: 443,
|
|
308
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
309
|
+
method: 'POST',
|
|
310
|
+
headers: {
|
|
311
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
312
|
+
'sign': sign,
|
|
313
|
+
'nonce': nonce,
|
|
314
|
+
't': t,
|
|
315
|
+
'Content-Type': 'application/json',
|
|
316
|
+
'Content-Length': body.length,
|
|
317
|
+
},
|
|
318
|
+
};
|
|
319
|
+
const req = https.request(options, res => {
|
|
320
|
+
this.debugLog(`Strip Light: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
321
|
+
this.statusCode({ res });
|
|
322
|
+
res.on('data', d => {
|
|
323
|
+
this.debugLog(`Strip Light: ${this.accessory.displayName} d: ${d}`);
|
|
324
|
+
});
|
|
325
|
+
});
|
|
326
|
+
req.on('error', (e: any) => {
|
|
327
|
+
this.errorLog(`Strip Light: ${this.accessory.displayName} error message: ${e.message}`);
|
|
328
|
+
});
|
|
329
|
+
req.write(body);
|
|
330
|
+
req.end();
|
|
331
|
+
this.debugLog(`Strip Light: ${this.accessory.displayName} pushchanges: ${JSON.stringify(req)}`);
|
|
266
332
|
this.OnCached = this.On;
|
|
267
333
|
this.accessory.context.On = this.OnCached;
|
|
268
334
|
}
|
|
@@ -294,22 +360,48 @@ export class StripLight {
|
|
|
294
360
|
|
|
295
361
|
const [red, green, blue] = hs2rgb(Number(this.Hue), Number(this.Saturation));
|
|
296
362
|
this.debugLog(`Strip Light: ${this.accessory.displayName} rgb: ${JSON.stringify([red, green, blue])}`);
|
|
297
|
-
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
this.
|
|
312
|
-
|
|
363
|
+
// Make Push On request to the API
|
|
364
|
+
const t = Date.now();
|
|
365
|
+
const nonce = 'requestID';
|
|
366
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
367
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
368
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
369
|
+
.digest();
|
|
370
|
+
const sign = signTerm.toString('base64');
|
|
371
|
+
this.debugLog(`Strip Light: ${this.accessory.displayName} sign: ${sign}`);
|
|
372
|
+
const body = JSON.stringify({
|
|
373
|
+
'command': 'setColor',
|
|
374
|
+
'parameter': `${red}:${green}:${blue}`,
|
|
375
|
+
'commandType': 'command',
|
|
376
|
+
});
|
|
377
|
+
this.infoLog(`Strip Light: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
378
|
+
const options = {
|
|
379
|
+
hostname: HostDomain,
|
|
380
|
+
port: 443,
|
|
381
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
382
|
+
method: 'POST',
|
|
383
|
+
headers: {
|
|
384
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
385
|
+
'sign': sign,
|
|
386
|
+
'nonce': nonce,
|
|
387
|
+
't': t,
|
|
388
|
+
'Content-Type': 'application/json',
|
|
389
|
+
'Content-Length': body.length,
|
|
390
|
+
},
|
|
391
|
+
};
|
|
392
|
+
const req = https.request(options, res => {
|
|
393
|
+
this.debugLog(`Strip Light: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
394
|
+
this.statusCode({ res });
|
|
395
|
+
res.on('data', d => {
|
|
396
|
+
this.debugLog(`Strip Light: ${this.accessory.displayName} d: ${d}`);
|
|
397
|
+
});
|
|
398
|
+
});
|
|
399
|
+
req.on('error', (e: any) => {
|
|
400
|
+
this.errorLog(`Strip Light: ${this.accessory.displayName} error message: ${e.message}`);
|
|
401
|
+
});
|
|
402
|
+
req.write(body);
|
|
403
|
+
req.end();
|
|
404
|
+
this.debugLog(`Strip Light: ${this.accessory.displayName} pushHueSaturationChanges: ${JSON.stringify(req)}`);
|
|
313
405
|
this.HueCached = this.Hue;
|
|
314
406
|
this.SaturationCached = this.Saturation;
|
|
315
407
|
} else {
|
|
@@ -319,10 +411,11 @@ export class StripLight {
|
|
|
319
411
|
);
|
|
320
412
|
}
|
|
321
413
|
} catch (e: any) {
|
|
322
|
-
this.errorLog(`Strip Light: ${this.accessory.displayName} failed
|
|
414
|
+
this.errorLog(`Strip Light: ${this.accessory.displayName} failed pushHueSaturationChanges with OpenAPI Connection`);
|
|
323
415
|
if (this.deviceLogging.includes('debug')) {
|
|
324
416
|
this.errorLog(
|
|
325
|
-
`Strip Light: ${this.accessory.displayName} failed
|
|
417
|
+
`Strip Light: ${this.accessory.displayName} failed pushHueSaturationChanges with OpenAPI Connection,`
|
|
418
|
+
+ ` Error Message: ${JSON.stringify(e.message)}`,
|
|
326
419
|
);
|
|
327
420
|
}
|
|
328
421
|
this.apiError(e);
|
|
@@ -332,21 +425,48 @@ export class StripLight {
|
|
|
332
425
|
async pushBrightnessChanges(): Promise<void> {
|
|
333
426
|
try {
|
|
334
427
|
if (this.Brightness !== this.BrightnessCached) {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
this.
|
|
428
|
+
// Make Push On request to the API
|
|
429
|
+
const t = Date.now();
|
|
430
|
+
const nonce = 'requestID';
|
|
431
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
432
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
433
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
434
|
+
.digest();
|
|
435
|
+
const sign = signTerm.toString('base64');
|
|
436
|
+
this.debugLog(`Strip Light: ${this.accessory.displayName} sign: ${sign}`);
|
|
437
|
+
const body = JSON.stringify({
|
|
438
|
+
'command': 'setBrightness',
|
|
439
|
+
'parameter': `${this.Brightness}`,
|
|
440
|
+
'commandType': 'command',
|
|
441
|
+
});
|
|
442
|
+
this.infoLog(`Strip Light: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
443
|
+
const options = {
|
|
444
|
+
hostname: HostDomain,
|
|
445
|
+
port: 443,
|
|
446
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
447
|
+
method: 'POST',
|
|
448
|
+
headers: {
|
|
449
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
450
|
+
'sign': sign,
|
|
451
|
+
'nonce': nonce,
|
|
452
|
+
't': t,
|
|
453
|
+
'Content-Type': 'application/json',
|
|
454
|
+
'Content-Length': body.length,
|
|
455
|
+
},
|
|
456
|
+
};
|
|
457
|
+
const req = https.request(options, res => {
|
|
458
|
+
this.debugLog(`Strip Light: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
459
|
+
this.statusCode({ res });
|
|
460
|
+
res.on('data', d => {
|
|
461
|
+
this.debugLog(`Strip Light: ${this.accessory.displayName} d: ${d}`);
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
req.on('error', (e: any) => {
|
|
465
|
+
this.errorLog(`Strip Light: ${this.accessory.displayName} error message: ${e.message}`);
|
|
466
|
+
});
|
|
467
|
+
req.write(body);
|
|
468
|
+
req.end();
|
|
469
|
+
this.debugLog(`Strip Light: ${this.accessory.displayName} pushBrightnessChanges: ${JSON.stringify(req)}`);
|
|
350
470
|
this.BrightnessCached = this.Brightness;
|
|
351
471
|
} else {
|
|
352
472
|
this.debugLog(
|
|
@@ -354,10 +474,11 @@ export class StripLight {
|
|
|
354
474
|
);
|
|
355
475
|
}
|
|
356
476
|
} catch (e: any) {
|
|
357
|
-
this.errorLog(`Strip Light: ${this.accessory.displayName} failed
|
|
477
|
+
this.errorLog(`Strip Light: ${this.accessory.displayName} failed pushBrightnessChanges with OpenAPI Connection`);
|
|
358
478
|
if (this.deviceLogging.includes('debug')) {
|
|
359
479
|
this.errorLog(
|
|
360
|
-
`Strip Light: ${this.accessory.displayName} failed
|
|
480
|
+
`Strip Light: ${this.accessory.displayName} failed pushBrightnessChanges with OpenAPI Connection,`
|
|
481
|
+
+ ` Error Message: ${JSON.stringify(e.message)}`,
|
|
361
482
|
);
|
|
362
483
|
}
|
|
363
484
|
this.apiError(e);
|
|
@@ -399,8 +520,8 @@ export class StripLight {
|
|
|
399
520
|
//throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
|
|
400
521
|
}
|
|
401
522
|
|
|
402
|
-
statusCode(
|
|
403
|
-
switch (
|
|
523
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
524
|
+
switch (res.statusCode) {
|
|
404
525
|
case 151:
|
|
405
526
|
this.errorLog(`Strip Light: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
406
527
|
break;
|
|
@@ -421,7 +542,7 @@ export class StripLight {
|
|
|
421
542
|
case 190:
|
|
422
543
|
this.errorLog(
|
|
423
544
|
`Strip Light: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
424
|
-
` Or command: ${JSON.stringify(
|
|
545
|
+
` Or command: ${JSON.stringify(res)} format is invalid`,
|
|
425
546
|
);
|
|
426
547
|
break;
|
|
427
548
|
case 100:
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import https from 'https';
|
|
2
|
+
import crypto from 'crypto';
|
|
3
|
+
import { IncomingMessage } from 'http';
|
|
2
4
|
import { SwitchBotPlatform } from '../platform';
|
|
3
|
-
import { irDevicesConfig,
|
|
5
|
+
import { irDevicesConfig, irdevice, HostDomain, DevicePath } from '../settings';
|
|
4
6
|
import { CharacteristicValue, PlatformAccessory, Service } from 'homebridge';
|
|
5
7
|
|
|
6
8
|
/**
|
|
@@ -250,7 +252,7 @@ export class AirConditioner {
|
|
|
250
252
|
await this.pushChanges(payload);
|
|
251
253
|
}
|
|
252
254
|
|
|
253
|
-
async pushChanges(payload
|
|
255
|
+
async pushChanges(payload): Promise<void> {
|
|
254
256
|
try {
|
|
255
257
|
this.infoLog(
|
|
256
258
|
`Air Conditioner: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},` +
|
|
@@ -258,9 +260,42 @@ export class AirConditioner {
|
|
|
258
260
|
);
|
|
259
261
|
|
|
260
262
|
// Make the API request
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
this.
|
|
263
|
+
const t = Date.now();
|
|
264
|
+
const nonce = 'requestID';
|
|
265
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
266
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
267
|
+
const sign = signTerm.toString('base64');
|
|
268
|
+
this.debugLog(`Air Conditioner: ${this.accessory.displayName} sign: ${sign}`);
|
|
269
|
+
const options = {
|
|
270
|
+
hostname: HostDomain,
|
|
271
|
+
port: 443,
|
|
272
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
273
|
+
method: 'POST',
|
|
274
|
+
headers: {
|
|
275
|
+
Authorization: this.platform.config.credentials?.token,
|
|
276
|
+
sign: sign,
|
|
277
|
+
nonce: nonce,
|
|
278
|
+
t: t,
|
|
279
|
+
'Content-Type': 'application/json',
|
|
280
|
+
},
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
const req = https.request(options, (res) => {
|
|
284
|
+
this.debugLog(`Air Conditioner: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
285
|
+
this.statusCode({ res });
|
|
286
|
+
res.on('data', (d) => {
|
|
287
|
+
this.debugLog(`Air Conditioner: ${this.accessory.displayName} d: ${d}`);
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
req.on('error', (error) => {
|
|
292
|
+
this.errorLog(`Air Conditioner: ${this.accessory.displayName} error: ${error}`);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
req.write(payload);
|
|
296
|
+
req.end();
|
|
297
|
+
|
|
298
|
+
this.debugLog(`Air Conditioner: ${this.accessory.displayName} pushchanges: ${JSON.stringify(req)}`);
|
|
264
299
|
this.CurrentTemperatureCached = this.CurrentTemperature;
|
|
265
300
|
this.accessory.context.CurrentTemperature = this.CurrentTemperatureCached;
|
|
266
301
|
this.HeatingThresholdTemperature = this.CurrentTemperatureCached;
|
|
@@ -279,8 +314,8 @@ export class AirConditioner {
|
|
|
279
314
|
}
|
|
280
315
|
}
|
|
281
316
|
|
|
282
|
-
async statusCode(
|
|
283
|
-
switch (
|
|
317
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
318
|
+
switch (res.statusCode) {
|
|
284
319
|
case 151:
|
|
285
320
|
this.errorLog(`Air Conditioner: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
286
321
|
break;
|
|
@@ -299,7 +334,7 @@ export class AirConditioner {
|
|
|
299
334
|
case 190:
|
|
300
335
|
this.errorLog(
|
|
301
336
|
`Air Conditioner: ${this.accessory.displayName} Device internal error due to device states not synchronized` +
|
|
302
|
-
` with server, Or command: ${JSON.stringify(
|
|
337
|
+
` with server, Or command: ${JSON.stringify(res)} format is invalid`,
|
|
303
338
|
);
|
|
304
339
|
break;
|
|
305
340
|
case 100:
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import https from 'https';
|
|
2
|
+
import crypto from 'crypto';
|
|
3
|
+
import { IncomingMessage } from 'http';
|
|
2
4
|
import { SwitchBotPlatform } from '../platform';
|
|
3
|
-
import { irDevicesConfig,
|
|
5
|
+
import { irDevicesConfig, irdevice, HostDomain, DevicePath } from '../settings';
|
|
4
6
|
import { CharacteristicValue, PlatformAccessory, Service } from 'homebridge';
|
|
5
7
|
|
|
6
8
|
/**
|
|
@@ -160,7 +162,7 @@ export class AirPurifier {
|
|
|
160
162
|
commandType: 'command',
|
|
161
163
|
parameter: 'default',
|
|
162
164
|
command: 'turnOn',
|
|
163
|
-
}
|
|
165
|
+
};
|
|
164
166
|
await this.pushChanges(payload);
|
|
165
167
|
}
|
|
166
168
|
}
|
|
@@ -171,7 +173,7 @@ export class AirPurifier {
|
|
|
171
173
|
commandType: 'command',
|
|
172
174
|
parameter: 'default',
|
|
173
175
|
command: 'turnOff',
|
|
174
|
-
}
|
|
176
|
+
};
|
|
175
177
|
await this.pushChanges(payload);
|
|
176
178
|
}
|
|
177
179
|
}
|
|
@@ -188,16 +190,16 @@ export class AirPurifier {
|
|
|
188
190
|
}
|
|
189
191
|
|
|
190
192
|
async pushAirConditionerDetailsChanges(): Promise<void> {
|
|
191
|
-
const payload = {
|
|
192
|
-
commandType: 'command',
|
|
193
|
-
command: 'setAll',
|
|
194
|
-
} as payload;
|
|
195
|
-
|
|
196
193
|
this.CurrentAPTemp = this.CurrentTemperature || 24;
|
|
197
194
|
this.CurrentAPMode = this.CurrentMode || 1;
|
|
198
195
|
this.CurrentAPFanSpeed = this.CurrentFanSpeed || 1;
|
|
199
196
|
this.APActive = this.Active === 1 ? 'on' : 'off';
|
|
200
|
-
|
|
197
|
+
const parameter = `${this.CurrentAPTemp},${this.CurrentAPMode},${this.CurrentAPFanSpeed},${this.APActive}`;
|
|
198
|
+
const payload = JSON.stringify({
|
|
199
|
+
'command': 'setAll',
|
|
200
|
+
'parameter': `${parameter}`,
|
|
201
|
+
'commandType': 'command',
|
|
202
|
+
});
|
|
201
203
|
|
|
202
204
|
if (this.Active === 1) {
|
|
203
205
|
if ((this.CurrentTemperature || 24) < (this.LastTemperature || 30)) {
|
|
@@ -212,7 +214,7 @@ export class AirPurifier {
|
|
|
212
214
|
await this.pushChanges(payload);
|
|
213
215
|
}
|
|
214
216
|
|
|
215
|
-
async pushChanges(payload
|
|
217
|
+
async pushChanges(payload): Promise<void> {
|
|
216
218
|
try {
|
|
217
219
|
this.infoLog(
|
|
218
220
|
`Air Purifier: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},` +
|
|
@@ -220,9 +222,42 @@ export class AirPurifier {
|
|
|
220
222
|
);
|
|
221
223
|
|
|
222
224
|
// Make the API request
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
this.
|
|
225
|
+
const t = Date.now();
|
|
226
|
+
const nonce = 'requestID';
|
|
227
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
228
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
229
|
+
const sign = signTerm.toString('base64');
|
|
230
|
+
this.debugLog(`Air Purifier: ${this.accessory.displayName} sign: ${sign}`);
|
|
231
|
+
const options = {
|
|
232
|
+
hostname: HostDomain,
|
|
233
|
+
port: 443,
|
|
234
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
235
|
+
method: 'POST',
|
|
236
|
+
headers: {
|
|
237
|
+
Authorization: this.platform.config.credentials?.token,
|
|
238
|
+
sign: sign,
|
|
239
|
+
nonce: nonce,
|
|
240
|
+
t: t,
|
|
241
|
+
'Content-Type': 'application/json',
|
|
242
|
+
},
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
const req = https.request(options, (res) => {
|
|
246
|
+
this.debugLog(`Air Purifier: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
247
|
+
this.statusCode({ res });
|
|
248
|
+
res.on('data', (d) => {
|
|
249
|
+
this.debugLog(`Air Purifier: ${this.accessory.displayName} d: ${d}`);
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
req.on('error', (error) => {
|
|
254
|
+
this.errorLog(`Air Purifier: ${this.accessory.displayName} error: ${error}`);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
req.write(payload);
|
|
258
|
+
req.end();
|
|
259
|
+
|
|
260
|
+
this.debugLog(`Air Purifier: ${this.accessory.displayName} pushchanges: ${JSON.stringify(req)}`);
|
|
226
261
|
this.updateHomeKitCharacteristics();
|
|
227
262
|
this.CurrentTemperatureCached = this.CurrentTemperature;
|
|
228
263
|
this.accessory.context.CurrentTemperature = this.CurrentTemperatureCached;
|
|
@@ -237,8 +272,8 @@ export class AirPurifier {
|
|
|
237
272
|
}
|
|
238
273
|
}
|
|
239
274
|
|
|
240
|
-
async statusCode(
|
|
241
|
-
switch (
|
|
275
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
276
|
+
switch (res.statusCode) {
|
|
242
277
|
case 151:
|
|
243
278
|
this.errorLog(`Air Purifier: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
244
279
|
break;
|
|
@@ -257,7 +292,7 @@ export class AirPurifier {
|
|
|
257
292
|
case 190:
|
|
258
293
|
this.errorLog(
|
|
259
294
|
`Air Purifier: ${this.accessory.displayName} Device internal error due to device states not synchronized` +
|
|
260
|
-
` with server, Or command: ${JSON.stringify(
|
|
295
|
+
` with server, Or command: ${JSON.stringify(res)} format is invalid`,
|
|
261
296
|
);
|
|
262
297
|
break;
|
|
263
298
|
case 100:
|
package/src/irdevice/camera.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import https from 'https';
|
|
2
|
+
import crypto from 'crypto';
|
|
3
|
+
import { IncomingMessage } from 'http';
|
|
2
4
|
import { SwitchBotPlatform } from '../platform';
|
|
3
|
-
import { irDevicesConfig,
|
|
5
|
+
import { irDevicesConfig, irdevice, HostDomain, DevicePath } from '../settings';
|
|
4
6
|
import { CharacteristicValue, PlatformAccessory, Service } from 'homebridge';
|
|
5
7
|
|
|
6
8
|
/**
|
|
@@ -88,7 +90,7 @@ export class Camera {
|
|
|
88
90
|
commandType: 'command',
|
|
89
91
|
parameter: 'default',
|
|
90
92
|
command: 'turnOn',
|
|
91
|
-
}
|
|
93
|
+
};
|
|
92
94
|
await this.pushChanges(payload);
|
|
93
95
|
}
|
|
94
96
|
}
|
|
@@ -99,12 +101,12 @@ export class Camera {
|
|
|
99
101
|
commandType: 'command',
|
|
100
102
|
parameter: 'default',
|
|
101
103
|
command: 'turnOff',
|
|
102
|
-
}
|
|
104
|
+
};
|
|
103
105
|
await this.pushChanges(payload);
|
|
104
106
|
}
|
|
105
107
|
}
|
|
106
108
|
|
|
107
|
-
async pushChanges(payload
|
|
109
|
+
async pushChanges(payload): Promise<void> {
|
|
108
110
|
try {
|
|
109
111
|
this.infoLog(
|
|
110
112
|
`Camera: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},` +
|
|
@@ -112,9 +114,42 @@ export class Camera {
|
|
|
112
114
|
);
|
|
113
115
|
|
|
114
116
|
// Make the API request
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
this.
|
|
117
|
+
const t = Date.now();
|
|
118
|
+
const nonce = 'requestID';
|
|
119
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
120
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
121
|
+
const sign = signTerm.toString('base64');
|
|
122
|
+
this.debugLog(`Camera: ${this.accessory.displayName} sign: ${sign}`);
|
|
123
|
+
const options = {
|
|
124
|
+
hostname: HostDomain,
|
|
125
|
+
port: 443,
|
|
126
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
127
|
+
method: 'POST',
|
|
128
|
+
headers: {
|
|
129
|
+
Authorization: this.platform.config.credentials?.token,
|
|
130
|
+
sign: sign,
|
|
131
|
+
nonce: nonce,
|
|
132
|
+
t: t,
|
|
133
|
+
'Content-Type': 'application/json',
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const req = https.request(options, (res) => {
|
|
138
|
+
this.debugLog(`Camera: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
139
|
+
this.statusCode({ res });
|
|
140
|
+
res.on('data', (d) => {
|
|
141
|
+
this.debugLog(`Camera: ${this.accessory.displayName} d: ${d}`);
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
req.on('error', (error) => {
|
|
146
|
+
this.errorLog(`Camera: ${this.accessory.displayName} error: ${error}`);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
req.write(payload);
|
|
150
|
+
req.end();
|
|
151
|
+
|
|
152
|
+
this.debugLog(`Camera: ${this.accessory.displayName} pushchanges: ${JSON.stringify(req)}`);
|
|
118
153
|
this.updateHomeKitCharacteristics();
|
|
119
154
|
this.OnCached = this.On;
|
|
120
155
|
this.accessory.context.On = this.OnCached;
|
|
@@ -129,8 +164,8 @@ export class Camera {
|
|
|
129
164
|
}
|
|
130
165
|
}
|
|
131
166
|
|
|
132
|
-
async statusCode(
|
|
133
|
-
switch (
|
|
167
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
168
|
+
switch (res.statusCode) {
|
|
134
169
|
case 151:
|
|
135
170
|
this.errorLog(`Camera: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
136
171
|
break;
|
|
@@ -149,7 +184,7 @@ export class Camera {
|
|
|
149
184
|
case 190:
|
|
150
185
|
this.errorLog(
|
|
151
186
|
`Camera: ${this.accessory.displayName} Device internal error due to device states not synchronized` +
|
|
152
|
-
` with server, Or command: ${JSON.stringify(
|
|
187
|
+
` with server, Or command: ${JSON.stringify(res)} format is invalid`,
|
|
153
188
|
);
|
|
154
189
|
break;
|
|
155
190
|
case 100:
|