@switchbot/homebridge-switchbot 1.15.1-beta.7 → 1.15.1-beta.9

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 (112) hide show
  1. package/.prettierrc +1 -1
  2. package/dist/device/bot.d.ts +8 -7
  3. package/dist/device/bot.d.ts.map +1 -1
  4. package/dist/device/bot.js +97 -21
  5. package/dist/device/bot.js.map +1 -1
  6. package/dist/device/colorbulb.d.ts +8 -7
  7. package/dist/device/colorbulb.d.ts.map +1 -1
  8. package/dist/device/colorbulb.js +221 -56
  9. package/dist/device/colorbulb.js.map +1 -1
  10. package/dist/device/contact.d.ts +3 -3
  11. package/dist/device/contact.d.ts.map +1 -1
  12. package/dist/device/contact.js +50 -7
  13. package/dist/device/contact.js.map +1 -1
  14. package/dist/device/curtain.d.ts +9 -8
  15. package/dist/device/curtain.d.ts.map +1 -1
  16. package/dist/device/curtain.js +95 -21
  17. package/dist/device/curtain.js.map +1 -1
  18. package/dist/device/humidifier.d.ts +8 -7
  19. package/dist/device/humidifier.d.ts.map +1 -1
  20. package/dist/device/humidifier.js +180 -59
  21. package/dist/device/humidifier.js.map +1 -1
  22. package/dist/device/lock.d.ts +8 -7
  23. package/dist/device/lock.d.ts.map +1 -1
  24. package/dist/device/lock.js +98 -22
  25. package/dist/device/lock.js.map +1 -1
  26. package/dist/device/meter.d.ts +4 -4
  27. package/dist/device/meter.d.ts.map +1 -1
  28. package/dist/device/meter.js +51 -8
  29. package/dist/device/meter.js.map +1 -1
  30. package/dist/device/meterplus.d.ts +3 -3
  31. package/dist/device/meterplus.d.ts.map +1 -1
  32. package/dist/device/meterplus.js +49 -6
  33. package/dist/device/meterplus.js.map +1 -1
  34. package/dist/device/motion.d.ts +3 -3
  35. package/dist/device/motion.d.ts.map +1 -1
  36. package/dist/device/motion.js +49 -9
  37. package/dist/device/motion.js.map +1 -1
  38. package/dist/device/plug.d.ts +8 -7
  39. package/dist/device/plug.d.ts.map +1 -1
  40. package/dist/device/plug.js +96 -20
  41. package/dist/device/plug.js.map +1 -1
  42. package/dist/device/striplight.d.ts +8 -7
  43. package/dist/device/striplight.d.ts.map +1 -1
  44. package/dist/device/striplight.js +186 -47
  45. package/dist/device/striplight.js.map +1 -1
  46. package/dist/irdevice/airconditioner.d.ts +7 -6
  47. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  48. package/dist/irdevice/airconditioner.js +40 -6
  49. package/dist/irdevice/airconditioner.js.map +1 -1
  50. package/dist/irdevice/airpurifier.d.ts +7 -6
  51. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  52. package/dist/irdevice/airpurifier.js +46 -11
  53. package/dist/irdevice/airpurifier.js.map +1 -1
  54. package/dist/irdevice/camera.d.ts +7 -6
  55. package/dist/irdevice/camera.d.ts.map +1 -1
  56. package/dist/irdevice/camera.js +40 -6
  57. package/dist/irdevice/camera.js.map +1 -1
  58. package/dist/irdevice/fan.d.ts +8 -7
  59. package/dist/irdevice/fan.d.ts.map +1 -1
  60. package/dist/irdevice/fan.js +40 -6
  61. package/dist/irdevice/fan.js.map +1 -1
  62. package/dist/irdevice/light.d.ts +7 -6
  63. package/dist/irdevice/light.d.ts.map +1 -1
  64. package/dist/irdevice/light.js +40 -6
  65. package/dist/irdevice/light.js.map +1 -1
  66. package/dist/irdevice/other.d.ts +7 -6
  67. package/dist/irdevice/other.d.ts.map +1 -1
  68. package/dist/irdevice/other.js +40 -6
  69. package/dist/irdevice/other.js.map +1 -1
  70. package/dist/irdevice/tv.d.ts +8 -7
  71. package/dist/irdevice/tv.d.ts.map +1 -1
  72. package/dist/irdevice/tv.js +40 -6
  73. package/dist/irdevice/tv.js.map +1 -1
  74. package/dist/irdevice/vacuumcleaner.d.ts +7 -6
  75. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  76. package/dist/irdevice/vacuumcleaner.js +40 -6
  77. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  78. package/dist/irdevice/waterheater.d.ts +7 -6
  79. package/dist/irdevice/waterheater.d.ts.map +1 -1
  80. package/dist/irdevice/waterheater.js +40 -6
  81. package/dist/irdevice/waterheater.js.map +1 -1
  82. package/dist/platform.d.ts +3 -5
  83. package/dist/platform.d.ts.map +1 -1
  84. package/dist/platform.js +141 -95
  85. package/dist/platform.js.map +1 -1
  86. package/dist/settings.d.ts +2 -21
  87. package/dist/settings.d.ts.map +1 -1
  88. package/dist/settings.js +3 -3
  89. package/dist/settings.js.map +1 -1
  90. package/package.json +6 -7
  91. package/src/device/bot.ts +97 -30
  92. package/src/device/colorbulb.ts +225 -93
  93. package/src/device/contact.ts +49 -10
  94. package/src/device/curtain.ts +98 -31
  95. package/src/device/humidifier.ts +182 -77
  96. package/src/device/lock.ts +97 -30
  97. package/src/device/meter.ts +51 -12
  98. package/src/device/meterplus.ts +48 -9
  99. package/src/device/motion.ts +48 -12
  100. package/src/device/plug.ts +97 -29
  101. package/src/device/striplight.ts +189 -68
  102. package/src/irdevice/airconditioner.ts +44 -9
  103. package/src/irdevice/airpurifier.ts +52 -17
  104. package/src/irdevice/camera.ts +46 -11
  105. package/src/irdevice/fan.ts +50 -15
  106. package/src/irdevice/light.ts +48 -13
  107. package/src/irdevice/other.ts +46 -11
  108. package/src/irdevice/tv.ts +56 -21
  109. package/src/irdevice/vacuumcleaner.ts +46 -11
  110. package/src/irdevice/waterheater.ts +46 -11
  111. package/src/platform.ts +154 -108
  112. package/src/settings.ts +2 -25
@@ -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:
@@ -1,6 +1,8 @@
1
- import { AxiosResponse } from 'axios';
1
+ import https from 'https';
2
+ import crypto from 'crypto';
3
+ import { IncomingMessage } from 'http';
2
4
  import { SwitchBotPlatform } from '../platform';
3
- import { irDevicesConfig, DeviceURL, irdevice, payload } from '../settings';
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: payload): Promise<void> {
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 push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
262
- this.debugLog(`Air Conditioner: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
263
- this.statusCode(push);
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(push: AxiosResponse<{ statusCode: number }>): Promise<void> {
283
- switch (push.data.statusCode) {
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(push.data)} format is invalid`,
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 { AxiosResponse } from 'axios';
1
+ import https from 'https';
2
+ import crypto from 'crypto';
3
+ import { IncomingMessage } from 'http';
2
4
  import { SwitchBotPlatform } from '../platform';
3
- import { irDevicesConfig, DeviceURL, irdevice, payload } from '../settings';
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
- } as payload;
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
- } as payload;
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
- payload.parameter = `${this.CurrentAPTemp},${this.CurrentAPMode},${this.CurrentAPFanSpeed},${this.APActive}`;
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: payload): Promise<void> {
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 push = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
224
- this.debugLog(`Air Purifier: ${this.accessory.displayName} pushChanges: ${push.data}`);
225
- this.statusCode(push);
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(push: AxiosResponse<{ statusCode: number }>): Promise<void> {
241
- switch (push.data.statusCode) {
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(push.data)} format is invalid`,
295
+ ` with server, Or command: ${JSON.stringify(res)} format is invalid`,
261
296
  );
262
297
  break;
263
298
  case 100:
@@ -1,6 +1,8 @@
1
- import { AxiosResponse } from 'axios';
1
+ import https from 'https';
2
+ import crypto from 'crypto';
3
+ import { IncomingMessage } from 'http';
2
4
  import { SwitchBotPlatform } from '../platform';
3
- import { irDevicesConfig, DeviceURL, irdevice, payload } from '../settings';
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
- } as payload;
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
- } as payload;
104
+ };
103
105
  await this.pushChanges(payload);
104
106
  }
105
107
  }
106
108
 
107
- async pushChanges(payload: payload): Promise<void> {
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 push = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
116
- this.debugLog(`Camera: ${this.accessory.displayName} pushChanges: ${push.data}`);
117
- this.statusCode(push);
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(push: AxiosResponse<{ statusCode: number }>): Promise<void> {
133
- switch (push.data.statusCode) {
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(push.data)} format is invalid`,
187
+ ` with server, Or command: ${JSON.stringify(res)} format is invalid`,
153
188
  );
154
189
  break;
155
190
  case 100: