@switchbot/homebridge-switchbot 1.15.1-beta.1 → 1.15.1-beta.11

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 (116) hide show
  1. package/.github/ISSUE_TEMPLATE/bug-report.yml +1 -0
  2. package/.github/ISSUE_TEMPLATE/feature-request.yml +1 -0
  3. package/.github/ISSUE_TEMPLATE/support-request.yml +1 -0
  4. package/.prettierrc +1 -1
  5. package/CHANGELOG.md +9 -0
  6. package/dist/device/bot.d.ts +8 -7
  7. package/dist/device/bot.d.ts.map +1 -1
  8. package/dist/device/bot.js +97 -21
  9. package/dist/device/bot.js.map +1 -1
  10. package/dist/device/colorbulb.d.ts +8 -7
  11. package/dist/device/colorbulb.d.ts.map +1 -1
  12. package/dist/device/colorbulb.js +221 -56
  13. package/dist/device/colorbulb.js.map +1 -1
  14. package/dist/device/contact.d.ts +3 -3
  15. package/dist/device/contact.d.ts.map +1 -1
  16. package/dist/device/contact.js +50 -7
  17. package/dist/device/contact.js.map +1 -1
  18. package/dist/device/curtain.d.ts +9 -8
  19. package/dist/device/curtain.d.ts.map +1 -1
  20. package/dist/device/curtain.js +95 -21
  21. package/dist/device/curtain.js.map +1 -1
  22. package/dist/device/humidifier.d.ts +8 -7
  23. package/dist/device/humidifier.d.ts.map +1 -1
  24. package/dist/device/humidifier.js +180 -59
  25. package/dist/device/humidifier.js.map +1 -1
  26. package/dist/device/lock.d.ts +8 -7
  27. package/dist/device/lock.d.ts.map +1 -1
  28. package/dist/device/lock.js +98 -22
  29. package/dist/device/lock.js.map +1 -1
  30. package/dist/device/meter.d.ts +4 -4
  31. package/dist/device/meter.d.ts.map +1 -1
  32. package/dist/device/meter.js +51 -8
  33. package/dist/device/meter.js.map +1 -1
  34. package/dist/device/meterplus.d.ts +3 -3
  35. package/dist/device/meterplus.d.ts.map +1 -1
  36. package/dist/device/meterplus.js +49 -6
  37. package/dist/device/meterplus.js.map +1 -1
  38. package/dist/device/motion.d.ts +3 -3
  39. package/dist/device/motion.d.ts.map +1 -1
  40. package/dist/device/motion.js +49 -9
  41. package/dist/device/motion.js.map +1 -1
  42. package/dist/device/plug.d.ts +8 -7
  43. package/dist/device/plug.d.ts.map +1 -1
  44. package/dist/device/plug.js +96 -20
  45. package/dist/device/plug.js.map +1 -1
  46. package/dist/device/striplight.d.ts +8 -7
  47. package/dist/device/striplight.d.ts.map +1 -1
  48. package/dist/device/striplight.js +186 -47
  49. package/dist/device/striplight.js.map +1 -1
  50. package/dist/irdevice/airconditioner.d.ts +7 -6
  51. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  52. package/dist/irdevice/airconditioner.js +65 -28
  53. package/dist/irdevice/airconditioner.js.map +1 -1
  54. package/dist/irdevice/airpurifier.d.ts +7 -6
  55. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  56. package/dist/irdevice/airpurifier.js +65 -28
  57. package/dist/irdevice/airpurifier.js.map +1 -1
  58. package/dist/irdevice/camera.d.ts +7 -6
  59. package/dist/irdevice/camera.d.ts.map +1 -1
  60. package/dist/irdevice/camera.js +58 -22
  61. package/dist/irdevice/camera.js.map +1 -1
  62. package/dist/irdevice/fan.d.ts +8 -7
  63. package/dist/irdevice/fan.d.ts.map +1 -1
  64. package/dist/irdevice/fan.js +76 -40
  65. package/dist/irdevice/fan.js.map +1 -1
  66. package/dist/irdevice/light.d.ts +7 -6
  67. package/dist/irdevice/light.d.ts.map +1 -1
  68. package/dist/irdevice/light.js +71 -35
  69. package/dist/irdevice/light.js.map +1 -1
  70. package/dist/irdevice/other.d.ts +7 -6
  71. package/dist/irdevice/other.d.ts.map +1 -1
  72. package/dist/irdevice/other.js +58 -22
  73. package/dist/irdevice/other.js.map +1 -1
  74. package/dist/irdevice/tv.d.ts +8 -7
  75. package/dist/irdevice/tv.d.ts.map +1 -1
  76. package/dist/irdevice/tv.js +112 -76
  77. package/dist/irdevice/tv.js.map +1 -1
  78. package/dist/irdevice/vacuumcleaner.d.ts +7 -6
  79. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  80. package/dist/irdevice/vacuumcleaner.js +58 -22
  81. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  82. package/dist/irdevice/waterheater.d.ts +7 -6
  83. package/dist/irdevice/waterheater.d.ts.map +1 -1
  84. package/dist/irdevice/waterheater.js +58 -22
  85. package/dist/irdevice/waterheater.js.map +1 -1
  86. package/dist/platform.d.ts +3 -5
  87. package/dist/platform.d.ts.map +1 -1
  88. package/dist/platform.js +143 -87
  89. package/dist/platform.js.map +1 -1
  90. package/dist/settings.d.ts +2 -21
  91. package/dist/settings.d.ts.map +1 -1
  92. package/dist/settings.js +3 -3
  93. package/dist/settings.js.map +1 -1
  94. package/package.json +10 -12
  95. package/src/device/bot.ts +97 -30
  96. package/src/device/colorbulb.ts +225 -93
  97. package/src/device/contact.ts +49 -10
  98. package/src/device/curtain.ts +98 -31
  99. package/src/device/humidifier.ts +182 -77
  100. package/src/device/lock.ts +97 -30
  101. package/src/device/meter.ts +51 -12
  102. package/src/device/meterplus.ts +48 -9
  103. package/src/device/motion.ts +48 -12
  104. package/src/device/plug.ts +97 -29
  105. package/src/device/striplight.ts +189 -68
  106. package/src/irdevice/airconditioner.ts +64 -34
  107. package/src/irdevice/airpurifier.ts +64 -36
  108. package/src/irdevice/camera.ts +57 -27
  109. package/src/irdevice/fan.ts +76 -46
  110. package/src/irdevice/light.ts +69 -39
  111. package/src/irdevice/other.ts +57 -27
  112. package/src/irdevice/tv.ts +112 -82
  113. package/src/irdevice/vacuumcleaner.ts +57 -27
  114. package/src/irdevice/waterheater.ts +57 -27
  115. package/src/platform.ts +157 -100
  116. package/src/settings.ts +2 -25
@@ -1,9 +1,11 @@
1
+ import https from 'https';
2
+ import crypto from 'crypto';
3
+ import { Context } from 'vm';
1
4
  import { interval, Subject } from 'rxjs';
2
5
  import { skipWhile } from 'rxjs/operators';
3
6
  import { SwitchBotPlatform } from '../platform';
4
7
  import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
5
- import { DeviceURL, device, devicesConfig, serviceData, switchbot, deviceStatusResponse, deviceStatus, ad } from '../settings';
6
- import { Context } from 'vm';
8
+ import { device, devicesConfig, serviceData, switchbot, deviceStatus, ad, HostDomain, DevicePath } from '../settings';
7
9
 
8
10
  /**
9
11
  * Platform Accessory
@@ -23,7 +25,7 @@ export class Motion {
23
25
  StatusLowBattery?: CharacteristicValue;
24
26
 
25
27
  // OpenAPI Others
26
- deviceStatus!: deviceStatusResponse;
28
+ deviceStatus!: any; //deviceStatusResponse;
27
29
  moveDetected: deviceStatus['moveDetected'];
28
30
  brightness: deviceStatus['brightness'];
29
31
 
@@ -326,15 +328,49 @@ export class Motion {
326
328
  if (this.platform.config.credentials?.token) {
327
329
  this.debugLog(`Motion Sensor: ${this.accessory.displayName} OpenAPI RefreshStatus`);
328
330
  try {
329
- this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
330
- this.debugLog(`Motion Sensor: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
331
- if (this.deviceStatus.body.moveDetected === undefined) {
332
- this.errorLog(`Motion Sensor: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
333
- }
334
- this.moveDetected = this.deviceStatus.body.moveDetected;
335
- this.brightness = this.deviceStatus.body.brightness;
336
- this.parseStatus();
337
- this.updateHomeKitCharacteristics();
331
+ const t = Date.now();
332
+ const nonce = 'requestID';
333
+ const data = this.platform.config.credentials?.token + t + nonce;
334
+ const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
335
+ const sign = signTerm.toString('base64');
336
+ this.debugLog(`Motion Sensor: ${this.accessory.displayName} sign: ${sign}`);
337
+ const options = {
338
+ hostname: HostDomain,
339
+ port: 443,
340
+ path: `${DevicePath}/${this.device.deviceId}/status`,
341
+ method: 'GET',
342
+ headers: {
343
+ Authorization: this.platform.config.credentials?.token,
344
+ sign: sign,
345
+ nonce: nonce,
346
+ t: t,
347
+ 'Content-Type': 'application/json',
348
+ },
349
+ };
350
+ const req = https.request(options, (res) => {
351
+ this.debugLog(`Motion Sensor: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
352
+ let rawData = '';
353
+ res.on('data', (d) => {
354
+ rawData += d;
355
+ this.debugLog(`Motion Sensor: ${this.accessory.displayName} d: ${d}`);
356
+ });
357
+ res.on('end', () => {
358
+ try {
359
+ this.deviceStatus = JSON.parse(rawData);
360
+ this.debugLog(`Motion Sensor: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
361
+ this.moveDetected = this.deviceStatus.body.moveDetected;
362
+ this.brightness = this.deviceStatus.body.brightness;
363
+ this.parseStatus();
364
+ this.updateHomeKitCharacteristics();
365
+ } catch (e: any) {
366
+ this.errorLog(`Motion Sensor: ${this.accessory.displayName} error message: ${e.message}`);
367
+ }
368
+ });
369
+ });
370
+ req.on('error', (e: any) => {
371
+ this.errorLog(`Motion Sensor: ${this.accessory.displayName} error message: ${e.message}`);
372
+ });
373
+ req.end();
338
374
  } catch (e: any) {
339
375
  this.errorLog(`Motion Sensor: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
340
376
  if (this.deviceLogging.includes('debug')) {
@@ -1,10 +1,12 @@
1
- import { AxiosResponse } from 'axios';
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, take, tap } from 'rxjs/operators';
5
8
  import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
6
- import { DeviceURL, device, devicesConfig, deviceStatusResponse, payload, deviceStatus, ad, serviceData, switchbot } from '../settings';
7
- import { Context } from 'vm';
9
+ import { device, devicesConfig, deviceStatus, ad, serviceData, switchbot, HostDomain, DevicePath } from '../settings';
8
10
 
9
11
  export class Plug {
10
12
  // Services
@@ -16,7 +18,7 @@ export class Plug {
16
18
 
17
19
  // OpenAPI Others
18
20
  power: deviceStatus['power'];
19
- deviceStatus!: deviceStatusResponse;
21
+ deviceStatus!: any; //deviceStatusResponse;
20
22
 
21
23
  // BLE Others
22
24
  connected?: boolean;
@@ -281,11 +283,48 @@ export class Plug {
281
283
 
282
284
  async openAPIRefreshStatus() {
283
285
  try {
284
- this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
285
- this.debugLog(`Plug: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
286
- this.power = this.deviceStatus.body.power;
287
- this.parseStatus();
288
- this.updateHomeKitCharacteristics();
286
+ const t = Date.now();
287
+ const nonce = 'requestID';
288
+ const data = this.platform.config.credentials?.token + t + nonce;
289
+ const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
290
+ const sign = signTerm.toString('base64');
291
+ this.debugLog(`Plug: ${this.accessory.displayName} sign: ${sign}`);
292
+ const options = {
293
+ hostname: HostDomain,
294
+ port: 443,
295
+ path: `${DevicePath}/${this.device.deviceId}/status`,
296
+ method: 'GET',
297
+ headers: {
298
+ Authorization: this.platform.config.credentials?.token,
299
+ sign: sign,
300
+ nonce: nonce,
301
+ t: t,
302
+ 'Content-Type': 'application/json',
303
+ },
304
+ };
305
+ const req = https.request(options, (res) => {
306
+ this.debugLog(`Plug: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
307
+ let rawData = '';
308
+ res.on('data', (d) => {
309
+ rawData += d;
310
+ this.debugLog(`Plug: ${this.accessory.displayName} d: ${d}`);
311
+ });
312
+ res.on('end', () => {
313
+ try {
314
+ this.deviceStatus = JSON.parse(rawData);
315
+ this.debugLog(`Plug: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
316
+ this.power = this.deviceStatus.body.power;
317
+ this.parseStatus();
318
+ this.updateHomeKitCharacteristics();
319
+ } catch (e: any) {
320
+ this.errorLog(`Plug: ${this.accessory.displayName} error message: ${e.message}`);
321
+ }
322
+ });
323
+ });
324
+ req.on('error', (e: any) => {
325
+ this.errorLog(`Plug: ${this.accessory.displayName} error message: ${e.message}`);
326
+ });
327
+ req.end();
289
328
  } catch (e: any) {
290
329
  this.errorLog(`Plug: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
291
330
  if (this.deviceLogging.includes('debug')) {
@@ -376,27 +415,56 @@ export class Plug {
376
415
  async openAPIpushChanges() {
377
416
  if (this.platform.config.credentials?.token) {
378
417
  if (this.On !== this.OnCached) {
418
+ // Make Push On request to the API
379
419
  this.debugLog(`Plug: ${this.accessory.displayName} OpenAPI pushChanges`);
380
- const payload = {
381
- commandType: 'command',
382
- parameter: 'default',
383
- } as payload;
384
-
420
+ const t = Date.now();
421
+ const nonce = 'requestID';
422
+ const data = this.platform.config.credentials?.token + t + nonce;
423
+ const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
424
+ .update(Buffer.from(data, 'utf-8'))
425
+ .digest();
426
+ const sign = signTerm.toString('base64');
427
+ this.debugLog(`Plug: ${this.accessory.displayName} sign: ${sign}`);
428
+
429
+ let command = '';
385
430
  if (this.On) {
386
- payload.command = 'turnOn';
431
+ command = 'turnOn';
387
432
  } else {
388
- payload.command = 'turnOff';
433
+ command = 'turnOff';
389
434
  }
390
-
391
- this.infoLog(
392
- `Plug: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},` +
393
- ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`,
394
- );
395
-
396
- // Make the API request
397
- const push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
398
- this.debugLog(`Plug: ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
399
- this.statusCode(push);
435
+ const body = JSON.stringify({
436
+ 'command': `${command}`,
437
+ 'parameter': 'default',
438
+ 'commandType': 'command',
439
+ });
440
+ this.infoLog(`Plug: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
441
+ const options = {
442
+ hostname: HostDomain,
443
+ port: 443,
444
+ path: `${DevicePath}/${this.device.deviceId}/commands`,
445
+ method: 'POST',
446
+ headers: {
447
+ 'Authorization': this.platform.config.credentials?.token,
448
+ 'sign': sign,
449
+ 'nonce': nonce,
450
+ 't': t,
451
+ 'Content-Type': 'application/json',
452
+ 'Content-Length': body.length,
453
+ },
454
+ };
455
+ const req = https.request(options, res => {
456
+ this.debugLog(`Plug: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
457
+ this.statusCode({ res });
458
+ res.on('data', d => {
459
+ this.debugLog(`Plug: ${this.accessory.displayName} d: ${d}`);
460
+ });
461
+ });
462
+ req.on('error', (e: any) => {
463
+ this.errorLog(`Plug: ${this.accessory.displayName} error message: ${e.message}`);
464
+ });
465
+ req.write(body);
466
+ req.end();
467
+ this.debugLog(`Plug: ${this.accessory.displayName} openAPIpushChanges: ${JSON.stringify(req)}`);
400
468
  this.OnCached = this.On;
401
469
  this.accessory.context.On = this.OnCached;
402
470
  }
@@ -422,8 +490,8 @@ export class Plug {
422
490
  //throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
423
491
  }
424
492
 
425
- async statusCode(push: AxiosResponse<{ statusCode: number }>): Promise<void> {
426
- switch (push.data.statusCode) {
493
+ async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
494
+ switch (res.statusCode) {
427
495
  case 151:
428
496
  this.errorLog(`Plug: ${this.accessory.displayName} Command not supported by this device type.`);
429
497
  break;
@@ -444,7 +512,7 @@ export class Plug {
444
512
  case 190:
445
513
  this.errorLog(
446
514
  `Plug: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
447
- ` Or command: ${JSON.stringify(push.data)} format is invalid`,
515
+ ` Or command: ${JSON.stringify(res)} format is invalid`,
448
516
  );
449
517
  break;
450
518
  case 100:
@@ -1,10 +1,12 @@
1
- import { AxiosResponse } from 'axios';
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 { DeviceURL, device, devicesConfig, switchbot, deviceStatusResponse, payload, hs2rgb, rgb2hs, deviceStatus } from '../settings';
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
- this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
214
- this.debugLog(`Strip Light: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
215
- this.power = this.deviceStatus.body.power;
216
- this.color = this.deviceStatus.body.color;
217
- this.brightness = this.deviceStatus.body.brightness;
218
-
219
- this.parseStatus();
220
- this.updateHomeKitCharacteristics();
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 Update
246
- const payload = {
247
- commandType: 'command',
248
- parameter: 'default',
249
- } as payload;
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
- payload.command = 'turnOn';
295
+ command = 'turnOn';
253
296
  } else {
254
- payload.command = 'turnOff';
297
+ command = 'turnOff';
255
298
  }
256
-
257
- this.infoLog(
258
- `Strip Light: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},` +
259
- ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`,
260
- );
261
-
262
- // Make the API request
263
- const push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
264
- this.debugLog(`Strip Light: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
265
- this.statusCode(push);
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 payload = {
299
- commandType: 'command',
300
- command: 'setColor',
301
- parameter: `${red}:${green}:${blue}`,
302
- } as payload;
303
-
304
- this.infoLog(
305
- `Strip Light: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},` +
306
- ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`,
307
- );
308
-
309
- // Make the API request
310
- const push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
311
- this.debugLog(`Strip Light: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
312
- this.statusCode(push);
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 pushChanges with OpenAPI Connection`);
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 pushChanges with OpenAPI Connection,` + ` Error Message: ${JSON.stringify(e.message)}`,
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
- const payload = {
336
- commandType: 'command',
337
- command: 'setBrightness',
338
- parameter: `${this.Brightness}`,
339
- } as payload;
340
-
341
- this.infoLog(
342
- `Strip Light: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},` +
343
- ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`,
344
- );
345
-
346
- // Make the API request
347
- const push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
348
- this.debugLog(`Strip Light: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
349
- this.statusCode(push);
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 pushChanges with OpenAPI Connection`);
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 pushChanges with OpenAPI Connection,` + ` Error Message: ${JSON.stringify(e.message)}`,
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(push: AxiosResponse<{ statusCode: number }>): void {
403
- switch (push.data.statusCode) {
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(push.data)} format is invalid`,
545
+ ` Or command: ${JSON.stringify(res)} format is invalid`,
425
546
  );
426
547
  break;
427
548
  case 100: