@switchbot/homebridge-switchbot 3.7.1-beta.2 → 3.7.1-beta.20
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 +10 -0
- package/README.md +14 -0
- package/assets/security-privacy-bluetooth.png +0 -0
- package/config.schema.json +74 -2
- package/dist/device/blindtilt.d.ts +21 -9
- package/dist/device/blindtilt.d.ts.map +1 -1
- package/dist/device/blindtilt.js +167 -96
- package/dist/device/blindtilt.js.map +1 -1
- package/dist/device/bot-old.d.ts +132 -0
- package/dist/device/bot-old.d.ts.map +1 -0
- package/dist/device/bot-old.js +1514 -0
- package/dist/device/bot-old.js.map +1 -0
- package/dist/device/bot.d.ts +10 -9
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +186 -187
- package/dist/device/bot.js.map +1 -1
- package/dist/device/ceilinglight.d.ts +14 -13
- package/dist/device/ceilinglight.d.ts.map +1 -1
- package/dist/device/ceilinglight.js +87 -97
- package/dist/device/ceilinglight.js.map +1 -1
- package/dist/device/colorbulb.d.ts +13 -12
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +92 -105
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts +6 -5
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +71 -68
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts +17 -5
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +184 -118
- 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 +9 -8
- package/dist/device/fan.d.ts.map +1 -1
- package/dist/device/fan.js +94 -101
- package/dist/device/fan.js.map +1 -1
- package/dist/device/hub.d.ts +6 -5
- package/dist/device/hub.d.ts.map +1 -1
- package/dist/device/hub.js +69 -65
- package/dist/device/hub.js.map +1 -1
- package/dist/device/humidifier.d.ts +6 -5
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +89 -104
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/iosensor.d.ts +6 -5
- package/dist/device/iosensor.d.ts.map +1 -1
- package/dist/device/iosensor.js +72 -66
- package/dist/device/iosensor.js.map +1 -1
- package/dist/device/lightstrip.d.ts +7 -6
- package/dist/device/lightstrip.d.ts.map +1 -1
- package/dist/device/lightstrip.js +85 -99
- package/dist/device/lightstrip.js.map +1 -1
- package/dist/device/lock.d.ts +10 -9
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +89 -79
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +6 -5
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +72 -65
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +6 -5
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +72 -64
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts +6 -5
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +65 -58
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +13 -12
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +68 -52
- package/dist/device/plug.js.map +1 -1
- package/dist/device/robotvacuumcleaner.d.ts +12 -11
- package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
- package/dist/device/robotvacuumcleaner.js +93 -82
- package/dist/device/robotvacuumcleaner.js.map +1 -1
- package/dist/device/waterdetector.d.ts +6 -5
- package/dist/device/waterdetector.d.ts.map +1 -1
- package/dist/device/waterdetector.js +73 -63
- 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 +64 -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 +510 -722
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +5 -2
- 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 -53
- package/src/device/blindtilt.ts +537 -456
- package/src/device/bot-old.ts +1578 -0
- package/src/device/bot.ts +732 -725
- package/src/device/ceilinglight.ts +359 -368
- package/src/device/colorbulb.ts +441 -453
- package/src/device/contact.ts +229 -226
- package/src/device/curtain.ts +526 -444
- package/src/device/device.ts +206 -208
- package/src/device/fan.ts +336 -345
- package/src/device/hub.ts +213 -214
- package/src/device/humidifier.ts +326 -347
- package/src/device/iosensor.ts +211 -209
- package/src/device/lightstrip.ts +391 -404
- package/src/device/lock.ts +292 -282
- package/src/device/meter.ts +212 -210
- package/src/device/meterplus.ts +212 -209
- package/src/device/motion.ts +198 -190
- package/src/device/plug.ts +203 -182
- package/src/device/robotvacuumcleaner.ts +280 -269
- package/src/device/waterdetector.ts +198 -189
- package/src/homebridge-ui/server.ts +16 -15
- package/src/index.ts +5 -6
- package/src/irdevice/airconditioner.ts +280 -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 +1493 -1681
- package/src/settings.ts +172 -169
- package/src/types/bledevicestatus.ts +255 -255
- 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 -127
- 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/dist/platform.js
CHANGED
|
@@ -1,55 +1,58 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
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 { SwitchBotModel } from 'node-switchbot';
|
|
14
|
+
import { queueScheduler } from 'rxjs';
|
|
15
|
+
import { request } from 'undici';
|
|
16
|
+
import { BlindTilt } from './device/blindtilt.js';
|
|
17
|
+
import { Bot } from './device/bot-old.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
|
-
import { SwitchBotModel } from 'node-switchbot';
|
|
44
45
|
/**
|
|
45
46
|
* HomebridgePlatform
|
|
46
47
|
* This class is the main constructor for your plugin, this is where you should
|
|
47
48
|
* parse the user config and discover/register accessories with Homebridge.
|
|
48
49
|
*/
|
|
49
50
|
export class SwitchBotPlatform {
|
|
50
|
-
|
|
51
|
+
// Platform properties
|
|
52
|
+
accessories = [];
|
|
51
53
|
api;
|
|
52
54
|
log;
|
|
55
|
+
// Configuration properties
|
|
53
56
|
version;
|
|
54
57
|
Logging;
|
|
55
58
|
debugMode;
|
|
@@ -58,15 +61,16 @@ export class SwitchBotPlatform {
|
|
|
58
61
|
platformConfig;
|
|
59
62
|
platformLogging;
|
|
60
63
|
config;
|
|
64
|
+
// MQTT and Webhook properties
|
|
61
65
|
mqttClient = null;
|
|
62
66
|
webhookEventListener = null;
|
|
67
|
+
// External APIs
|
|
63
68
|
eve;
|
|
64
69
|
fakegatoAPI;
|
|
70
|
+
// Event Handlers
|
|
65
71
|
webhookEventHandler = {};
|
|
66
72
|
bleEventHandler = {};
|
|
67
73
|
constructor(log, config, api) {
|
|
68
|
-
// initialize
|
|
69
|
-
this.accessories = [];
|
|
70
74
|
this.api = api;
|
|
71
75
|
this.log = log;
|
|
72
76
|
// only load if configured
|
|
@@ -104,27 +108,42 @@ export class SwitchBotPlatform {
|
|
|
104
108
|
// in order to ensure they weren't added to homebridge already. This event can also be used
|
|
105
109
|
// to start discovery of new accessories.
|
|
106
110
|
this.api.on('didFinishLaunching', async () => {
|
|
107
|
-
this.debugLog('Executed didFinishLaunching callback');
|
|
111
|
+
await this.debugLog('Executed didFinishLaunching callback');
|
|
108
112
|
// run the method to discover / register your devices as accessories
|
|
109
113
|
try {
|
|
110
114
|
if (this.config.credentials?.openToken && !this.config.credentials.token) {
|
|
111
115
|
await this.updateToken();
|
|
112
116
|
}
|
|
113
117
|
else if (this.config.credentials?.token && !this.config.credentials?.secret) {
|
|
114
|
-
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.');
|
|
115
119
|
}
|
|
116
120
|
else {
|
|
117
|
-
this.discoverDevices();
|
|
121
|
+
await this.discoverDevices();
|
|
118
122
|
}
|
|
119
123
|
}
|
|
120
124
|
catch (e) {
|
|
121
|
-
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');
|
|
122
126
|
await this.debugErrorLog(`Failed to Discover, Error: ${e}`);
|
|
123
127
|
}
|
|
124
128
|
});
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
129
|
+
try {
|
|
130
|
+
this.setupMqtt();
|
|
131
|
+
}
|
|
132
|
+
catch (e) {
|
|
133
|
+
this.errorLog(`Setup MQTT, Error Message: ${e.message}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug');
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
this.setupwebhook();
|
|
137
|
+
}
|
|
138
|
+
catch (e) {
|
|
139
|
+
this.errorLog(`Setup Webhook, Error Message: ${e.message}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug');
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
this.setupBlE();
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
this.errorLog(`Setup Platform BLE, Error Message: ${e.message}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug');
|
|
146
|
+
}
|
|
128
147
|
}
|
|
129
148
|
async setupMqtt() {
|
|
130
149
|
if (this.config.options?.mqttURL) {
|
|
@@ -141,7 +160,7 @@ export class SwitchBotPlatform {
|
|
|
141
160
|
this.mqttClient.subscribe('homebridge-switchbot/webhook/+');
|
|
142
161
|
this.mqttClient.on('message', async (topic, message) => {
|
|
143
162
|
try {
|
|
144
|
-
await
|
|
163
|
+
await this.debugLog(`Received Webhook via MQTT: ${topic}=${message}`);
|
|
145
164
|
const context = JSON.parse(message.toString());
|
|
146
165
|
this.webhookEventHandler[context.deviceMac]?.(context);
|
|
147
166
|
}
|
|
@@ -158,7 +177,7 @@ export class SwitchBotPlatform {
|
|
|
158
177
|
}
|
|
159
178
|
}
|
|
160
179
|
async setupwebhook() {
|
|
161
|
-
//webhook configuration
|
|
180
|
+
// webhook configuration
|
|
162
181
|
if (this.config.options?.webhookURL) {
|
|
163
182
|
const url = this.config.options?.webhookURL;
|
|
164
183
|
try {
|
|
@@ -173,17 +192,14 @@ export class SwitchBotPlatform {
|
|
|
173
192
|
const body = JSON.parse(data);
|
|
174
193
|
await this.debugLog(`Received Webhook: ${JSON.stringify(body)}`);
|
|
175
194
|
if (this.config.options?.mqttURL) {
|
|
176
|
-
const mac = body.context.deviceMac
|
|
177
|
-
?.toLowerCase()
|
|
178
|
-
.match(/[\s\S]{1,2}/g)
|
|
179
|
-
?.join(':');
|
|
195
|
+
const mac = body.context.deviceMac?.toLowerCase().match(/[\s\S]{1,2}/g)?.join(':');
|
|
180
196
|
const options = this.config.options?.mqttPubOptions || {};
|
|
181
197
|
this.mqttClient?.publish(`homebridge-switchbot/webhook/${mac}`, `${JSON.stringify(body.context)}`, options);
|
|
182
198
|
}
|
|
183
199
|
this.webhookEventHandler[body.context.deviceMac]?.(body.context);
|
|
184
200
|
}
|
|
185
201
|
catch (e) {
|
|
186
|
-
this.errorLog(`Failed to handle webhook event. Error:${e}`);
|
|
202
|
+
await this.errorLog(`Failed to handle webhook event. Error:${e}`);
|
|
187
203
|
}
|
|
188
204
|
});
|
|
189
205
|
response.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
@@ -197,10 +213,10 @@ export class SwitchBotPlatform {
|
|
|
197
213
|
catch (e) {
|
|
198
214
|
this.errorLog(`Failed to handle webhook event. Error:${e}`);
|
|
199
215
|
}
|
|
200
|
-
}).listen(port
|
|
216
|
+
}).listen(port || 80);
|
|
201
217
|
}
|
|
202
218
|
catch (e) {
|
|
203
|
-
this.errorLog(`Failed to create webhook listener. Error:${e.message}`);
|
|
219
|
+
await this.errorLog(`Failed to create webhook listener. Error:${e.message}`);
|
|
204
220
|
return;
|
|
205
221
|
}
|
|
206
222
|
try {
|
|
@@ -208,64 +224,61 @@ export class SwitchBotPlatform {
|
|
|
208
224
|
method: 'POST',
|
|
209
225
|
headers: this.generateHeaders(),
|
|
210
226
|
body: JSON.stringify({
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
227
|
+
action: 'setupWebhook',
|
|
228
|
+
url,
|
|
229
|
+
deviceList: 'ALL',
|
|
214
230
|
}),
|
|
215
231
|
});
|
|
216
232
|
const response = await body.json();
|
|
217
|
-
await this.debugLog(`setupWebhook: url:${url}`);
|
|
218
|
-
await this.debugLog(`setupWebhook: body:${JSON.stringify(response)}`);
|
|
219
|
-
await this.debugLog(`setupWebhook: statusCode:${statusCode}`);
|
|
233
|
+
await this.debugLog(`setupWebhook: url:${url}, body:${JSON.stringify(response)}, statusCode:${statusCode}`);
|
|
220
234
|
if (statusCode !== 200 || response?.statusCode !== 100) {
|
|
221
|
-
this.errorLog(`Failed to configure webhook. Existing webhook well be overridden. HTTP:${statusCode} API:${response?.statusCode} `
|
|
222
|
-
+ `message:${response?.message}`);
|
|
235
|
+
await this.errorLog(`Failed to configure webhook. Existing webhook well be overridden. HTTP:${statusCode} API:${response?.statusCode} message:${response?.message}`);
|
|
223
236
|
}
|
|
224
237
|
}
|
|
225
238
|
catch (e) {
|
|
226
|
-
this.errorLog(`Failed to configure webhook. Error: ${e.message}`);
|
|
239
|
+
await this.errorLog(`Failed to configure webhook. Error: ${e.message}`);
|
|
227
240
|
}
|
|
228
241
|
try {
|
|
229
242
|
const { body, statusCode } = await request(updateWebhook, {
|
|
230
|
-
method: 'POST',
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
243
|
+
method: 'POST',
|
|
244
|
+
headers: this.generateHeaders(),
|
|
245
|
+
body: JSON.stringify({
|
|
246
|
+
action: 'updateWebhook',
|
|
247
|
+
config: {
|
|
248
|
+
url,
|
|
249
|
+
enable: true,
|
|
235
250
|
},
|
|
236
251
|
}),
|
|
237
252
|
});
|
|
238
253
|
const response = await body.json();
|
|
239
|
-
await this.debugLog(`updateWebhook: url:${url}`);
|
|
240
|
-
await this.debugLog(`updateWebhook: body:${JSON.stringify(response)}`);
|
|
241
|
-
await this.debugLog(`updateWebhook: statusCode:${statusCode}`);
|
|
254
|
+
await this.debugLog(`updateWebhook: url:${url}, body:${JSON.stringify(response)}, statusCode:${statusCode}`);
|
|
242
255
|
if (statusCode !== 200 || response?.statusCode !== 100) {
|
|
243
|
-
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}`);
|
|
244
257
|
}
|
|
245
258
|
}
|
|
246
259
|
catch (e) {
|
|
247
|
-
this.errorLog(`Failed to update webhook. Error:${e.message}`);
|
|
260
|
+
await this.errorLog(`Failed to update webhook. Error:${e.message}`);
|
|
248
261
|
}
|
|
249
262
|
try {
|
|
250
263
|
const { body, statusCode } = await request(queryWebhook, {
|
|
251
264
|
method: 'POST',
|
|
252
265
|
headers: this.generateHeaders(),
|
|
253
266
|
body: JSON.stringify({
|
|
254
|
-
|
|
267
|
+
action: 'queryUrl',
|
|
255
268
|
}),
|
|
256
269
|
});
|
|
257
270
|
const response = await body.json();
|
|
258
271
|
await this.debugLog(`queryWebhook: body:${JSON.stringify(response)}`);
|
|
259
272
|
await this.debugLog(`queryWebhook: statusCode:${statusCode}`);
|
|
260
273
|
if (statusCode !== 200 || response?.statusCode !== 100) {
|
|
261
|
-
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}`);
|
|
262
275
|
}
|
|
263
276
|
else {
|
|
264
|
-
this.infoLog(`Listening webhook on ${response?.body?.urls[0]}`);
|
|
277
|
+
await this.infoLog(`Listening webhook on ${response?.body?.urls[0]}`);
|
|
265
278
|
}
|
|
266
279
|
}
|
|
267
280
|
catch (e) {
|
|
268
|
-
this.errorLog(`Failed to query webhook. Error:${e}`);
|
|
281
|
+
await this.errorLog(`Failed to query webhook. Error:${e}`);
|
|
269
282
|
}
|
|
270
283
|
this.api.on('shutdown', async () => {
|
|
271
284
|
try {
|
|
@@ -273,21 +286,21 @@ export class SwitchBotPlatform {
|
|
|
273
286
|
method: 'POST',
|
|
274
287
|
headers: this.generateHeaders(),
|
|
275
288
|
body: JSON.stringify({
|
|
276
|
-
|
|
277
|
-
|
|
289
|
+
action: 'deleteWebhook',
|
|
290
|
+
url,
|
|
278
291
|
}),
|
|
279
292
|
});
|
|
280
293
|
const response = await body.json();
|
|
281
294
|
await this.debugLog(`deleteWebhook: url:${url}, body:${JSON.stringify(response)}, statusCode:${statusCode}`);
|
|
282
295
|
if (statusCode !== 200 || response?.statusCode !== 100) {
|
|
283
|
-
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}`);
|
|
284
297
|
}
|
|
285
298
|
else {
|
|
286
|
-
this.infoLog('Unregistered webhook to close listening.');
|
|
299
|
+
await this.infoLog('Unregistered webhook to close listening.');
|
|
287
300
|
}
|
|
288
301
|
}
|
|
289
302
|
catch (e) {
|
|
290
|
-
this.errorLog(`Failed to delete webhook. Error:${e.message}`);
|
|
303
|
+
await this.errorLog(`Failed to delete webhook. Error:${e.message}`);
|
|
291
304
|
}
|
|
292
305
|
});
|
|
293
306
|
}
|
|
@@ -319,10 +332,10 @@ export class SwitchBotPlatform {
|
|
|
319
332
|
this.api.on('shutdown', async () => {
|
|
320
333
|
try {
|
|
321
334
|
switchbot.stopScan();
|
|
322
|
-
this.infoLog('Stopped BLE scanning to close listening.');
|
|
335
|
+
await this.infoLog('Stopped BLE scanning to close listening.');
|
|
323
336
|
}
|
|
324
337
|
catch (e) {
|
|
325
|
-
this.errorLog(`Failed to stop Platform BLE scanning. Error:${e.message}`);
|
|
338
|
+
await this.errorLog(`Failed to stop Platform BLE scanning. Error:${e.message}`);
|
|
326
339
|
}
|
|
327
340
|
});
|
|
328
341
|
}
|
|
@@ -336,7 +349,8 @@ export class SwitchBotPlatform {
|
|
|
336
349
|
* It should be used to setup event handlers for characteristics and update respective values.
|
|
337
350
|
*/
|
|
338
351
|
async configureAccessory(accessory) {
|
|
339
|
-
|
|
352
|
+
const { displayName } = accessory;
|
|
353
|
+
await this.debugLog(`Loading accessory from cache: ${displayName}`);
|
|
340
354
|
// add the restored accessory to the accessories cache so we can track if it has already been registered
|
|
341
355
|
this.accessories.push(accessory);
|
|
342
356
|
}
|
|
@@ -344,18 +358,18 @@ export class SwitchBotPlatform {
|
|
|
344
358
|
* Verify the config passed to the plugin is valid
|
|
345
359
|
*/
|
|
346
360
|
async verifyConfig() {
|
|
347
|
-
this.debugLog('Verifying Config');
|
|
361
|
+
await this.debugLog('Verifying Config');
|
|
348
362
|
this.config = this.config || {};
|
|
349
363
|
this.config.options = this.config.options || {};
|
|
350
364
|
const platformConfig = {};
|
|
351
365
|
if (this.config.options.logging) {
|
|
352
|
-
platformConfig
|
|
366
|
+
platformConfig.logging = this.config.options.logging;
|
|
353
367
|
}
|
|
354
368
|
if (this.config.options.logging && this.config.options.refreshRate) {
|
|
355
|
-
platformConfig
|
|
369
|
+
platformConfig.refreshRate = this.config.options.refreshRate;
|
|
356
370
|
}
|
|
357
371
|
if (this.config.options.logging && this.config.options.pushRate) {
|
|
358
|
-
platformConfig
|
|
372
|
+
platformConfig.pushRate = this.config.options.pushRate;
|
|
359
373
|
}
|
|
360
374
|
if (Object.entries(platformConfig).length !== 0) {
|
|
361
375
|
await this.debugWarnLog(`Platform Config: ${JSON.stringify(platformConfig)}`);
|
|
@@ -379,10 +393,10 @@ export class SwitchBotPlatform {
|
|
|
379
393
|
for (const irDeviceConfig of this.config.options.irdevices) {
|
|
380
394
|
if (!irDeviceConfig.hide_device) {
|
|
381
395
|
if (!irDeviceConfig.deviceId) {
|
|
382
|
-
this.errorLog('The devices config section is missing the *Device ID* in the config. Please check your config.');
|
|
396
|
+
await this.errorLog('The devices config section is missing the *Device ID* in the config. Please check your config.');
|
|
383
397
|
}
|
|
384
398
|
if (!irDeviceConfig.deviceId && !irDeviceConfig.configRemoteType) {
|
|
385
|
-
this.errorLog('The devices config section is missing the *Device Type* in the config. Please check your config.');
|
|
399
|
+
await this.errorLog('The devices config section is missing the *Device Type* in the config. Please check your config.');
|
|
386
400
|
}
|
|
387
401
|
}
|
|
388
402
|
}
|
|
@@ -394,16 +408,16 @@ export class SwitchBotPlatform {
|
|
|
394
408
|
if (!this.config.options.refreshRate) {
|
|
395
409
|
// default 120 seconds (2 minutes)
|
|
396
410
|
this.config.options.refreshRate = 120;
|
|
397
|
-
this.debugWarnLog('Using Default Refresh Rate (2 minutes).');
|
|
411
|
+
await this.debugWarnLog('Using Default Refresh Rate (2 minutes).');
|
|
398
412
|
}
|
|
399
413
|
if (!this.config.options.pushRate) {
|
|
400
414
|
// default 100 milliseconds
|
|
401
415
|
this.config.options.pushRate = 0.1;
|
|
402
|
-
this.debugWarnLog('Using Default Push Rate.');
|
|
416
|
+
await this.debugWarnLog('Using Default Push Rate.');
|
|
403
417
|
}
|
|
404
418
|
if (!this.config.options.maxRetries) {
|
|
405
419
|
this.config.options.maxRetries = 5;
|
|
406
|
-
this.debugWarnLog('Using Default Max Retries.');
|
|
420
|
+
await this.debugWarnLog('Using Default Max Retries.');
|
|
407
421
|
}
|
|
408
422
|
else {
|
|
409
423
|
this.maxRetries = this.config.options.maxRetries;
|
|
@@ -411,23 +425,23 @@ export class SwitchBotPlatform {
|
|
|
411
425
|
if (!this.config.options.delayBetweenRetries) {
|
|
412
426
|
// default 3 seconds
|
|
413
427
|
this.config.options.delayBetweenRetries = 3000;
|
|
414
|
-
this.debugWarnLog('Using Default Delay Between Retries.');
|
|
428
|
+
await this.debugWarnLog('Using Default Delay Between Retries.');
|
|
415
429
|
}
|
|
416
430
|
else {
|
|
417
431
|
this.delayBetweenRetries = this.config.options.delayBetweenRetries * 1000;
|
|
418
432
|
}
|
|
419
433
|
if (!this.config.credentials && !this.config.options) {
|
|
420
|
-
this.debugWarnLog('Missing Credentials');
|
|
434
|
+
await this.debugWarnLog('Missing Credentials');
|
|
421
435
|
}
|
|
422
436
|
else if (this.config.credentials && !this.config.credentials.notice) {
|
|
423
437
|
if (!this.config.credentials?.token) {
|
|
424
|
-
this.debugErrorLog('Missing token');
|
|
425
|
-
this.debugWarnLog('Cloud Enabled SwitchBot Devices & IR Devices will not work');
|
|
438
|
+
await this.debugErrorLog('Missing token');
|
|
439
|
+
await this.debugWarnLog('Cloud Enabled SwitchBot Devices & IR Devices will not work');
|
|
426
440
|
}
|
|
427
441
|
if (this.config.credentials?.token) {
|
|
428
442
|
if (!this.config.credentials?.secret) {
|
|
429
|
-
this.debugErrorLog('Missing secret');
|
|
430
|
-
this.debugWarnLog('Cloud Enabled SwitchBot Devices & IR Devices will not work');
|
|
443
|
+
await this.debugErrorLog('Missing secret');
|
|
444
|
+
await this.debugWarnLog('Cloud Enabled SwitchBot Devices & IR Devices will not work');
|
|
431
445
|
}
|
|
432
446
|
}
|
|
433
447
|
}
|
|
@@ -435,7 +449,6 @@ export class SwitchBotPlatform {
|
|
|
435
449
|
/**
|
|
436
450
|
* The openToken was old config.
|
|
437
451
|
* This method saves the openToken as the token in the config.json file
|
|
438
|
-
* @param this.config.credentials.openToken
|
|
439
452
|
*/
|
|
440
453
|
async updateToken() {
|
|
441
454
|
try {
|
|
@@ -447,7 +460,7 @@ export class SwitchBotPlatform {
|
|
|
447
460
|
const currentConfig = JSON.parse(readFileSync(this.api.user.configPath(), 'utf8'));
|
|
448
461
|
// check the platforms section is an array before we do array things on it
|
|
449
462
|
if (!Array.isArray(currentConfig.platforms)) {
|
|
450
|
-
throw new
|
|
463
|
+
throw new TypeError('Cannot find platforms array in config');
|
|
451
464
|
}
|
|
452
465
|
// find this plugins current config
|
|
453
466
|
const pluginConfig = currentConfig.platforms.find((x) => x.platform === PLATFORM_NAME);
|
|
@@ -456,17 +469,15 @@ export class SwitchBotPlatform {
|
|
|
456
469
|
}
|
|
457
470
|
// check the .credentials is an object before doing object things with it
|
|
458
471
|
if (typeof pluginConfig.credentials !== 'object') {
|
|
459
|
-
throw new
|
|
472
|
+
throw new TypeError('pluginConfig.credentials is not an object');
|
|
460
473
|
}
|
|
461
474
|
// Move openToken to token
|
|
462
475
|
if (!this.config.credentials.secret) {
|
|
463
|
-
this.warnLog('This plugin has been updated to use OpenAPI v1.1, config is set with openToken,'
|
|
464
|
-
+ ' "openToken" cconfig has been moved to the "token" config');
|
|
476
|
+
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');
|
|
465
477
|
this.errorLog('"secret" config is not populated, you must populate then please restart Homebridge.');
|
|
466
478
|
}
|
|
467
479
|
else {
|
|
468
|
-
this.warnLog('This plugin has been updated to use OpenAPI v1.1, config is set with openToken, '
|
|
469
|
-
+ '"openToken" config has been moved to the "token" config, please restart Homebridge.');
|
|
480
|
+
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.');
|
|
470
481
|
}
|
|
471
482
|
// set the refresh token
|
|
472
483
|
pluginConfig.credentials.token = this.config.credentials?.openToken;
|
|
@@ -476,10 +487,10 @@ export class SwitchBotPlatform {
|
|
|
476
487
|
await this.debugWarnLog(`token: ${pluginConfig.credentials.token}`);
|
|
477
488
|
// save the config, ensuring we maintain pretty json
|
|
478
489
|
writeFileSync(this.api.user.configPath(), JSON.stringify(currentConfig, null, 4));
|
|
479
|
-
this.verifyConfig();
|
|
490
|
+
await this.verifyConfig();
|
|
480
491
|
}
|
|
481
492
|
catch (e) {
|
|
482
|
-
this.errorLog(`Update Token: ${e}`);
|
|
493
|
+
await this.errorLog(`Update Token: ${e}`);
|
|
483
494
|
}
|
|
484
495
|
}
|
|
485
496
|
generateHeaders = () => {
|
|
@@ -492,340 +503,228 @@ export class SwitchBotPlatform {
|
|
|
492
503
|
.digest();
|
|
493
504
|
const sign = signTerm.toString('base64');
|
|
494
505
|
return {
|
|
495
|
-
Authorization: this.config.credentials?.token,
|
|
496
|
-
sign: sign,
|
|
497
|
-
nonce: nonce,
|
|
498
|
-
t: t,
|
|
506
|
+
'Authorization': this.config.credentials?.token,
|
|
507
|
+
'sign': sign,
|
|
508
|
+
'nonce': nonce,
|
|
509
|
+
't': t,
|
|
499
510
|
'Content-Type': 'application/json',
|
|
500
511
|
};
|
|
501
512
|
};
|
|
502
|
-
/**
|
|
503
|
-
* this method discovers devices
|
|
504
|
-
*
|
|
505
|
-
const t = `${Date.now()}`;
|
|
506
|
-
const nonce = 'requestID';
|
|
507
|
-
const data = this.config.credentials?.token + t + nonce;
|
|
508
|
-
const signTerm = crypto.createHmac('sha256', this.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
509
|
-
const sign = signTerm.toString('base64');
|
|
510
|
-
*/
|
|
511
513
|
async discoverDevices() {
|
|
512
|
-
if (this.config.credentials?.token) {
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
await this.
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
// SwitchBot Devices
|
|
532
|
-
const deviceLists = devicesAPI.body.deviceList;
|
|
533
|
-
await this.debugWarnLog(`DeviceLists: ${JSON.stringify(deviceLists)}`);
|
|
534
|
-
await this.debugWarnLog(`DeviceLists Length: ${deviceLists.length}`);
|
|
535
|
-
if (!this.config.options?.devices) {
|
|
536
|
-
await this.debugLog(`SwitchBot Device Config Not Set: ${JSON.stringify(this.config.options?.devices)}`);
|
|
537
|
-
if (deviceLists.length === 0) {
|
|
538
|
-
await this.debugLog(`SwitchBot API Has No Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
|
|
539
|
-
}
|
|
540
|
-
else {
|
|
541
|
-
const devices = deviceLists.map((v) => v);
|
|
542
|
-
for (const device of devices) {
|
|
543
|
-
if (device.deviceType) {
|
|
544
|
-
if (device.configDeviceName) {
|
|
545
|
-
device.deviceName = device.configDeviceName;
|
|
546
|
-
}
|
|
547
|
-
this.createDevice(device);
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
else if (this.config.credentials?.token && this.config.options.devices) {
|
|
553
|
-
await this.debugLog(`SwitchBot Device Config Set: ${JSON.stringify(this.config.options?.devices)}`);
|
|
554
|
-
if (deviceLists.length === 0) {
|
|
555
|
-
await this.debugLog(`SwitchBot API Has No Devices With Cloud Services Enabled: ${JSON.stringify(devicesAPI.body)}`);
|
|
556
|
-
}
|
|
557
|
-
else {
|
|
558
|
-
const deviceConfigs = this.config.options?.devices;
|
|
559
|
-
const mergeBydeviceId = (a1, a2) => a1.map((itm) => ({
|
|
560
|
-
...a2.find((item) => item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item),
|
|
561
|
-
...itm,
|
|
562
|
-
}));
|
|
563
|
-
const devices = mergeBydeviceId(deviceLists, deviceConfigs);
|
|
564
|
-
await this.debugLog(`SwitchBot Devices: ${JSON.stringify(devices)}`);
|
|
565
|
-
for (const device of devices) {
|
|
566
|
-
if (!device.deviceType) {
|
|
567
|
-
device.deviceType = device.configDeviceType;
|
|
568
|
-
this.errorLog(`API has displaying no deviceType: ${device.deviceType}, So using configDeviceType: ${device.configDeviceType}`);
|
|
569
|
-
}
|
|
570
|
-
if (device.deviceType) {
|
|
571
|
-
if (device.configDeviceName) {
|
|
572
|
-
device.deviceName = device.configDeviceName;
|
|
573
|
-
}
|
|
574
|
-
this.createDevice(device);
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
else {
|
|
580
|
-
this.errorLog('SwitchBot Token Supplied, Issue with Auth.');
|
|
581
|
-
}
|
|
582
|
-
if (devicesAPI.body.deviceList.length !== 0) {
|
|
583
|
-
this.infoLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
|
|
584
|
-
}
|
|
585
|
-
else {
|
|
586
|
-
await this.debugLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
|
|
587
|
-
}
|
|
588
|
-
// IR Devices
|
|
589
|
-
const irDeviceLists = devicesAPI.body.infraredRemoteList;
|
|
590
|
-
if (!this.config.options?.irdevices) {
|
|
591
|
-
await this.debugLog(`IR Device Config Not Set: ${JSON.stringify(this.config.options?.irdevices)}`);
|
|
592
|
-
const devices = irDeviceLists.map((v) => v);
|
|
593
|
-
for (const device of devices) {
|
|
594
|
-
if (device.remoteType) {
|
|
595
|
-
this.createIRDevice(device);
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
else {
|
|
600
|
-
await this.debugLog(`IR Device Config Set: ${JSON.stringify(this.config.options?.irdevices)}`);
|
|
601
|
-
const irDeviceConfig = this.config.options?.irdevices;
|
|
602
|
-
const mergeIRBydeviceId = (a1, a2) => a1.map((itm) => ({
|
|
603
|
-
...a2.find((item) => item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item),
|
|
604
|
-
...itm,
|
|
605
|
-
}));
|
|
606
|
-
const devices = mergeIRBydeviceId(irDeviceLists, irDeviceConfig);
|
|
607
|
-
await this.debugLog(`IR Devices: ${JSON.stringify(devices)}`);
|
|
608
|
-
for (const device of devices) {
|
|
609
|
-
this.createIRDevice(device);
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
if (devicesAPI.body.infraredRemoteList.length !== 0) {
|
|
613
|
-
this.infoLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
|
|
614
|
-
}
|
|
615
|
-
else {
|
|
616
|
-
await this.debugLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
|
|
617
|
-
}
|
|
618
|
-
break;
|
|
619
|
-
}
|
|
620
|
-
else {
|
|
621
|
-
this.statusCode(statusCode);
|
|
622
|
-
this.statusCode(devicesAPI.statusCode);
|
|
623
|
-
if (statusCode === 500) {
|
|
624
|
-
retryCount++;
|
|
625
|
-
this.infoLog(`statusCode: ${statusCode} Attempt ${retryCount} of ${maxRetries}`);
|
|
626
|
-
await sleep(delayBetweenRetries);
|
|
627
|
-
}
|
|
628
|
-
}
|
|
514
|
+
if (!this.config.credentials?.token) {
|
|
515
|
+
return this.handleManualConfig();
|
|
516
|
+
}
|
|
517
|
+
let retryCount = 0;
|
|
518
|
+
const maxRetries = this.maxRetries;
|
|
519
|
+
const delayBetweenRetries = this.delayBetweenRetries;
|
|
520
|
+
await this.debugWarnLog(`Retry Count: ${retryCount}`);
|
|
521
|
+
await this.debugWarnLog(`Max Retries: ${maxRetries}`);
|
|
522
|
+
await this.debugWarnLog(`Delay Between Retries: ${delayBetweenRetries}`);
|
|
523
|
+
while (retryCount < maxRetries) {
|
|
524
|
+
try {
|
|
525
|
+
const { body, statusCode } = await request(Devices, { headers: this.generateHeaders() });
|
|
526
|
+
await this.debugWarnLog(`statusCode: ${statusCode}`);
|
|
527
|
+
const devicesAPI = await body.json();
|
|
528
|
+
await this.debugWarnLog(`devicesAPI: ${JSON.stringify(devicesAPI)}`);
|
|
529
|
+
if (this.isSuccessfulResponse(statusCode, devicesAPI.statusCode)) {
|
|
530
|
+
await this.handleDevices(devicesAPI.body.deviceList);
|
|
531
|
+
await this.handleIRDevices(devicesAPI.body.infraredRemoteList);
|
|
532
|
+
break;
|
|
629
533
|
}
|
|
630
|
-
|
|
534
|
+
else {
|
|
535
|
+
await this.handleErrorResponse(statusCode, devicesAPI.statusCode, retryCount, maxRetries, delayBetweenRetries);
|
|
631
536
|
retryCount++;
|
|
632
|
-
this.debugErrorLog(`Failed to Discover Devices, Error Message: ${JSON.stringify(e.message)}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug');
|
|
633
|
-
await this.debugErrorLog(`Failed to Discover Devices, Error: ${e}`);
|
|
634
537
|
}
|
|
635
538
|
}
|
|
539
|
+
catch (e) {
|
|
540
|
+
retryCount++;
|
|
541
|
+
await this.debugErrorLog(`Failed to Discover Devices, Error Message: ${JSON.stringify(e.message)}, Submit Bugs Here: https://tinyurl.com/SwitchBotBug`);
|
|
542
|
+
await this.debugErrorLog(`Failed to Discover Devices, Error: ${e}`);
|
|
543
|
+
}
|
|
636
544
|
}
|
|
637
|
-
|
|
545
|
+
}
|
|
546
|
+
async handleManualConfig() {
|
|
547
|
+
if (this.config.options?.devices) {
|
|
638
548
|
await this.debugLog(`SwitchBot Device Manual Config Set: ${JSON.stringify(this.config.options?.devices)}`);
|
|
639
|
-
const
|
|
640
|
-
const devices = deviceConfigs.map((v) => v);
|
|
549
|
+
const devices = this.config.options.devices.map((v) => v);
|
|
641
550
|
for (const device of devices) {
|
|
642
551
|
device.deviceType = device.configDeviceType;
|
|
643
552
|
device.deviceName = device.configDeviceName;
|
|
644
553
|
if (device.deviceType) {
|
|
645
|
-
this.createDevice(device);
|
|
554
|
+
await this.createDevice(device);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
else {
|
|
559
|
+
await this.errorLog('Neither SwitchBot Token or Device Config are set.');
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
isSuccessfulResponse(statusCode, apiStatusCode) {
|
|
563
|
+
return (statusCode === 200 || statusCode === 100) && (apiStatusCode === 200 || apiStatusCode === 100);
|
|
564
|
+
}
|
|
565
|
+
async handleDevices(deviceLists) {
|
|
566
|
+
if (!this.config.options?.devices) {
|
|
567
|
+
await this.debugLog(`SwitchBot Device Config Not Set: ${JSON.stringify(this.config.options?.devices)}`);
|
|
568
|
+
if (deviceLists.length === 0) {
|
|
569
|
+
await this.debugLog('SwitchBot API Has No Devices With Cloud Services Enabled');
|
|
570
|
+
}
|
|
571
|
+
else {
|
|
572
|
+
for (const device of deviceLists) {
|
|
573
|
+
if (device.deviceType) {
|
|
574
|
+
if (device.configDeviceName) {
|
|
575
|
+
device.deviceName = device.configDeviceName;
|
|
576
|
+
}
|
|
577
|
+
await this.createDevice(device);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
else {
|
|
583
|
+
await this.debugLog(`SwitchBot Device Config Set: ${JSON.stringify(this.config.options?.devices)}`);
|
|
584
|
+
const devices = this.mergeByDeviceId(deviceLists, this.config.options.devices);
|
|
585
|
+
await this.debugLog(`SwitchBot Devices: ${JSON.stringify(devices)}`);
|
|
586
|
+
for (const device of devices) {
|
|
587
|
+
if (!device.deviceType && device.configDeviceType) {
|
|
588
|
+
device.deviceType = device.configDeviceType;
|
|
589
|
+
await this.warnLog(`API is displaying no deviceType: ${device.deviceType}, So using configDeviceType: ${device.configDeviceType}`);
|
|
590
|
+
}
|
|
591
|
+
else if (!device.deviceType && !device.configDeviceName) {
|
|
592
|
+
await this.errorLog('No deviceType or configDeviceType for device. No device will be created.');
|
|
593
|
+
}
|
|
594
|
+
if (device.deviceType) {
|
|
595
|
+
if (device.configDeviceName) {
|
|
596
|
+
device.deviceName = device.configDeviceName;
|
|
597
|
+
}
|
|
598
|
+
await this.createDevice(device);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
async handleIRDevices(irDeviceLists) {
|
|
604
|
+
if (!this.config.options?.irdevices) {
|
|
605
|
+
await this.debugLog(`IR Device Config Not Set: ${JSON.stringify(this.config.options?.irdevices)}`);
|
|
606
|
+
for (const device of irDeviceLists) {
|
|
607
|
+
if (device.remoteType) {
|
|
608
|
+
await this.createIRDevice(device);
|
|
646
609
|
}
|
|
647
610
|
}
|
|
648
611
|
}
|
|
649
612
|
else {
|
|
650
|
-
this.
|
|
613
|
+
await this.debugLog(`IR Device Config Set: ${JSON.stringify(this.config.options?.irdevices)}`);
|
|
614
|
+
const devices = this.mergeByDeviceId(irDeviceLists, this.config.options.irdevices);
|
|
615
|
+
await this.debugLog(`IR Devices: ${JSON.stringify(devices)}`);
|
|
616
|
+
for (const device of devices) {
|
|
617
|
+
await this.createIRDevice(device);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
mergeByDeviceId(a1, a2) {
|
|
622
|
+
const normalizeDeviceId = (deviceId) => deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '');
|
|
623
|
+
return a1.map((itm) => {
|
|
624
|
+
const matchingItem = a2.find(item => normalizeDeviceId(item.deviceId) === normalizeDeviceId(itm.deviceId));
|
|
625
|
+
return { ...matchingItem, ...itm };
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
async handleErrorResponse(statusCode, apiStatusCode, retryCount, maxRetries, delayBetweenRetries) {
|
|
629
|
+
await this.statusCode(statusCode);
|
|
630
|
+
await this.statusCode(apiStatusCode);
|
|
631
|
+
if (statusCode === 500) {
|
|
632
|
+
this.infoLog(`statusCode: ${statusCode} Attempt ${retryCount + 1} of ${maxRetries}`);
|
|
633
|
+
await sleep(delayBetweenRetries);
|
|
651
634
|
}
|
|
652
635
|
}
|
|
653
636
|
async createDevice(device) {
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
this.createContact(device);
|
|
697
|
-
break;
|
|
698
|
-
case 'Curtain':
|
|
699
|
-
case 'Curtain3':
|
|
700
|
-
await this.debugLog(`Discovered ${device.deviceType} ${device.deviceName}: ${device.deviceId}`);
|
|
701
|
-
this.createCurtain(device);
|
|
702
|
-
break;
|
|
703
|
-
case 'Blind Tilt':
|
|
704
|
-
await this.debugLog(`Discovered ${device.deviceType} ${device.deviceName}: ${device.deviceId}`);
|
|
705
|
-
this.createBlindTilt(device);
|
|
706
|
-
break;
|
|
707
|
-
case 'Plug':
|
|
708
|
-
case 'Plug Mini (US)':
|
|
709
|
-
case 'Plug Mini (JP)':
|
|
710
|
-
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
|
|
711
|
-
this.createPlug(device);
|
|
712
|
-
break;
|
|
713
|
-
case 'Smart Lock':
|
|
714
|
-
case 'Smart Lock Pro':
|
|
715
|
-
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
|
|
716
|
-
this.createLock(device);
|
|
717
|
-
break;
|
|
718
|
-
case 'Color Bulb':
|
|
719
|
-
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
|
|
720
|
-
this.createColorBulb(device);
|
|
721
|
-
break;
|
|
722
|
-
case 'K10+':
|
|
723
|
-
case 'WoSweeper':
|
|
724
|
-
case 'WoSweeperMini':
|
|
725
|
-
case 'Robot Vacuum Cleaner S1':
|
|
726
|
-
case 'Robot Vacuum Cleaner S1 Plus':
|
|
727
|
-
case 'Robot Vacuum Cleaner S10':
|
|
728
|
-
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
|
|
729
|
-
this.createRobotVacuumCleaner(device);
|
|
730
|
-
break;
|
|
731
|
-
case 'Ceiling Light':
|
|
732
|
-
case 'Ceiling Light Pro':
|
|
733
|
-
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
|
|
734
|
-
this.createCeilingLight(device);
|
|
735
|
-
break;
|
|
736
|
-
case 'Strip Light':
|
|
737
|
-
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
|
|
738
|
-
this.createStripLight(device);
|
|
739
|
-
break;
|
|
740
|
-
case 'Battery Circulator Fan':
|
|
741
|
-
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
|
|
742
|
-
this.createFan(device);
|
|
743
|
-
break;
|
|
744
|
-
case 'Remote':
|
|
745
|
-
case 'Indoor Cam':
|
|
746
|
-
case 'remote with screen+':
|
|
747
|
-
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}, is currently not supported, device: ${JSON.stringify(device)}`);
|
|
748
|
-
break;
|
|
749
|
-
default:
|
|
750
|
-
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)}`);
|
|
637
|
+
const deviceTypeHandlers = {
|
|
638
|
+
'Humidifier': this.createHumidifier.bind(this),
|
|
639
|
+
'Hub 2': this.createHub2.bind(this),
|
|
640
|
+
'Bot': this.createBot.bind(this),
|
|
641
|
+
'Meter': this.createMeter.bind(this),
|
|
642
|
+
'MeterPlus': this.createMeterPlus.bind(this),
|
|
643
|
+
'Meter Plus (JP)': this.createMeterPlus.bind(this),
|
|
644
|
+
'WoIOSensor': this.createIOSensor.bind(this),
|
|
645
|
+
'Water Detector': this.createWaterDetector.bind(this),
|
|
646
|
+
'Motion Sensor': this.createMotion.bind(this),
|
|
647
|
+
'Contact Sensor': this.createContact.bind(this),
|
|
648
|
+
'Curtain': this.createCurtain.bind(this),
|
|
649
|
+
'Curtain3': this.createCurtain.bind(this),
|
|
650
|
+
'WoRollerShade': this.createCurtain.bind(this),
|
|
651
|
+
'Roller Shade': this.createCurtain.bind(this),
|
|
652
|
+
'Blind Tilt': this.createBlindTilt.bind(this),
|
|
653
|
+
'Plug': this.createPlug.bind(this),
|
|
654
|
+
'Plug Mini (US)': this.createPlug.bind(this),
|
|
655
|
+
'Plug Mini (JP)': this.createPlug.bind(this),
|
|
656
|
+
'Smart Lock': this.createLock.bind(this),
|
|
657
|
+
'Smart Lock Pro': this.createLock.bind(this),
|
|
658
|
+
'Color Bulb': this.createColorBulb.bind(this),
|
|
659
|
+
'K10+': this.createRobotVacuumCleaner.bind(this),
|
|
660
|
+
'WoSweeper': this.createRobotVacuumCleaner.bind(this),
|
|
661
|
+
'WoSweeperMini': this.createRobotVacuumCleaner.bind(this),
|
|
662
|
+
'Robot Vacuum Cleaner S1': this.createRobotVacuumCleaner.bind(this),
|
|
663
|
+
'Robot Vacuum Cleaner S1 Plus': this.createRobotVacuumCleaner.bind(this),
|
|
664
|
+
'Robot Vacuum Cleaner S10': this.createRobotVacuumCleaner.bind(this),
|
|
665
|
+
'Ceiling Light': this.createCeilingLight.bind(this),
|
|
666
|
+
'Ceiling Light Pro': this.createCeilingLight.bind(this),
|
|
667
|
+
'Strip Light': this.createStripLight.bind(this),
|
|
668
|
+
'Battery Circulator Fan': this.createFan.bind(this),
|
|
669
|
+
};
|
|
670
|
+
if (deviceTypeHandlers[device.deviceType]) {
|
|
671
|
+
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
|
|
672
|
+
await deviceTypeHandlers[device.deviceType](device);
|
|
673
|
+
}
|
|
674
|
+
else if (['Hub Mini', 'Hub Plus', 'Remote', 'Indoor Cam', 'remote with screen'].includes(device.deviceType)) {
|
|
675
|
+
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}, is currently not supported, device: ${JSON.stringify(device)}`);
|
|
676
|
+
}
|
|
677
|
+
else {
|
|
678
|
+
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)}`);
|
|
751
679
|
}
|
|
752
680
|
}
|
|
753
681
|
async createIRDevice(device) {
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
break;
|
|
794
|
-
case 'Air Purifier':
|
|
795
|
-
case 'DIY Air Purifier':
|
|
796
|
-
await this.debugLog(`Discovered ${device.remoteType}: ${device.deviceId}`);
|
|
797
|
-
this.createAirPurifier(device);
|
|
798
|
-
break;
|
|
799
|
-
case 'Water Heater':
|
|
800
|
-
case 'DIY Water Heater':
|
|
801
|
-
await this.debugLog(`Discovered ${device.remoteType}: ${device.deviceId}`);
|
|
802
|
-
this.createWaterHeater(device);
|
|
803
|
-
break;
|
|
804
|
-
case 'Vacuum Cleaner':
|
|
805
|
-
case 'DIY Vacuum Cleaner':
|
|
806
|
-
await this.debugLog(`Discovered ${device.remoteType}: ${device.deviceId}`);
|
|
807
|
-
this.createVacuumCleaner(device);
|
|
808
|
-
break;
|
|
809
|
-
case 'Camera':
|
|
810
|
-
case 'DIY Camera':
|
|
811
|
-
await this.debugLog(`Discovered ${device.remoteType}: ${device.deviceId}`);
|
|
812
|
-
this.createCamera(device);
|
|
813
|
-
break;
|
|
814
|
-
case 'Others':
|
|
815
|
-
await this.debugLog(`Discovered ${device.remoteType}: ${device.deviceId}`);
|
|
816
|
-
this.createOthers(device);
|
|
817
|
-
break;
|
|
818
|
-
default:
|
|
819
|
-
await this.debugLog(`Unsupported Device: ${JSON.stringify(device)}`);
|
|
820
|
-
this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.remoteType}, is currently not supported.`);
|
|
821
|
-
this.warnLog('Submit Feature Requests Here: ' + 'https://tinyurl.com/SwitchBotFeatureRequest');
|
|
682
|
+
device.connectionType = device.connectionType ?? 'OpenAPI';
|
|
683
|
+
const deviceTypeHandlers = {
|
|
684
|
+
'TV': this.createTV.bind(this),
|
|
685
|
+
'DIY TV': this.createTV.bind(this),
|
|
686
|
+
'Projector': this.createTV.bind(this),
|
|
687
|
+
'DIY Projector': this.createTV.bind(this),
|
|
688
|
+
'Set Top Box': this.createTV.bind(this),
|
|
689
|
+
'DIY Set Top Box': this.createTV.bind(this),
|
|
690
|
+
'IPTV': this.createTV.bind(this),
|
|
691
|
+
'DIY IPTV': this.createTV.bind(this),
|
|
692
|
+
'DVD': this.createTV.bind(this),
|
|
693
|
+
'DIY DVD': this.createTV.bind(this),
|
|
694
|
+
'Speaker': this.createTV.bind(this),
|
|
695
|
+
'DIY Speaker': this.createTV.bind(this),
|
|
696
|
+
'Fan': this.createIRFan.bind(this),
|
|
697
|
+
'DIY Fan': this.createIRFan.bind(this),
|
|
698
|
+
'Air Conditioner': this.createAirConditioner.bind(this),
|
|
699
|
+
'DIY Air Conditioner': this.createAirConditioner.bind(this),
|
|
700
|
+
'Light': this.createLight.bind(this),
|
|
701
|
+
'DIY Light': this.createLight.bind(this),
|
|
702
|
+
'Air Purifier': this.createAirPurifier.bind(this),
|
|
703
|
+
'DIY Air Purifier': this.createAirPurifier.bind(this),
|
|
704
|
+
'Water Heater': this.createWaterHeater.bind(this),
|
|
705
|
+
'DIY Water Heater': this.createWaterHeater.bind(this),
|
|
706
|
+
'Vacuum Cleaner': this.createVacuumCleaner.bind(this),
|
|
707
|
+
'DIY Vacuum Cleaner': this.createVacuumCleaner.bind(this),
|
|
708
|
+
'Camera': this.createCamera.bind(this),
|
|
709
|
+
'DIY Camera': this.createCamera.bind(this),
|
|
710
|
+
'Others': this.createOthers.bind(this),
|
|
711
|
+
};
|
|
712
|
+
if (deviceTypeHandlers[device.remoteType]) {
|
|
713
|
+
await this.debugLog(`Discovered ${device.remoteType}: ${device.deviceId}`);
|
|
714
|
+
if (device.remoteType.startsWith('DIY') && device.external === undefined) {
|
|
715
|
+
device.external = true;
|
|
716
|
+
}
|
|
717
|
+
await deviceTypeHandlers[device.remoteType](device);
|
|
718
|
+
}
|
|
719
|
+
else {
|
|
720
|
+
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)}`);
|
|
822
721
|
}
|
|
823
722
|
}
|
|
824
723
|
async createHumidifier(device) {
|
|
825
724
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
826
725
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
827
726
|
// the cached devices we stored in the `configureAccessory` method above
|
|
828
|
-
const existingAccessory = this.accessories.find(
|
|
727
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
829
728
|
if (existingAccessory) {
|
|
830
729
|
// the accessory already exists
|
|
831
730
|
if (await this.registerDevice(device)) {
|
|
@@ -884,7 +783,7 @@ export class SwitchBotPlatform {
|
|
|
884
783
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
885
784
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
886
785
|
// the cached devices we stored in the `configureAccessory` method above
|
|
887
|
-
const existingAccessory = this.accessories.find(
|
|
786
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
888
787
|
if (existingAccessory) {
|
|
889
788
|
// the accessory already exists
|
|
890
789
|
if (await this.registerDevice(device)) {
|
|
@@ -945,7 +844,7 @@ export class SwitchBotPlatform {
|
|
|
945
844
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
946
845
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
947
846
|
// the cached devices we stored in the `configureAccessory` method above
|
|
948
|
-
const existingAccessory = this.accessories.find(
|
|
847
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
949
848
|
if (existingAccessory) {
|
|
950
849
|
// the accessory already exists
|
|
951
850
|
if (await this.registerDevice(device)) {
|
|
@@ -1005,7 +904,7 @@ export class SwitchBotPlatform {
|
|
|
1005
904
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1006
905
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1007
906
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1008
|
-
const existingAccessory = this.accessories.find(
|
|
907
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1009
908
|
if (existingAccessory) {
|
|
1010
909
|
// the accessory already exists
|
|
1011
910
|
if (await this.registerDevice(device)) {
|
|
@@ -1066,7 +965,7 @@ export class SwitchBotPlatform {
|
|
|
1066
965
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1067
966
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1068
967
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1069
|
-
const existingAccessory = this.accessories.find(
|
|
968
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1070
969
|
if (existingAccessory) {
|
|
1071
970
|
// the accessory already exists
|
|
1072
971
|
if (await this.registerDevice(device)) {
|
|
@@ -1127,7 +1026,7 @@ export class SwitchBotPlatform {
|
|
|
1127
1026
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1128
1027
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1129
1028
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1130
|
-
const existingAccessory = this.accessories.find(
|
|
1029
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1131
1030
|
if (existingAccessory) {
|
|
1132
1031
|
// the accessory already exists
|
|
1133
1032
|
if (await this.registerDevice(device)) {
|
|
@@ -1187,7 +1086,7 @@ export class SwitchBotPlatform {
|
|
|
1187
1086
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1188
1087
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1189
1088
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1190
|
-
const existingAccessory = this.accessories.find(
|
|
1089
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1191
1090
|
if (existingAccessory) {
|
|
1192
1091
|
// the accessory already exists
|
|
1193
1092
|
if (await this.registerDevice(device)) {
|
|
@@ -1247,7 +1146,7 @@ export class SwitchBotPlatform {
|
|
|
1247
1146
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1248
1147
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1249
1148
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1250
|
-
const existingAccessory = this.accessories.find(
|
|
1149
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1251
1150
|
if (existingAccessory) {
|
|
1252
1151
|
// the accessory already exists
|
|
1253
1152
|
if (await this.registerDevice(device)) {
|
|
@@ -1307,7 +1206,7 @@ export class SwitchBotPlatform {
|
|
|
1307
1206
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1308
1207
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1309
1208
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1310
|
-
const existingAccessory = this.accessories.find(
|
|
1209
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1311
1210
|
if (existingAccessory) {
|
|
1312
1211
|
// the accessory already exists
|
|
1313
1212
|
if (await this.registerDevice(device)) {
|
|
@@ -1367,7 +1266,7 @@ export class SwitchBotPlatform {
|
|
|
1367
1266
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1368
1267
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1369
1268
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1370
|
-
const existingAccessory = this.accessories.find(
|
|
1269
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1371
1270
|
if (existingAccessory) {
|
|
1372
1271
|
// the accessory already exists
|
|
1373
1272
|
if (await this.registerDevice(device)) {
|
|
@@ -1395,8 +1294,8 @@ export class SwitchBotPlatform {
|
|
|
1395
1294
|
else if (await this.registerDevice(device)) {
|
|
1396
1295
|
if (isBlindTiltDevice(device)) {
|
|
1397
1296
|
if (device.group && !device.curtain?.disable_group) {
|
|
1398
|
-
this.debugLog('Your Curtains are grouped, '
|
|
1399
|
-
`, Secondary curtain automatically hidden. Main Curtain: ${device.deviceName}, deviceId: ${device.deviceId}`);
|
|
1297
|
+
this.debugLog('Your Curtains are grouped, '
|
|
1298
|
+
+ `, Secondary curtain automatically hidden. Main Curtain: ${device.deviceName}, deviceId: ${device.deviceId}`);
|
|
1400
1299
|
}
|
|
1401
1300
|
else {
|
|
1402
1301
|
if (device.master) {
|
|
@@ -1414,7 +1313,6 @@ export class SwitchBotPlatform {
|
|
|
1414
1313
|
// store a copy of the device object in the `accessory.context`
|
|
1415
1314
|
// the `context` property can be used to store any data about the accessory you may need
|
|
1416
1315
|
accessory.context.device = device;
|
|
1417
|
-
;
|
|
1418
1316
|
accessory.context.deviceId = device.deviceId;
|
|
1419
1317
|
accessory.context.deviceType = device.deviceType;
|
|
1420
1318
|
accessory.context.model = SwitchBotModel.BlindTilt;
|
|
@@ -1442,7 +1340,7 @@ export class SwitchBotPlatform {
|
|
|
1442
1340
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1443
1341
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1444
1342
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1445
|
-
const existingAccessory = this.accessories.find(
|
|
1343
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1446
1344
|
if (existingAccessory) {
|
|
1447
1345
|
// the accessory already exists
|
|
1448
1346
|
if (await this.registerDevice(device)) {
|
|
@@ -1470,8 +1368,8 @@ export class SwitchBotPlatform {
|
|
|
1470
1368
|
else if (await this.registerDevice(device)) {
|
|
1471
1369
|
if (isCurtainDevice(device)) {
|
|
1472
1370
|
if (device.group && !device.curtain?.disable_group) {
|
|
1473
|
-
this.debugLog('Your Curtains are grouped, '
|
|
1474
|
-
`, Secondary curtain automatically hidden. Main Curtain: ${device.deviceName}, deviceId: ${device.deviceId}`);
|
|
1371
|
+
this.debugLog('Your Curtains are grouped, '
|
|
1372
|
+
+ `, Secondary curtain automatically hidden. Main Curtain: ${device.deviceName}, deviceId: ${device.deviceId}`);
|
|
1475
1373
|
}
|
|
1476
1374
|
else {
|
|
1477
1375
|
if (device.master) {
|
|
@@ -1516,7 +1414,7 @@ export class SwitchBotPlatform {
|
|
|
1516
1414
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1517
1415
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1518
1416
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1519
|
-
const existingAccessory = this.accessories.find(
|
|
1417
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1520
1418
|
if (existingAccessory) {
|
|
1521
1419
|
// the accessory already exists
|
|
1522
1420
|
if (await this.registerDevice(device)) {
|
|
@@ -1524,8 +1422,11 @@ export class SwitchBotPlatform {
|
|
|
1524
1422
|
existingAccessory.context.device = device;
|
|
1525
1423
|
existingAccessory.context.deviceId = device.deviceId;
|
|
1526
1424
|
existingAccessory.context.deviceType = device.deviceType;
|
|
1527
|
-
existingAccessory.context.model = device.deviceType === 'Plug Mini (US)'
|
|
1528
|
-
? SwitchBotModel.
|
|
1425
|
+
existingAccessory.context.model = device.deviceType === 'Plug Mini (US)'
|
|
1426
|
+
? SwitchBotModel.PlugMiniUS
|
|
1427
|
+
: device.deviceType === 'Plug Mini (JP)'
|
|
1428
|
+
? SwitchBotModel.PlugMiniJP
|
|
1429
|
+
: SwitchBotModel.Plug;
|
|
1529
1430
|
existingAccessory.displayName = device.configDeviceName
|
|
1530
1431
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
1531
1432
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
@@ -1552,8 +1453,11 @@ export class SwitchBotPlatform {
|
|
|
1552
1453
|
accessory.context.device = device;
|
|
1553
1454
|
accessory.context.deviceId = device.deviceId;
|
|
1554
1455
|
accessory.context.deviceType = device.deviceType;
|
|
1555
|
-
accessory.context.model = device.deviceType === 'Plug Mini (US)'
|
|
1556
|
-
? SwitchBotModel.
|
|
1456
|
+
accessory.context.model = device.deviceType === 'Plug Mini (US)'
|
|
1457
|
+
? SwitchBotModel.PlugMiniUS
|
|
1458
|
+
: device.deviceType === 'Plug Mini (JP)'
|
|
1459
|
+
? SwitchBotModel.PlugMiniJP
|
|
1460
|
+
: SwitchBotModel.Plug;
|
|
1557
1461
|
accessory.displayName = device.configDeviceName
|
|
1558
1462
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
1559
1463
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
@@ -1578,7 +1482,7 @@ export class SwitchBotPlatform {
|
|
|
1578
1482
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1579
1483
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1580
1484
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1581
|
-
const existingAccessory = this.accessories.find(
|
|
1485
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1582
1486
|
if (existingAccessory) {
|
|
1583
1487
|
// the accessory already exists
|
|
1584
1488
|
if (await this.registerDevice(device)) {
|
|
@@ -1638,7 +1542,7 @@ export class SwitchBotPlatform {
|
|
|
1638
1542
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1639
1543
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1640
1544
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1641
|
-
const existingAccessory = this.accessories.find(
|
|
1545
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1642
1546
|
if (existingAccessory) {
|
|
1643
1547
|
// the accessory already exists
|
|
1644
1548
|
if (await this.registerDevice(device)) {
|
|
@@ -1698,7 +1602,7 @@ export class SwitchBotPlatform {
|
|
|
1698
1602
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1699
1603
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1700
1604
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1701
|
-
const existingAccessory = this.accessories.find(
|
|
1605
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1702
1606
|
if (existingAccessory) {
|
|
1703
1607
|
// the accessory already exists
|
|
1704
1608
|
if (await this.registerDevice(device)) {
|
|
@@ -1758,7 +1662,7 @@ export class SwitchBotPlatform {
|
|
|
1758
1662
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1759
1663
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1760
1664
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1761
|
-
const existingAccessory = this.accessories.find(
|
|
1665
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1762
1666
|
if (existingAccessory) {
|
|
1763
1667
|
// the accessory already exists
|
|
1764
1668
|
if (await this.registerDevice(device)) {
|
|
@@ -1818,7 +1722,7 @@ export class SwitchBotPlatform {
|
|
|
1818
1722
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1819
1723
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1820
1724
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1821
|
-
const existingAccessory = this.accessories.find(
|
|
1725
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1822
1726
|
if (existingAccessory) {
|
|
1823
1727
|
// the accessory already exists
|
|
1824
1728
|
if (await this.registerDevice(device)) {
|
|
@@ -1878,7 +1782,7 @@ export class SwitchBotPlatform {
|
|
|
1878
1782
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1879
1783
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1880
1784
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1881
|
-
const existingAccessory = this.accessories.find(
|
|
1785
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1882
1786
|
if (existingAccessory) {
|
|
1883
1787
|
// the accessory already exists
|
|
1884
1788
|
if (await this.registerDevice(device)) {
|
|
@@ -1886,11 +1790,17 @@ export class SwitchBotPlatform {
|
|
|
1886
1790
|
existingAccessory.context.device = device;
|
|
1887
1791
|
existingAccessory.context.deviceId = device.deviceId;
|
|
1888
1792
|
existingAccessory.context.deviceType = device.deviceType;
|
|
1889
|
-
existingAccessory.context.model = device.deviceType === 'Robot Vacuum Cleaner S1'
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1793
|
+
existingAccessory.context.model = device.deviceType === 'Robot Vacuum Cleaner S1'
|
|
1794
|
+
? SwitchBotModel.RobotVacuumCleanerS1
|
|
1795
|
+
: device.deviceType === 'Robot Vacuum Cleaner S1 Plus'
|
|
1796
|
+
? SwitchBotModel.RobotVacuumCleanerS1Plus
|
|
1797
|
+
: device.deviceType === 'Robot Vacuum Cleaner S10'
|
|
1798
|
+
? SwitchBotModel.RobotVacuumCleanerS10
|
|
1799
|
+
: device.deviceType === 'WoSweeper'
|
|
1800
|
+
? SwitchBotModel.WoSweeper
|
|
1801
|
+
: device.deviceType === 'WoSweeperMini'
|
|
1802
|
+
? SwitchBotModel.WoSweeperMini
|
|
1803
|
+
: SwitchBotModel.Unknown;
|
|
1894
1804
|
existingAccessory.displayName = device.configDeviceName
|
|
1895
1805
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
1896
1806
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
@@ -1917,11 +1827,17 @@ export class SwitchBotPlatform {
|
|
|
1917
1827
|
accessory.context.device = device;
|
|
1918
1828
|
accessory.context.deviceId = device.deviceId;
|
|
1919
1829
|
accessory.context.deviceType = device.deviceType;
|
|
1920
|
-
accessory.context.model = device.deviceType === 'Robot Vacuum Cleaner S1'
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1830
|
+
accessory.context.model = device.deviceType === 'Robot Vacuum Cleaner S1'
|
|
1831
|
+
? SwitchBotModel.RobotVacuumCleanerS1
|
|
1832
|
+
: device.deviceType === 'Robot Vacuum Cleaner S1 Plus'
|
|
1833
|
+
? SwitchBotModel.RobotVacuumCleanerS1Plus
|
|
1834
|
+
: device.deviceType === 'Robot Vacuum Cleaner S10'
|
|
1835
|
+
? SwitchBotModel.RobotVacuumCleanerS10
|
|
1836
|
+
: device.deviceType === 'WoSweeper'
|
|
1837
|
+
? SwitchBotModel.WoSweeper
|
|
1838
|
+
: device.deviceType === 'WoSweeperMini'
|
|
1839
|
+
? SwitchBotModel.WoSweeperMini
|
|
1840
|
+
: SwitchBotModel.Unknown;
|
|
1925
1841
|
accessory.displayName = device.configDeviceName
|
|
1926
1842
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
1927
1843
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
@@ -1946,7 +1862,7 @@ export class SwitchBotPlatform {
|
|
|
1946
1862
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
1947
1863
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1948
1864
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1949
|
-
const existingAccessory = this.accessories.find(
|
|
1865
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1950
1866
|
if (!device.hide_device && existingAccessory) {
|
|
1951
1867
|
// if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
|
|
1952
1868
|
existingAccessory.context.device = device;
|
|
@@ -1979,7 +1895,6 @@ export class SwitchBotPlatform {
|
|
|
1979
1895
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
1980
1896
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
1981
1897
|
accessory.context.connectionType = await this.connectionType(device);
|
|
1982
|
-
accessory.context.connectionType = device.connectionType;
|
|
1983
1898
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
1984
1899
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
1985
1900
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -1987,7 +1902,7 @@ export class SwitchBotPlatform {
|
|
|
1987
1902
|
// this is imported from `platformAccessory.ts`
|
|
1988
1903
|
new TV(this, accessory, device);
|
|
1989
1904
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
1990
|
-
this.
|
|
1905
|
+
this.externalOrPlatform(device, accessory);
|
|
1991
1906
|
this.accessories.push(accessory);
|
|
1992
1907
|
}
|
|
1993
1908
|
else {
|
|
@@ -1998,7 +1913,7 @@ export class SwitchBotPlatform {
|
|
|
1998
1913
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
1999
1914
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2000
1915
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2001
|
-
const existingAccessory = this.accessories.find(
|
|
1916
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2002
1917
|
if (existingAccessory) {
|
|
2003
1918
|
// the accessory already exists
|
|
2004
1919
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2037,7 +1952,6 @@ export class SwitchBotPlatform {
|
|
|
2037
1952
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2038
1953
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2039
1954
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2040
|
-
accessory.context.connectionType = device.connectionType;
|
|
2041
1955
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2042
1956
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2043
1957
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2046,7 +1960,7 @@ export class SwitchBotPlatform {
|
|
|
2046
1960
|
new IRFan(this, accessory, device);
|
|
2047
1961
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2048
1962
|
// publish device externally or link the accessory to your platform
|
|
2049
|
-
this.
|
|
1963
|
+
this.externalOrPlatform(device, accessory);
|
|
2050
1964
|
this.accessories.push(accessory);
|
|
2051
1965
|
}
|
|
2052
1966
|
else {
|
|
@@ -2057,7 +1971,7 @@ export class SwitchBotPlatform {
|
|
|
2057
1971
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2058
1972
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2059
1973
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2060
|
-
const existingAccessory = this.accessories.find(
|
|
1974
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2061
1975
|
if (existingAccessory) {
|
|
2062
1976
|
// the accessory already exists
|
|
2063
1977
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2096,7 +2010,6 @@ export class SwitchBotPlatform {
|
|
|
2096
2010
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2097
2011
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2098
2012
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2099
|
-
accessory.context.connectionType = device.connectionType;
|
|
2100
2013
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2101
2014
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2102
2015
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2105,7 +2018,7 @@ export class SwitchBotPlatform {
|
|
|
2105
2018
|
new Light(this, accessory, device);
|
|
2106
2019
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2107
2020
|
// publish device externally or link the accessory to your platform
|
|
2108
|
-
this.
|
|
2021
|
+
this.externalOrPlatform(device, accessory);
|
|
2109
2022
|
this.accessories.push(accessory);
|
|
2110
2023
|
}
|
|
2111
2024
|
else {
|
|
@@ -2116,7 +2029,7 @@ export class SwitchBotPlatform {
|
|
|
2116
2029
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2117
2030
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2118
2031
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2119
|
-
const existingAccessory = this.accessories.find(
|
|
2032
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2120
2033
|
if (existingAccessory) {
|
|
2121
2034
|
// the accessory already exists
|
|
2122
2035
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2155,7 +2068,6 @@ export class SwitchBotPlatform {
|
|
|
2155
2068
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2156
2069
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2157
2070
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2158
|
-
accessory.context.connectionType = device.connectionType;
|
|
2159
2071
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2160
2072
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2161
2073
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2164,7 +2076,7 @@ export class SwitchBotPlatform {
|
|
|
2164
2076
|
new AirConditioner(this, accessory, device);
|
|
2165
2077
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2166
2078
|
// publish device externally or link the accessory to your platform
|
|
2167
|
-
this.
|
|
2079
|
+
this.externalOrPlatform(device, accessory);
|
|
2168
2080
|
this.accessories.push(accessory);
|
|
2169
2081
|
}
|
|
2170
2082
|
else {
|
|
@@ -2175,7 +2087,7 @@ export class SwitchBotPlatform {
|
|
|
2175
2087
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2176
2088
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2177
2089
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2178
|
-
const existingAccessory = this.accessories.find(
|
|
2090
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2179
2091
|
if (existingAccessory) {
|
|
2180
2092
|
// the accessory already exists
|
|
2181
2093
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2214,7 +2126,6 @@ export class SwitchBotPlatform {
|
|
|
2214
2126
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2215
2127
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2216
2128
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2217
|
-
accessory.context.connectionType = device.connectionType;
|
|
2218
2129
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2219
2130
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2220
2131
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2223,7 +2134,7 @@ export class SwitchBotPlatform {
|
|
|
2223
2134
|
new AirPurifier(this, accessory, device);
|
|
2224
2135
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2225
2136
|
// publish device externally or link the accessory to your platform
|
|
2226
|
-
this.
|
|
2137
|
+
this.externalOrPlatform(device, accessory);
|
|
2227
2138
|
this.accessories.push(accessory);
|
|
2228
2139
|
}
|
|
2229
2140
|
else {
|
|
@@ -2234,7 +2145,7 @@ export class SwitchBotPlatform {
|
|
|
2234
2145
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2235
2146
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2236
2147
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2237
|
-
const existingAccessory = this.accessories.find(
|
|
2148
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2238
2149
|
if (existingAccessory) {
|
|
2239
2150
|
// the accessory already exists
|
|
2240
2151
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2273,7 +2184,6 @@ export class SwitchBotPlatform {
|
|
|
2273
2184
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2274
2185
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2275
2186
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2276
|
-
accessory.context.connectionType = device.connectionType;
|
|
2277
2187
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2278
2188
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2279
2189
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2282,7 +2192,7 @@ export class SwitchBotPlatform {
|
|
|
2282
2192
|
new WaterHeater(this, accessory, device);
|
|
2283
2193
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2284
2194
|
// publish device externally or link the accessory to your platform
|
|
2285
|
-
this.
|
|
2195
|
+
this.externalOrPlatform(device, accessory);
|
|
2286
2196
|
this.accessories.push(accessory);
|
|
2287
2197
|
}
|
|
2288
2198
|
else {
|
|
@@ -2293,7 +2203,7 @@ export class SwitchBotPlatform {
|
|
|
2293
2203
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2294
2204
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2295
2205
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2296
|
-
const existingAccessory = this.accessories.find(
|
|
2206
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2297
2207
|
if (existingAccessory) {
|
|
2298
2208
|
// the accessory already exists
|
|
2299
2209
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2332,7 +2242,6 @@ export class SwitchBotPlatform {
|
|
|
2332
2242
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2333
2243
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2334
2244
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2335
|
-
accessory.context.connectionType = device.connectionType;
|
|
2336
2245
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2337
2246
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2338
2247
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2341,7 +2250,7 @@ export class SwitchBotPlatform {
|
|
|
2341
2250
|
new VacuumCleaner(this, accessory, device);
|
|
2342
2251
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2343
2252
|
// publish device externally or link the accessory to your platform
|
|
2344
|
-
this.
|
|
2253
|
+
this.externalOrPlatform(device, accessory);
|
|
2345
2254
|
this.accessories.push(accessory);
|
|
2346
2255
|
}
|
|
2347
2256
|
else {
|
|
@@ -2352,7 +2261,7 @@ export class SwitchBotPlatform {
|
|
|
2352
2261
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2353
2262
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2354
2263
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2355
|
-
const existingAccessory = this.accessories.find(
|
|
2264
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2356
2265
|
if (existingAccessory) {
|
|
2357
2266
|
// the accessory already exists
|
|
2358
2267
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2391,7 +2300,6 @@ export class SwitchBotPlatform {
|
|
|
2391
2300
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2392
2301
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2393
2302
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2394
|
-
accessory.context.connectionType = device.connectionType;
|
|
2395
2303
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2396
2304
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2397
2305
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2400,7 +2308,7 @@ export class SwitchBotPlatform {
|
|
|
2400
2308
|
new Camera(this, accessory, device);
|
|
2401
2309
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2402
2310
|
// publish device externally or link the accessory to your platform
|
|
2403
|
-
this.
|
|
2311
|
+
this.externalOrPlatform(device, accessory);
|
|
2404
2312
|
this.accessories.push(accessory);
|
|
2405
2313
|
}
|
|
2406
2314
|
else {
|
|
@@ -2411,7 +2319,7 @@ export class SwitchBotPlatform {
|
|
|
2411
2319
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2412
2320
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2413
2321
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2414
|
-
const existingAccessory = this.accessories.find(
|
|
2322
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2415
2323
|
if (existingAccessory) {
|
|
2416
2324
|
// the accessory already exists
|
|
2417
2325
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2450,7 +2358,6 @@ export class SwitchBotPlatform {
|
|
|
2450
2358
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2451
2359
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2452
2360
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2453
|
-
accessory.context.connectionType = device.connectionType;
|
|
2454
2361
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2455
2362
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2456
2363
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2459,7 +2366,7 @@ export class SwitchBotPlatform {
|
|
|
2459
2366
|
new Others(this, accessory, device);
|
|
2460
2367
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2461
2368
|
// publish device externally or link the accessory to your platform
|
|
2462
|
-
this.
|
|
2369
|
+
this.externalOrPlatform(device, accessory);
|
|
2463
2370
|
this.accessories.push(accessory);
|
|
2464
2371
|
}
|
|
2465
2372
|
else {
|
|
@@ -2467,24 +2374,13 @@ export class SwitchBotPlatform {
|
|
|
2467
2374
|
}
|
|
2468
2375
|
}
|
|
2469
2376
|
async registerCurtains(device) {
|
|
2470
|
-
/*function isCurtainDevice(device: device & devicesConfig): device is (curtain | curtain3) & devicesConfig {
|
|
2471
|
-
return device.deviceType === 'Curtain' || device.deviceType === 'Curtain3';
|
|
2472
|
-
}
|
|
2473
|
-
|
|
2474
|
-
function isBlindTiltDevice(device: device & devicesConfig): device is blindTilt & devicesConfig {
|
|
2475
|
-
return device.deviceType === 'Blind Tilt';
|
|
2476
|
-
}*/
|
|
2477
2377
|
let registerWindowCovering;
|
|
2478
2378
|
if (isCurtainDevice(device)) {
|
|
2479
|
-
await this.debugWarnLog(`deviceName: ${device.deviceName} deviceId: ${device.deviceId}, curtainDevicesIds: ${device.curtainDevicesIds}
|
|
2480
|
-
+ ` master: ${device.master}, group: ${device.group}, disable_group: ${device.curtain?.disable_group},`
|
|
2481
|
-
+ ` connectionType: ${device.connectionType}`);
|
|
2379
|
+
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}`);
|
|
2482
2380
|
registerWindowCovering = await this.registerWindowCovering(device);
|
|
2483
2381
|
}
|
|
2484
2382
|
else if (isBlindTiltDevice(device)) {
|
|
2485
|
-
await this.debugWarnLog(`deviceName: ${device.deviceName} deviceId: ${device.deviceId}, blindTiltDevicesIds: ${device.blindTiltDevicesIds}
|
|
2486
|
-
+ ` master: ${device.master}, group: ${device.group}, disable_group: ${device.curtain?.disable_group},`
|
|
2487
|
-
+ ` connectionType: ${device.connectionType}`);
|
|
2383
|
+
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}`);
|
|
2488
2384
|
registerWindowCovering = await this.registerWindowCovering(device);
|
|
2489
2385
|
}
|
|
2490
2386
|
else {
|
|
@@ -2498,36 +2394,31 @@ export class SwitchBotPlatform {
|
|
|
2498
2394
|
if (device.master && device.group) {
|
|
2499
2395
|
// OpenAPI: Master Curtains/Blind Tilt in Group
|
|
2500
2396
|
registerCurtain = true;
|
|
2501
|
-
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}
|
|
2502
|
-
+ ` device.group: ${device.group} connectionType; ${device.connectionType}`);
|
|
2397
|
+
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}, device.group: ${device.group} connectionType; ${device.connectionType}`);
|
|
2503
2398
|
await this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}`);
|
|
2504
2399
|
}
|
|
2505
2400
|
else if (!device.master && device.curtain?.disable_group) {
|
|
2506
|
-
|
|
2401
|
+
// !device.group && device.connectionType === 'BLE'
|
|
2507
2402
|
// OpenAPI: Non-Master Curtains/Blind Tilts that has Disable Grouping Checked
|
|
2508
2403
|
registerCurtain = true;
|
|
2509
|
-
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}, disable_group: `
|
|
2510
|
-
+ `${device.curtain?.disable_group}, connectionType; ${device.connectionType}`);
|
|
2404
|
+
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}, disable_group: ${device.curtain?.disable_group}, connectionType; ${device.connectionType}`);
|
|
2511
2405
|
await this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}`);
|
|
2512
2406
|
}
|
|
2513
2407
|
else if (device.master && !device.group) {
|
|
2514
2408
|
// OpenAPI: Master Curtains/Blind Tilts not in Group
|
|
2515
2409
|
registerCurtain = true;
|
|
2516
|
-
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}
|
|
2517
|
-
+ ` device.group: ${device.group} connectionType; ${device.connectionType}`);
|
|
2410
|
+
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}, device.group: ${device.group} connectionType; ${device.connectionType}`);
|
|
2518
2411
|
await this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}`);
|
|
2519
2412
|
}
|
|
2520
2413
|
else if (device.connectionType === 'BLE') {
|
|
2521
2414
|
// BLE: Curtains/Blind Tilt
|
|
2522
2415
|
registerCurtain = true;
|
|
2523
|
-
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] connectionType: ${device.connectionType}, `
|
|
2524
|
-
+ ` group: ${device.group}`);
|
|
2416
|
+
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] connectionType: ${device.connectionType}, group: ${device.group}`);
|
|
2525
2417
|
await this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}`);
|
|
2526
2418
|
}
|
|
2527
2419
|
else {
|
|
2528
2420
|
registerCurtain = false;
|
|
2529
|
-
await this.debugErrorLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] disable_group: ${device.curtain?.disable_group}
|
|
2530
|
-
+ ` device.master: ${device.master}, device.group: ${device.group}`);
|
|
2421
|
+
await this.debugErrorLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] disable_group: ${device.curtain?.disable_group}, device.master: ${device.master}, device.group: ${device.group}`);
|
|
2531
2422
|
await this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}, device.connectionType: ${device.connectionType}`);
|
|
2532
2423
|
}
|
|
2533
2424
|
return registerCurtain;
|
|
@@ -2545,189 +2436,93 @@ export class SwitchBotPlatform {
|
|
|
2545
2436
|
async registerDevice(device) {
|
|
2546
2437
|
device.connectionType = await this.connectionType(device);
|
|
2547
2438
|
let registerDevice;
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
case 'Curtain3':
|
|
2552
|
-
case 'Blind Tilt':
|
|
2553
|
-
registerDevice = await this.registerCurtains(device);
|
|
2554
|
-
await this.debugWarnLog(`Device: ${device.deviceName} ${device.deviceType} registerDevice: ${registerDevice}`);
|
|
2555
|
-
break;
|
|
2556
|
-
default:
|
|
2557
|
-
registerDevice = true;
|
|
2558
|
-
await this.debugWarnLog(`Device: ${device.deviceName} registerDevice: ${registerDevice}`);
|
|
2559
|
-
}
|
|
2560
|
-
if (registerDevice === true) {
|
|
2561
|
-
await this.debugWarnLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, will display in HomeKit`);
|
|
2562
|
-
}
|
|
2563
|
-
else {
|
|
2564
|
-
await this.debugErrorLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, will not display in HomeKit`);
|
|
2565
|
-
}
|
|
2566
|
-
}
|
|
2567
|
-
else if (!device.hide_device && device.deviceId && device.configDeviceType && device.configDeviceName && device.connectionType === 'BLE') {
|
|
2568
|
-
switch (device.deviceType) {
|
|
2569
|
-
case 'Curtain':
|
|
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.connectionType === 'OpenAPI') {
|
|
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 === 'Disabled') {
|
|
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
|
-
await this.debugWarnLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, will continue to display in HomeKit`);
|
|
2618
|
-
}
|
|
2619
|
-
else if (!device.connectionType && !device.hide_device) {
|
|
2620
|
-
registerDevice = false;
|
|
2621
|
-
await this.debugErrorLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, will not display in HomeKit`);
|
|
2622
|
-
}
|
|
2623
|
-
else if (device.hide_device) {
|
|
2624
|
-
registerDevice = false;
|
|
2625
|
-
await this.debugErrorLog(`Device: ${device.deviceName} hide_device: ${device.hide_device}, will not display in HomeKit`);
|
|
2439
|
+
const shouldRegister = !device.hide_device && (device.connectionType === 'BLE/OpenAPI' || (device.deviceId && device.configDeviceType && device.configDeviceName && device.connectionType === 'BLE') || device.connectionType === 'OpenAPI' || device.connectionType === 'Disabled');
|
|
2440
|
+
if (shouldRegister) {
|
|
2441
|
+
registerDevice = await this.handleDeviceRegistration(device);
|
|
2626
2442
|
}
|
|
2627
2443
|
else {
|
|
2628
2444
|
registerDevice = false;
|
|
2629
|
-
await this.debugErrorLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, hide_device: `
|
|
2630
|
-
+ `${device.hide_device}, will not display in HomeKit`);
|
|
2445
|
+
await this.debugErrorLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, hide_device: ${device.hide_device}, will not display in HomeKit`);
|
|
2631
2446
|
}
|
|
2632
2447
|
return registerDevice;
|
|
2633
2448
|
}
|
|
2634
|
-
async
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2449
|
+
async handleDeviceRegistration(device) {
|
|
2450
|
+
let registerDevice;
|
|
2451
|
+
switch (device.deviceType) {
|
|
2452
|
+
case 'Curtain':
|
|
2453
|
+
case 'Curtain3':
|
|
2454
|
+
case 'Blind Tilt':
|
|
2455
|
+
registerDevice = await this.registerCurtains(device);
|
|
2456
|
+
await this.debugWarnLog(`Device: ${device.deviceName} ${device.deviceType} registerDevice: ${registerDevice}`);
|
|
2457
|
+
break;
|
|
2458
|
+
default:
|
|
2459
|
+
registerDevice = true;
|
|
2460
|
+
await this.debugWarnLog(`Device: ${device.deviceName} registerDevice: ${registerDevice}`);
|
|
2461
|
+
}
|
|
2462
|
+
if (registerDevice) {
|
|
2463
|
+
await this.debugWarnLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, will display in HomeKit`);
|
|
2643
2464
|
}
|
|
2644
2465
|
else {
|
|
2645
|
-
await this.
|
|
2646
|
-
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
|
|
2466
|
+
await this.debugErrorLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, will not display in HomeKit`);
|
|
2647
2467
|
}
|
|
2468
|
+
return registerDevice;
|
|
2648
2469
|
}
|
|
2649
2470
|
async externalOrPlatform(device, accessory) {
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2471
|
+
const { displayName } = accessory;
|
|
2472
|
+
const isExternal = device.external ?? false;
|
|
2473
|
+
if (isExternal) {
|
|
2474
|
+
await this.debugWarnLog(`${displayName} External Accessory Mode`);
|
|
2475
|
+
this.api.publishExternalAccessories(PLUGIN_NAME, [accessory]);
|
|
2653
2476
|
}
|
|
2654
2477
|
else {
|
|
2655
|
-
await this.debugLog(`${
|
|
2478
|
+
await this.debugLog(`${displayName} External Accessory Mode: ${isExternal}`);
|
|
2656
2479
|
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
|
|
2657
2480
|
}
|
|
2658
2481
|
}
|
|
2659
|
-
async externalAccessory(accessory) {
|
|
2660
|
-
this.api.publishExternalAccessories(PLUGIN_NAME, [accessory]);
|
|
2661
|
-
}
|
|
2662
2482
|
unregisterPlatformAccessories(existingAccessory) {
|
|
2483
|
+
const { displayName } = existingAccessory;
|
|
2663
2484
|
// remove platform accessories when no longer present
|
|
2664
2485
|
this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [existingAccessory]);
|
|
2665
|
-
this.warnLog(`Removing existing accessory from cache: ${
|
|
2486
|
+
this.warnLog(`Removing existing accessory from cache: ${displayName}`);
|
|
2666
2487
|
}
|
|
2488
|
+
/**
|
|
2489
|
+
* Handles the status codes returned by the device and logs appropriate messages.
|
|
2490
|
+
*
|
|
2491
|
+
* @param statusCode - The status code returned by the device.
|
|
2492
|
+
* @returns A promise that resolves when the logging is complete.
|
|
2493
|
+
*/
|
|
2667
2494
|
async statusCode(statusCode) {
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
await this.errorLog('Unauthorized, Authorization for the API is required, but the request has not been authenticated, '
|
|
2700
|
-
+ `statusCode: ${statusCode}`);
|
|
2701
|
-
break;
|
|
2702
|
-
case 403:
|
|
2703
|
-
await this.errorLog('Forbidden, The request has been authenticated but does not have appropriate permissions, or a requested resource is not '
|
|
2704
|
-
+ `found, statusCode: ${statusCode}`);
|
|
2705
|
-
break;
|
|
2706
|
-
case 404:
|
|
2707
|
-
await this.errorLog(`Not Found, Specifies the requested path does not exist, statusCode: ${statusCode}`);
|
|
2708
|
-
break;
|
|
2709
|
-
case 406:
|
|
2710
|
-
await this.errorLog('Not Acceptable, The client has requested a MIME type via the Accept header for a value not supported by the server, '
|
|
2711
|
-
+ `statusCode: ${statusCode}`);
|
|
2712
|
-
break;
|
|
2713
|
-
case 415:
|
|
2714
|
-
await this.errorLog('Unsupported Media Type, The client has defined a contentType header that is not supported by the server, '
|
|
2715
|
-
+ `statusCode: ${statusCode}`);
|
|
2716
|
-
break;
|
|
2717
|
-
case 422:
|
|
2718
|
-
await this.errorLog('Unprocessable Entity, The client has made a valid request, but the server cannot process it. This is often used for '
|
|
2719
|
-
+ `APIs for which certain limits have been exceeded, statusCode: ${statusCode}`);
|
|
2720
|
-
break;
|
|
2721
|
-
case 429:
|
|
2722
|
-
await this.errorLog('Too Many Requests, The client has exceeded the number of requests allowed for a given time window, '
|
|
2723
|
-
+ `statusCode: ${statusCode}`);
|
|
2724
|
-
break;
|
|
2725
|
-
case 500:
|
|
2726
|
-
await this.errorLog('Internal Server Error, An unexpected error on the SmartThings servers has occurred. These errors should be rare, '
|
|
2727
|
-
+ `statusCode: ${statusCode}`);
|
|
2728
|
-
break;
|
|
2729
|
-
default:
|
|
2730
|
-
await this.errorLog(`Unknown statusCode, statusCode: ${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`);
|
|
2495
|
+
const messages = {
|
|
2496
|
+
151: `Command not supported by this device type, statusCode: ${statusCode}, Submit Feature Request Here:
|
|
2497
|
+
https://tinyurl.com/SwitchBotFeatureRequest`,
|
|
2498
|
+
152: `Device not found, statusCode: ${statusCode}`,
|
|
2499
|
+
160: `Command is not supported, statusCode: ${statusCode}, Submit Bugs Here: https://tinyurl.com/SwitchBotBug`,
|
|
2500
|
+
161: `Device is offline, statusCode: ${statusCode}`,
|
|
2501
|
+
171: `is offline, statusCode: ${statusCode}`,
|
|
2502
|
+
190: `Requests reached the daily limit, statusCode: ${statusCode}`,
|
|
2503
|
+
100: `Command successfully sent, statusCode: ${statusCode}`,
|
|
2504
|
+
200: `Request successful, statusCode: ${statusCode}`,
|
|
2505
|
+
400: `Bad Request, The client has issued an invalid request. This is commonly used to specify validation errors in a request payload,
|
|
2506
|
+
statusCode: ${statusCode}`,
|
|
2507
|
+
401: `Unauthorized, Authorization for the API is required, but the request has not been authenticated, statusCode: ${statusCode}`,
|
|
2508
|
+
403: `Forbidden, The request has been authenticated but does not have appropriate permissions, or a requested resource is not found,
|
|
2509
|
+
statusCode: ${statusCode}`,
|
|
2510
|
+
404: `Not Found, Specifies the requested path does not exist, statusCode: ${statusCode}`,
|
|
2511
|
+
406: `Not Acceptable, The client has requested a MIME type via the Accept header for a value not supported by the server,
|
|
2512
|
+
statusCode: ${statusCode}`,
|
|
2513
|
+
415: `Unsupported Media Type, The client has defined a contentType header that is not supported by the server, statusCode: ${statusCode}`,
|
|
2514
|
+
422: `Unprocessable Entity, The client has made a valid request, but the server cannot process it. This is often used for APIs for which
|
|
2515
|
+
certain limits have been exceeded, statusCode: ${statusCode}`,
|
|
2516
|
+
429: `Too Many Requests, The client has exceeded the number of requests allowed for a given time window, statusCode: ${statusCode}`,
|
|
2517
|
+
500: `Internal Server Error, An unexpected error on the SmartThings servers has occurred. These errors should be rare,
|
|
2518
|
+
statusCode: ${statusCode}`,
|
|
2519
|
+
};
|
|
2520
|
+
const message = messages[statusCode] ?? `Unknown statusCode, statusCode: ${statusCode}, Submit Bugs Here: https://tinyurl.com/SwitchBotBug`;
|
|
2521
|
+
if ([100, 200].includes(statusCode)) {
|
|
2522
|
+
await this.debugLog(message);
|
|
2523
|
+
}
|
|
2524
|
+
else {
|
|
2525
|
+
await this.errorLog(message);
|
|
2731
2526
|
}
|
|
2732
2527
|
}
|
|
2733
2528
|
async retryRequest(deviceMaxRetries, deviceDelayBetweenRetries, url, options) {
|
|
@@ -2755,57 +2550,43 @@ export class SwitchBotPlatform {
|
|
|
2755
2550
|
}
|
|
2756
2551
|
// BLE Connection
|
|
2757
2552
|
async connectBLE(accessory, device) {
|
|
2758
|
-
let switchbot;
|
|
2759
2553
|
try {
|
|
2760
|
-
const SwitchBot =
|
|
2761
|
-
|
|
2554
|
+
const { SwitchBot } = await import('node-switchbot');
|
|
2555
|
+
const switchbot = new SwitchBot();
|
|
2556
|
+
queueScheduler.schedule(async () => switchbot);
|
|
2762
2557
|
await this.debugLog(`${device.deviceType}: ${accessory.displayName} 'node-switchbot' found: ${switchbot}`);
|
|
2558
|
+
return switchbot;
|
|
2763
2559
|
}
|
|
2764
2560
|
catch (e) {
|
|
2765
|
-
switchbot
|
|
2766
|
-
|
|
2561
|
+
await this.errorLog(`${device.deviceType}: ${accessory.displayName} 'node-switchbot' not found, Error: ${e}`);
|
|
2562
|
+
return false;
|
|
2767
2563
|
}
|
|
2768
|
-
return switchbot;
|
|
2769
2564
|
}
|
|
2770
2565
|
async getVersion() {
|
|
2771
2566
|
const json = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf-8'));
|
|
2772
2567
|
await this.debugLog(`Plugin Version: ${json.version}`);
|
|
2773
2568
|
this.version = json.version;
|
|
2569
|
+
return json.version;
|
|
2774
2570
|
}
|
|
2775
2571
|
async getPlatformConfigSettings() {
|
|
2572
|
+
const { options } = this.config;
|
|
2776
2573
|
const platformConfig = {};
|
|
2777
|
-
if (
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
if (
|
|
2785
|
-
|
|
2786
|
-
}
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
}
|
|
2794
|
-
else {
|
|
2795
|
-
this.maxRetries = 3;
|
|
2796
|
-
this.debugWarnLog('Using Default Max Retries');
|
|
2797
|
-
platformConfig.maxRetries = this.maxRetries;
|
|
2798
|
-
}
|
|
2799
|
-
if (this.config.options.delayBetweenRetries) {
|
|
2800
|
-
this.delayBetweenRetries = this.config.options.delayBetweenRetries * 1000;
|
|
2801
|
-
platformConfig.delayBetweenRetries = this.config.options.delayBetweenRetries;
|
|
2802
|
-
}
|
|
2803
|
-
else {
|
|
2804
|
-
this.delayBetweenRetries = 3000;
|
|
2805
|
-
this.debugWarnLog('Using Default Delay Between Retries');
|
|
2806
|
-
platformConfig.delayBetweenRetries = this.delayBetweenRetries / 1000;
|
|
2807
|
-
}
|
|
2808
|
-
if (Object.entries(platformConfig).length !== 0) {
|
|
2574
|
+
if (options) {
|
|
2575
|
+
platformConfig.logging = options.logging;
|
|
2576
|
+
platformConfig.refreshRate = options.refreshRate;
|
|
2577
|
+
platformConfig.updateRate = options.updateRate;
|
|
2578
|
+
platformConfig.pushRate = options.pushRate;
|
|
2579
|
+
this.maxRetries = options.maxRetries || 3;
|
|
2580
|
+
platformConfig.maxRetries = this.maxRetries;
|
|
2581
|
+
if (!options.maxRetries) {
|
|
2582
|
+
await this.debugWarnLog('Using Default Max Retries');
|
|
2583
|
+
}
|
|
2584
|
+
this.delayBetweenRetries = (options.delayBetweenRetries || 3) * 1000;
|
|
2585
|
+
platformConfig.delayBetweenRetries = this.delayBetweenRetries / 1000;
|
|
2586
|
+
if (!options.delayBetweenRetries) {
|
|
2587
|
+
await this.debugWarnLog('Using Default Delay Between Retries');
|
|
2588
|
+
}
|
|
2589
|
+
if (Object.keys(platformConfig).length) {
|
|
2809
2590
|
await this.debugLog(`Platform Config: ${JSON.stringify(platformConfig)}`);
|
|
2810
2591
|
}
|
|
2811
2592
|
this.platformConfig = platformConfig;
|
|
@@ -2828,31 +2609,38 @@ export class SwitchBotPlatform {
|
|
|
2828
2609
|
}
|
|
2829
2610
|
/**
|
|
2830
2611
|
* Validate and clean a string value for a Name Characteristic.
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2612
|
+
* @param displayName - The display name of the accessory.
|
|
2613
|
+
* @param name - The name of the characteristic.
|
|
2614
|
+
* @param value - The value to be validated and cleaned.
|
|
2615
|
+
* @returns The cleaned string value.
|
|
2616
|
+
*/
|
|
2836
2617
|
async validateAndCleanDisplayName(displayName, name, value) {
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2618
|
+
if (this.config.options?.allowInvalidCharacters) {
|
|
2619
|
+
return value;
|
|
2620
|
+
}
|
|
2621
|
+
else {
|
|
2622
|
+
const validPattern = /^[\p{L}\p{N}][\p{L}\p{N} ']*[\p{L}\p{N}]$/u;
|
|
2623
|
+
const invalidCharsPattern = /[^\p{L}\p{N} ']/gu;
|
|
2624
|
+
const invalidStartEndPattern = /^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/gu;
|
|
2625
|
+
if (typeof value === 'string' && !validPattern.test(value)) {
|
|
2626
|
+
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.`);
|
|
2627
|
+
// Remove invalid characters
|
|
2628
|
+
if (invalidCharsPattern.test(value)) {
|
|
2629
|
+
const before = value;
|
|
2630
|
+
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`);
|
|
2631
|
+
value = value.replace(invalidCharsPattern, '');
|
|
2632
|
+
await this.warnLog(`${name} Before: '${before}' After: '${value}'`);
|
|
2633
|
+
}
|
|
2634
|
+
// Ensure it starts and ends with an alphanumeric character
|
|
2635
|
+
if (invalidStartEndPattern.test(value)) {
|
|
2636
|
+
const before = value;
|
|
2637
|
+
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`);
|
|
2638
|
+
value = value.replace(invalidStartEndPattern, '');
|
|
2639
|
+
await this.warnLog(`${name} Before: '${before}' After: '${value}'`);
|
|
2640
|
+
}
|
|
2641
|
+
}
|
|
2642
|
+
return value;
|
|
2643
|
+
}
|
|
2856
2644
|
}
|
|
2857
2645
|
/**
|
|
2858
2646
|
* If device level logging is turned on, log to log.warn
|