@switchbot/homebridge-switchbot 3.7.1-beta.8 → 3.8.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.
- package/CHANGELOG.md +8 -2
- package/README.md +14 -0
- package/assets/security-privacy-bluetooth.png +0 -0
- package/config.schema.json +78 -3
- package/dist/device/blindtilt.d.ts +18 -8
- package/dist/device/blindtilt.d.ts.map +1 -1
- package/dist/device/blindtilt.js +108 -70
- package/dist/device/blindtilt.js.map +1 -1
- package/dist/device/bot.d.ts +9 -9
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +143 -170
- package/dist/device/bot.js.map +1 -1
- package/dist/device/ceilinglight.d.ts +13 -13
- package/dist/device/ceilinglight.d.ts.map +1 -1
- package/dist/device/ceilinglight.js +38 -73
- package/dist/device/ceilinglight.js.map +1 -1
- package/dist/device/colorbulb.d.ts +12 -12
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +41 -79
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts +5 -5
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +20 -42
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts +15 -5
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +127 -81
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/device.d.ts +18 -18
- package/dist/device/device.d.ts.map +1 -1
- package/dist/device/device.js +33 -36
- package/dist/device/device.js.map +1 -1
- package/dist/device/fan.d.ts +8 -8
- package/dist/device/fan.d.ts.map +1 -1
- package/dist/device/fan.js +43 -75
- package/dist/device/fan.js.map +1 -1
- package/dist/device/hub.d.ts +5 -5
- package/dist/device/hub.d.ts.map +1 -1
- package/dist/device/hub.js +18 -39
- package/dist/device/hub.js.map +1 -1
- package/dist/device/humidifier.d.ts +5 -5
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +38 -78
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/iosensor.d.ts +5 -5
- package/dist/device/iosensor.d.ts.map +1 -1
- package/dist/device/iosensor.js +21 -40
- package/dist/device/iosensor.js.map +1 -1
- package/dist/device/lightstrip.d.ts +6 -6
- package/dist/device/lightstrip.d.ts.map +1 -1
- package/dist/device/lightstrip.js +34 -73
- package/dist/device/lightstrip.js.map +1 -1
- package/dist/device/lock.d.ts +9 -9
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +37 -52
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +5 -5
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +21 -39
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +5 -5
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +21 -38
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts +5 -5
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +14 -32
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +12 -12
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +16 -25
- package/dist/device/plug.js.map +1 -1
- package/dist/device/robotvacuumcleaner.d.ts +11 -11
- package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
- package/dist/device/robotvacuumcleaner.js +42 -56
- package/dist/device/robotvacuumcleaner.js.map +1 -1
- package/dist/device/waterdetector.d.ts +5 -5
- package/dist/device/waterdetector.d.ts.map +1 -1
- package/dist/device/waterdetector.js +47 -44
- package/dist/device/waterdetector.js.map +1 -1
- package/dist/homebridge-ui/server.js +2 -2
- package/dist/homebridge-ui/server.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -4
- package/dist/index.js.map +1 -1
- package/dist/irdevice/airconditioner.d.ts +8 -8
- package/dist/irdevice/airconditioner.d.ts.map +1 -1
- package/dist/irdevice/airconditioner.js +61 -105
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts +10 -10
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +22 -42
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts +9 -9
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +15 -25
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts +8 -8
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +21 -40
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/irdevice.d.ts +11 -11
- package/dist/irdevice/irdevice.d.ts.map +1 -1
- package/dist/irdevice/irdevice.js +14 -22
- package/dist/irdevice/irdevice.js.map +1 -1
- package/dist/irdevice/light.d.ts +9 -9
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +24 -47
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts +9 -9
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +40 -83
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts +9 -9
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +29 -54
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts +5 -5
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +11 -21
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts +5 -5
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +11 -22
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +24 -23
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +471 -715
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +6 -3
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js.map +1 -1
- package/dist/types/bledevicestatus.d.ts +9 -9
- package/dist/types/bledevicestatus.d.ts.map +1 -1
- package/dist/types/devicelist.d.ts +6 -6
- package/dist/types/devicelist.d.ts.map +1 -1
- package/dist/types/deviceresponse.d.ts +4 -4
- package/dist/types/deviceresponse.d.ts.map +1 -1
- package/dist/types/devicestatus.d.ts +2 -2
- package/dist/types/devicestatus.d.ts.map +1 -1
- package/dist/types/devicewebhookstatus.d.ts +5 -5
- package/dist/types/devicewebhookstatus.d.ts.map +1 -1
- package/dist/types/irdevicelist.d.ts +4 -4
- package/dist/types/irdevicelist.d.ts.map +1 -1
- package/dist/types/pushbody.d.ts +2 -2
- package/dist/types/pushbody.d.ts.map +1 -1
- package/dist/utils.d.ts +4 -4
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +9 -13
- package/dist/utils.js.map +1 -1
- package/eslint.config.js +48 -93
- package/package.json +62 -55
- package/src/device/blindtilt.ts +509 -460
- package/src/device/bot.ts +696 -718
- package/src/device/ceilinglight.ts +331 -364
- package/src/device/colorbulb.ts +412 -448
- package/src/device/contact.ts +200 -221
- package/src/device/curtain.ts +506 -444
- package/src/device/device.ts +206 -208
- package/src/device/fan.ts +307 -340
- package/src/device/hub.ts +184 -209
- package/src/device/humidifier.ts +297 -342
- package/src/device/iosensor.ts +182 -204
- package/src/device/lightstrip.ts +362 -399
- package/src/device/lock.ts +262 -276
- package/src/device/meter.ts +183 -205
- package/src/device/meterplus.ts +183 -204
- package/src/device/motion.ts +169 -185
- package/src/device/plug.ts +174 -177
- package/src/device/robotvacuumcleaner.ts +256 -269
- package/src/device/waterdetector.ts +185 -185
- package/src/homebridge-ui/server.ts +16 -15
- package/src/index.ts +5 -6
- package/src/irdevice/airconditioner.ts +277 -326
- package/src/irdevice/airpurifier.ts +124 -143
- package/src/irdevice/camera.ts +58 -64
- package/src/irdevice/fan.ts +106 -123
- package/src/irdevice/irdevice.ts +116 -119
- package/src/irdevice/light.ts +119 -143
- package/src/irdevice/other.ts +417 -461
- package/src/irdevice/tv.ts +155 -177
- package/src/irdevice/vacuumcleaner.ts +54 -60
- package/src/irdevice/waterheater.ts +56 -63
- package/src/platform.ts +1467 -1683
- package/src/settings.ts +173 -170
- package/src/types/bledevicestatus.ts +252 -256
- package/src/types/devicelist.ts +79 -79
- package/src/types/deviceresponse.ts +12 -13
- package/src/types/devicestatus.ts +124 -124
- package/src/types/devicewebhookstatus.ts +126 -131
- package/src/types/irdevicelist.ts +10 -10
- package/src/types/pushbody.ts +5 -5
- package/src/utils.ts +64 -65
- package/tsconfig.json +10 -9
- package/.github/npm-version-script.cjs +0 -81
package/dist/platform.js
CHANGED
|
@@ -1,59 +1,58 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import
|
|
1
|
+
import { Buffer } from 'node:buffer';
|
|
2
|
+
import crypto, { randomUUID } from 'node:crypto';
|
|
3
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { createServer } from 'node:http';
|
|
5
|
+
import process from 'node:process';
|
|
6
|
+
import asyncmqtt from 'async-mqtt';
|
|
7
|
+
import fakegato from 'fakegato-history';
|
|
8
|
+
import { EveHomeKitTypes } from 'homebridge-lib/EveHomeKitTypes';
|
|
9
|
+
/*
|
|
10
|
+
* For Testing Locally:
|
|
11
|
+
* import { SwitchBotModel } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js';
|
|
12
|
+
*/
|
|
13
|
+
import { SwitchBot, SwitchBotModel } from 'node-switchbot';
|
|
14
|
+
import { queueScheduler } from 'rxjs';
|
|
15
|
+
import { request } from 'undici';
|
|
16
|
+
import { BlindTilt } from './device/blindtilt.js';
|
|
6
17
|
import { Bot } from './device/bot.js';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { Meter } from './device/meter.js';
|
|
10
|
-
import { Motion } from './device/motion.js';
|
|
18
|
+
import { CeilingLight } from './device/ceilinglight.js';
|
|
19
|
+
import { ColorBulb } from './device/colorbulb.js';
|
|
11
20
|
import { Contact } from './device/contact.js';
|
|
12
21
|
import { Curtain } from './device/curtain.js';
|
|
22
|
+
import { Fan } from './device/fan.js';
|
|
23
|
+
import { Hub } from './device/hub.js';
|
|
24
|
+
import { Humidifier } from './device/humidifier.js';
|
|
13
25
|
import { IOSensor } from './device/iosensor.js';
|
|
14
|
-
import { MeterPlus } from './device/meterplus.js';
|
|
15
|
-
import { ColorBulb } from './device/colorbulb.js';
|
|
16
26
|
import { StripLight } from './device/lightstrip.js';
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
27
|
+
import { Lock } from './device/lock.js';
|
|
28
|
+
import { Meter } from './device/meter.js';
|
|
29
|
+
import { MeterPlus } from './device/meterplus.js';
|
|
30
|
+
import { Motion } from './device/motion.js';
|
|
31
|
+
import { Plug } from './device/plug.js';
|
|
20
32
|
import { RobotVacuumCleaner } from './device/robotvacuumcleaner.js';
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
33
|
+
import { WaterDetector } from './device/waterdetector.js';
|
|
34
|
+
import { AirConditioner } from './irdevice/airconditioner.js';
|
|
35
|
+
import { AirPurifier } from './irdevice/airpurifier.js';
|
|
36
|
+
import { Camera } from './irdevice/camera.js';
|
|
23
37
|
import { IRFan } from './irdevice/fan.js';
|
|
24
38
|
import { Light } from './irdevice/light.js';
|
|
25
39
|
import { Others } from './irdevice/other.js';
|
|
26
|
-
import {
|
|
27
|
-
import { BlindTilt } from './device/blindtilt.js';
|
|
28
|
-
import { AirPurifier } from './irdevice/airpurifier.js';
|
|
29
|
-
import { WaterHeater } from './irdevice/waterheater.js';
|
|
40
|
+
import { TV } from './irdevice/tv.js';
|
|
30
41
|
import { VacuumCleaner } from './irdevice/vacuumcleaner.js';
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import { request } from 'undici';
|
|
34
|
-
import asyncmqtt from 'async-mqtt';
|
|
35
|
-
import { createServer } from 'http';
|
|
36
|
-
import { queueScheduler } from 'rxjs';
|
|
37
|
-
import fakegato from 'fakegato-history';
|
|
38
|
-
import crypto, { randomUUID } from 'crypto';
|
|
39
|
-
import { readFileSync, writeFileSync } from 'fs';
|
|
40
|
-
import { EveHomeKitTypes } from 'homebridge-lib/EveHomeKitTypes';
|
|
41
|
-
import { PLATFORM_NAME, PLUGIN_NAME, Devices, deleteWebhook, queryWebhook, setupWebhook, updateWebhook } from './settings.js';
|
|
42
|
+
import { WaterHeater } from './irdevice/waterheater.js';
|
|
43
|
+
import { deleteWebhook, Devices, PLATFORM_NAME, PLUGIN_NAME, queryWebhook, setupWebhook, updateWebhook } from './settings.js';
|
|
42
44
|
import { isBlindTiltDevice, isCurtainDevice, sleep } from './utils.js';
|
|
43
|
-
/*
|
|
44
|
-
* For Testing Locally:
|
|
45
|
-
* import { SwitchBotModel } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js';
|
|
46
|
-
*/
|
|
47
|
-
import { SwitchBotModel } from 'node-switchbot';
|
|
48
45
|
/**
|
|
49
46
|
* HomebridgePlatform
|
|
50
47
|
* This class is the main constructor for your plugin, this is where you should
|
|
51
48
|
* parse the user config and discover/register accessories with Homebridge.
|
|
52
49
|
*/
|
|
53
50
|
export class SwitchBotPlatform {
|
|
54
|
-
|
|
51
|
+
// Platform properties
|
|
52
|
+
accessories = [];
|
|
55
53
|
api;
|
|
56
54
|
log;
|
|
55
|
+
// Configuration properties
|
|
57
56
|
version;
|
|
58
57
|
Logging;
|
|
59
58
|
debugMode;
|
|
@@ -62,15 +61,16 @@ export class SwitchBotPlatform {
|
|
|
62
61
|
platformConfig;
|
|
63
62
|
platformLogging;
|
|
64
63
|
config;
|
|
64
|
+
// MQTT and Webhook properties
|
|
65
65
|
mqttClient = null;
|
|
66
66
|
webhookEventListener = null;
|
|
67
|
+
// External APIs
|
|
67
68
|
eve;
|
|
68
69
|
fakegatoAPI;
|
|
70
|
+
// Event Handlers
|
|
69
71
|
webhookEventHandler = {};
|
|
70
72
|
bleEventHandler = {};
|
|
71
73
|
constructor(log, config, api) {
|
|
72
|
-
// initialize
|
|
73
|
-
this.accessories = [];
|
|
74
74
|
this.api = api;
|
|
75
75
|
this.log = log;
|
|
76
76
|
// only load if configured
|
|
@@ -108,21 +108,21 @@ export class SwitchBotPlatform {
|
|
|
108
108
|
// in order to ensure they weren't added to homebridge already. This event can also be used
|
|
109
109
|
// to start discovery of new accessories.
|
|
110
110
|
this.api.on('didFinishLaunching', async () => {
|
|
111
|
-
this.debugLog('Executed didFinishLaunching callback');
|
|
111
|
+
await this.debugLog('Executed didFinishLaunching callback');
|
|
112
112
|
// run the method to discover / register your devices as accessories
|
|
113
113
|
try {
|
|
114
114
|
if (this.config.credentials?.openToken && !this.config.credentials.token) {
|
|
115
115
|
await this.updateToken();
|
|
116
116
|
}
|
|
117
117
|
else if (this.config.credentials?.token && !this.config.credentials?.secret) {
|
|
118
|
-
this.errorLog('"secret" config is not populated, you must populate then please restart Homebridge.');
|
|
118
|
+
await this.errorLog('"secret" config is not populated, you must populate then please restart Homebridge.');
|
|
119
119
|
}
|
|
120
120
|
else {
|
|
121
|
-
this.discoverDevices();
|
|
121
|
+
await this.discoverDevices();
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
catch (e) {
|
|
125
|
-
this.errorLog(`Failed to Discover, Error Message: ${e.message}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug');
|
|
125
|
+
await this.errorLog(`Failed to Discover, Error Message: ${e.message}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug');
|
|
126
126
|
await this.debugErrorLog(`Failed to Discover, Error: ${e}`);
|
|
127
127
|
}
|
|
128
128
|
});
|
|
@@ -160,7 +160,7 @@ export class SwitchBotPlatform {
|
|
|
160
160
|
this.mqttClient.subscribe('homebridge-switchbot/webhook/+');
|
|
161
161
|
this.mqttClient.on('message', async (topic, message) => {
|
|
162
162
|
try {
|
|
163
|
-
await
|
|
163
|
+
await this.debugLog(`Received Webhook via MQTT: ${topic}=${message}`);
|
|
164
164
|
const context = JSON.parse(message.toString());
|
|
165
165
|
this.webhookEventHandler[context.deviceMac]?.(context);
|
|
166
166
|
}
|
|
@@ -177,7 +177,7 @@ export class SwitchBotPlatform {
|
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
async setupwebhook() {
|
|
180
|
-
//webhook configuration
|
|
180
|
+
// webhook configuration
|
|
181
181
|
if (this.config.options?.webhookURL) {
|
|
182
182
|
const url = this.config.options?.webhookURL;
|
|
183
183
|
try {
|
|
@@ -192,17 +192,14 @@ export class SwitchBotPlatform {
|
|
|
192
192
|
const body = JSON.parse(data);
|
|
193
193
|
await this.debugLog(`Received Webhook: ${JSON.stringify(body)}`);
|
|
194
194
|
if (this.config.options?.mqttURL) {
|
|
195
|
-
const mac = body.context.deviceMac
|
|
196
|
-
?.toLowerCase()
|
|
197
|
-
.match(/[\s\S]{1,2}/g)
|
|
198
|
-
?.join(':');
|
|
195
|
+
const mac = body.context.deviceMac?.toLowerCase().match(/[\s\S]{1,2}/g)?.join(':');
|
|
199
196
|
const options = this.config.options?.mqttPubOptions || {};
|
|
200
197
|
this.mqttClient?.publish(`homebridge-switchbot/webhook/${mac}`, `${JSON.stringify(body.context)}`, options);
|
|
201
198
|
}
|
|
202
199
|
this.webhookEventHandler[body.context.deviceMac]?.(body.context);
|
|
203
200
|
}
|
|
204
201
|
catch (e) {
|
|
205
|
-
this.errorLog(`Failed to handle webhook event. Error:${e}`);
|
|
202
|
+
await this.errorLog(`Failed to handle webhook event. Error:${e}`);
|
|
206
203
|
}
|
|
207
204
|
});
|
|
208
205
|
response.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
@@ -216,10 +213,10 @@ export class SwitchBotPlatform {
|
|
|
216
213
|
catch (e) {
|
|
217
214
|
this.errorLog(`Failed to handle webhook event. Error:${e}`);
|
|
218
215
|
}
|
|
219
|
-
}).listen(port
|
|
216
|
+
}).listen(port || 80);
|
|
220
217
|
}
|
|
221
218
|
catch (e) {
|
|
222
|
-
this.errorLog(`Failed to create webhook listener. Error:${e.message}`);
|
|
219
|
+
await this.errorLog(`Failed to create webhook listener. Error:${e.message}`);
|
|
223
220
|
return;
|
|
224
221
|
}
|
|
225
222
|
try {
|
|
@@ -227,64 +224,61 @@ export class SwitchBotPlatform {
|
|
|
227
224
|
method: 'POST',
|
|
228
225
|
headers: this.generateHeaders(),
|
|
229
226
|
body: JSON.stringify({
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
227
|
+
action: 'setupWebhook',
|
|
228
|
+
url,
|
|
229
|
+
deviceList: 'ALL',
|
|
233
230
|
}),
|
|
234
231
|
});
|
|
235
232
|
const response = await body.json();
|
|
236
|
-
await this.debugLog(`setupWebhook: url:${url}`);
|
|
237
|
-
await this.debugLog(`setupWebhook: body:${JSON.stringify(response)}`);
|
|
238
|
-
await this.debugLog(`setupWebhook: statusCode:${statusCode}`);
|
|
233
|
+
await this.debugLog(`setupWebhook: url:${url}, body:${JSON.stringify(response)}, statusCode:${statusCode}`);
|
|
239
234
|
if (statusCode !== 200 || response?.statusCode !== 100) {
|
|
240
|
-
this.errorLog(`Failed to configure webhook. Existing webhook well be overridden. HTTP:${statusCode} API:${response?.statusCode} `
|
|
241
|
-
+ `message:${response?.message}`);
|
|
235
|
+
await this.errorLog(`Failed to configure webhook. Existing webhook well be overridden. HTTP:${statusCode} API:${response?.statusCode} message:${response?.message}`);
|
|
242
236
|
}
|
|
243
237
|
}
|
|
244
238
|
catch (e) {
|
|
245
|
-
this.errorLog(`Failed to configure webhook. Error: ${e.message}`);
|
|
239
|
+
await this.errorLog(`Failed to configure webhook. Error: ${e.message}`);
|
|
246
240
|
}
|
|
247
241
|
try {
|
|
248
242
|
const { body, statusCode } = await request(updateWebhook, {
|
|
249
|
-
method: 'POST',
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
243
|
+
method: 'POST',
|
|
244
|
+
headers: this.generateHeaders(),
|
|
245
|
+
body: JSON.stringify({
|
|
246
|
+
action: 'updateWebhook',
|
|
247
|
+
config: {
|
|
248
|
+
url,
|
|
249
|
+
enable: true,
|
|
254
250
|
},
|
|
255
251
|
}),
|
|
256
252
|
});
|
|
257
253
|
const response = await body.json();
|
|
258
|
-
await this.debugLog(`updateWebhook: url:${url}`);
|
|
259
|
-
await this.debugLog(`updateWebhook: body:${JSON.stringify(response)}`);
|
|
260
|
-
await this.debugLog(`updateWebhook: statusCode:${statusCode}`);
|
|
254
|
+
await this.debugLog(`updateWebhook: url:${url}, body:${JSON.stringify(response)}, statusCode:${statusCode}`);
|
|
261
255
|
if (statusCode !== 200 || response?.statusCode !== 100) {
|
|
262
|
-
this.errorLog(`Failed to update webhook. HTTP:${statusCode} API:${response?.statusCode} message:${response?.message}`);
|
|
256
|
+
await this.errorLog(`Failed to update webhook. HTTP:${statusCode} API:${response?.statusCode} message:${response?.message}`);
|
|
263
257
|
}
|
|
264
258
|
}
|
|
265
259
|
catch (e) {
|
|
266
|
-
this.errorLog(`Failed to update webhook. Error:${e.message}`);
|
|
260
|
+
await this.errorLog(`Failed to update webhook. Error:${e.message}`);
|
|
267
261
|
}
|
|
268
262
|
try {
|
|
269
263
|
const { body, statusCode } = await request(queryWebhook, {
|
|
270
264
|
method: 'POST',
|
|
271
265
|
headers: this.generateHeaders(),
|
|
272
266
|
body: JSON.stringify({
|
|
273
|
-
|
|
267
|
+
action: 'queryUrl',
|
|
274
268
|
}),
|
|
275
269
|
});
|
|
276
270
|
const response = await body.json();
|
|
277
271
|
await this.debugLog(`queryWebhook: body:${JSON.stringify(response)}`);
|
|
278
272
|
await this.debugLog(`queryWebhook: statusCode:${statusCode}`);
|
|
279
273
|
if (statusCode !== 200 || response?.statusCode !== 100) {
|
|
280
|
-
this.errorLog(`Failed to query webhook. HTTP:${statusCode} API:${response?.statusCode} message:${response?.message}`);
|
|
274
|
+
await this.errorLog(`Failed to query webhook. HTTP:${statusCode} API:${response?.statusCode} message:${response?.message}`);
|
|
281
275
|
}
|
|
282
276
|
else {
|
|
283
|
-
this.infoLog(`Listening webhook on ${response?.body?.urls[0]}`);
|
|
277
|
+
await this.infoLog(`Listening webhook on ${response?.body?.urls[0]}`);
|
|
284
278
|
}
|
|
285
279
|
}
|
|
286
280
|
catch (e) {
|
|
287
|
-
this.errorLog(`Failed to query webhook. Error:${e}`);
|
|
281
|
+
await this.errorLog(`Failed to query webhook. Error:${e}`);
|
|
288
282
|
}
|
|
289
283
|
this.api.on('shutdown', async () => {
|
|
290
284
|
try {
|
|
@@ -292,21 +286,21 @@ export class SwitchBotPlatform {
|
|
|
292
286
|
method: 'POST',
|
|
293
287
|
headers: this.generateHeaders(),
|
|
294
288
|
body: JSON.stringify({
|
|
295
|
-
|
|
296
|
-
|
|
289
|
+
action: 'deleteWebhook',
|
|
290
|
+
url,
|
|
297
291
|
}),
|
|
298
292
|
});
|
|
299
293
|
const response = await body.json();
|
|
300
294
|
await this.debugLog(`deleteWebhook: url:${url}, body:${JSON.stringify(response)}, statusCode:${statusCode}`);
|
|
301
295
|
if (statusCode !== 200 || response?.statusCode !== 100) {
|
|
302
|
-
this.errorLog(`Failed to delete webhook. HTTP:${statusCode} API:${response?.statusCode} message:${response?.message}`);
|
|
296
|
+
await this.errorLog(`Failed to delete webhook. HTTP:${statusCode} API:${response?.statusCode} message:${response?.message}`);
|
|
303
297
|
}
|
|
304
298
|
else {
|
|
305
|
-
this.infoLog('Unregistered webhook to close listening.');
|
|
299
|
+
await this.infoLog('Unregistered webhook to close listening.');
|
|
306
300
|
}
|
|
307
301
|
}
|
|
308
302
|
catch (e) {
|
|
309
|
-
this.errorLog(`Failed to delete webhook. Error:${e.message}`);
|
|
303
|
+
await this.errorLog(`Failed to delete webhook. Error:${e.message}`);
|
|
310
304
|
}
|
|
311
305
|
});
|
|
312
306
|
}
|
|
@@ -314,7 +308,6 @@ export class SwitchBotPlatform {
|
|
|
314
308
|
async setupBlE() {
|
|
315
309
|
if (this.config.options?.BLE) {
|
|
316
310
|
await this.debugLog('setupBLE');
|
|
317
|
-
const SwitchBot = (await import('node-switchbot')).SwitchBot;
|
|
318
311
|
const switchbot = new SwitchBot();
|
|
319
312
|
if (switchbot === undefined) {
|
|
320
313
|
await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
|
|
@@ -338,10 +331,10 @@ export class SwitchBotPlatform {
|
|
|
338
331
|
this.api.on('shutdown', async () => {
|
|
339
332
|
try {
|
|
340
333
|
switchbot.stopScan();
|
|
341
|
-
this.infoLog('Stopped BLE scanning to close listening.');
|
|
334
|
+
await this.infoLog('Stopped BLE scanning to close listening.');
|
|
342
335
|
}
|
|
343
336
|
catch (e) {
|
|
344
|
-
this.errorLog(`Failed to stop Platform BLE scanning. Error:${e.message}`);
|
|
337
|
+
await this.errorLog(`Failed to stop Platform BLE scanning. Error:${e.message}`);
|
|
345
338
|
}
|
|
346
339
|
});
|
|
347
340
|
}
|
|
@@ -355,7 +348,8 @@ export class SwitchBotPlatform {
|
|
|
355
348
|
* It should be used to setup event handlers for characteristics and update respective values.
|
|
356
349
|
*/
|
|
357
350
|
async configureAccessory(accessory) {
|
|
358
|
-
|
|
351
|
+
const { displayName } = accessory;
|
|
352
|
+
await this.debugLog(`Loading accessory from cache: ${displayName}`);
|
|
359
353
|
// add the restored accessory to the accessories cache so we can track if it has already been registered
|
|
360
354
|
this.accessories.push(accessory);
|
|
361
355
|
}
|
|
@@ -363,18 +357,18 @@ export class SwitchBotPlatform {
|
|
|
363
357
|
* Verify the config passed to the plugin is valid
|
|
364
358
|
*/
|
|
365
359
|
async verifyConfig() {
|
|
366
|
-
this.debugLog('Verifying Config');
|
|
360
|
+
await this.debugLog('Verifying Config');
|
|
367
361
|
this.config = this.config || {};
|
|
368
362
|
this.config.options = this.config.options || {};
|
|
369
363
|
const platformConfig = {};
|
|
370
364
|
if (this.config.options.logging) {
|
|
371
|
-
platformConfig
|
|
365
|
+
platformConfig.logging = this.config.options.logging;
|
|
372
366
|
}
|
|
373
367
|
if (this.config.options.logging && this.config.options.refreshRate) {
|
|
374
|
-
platformConfig
|
|
368
|
+
platformConfig.refreshRate = this.config.options.refreshRate;
|
|
375
369
|
}
|
|
376
370
|
if (this.config.options.logging && this.config.options.pushRate) {
|
|
377
|
-
platformConfig
|
|
371
|
+
platformConfig.pushRate = this.config.options.pushRate;
|
|
378
372
|
}
|
|
379
373
|
if (Object.entries(platformConfig).length !== 0) {
|
|
380
374
|
await this.debugWarnLog(`Platform Config: ${JSON.stringify(platformConfig)}`);
|
|
@@ -398,10 +392,10 @@ export class SwitchBotPlatform {
|
|
|
398
392
|
for (const irDeviceConfig of this.config.options.irdevices) {
|
|
399
393
|
if (!irDeviceConfig.hide_device) {
|
|
400
394
|
if (!irDeviceConfig.deviceId) {
|
|
401
|
-
this.errorLog('The devices config section is missing the *Device ID* in the config. Please check your config.');
|
|
395
|
+
await this.errorLog('The devices config section is missing the *Device ID* in the config. Please check your config.');
|
|
402
396
|
}
|
|
403
397
|
if (!irDeviceConfig.deviceId && !irDeviceConfig.configRemoteType) {
|
|
404
|
-
this.errorLog('The devices config section is missing the *Device Type* in the config. Please check your config.');
|
|
398
|
+
await this.errorLog('The devices config section is missing the *Device Type* in the config. Please check your config.');
|
|
405
399
|
}
|
|
406
400
|
}
|
|
407
401
|
}
|
|
@@ -413,16 +407,16 @@ export class SwitchBotPlatform {
|
|
|
413
407
|
if (!this.config.options.refreshRate) {
|
|
414
408
|
// default 120 seconds (2 minutes)
|
|
415
409
|
this.config.options.refreshRate = 120;
|
|
416
|
-
this.debugWarnLog('Using Default Refresh Rate (2 minutes).');
|
|
410
|
+
await this.debugWarnLog('Using Default Refresh Rate (2 minutes).');
|
|
417
411
|
}
|
|
418
412
|
if (!this.config.options.pushRate) {
|
|
419
413
|
// default 100 milliseconds
|
|
420
414
|
this.config.options.pushRate = 0.1;
|
|
421
|
-
this.debugWarnLog('Using Default Push Rate.');
|
|
415
|
+
await this.debugWarnLog('Using Default Push Rate.');
|
|
422
416
|
}
|
|
423
417
|
if (!this.config.options.maxRetries) {
|
|
424
418
|
this.config.options.maxRetries = 5;
|
|
425
|
-
this.debugWarnLog('Using Default Max Retries.');
|
|
419
|
+
await this.debugWarnLog('Using Default Max Retries.');
|
|
426
420
|
}
|
|
427
421
|
else {
|
|
428
422
|
this.maxRetries = this.config.options.maxRetries;
|
|
@@ -430,23 +424,23 @@ export class SwitchBotPlatform {
|
|
|
430
424
|
if (!this.config.options.delayBetweenRetries) {
|
|
431
425
|
// default 3 seconds
|
|
432
426
|
this.config.options.delayBetweenRetries = 3000;
|
|
433
|
-
this.debugWarnLog('Using Default Delay Between Retries.');
|
|
427
|
+
await this.debugWarnLog('Using Default Delay Between Retries.');
|
|
434
428
|
}
|
|
435
429
|
else {
|
|
436
430
|
this.delayBetweenRetries = this.config.options.delayBetweenRetries * 1000;
|
|
437
431
|
}
|
|
438
432
|
if (!this.config.credentials && !this.config.options) {
|
|
439
|
-
this.debugWarnLog('Missing Credentials');
|
|
433
|
+
await this.debugWarnLog('Missing Credentials');
|
|
440
434
|
}
|
|
441
435
|
else if (this.config.credentials && !this.config.credentials.notice) {
|
|
442
436
|
if (!this.config.credentials?.token) {
|
|
443
|
-
this.debugErrorLog('Missing token');
|
|
444
|
-
this.debugWarnLog('Cloud Enabled SwitchBot Devices & IR Devices will not work');
|
|
437
|
+
await this.debugErrorLog('Missing token');
|
|
438
|
+
await this.debugWarnLog('Cloud Enabled SwitchBot Devices & IR Devices will not work');
|
|
445
439
|
}
|
|
446
440
|
if (this.config.credentials?.token) {
|
|
447
441
|
if (!this.config.credentials?.secret) {
|
|
448
|
-
this.debugErrorLog('Missing secret');
|
|
449
|
-
this.debugWarnLog('Cloud Enabled SwitchBot Devices & IR Devices will not work');
|
|
442
|
+
await this.debugErrorLog('Missing secret');
|
|
443
|
+
await this.debugWarnLog('Cloud Enabled SwitchBot Devices & IR Devices will not work');
|
|
450
444
|
}
|
|
451
445
|
}
|
|
452
446
|
}
|
|
@@ -454,7 +448,6 @@ export class SwitchBotPlatform {
|
|
|
454
448
|
/**
|
|
455
449
|
* The openToken was old config.
|
|
456
450
|
* This method saves the openToken as the token in the config.json file
|
|
457
|
-
* @param this.config.credentials.openToken
|
|
458
451
|
*/
|
|
459
452
|
async updateToken() {
|
|
460
453
|
try {
|
|
@@ -466,7 +459,7 @@ export class SwitchBotPlatform {
|
|
|
466
459
|
const currentConfig = JSON.parse(readFileSync(this.api.user.configPath(), 'utf8'));
|
|
467
460
|
// check the platforms section is an array before we do array things on it
|
|
468
461
|
if (!Array.isArray(currentConfig.platforms)) {
|
|
469
|
-
throw new
|
|
462
|
+
throw new TypeError('Cannot find platforms array in config');
|
|
470
463
|
}
|
|
471
464
|
// find this plugins current config
|
|
472
465
|
const pluginConfig = currentConfig.platforms.find((x) => x.platform === PLATFORM_NAME);
|
|
@@ -475,17 +468,15 @@ export class SwitchBotPlatform {
|
|
|
475
468
|
}
|
|
476
469
|
// check the .credentials is an object before doing object things with it
|
|
477
470
|
if (typeof pluginConfig.credentials !== 'object') {
|
|
478
|
-
throw new
|
|
471
|
+
throw new TypeError('pluginConfig.credentials is not an object');
|
|
479
472
|
}
|
|
480
473
|
// Move openToken to token
|
|
481
474
|
if (!this.config.credentials.secret) {
|
|
482
|
-
this.warnLog('This plugin has been updated to use OpenAPI v1.1, config is set with openToken,'
|
|
483
|
-
+ ' "openToken" cconfig has been moved to the "token" config');
|
|
475
|
+
await this.warnLog('This plugin has been updated to use OpenAPI v1.1, config is set with openToken, "openToken" cconfig has been moved to the "token" config');
|
|
484
476
|
this.errorLog('"secret" config is not populated, you must populate then please restart Homebridge.');
|
|
485
477
|
}
|
|
486
478
|
else {
|
|
487
|
-
this.warnLog('This plugin has been updated to use OpenAPI v1.1, config is set with openToken, '
|
|
488
|
-
+ '"openToken" config has been moved to the "token" config, please restart Homebridge.');
|
|
479
|
+
await this.warnLog('This plugin has been updated to use OpenAPI v1.1, config is set with openToken, "openToken" config has been moved to the "token" config, please restart Homebridge.');
|
|
489
480
|
}
|
|
490
481
|
// set the refresh token
|
|
491
482
|
pluginConfig.credentials.token = this.config.credentials?.openToken;
|
|
@@ -495,10 +486,10 @@ export class SwitchBotPlatform {
|
|
|
495
486
|
await this.debugWarnLog(`token: ${pluginConfig.credentials.token}`);
|
|
496
487
|
// save the config, ensuring we maintain pretty json
|
|
497
488
|
writeFileSync(this.api.user.configPath(), JSON.stringify(currentConfig, null, 4));
|
|
498
|
-
this.verifyConfig();
|
|
489
|
+
await this.verifyConfig();
|
|
499
490
|
}
|
|
500
491
|
catch (e) {
|
|
501
|
-
this.errorLog(`Update Token: ${e}`);
|
|
492
|
+
await this.errorLog(`Update Token: ${e}`);
|
|
502
493
|
}
|
|
503
494
|
}
|
|
504
495
|
generateHeaders = () => {
|
|
@@ -511,340 +502,228 @@ export class SwitchBotPlatform {
|
|
|
511
502
|
.digest();
|
|
512
503
|
const sign = signTerm.toString('base64');
|
|
513
504
|
return {
|
|
514
|
-
Authorization: this.config.credentials?.token,
|
|
515
|
-
sign: sign,
|
|
516
|
-
nonce: nonce,
|
|
517
|
-
t: t,
|
|
505
|
+
'Authorization': this.config.credentials?.token,
|
|
506
|
+
'sign': sign,
|
|
507
|
+
'nonce': nonce,
|
|
508
|
+
't': t,
|
|
518
509
|
'Content-Type': 'application/json',
|
|
519
510
|
};
|
|
520
511
|
};
|
|
521
|
-
/**
|
|
522
|
-
* this method discovers devices
|
|
523
|
-
*
|
|
524
|
-
const t = `${Date.now()}`;
|
|
525
|
-
const nonce = 'requestID';
|
|
526
|
-
const data = this.config.credentials?.token + t + nonce;
|
|
527
|
-
const signTerm = crypto.createHmac('sha256', this.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
528
|
-
const sign = signTerm.toString('base64');
|
|
529
|
-
*/
|
|
530
512
|
async discoverDevices() {
|
|
531
|
-
if (this.config.credentials?.token) {
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
await this.
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
// SwitchBot Devices
|
|
551
|
-
const deviceLists = devicesAPI.body.deviceList;
|
|
552
|
-
await this.debugWarnLog(`DeviceLists: ${JSON.stringify(deviceLists)}`);
|
|
553
|
-
await this.debugWarnLog(`DeviceLists Length: ${deviceLists.length}`);
|
|
554
|
-
if (!this.config.options?.devices) {
|
|
555
|
-
await this.debugLog(`SwitchBot Device Config Not Set: ${JSON.stringify(this.config.options?.devices)}`);
|
|
556
|
-
if (deviceLists.length === 0) {
|
|
557
|
-
await this.debugLog(`SwitchBot API Has No Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
|
|
558
|
-
}
|
|
559
|
-
else {
|
|
560
|
-
const devices = deviceLists.map((v) => v);
|
|
561
|
-
for (const device of devices) {
|
|
562
|
-
if (device.deviceType) {
|
|
563
|
-
if (device.configDeviceName) {
|
|
564
|
-
device.deviceName = device.configDeviceName;
|
|
565
|
-
}
|
|
566
|
-
this.createDevice(device);
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
else if (this.config.credentials?.token && this.config.options.devices) {
|
|
572
|
-
await this.debugLog(`SwitchBot Device Config Set: ${JSON.stringify(this.config.options?.devices)}`);
|
|
573
|
-
if (deviceLists.length === 0) {
|
|
574
|
-
await this.debugLog(`SwitchBot API Has No Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
|
|
575
|
-
}
|
|
576
|
-
else {
|
|
577
|
-
const deviceConfigs = this.config.options?.devices;
|
|
578
|
-
const mergeBydeviceId = (a1, a2) => a1.map((itm) => ({
|
|
579
|
-
...a2.find((item) => item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item),
|
|
580
|
-
...itm,
|
|
581
|
-
}));
|
|
582
|
-
const devices = mergeBydeviceId(deviceLists, deviceConfigs);
|
|
583
|
-
await this.debugLog(`SwitchBot Devices: ${JSON.stringify(devices)}`);
|
|
584
|
-
for (const device of devices) {
|
|
585
|
-
if (!device.deviceType) {
|
|
586
|
-
device.deviceType = device.configDeviceType;
|
|
587
|
-
this.errorLog(`API has displaying no deviceType: ${device.deviceType}, So using configDeviceType: ${device.configDeviceType}`);
|
|
588
|
-
}
|
|
589
|
-
if (device.deviceType) {
|
|
590
|
-
if (device.configDeviceName) {
|
|
591
|
-
device.deviceName = device.configDeviceName;
|
|
592
|
-
}
|
|
593
|
-
this.createDevice(device);
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
else {
|
|
599
|
-
this.errorLog('SwitchBot Token Supplied, Issue with Auth.');
|
|
600
|
-
}
|
|
601
|
-
if (devicesAPI.body.deviceList.length !== 0) {
|
|
602
|
-
this.infoLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
|
|
603
|
-
}
|
|
604
|
-
else {
|
|
605
|
-
await this.debugLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
|
|
606
|
-
}
|
|
607
|
-
// IR Devices
|
|
608
|
-
const irDeviceLists = devicesAPI.body.infraredRemoteList;
|
|
609
|
-
if (!this.config.options?.irdevices) {
|
|
610
|
-
await this.debugLog(`IR Device Config Not Set: ${JSON.stringify(this.config.options?.irdevices)}`);
|
|
611
|
-
const devices = irDeviceLists.map((v) => v);
|
|
612
|
-
for (const device of devices) {
|
|
613
|
-
if (device.remoteType) {
|
|
614
|
-
this.createIRDevice(device);
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
else {
|
|
619
|
-
await this.debugLog(`IR Device Config Set: ${JSON.stringify(this.config.options?.irdevices)}`);
|
|
620
|
-
const irDeviceConfig = this.config.options?.irdevices;
|
|
621
|
-
const mergeIRBydeviceId = (a1, a2) => a1.map((itm) => ({
|
|
622
|
-
...a2.find((item) => item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item),
|
|
623
|
-
...itm,
|
|
624
|
-
}));
|
|
625
|
-
const devices = mergeIRBydeviceId(irDeviceLists, irDeviceConfig);
|
|
626
|
-
await this.debugLog(`IR Devices: ${JSON.stringify(devices)}`);
|
|
627
|
-
for (const device of devices) {
|
|
628
|
-
this.createIRDevice(device);
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
if (devicesAPI.body.infraredRemoteList.length !== 0) {
|
|
632
|
-
this.infoLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
|
|
633
|
-
}
|
|
634
|
-
else {
|
|
635
|
-
await this.debugLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
|
|
636
|
-
}
|
|
637
|
-
break;
|
|
638
|
-
}
|
|
639
|
-
else {
|
|
640
|
-
this.statusCode(statusCode);
|
|
641
|
-
this.statusCode(devicesAPI.statusCode);
|
|
642
|
-
if (statusCode === 500) {
|
|
643
|
-
retryCount++;
|
|
644
|
-
this.infoLog(`statusCode: ${statusCode} Attempt ${retryCount} of ${maxRetries}`);
|
|
645
|
-
await sleep(delayBetweenRetries);
|
|
646
|
-
}
|
|
647
|
-
}
|
|
513
|
+
if (!this.config.credentials?.token) {
|
|
514
|
+
return this.handleManualConfig();
|
|
515
|
+
}
|
|
516
|
+
let retryCount = 0;
|
|
517
|
+
const maxRetries = this.maxRetries;
|
|
518
|
+
const delayBetweenRetries = this.delayBetweenRetries;
|
|
519
|
+
await this.debugWarnLog(`Retry Count: ${retryCount}`);
|
|
520
|
+
await this.debugWarnLog(`Max Retries: ${maxRetries}`);
|
|
521
|
+
await this.debugWarnLog(`Delay Between Retries: ${delayBetweenRetries}`);
|
|
522
|
+
while (retryCount < maxRetries) {
|
|
523
|
+
try {
|
|
524
|
+
const { body, statusCode } = await request(Devices, { headers: this.generateHeaders() });
|
|
525
|
+
await this.debugWarnLog(`statusCode: ${statusCode}`);
|
|
526
|
+
const devicesAPI = await body.json();
|
|
527
|
+
await this.debugWarnLog(`devicesAPI: ${JSON.stringify(devicesAPI)}`);
|
|
528
|
+
if (this.isSuccessfulResponse(statusCode, devicesAPI.statusCode)) {
|
|
529
|
+
await this.handleDevices(devicesAPI.body.deviceList);
|
|
530
|
+
await this.handleIRDevices(devicesAPI.body.infraredRemoteList);
|
|
531
|
+
break;
|
|
648
532
|
}
|
|
649
|
-
|
|
533
|
+
else {
|
|
534
|
+
await this.handleErrorResponse(statusCode, devicesAPI.statusCode, retryCount, maxRetries, delayBetweenRetries);
|
|
650
535
|
retryCount++;
|
|
651
|
-
this.debugErrorLog(`Failed to Discover Devices, Error Message: ${JSON.stringify(e.message)}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug');
|
|
652
|
-
await this.debugErrorLog(`Failed to Discover Devices, Error: ${e}`);
|
|
653
536
|
}
|
|
654
537
|
}
|
|
538
|
+
catch (e) {
|
|
539
|
+
retryCount++;
|
|
540
|
+
await this.debugErrorLog(`Failed to Discover Devices, Error Message: ${JSON.stringify(e.message)}, Submit Bugs Here: https://tinyurl.com/SwitchBotBug`);
|
|
541
|
+
await this.debugErrorLog(`Failed to Discover Devices, Error: ${e}`);
|
|
542
|
+
}
|
|
655
543
|
}
|
|
656
|
-
|
|
544
|
+
}
|
|
545
|
+
async handleManualConfig() {
|
|
546
|
+
if (this.config.options?.devices) {
|
|
657
547
|
await this.debugLog(`SwitchBot Device Manual Config Set: ${JSON.stringify(this.config.options?.devices)}`);
|
|
658
|
-
const
|
|
659
|
-
const devices = deviceConfigs.map((v) => v);
|
|
548
|
+
const devices = this.config.options.devices.map((v) => v);
|
|
660
549
|
for (const device of devices) {
|
|
661
550
|
device.deviceType = device.configDeviceType;
|
|
662
551
|
device.deviceName = device.configDeviceName;
|
|
663
552
|
if (device.deviceType) {
|
|
664
|
-
this.createDevice(device);
|
|
553
|
+
await this.createDevice(device);
|
|
665
554
|
}
|
|
666
555
|
}
|
|
667
556
|
}
|
|
668
557
|
else {
|
|
669
|
-
this.errorLog('Neither SwitchBot Token or Device Config are
|
|
558
|
+
await this.errorLog('Neither SwitchBot Token or Device Config are set.');
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
isSuccessfulResponse(statusCode, apiStatusCode) {
|
|
562
|
+
return (statusCode === 200 || statusCode === 100) && (apiStatusCode === 200 || apiStatusCode === 100);
|
|
563
|
+
}
|
|
564
|
+
async handleDevices(deviceLists) {
|
|
565
|
+
if (!this.config.options?.devices) {
|
|
566
|
+
await this.debugLog(`SwitchBot Device Config Not Set: ${JSON.stringify(this.config.options?.devices)}`);
|
|
567
|
+
if (deviceLists.length === 0) {
|
|
568
|
+
await this.debugLog('SwitchBot API Has No Devices With Cloud Services Enabled');
|
|
569
|
+
}
|
|
570
|
+
else {
|
|
571
|
+
for (const device of deviceLists) {
|
|
572
|
+
if (device.deviceType) {
|
|
573
|
+
if (device.configDeviceName) {
|
|
574
|
+
device.deviceName = device.configDeviceName;
|
|
575
|
+
}
|
|
576
|
+
await this.createDevice(device);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
else {
|
|
582
|
+
await this.debugLog(`SwitchBot Device Config Set: ${JSON.stringify(this.config.options?.devices)}`);
|
|
583
|
+
const devices = this.mergeByDeviceId(deviceLists, this.config.options.devices);
|
|
584
|
+
await this.debugLog(`SwitchBot Devices: ${JSON.stringify(devices)}`);
|
|
585
|
+
for (const device of devices) {
|
|
586
|
+
if (!device.deviceType && device.configDeviceType) {
|
|
587
|
+
device.deviceType = device.configDeviceType;
|
|
588
|
+
await this.warnLog(`API is displaying no deviceType: ${device.deviceType}, So using configDeviceType: ${device.configDeviceType}`);
|
|
589
|
+
}
|
|
590
|
+
else if (!device.deviceType && !device.configDeviceName) {
|
|
591
|
+
await this.errorLog('No deviceType or configDeviceType for device. No device will be created.');
|
|
592
|
+
}
|
|
593
|
+
if (device.deviceType) {
|
|
594
|
+
if (device.configDeviceName) {
|
|
595
|
+
device.deviceName = device.configDeviceName;
|
|
596
|
+
}
|
|
597
|
+
await this.createDevice(device);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
async handleIRDevices(irDeviceLists) {
|
|
603
|
+
if (!this.config.options?.irdevices) {
|
|
604
|
+
await this.debugLog(`IR Device Config Not Set: ${JSON.stringify(this.config.options?.irdevices)}`);
|
|
605
|
+
for (const device of irDeviceLists) {
|
|
606
|
+
if (device.remoteType) {
|
|
607
|
+
await this.createIRDevice(device);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
else {
|
|
612
|
+
await this.debugLog(`IR Device Config Set: ${JSON.stringify(this.config.options?.irdevices)}`);
|
|
613
|
+
const devices = this.mergeByDeviceId(irDeviceLists, this.config.options.irdevices);
|
|
614
|
+
await this.debugLog(`IR Devices: ${JSON.stringify(devices)}`);
|
|
615
|
+
for (const device of devices) {
|
|
616
|
+
await this.createIRDevice(device);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
mergeByDeviceId(a1, a2) {
|
|
621
|
+
const normalizeDeviceId = (deviceId) => deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '');
|
|
622
|
+
return a1.map((itm) => {
|
|
623
|
+
const matchingItem = a2.find(item => normalizeDeviceId(item.deviceId) === normalizeDeviceId(itm.deviceId));
|
|
624
|
+
return { ...matchingItem, ...itm };
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
async handleErrorResponse(statusCode, apiStatusCode, retryCount, maxRetries, delayBetweenRetries) {
|
|
628
|
+
await this.statusCode(statusCode);
|
|
629
|
+
await this.statusCode(apiStatusCode);
|
|
630
|
+
if (statusCode === 500) {
|
|
631
|
+
this.infoLog(`statusCode: ${statusCode} Attempt ${retryCount + 1} of ${maxRetries}`);
|
|
632
|
+
await sleep(delayBetweenRetries);
|
|
670
633
|
}
|
|
671
634
|
}
|
|
672
635
|
async createDevice(device) {
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
this.createContact(device);
|
|
716
|
-
break;
|
|
717
|
-
case 'Curtain':
|
|
718
|
-
case 'Curtain3':
|
|
719
|
-
await this.debugLog(`Discovered ${device.deviceType} ${device.deviceName}: ${device.deviceId}`);
|
|
720
|
-
this.createCurtain(device);
|
|
721
|
-
break;
|
|
722
|
-
case 'Blind Tilt':
|
|
723
|
-
await this.debugLog(`Discovered ${device.deviceType} ${device.deviceName}: ${device.deviceId}`);
|
|
724
|
-
this.createBlindTilt(device);
|
|
725
|
-
break;
|
|
726
|
-
case 'Plug':
|
|
727
|
-
case 'Plug Mini (US)':
|
|
728
|
-
case 'Plug Mini (JP)':
|
|
729
|
-
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
|
|
730
|
-
this.createPlug(device);
|
|
731
|
-
break;
|
|
732
|
-
case 'Smart Lock':
|
|
733
|
-
case 'Smart Lock Pro':
|
|
734
|
-
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
|
|
735
|
-
this.createLock(device);
|
|
736
|
-
break;
|
|
737
|
-
case 'Color Bulb':
|
|
738
|
-
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
|
|
739
|
-
this.createColorBulb(device);
|
|
740
|
-
break;
|
|
741
|
-
case 'K10+':
|
|
742
|
-
case 'WoSweeper':
|
|
743
|
-
case 'WoSweeperMini':
|
|
744
|
-
case 'Robot Vacuum Cleaner S1':
|
|
745
|
-
case 'Robot Vacuum Cleaner S1 Plus':
|
|
746
|
-
case 'Robot Vacuum Cleaner S10':
|
|
747
|
-
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
|
|
748
|
-
this.createRobotVacuumCleaner(device);
|
|
749
|
-
break;
|
|
750
|
-
case 'Ceiling Light':
|
|
751
|
-
case 'Ceiling Light Pro':
|
|
752
|
-
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
|
|
753
|
-
this.createCeilingLight(device);
|
|
754
|
-
break;
|
|
755
|
-
case 'Strip Light':
|
|
756
|
-
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
|
|
757
|
-
this.createStripLight(device);
|
|
758
|
-
break;
|
|
759
|
-
case 'Battery Circulator Fan':
|
|
760
|
-
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
|
|
761
|
-
this.createFan(device);
|
|
762
|
-
break;
|
|
763
|
-
case 'Remote':
|
|
764
|
-
case 'Indoor Cam':
|
|
765
|
-
case 'remote with screen+':
|
|
766
|
-
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}, is currently not supported, device: ${JSON.stringify(device)}`);
|
|
767
|
-
break;
|
|
768
|
-
default:
|
|
769
|
-
this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported.`, +`Submit Feature Requests Here: https://tinyurl.com/SwitchBotFeatureRequest, device: ${JSON.stringify(device)}`);
|
|
636
|
+
const deviceTypeHandlers = {
|
|
637
|
+
'Humidifier': this.createHumidifier.bind(this),
|
|
638
|
+
'Hub 2': this.createHub2.bind(this),
|
|
639
|
+
'Bot': this.createBot.bind(this),
|
|
640
|
+
'Meter': this.createMeter.bind(this),
|
|
641
|
+
'MeterPlus': this.createMeterPlus.bind(this),
|
|
642
|
+
'Meter Plus (JP)': this.createMeterPlus.bind(this),
|
|
643
|
+
'WoIOSensor': this.createIOSensor.bind(this),
|
|
644
|
+
'Water Detector': this.createWaterDetector.bind(this),
|
|
645
|
+
'Motion Sensor': this.createMotion.bind(this),
|
|
646
|
+
'Contact Sensor': this.createContact.bind(this),
|
|
647
|
+
'Curtain': this.createCurtain.bind(this),
|
|
648
|
+
'Curtain3': this.createCurtain.bind(this),
|
|
649
|
+
'WoRollerShade': this.createCurtain.bind(this),
|
|
650
|
+
'Roller Shade': this.createCurtain.bind(this),
|
|
651
|
+
'Blind Tilt': this.createBlindTilt.bind(this),
|
|
652
|
+
'Plug': this.createPlug.bind(this),
|
|
653
|
+
'Plug Mini (US)': this.createPlug.bind(this),
|
|
654
|
+
'Plug Mini (JP)': this.createPlug.bind(this),
|
|
655
|
+
'Smart Lock': this.createLock.bind(this),
|
|
656
|
+
'Smart Lock Pro': this.createLock.bind(this),
|
|
657
|
+
'Color Bulb': this.createColorBulb.bind(this),
|
|
658
|
+
'K10+': this.createRobotVacuumCleaner.bind(this),
|
|
659
|
+
'WoSweeper': this.createRobotVacuumCleaner.bind(this),
|
|
660
|
+
'WoSweeperMini': this.createRobotVacuumCleaner.bind(this),
|
|
661
|
+
'Robot Vacuum Cleaner S1': this.createRobotVacuumCleaner.bind(this),
|
|
662
|
+
'Robot Vacuum Cleaner S1 Plus': this.createRobotVacuumCleaner.bind(this),
|
|
663
|
+
'Robot Vacuum Cleaner S10': this.createRobotVacuumCleaner.bind(this),
|
|
664
|
+
'Ceiling Light': this.createCeilingLight.bind(this),
|
|
665
|
+
'Ceiling Light Pro': this.createCeilingLight.bind(this),
|
|
666
|
+
'Strip Light': this.createStripLight.bind(this),
|
|
667
|
+
'Battery Circulator Fan': this.createFan.bind(this),
|
|
668
|
+
};
|
|
669
|
+
if (deviceTypeHandlers[device.deviceType]) {
|
|
670
|
+
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
|
|
671
|
+
await deviceTypeHandlers[device.deviceType](device);
|
|
672
|
+
}
|
|
673
|
+
else if (['Hub Mini', 'Hub Plus', 'Remote', 'Indoor Cam', 'remote with screen'].includes(device.deviceType)) {
|
|
674
|
+
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}, is currently not supported, device: ${JSON.stringify(device)}`);
|
|
675
|
+
}
|
|
676
|
+
else {
|
|
677
|
+
await this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported. Submit Feature Requests Here: https://tinyurl.com/SwitchBotFeatureRequest, device: ${JSON.stringify(device)}`);
|
|
770
678
|
}
|
|
771
679
|
}
|
|
772
680
|
async createIRDevice(device) {
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
break;
|
|
813
|
-
case 'Air Purifier':
|
|
814
|
-
case 'DIY Air Purifier':
|
|
815
|
-
await this.debugLog(`Discovered ${device.remoteType}: ${device.deviceId}`);
|
|
816
|
-
this.createAirPurifier(device);
|
|
817
|
-
break;
|
|
818
|
-
case 'Water Heater':
|
|
819
|
-
case 'DIY Water Heater':
|
|
820
|
-
await this.debugLog(`Discovered ${device.remoteType}: ${device.deviceId}`);
|
|
821
|
-
this.createWaterHeater(device);
|
|
822
|
-
break;
|
|
823
|
-
case 'Vacuum Cleaner':
|
|
824
|
-
case 'DIY Vacuum Cleaner':
|
|
825
|
-
await this.debugLog(`Discovered ${device.remoteType}: ${device.deviceId}`);
|
|
826
|
-
this.createVacuumCleaner(device);
|
|
827
|
-
break;
|
|
828
|
-
case 'Camera':
|
|
829
|
-
case 'DIY Camera':
|
|
830
|
-
await this.debugLog(`Discovered ${device.remoteType}: ${device.deviceId}`);
|
|
831
|
-
this.createCamera(device);
|
|
832
|
-
break;
|
|
833
|
-
case 'Others':
|
|
834
|
-
await this.debugLog(`Discovered ${device.remoteType}: ${device.deviceId}`);
|
|
835
|
-
this.createOthers(device);
|
|
836
|
-
break;
|
|
837
|
-
default:
|
|
838
|
-
await this.debugLog(`Unsupported Device: ${JSON.stringify(device)}`);
|
|
839
|
-
this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.remoteType}, is currently not supported.`);
|
|
840
|
-
this.warnLog('Submit Feature Requests Here: ' + 'https://tinyurl.com/SwitchBotFeatureRequest');
|
|
681
|
+
device.connectionType = device.connectionType ?? 'OpenAPI';
|
|
682
|
+
const deviceTypeHandlers = {
|
|
683
|
+
'TV': this.createTV.bind(this),
|
|
684
|
+
'DIY TV': this.createTV.bind(this),
|
|
685
|
+
'Projector': this.createTV.bind(this),
|
|
686
|
+
'DIY Projector': this.createTV.bind(this),
|
|
687
|
+
'Set Top Box': this.createTV.bind(this),
|
|
688
|
+
'DIY Set Top Box': this.createTV.bind(this),
|
|
689
|
+
'IPTV': this.createTV.bind(this),
|
|
690
|
+
'DIY IPTV': this.createTV.bind(this),
|
|
691
|
+
'DVD': this.createTV.bind(this),
|
|
692
|
+
'DIY DVD': this.createTV.bind(this),
|
|
693
|
+
'Speaker': this.createTV.bind(this),
|
|
694
|
+
'DIY Speaker': this.createTV.bind(this),
|
|
695
|
+
'Fan': this.createIRFan.bind(this),
|
|
696
|
+
'DIY Fan': this.createIRFan.bind(this),
|
|
697
|
+
'Air Conditioner': this.createAirConditioner.bind(this),
|
|
698
|
+
'DIY Air Conditioner': this.createAirConditioner.bind(this),
|
|
699
|
+
'Light': this.createLight.bind(this),
|
|
700
|
+
'DIY Light': this.createLight.bind(this),
|
|
701
|
+
'Air Purifier': this.createAirPurifier.bind(this),
|
|
702
|
+
'DIY Air Purifier': this.createAirPurifier.bind(this),
|
|
703
|
+
'Water Heater': this.createWaterHeater.bind(this),
|
|
704
|
+
'DIY Water Heater': this.createWaterHeater.bind(this),
|
|
705
|
+
'Vacuum Cleaner': this.createVacuumCleaner.bind(this),
|
|
706
|
+
'DIY Vacuum Cleaner': this.createVacuumCleaner.bind(this),
|
|
707
|
+
'Camera': this.createCamera.bind(this),
|
|
708
|
+
'DIY Camera': this.createCamera.bind(this),
|
|
709
|
+
'Others': this.createOthers.bind(this),
|
|
710
|
+
};
|
|
711
|
+
if (deviceTypeHandlers[device.remoteType]) {
|
|
712
|
+
await this.debugLog(`Discovered ${device.remoteType}: ${device.deviceId}`);
|
|
713
|
+
if (device.remoteType.startsWith('DIY') && device.external === undefined) {
|
|
714
|
+
device.external = true;
|
|
715
|
+
}
|
|
716
|
+
await deviceTypeHandlers[device.remoteType](device);
|
|
717
|
+
}
|
|
718
|
+
else {
|
|
719
|
+
await this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.remoteType}, is currently not supported. Submit Feature Requests Here: https://tinyurl.com/SwitchBotFeatureRequest, device: ${JSON.stringify(device)}`);
|
|
841
720
|
}
|
|
842
721
|
}
|
|
843
722
|
async createHumidifier(device) {
|
|
844
723
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
845
724
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
846
725
|
// the cached devices we stored in the `configureAccessory` method above
|
|
847
|
-
const existingAccessory = this.accessories.find(
|
|
726
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
848
727
|
if (existingAccessory) {
|
|
849
728
|
// the accessory already exists
|
|
850
729
|
if (await this.registerDevice(device)) {
|
|
@@ -903,7 +782,7 @@ export class SwitchBotPlatform {
|
|
|
903
782
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
904
783
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
905
784
|
// the cached devices we stored in the `configureAccessory` method above
|
|
906
|
-
const existingAccessory = this.accessories.find(
|
|
785
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
907
786
|
if (existingAccessory) {
|
|
908
787
|
// the accessory already exists
|
|
909
788
|
if (await this.registerDevice(device)) {
|
|
@@ -964,7 +843,7 @@ export class SwitchBotPlatform {
|
|
|
964
843
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
965
844
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
966
845
|
// the cached devices we stored in the `configureAccessory` method above
|
|
967
|
-
const existingAccessory = this.accessories.find(
|
|
846
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
968
847
|
if (existingAccessory) {
|
|
969
848
|
// the accessory already exists
|
|
970
849
|
if (await this.registerDevice(device)) {
|
|
@@ -1024,7 +903,7 @@ export class SwitchBotPlatform {
|
|
|
1024
903
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1025
904
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1026
905
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1027
|
-
const existingAccessory = this.accessories.find(
|
|
906
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1028
907
|
if (existingAccessory) {
|
|
1029
908
|
// the accessory already exists
|
|
1030
909
|
if (await this.registerDevice(device)) {
|
|
@@ -1085,7 +964,7 @@ export class SwitchBotPlatform {
|
|
|
1085
964
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1086
965
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1087
966
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1088
|
-
const existingAccessory = this.accessories.find(
|
|
967
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1089
968
|
if (existingAccessory) {
|
|
1090
969
|
// the accessory already exists
|
|
1091
970
|
if (await this.registerDevice(device)) {
|
|
@@ -1146,7 +1025,7 @@ export class SwitchBotPlatform {
|
|
|
1146
1025
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1147
1026
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1148
1027
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1149
|
-
const existingAccessory = this.accessories.find(
|
|
1028
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1150
1029
|
if (existingAccessory) {
|
|
1151
1030
|
// the accessory already exists
|
|
1152
1031
|
if (await this.registerDevice(device)) {
|
|
@@ -1206,7 +1085,7 @@ export class SwitchBotPlatform {
|
|
|
1206
1085
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1207
1086
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1208
1087
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1209
|
-
const existingAccessory = this.accessories.find(
|
|
1088
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1210
1089
|
if (existingAccessory) {
|
|
1211
1090
|
// the accessory already exists
|
|
1212
1091
|
if (await this.registerDevice(device)) {
|
|
@@ -1266,7 +1145,7 @@ export class SwitchBotPlatform {
|
|
|
1266
1145
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1267
1146
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1268
1147
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1269
|
-
const existingAccessory = this.accessories.find(
|
|
1148
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1270
1149
|
if (existingAccessory) {
|
|
1271
1150
|
// the accessory already exists
|
|
1272
1151
|
if (await this.registerDevice(device)) {
|
|
@@ -1326,7 +1205,7 @@ export class SwitchBotPlatform {
|
|
|
1326
1205
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1327
1206
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1328
1207
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1329
|
-
const existingAccessory = this.accessories.find(
|
|
1208
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1330
1209
|
if (existingAccessory) {
|
|
1331
1210
|
// the accessory already exists
|
|
1332
1211
|
if (await this.registerDevice(device)) {
|
|
@@ -1386,7 +1265,7 @@ export class SwitchBotPlatform {
|
|
|
1386
1265
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1387
1266
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1388
1267
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1389
|
-
const existingAccessory = this.accessories.find(
|
|
1268
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1390
1269
|
if (existingAccessory) {
|
|
1391
1270
|
// the accessory already exists
|
|
1392
1271
|
if (await this.registerDevice(device)) {
|
|
@@ -1414,8 +1293,8 @@ export class SwitchBotPlatform {
|
|
|
1414
1293
|
else if (await this.registerDevice(device)) {
|
|
1415
1294
|
if (isBlindTiltDevice(device)) {
|
|
1416
1295
|
if (device.group && !device.curtain?.disable_group) {
|
|
1417
|
-
this.debugLog('Your Curtains are grouped, '
|
|
1418
|
-
`, Secondary curtain automatically hidden. Main Curtain: ${device.deviceName}, deviceId: ${device.deviceId}`);
|
|
1296
|
+
this.debugLog('Your Curtains are grouped, '
|
|
1297
|
+
+ `, Secondary curtain automatically hidden. Main Curtain: ${device.deviceName}, deviceId: ${device.deviceId}`);
|
|
1419
1298
|
}
|
|
1420
1299
|
else {
|
|
1421
1300
|
if (device.master) {
|
|
@@ -1433,7 +1312,6 @@ export class SwitchBotPlatform {
|
|
|
1433
1312
|
// store a copy of the device object in the `accessory.context`
|
|
1434
1313
|
// the `context` property can be used to store any data about the accessory you may need
|
|
1435
1314
|
accessory.context.device = device;
|
|
1436
|
-
;
|
|
1437
1315
|
accessory.context.deviceId = device.deviceId;
|
|
1438
1316
|
accessory.context.deviceType = device.deviceType;
|
|
1439
1317
|
accessory.context.model = SwitchBotModel.BlindTilt;
|
|
@@ -1461,7 +1339,7 @@ export class SwitchBotPlatform {
|
|
|
1461
1339
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1462
1340
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1463
1341
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1464
|
-
const existingAccessory = this.accessories.find(
|
|
1342
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1465
1343
|
if (existingAccessory) {
|
|
1466
1344
|
// the accessory already exists
|
|
1467
1345
|
if (await this.registerDevice(device)) {
|
|
@@ -1489,8 +1367,8 @@ export class SwitchBotPlatform {
|
|
|
1489
1367
|
else if (await this.registerDevice(device)) {
|
|
1490
1368
|
if (isCurtainDevice(device)) {
|
|
1491
1369
|
if (device.group && !device.curtain?.disable_group) {
|
|
1492
|
-
this.debugLog('Your Curtains are grouped, '
|
|
1493
|
-
`, Secondary curtain automatically hidden. Main Curtain: ${device.deviceName}, deviceId: ${device.deviceId}`);
|
|
1370
|
+
this.debugLog('Your Curtains are grouped, '
|
|
1371
|
+
+ `, Secondary curtain automatically hidden. Main Curtain: ${device.deviceName}, deviceId: ${device.deviceId}`);
|
|
1494
1372
|
}
|
|
1495
1373
|
else {
|
|
1496
1374
|
if (device.master) {
|
|
@@ -1535,7 +1413,7 @@ export class SwitchBotPlatform {
|
|
|
1535
1413
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1536
1414
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1537
1415
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1538
|
-
const existingAccessory = this.accessories.find(
|
|
1416
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1539
1417
|
if (existingAccessory) {
|
|
1540
1418
|
// the accessory already exists
|
|
1541
1419
|
if (await this.registerDevice(device)) {
|
|
@@ -1543,8 +1421,11 @@ export class SwitchBotPlatform {
|
|
|
1543
1421
|
existingAccessory.context.device = device;
|
|
1544
1422
|
existingAccessory.context.deviceId = device.deviceId;
|
|
1545
1423
|
existingAccessory.context.deviceType = device.deviceType;
|
|
1546
|
-
existingAccessory.context.model = device.deviceType === 'Plug Mini (US)'
|
|
1547
|
-
? SwitchBotModel.
|
|
1424
|
+
existingAccessory.context.model = device.deviceType === 'Plug Mini (US)'
|
|
1425
|
+
? SwitchBotModel.PlugMiniUS
|
|
1426
|
+
: device.deviceType === 'Plug Mini (JP)'
|
|
1427
|
+
? SwitchBotModel.PlugMiniJP
|
|
1428
|
+
: SwitchBotModel.Plug;
|
|
1548
1429
|
existingAccessory.displayName = device.configDeviceName
|
|
1549
1430
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
1550
1431
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
@@ -1571,8 +1452,11 @@ export class SwitchBotPlatform {
|
|
|
1571
1452
|
accessory.context.device = device;
|
|
1572
1453
|
accessory.context.deviceId = device.deviceId;
|
|
1573
1454
|
accessory.context.deviceType = device.deviceType;
|
|
1574
|
-
accessory.context.model = device.deviceType === 'Plug Mini (US)'
|
|
1575
|
-
? SwitchBotModel.
|
|
1455
|
+
accessory.context.model = device.deviceType === 'Plug Mini (US)'
|
|
1456
|
+
? SwitchBotModel.PlugMiniUS
|
|
1457
|
+
: device.deviceType === 'Plug Mini (JP)'
|
|
1458
|
+
? SwitchBotModel.PlugMiniJP
|
|
1459
|
+
: SwitchBotModel.Plug;
|
|
1576
1460
|
accessory.displayName = device.configDeviceName
|
|
1577
1461
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
1578
1462
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
@@ -1597,7 +1481,7 @@ export class SwitchBotPlatform {
|
|
|
1597
1481
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1598
1482
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1599
1483
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1600
|
-
const existingAccessory = this.accessories.find(
|
|
1484
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1601
1485
|
if (existingAccessory) {
|
|
1602
1486
|
// the accessory already exists
|
|
1603
1487
|
if (await this.registerDevice(device)) {
|
|
@@ -1657,7 +1541,7 @@ export class SwitchBotPlatform {
|
|
|
1657
1541
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1658
1542
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1659
1543
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1660
|
-
const existingAccessory = this.accessories.find(
|
|
1544
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1661
1545
|
if (existingAccessory) {
|
|
1662
1546
|
// the accessory already exists
|
|
1663
1547
|
if (await this.registerDevice(device)) {
|
|
@@ -1717,7 +1601,7 @@ export class SwitchBotPlatform {
|
|
|
1717
1601
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1718
1602
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1719
1603
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1720
|
-
const existingAccessory = this.accessories.find(
|
|
1604
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1721
1605
|
if (existingAccessory) {
|
|
1722
1606
|
// the accessory already exists
|
|
1723
1607
|
if (await this.registerDevice(device)) {
|
|
@@ -1777,7 +1661,7 @@ export class SwitchBotPlatform {
|
|
|
1777
1661
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1778
1662
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1779
1663
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1780
|
-
const existingAccessory = this.accessories.find(
|
|
1664
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1781
1665
|
if (existingAccessory) {
|
|
1782
1666
|
// the accessory already exists
|
|
1783
1667
|
if (await this.registerDevice(device)) {
|
|
@@ -1837,7 +1721,7 @@ export class SwitchBotPlatform {
|
|
|
1837
1721
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1838
1722
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1839
1723
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1840
|
-
const existingAccessory = this.accessories.find(
|
|
1724
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1841
1725
|
if (existingAccessory) {
|
|
1842
1726
|
// the accessory already exists
|
|
1843
1727
|
if (await this.registerDevice(device)) {
|
|
@@ -1897,7 +1781,7 @@ export class SwitchBotPlatform {
|
|
|
1897
1781
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1898
1782
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1899
1783
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1900
|
-
const existingAccessory = this.accessories.find(
|
|
1784
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1901
1785
|
if (existingAccessory) {
|
|
1902
1786
|
// the accessory already exists
|
|
1903
1787
|
if (await this.registerDevice(device)) {
|
|
@@ -1905,11 +1789,17 @@ export class SwitchBotPlatform {
|
|
|
1905
1789
|
existingAccessory.context.device = device;
|
|
1906
1790
|
existingAccessory.context.deviceId = device.deviceId;
|
|
1907
1791
|
existingAccessory.context.deviceType = device.deviceType;
|
|
1908
|
-
existingAccessory.context.model = device.deviceType === 'Robot Vacuum Cleaner S1'
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1792
|
+
existingAccessory.context.model = device.deviceType === 'Robot Vacuum Cleaner S1'
|
|
1793
|
+
? SwitchBotModel.RobotVacuumCleanerS1
|
|
1794
|
+
: device.deviceType === 'Robot Vacuum Cleaner S1 Plus'
|
|
1795
|
+
? SwitchBotModel.RobotVacuumCleanerS1Plus
|
|
1796
|
+
: device.deviceType === 'Robot Vacuum Cleaner S10'
|
|
1797
|
+
? SwitchBotModel.RobotVacuumCleanerS10
|
|
1798
|
+
: device.deviceType === 'WoSweeper'
|
|
1799
|
+
? SwitchBotModel.WoSweeper
|
|
1800
|
+
: device.deviceType === 'WoSweeperMini'
|
|
1801
|
+
? SwitchBotModel.WoSweeperMini
|
|
1802
|
+
: SwitchBotModel.Unknown;
|
|
1913
1803
|
existingAccessory.displayName = device.configDeviceName
|
|
1914
1804
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
1915
1805
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
@@ -1936,11 +1826,17 @@ export class SwitchBotPlatform {
|
|
|
1936
1826
|
accessory.context.device = device;
|
|
1937
1827
|
accessory.context.deviceId = device.deviceId;
|
|
1938
1828
|
accessory.context.deviceType = device.deviceType;
|
|
1939
|
-
accessory.context.model = device.deviceType === 'Robot Vacuum Cleaner S1'
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1829
|
+
accessory.context.model = device.deviceType === 'Robot Vacuum Cleaner S1'
|
|
1830
|
+
? SwitchBotModel.RobotVacuumCleanerS1
|
|
1831
|
+
: device.deviceType === 'Robot Vacuum Cleaner S1 Plus'
|
|
1832
|
+
? SwitchBotModel.RobotVacuumCleanerS1Plus
|
|
1833
|
+
: device.deviceType === 'Robot Vacuum Cleaner S10'
|
|
1834
|
+
? SwitchBotModel.RobotVacuumCleanerS10
|
|
1835
|
+
: device.deviceType === 'WoSweeper'
|
|
1836
|
+
? SwitchBotModel.WoSweeper
|
|
1837
|
+
: device.deviceType === 'WoSweeperMini'
|
|
1838
|
+
? SwitchBotModel.WoSweeperMini
|
|
1839
|
+
: SwitchBotModel.Unknown;
|
|
1944
1840
|
accessory.displayName = device.configDeviceName
|
|
1945
1841
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
1946
1842
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
@@ -1965,7 +1861,7 @@ export class SwitchBotPlatform {
|
|
|
1965
1861
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
1966
1862
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1967
1863
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1968
|
-
const existingAccessory = this.accessories.find(
|
|
1864
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1969
1865
|
if (!device.hide_device && existingAccessory) {
|
|
1970
1866
|
// if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
|
|
1971
1867
|
existingAccessory.context.device = device;
|
|
@@ -1998,7 +1894,6 @@ export class SwitchBotPlatform {
|
|
|
1998
1894
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
1999
1895
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2000
1896
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2001
|
-
accessory.context.connectionType = device.connectionType;
|
|
2002
1897
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2003
1898
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2004
1899
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2006,7 +1901,7 @@ export class SwitchBotPlatform {
|
|
|
2006
1901
|
// this is imported from `platformAccessory.ts`
|
|
2007
1902
|
new TV(this, accessory, device);
|
|
2008
1903
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2009
|
-
this.
|
|
1904
|
+
this.externalOrPlatform(device, accessory);
|
|
2010
1905
|
this.accessories.push(accessory);
|
|
2011
1906
|
}
|
|
2012
1907
|
else {
|
|
@@ -2017,7 +1912,7 @@ export class SwitchBotPlatform {
|
|
|
2017
1912
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2018
1913
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2019
1914
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2020
|
-
const existingAccessory = this.accessories.find(
|
|
1915
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2021
1916
|
if (existingAccessory) {
|
|
2022
1917
|
// the accessory already exists
|
|
2023
1918
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2056,7 +1951,6 @@ export class SwitchBotPlatform {
|
|
|
2056
1951
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2057
1952
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2058
1953
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2059
|
-
accessory.context.connectionType = device.connectionType;
|
|
2060
1954
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2061
1955
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2062
1956
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2065,7 +1959,7 @@ export class SwitchBotPlatform {
|
|
|
2065
1959
|
new IRFan(this, accessory, device);
|
|
2066
1960
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2067
1961
|
// publish device externally or link the accessory to your platform
|
|
2068
|
-
this.
|
|
1962
|
+
this.externalOrPlatform(device, accessory);
|
|
2069
1963
|
this.accessories.push(accessory);
|
|
2070
1964
|
}
|
|
2071
1965
|
else {
|
|
@@ -2076,7 +1970,7 @@ export class SwitchBotPlatform {
|
|
|
2076
1970
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2077
1971
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2078
1972
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2079
|
-
const existingAccessory = this.accessories.find(
|
|
1973
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2080
1974
|
if (existingAccessory) {
|
|
2081
1975
|
// the accessory already exists
|
|
2082
1976
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2115,7 +2009,6 @@ export class SwitchBotPlatform {
|
|
|
2115
2009
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2116
2010
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2117
2011
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2118
|
-
accessory.context.connectionType = device.connectionType;
|
|
2119
2012
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2120
2013
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2121
2014
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2124,7 +2017,7 @@ export class SwitchBotPlatform {
|
|
|
2124
2017
|
new Light(this, accessory, device);
|
|
2125
2018
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2126
2019
|
// publish device externally or link the accessory to your platform
|
|
2127
|
-
this.
|
|
2020
|
+
this.externalOrPlatform(device, accessory);
|
|
2128
2021
|
this.accessories.push(accessory);
|
|
2129
2022
|
}
|
|
2130
2023
|
else {
|
|
@@ -2135,7 +2028,7 @@ export class SwitchBotPlatform {
|
|
|
2135
2028
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2136
2029
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2137
2030
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2138
|
-
const existingAccessory = this.accessories.find(
|
|
2031
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2139
2032
|
if (existingAccessory) {
|
|
2140
2033
|
// the accessory already exists
|
|
2141
2034
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2174,7 +2067,6 @@ export class SwitchBotPlatform {
|
|
|
2174
2067
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2175
2068
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2176
2069
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2177
|
-
accessory.context.connectionType = device.connectionType;
|
|
2178
2070
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2179
2071
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2180
2072
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2183,7 +2075,7 @@ export class SwitchBotPlatform {
|
|
|
2183
2075
|
new AirConditioner(this, accessory, device);
|
|
2184
2076
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2185
2077
|
// publish device externally or link the accessory to your platform
|
|
2186
|
-
this.
|
|
2078
|
+
this.externalOrPlatform(device, accessory);
|
|
2187
2079
|
this.accessories.push(accessory);
|
|
2188
2080
|
}
|
|
2189
2081
|
else {
|
|
@@ -2194,7 +2086,7 @@ export class SwitchBotPlatform {
|
|
|
2194
2086
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2195
2087
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2196
2088
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2197
|
-
const existingAccessory = this.accessories.find(
|
|
2089
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2198
2090
|
if (existingAccessory) {
|
|
2199
2091
|
// the accessory already exists
|
|
2200
2092
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2233,7 +2125,6 @@ export class SwitchBotPlatform {
|
|
|
2233
2125
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2234
2126
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2235
2127
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2236
|
-
accessory.context.connectionType = device.connectionType;
|
|
2237
2128
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2238
2129
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2239
2130
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2242,7 +2133,7 @@ export class SwitchBotPlatform {
|
|
|
2242
2133
|
new AirPurifier(this, accessory, device);
|
|
2243
2134
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2244
2135
|
// publish device externally or link the accessory to your platform
|
|
2245
|
-
this.
|
|
2136
|
+
this.externalOrPlatform(device, accessory);
|
|
2246
2137
|
this.accessories.push(accessory);
|
|
2247
2138
|
}
|
|
2248
2139
|
else {
|
|
@@ -2253,7 +2144,7 @@ export class SwitchBotPlatform {
|
|
|
2253
2144
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2254
2145
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2255
2146
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2256
|
-
const existingAccessory = this.accessories.find(
|
|
2147
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2257
2148
|
if (existingAccessory) {
|
|
2258
2149
|
// the accessory already exists
|
|
2259
2150
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2292,7 +2183,6 @@ export class SwitchBotPlatform {
|
|
|
2292
2183
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2293
2184
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2294
2185
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2295
|
-
accessory.context.connectionType = device.connectionType;
|
|
2296
2186
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2297
2187
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2298
2188
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2301,7 +2191,7 @@ export class SwitchBotPlatform {
|
|
|
2301
2191
|
new WaterHeater(this, accessory, device);
|
|
2302
2192
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2303
2193
|
// publish device externally or link the accessory to your platform
|
|
2304
|
-
this.
|
|
2194
|
+
this.externalOrPlatform(device, accessory);
|
|
2305
2195
|
this.accessories.push(accessory);
|
|
2306
2196
|
}
|
|
2307
2197
|
else {
|
|
@@ -2312,7 +2202,7 @@ export class SwitchBotPlatform {
|
|
|
2312
2202
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2313
2203
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2314
2204
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2315
|
-
const existingAccessory = this.accessories.find(
|
|
2205
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2316
2206
|
if (existingAccessory) {
|
|
2317
2207
|
// the accessory already exists
|
|
2318
2208
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2351,7 +2241,6 @@ export class SwitchBotPlatform {
|
|
|
2351
2241
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2352
2242
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2353
2243
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2354
|
-
accessory.context.connectionType = device.connectionType;
|
|
2355
2244
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2356
2245
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2357
2246
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2360,7 +2249,7 @@ export class SwitchBotPlatform {
|
|
|
2360
2249
|
new VacuumCleaner(this, accessory, device);
|
|
2361
2250
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2362
2251
|
// publish device externally or link the accessory to your platform
|
|
2363
|
-
this.
|
|
2252
|
+
this.externalOrPlatform(device, accessory);
|
|
2364
2253
|
this.accessories.push(accessory);
|
|
2365
2254
|
}
|
|
2366
2255
|
else {
|
|
@@ -2371,7 +2260,7 @@ export class SwitchBotPlatform {
|
|
|
2371
2260
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2372
2261
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2373
2262
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2374
|
-
const existingAccessory = this.accessories.find(
|
|
2263
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2375
2264
|
if (existingAccessory) {
|
|
2376
2265
|
// the accessory already exists
|
|
2377
2266
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2410,7 +2299,6 @@ export class SwitchBotPlatform {
|
|
|
2410
2299
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2411
2300
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2412
2301
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2413
|
-
accessory.context.connectionType = device.connectionType;
|
|
2414
2302
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2415
2303
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2416
2304
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2419,7 +2307,7 @@ export class SwitchBotPlatform {
|
|
|
2419
2307
|
new Camera(this, accessory, device);
|
|
2420
2308
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2421
2309
|
// publish device externally or link the accessory to your platform
|
|
2422
|
-
this.
|
|
2310
|
+
this.externalOrPlatform(device, accessory);
|
|
2423
2311
|
this.accessories.push(accessory);
|
|
2424
2312
|
}
|
|
2425
2313
|
else {
|
|
@@ -2430,7 +2318,7 @@ export class SwitchBotPlatform {
|
|
|
2430
2318
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2431
2319
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2432
2320
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2433
|
-
const existingAccessory = this.accessories.find(
|
|
2321
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2434
2322
|
if (existingAccessory) {
|
|
2435
2323
|
// the accessory already exists
|
|
2436
2324
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2469,7 +2357,6 @@ export class SwitchBotPlatform {
|
|
|
2469
2357
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2470
2358
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2471
2359
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2472
|
-
accessory.context.connectionType = device.connectionType;
|
|
2473
2360
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2474
2361
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2475
2362
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2478,7 +2365,7 @@ export class SwitchBotPlatform {
|
|
|
2478
2365
|
new Others(this, accessory, device);
|
|
2479
2366
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2480
2367
|
// publish device externally or link the accessory to your platform
|
|
2481
|
-
this.
|
|
2368
|
+
this.externalOrPlatform(device, accessory);
|
|
2482
2369
|
this.accessories.push(accessory);
|
|
2483
2370
|
}
|
|
2484
2371
|
else {
|
|
@@ -2486,24 +2373,13 @@ export class SwitchBotPlatform {
|
|
|
2486
2373
|
}
|
|
2487
2374
|
}
|
|
2488
2375
|
async registerCurtains(device) {
|
|
2489
|
-
/*function isCurtainDevice(device: device & devicesConfig): device is (curtain | curtain3) & devicesConfig {
|
|
2490
|
-
return device.deviceType === 'Curtain' || device.deviceType === 'Curtain3';
|
|
2491
|
-
}
|
|
2492
|
-
|
|
2493
|
-
function isBlindTiltDevice(device: device & devicesConfig): device is blindTilt & devicesConfig {
|
|
2494
|
-
return device.deviceType === 'Blind Tilt';
|
|
2495
|
-
}*/
|
|
2496
2376
|
let registerWindowCovering;
|
|
2497
2377
|
if (isCurtainDevice(device)) {
|
|
2498
|
-
await this.debugWarnLog(`deviceName: ${device.deviceName} deviceId: ${device.deviceId}, curtainDevicesIds: ${device.curtainDevicesIds}
|
|
2499
|
-
+ ` master: ${device.master}, group: ${device.group}, disable_group: ${device.curtain?.disable_group},`
|
|
2500
|
-
+ ` connectionType: ${device.connectionType}`);
|
|
2378
|
+
await this.debugWarnLog(`deviceName: ${device.deviceName} deviceId: ${device.deviceId}, curtainDevicesIds: ${device.curtainDevicesIds},x master: ${device.master}, group: ${device.group}, disable_group: ${device.curtain?.disable_group}, connectionType: ${device.connectionType}`);
|
|
2501
2379
|
registerWindowCovering = await this.registerWindowCovering(device);
|
|
2502
2380
|
}
|
|
2503
2381
|
else if (isBlindTiltDevice(device)) {
|
|
2504
|
-
await this.debugWarnLog(`deviceName: ${device.deviceName} deviceId: ${device.deviceId}, blindTiltDevicesIds: ${device.blindTiltDevicesIds}
|
|
2505
|
-
+ ` master: ${device.master}, group: ${device.group}, disable_group: ${device.curtain?.disable_group},`
|
|
2506
|
-
+ ` connectionType: ${device.connectionType}`);
|
|
2382
|
+
await this.debugWarnLog(`deviceName: ${device.deviceName} deviceId: ${device.deviceId}, blindTiltDevicesIds: ${device.blindTiltDevicesIds}, master: ${device.master}, group: ${device.group}, disable_group: ${device.curtain?.disable_group}, connectionType: ${device.connectionType}`);
|
|
2507
2383
|
registerWindowCovering = await this.registerWindowCovering(device);
|
|
2508
2384
|
}
|
|
2509
2385
|
else {
|
|
@@ -2517,36 +2393,31 @@ export class SwitchBotPlatform {
|
|
|
2517
2393
|
if (device.master && device.group) {
|
|
2518
2394
|
// OpenAPI: Master Curtains/Blind Tilt in Group
|
|
2519
2395
|
registerCurtain = true;
|
|
2520
|
-
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}
|
|
2521
|
-
+ ` device.group: ${device.group} connectionType; ${device.connectionType}`);
|
|
2396
|
+
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}, device.group: ${device.group} connectionType; ${device.connectionType}`);
|
|
2522
2397
|
await this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}`);
|
|
2523
2398
|
}
|
|
2524
2399
|
else if (!device.master && device.curtain?.disable_group) {
|
|
2525
|
-
|
|
2400
|
+
// !device.group && device.connectionType === 'BLE'
|
|
2526
2401
|
// OpenAPI: Non-Master Curtains/Blind Tilts that has Disable Grouping Checked
|
|
2527
2402
|
registerCurtain = true;
|
|
2528
|
-
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}, disable_group: `
|
|
2529
|
-
+ `${device.curtain?.disable_group}, connectionType; ${device.connectionType}`);
|
|
2403
|
+
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}, disable_group: ${device.curtain?.disable_group}, connectionType; ${device.connectionType}`);
|
|
2530
2404
|
await this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}`);
|
|
2531
2405
|
}
|
|
2532
2406
|
else if (device.master && !device.group) {
|
|
2533
2407
|
// OpenAPI: Master Curtains/Blind Tilts not in Group
|
|
2534
2408
|
registerCurtain = true;
|
|
2535
|
-
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}
|
|
2536
|
-
+ ` device.group: ${device.group} connectionType; ${device.connectionType}`);
|
|
2409
|
+
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}, device.group: ${device.group} connectionType; ${device.connectionType}`);
|
|
2537
2410
|
await this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}`);
|
|
2538
2411
|
}
|
|
2539
2412
|
else if (device.connectionType === 'BLE') {
|
|
2540
2413
|
// BLE: Curtains/Blind Tilt
|
|
2541
2414
|
registerCurtain = true;
|
|
2542
|
-
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] connectionType: ${device.connectionType}, `
|
|
2543
|
-
+ ` group: ${device.group}`);
|
|
2415
|
+
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] connectionType: ${device.connectionType}, group: ${device.group}`);
|
|
2544
2416
|
await this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}`);
|
|
2545
2417
|
}
|
|
2546
2418
|
else {
|
|
2547
2419
|
registerCurtain = false;
|
|
2548
|
-
await this.debugErrorLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] disable_group: ${device.curtain?.disable_group}
|
|
2549
|
-
+ ` device.master: ${device.master}, device.group: ${device.group}`);
|
|
2420
|
+
await this.debugErrorLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] disable_group: ${device.curtain?.disable_group}, device.master: ${device.master}, device.group: ${device.group}`);
|
|
2550
2421
|
await this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}, device.connectionType: ${device.connectionType}`);
|
|
2551
2422
|
}
|
|
2552
2423
|
return registerCurtain;
|
|
@@ -2564,189 +2435,93 @@ export class SwitchBotPlatform {
|
|
|
2564
2435
|
async registerDevice(device) {
|
|
2565
2436
|
device.connectionType = await this.connectionType(device);
|
|
2566
2437
|
let registerDevice;
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
case 'Curtain3':
|
|
2571
|
-
case 'Blind Tilt':
|
|
2572
|
-
registerDevice = await this.registerCurtains(device);
|
|
2573
|
-
await this.debugWarnLog(`Device: ${device.deviceName} ${device.deviceType} registerDevice: ${registerDevice}`);
|
|
2574
|
-
break;
|
|
2575
|
-
default:
|
|
2576
|
-
registerDevice = true;
|
|
2577
|
-
await this.debugWarnLog(`Device: ${device.deviceName} registerDevice: ${registerDevice}`);
|
|
2578
|
-
}
|
|
2579
|
-
if (registerDevice === true) {
|
|
2580
|
-
await this.debugWarnLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, will display in HomeKit`);
|
|
2581
|
-
}
|
|
2582
|
-
else {
|
|
2583
|
-
await this.debugErrorLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, will not display in HomeKit`);
|
|
2584
|
-
}
|
|
2585
|
-
}
|
|
2586
|
-
else if (!device.hide_device && device.deviceId && device.configDeviceType && device.configDeviceName && device.connectionType === 'BLE') {
|
|
2587
|
-
switch (device.deviceType) {
|
|
2588
|
-
case 'Curtain':
|
|
2589
|
-
case 'Curtain3':
|
|
2590
|
-
case 'Blind Tilt':
|
|
2591
|
-
registerDevice = await this.registerCurtains(device);
|
|
2592
|
-
await this.debugWarnLog(`Device: ${device.deviceName} ${device.deviceType} registerDevice: ${registerDevice}`);
|
|
2593
|
-
break;
|
|
2594
|
-
default:
|
|
2595
|
-
registerDevice = true;
|
|
2596
|
-
await this.debugWarnLog(`Device: ${device.deviceName} registerDevice: ${registerDevice}`);
|
|
2597
|
-
}
|
|
2598
|
-
if (registerDevice === true) {
|
|
2599
|
-
await this.debugWarnLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, will display in HomeKit`);
|
|
2600
|
-
}
|
|
2601
|
-
else {
|
|
2602
|
-
await this.debugErrorLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, will not display in HomeKit`);
|
|
2603
|
-
}
|
|
2604
|
-
}
|
|
2605
|
-
else if (!device.hide_device && device.connectionType === 'OpenAPI') {
|
|
2606
|
-
switch (device.deviceType) {
|
|
2607
|
-
case 'Curtain':
|
|
2608
|
-
case 'Curtain3':
|
|
2609
|
-
case 'Blind Tilt':
|
|
2610
|
-
registerDevice = await this.registerCurtains(device);
|
|
2611
|
-
await this.debugWarnLog(`Device: ${device.deviceName} ${device.deviceType} registerDevice: ${registerDevice}`);
|
|
2612
|
-
break;
|
|
2613
|
-
default:
|
|
2614
|
-
registerDevice = true;
|
|
2615
|
-
await this.debugWarnLog(`Device: ${device.deviceName} registerDevice: ${registerDevice}`);
|
|
2616
|
-
}
|
|
2617
|
-
if (registerDevice === true) {
|
|
2618
|
-
await this.debugWarnLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, will display in HomeKit`);
|
|
2619
|
-
}
|
|
2620
|
-
else {
|
|
2621
|
-
await this.debugErrorLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, will not display in HomeKit`);
|
|
2622
|
-
}
|
|
2623
|
-
}
|
|
2624
|
-
else if (!device.hide_device && device.connectionType === 'Disabled') {
|
|
2625
|
-
switch (device.deviceType) {
|
|
2626
|
-
case 'Curtain':
|
|
2627
|
-
case 'Curtain3':
|
|
2628
|
-
case 'Blind Tilt':
|
|
2629
|
-
registerDevice = await this.registerCurtains(device);
|
|
2630
|
-
await this.debugWarnLog(`Device: ${device.deviceName} ${device.deviceType} registerDevice: ${registerDevice}`);
|
|
2631
|
-
break;
|
|
2632
|
-
default:
|
|
2633
|
-
registerDevice = true;
|
|
2634
|
-
await this.debugWarnLog(`Device: ${device.deviceName} registerDevice: ${registerDevice}`);
|
|
2635
|
-
}
|
|
2636
|
-
await this.debugWarnLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, will continue to display in HomeKit`);
|
|
2637
|
-
}
|
|
2638
|
-
else if (!device.connectionType && !device.hide_device) {
|
|
2639
|
-
registerDevice = false;
|
|
2640
|
-
await this.debugErrorLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, will not display in HomeKit`);
|
|
2641
|
-
}
|
|
2642
|
-
else if (device.hide_device) {
|
|
2643
|
-
registerDevice = false;
|
|
2644
|
-
await this.debugErrorLog(`Device: ${device.deviceName} hide_device: ${device.hide_device}, will not display in HomeKit`);
|
|
2438
|
+
const shouldRegister = !device.hide_device && (device.connectionType === 'BLE/OpenAPI' || (device.deviceId && device.configDeviceType && device.configDeviceName && device.connectionType === 'BLE') || device.connectionType === 'OpenAPI' || device.connectionType === 'Disabled');
|
|
2439
|
+
if (shouldRegister) {
|
|
2440
|
+
registerDevice = await this.handleDeviceRegistration(device);
|
|
2645
2441
|
}
|
|
2646
2442
|
else {
|
|
2647
2443
|
registerDevice = false;
|
|
2648
|
-
await this.debugErrorLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, hide_device: `
|
|
2649
|
-
+ `${device.hide_device}, will not display in HomeKit`);
|
|
2444
|
+
await this.debugErrorLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, hide_device: ${device.hide_device}, will not display in HomeKit`);
|
|
2650
2445
|
}
|
|
2651
2446
|
return registerDevice;
|
|
2652
2447
|
}
|
|
2653
|
-
async
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2448
|
+
async handleDeviceRegistration(device) {
|
|
2449
|
+
let registerDevice;
|
|
2450
|
+
switch (device.deviceType) {
|
|
2451
|
+
case 'Curtain':
|
|
2452
|
+
case 'Curtain3':
|
|
2453
|
+
case 'Blind Tilt':
|
|
2454
|
+
registerDevice = await this.registerCurtains(device);
|
|
2455
|
+
await this.debugWarnLog(`Device: ${device.deviceName} ${device.deviceType} registerDevice: ${registerDevice}`);
|
|
2456
|
+
break;
|
|
2457
|
+
default:
|
|
2458
|
+
registerDevice = true;
|
|
2459
|
+
await this.debugWarnLog(`Device: ${device.deviceName} registerDevice: ${registerDevice}`);
|
|
2460
|
+
}
|
|
2461
|
+
if (registerDevice) {
|
|
2462
|
+
await this.debugWarnLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, will display in HomeKit`);
|
|
2662
2463
|
}
|
|
2663
2464
|
else {
|
|
2664
|
-
await this.
|
|
2665
|
-
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
|
|
2465
|
+
await this.debugErrorLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, will not display in HomeKit`);
|
|
2666
2466
|
}
|
|
2467
|
+
return registerDevice;
|
|
2667
2468
|
}
|
|
2668
2469
|
async externalOrPlatform(device, accessory) {
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2470
|
+
const { displayName } = accessory;
|
|
2471
|
+
const isExternal = device.external ?? false;
|
|
2472
|
+
if (isExternal) {
|
|
2473
|
+
await this.debugWarnLog(`${displayName} External Accessory Mode`);
|
|
2474
|
+
this.api.publishExternalAccessories(PLUGIN_NAME, [accessory]);
|
|
2672
2475
|
}
|
|
2673
2476
|
else {
|
|
2674
|
-
await this.debugLog(`${
|
|
2477
|
+
await this.debugLog(`${displayName} External Accessory Mode: ${isExternal}`);
|
|
2675
2478
|
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
|
|
2676
2479
|
}
|
|
2677
2480
|
}
|
|
2678
|
-
async externalAccessory(accessory) {
|
|
2679
|
-
this.api.publishExternalAccessories(PLUGIN_NAME, [accessory]);
|
|
2680
|
-
}
|
|
2681
2481
|
unregisterPlatformAccessories(existingAccessory) {
|
|
2482
|
+
const { displayName } = existingAccessory;
|
|
2682
2483
|
// remove platform accessories when no longer present
|
|
2683
2484
|
this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [existingAccessory]);
|
|
2684
|
-
this.warnLog(`Removing existing accessory from cache: ${
|
|
2485
|
+
this.warnLog(`Removing existing accessory from cache: ${displayName}`);
|
|
2685
2486
|
}
|
|
2487
|
+
/**
|
|
2488
|
+
* Handles the status codes returned by the device and logs appropriate messages.
|
|
2489
|
+
*
|
|
2490
|
+
* @param statusCode - The status code returned by the device.
|
|
2491
|
+
* @returns A promise that resolves when the logging is complete.
|
|
2492
|
+
*/
|
|
2686
2493
|
async statusCode(statusCode) {
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
await this.errorLog('Unauthorized, Authorization for the API is required, but the request has not been authenticated, '
|
|
2719
|
-
+ `statusCode: ${statusCode}`);
|
|
2720
|
-
break;
|
|
2721
|
-
case 403:
|
|
2722
|
-
await this.errorLog('Forbidden, The request has been authenticated but does not have appropriate permissions, or a requested resource is not '
|
|
2723
|
-
+ `found, statusCode: ${statusCode}`);
|
|
2724
|
-
break;
|
|
2725
|
-
case 404:
|
|
2726
|
-
await this.errorLog(`Not Found, Specifies the requested path does not exist, statusCode: ${statusCode}`);
|
|
2727
|
-
break;
|
|
2728
|
-
case 406:
|
|
2729
|
-
await this.errorLog('Not Acceptable, The client has requested a MIME type via the Accept header for a value not supported by the server, '
|
|
2730
|
-
+ `statusCode: ${statusCode}`);
|
|
2731
|
-
break;
|
|
2732
|
-
case 415:
|
|
2733
|
-
await this.errorLog('Unsupported Media Type, The client has defined a contentType header that is not supported by the server, '
|
|
2734
|
-
+ `statusCode: ${statusCode}`);
|
|
2735
|
-
break;
|
|
2736
|
-
case 422:
|
|
2737
|
-
await this.errorLog('Unprocessable Entity, The client has made a valid request, but the server cannot process it. This is often used for '
|
|
2738
|
-
+ `APIs for which certain limits have been exceeded, statusCode: ${statusCode}`);
|
|
2739
|
-
break;
|
|
2740
|
-
case 429:
|
|
2741
|
-
await this.errorLog('Too Many Requests, The client has exceeded the number of requests allowed for a given time window, '
|
|
2742
|
-
+ `statusCode: ${statusCode}`);
|
|
2743
|
-
break;
|
|
2744
|
-
case 500:
|
|
2745
|
-
await this.errorLog('Internal Server Error, An unexpected error on the SmartThings servers has occurred. These errors should be rare, '
|
|
2746
|
-
+ `statusCode: ${statusCode}`);
|
|
2747
|
-
break;
|
|
2748
|
-
default:
|
|
2749
|
-
await this.errorLog(`Unknown statusCode, statusCode: ${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`);
|
|
2494
|
+
const messages = {
|
|
2495
|
+
151: `Command not supported by this device type, statusCode: ${statusCode}, Submit Feature Request Here:
|
|
2496
|
+
https://tinyurl.com/SwitchBotFeatureRequest`,
|
|
2497
|
+
152: `Device not found, statusCode: ${statusCode}`,
|
|
2498
|
+
160: `Command is not supported, statusCode: ${statusCode}, Submit Bugs Here: https://tinyurl.com/SwitchBotBug`,
|
|
2499
|
+
161: `Device is offline, statusCode: ${statusCode}`,
|
|
2500
|
+
171: `is offline, statusCode: ${statusCode}`,
|
|
2501
|
+
190: `Requests reached the daily limit, statusCode: ${statusCode}`,
|
|
2502
|
+
100: `Command successfully sent, statusCode: ${statusCode}`,
|
|
2503
|
+
200: `Request successful, statusCode: ${statusCode}`,
|
|
2504
|
+
400: `Bad Request, The client has issued an invalid request. This is commonly used to specify validation errors in a request payload,
|
|
2505
|
+
statusCode: ${statusCode}`,
|
|
2506
|
+
401: `Unauthorized, Authorization for the API is required, but the request has not been authenticated, statusCode: ${statusCode}`,
|
|
2507
|
+
403: `Forbidden, The request has been authenticated but does not have appropriate permissions, or a requested resource is not found,
|
|
2508
|
+
statusCode: ${statusCode}`,
|
|
2509
|
+
404: `Not Found, Specifies the requested path does not exist, statusCode: ${statusCode}`,
|
|
2510
|
+
406: `Not Acceptable, The client has requested a MIME type via the Accept header for a value not supported by the server,
|
|
2511
|
+
statusCode: ${statusCode}`,
|
|
2512
|
+
415: `Unsupported Media Type, The client has defined a contentType header that is not supported by the server, statusCode: ${statusCode}`,
|
|
2513
|
+
422: `Unprocessable Entity, The client has made a valid request, but the server cannot process it. This is often used for APIs for which
|
|
2514
|
+
certain limits have been exceeded, statusCode: ${statusCode}`,
|
|
2515
|
+
429: `Too Many Requests, The client has exceeded the number of requests allowed for a given time window, statusCode: ${statusCode}`,
|
|
2516
|
+
500: `Internal Server Error, An unexpected error on the SmartThings servers has occurred. These errors should be rare,
|
|
2517
|
+
statusCode: ${statusCode}`,
|
|
2518
|
+
};
|
|
2519
|
+
const message = messages[statusCode] ?? `Unknown statusCode, statusCode: ${statusCode}, Submit Bugs Here: https://tinyurl.com/SwitchBotBug`;
|
|
2520
|
+
if ([100, 200].includes(statusCode)) {
|
|
2521
|
+
await this.debugLog(message);
|
|
2522
|
+
}
|
|
2523
|
+
else {
|
|
2524
|
+
await this.errorLog(message);
|
|
2750
2525
|
}
|
|
2751
2526
|
}
|
|
2752
2527
|
async retryRequest(deviceMaxRetries, deviceDelayBetweenRetries, url, options) {
|
|
@@ -2774,57 +2549,42 @@ export class SwitchBotPlatform {
|
|
|
2774
2549
|
}
|
|
2775
2550
|
// BLE Connection
|
|
2776
2551
|
async connectBLE(accessory, device) {
|
|
2777
|
-
let switchbot;
|
|
2778
2552
|
try {
|
|
2779
|
-
const
|
|
2780
|
-
queueScheduler.schedule(() =>
|
|
2553
|
+
const switchbot = new SwitchBot();
|
|
2554
|
+
queueScheduler.schedule(async () => switchbot);
|
|
2781
2555
|
await this.debugLog(`${device.deviceType}: ${accessory.displayName} 'node-switchbot' found: ${switchbot}`);
|
|
2556
|
+
return switchbot;
|
|
2782
2557
|
}
|
|
2783
2558
|
catch (e) {
|
|
2784
|
-
switchbot
|
|
2785
|
-
|
|
2559
|
+
await this.errorLog(`${device.deviceType}: ${accessory.displayName} 'node-switchbot' not found, Error: ${e}`);
|
|
2560
|
+
return false;
|
|
2786
2561
|
}
|
|
2787
|
-
return switchbot;
|
|
2788
2562
|
}
|
|
2789
2563
|
async getVersion() {
|
|
2790
2564
|
const json = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf-8'));
|
|
2791
2565
|
await this.debugLog(`Plugin Version: ${json.version}`);
|
|
2792
2566
|
this.version = json.version;
|
|
2567
|
+
return json.version;
|
|
2793
2568
|
}
|
|
2794
2569
|
async getPlatformConfigSettings() {
|
|
2570
|
+
const { options } = this.config;
|
|
2795
2571
|
const platformConfig = {};
|
|
2796
|
-
if (
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
if (
|
|
2804
|
-
|
|
2805
|
-
}
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
}
|
|
2813
|
-
else {
|
|
2814
|
-
this.maxRetries = 3;
|
|
2815
|
-
this.debugWarnLog('Using Default Max Retries');
|
|
2816
|
-
platformConfig.maxRetries = this.maxRetries;
|
|
2817
|
-
}
|
|
2818
|
-
if (this.config.options.delayBetweenRetries) {
|
|
2819
|
-
this.delayBetweenRetries = this.config.options.delayBetweenRetries * 1000;
|
|
2820
|
-
platformConfig.delayBetweenRetries = this.config.options.delayBetweenRetries;
|
|
2821
|
-
}
|
|
2822
|
-
else {
|
|
2823
|
-
this.delayBetweenRetries = 3000;
|
|
2824
|
-
this.debugWarnLog('Using Default Delay Between Retries');
|
|
2825
|
-
platformConfig.delayBetweenRetries = this.delayBetweenRetries / 1000;
|
|
2826
|
-
}
|
|
2827
|
-
if (Object.entries(platformConfig).length !== 0) {
|
|
2572
|
+
if (options) {
|
|
2573
|
+
platformConfig.logging = options.logging;
|
|
2574
|
+
platformConfig.refreshRate = options.refreshRate;
|
|
2575
|
+
platformConfig.updateRate = options.updateRate;
|
|
2576
|
+
platformConfig.pushRate = options.pushRate;
|
|
2577
|
+
this.maxRetries = options.maxRetries || 3;
|
|
2578
|
+
platformConfig.maxRetries = this.maxRetries;
|
|
2579
|
+
if (!options.maxRetries) {
|
|
2580
|
+
await this.debugWarnLog('Using Default Max Retries');
|
|
2581
|
+
}
|
|
2582
|
+
this.delayBetweenRetries = (options.delayBetweenRetries || 3) * 1000;
|
|
2583
|
+
platformConfig.delayBetweenRetries = this.delayBetweenRetries / 1000;
|
|
2584
|
+
if (!options.delayBetweenRetries) {
|
|
2585
|
+
await this.debugWarnLog('Using Default Delay Between Retries');
|
|
2586
|
+
}
|
|
2587
|
+
if (Object.keys(platformConfig).length) {
|
|
2828
2588
|
await this.debugLog(`Platform Config: ${JSON.stringify(platformConfig)}`);
|
|
2829
2589
|
}
|
|
2830
2590
|
this.platformConfig = platformConfig;
|
|
@@ -2847,38 +2607,34 @@ export class SwitchBotPlatform {
|
|
|
2847
2607
|
}
|
|
2848
2608
|
/**
|
|
2849
2609
|
* Validate and clean a string value for a Name Characteristic.
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2610
|
+
* @param displayName - The display name of the accessory.
|
|
2611
|
+
* @param name - The name of the characteristic.
|
|
2612
|
+
* @param value - The value to be validated and cleaned.
|
|
2613
|
+
* @returns The cleaned string value.
|
|
2614
|
+
*/
|
|
2855
2615
|
async validateAndCleanDisplayName(displayName, name, value) {
|
|
2856
|
-
if (this.config.options?.
|
|
2616
|
+
if (this.config.options?.allowInvalidCharacters) {
|
|
2857
2617
|
return value;
|
|
2858
2618
|
}
|
|
2859
2619
|
else {
|
|
2860
|
-
const validPattern =
|
|
2620
|
+
const validPattern = /^[\p{L}\p{N}][\p{L}\p{N} ']*[\p{L}\p{N}]$/u;
|
|
2861
2621
|
const invalidCharsPattern = /[^\p{L}\p{N} ']/gu;
|
|
2862
2622
|
const invalidStartEndPattern = /^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/gu;
|
|
2863
2623
|
if (typeof value === 'string' && !validPattern.test(value)) {
|
|
2864
|
-
this.warnLog(`WARNING: The accessory '${displayName}' has an invalid '${name}' characteristic ('${value}'). Please use only alphanumeric
|
|
2865
|
-
+ ' space, and apostrophe characters. Ensure it starts and ends with an alphabetic or numeric character, and avoid emojis. This may'
|
|
2866
|
-
+ ' prevent the accessory from being added in the Home App or cause unresponsiveness.');
|
|
2624
|
+
await this.warnLog(`WARNING: The accessory '${displayName}' has an invalid '${name}' characteristic ('${value}'). Please use only alphanumeric, space, and apostrophe characters. Ensure it starts and ends with an alphabetic or numeric character, and avoid emojis. This may prevent the accessory from being added in the Home App or cause unresponsiveness.`);
|
|
2867
2625
|
// Remove invalid characters
|
|
2868
2626
|
if (invalidCharsPattern.test(value)) {
|
|
2869
2627
|
const before = value;
|
|
2870
|
-
this.warnLog(`Removing invalid characters from '${name}' characteristic, if you feel this is incorrect
|
|
2871
|
-
+ ' please enable \'allowInvalidCharacter\' in the config to allow all characters');
|
|
2628
|
+
await this.warnLog(`Removing invalid characters from '${name}' characteristic, if you feel this is incorrect, please enable \'allowInvalidCharacter\' in the config to allow all characters`);
|
|
2872
2629
|
value = value.replace(invalidCharsPattern, '');
|
|
2873
|
-
this.warnLog(`${name} Before: '${before}' After: '${value}'`);
|
|
2630
|
+
await this.warnLog(`${name} Before: '${before}' After: '${value}'`);
|
|
2874
2631
|
}
|
|
2875
2632
|
// Ensure it starts and ends with an alphanumeric character
|
|
2876
2633
|
if (invalidStartEndPattern.test(value)) {
|
|
2877
2634
|
const before = value;
|
|
2878
|
-
this.warnLog(`Removing invalid starting or ending characters from '${name}' characteristic, if you feel this is incorrect
|
|
2879
|
-
+ ' please enable \'allowInvalidCharacter\' in the config to allow all characters');
|
|
2635
|
+
await this.warnLog(`Removing invalid starting or ending characters from '${name}' characteristic, if you feel this is incorrect, please enable \'allowInvalidCharacter\' in the config to allow all characters`);
|
|
2880
2636
|
value = value.replace(invalidStartEndPattern, '');
|
|
2881
|
-
this.warnLog(`${name} Before: '${before}' After: '${value}'`);
|
|
2637
|
+
await this.warnLog(`${name} Before: '${before}' After: '${value}'`);
|
|
2882
2638
|
}
|
|
2883
2639
|
}
|
|
2884
2640
|
return value;
|