@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,14 +1,11 @@
1
- import https from 'https';
2
- import crypto from 'crypto';
3
1
  import { Context } from 'vm';
4
- import { IncomingMessage } from 'http';
2
+ import { request } from 'undici';
3
+ import { sleep } from '../utils';
5
4
  import { interval, Subject } from 'rxjs';
6
- import superStringify from 'super-stringify';
7
5
  import { SwitchBotPlatform } from '../platform';
8
6
  import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
9
7
  import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
10
- import { device, devicesConfig, deviceStatus, HostDomain, DevicePath, switchbot, ad, serviceData } from '../settings';
11
- import { sleep } from '../utils';
8
+ import { device, devicesConfig, deviceStatus, switchbot, ad, serviceData, Devices } from '../settings';
12
9
 
13
10
  export class Lock {
14
11
  // Services
@@ -144,7 +141,7 @@ export class Lock {
144
141
  } catch (e: any) {
145
142
  this.apiError(e);
146
143
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with ${this.device.connectionType} Connection,`
147
- + ` Error Message: ${superStringify(e.message)}`);
144
+ + ` Error Message: ${JSON.stringify(e.message)}`);
148
145
  }
149
146
  this.lockUpdateInProgress = false;
150
147
  });
@@ -163,7 +160,7 @@ export class Lock {
163
160
  } else {
164
161
  await this.offlineOff();
165
162
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
166
- + ` ${this.device.connectionType}, parseStatus will not happen.`);
163
+ + ` ${this.device.connectionType}, parseStatus will not happen.`);
167
164
  }
168
165
  }
169
166
 
@@ -222,7 +219,7 @@ export class Lock {
222
219
  } else {
223
220
  await this.offlineOff();
224
221
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
225
- + ` ${this.device.connectionType}, refreshStatus will not happen.`);
222
+ + ` ${this.device.connectionType}, refreshStatus will not happen.`);
226
223
  }
227
224
  }
228
225
 
@@ -248,7 +245,7 @@ export class Lock {
248
245
  switchbot.onadvertisement = async (ad: any) => {
249
246
  this.address = ad.address;
250
247
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac},`
251
- + ` BLE Address Found: ${this.address}`);
248
+ + ` BLE Address Found: ${this.address}`);
252
249
  this.serviceData = ad.serviceData;
253
250
  this.battery = ad.serviceData.battery;
254
251
  this.calibration = ad.serviceData.calibration;
@@ -259,11 +256,11 @@ export class Lock {
259
256
  this.unclosed_alarm = ad.serviceData.unclosed_alarm;
260
257
  this.unlocked_alarm = ad.serviceData.unlocked_alarm;
261
258
  this.auto_lock_paused = ad.serviceData.auto_lock_paused;
262
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${superStringify(ad.serviceData)}`);
259
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
263
260
  this.debugLog(
264
261
  `${this.device.deviceType}: ${this.accessory.displayName} battery: ${ad.serviceData.battery}, ` +
265
- `calibration: ${ad.serviceData.calibration}, status: ${ad.serviceData.status}, battery: ${ad.serviceData.battery}, ` +
266
- `door_open: ${ad.serviceData.door_open}`);
262
+ `calibration: ${ad.serviceData.calibration}, status: ${ad.serviceData.status}, battery: ${ad.serviceData.battery}, ` +
263
+ `door_open: ${ad.serviceData.door_open}`);
267
264
 
268
265
  if (this.serviceData) {
269
266
  this.connected = true;
@@ -284,7 +281,7 @@ export class Lock {
284
281
  .catch(async (e: any) => {
285
282
  this.apiError(e);
286
283
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}`
287
- + ` Connection, Error Message: ${superStringify(e.message)}`);
284
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
288
285
  await this.BLERefreshConnection(switchbot);
289
286
  });
290
287
  } else {
@@ -295,53 +292,25 @@ export class Lock {
295
292
  async openAPIRefreshStatus(): Promise<void> {
296
293
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
297
294
  try {
298
- const t = Date.now();
299
- const nonce = 'requestID';
300
- const data = this.platform.config.credentials?.token + t + nonce;
301
- const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
302
- const sign = signTerm.toString('base64');
303
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
304
- const options = {
305
- hostname: HostDomain,
306
- port: 443,
307
- path: `${DevicePath}/${this.device.deviceId}/status`,
308
- method: 'GET',
309
- headers: {
310
- Authorization: this.platform.config.credentials?.token,
311
- sign: sign,
312
- nonce: nonce,
313
- t: t,
314
- 'Content-Type': 'application/json',
315
- },
316
- };
317
- const req = https.request(options, (res) => {
318
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus statusCode: ${res.statusCode}`);
319
- let rawData = '';
320
- res.on('data', (d) => {
321
- rawData += d;
322
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
323
- });
324
- res.on('end', () => {
325
- try {
326
- this.deviceStatus = JSON.parse(rawData);
327
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus: ${superStringify(this.deviceStatus)}`);
328
- this.lockState = this.deviceStatus.body.lockState;
329
- this.doorState = this.deviceStatus.body.doorState;
330
- this.openAPIparseStatus();
331
- this.updateHomeKitCharacteristics();
332
- } catch (e: any) {
333
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
334
- }
335
- });
336
- });
337
- req.on('error', (e: any) => {
338
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
295
+ const { body, statusCode, headers } = await request(`${Devices}/${this.device.deviceId}/status`, {
296
+ headers: this.platform.generateHeaders(),
339
297
  });
340
- req.end();
298
+ const deviceStatus = await body.json();
299
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Devices: ${JSON.stringify(deviceStatus.body)}`);
300
+ this.statusCode(statusCode);
301
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Headers: ${JSON.stringify(headers)}`);
302
+ this.debugLog(
303
+ `${this.device.deviceType}: ${this.accessory.displayName
304
+ } refreshStatus: ${JSON.stringify(deviceStatus)}`,
305
+ );
306
+ this.lockState = deviceStatus.body.lockState;
307
+ this.doorState = deviceStatus.body.doorState;
308
+ this.openAPIparseStatus();
309
+ this.updateHomeKitCharacteristics();
341
310
  } catch (e: any) {
342
311
  this.apiError(e);
343
312
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
344
- + ` Connection, Error Message: ${superStringify(e.message)}`);
313
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
345
314
  }
346
315
  }
347
316
 
@@ -361,7 +330,7 @@ export class Lock {
361
330
  } else {
362
331
  await this.offlineOff();
363
332
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
364
- + ` ${this.device.connectionType}, pushChanges will not happen.`);
333
+ + ` ${this.device.connectionType}, pushChanges will not happen.`);
365
334
  }
366
335
  // Refresh the status from the API
367
336
  interval(15000)
@@ -376,7 +345,7 @@ export class Lock {
376
345
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
377
346
  if (this.LockTargetState !== this.accessory.context.LockTargetState) {
378
347
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges LockTargetState: ${this.LockTargetState}`
379
- + ` LockTargetStateCached: ${this.accessory.context.LockTargetState}`);
348
+ + ` LockTargetStateCached: ${this.accessory.context.LockTargetState}`);
380
349
  const switchbot = await this.platform.connectBLE();
381
350
  // Convert to BLE Address
382
351
  this.device.bleMac = this.device
@@ -396,80 +365,50 @@ export class Lock {
396
365
  .catch(async (e: any) => {
397
366
  this.apiError(e);
398
367
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
399
- + ` Connection, Error Message: ${superStringify(e.message)}`);
368
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
400
369
  await this.BLEPushConnection();
401
370
  });
402
371
  } else {
403
372
  this.debugLog(
404
373
  `${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges.` + `LockTargetState: ${this.LockTargetState}, `
405
- +`LockTargetStateCached: ${this.accessory.context.LockTargetState}`,
374
+ + `LockTargetStateCached: ${this.accessory.context.LockTargetState}`,
406
375
  );
407
376
  }
408
377
  }
409
378
 
410
379
  async openAPIpushChanges(): Promise<void> {
411
- try {
412
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
413
- if (this.LockTargetState !== this.accessory.context.LockTargetState) {
414
- // Make Push On request to the API
415
- const t = Date.now();
416
- const nonce = 'requestID';
417
- const data = this.platform.config.credentials?.token + t + nonce;
418
- const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
419
- .update(Buffer.from(data, 'utf-8'))
420
- .digest();
421
- const sign = signTerm.toString('base64');
422
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
423
- let command = '';
424
- if (this.LockTargetState) {
425
- command = 'lock';
426
- } else {
427
- command = 'unlock';
428
- }
429
- const body = superStringify({
430
- 'command': `${command}`,
431
- 'parameter': 'default',
432
- 'commandType': 'command',
433
- });
434
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${body},`);
435
- const options = {
436
- hostname: HostDomain,
437
- port: 443,
438
- path: `${DevicePath}/${this.device.deviceId}/commands`,
380
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
381
+ if (this.LockTargetState !== this.accessory.context.LockTargetState) {
382
+ let command = '';
383
+ if (this.LockTargetState) {
384
+ command = 'lock';
385
+ } else {
386
+ command = 'unlock';
387
+ }
388
+ const body = JSON.stringify({
389
+ 'command': `${command}`,
390
+ 'parameter': 'default',
391
+ 'commandType': 'command',
392
+ });
393
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${body},`);
394
+ try {
395
+ const { body, statusCode, headers } = await request(`${Devices}/${this.device.deviceId}/commands`, {
439
396
  method: 'POST',
440
- headers: {
441
- 'Authorization': this.platform.config.credentials?.token,
442
- 'sign': sign,
443
- 'nonce': nonce,
444
- 't': t,
445
- 'Content-Type': 'application/json',
446
- 'Content-Length': body.length,
447
- },
448
- };
449
- const req = https.request(options, res => {
450
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges statusCode: ${res.statusCode}`);
451
- this.statusCode({ res });
452
- res.on('data', d => {
453
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
454
- });
455
- });
456
- req.on('error', (e: any) => {
457
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
397
+ headers: this.platform.generateHeaders(),
458
398
  });
459
- req.write(body);
460
- req.end();
461
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges: ${superStringify(req)}`);
462
- } else {
463
- this.debugLog(
464
- `${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges.` + `LockTargetState: ${this.LockTargetState}, `
465
- +`LockTargetStateCached: ${this.accessory.context.LockTargetState}`,
399
+ const deviceStatus = await body.json();
400
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Devices: ${JSON.stringify(deviceStatus.body)}`);
401
+ this.statusCode(statusCode);
402
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Headers: ${JSON.stringify(headers)}`);
403
+ } catch (e: any) {
404
+ this.apiError(e);
405
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
406
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`,
466
407
  );
467
408
  }
468
- } catch (e: any) {
469
- this.apiError(e);
470
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
471
- + ` Connection, Error Message: ${superStringify(e.message)}`,
472
- );
409
+ } else {
410
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges.` + `LockTargetState: ${this.LockTargetState}, `
411
+ + `LockTargetStateCached: ${this.accessory.context.LockTargetState}`);
473
412
  }
474
413
  }
475
414
 
@@ -532,7 +471,7 @@ export class Lock {
532
471
  });
533
472
  // Set an event handler
534
473
  switchbot.onadvertisement = (ad: any) => {
535
- this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${superStringify(ad, null, ' ')}`);
474
+ this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${JSON.stringify(ad, null, ' ')}`);
536
475
  };
537
476
  await sleep(10000);
538
477
  // Stop to monitor
@@ -570,36 +509,41 @@ export class Lock {
570
509
  }
571
510
  }
572
511
 
573
- async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
574
- switch (res.statusCode) {
512
+ async statusCode(statusCode: number): Promise<void> {
513
+ switch (statusCode) {
575
514
  case 151:
576
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this device type.`);
515
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this deviceType, statusCode: ${statusCode}`);
577
516
  break;
578
517
  case 152:
579
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found.`);
518
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found, statusCode: ${statusCode}`);
580
519
  break;
581
520
  case 160:
582
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported.`);
521
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported, statusCode: ${statusCode}`);
583
522
  break;
584
523
  case 161:
585
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline.`);
586
- await this.offlineOff();
524
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline, statusCode: ${statusCode}`);
525
+ this.offlineOff();
587
526
  break;
588
527
  case 171:
589
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
590
- await this.offlineOff();
528
+ this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Hub Device is offline, statusCode: ${statusCode}. `
529
+ + `Hub: ${this.device.hubDeviceId}`);
530
+ this.offlineOff();
591
531
  break;
592
532
  case 190:
593
533
  this.errorLog(
594
534
  `${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
595
- ` Or command: ${superStringify(res)} format is invalid`,
535
+ ` Or command format is invalid, statusCode: ${statusCode}`,
596
536
  );
597
537
  break;
598
538
  case 100:
599
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent.`);
539
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent, statusCode: ${statusCode}`);
540
+ break;
541
+ case 200:
542
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Request successful, statusCode: ${statusCode}`);
600
543
  break;
601
544
  default:
602
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode.`);
545
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode: `
546
+ + `${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`);
603
547
  }
604
548
  }
605
549
 
@@ -621,7 +565,7 @@ export class Lock {
621
565
  FirmwareRevision(accessory: PlatformAccessory<Context>, device: device & devicesConfig): CharacteristicValue {
622
566
  let FirmwareRevision: string;
623
567
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
624
- + ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
568
+ + ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
625
569
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
626
570
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
627
571
  if (accessory.context.FirmwareRevision) {
@@ -673,7 +617,7 @@ export class Lock {
673
617
  config['scanDuration'] = device.scanDuration;
674
618
  }
675
619
  if (Object.entries(config).length !== 0) {
676
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${superStringify(config)}`);
620
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
677
621
  }
678
622
  }
679
623
 
@@ -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
- import { connectAsync } from 'async-mqtt';
7
6
  import { interval, Subject } from 'rxjs';
7
+ import { connectAsync } from 'async-mqtt';
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
@@ -194,7 +191,7 @@ export class Meter {
194
191
  } else {
195
192
  await this.offlineOff();
196
193
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
197
- + ` ${this.device.connectionType}, parseStatus will not happen.`);
194
+ + ` ${this.device.connectionType}, parseStatus will not happen.`);
198
195
  }
199
196
  }
200
197
 
@@ -252,7 +249,7 @@ export class Meter {
252
249
  } else {
253
250
  await this.offlineOff();
254
251
  this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
255
- + ` ${this.device.connectionType}, refreshStatus will not happen.`);
252
+ + ` ${this.device.connectionType}, refreshStatus will not happen.`);
256
253
  }
257
254
  }
258
255
 
@@ -278,7 +275,7 @@ export class Meter {
278
275
  switchbot.onadvertisement = async (ad: ad) => {
279
276
  this.address = ad.address;
280
277
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac},`
281
- + ` BLE Address Found: ${this.address}`);
278
+ + ` BLE Address Found: ${this.address}`);
282
279
  if (ad.serviceData.humidity! > 0) {
283
280
  // reject unreliable data
284
281
  this.humidity = ad.serviceData.humidity;
@@ -288,11 +285,11 @@ export class Meter {
288
285
  this.celsius = ad.serviceData.temperature!.c;
289
286
  this.fahrenheit = ad.serviceData.temperature!.f;
290
287
  this.battery = ad.serviceData.battery;
291
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${superStringify(ad.serviceData)}`);
288
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
292
289
  this.debugLog(
293
290
  `${this.device.deviceType}: ${this.accessory.displayName} model: ${ad.serviceData.model}, modelName: ${ad.serviceData.modelName}, ` +
294
- `temperature: ${superStringify(ad.serviceData.temperature?.c)}, humidity: ${ad.serviceData.humidity}, ` +
295
- `battery: ${ad.serviceData.battery}`,
291
+ `temperature: ${JSON.stringify(ad.serviceData.temperature?.c)}, humidity: ${ad.serviceData.humidity}, ` +
292
+ `battery: ${ad.serviceData.battery}`,
296
293
  );
297
294
 
298
295
  if (this.serviceData) {
@@ -314,7 +311,7 @@ export class Meter {
314
311
  .catch(async (e: any) => {
315
312
  this.apiError(e);
316
313
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}`
317
- + ` Connection, Error Message: ${superStringify(e.message)}`);
314
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
318
315
  await this.BLERefreshConnection(switchbot);
319
316
  });
320
317
  } else {
@@ -325,53 +322,25 @@ export class Meter {
325
322
  async openAPIRefreshStatus(): Promise<void> {
326
323
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
327
324
  try {
328
- const t = Date.now();
329
- const nonce = 'requestID';
330
- const data = this.platform.config.credentials?.token + t + nonce;
331
- const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
332
- const sign = signTerm.toString('base64');
333
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
334
- const options = {
335
- hostname: HostDomain,
336
- port: 443,
337
- path: `${DevicePath}/${this.device.deviceId}/status`,
338
- method: 'GET',
339
- headers: {
340
- Authorization: this.platform.config.credentials?.token,
341
- sign: sign,
342
- nonce: nonce,
343
- t: t,
344
- 'Content-Type': 'application/json',
345
- },
346
- };
347
- const req = https.request(options, (res) => {
348
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus statusCode: ${res.statusCode}`);
349
- let rawData = '';
350
- res.on('data', (d) => {
351
- rawData += d;
352
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
353
- });
354
- res.on('end', () => {
355
- try {
356
- this.deviceStatus = JSON.parse(rawData);
357
- this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus: ${superStringify(this.deviceStatus)}`);
358
- this.Humidity = this.deviceStatus.body.humidity!;
359
- this.Temperature = this.deviceStatus.body.temperature!;
360
- this.openAPIparseStatus();
361
- this.updateHomeKitCharacteristics();
362
- } catch (e: any) {
363
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
364
- }
365
- });
366
- });
367
- req.on('error', (e: any) => {
368
- this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
325
+ const { body, statusCode, headers } = await request(`${Devices}/${this.device.deviceId}/status`, {
326
+ headers: this.platform.generateHeaders(),
369
327
  });
370
- req.end();
328
+ const deviceStatus = await body.json();
329
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Devices: ${JSON.stringify(deviceStatus.body)}`);
330
+ this.statusCode(statusCode);
331
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Headers: ${JSON.stringify(headers)}`);
332
+ this.debugLog(
333
+ `${this.device.deviceType}: ${this.accessory.displayName
334
+ } refreshStatus: ${JSON.stringify(deviceStatus)}`,
335
+ );
336
+ this.Humidity = deviceStatus.body.humidity!;
337
+ this.Temperature = deviceStatus.body.temperature!;
338
+ this.openAPIparseStatus();
339
+ this.updateHomeKitCharacteristics();
371
340
  } catch (e: any) {
372
341
  this.apiError(e);
373
342
  this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
374
- + ` Connection, Error Message: ${superStringify(e.message)}`);
343
+ + ` Connection, Error Message: ${JSON.stringify(e.message)}`);
375
344
  }
376
345
  }
377
346
 
@@ -388,7 +357,7 @@ export class Meter {
388
357
  this.accessory.context.CurrentRelativeHumidity = this.CurrentRelativeHumidity;
389
358
  this.humidityservice?.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, this.CurrentRelativeHumidity);
390
359
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
391
- + ` CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
360
+ + ` CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
392
361
  if (this.device.mqttURL) {
393
362
  mqttmessage.push(`"humidity": ${this.CurrentRelativeHumidity}`);
394
363
  }
@@ -457,7 +426,7 @@ export class Meter {
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 Meter {
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 Meter {
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
 
@@ -605,7 +575,7 @@ export class Meter {
605
575
  FirmwareRevision(accessory: PlatformAccessory<Context>, device: device & devicesConfig): CharacteristicValue {
606
576
  let FirmwareRevision: string;
607
577
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
608
- + ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
578
+ + ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
609
579
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
610
580
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
611
581
  if (accessory.context.FirmwareRevision) {
@@ -678,7 +648,7 @@ export class Meter {
678
648
  config['scanDuration'] = device.scanDuration;
679
649
  }
680
650
  if (Object.entries(config).length !== 0) {
681
- this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${superStringify(config)}`);
651
+ this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
682
652
  }
683
653
  }
684
654