@switchbot/homebridge-switchbot 2.0.0-beta.23 → 2.0.0-beta.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/platform.ts CHANGED
@@ -26,6 +26,8 @@ import superStringify from 'super-stringify';
26
26
  import { readFileSync, writeFileSync } from 'fs';
27
27
  import { API, DynamicPlatformPlugin, Logger, PlatformAccessory, Service, Characteristic } from 'homebridge';
28
28
  import { PLATFORM_NAME, PLUGIN_NAME, irdevice, device, SwitchBotPlatformConfig, devicesConfig, DevicePath, HostDomain } from './settings';
29
+ import { IncomingMessage } from 'http';
30
+ import { interval, take } from 'rxjs';
29
31
 
30
32
  /**
31
33
  * HomebridgePlatform
@@ -68,7 +70,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
68
70
  } catch (e: any) {
69
71
  this.errorLog(superStringify(e.message));
70
72
  if (this.platformLogging?.includes('debug')) {
71
- this.errorLog(superStringify(e));
73
+ this.errorLog(`Verify Config: ${e}`);
72
74
  }
73
75
  return;
74
76
  }
@@ -95,7 +97,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
95
97
  } catch (e: any) {
96
98
  this.errorLog('Failed to Discover Devices.', superStringify(e.message));
97
99
  if (this.platformLogging?.includes('debug')) {
98
- this.errorLog(superStringify(e));
100
+ this.errorLog(`Platform: ${e}`);
99
101
  }
100
102
  }
101
103
  });
@@ -221,6 +223,16 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
221
223
  }
222
224
  }
223
225
  }
226
+
227
+ // Re-Discover Devices
228
+ if (!this.config.options.discoverDevices) {
229
+ this.config.options.discoverDevices = false;
230
+ this.debugLog(`Rediscover Devices disabled, discoverDevices: ${this.config.options.discoverDevices}`);
231
+ }
232
+ if (!this.config.options.discoverDevicesInterval) {
233
+ this.config.options.discoverDevicesInterval = 86400;
234
+ this.debugLog(`Default Rediscover Devices Interval, discoverDevicesInterval: ${this.config.options.discoverDevicesInterval}`);
235
+ }
224
236
  }
225
237
 
226
238
  /**
@@ -276,7 +288,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
276
288
  writeFileSync(this.api.user.configPath(), JSON.stringify(currentConfig, null, 4));
277
289
  this.verifyConfig();
278
290
  } catch (e: any) {
279
- this.errorLog(e);
291
+ this.errorLog(`Update Token: ${e}`);
280
292
  }
281
293
  }
282
294
 
@@ -305,8 +317,9 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
305
317
  'Content-Type': 'application/json',
306
318
  },
307
319
  };
308
- const req = https.request(options, (res) => {
320
+ const req = https.request(options, async (res) => {
309
321
  this.debugLog(`statusCode: ${res.statusCode}`);
322
+ await this.statusCode({ res });
310
323
  this.debugLog(`headers: ${superStringify(res.headers)}`);
311
324
  let rawData = '';
312
325
  res.on('data', (d) => {
@@ -319,93 +332,113 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
319
332
  this.debugLog(`devicesAPI: ${superStringify(devicesAPI.body)}`);
320
333
 
321
334
  // SwitchBot Devices
322
- if (devicesAPI.body.deviceList.length !== 0) {
335
+ /*if (devicesAPI.body.deviceList.length !== 0) {
323
336
  this.infoLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
324
337
  } else {
325
338
  this.debugLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
326
- }
327
- const deviceLists = devicesAPI.body.deviceList;
328
- if (!this.config.options?.devices) {
329
- this.debugLog(`SwitchBot Device Config Not Set: ${superStringify(this.config.options?.devices)}`);
330
- const devices = deviceLists.map((v: any) => v);
331
- for (const device of devices) {
332
- if (device.deviceType) {
333
- if (device.configDeviceName) {
334
- device.deviceName = device.configDeviceName;
339
+ }*/
340
+ const deviceBodyList = devicesAPI.body.deviceList;
341
+ let deviceLists: any[];
342
+ if (deviceBodyList) {
343
+ if (deviceBodyList.length > 1) {
344
+ deviceLists = deviceBodyList;
345
+ this.infoLog(`Total SwitchBot Devices Found: ${deviceLists.length}`);
346
+ } else {
347
+ deviceLists = [deviceBodyList];
348
+ this.infoLog(`Total SwitchBot Devices Found: ${deviceLists.length}`);
349
+ }
350
+ if (!this.config.options?.devices) {
351
+ this.debugLog(`SwitchBot Device Config Not Set: ${superStringify(this.config.options?.devices)}`);
352
+ const devices = deviceLists.map((v: any) => v);
353
+ for (const device of devices) {
354
+ if (device.deviceType) {
355
+ if (device.configDeviceName) {
356
+ device.deviceName = device.configDeviceName;
357
+ }
358
+ this.createDevice(device);
335
359
  }
336
- this.createDevice(device);
337
360
  }
338
- }
339
- } else if (this.config.credentials?.token && this.config.options.devices) {
340
- this.debugLog(`SwitchBot Device Config Set: ${superStringify(this.config.options?.devices)}`);
341
- const deviceConfigs = this.config.options?.devices;
342
-
343
- const mergeBydeviceId = (a1: { deviceId: string }[], a2: any[]) =>
344
- a1.map((itm: { deviceId: string }) => ({
345
- ...a2.find(
346
- (item: { deviceId: string }) =>
347
- item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item,
348
- ),
349
- ...itm,
350
- }));
351
-
352
- const devices = mergeBydeviceId(deviceLists, deviceConfigs);
353
- this.debugLog(`SwitchBot Devices: ${superStringify(devices)}`);
354
- for (const device of devices) {
355
- if (device.deviceType) {
356
- if (device.configDeviceName) {
357
- device.deviceName = device.configDeviceName;
361
+ } else if (this.config.credentials?.token && this.config.options.devices) {
362
+ this.debugLog(`SwitchBot Device Config Set: ${superStringify(this.config.options?.devices)}`);
363
+ const deviceConfigs = this.config.options?.devices;
364
+
365
+ const mergeBydeviceId = (a1: { deviceId: string }[], a2: any[]) =>
366
+ a1.map((itm: { deviceId: string }) => ({
367
+ ...a2.find(
368
+ (item: { deviceId: string }) =>
369
+ item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item,
370
+ ),
371
+ ...itm,
372
+ }));
373
+
374
+ const devices = mergeBydeviceId(deviceLists, deviceConfigs);
375
+ this.debugLog(`SwitchBot Devices: ${superStringify(devices)}`);
376
+ for (const device of devices) {
377
+ if (device.deviceType) {
378
+ if (device.configDeviceName) {
379
+ device.deviceName = device.configDeviceName;
380
+ }
381
+ this.createDevice(device);
358
382
  }
359
- this.createDevice(device);
360
383
  }
384
+ } else {
385
+ this.errorLog('SwitchBot Token Supplied, Issue with Auth.');
361
386
  }
362
- } else {
363
- this.errorLog('SwitchBot Token Supplied, Issue with Auth.');
364
387
  }
365
-
366
388
  // IR Devices
367
- if (devicesAPI.body.infraredRemoteList.length !== 0) {
389
+ /*if (devicesAPI.body.infraredRemoteList.length !== 0) {
368
390
  this.infoLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
369
391
  } else {
370
392
  this.debugLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
371
- }
372
- const irDeviceLists = devicesAPI.body.infraredRemoteList;
373
- if (!this.config.options?.irdevices) {
374
- this.debugLog(`IR Device Config Not Set: ${superStringify(this.config.options?.irdevices)}`);
375
- const devices = irDeviceLists.map((v: any) => v);
376
- for (const device of devices) {
377
- if (device.remoteType) {
378
- this.createIRDevice(device);
379
- }
393
+ }*/
394
+ const irDeviceBodyList = devicesAPI.body.infraredRemoteList;
395
+ let irDeviceLists: any[];
396
+
397
+ if (irDeviceBodyList) {
398
+ if (irDeviceBodyList.length > 1) {
399
+ irDeviceLists = irDeviceBodyList;
400
+ this.infoLog(`Total IR Devices Found: ${irDeviceLists.length}`);
401
+ } else {
402
+ irDeviceLists = [irDeviceBodyList];
403
+ this.infoLog(`Total IR Devices Found: ${irDeviceLists.length}`);
380
404
  }
381
- } else {
382
- this.debugLog(`IR Device Config Set: ${superStringify(this.config.options?.irdevices)}`);
383
- const irDeviceConfig = this.config.options?.irdevices;
384
-
385
- const mergeIRBydeviceId = (a1: { deviceId: string }[], a2: any[]) =>
386
- a1.map((itm: { deviceId: string }) => ({
387
- ...a2.find(
388
- (item: { deviceId: string }) =>
389
- item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item,
390
- ),
391
- ...itm,
392
- }));
393
-
394
- const devices = mergeIRBydeviceId(irDeviceLists, irDeviceConfig);
395
- this.debugLog(`IR Devices: ${superStringify(devices)}`);
396
- for (const device of devices) {
397
- if (device.remoteType) {
398
- this.createIRDevice(device);
405
+ if (!this.config.options?.irdevices) {
406
+ this.debugLog(`IR Device Config Not Set: ${superStringify(this.config.options?.irdevices)}`);
407
+ const devices = irDeviceLists.map((v: any) => v);
408
+ for (const device of devices) {
409
+ if (device.remoteType) {
410
+ this.createIRDevice(device);
411
+ }
412
+ }
413
+ } else {
414
+ this.debugLog(`IR Device Config Set: ${superStringify(this.config.options?.irdevices)}`);
415
+ const irDeviceConfig = this.config.options?.irdevices;
416
+
417
+ const mergeIRBydeviceId = (a1: { deviceId: string }[], a2: any[]) =>
418
+ a1.map((itm: { deviceId: string }) => ({
419
+ ...a2.find(
420
+ (item: { deviceId: string }) =>
421
+ item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item,
422
+ ),
423
+ ...itm,
424
+ }));
425
+
426
+ const devices = mergeIRBydeviceId(irDeviceLists, irDeviceConfig);
427
+ this.debugLog(`IR Devices: ${superStringify(devices)}`);
428
+ for (const device of devices) {
429
+ if (device.remoteType) {
430
+ this.createIRDevice(device);
431
+ }
399
432
  }
400
433
  }
401
434
  }
402
435
  } catch (e:any) {
403
- this.errorLog(e.message);
436
+ this.errorLog(`API Request: ${e}`);
404
437
  }
405
438
  });
406
439
  });
407
- req.on('error', (error) => {
408
- this.errorLog(error);
440
+ req.on('error', (e: any) => {
441
+ this.errorLog(`req: ${e}`);
409
442
  });
410
443
  req.end();
411
444
  } else if (!this.config.credentials?.token && this.config.options?.devices) {
@@ -423,7 +456,14 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
423
456
  this.errorLog('Neither SwitchBot Token or Device Config are not set.');
424
457
  }
425
458
  } catch (e: any) {
426
- this.deviceError(e);
459
+ this.deviceError(`Discover Devices: ${e}`);
460
+ }
461
+ if (this.config.options?.discoverDevices) {
462
+ interval(this.config.options!.discoverDevicesInterval * 1000)
463
+ .pipe(take(1))
464
+ .subscribe(async () => {
465
+ await this.discoverDevices();
466
+ });
427
467
  }
428
468
  }
429
469
 
@@ -465,7 +505,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
465
505
  this.errorLog(`Failed to Discover Devices, Error Message: ${superStringify(e.message)}`);
466
506
  }
467
507
  if (this.platformLogging === 'debugMode') {
468
- this.errorLog(`Failed to Discover Devices, Error: ${superStringify(e)}`);
508
+ this.errorLog(`Failed to Discover Devices, Error: ${e}`);
469
509
  }
470
510
  }
471
511
 
@@ -524,7 +564,6 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
524
564
  this.createStripLight(device);
525
565
  break;
526
566
  case 'Indoor Cam':
527
- this.deviceInfo(device);
528
567
  this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
529
568
  this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported.`);
530
569
  break;
@@ -532,7 +571,6 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
532
571
  this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId} is Not Supported.`);
533
572
  break;
534
573
  default:
535
- this.deviceInfo(device);
536
574
  this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported.`);
537
575
  this.warnLog('Submit Feature Requests Here: https://git.io/JL14Z');
538
576
  }
@@ -595,7 +633,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
595
633
  this.createOthers(device);
596
634
  break;
597
635
  default:
598
- this.deviceInfo(device);
636
+ this.debugLog(`Unsupported Device: ${superStringify(device)}`);
599
637
  this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.remoteType}, is currently not supported.`);
600
638
  this.warnLog('Submit Feature Requests Here: https://git.io/JL14Z');
601
639
  }
@@ -1775,47 +1813,35 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1775
1813
  }
1776
1814
  }
1777
1815
 
1778
- public async deviceInfo(device: (irdevice & devicesConfig) | (device & devicesConfig)) {
1779
- if (this.platformLogging?.includes('debug')) {
1780
- this.warnLog(superStringify(device));
1781
-
1782
- const t = Date.now();
1783
- const nonce = 'requestID';
1784
- const data = this.config.credentials?.token + t + nonce;
1785
- const signTerm = crypto.createHmac('sha256', this.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
1786
- const sign = signTerm.toString('base64');
1787
- this.debugLog(sign);
1788
- const options = {
1789
- hostname: HostDomain,
1790
- port: 443,
1791
- path: `${DevicePath}/${device.deviceId}/status`,
1792
- method: 'GET',
1793
- headers: {
1794
- Authorization: this.config.credentials?.token,
1795
- sign: sign,
1796
- nonce: nonce,
1797
- t: t,
1798
- 'Content-Type': 'application/json',
1799
- },
1800
- };
1801
- const req = https.request(options, (res) => {
1802
- this.debugLog(`statusCode: ${res.statusCode}`);
1803
- res.on('data', (d) => {
1804
- process.stdout.write(d);
1805
- });
1806
- });
1807
- req.on('error', (error) => {
1808
- this.errorLog(error);
1809
- });
1810
- req.end();
1811
-
1812
- this.deviceStatus = req;
1813
- if (this.deviceStatus.message === 'success') {
1814
- this.warnLog(`${device.deviceName} deviceInfoStatus: ${superStringify(this.deviceStatus)}`);
1815
- } else {
1816
- this.warnLog(`${device.deviceName} deviceInfoStatus: ${superStringify(this.deviceStatus.message)}`);
1817
- this.warnLog('Unable to retreive deviceInfoStatus.');
1818
- }
1816
+ async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
1817
+ switch (res.statusCode) {
1818
+ case 151:
1819
+ this.errorLog('Command not supported by this device type.');
1820
+ break;
1821
+ case 152:
1822
+ this.errorLog('Device not found.');
1823
+ break;
1824
+ case 160:
1825
+ this.errorLog('Command is not supported.');
1826
+ break;
1827
+ case 161:
1828
+ this.errorLog('Device is offline.');
1829
+ break;
1830
+ case 171:
1831
+ this.errorLog('is offline');
1832
+ break;
1833
+ case 190:
1834
+ this.errorLog('Requests reached the daily limit');
1835
+ break;
1836
+ case 100:
1837
+ if (this.debugMode) {
1838
+ this.debugLog('Command successfully sent.');
1839
+ }
1840
+ break;
1841
+ default:
1842
+ if (this.debugMode) {
1843
+ this.debugLog('Unknown statusCode.');
1844
+ }
1819
1845
  }
1820
1846
  }
1821
1847
 
@@ -1826,7 +1852,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1826
1852
  try {
1827
1853
  Switchbot = require('node-switchbot');
1828
1854
  switchbot = new Switchbot();
1829
- } catch (e) {
1855
+ } catch (e: any) {
1830
1856
  switchbot = false;
1831
1857
  this.errorLog(`Was 'node-switchbot' found: ${switchbot}`);
1832
1858
  }
package/src/settings.ts CHANGED
@@ -36,6 +36,8 @@ export type options = {
36
36
  refreshRate?: number;
37
37
  pushRate?: number;
38
38
  logging?: string;
39
+ discoverDevices: boolean;
40
+ discoverDevicesInterval: number;
39
41
  devices?: Array<devicesConfig>;
40
42
  irdevices?: Array<irDevicesConfig>;
41
43
  };