@switchbot/homebridge-switchbot 2.6.0-beta.4 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/.vscode/tasks.json +13 -0
  2. package/CHANGELOG.md +4 -2
  3. package/README.md +18 -9
  4. package/dist/device/blindtilt.d.ts +1 -5
  5. package/dist/device/blindtilt.d.ts.map +1 -1
  6. package/dist/device/blindtilt.js +80 -140
  7. package/dist/device/blindtilt.js.map +1 -1
  8. package/dist/device/bot.d.ts +1 -5
  9. package/dist/device/bot.d.ts.map +1 -1
  10. package/dist/device/bot.js +79 -138
  11. package/dist/device/bot.js.map +1 -1
  12. package/dist/device/ceilinglight.d.ts +2 -6
  13. package/dist/device/ceilinglight.d.ts.map +1 -1
  14. package/dist/device/ceilinglight.js +157 -304
  15. package/dist/device/ceilinglight.js.map +1 -1
  16. package/dist/device/colorbulb.d.ts +2 -6
  17. package/dist/device/colorbulb.d.ts.map +1 -1
  18. package/dist/device/colorbulb.js +164 -311
  19. package/dist/device/colorbulb.js.map +1 -1
  20. package/dist/device/contact.d.ts +1 -5
  21. package/dist/device/contact.d.ts.map +1 -1
  22. package/dist/device/contact.js +36 -72
  23. package/dist/device/contact.js.map +1 -1
  24. package/dist/device/curtain.d.ts +1 -5
  25. package/dist/device/curtain.d.ts.map +1 -1
  26. package/dist/device/curtain.js +78 -138
  27. package/dist/device/curtain.js.map +1 -1
  28. package/dist/device/hub.d.ts +2 -6
  29. package/dist/device/hub.d.ts.map +1 -1
  30. package/dist/device/hub.js +30 -63
  31. package/dist/device/hub.js.map +1 -1
  32. package/dist/device/humidifier.d.ts +1 -5
  33. package/dist/device/humidifier.d.ts.map +1 -1
  34. package/dist/device/humidifier.js +115 -228
  35. package/dist/device/humidifier.js.map +1 -1
  36. package/dist/device/iosensor.d.ts +1 -5
  37. package/dist/device/iosensor.d.ts.map +1 -1
  38. package/dist/device/iosensor.js +38 -74
  39. package/dist/device/iosensor.js.map +1 -1
  40. package/dist/device/{striplight.d.ts → lightstrip.d.ts} +2 -10
  41. package/dist/device/lightstrip.d.ts.map +1 -0
  42. package/dist/device/{striplight.js → lightstrip.js} +138 -194
  43. package/dist/device/lightstrip.js.map +1 -0
  44. package/dist/device/lock.d.ts +1 -5
  45. package/dist/device/lock.d.ts.map +1 -1
  46. package/dist/device/lock.js +66 -126
  47. package/dist/device/lock.js.map +1 -1
  48. package/dist/device/meter.d.ts +1 -5
  49. package/dist/device/meter.d.ts.map +1 -1
  50. package/dist/device/meter.js +38 -74
  51. package/dist/device/meter.js.map +1 -1
  52. package/dist/device/meterplus.d.ts +1 -5
  53. package/dist/device/meterplus.d.ts.map +1 -1
  54. package/dist/device/meterplus.js +39 -75
  55. package/dist/device/meterplus.js.map +1 -1
  56. package/dist/device/motion.d.ts +1 -5
  57. package/dist/device/motion.d.ts.map +1 -1
  58. package/dist/device/motion.js +35 -72
  59. package/dist/device/motion.js.map +1 -1
  60. package/dist/device/plug.d.ts +1 -5
  61. package/dist/device/plug.d.ts.map +1 -1
  62. package/dist/device/plug.js +65 -126
  63. package/dist/device/plug.js.map +1 -1
  64. package/dist/device/robotvacuumcleaner.d.ts +1 -5
  65. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  66. package/dist/device/robotvacuumcleaner.js +79 -151
  67. package/dist/device/robotvacuumcleaner.js.map +1 -1
  68. package/dist/irdevice/airconditioner.d.ts +3 -7
  69. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  70. package/dist/irdevice/airconditioner.js +34 -62
  71. package/dist/irdevice/airconditioner.js.map +1 -1
  72. package/dist/irdevice/airpurifier.d.ts +3 -7
  73. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  74. package/dist/irdevice/airpurifier.js +31 -59
  75. package/dist/irdevice/airpurifier.js.map +1 -1
  76. package/dist/irdevice/camera.d.ts +1 -5
  77. package/dist/irdevice/camera.d.ts.map +1 -1
  78. package/dist/irdevice/camera.js +30 -57
  79. package/dist/irdevice/camera.js.map +1 -1
  80. package/dist/irdevice/fan.d.ts +2 -6
  81. package/dist/irdevice/fan.d.ts.map +1 -1
  82. package/dist/irdevice/fan.js +39 -66
  83. package/dist/irdevice/fan.js.map +1 -1
  84. package/dist/irdevice/light.d.ts +1 -5
  85. package/dist/irdevice/light.d.ts.map +1 -1
  86. package/dist/irdevice/light.js +32 -59
  87. package/dist/irdevice/light.js.map +1 -1
  88. package/dist/irdevice/other.d.ts +1 -5
  89. package/dist/irdevice/other.d.ts.map +1 -1
  90. package/dist/irdevice/other.js +30 -57
  91. package/dist/irdevice/other.js.map +1 -1
  92. package/dist/irdevice/tv.d.ts +3 -7
  93. package/dist/irdevice/tv.d.ts.map +1 -1
  94. package/dist/irdevice/tv.js +46 -76
  95. package/dist/irdevice/tv.js.map +1 -1
  96. package/dist/irdevice/vacuumcleaner.d.ts +2 -6
  97. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  98. package/dist/irdevice/vacuumcleaner.js +30 -58
  99. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  100. package/dist/irdevice/waterheater.d.ts +7 -23
  101. package/dist/irdevice/waterheater.d.ts.map +1 -1
  102. package/dist/irdevice/waterheater.js +41 -74
  103. package/dist/irdevice/waterheater.js.map +1 -1
  104. package/dist/platform.d.ts +14 -5
  105. package/dist/platform.d.ts.map +1 -1
  106. package/dist/platform.js +156 -149
  107. package/dist/platform.js.map +1 -1
  108. package/dist/settings.d.ts +4 -0
  109. package/dist/settings.d.ts.map +1 -1
  110. package/dist/settings.js +5 -1
  111. package/dist/settings.js.map +1 -1
  112. package/nodemon.json +1 -1
  113. package/package.json +10 -10
  114. package/src/device/blindtilt.ts +122 -181
  115. package/src/device/bot.ts +96 -149
  116. package/src/device/ceilinglight.ts +172 -315
  117. package/src/device/colorbulb.ts +178 -324
  118. package/src/device/contact.ts +48 -78
  119. package/src/device/curtain.ts +93 -148
  120. package/src/device/hub.ts +34 -63
  121. package/src/device/humidifier.ts +135 -243
  122. package/src/device/iosensor.ts +49 -79
  123. package/src/device/{striplight.ts → lightstrip.ts} +148 -200
  124. package/src/device/lock.ts +78 -134
  125. package/src/device/meter.ts +48 -78
  126. package/src/device/meterplus.ts +50 -80
  127. package/src/device/motion.ts +46 -77
  128. package/src/device/plug.ts +76 -134
  129. package/src/device/robotvacuumcleaner.ts +91 -159
  130. package/src/irdevice/airconditioner.ts +56 -81
  131. package/src/irdevice/airpurifier.ts +41 -67
  132. package/src/irdevice/camera.ts +35 -60
  133. package/src/irdevice/fan.ts +46 -71
  134. package/src/irdevice/light.ts +38 -63
  135. package/src/irdevice/other.ts +35 -60
  136. package/src/irdevice/tv.ts +52 -80
  137. package/src/irdevice/vacuumcleaner.ts +36 -62
  138. package/src/irdevice/waterheater.ts +46 -76
  139. package/src/platform.ts +144 -158
  140. package/src/settings.ts +5 -0
  141. package/.github/npm-version-script.js +0 -81
  142. package/dist/device/striplight.d.ts.map +0 -1
  143. package/dist/device/striplight.js.map +0 -1
@@ -1,17 +1,14 @@
1
- import https from 'https';
2
- import crypto from 'crypto';
3
1
  import { Context } from 'vm';
4
2
  import { hostname } from 'os';
3
+ import { request } from 'undici';
4
+ import { sleep } from '../utils';
5
5
  import { MqttClient } from 'mqtt';
6
6
  import { connectAsync } from 'async-mqtt';
7
7
  import { interval, Subject } from 'rxjs';
8
8
  import { skipWhile } from 'rxjs/operators';
9
- import superStringify from 'super-stringify';
10
9
  import { SwitchBotPlatform } from '../platform';
11
10
  import { Service, PlatformAccessory, Units, CharacteristicValue } from 'homebridge';
12
- import { device, devicesConfig, serviceData, ad, switchbot, temperature, deviceStatus, HostDomain, DevicePath } from '../settings';
13
- import { IncomingMessage } from 'http';
14
- import { sleep } from '../utils';
11
+ import { device, devicesConfig, serviceData, ad, switchbot, temperature, deviceStatus, Devices } from '../settings';
15
12
 
16
13
  /**
17
14
  * Platform Accessory
@@ -186,7 +183,7 @@ export class IOSensor {
186
183
  } else {
187
184
  await this.offlineOff();
188
185
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
189
- + ` ${this.device.connectionType}, parseStatus will not happen.`);
186
+ + ` ${this.device.connectionType}, parseStatus will not happen.`);
190
187
  }
191
188
  }
192
189
 
@@ -254,7 +251,7 @@ export class IOSensor {
254
251
  } else {
255
252
  await this.offlineOff();
256
253
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
257
- + ` ${this.device.connectionType}, refreshStatus will not happen.`);
254
+ + ` ${this.device.connectionType}, refreshStatus will not happen.`);
258
255
  }
259
256
  }
260
257
 
@@ -280,7 +277,7 @@ export class IOSensor {
280
277
  switchbot.onadvertisement = async (ad: ad) => {
281
278
  this.address = ad.address;
282
279
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac},`
283
- + ` BLE Address Found: ${this.address}`);
280
+ + ` BLE Address Found: ${this.address}`);
284
281
  if (ad.serviceData.humidity! > 0) {
285
282
  // reject unreliable data
286
283
  this.humidity = ad.serviceData.humidity;
@@ -290,11 +287,11 @@ export class IOSensor {
290
287
  this.celsius = ad.serviceData.temperature!.c;
291
288
  this.fahrenheit = ad.serviceData.temperature!.f;
292
289
  this.battery = ad.serviceData.battery;
293
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${superStringify(ad.serviceData)}`);
290
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
294
291
  this.debugLog(
295
292
  `${this.device.deviceType}: ${this.accessory.displayName} model: ${ad.serviceData.model}, modelName: ${ad.serviceData.modelName}, ` +
296
- `temperature: ${superStringify(ad.serviceData.temperature?.c)}, humidity: ${ad.serviceData.humidity}, ` +
297
- `battery: ${ad.serviceData.battery}`,
293
+ `temperature: ${JSON.stringify(ad.serviceData.temperature?.c)}, humidity: ${ad.serviceData.humidity}, ` +
294
+ `battery: ${ad.serviceData.battery}`,
298
295
  );
299
296
 
300
297
  if (this.serviceData) {
@@ -316,7 +313,7 @@ export class IOSensor {
316
313
  .catch(async (e: any) => {
317
314
  this.apiError(e);
318
315
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}`
319
- + ` Connection, Error Message: ${superStringify(e.message)}`);
316
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
320
317
  await this.BLERefreshConnection(switchbot);
321
318
  });
322
319
  } else {
@@ -327,54 +324,26 @@ export class IOSensor {
327
324
  async openAPIRefreshStatus(): Promise<void> {
328
325
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
329
326
  try {
330
- const t = Date.now();
331
- const nonce = 'requestID';
332
- const data = this.platform.config.credentials?.token + t + nonce;
333
- const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
334
- const sign = signTerm.toString('base64');
335
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
336
- const options = {
337
- hostname: HostDomain,
338
- port: 443,
339
- path: `${DevicePath}/${this.device.deviceId}/status`,
340
- method: 'GET',
341
- headers: {
342
- Authorization: this.platform.config.credentials?.token,
343
- sign: sign,
344
- nonce: nonce,
345
- t: t,
346
- 'Content-Type': 'application/json',
347
- },
348
- };
349
- const req = https.request(options, (res) => {
350
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus statusCode: ${res.statusCode}`);
351
- let rawData = '';
352
- res.on('data', (d) => {
353
- rawData += d;
354
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
355
- });
356
- res.on('end', () => {
357
- try {
358
- this.deviceStatus = JSON.parse(rawData);
359
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus: ${superStringify(this.deviceStatus)}`);
360
- this.Humidity = this.deviceStatus.body.humidity!;
361
- this.Temperature = this.deviceStatus.body.temperature!;
362
- this.Battery = this.deviceStatus.body.battery!;
363
- this.parseStatus();
364
- this.updateHomeKitCharacteristics();
365
- } catch (e: any) {
366
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
367
- }
368
- });
369
- });
370
- req.on('error', (e: any) => {
371
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
327
+ const { body, statusCode, headers } = await request(`${Devices}/${this.device.deviceId}/status`, {
328
+ headers: this.platform.generateHeaders(),
372
329
  });
373
- req.end();
330
+ const deviceStatus = await body.json();
331
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Devices: ${JSON.stringify(deviceStatus.body)}`);
332
+ this.statusCode(statusCode);
333
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Headers: ${JSON.stringify(headers)}`);
334
+ this.debugLog(
335
+ `${this.device.deviceType}: ${this.accessory.displayName
336
+ } refreshStatus: ${JSON.stringify(deviceStatus)}`,
337
+ );
338
+ this.Humidity = deviceStatus.body.humidity!;
339
+ this.Temperature = deviceStatus.body.temperature!;
340
+ this.Battery = deviceStatus.body.battery!;
341
+ this.openAPIparseStatus();
342
+ this.updateHomeKitCharacteristics();
374
343
  } catch (e: any) {
375
344
  this.apiError(e);
376
345
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
377
- + ` Connection, Error Message: ${superStringify(e.message)}`);
346
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
378
347
  }
379
348
  }
380
349
 
@@ -391,7 +360,7 @@ export class IOSensor {
391
360
  this.accessory.context.CurrentRelativeHumidity = this.CurrentRelativeHumidity;
392
361
  this.humidityservice?.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, this.CurrentRelativeHumidity);
393
362
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
394
- + ` updateCharacteristic CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
363
+ + ` updateCharacteristic CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
395
364
  if (this.device.mqttURL) {
396
365
  mqttmessage.push(`"humidity": ${this.CurrentRelativeHumidity}`);
397
366
  }
@@ -407,7 +376,7 @@ export class IOSensor {
407
376
  if (this.device.mqttURL) {
408
377
  mqttmessage.push(`"temperature": ${this.CurrentTemperature}`);
409
378
  }
410
- if (this.device.history){
379
+ if (this.device.history) {
411
380
  entry['temp'] = this.CurrentTemperature;
412
381
  }
413
382
  this.accessory.context.CurrentTemperature = this.CurrentTemperature;
@@ -457,7 +426,7 @@ export class IOSensor {
457
426
  ?.join(':');
458
427
  const options = this.device.mqttPubOptions || {};
459
428
  this.mqttClient?.publish(`homebridge-switchbot/meter/${mac}`, `${message}`, options);
460
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT message: ${message} options:${superStringify(options)}`);
429
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT message: ${message} options:${JSON.stringify(options)}`);
461
430
  }
462
431
 
463
432
  /*
@@ -514,7 +483,7 @@ export class IOSensor {
514
483
  });
515
484
  // Set an event handler
516
485
  switchbot.onadvertisement = (ad: any) => {
517
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${superStringify(ad, null, ' ')}`);
486
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${JSON.stringify(ad, null, ' ')}`);
518
487
  };
519
488
  await sleep(10000);
520
489
  // Stop to monitor
@@ -545,40 +514,41 @@ export class IOSensor {
545
514
  }
546
515
  }
547
516
 
548
- async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
549
- switch (res.statusCode) {
517
+ async statusCode(statusCode: number): Promise<void> {
518
+ switch (statusCode) {
550
519
  case 151:
551
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this device type.`);
520
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this deviceType, statusCode: ${statusCode}`);
552
521
  break;
553
522
  case 152:
554
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found.`);
523
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found, statusCode: ${statusCode}`);
555
524
  break;
556
525
  case 160:
557
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported.`);
526
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported, statusCode: ${statusCode}`);
558
527
  break;
559
528
  case 161:
560
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline.`);
561
- await this.offlineOff();
529
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline, statusCode: ${statusCode}`);
530
+ this.offlineOff();
562
531
  break;
563
532
  case 171:
564
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} is offline. Hub: ${this.device.hubDeviceId}`);
565
- await this.offlineOff();
533
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Hub Device is offline, statusCode: ${statusCode}. `
534
+ + `Hub: ${this.device.hubDeviceId}`);
535
+ this.offlineOff();
566
536
  break;
567
537
  case 190:
568
538
  this.errorLog(
569
539
  `${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
570
- ` Or command: ${superStringify(res)} format is invalid`,
540
+ ` Or command format is invalid, statusCode: ${statusCode}`,
571
541
  );
572
542
  break;
573
543
  case 100:
574
- if (this.platform.debugMode) {
575
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent.`);
576
- }
544
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent, statusCode: ${statusCode}`);
545
+ break;
546
+ case 200:
547
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Request successful, statusCode: ${statusCode}`);
577
548
  break;
578
549
  default:
579
- if (this.platform.debugMode) {
580
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode.`);
581
- }
550
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode: `
551
+ + `${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`);
582
552
  }
583
553
  }
584
554
 
@@ -603,7 +573,7 @@ export class IOSensor {
603
573
  FirmwareRevision(accessory: PlatformAccessory<Context>, device: device & devicesConfig): CharacteristicValue {
604
574
  let FirmwareRevision: string;
605
575
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
606
- + ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
576
+ + ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
607
577
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
608
578
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
609
579
  if (accessory.context.FirmwareRevision) {
@@ -674,7 +644,7 @@ export class IOSensor {
674
644
  config['scanDuration'] = device.scanDuration;
675
645
  }
676
646
  if (Object.entries(config).length !== 0) {
677
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${superStringify(config)}`);
647
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
678
648
  }
679
649
  }
680
650