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

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,112 @@ 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
+ if (irDeviceBodyList) {
397
+ if (irDeviceBodyList.length > 1) {
398
+ irDeviceLists = irDeviceBodyList;
399
+ this.infoLog(`Total IR Devices Found: ${irDeviceLists.length}`);
400
+ } else {
401
+ irDeviceLists = [irDeviceBodyList];
402
+ this.infoLog(`Total IR Devices Found: ${irDeviceLists.length}`);
380
403
  }
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);
404
+ if (!this.config.options?.irdevices) {
405
+ this.debugLog(`IR Device Config Not Set: ${superStringify(this.config.options?.irdevices)}`);
406
+ const devices = irDeviceLists.map((v: any) => v);
407
+ for (const device of devices) {
408
+ if (device.remoteType) {
409
+ this.createIRDevice(device);
410
+ }
411
+ }
412
+ } else {
413
+ this.debugLog(`IR Device Config Set: ${superStringify(this.config.options?.irdevices)}`);
414
+ const irDeviceConfig = this.config.options?.irdevices;
415
+
416
+ const mergeIRBydeviceId = (a1: { deviceId: string }[], a2: any[]) =>
417
+ a1.map((itm: { deviceId: string }) => ({
418
+ ...a2.find(
419
+ (item: { deviceId: string }) =>
420
+ item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item,
421
+ ),
422
+ ...itm,
423
+ }));
424
+
425
+ const devices = mergeIRBydeviceId(irDeviceLists, irDeviceConfig);
426
+ this.debugLog(`IR Devices: ${superStringify(devices)}`);
427
+ for (const device of devices) {
428
+ if (device.remoteType) {
429
+ this.createIRDevice(device);
430
+ }
399
431
  }
400
432
  }
401
433
  }
402
434
  } catch (e:any) {
403
- this.errorLog(e.message);
435
+ this.errorLog(`API Request: ${e}`);
404
436
  }
405
437
  });
406
438
  });
407
- req.on('error', (error) => {
408
- this.errorLog(error);
439
+ req.on('error', (e: any) => {
440
+ this.errorLog(`req: ${e}`);
409
441
  });
410
442
  req.end();
411
443
  } else if (!this.config.credentials?.token && this.config.options?.devices) {
@@ -423,7 +455,14 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
423
455
  this.errorLog('Neither SwitchBot Token or Device Config are not set.');
424
456
  }
425
457
  } catch (e: any) {
426
- this.deviceError(e);
458
+ this.deviceError(`Discover Devices: ${e}`);
459
+ }
460
+ if (this.config.options?.discoverDevices) {
461
+ interval(this.config.options!.discoverDevicesInterval * 1000)
462
+ .pipe(take(1))
463
+ .subscribe(async () => {
464
+ await this.discoverDevices();
465
+ });
427
466
  }
428
467
  }
429
468
 
@@ -465,7 +504,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
465
504
  this.errorLog(`Failed to Discover Devices, Error Message: ${superStringify(e.message)}`);
466
505
  }
467
506
  if (this.platformLogging === 'debugMode') {
468
- this.errorLog(`Failed to Discover Devices, Error: ${superStringify(e)}`);
507
+ this.errorLog(`Failed to Discover Devices, Error: ${e}`);
469
508
  }
470
509
  }
471
510
 
@@ -524,7 +563,6 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
524
563
  this.createStripLight(device);
525
564
  break;
526
565
  case 'Indoor Cam':
527
- this.deviceInfo(device);
528
566
  this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
529
567
  this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported.`);
530
568
  break;
@@ -532,7 +570,6 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
532
570
  this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId} is Not Supported.`);
533
571
  break;
534
572
  default:
535
- this.deviceInfo(device);
536
573
  this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported.`);
537
574
  this.warnLog('Submit Feature Requests Here: https://git.io/JL14Z');
538
575
  }
@@ -595,7 +632,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
595
632
  this.createOthers(device);
596
633
  break;
597
634
  default:
598
- this.deviceInfo(device);
635
+ this.debugLog(`Unsupported Device: ${superStringify(device)}`);
599
636
  this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.remoteType}, is currently not supported.`);
600
637
  this.warnLog('Submit Feature Requests Here: https://git.io/JL14Z');
601
638
  }
@@ -1775,47 +1812,35 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1775
1812
  }
1776
1813
  }
1777
1814
 
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
- }
1815
+ async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
1816
+ switch (res.statusCode) {
1817
+ case 151:
1818
+ this.errorLog('Command not supported by this device type.');
1819
+ break;
1820
+ case 152:
1821
+ this.errorLog('Device not found.');
1822
+ break;
1823
+ case 160:
1824
+ this.errorLog('Command is not supported.');
1825
+ break;
1826
+ case 161:
1827
+ this.errorLog('Device is offline.');
1828
+ break;
1829
+ case 171:
1830
+ this.errorLog('is offline');
1831
+ break;
1832
+ case 190:
1833
+ this.errorLog('Requests reached the daily limit');
1834
+ break;
1835
+ case 100:
1836
+ if (this.debugMode) {
1837
+ this.debugLog('Command successfully sent.');
1838
+ }
1839
+ break;
1840
+ default:
1841
+ if (this.debugMode) {
1842
+ this.debugLog('Unknown statusCode.');
1843
+ }
1819
1844
  }
1820
1845
  }
1821
1846
 
@@ -1826,7 +1851,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
1826
1851
  try {
1827
1852
  Switchbot = require('node-switchbot');
1828
1853
  switchbot = new Switchbot();
1829
- } catch (e) {
1854
+ } catch (e: any) {
1830
1855
  switchbot = false;
1831
1856
  this.errorLog(`Was 'node-switchbot' found: ${switchbot}`);
1832
1857
  }
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
  };