@switchbot/homebridge-switchbot 3.5.0-beta.3 → 3.5.0-beta.31
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/CHANGELOG.md +4 -1
- package/config.schema.json +147 -9
- package/dist/device/blindtilt.d.ts +21 -94
- package/dist/device/blindtilt.d.ts.map +1 -1
- package/dist/device/blindtilt.js +347 -756
- package/dist/device/blindtilt.js.map +1 -1
- package/dist/device/bot.d.ts +25 -71
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +582 -759
- package/dist/device/bot.js.map +1 -1
- package/dist/device/ceilinglight.d.ts +13 -67
- package/dist/device/ceilinglight.d.ts.map +1 -1
- package/dist/device/ceilinglight.js +209 -587
- package/dist/device/ceilinglight.js.map +1 -1
- package/dist/device/colorbulb.d.ts +13 -74
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +250 -632
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts +14 -65
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +204 -531
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts +17 -86
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +335 -786
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/device.d.ts +59 -0
- package/dist/device/device.d.ts.map +1 -0
- package/dist/device/device.js +654 -0
- package/dist/device/device.js.map +1 -0
- package/dist/device/fan.d.ts +51 -0
- package/dist/device/fan.d.ts.map +1 -0
- package/dist/device/fan.js +499 -0
- package/dist/device/fan.js.map +1 -0
- package/dist/device/hub.d.ts +15 -59
- package/dist/device/hub.d.ts.map +1 -1
- package/dist/device/hub.js +242 -596
- package/dist/device/hub.js.map +1 -1
- package/dist/device/humidifier.d.ts +10 -65
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +207 -571
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/iosensor.d.ts +11 -64
- package/dist/device/iosensor.d.ts.map +1 -1
- package/dist/device/iosensor.js +174 -584
- package/dist/device/iosensor.js.map +1 -1
- package/dist/device/lightstrip.d.ts +10 -68
- package/dist/device/lightstrip.d.ts.map +1 -1
- package/dist/device/lightstrip.js +252 -568
- package/dist/device/lightstrip.js.map +1 -1
- package/dist/device/lock.d.ts +15 -62
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +210 -542
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +13 -63
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +170 -577
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +13 -64
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +159 -577
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts +13 -69
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +136 -518
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +9 -57
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +82 -452
- package/dist/device/plug.js.map +1 -1
- package/dist/device/robotvacuumcleaner.d.ts +11 -62
- package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
- package/dist/device/robotvacuumcleaner.js +140 -451
- package/dist/device/robotvacuumcleaner.js.map +1 -1
- package/dist/device/waterdetector.d.ts +9 -70
- package/dist/device/waterdetector.d.ts.map +1 -1
- package/dist/device/waterdetector.js +121 -664
- package/dist/device/waterdetector.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/irdevice/airconditioner.d.ts +8 -48
- package/dist/irdevice/airconditioner.d.ts.map +1 -1
- package/dist/irdevice/airconditioner.js +309 -419
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts +7 -38
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +72 -304
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts +6 -35
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +34 -278
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts +6 -39
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +67 -311
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/irdevice.d.ts +40 -0
- package/dist/irdevice/irdevice.d.ts.map +1 -0
- package/dist/irdevice/irdevice.js +509 -0
- package/dist/irdevice/irdevice.js.map +1 -0
- package/dist/irdevice/light.d.ts +6 -34
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +23 -272
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts +18 -47
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +352 -546
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts +7 -39
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +82 -321
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts +6 -35
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +41 -284
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts +6 -35
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +42 -287
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +14 -1
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +237 -94
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +40 -10
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +0 -552
- package/dist/settings.js.map +1 -1
- package/dist/utils.d.ts +77 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +638 -1
- package/dist/utils.js.map +1 -1
- package/package.json +16 -15
- package/src/custom.d.ts +2 -1
- package/src/device/blindtilt.ts +373 -782
- package/src/device/bot.ts +616 -844
- package/src/device/ceilinglight.ts +222 -607
- package/src/device/colorbulb.ts +264 -656
- package/src/device/contact.ts +229 -553
- package/src/device/curtain.ts +355 -810
- package/src/device/device.ts +681 -0
- package/src/device/fan.ts +548 -0
- package/src/device/hub.ts +268 -623
- package/src/device/humidifier.ts +237 -618
- package/src/device/iosensor.ts +200 -610
- package/src/device/lightstrip.ts +273 -596
- package/src/device/lock.ts +247 -582
- package/src/device/meter.ts +196 -601
- package/src/device/meterplus.ts +184 -602
- package/src/device/motion.ts +156 -541
- package/src/device/plug.ts +92 -480
- package/src/device/robotvacuumcleaner.ts +161 -477
- package/src/device/waterdetector.ts +139 -689
- package/src/index.ts +1 -1
- package/src/irdevice/airconditioner.ts +330 -446
- package/src/irdevice/airpurifier.ts +89 -321
- package/src/irdevice/camera.ts +42 -293
- package/src/irdevice/fan.ts +78 -327
- package/src/irdevice/irdevice.ts +526 -0
- package/src/irdevice/light.ts +32 -287
- package/src/irdevice/other.ts +396 -615
- package/src/irdevice/tv.ts +100 -339
- package/src/irdevice/vacuumcleaner.ts +49 -305
- package/src/irdevice/waterheater.ts +50 -310
- package/src/platform.ts +247 -102
- package/src/settings.ts +56 -565
- package/src/utils.ts +642 -1
package/src/platform.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* Copyright(C) 2017-
|
|
1
|
+
/* Copyright(C) 2017-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
|
|
2
2
|
*
|
|
3
3
|
* platform.ts: @switchbot/homebridge-switchbot platform class.
|
|
4
4
|
*/
|
|
@@ -20,8 +20,9 @@ import { CeilingLight } from './device/ceilinglight.js';
|
|
|
20
20
|
import { StripLight } from './device/lightstrip.js';
|
|
21
21
|
import { Humidifier } from './device/humidifier.js';
|
|
22
22
|
import { RobotVacuumCleaner } from './device/robotvacuumcleaner.js';
|
|
23
|
+
import { Fan } from './device/fan.js';
|
|
23
24
|
import { TV } from './irdevice/tv.js';
|
|
24
|
-
import {
|
|
25
|
+
import { IRFan } from './irdevice/fan.js';
|
|
25
26
|
import { Light } from './irdevice/light.js';
|
|
26
27
|
import { Others } from './irdevice/other.js';
|
|
27
28
|
import { Camera } from './irdevice/camera.js';
|
|
@@ -32,16 +33,16 @@ import { VacuumCleaner } from './irdevice/vacuumcleaner.js';
|
|
|
32
33
|
import { AirConditioner } from './irdevice/airconditioner.js';
|
|
33
34
|
import * as http from 'http';
|
|
34
35
|
import { Buffer } from 'buffer';
|
|
35
|
-
import { request } from 'undici';
|
|
36
|
+
import { Dispatcher, request } from 'undici';
|
|
36
37
|
import { MqttClient } from 'mqtt';
|
|
37
38
|
import { queueScheduler } from 'rxjs';
|
|
38
39
|
import fakegato from 'fakegato-history';
|
|
39
40
|
import asyncmqtt from 'async-mqtt';
|
|
40
41
|
import crypto, { randomUUID } from 'crypto';
|
|
41
42
|
import { readFileSync, writeFileSync } from 'fs';
|
|
42
|
-
import
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
import { EveHomeKitTypes } from 'homebridge-lib/EveHomeKitTypes';
|
|
44
|
+
import { UrlObject } from 'url';
|
|
45
|
+
import { sleep } from './utils.js';
|
|
45
46
|
|
|
46
47
|
/**
|
|
47
48
|
* HomebridgePlatform
|
|
@@ -56,6 +57,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
56
57
|
version!: string;
|
|
57
58
|
Logging?: string;
|
|
58
59
|
debugMode!: boolean;
|
|
60
|
+
maxRetries!: number;
|
|
61
|
+
delayBetweenRetries!: number;
|
|
59
62
|
platformConfig!: SwitchBotPlatformConfig['options'];
|
|
60
63
|
platformLogging!: SwitchBotPlatformConfig['logging'];
|
|
61
64
|
config!: SwitchBotPlatformConfig;
|
|
@@ -104,7 +107,6 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
104
107
|
}
|
|
105
108
|
|
|
106
109
|
// import fakegato-history module and EVE characteristics
|
|
107
|
-
const { EveHomeKitTypes } = hbLib;
|
|
108
110
|
this.fakegatoAPI = fakegato(api);
|
|
109
111
|
this.eve = new EveHomeKitTypes(api);
|
|
110
112
|
|
|
@@ -383,6 +385,21 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
383
385
|
this.debugWarnLog('Using Default Push Rate.');
|
|
384
386
|
}
|
|
385
387
|
|
|
388
|
+
if (!this.config.options.maxRetries) {
|
|
389
|
+
this.config.options.maxRetries = 5;
|
|
390
|
+
this.debugWarnLog('Using Default Max Retries.');
|
|
391
|
+
} else {
|
|
392
|
+
this.maxRetries = this.config.options.maxRetries;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (!this.config.options.delayBetweenRetries) {
|
|
396
|
+
// default 3 seconds
|
|
397
|
+
this.config.options!.delayBetweenRetries! = 3000;
|
|
398
|
+
this.debugWarnLog('Using Default Delay Between Retries.');
|
|
399
|
+
} else {
|
|
400
|
+
this.delayBetweenRetries = this.config.options.delayBetweenRetries * 1000;
|
|
401
|
+
}
|
|
402
|
+
|
|
386
403
|
if (!this.config.credentials && !this.config.options) {
|
|
387
404
|
this.debugWarnLog('Missing Credentials');
|
|
388
405
|
} else if (this.config.credentials && !this.config.credentials.notice) {
|
|
@@ -492,44 +509,98 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
492
509
|
*/
|
|
493
510
|
async discoverDevices() {
|
|
494
511
|
if (this.config.credentials?.token) {
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
const
|
|
508
|
-
this.debugWarnLog(`
|
|
509
|
-
this.debugWarnLog(`
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
512
|
+
let retryCount = 0;
|
|
513
|
+
const maxRetries = this.maxRetries; // Maximum number of retries
|
|
514
|
+
const delayBetweenRetries = this.delayBetweenRetries; // Delay between retries in milliseconds
|
|
515
|
+
this.debugWarnLog(`Retry Count: ${retryCount}`);
|
|
516
|
+
this.debugWarnLog(`Max Retries: ${maxRetries}`);
|
|
517
|
+
this.debugWarnLog(`Delay Between Retries: ${delayBetweenRetries}`);
|
|
518
|
+
while (retryCount < maxRetries) {
|
|
519
|
+
try {
|
|
520
|
+
const { body, statusCode } = await request(Devices, {
|
|
521
|
+
headers: this.generateHeaders(),
|
|
522
|
+
});
|
|
523
|
+
this.debugWarnLog(`statusCode: ${statusCode}`);
|
|
524
|
+
const devicesAPI: any = await body.json();
|
|
525
|
+
this.debugWarnLog(`devicesAPI: ${JSON.stringify(devicesAPI)}`);
|
|
526
|
+
this.debugWarnLog(`devicesAPI Body: ${JSON.stringify(devicesAPI.body)}`);
|
|
527
|
+
this.debugWarnLog(`devicesAPI StatusCode: ${devicesAPI.statusCode}`);
|
|
528
|
+
if ((statusCode === 200 || statusCode === 100) && (devicesAPI.statusCode === 200 || devicesAPI.statusCode === 100)) {
|
|
529
|
+
this.debugErrorLog(`statusCode: ${statusCode} & devicesAPI StatusCode: ${devicesAPI.statusCode}`);
|
|
530
|
+
// SwitchBot Devices
|
|
531
|
+
const deviceLists = devicesAPI.body.deviceList;
|
|
532
|
+
this.debugWarnLog(`DeviceLists: ${JSON.stringify(deviceLists)}`);
|
|
533
|
+
this.debugWarnLog(`DeviceLists Length: ${deviceLists.length}`);
|
|
534
|
+
if (!this.config.options?.devices) {
|
|
535
|
+
this.debugLog(`SwitchBot Device Config Not Set: ${JSON.stringify(this.config.options?.devices)}`);
|
|
536
|
+
if (deviceLists.length === 0) {
|
|
537
|
+
this.debugLog(`SwitchBot API Currently Doesn't Have Any Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
|
|
538
|
+
} else {
|
|
539
|
+
const devices = deviceLists.map((v: any) => v);
|
|
540
|
+
for (const device of devices) {
|
|
541
|
+
if (device.deviceType) {
|
|
542
|
+
if (device.configDeviceName) {
|
|
543
|
+
device.deviceName = device.configDeviceName;
|
|
544
|
+
}
|
|
545
|
+
this.createDevice(device);
|
|
520
546
|
}
|
|
521
|
-
this.createDevice(device);
|
|
522
547
|
}
|
|
523
548
|
}
|
|
549
|
+
} else if (this.config.credentials?.token && this.config.options.devices) {
|
|
550
|
+
this.debugLog(`SwitchBot Device Config Set: ${JSON.stringify(this.config.options?.devices)}`);
|
|
551
|
+
if (deviceLists.length === 0) {
|
|
552
|
+
this.debugLog(`SwitchBot API Currently Doesn't Have Any Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
|
|
553
|
+
} else {
|
|
554
|
+
const deviceConfigs = this.config.options?.devices;
|
|
555
|
+
|
|
556
|
+
const mergeBydeviceId = (a1: { deviceId: string }[], a2: any[]) =>
|
|
557
|
+
a1.map((itm: { deviceId: string }) => ({
|
|
558
|
+
...a2.find(
|
|
559
|
+
(item: { deviceId: string }) =>
|
|
560
|
+
item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item,
|
|
561
|
+
),
|
|
562
|
+
...itm,
|
|
563
|
+
}));
|
|
564
|
+
|
|
565
|
+
const devices = mergeBydeviceId(deviceLists, deviceConfigs);
|
|
566
|
+
this.debugLog(`SwitchBot Devices: ${JSON.stringify(devices)}`);
|
|
567
|
+
for (const device of devices) {
|
|
568
|
+
if (!device.deviceType) {
|
|
569
|
+
device.deviceType = device.configDeviceType;
|
|
570
|
+
this.errorLog(`API has displaying no deviceType: ${device.deviceType}, So using configDeviceType: ${device.configDeviceType}`);
|
|
571
|
+
}
|
|
572
|
+
if (device.deviceType) {
|
|
573
|
+
if (device.configDeviceName) {
|
|
574
|
+
device.deviceName = device.configDeviceName;
|
|
575
|
+
}
|
|
576
|
+
this.createDevice(device);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
} else {
|
|
581
|
+
this.errorLog('SwitchBot Token Supplied, Issue with Auth.');
|
|
524
582
|
}
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
if (deviceLists.length === 0) {
|
|
528
|
-
this.debugLog(`SwitchBot API Currently Doesn't Have Any Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
|
|
583
|
+
if (devicesAPI.body.deviceList.length !== 0) {
|
|
584
|
+
this.infoLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
|
|
529
585
|
} else {
|
|
530
|
-
|
|
586
|
+
this.debugLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
|
|
587
|
+
}
|
|
531
588
|
|
|
532
|
-
|
|
589
|
+
// IR Devices
|
|
590
|
+
const irDeviceLists = devicesAPI.body.infraredRemoteList;
|
|
591
|
+
if (!this.config.options?.irdevices) {
|
|
592
|
+
this.debugLog(`IR Device Config Not Set: ${JSON.stringify(this.config.options?.irdevices)}`);
|
|
593
|
+
const devices = irDeviceLists.map((v: any) => v);
|
|
594
|
+
for (const device of devices) {
|
|
595
|
+
if (device.remoteType) {
|
|
596
|
+
this.createIRDevice(device);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
} else {
|
|
600
|
+
this.debugLog(`IR Device Config Set: ${JSON.stringify(this.config.options?.irdevices)}`);
|
|
601
|
+
const irDeviceConfig = this.config.options?.irdevices;
|
|
602
|
+
|
|
603
|
+
const mergeIRBydeviceId = (a1: { deviceId: string }[], a2: any[]) =>
|
|
533
604
|
a1.map((itm: { deviceId: string }) => ({
|
|
534
605
|
...a2.find(
|
|
535
606
|
(item: { deviceId: string }) =>
|
|
@@ -538,73 +609,34 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
538
609
|
...itm,
|
|
539
610
|
}));
|
|
540
611
|
|
|
541
|
-
const devices =
|
|
542
|
-
this.debugLog(`
|
|
612
|
+
const devices = mergeIRBydeviceId(irDeviceLists, irDeviceConfig);
|
|
613
|
+
this.debugLog(`IR Devices: ${JSON.stringify(devices)}`);
|
|
543
614
|
for (const device of devices) {
|
|
544
|
-
if (!device.deviceType) {
|
|
545
|
-
device.deviceType = device.configDeviceType;
|
|
546
|
-
this.errorLog(`API has displaying no deviceType: ${device.deviceType}, So using configDeviceType: ${device.configDeviceType}`);
|
|
547
|
-
}
|
|
548
|
-
if (device.deviceType) {
|
|
549
|
-
if (device.configDeviceName) {
|
|
550
|
-
device.deviceName = device.configDeviceName;
|
|
551
|
-
}
|
|
552
|
-
this.createDevice(device);
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
} else {
|
|
557
|
-
this.errorLog('SwitchBot Token Supplied, Issue with Auth.');
|
|
558
|
-
}
|
|
559
|
-
if (devicesAPI.body.deviceList.length !== 0) {
|
|
560
|
-
this.infoLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
|
|
561
|
-
} else {
|
|
562
|
-
this.debugLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
// IR Devices
|
|
566
|
-
const irDeviceLists = devicesAPI.body.infraredRemoteList;
|
|
567
|
-
if (!this.config.options?.irdevices) {
|
|
568
|
-
this.debugLog(`IR Device Config Not Set: ${JSON.stringify(this.config.options?.irdevices)}`);
|
|
569
|
-
const devices = irDeviceLists.map((v: any) => v);
|
|
570
|
-
for (const device of devices) {
|
|
571
|
-
if (device.remoteType) {
|
|
572
615
|
this.createIRDevice(device);
|
|
573
616
|
}
|
|
574
617
|
}
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
const mergeIRBydeviceId = (a1: { deviceId: string }[], a2: any[]) =>
|
|
580
|
-
a1.map((itm: { deviceId: string }) => ({
|
|
581
|
-
...a2.find(
|
|
582
|
-
(item: { deviceId: string }) =>
|
|
583
|
-
item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item,
|
|
584
|
-
),
|
|
585
|
-
...itm,
|
|
586
|
-
}));
|
|
587
|
-
|
|
588
|
-
const devices = mergeIRBydeviceId(irDeviceLists, irDeviceConfig);
|
|
589
|
-
this.debugLog(`IR Devices: ${JSON.stringify(devices)}`);
|
|
590
|
-
for (const device of devices) {
|
|
591
|
-
this.createIRDevice(device);
|
|
618
|
+
if (devicesAPI.body.infraredRemoteList.length !== 0) {
|
|
619
|
+
this.infoLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
|
|
620
|
+
} else {
|
|
621
|
+
this.debugLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
|
|
592
622
|
}
|
|
593
|
-
|
|
594
|
-
if (devicesAPI.body.infraredRemoteList.length !== 0) {
|
|
595
|
-
this.infoLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
|
|
623
|
+
break;
|
|
596
624
|
} else {
|
|
597
|
-
this.
|
|
625
|
+
this.statusCode(statusCode);
|
|
626
|
+
this.statusCode(devicesAPI.statusCode);
|
|
627
|
+
if (statusCode === 500) {
|
|
628
|
+
retryCount++;
|
|
629
|
+
this.infoLog(`statusCode: ${statusCode} Attempt ${retryCount} of ${maxRetries}`);
|
|
630
|
+
await sleep(delayBetweenRetries);
|
|
631
|
+
}
|
|
598
632
|
}
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
this.
|
|
633
|
+
} catch (e: any) {
|
|
634
|
+
retryCount++;
|
|
635
|
+
this.debugErrorLog(
|
|
636
|
+
`Failed to Discover Devices, Error Message: ${JSON.stringify(e.message)}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug',
|
|
637
|
+
);
|
|
638
|
+
this.debugErrorLog(`Failed to Discover Devices, Error: ${e}`);
|
|
602
639
|
}
|
|
603
|
-
} catch (e: any) {
|
|
604
|
-
this.debugErrorLog(
|
|
605
|
-
`Failed to Discover Devices, Error Message: ${JSON.stringify(e.message)}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug',
|
|
606
|
-
);
|
|
607
|
-
this.debugErrorLog(`Failed to Discover Devices, Error: ${e}`);
|
|
608
640
|
}
|
|
609
641
|
} else if (!this.config.credentials?.token && this.config.options?.devices) {
|
|
610
642
|
this.debugLog(`SwitchBot Device Manual Config Set: ${JSON.stringify(this.config.options?.devices)}`);
|
|
@@ -691,10 +723,12 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
691
723
|
this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
|
|
692
724
|
this.createColorBulb(device);
|
|
693
725
|
break;
|
|
726
|
+
case 'K10+':
|
|
694
727
|
case 'WoSweeper':
|
|
695
728
|
case 'WoSweeperMini':
|
|
696
729
|
case 'Robot Vacuum Cleaner S1':
|
|
697
730
|
case 'Robot Vacuum Cleaner S1 Plus':
|
|
731
|
+
case 'Robot Vacuum Cleaner S10':
|
|
698
732
|
this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
|
|
699
733
|
this.createRobotVacuumCleaner(device);
|
|
700
734
|
break;
|
|
@@ -712,8 +746,13 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
712
746
|
this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported.`);
|
|
713
747
|
break;
|
|
714
748
|
case 'Remote':
|
|
749
|
+
case 'remote with screen+':
|
|
715
750
|
this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId} is Not Supported.`);
|
|
716
751
|
break;
|
|
752
|
+
case 'Battery Circulator Fan':
|
|
753
|
+
this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
|
|
754
|
+
this.createFan(device);
|
|
755
|
+
break;
|
|
717
756
|
default:
|
|
718
757
|
this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported.`);
|
|
719
758
|
// eslint-disable-next-line max-len
|
|
@@ -749,7 +788,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
749
788
|
case 'Fan':
|
|
750
789
|
case 'DIY Fan':
|
|
751
790
|
this.debugLog(`Discovered ${device.remoteType}: ${device.deviceId}`);
|
|
752
|
-
this.
|
|
791
|
+
this.createIRFan(device);
|
|
753
792
|
break;
|
|
754
793
|
case 'Air Conditioner':
|
|
755
794
|
case 'DIY Air Conditioner':
|
|
@@ -1781,6 +1820,66 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
1781
1820
|
}
|
|
1782
1821
|
}
|
|
1783
1822
|
|
|
1823
|
+
private async createFan(device: device & devicesConfig) {
|
|
1824
|
+
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1825
|
+
|
|
1826
|
+
// see if an accessory with the same uuid has already been registered and restored from
|
|
1827
|
+
// the cached devices we stored in the `configureAccessory` method above
|
|
1828
|
+
const existingAccessory = this.accessories.find((accessory) => accessory.UUID === uuid);
|
|
1829
|
+
|
|
1830
|
+
if (existingAccessory) {
|
|
1831
|
+
// the accessory already exists
|
|
1832
|
+
if (await this.registerDevice(device)) {
|
|
1833
|
+
// if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
|
|
1834
|
+
existingAccessory.context.model = device.deviceType;
|
|
1835
|
+
existingAccessory.context.deviceID = device.deviceId;
|
|
1836
|
+
existingAccessory.displayName = device.configDeviceName || device.deviceName;
|
|
1837
|
+
if (device.firmware) {
|
|
1838
|
+
existingAccessory.context.FirmwareRevision = device.firmware;
|
|
1839
|
+
}
|
|
1840
|
+
existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
|
|
1841
|
+
this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceId}`);
|
|
1842
|
+
existingAccessory.context.connectionType = await this.connectionType(device);
|
|
1843
|
+
this.api.updatePlatformAccessories([existingAccessory]);
|
|
1844
|
+
// create the accessory handler for the restored accessory
|
|
1845
|
+
// this is imported from `platformAccessory.ts`
|
|
1846
|
+
new Fan(this, existingAccessory, device);
|
|
1847
|
+
this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`);
|
|
1848
|
+
} else {
|
|
1849
|
+
this.unregisterPlatformAccessories(existingAccessory);
|
|
1850
|
+
}
|
|
1851
|
+
} else if (await this.registerDevice(device)) {
|
|
1852
|
+
// the accessory does not yet exist, so we need to create it
|
|
1853
|
+
if (!device.external) {
|
|
1854
|
+
this.infoLog(`Adding new accessory: ${device.deviceName} ${device.deviceType} DeviceID: ${device.deviceId}`);
|
|
1855
|
+
}
|
|
1856
|
+
|
|
1857
|
+
// create a new accessory
|
|
1858
|
+
const accessory = new this.api.platformAccessory(device.deviceName, uuid);
|
|
1859
|
+
|
|
1860
|
+
// store a copy of the device object in the `accessory.context`
|
|
1861
|
+
// the `context` property can be used to store any data about the accessory you may need
|
|
1862
|
+
accessory.context.device = device;
|
|
1863
|
+
accessory.context.model = device.deviceType;
|
|
1864
|
+
accessory.context.deviceID = device.deviceId;
|
|
1865
|
+
if (device.firmware) {
|
|
1866
|
+
accessory.context.FirmwareRevision = device.firmware;
|
|
1867
|
+
}
|
|
1868
|
+
accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
|
|
1869
|
+
accessory.context.connectionType = await this.connectionType(device);
|
|
1870
|
+
// create the accessory handler for the newly create accessory
|
|
1871
|
+
// this is imported from `platformAccessory.ts`
|
|
1872
|
+
new Fan(this, accessory, device);
|
|
1873
|
+
this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`);
|
|
1874
|
+
|
|
1875
|
+
// publish device externally or link the accessory to your platform
|
|
1876
|
+
this.externalOrPlatform(device, accessory);
|
|
1877
|
+
this.accessories.push(accessory);
|
|
1878
|
+
} else {
|
|
1879
|
+
this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} DeviceID: ${device.deviceId}`);
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1784
1883
|
private async createRobotVacuumCleaner(device: device & devicesConfig) {
|
|
1785
1884
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1786
1885
|
|
|
@@ -1893,7 +1992,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
1893
1992
|
}
|
|
1894
1993
|
}
|
|
1895
1994
|
|
|
1896
|
-
private async
|
|
1995
|
+
private async createIRFan(device: irdevice & devicesConfig) {
|
|
1897
1996
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
1898
1997
|
|
|
1899
1998
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
@@ -1916,7 +2015,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
1916
2015
|
this.api.updatePlatformAccessories([existingAccessory]);
|
|
1917
2016
|
// create the accessory handler for the restored accessory
|
|
1918
2017
|
// this is imported from `platformAccessory.ts`
|
|
1919
|
-
new
|
|
2018
|
+
new IRFan(this, existingAccessory, device);
|
|
1920
2019
|
this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${existingAccessory.UUID})`);
|
|
1921
2020
|
} else {
|
|
1922
2021
|
this.unregisterPlatformAccessories(existingAccessory);
|
|
@@ -1942,7 +2041,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
1942
2041
|
accessory.context.connectionType = device.connectionType;
|
|
1943
2042
|
// create the accessory handler for the newly create accessory
|
|
1944
2043
|
// this is imported from `platformAccessory.ts`
|
|
1945
|
-
new
|
|
2044
|
+
new IRFan(this, accessory, device);
|
|
1946
2045
|
this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
1947
2046
|
|
|
1948
2047
|
// publish device externally or link the accessory to your platform
|
|
@@ -2626,6 +2725,30 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
2626
2725
|
}
|
|
2627
2726
|
}
|
|
2628
2727
|
|
|
2728
|
+
async retryRequest(deviceMaxRetries: number, deviceDelayBetweenRetries: number, url: string | URL | UrlObject,
|
|
2729
|
+
options?: { dispatcher?: Dispatcher } & Omit<Dispatcher.RequestOptions,
|
|
2730
|
+
'origin' | 'path' | 'method'> & Partial<Pick<Dispatcher.RequestOptions, 'method'>>): Promise<{ body: any; statusCode: number }> {
|
|
2731
|
+
let retryCount = 0;
|
|
2732
|
+
const maxRetries = deviceMaxRetries;
|
|
2733
|
+
const delayBetweenRetries = deviceDelayBetweenRetries;
|
|
2734
|
+
while (retryCount < maxRetries) {
|
|
2735
|
+
try {
|
|
2736
|
+
const { body, statusCode } = await request(url, options);
|
|
2737
|
+
if (statusCode === 200 || statusCode === 100) {
|
|
2738
|
+
return { body, statusCode };
|
|
2739
|
+
} else {
|
|
2740
|
+
this.debugLog(`Received status code: ${statusCode}`);
|
|
2741
|
+
}
|
|
2742
|
+
} catch (error: any) {
|
|
2743
|
+
this.errorLog(`Error making request: ${error.message}`);
|
|
2744
|
+
}
|
|
2745
|
+
retryCount++;
|
|
2746
|
+
this.debugLog(`Retry attempt ${retryCount} of ${maxRetries}`);
|
|
2747
|
+
await sleep(delayBetweenRetries);
|
|
2748
|
+
}
|
|
2749
|
+
return { body: null, statusCode: -1 };
|
|
2750
|
+
}
|
|
2751
|
+
|
|
2629
2752
|
// BLE Connection
|
|
2630
2753
|
async connectBLE() {
|
|
2631
2754
|
let switchbot: any;
|
|
@@ -2662,6 +2785,22 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
2662
2785
|
if (this.config.options.pushRate) {
|
|
2663
2786
|
platformConfig.pushRate = this.config.options.pushRate;
|
|
2664
2787
|
}
|
|
2788
|
+
if (this.config.options.maxRetries) {
|
|
2789
|
+
this.maxRetries = this.config.options.maxRetries;
|
|
2790
|
+
platformConfig.maxRetries = this.config.options.maxRetries;
|
|
2791
|
+
} else {
|
|
2792
|
+
this.maxRetries = 3;
|
|
2793
|
+
this.debugWarnLog('Using Default Max Retries');
|
|
2794
|
+
platformConfig.maxRetries = this.maxRetries;
|
|
2795
|
+
}
|
|
2796
|
+
if (this.config.options.delayBetweenRetries) {
|
|
2797
|
+
this.delayBetweenRetries = this.config.options.delayBetweenRetries * 1000;
|
|
2798
|
+
platformConfig.delayBetweenRetries = this.config.options.delayBetweenRetries;
|
|
2799
|
+
} else {
|
|
2800
|
+
this.delayBetweenRetries = 3000;
|
|
2801
|
+
this.debugWarnLog('Using Default Delay Between Retries');
|
|
2802
|
+
platformConfig.delayBetweenRetries = this.delayBetweenRetries / 1000;
|
|
2803
|
+
}
|
|
2665
2804
|
if (Object.entries(platformConfig).length !== 0) {
|
|
2666
2805
|
this.debugLog(`Platform Config: ${JSON.stringify(platformConfig)}`);
|
|
2667
2806
|
}
|
|
@@ -2687,6 +2826,12 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
2687
2826
|
* If device level logging is turned on, log to log.warn
|
|
2688
2827
|
* Otherwise send debug logs to log.debug
|
|
2689
2828
|
*/
|
|
2829
|
+
successLog(...log: any[]): void {
|
|
2830
|
+
if (this.enablingPlatformLogging()) {
|
|
2831
|
+
this.log.success(String(...log));
|
|
2832
|
+
}
|
|
2833
|
+
}
|
|
2834
|
+
|
|
2690
2835
|
infoLog(...log: any[]): void {
|
|
2691
2836
|
if (this.enablingPlatformLogging()) {
|
|
2692
2837
|
this.log.info(String(...log));
|