@switchbot/homebridge-switchbot 3.7.1-beta.2 → 3.7.1-beta.21
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 +1482 -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 +61 -105
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts +10 -10
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +22 -42
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts +9 -9
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +15 -25
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts +8 -8
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +21 -40
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/irdevice.d.ts +11 -11
- package/dist/irdevice/irdevice.d.ts.map +1 -1
- package/dist/irdevice/irdevice.js +14 -22
- package/dist/irdevice/irdevice.js.map +1 -1
- package/dist/irdevice/light.d.ts +9 -9
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +24 -47
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts +9 -9
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +40 -83
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts +9 -9
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +29 -54
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts +5 -5
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +11 -21
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts +5 -5
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +11 -22
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +24 -23
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +509 -723
- 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 +64 -57
- package/src/device/blindtilt.ts +537 -456
- package/src/device/bot-old.ts +1540 -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 +277 -326
- package/src/irdevice/airpurifier.ts +124 -143
- package/src/irdevice/camera.ts +58 -64
- package/src/irdevice/fan.ts +106 -123
- package/src/irdevice/irdevice.ts +116 -119
- package/src/irdevice/light.ts +119 -143
- package/src/irdevice/other.ts +417 -461
- package/src/irdevice/tv.ts +155 -177
- package/src/irdevice/vacuumcleaner.ts +54 -60
- package/src/irdevice/waterheater.ts +56 -63
- package/src/platform.ts +1491 -1681
- package/src/settings.ts +172 -169
- package/src/types/bledevicestatus.ts +252 -256
- package/src/types/devicelist.ts +79 -79
- package/src/types/deviceresponse.ts +12 -13
- package/src/types/devicestatus.ts +124 -124
- package/src/types/devicewebhookstatus.ts +126 -131
- package/src/types/irdevicelist.ts +10 -10
- package/src/types/pushbody.ts +5 -5
- package/src/utils.ts +64 -65
- package/tsconfig.json +10 -9
package/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 { SwitchBot, 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
|
}
|
|
@@ -295,7 +308,6 @@ export class SwitchBotPlatform {
|
|
|
295
308
|
async setupBlE() {
|
|
296
309
|
if (this.config.options?.BLE) {
|
|
297
310
|
await this.debugLog('setupBLE');
|
|
298
|
-
const SwitchBot = (await import('node-switchbot')).SwitchBot;
|
|
299
311
|
const switchbot = new SwitchBot();
|
|
300
312
|
if (switchbot === undefined) {
|
|
301
313
|
await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
|
|
@@ -319,10 +331,10 @@ export class SwitchBotPlatform {
|
|
|
319
331
|
this.api.on('shutdown', async () => {
|
|
320
332
|
try {
|
|
321
333
|
switchbot.stopScan();
|
|
322
|
-
this.infoLog('Stopped BLE scanning to close listening.');
|
|
334
|
+
await this.infoLog('Stopped BLE scanning to close listening.');
|
|
323
335
|
}
|
|
324
336
|
catch (e) {
|
|
325
|
-
this.errorLog(`Failed to stop Platform BLE scanning. Error:${e.message}`);
|
|
337
|
+
await this.errorLog(`Failed to stop Platform BLE scanning. Error:${e.message}`);
|
|
326
338
|
}
|
|
327
339
|
});
|
|
328
340
|
}
|
|
@@ -336,7 +348,8 @@ export class SwitchBotPlatform {
|
|
|
336
348
|
* It should be used to setup event handlers for characteristics and update respective values.
|
|
337
349
|
*/
|
|
338
350
|
async configureAccessory(accessory) {
|
|
339
|
-
|
|
351
|
+
const { displayName } = accessory;
|
|
352
|
+
await this.debugLog(`Loading accessory from cache: ${displayName}`);
|
|
340
353
|
// add the restored accessory to the accessories cache so we can track if it has already been registered
|
|
341
354
|
this.accessories.push(accessory);
|
|
342
355
|
}
|
|
@@ -344,18 +357,18 @@ export class SwitchBotPlatform {
|
|
|
344
357
|
* Verify the config passed to the plugin is valid
|
|
345
358
|
*/
|
|
346
359
|
async verifyConfig() {
|
|
347
|
-
this.debugLog('Verifying Config');
|
|
360
|
+
await this.debugLog('Verifying Config');
|
|
348
361
|
this.config = this.config || {};
|
|
349
362
|
this.config.options = this.config.options || {};
|
|
350
363
|
const platformConfig = {};
|
|
351
364
|
if (this.config.options.logging) {
|
|
352
|
-
platformConfig
|
|
365
|
+
platformConfig.logging = this.config.options.logging;
|
|
353
366
|
}
|
|
354
367
|
if (this.config.options.logging && this.config.options.refreshRate) {
|
|
355
|
-
platformConfig
|
|
368
|
+
platformConfig.refreshRate = this.config.options.refreshRate;
|
|
356
369
|
}
|
|
357
370
|
if (this.config.options.logging && this.config.options.pushRate) {
|
|
358
|
-
platformConfig
|
|
371
|
+
platformConfig.pushRate = this.config.options.pushRate;
|
|
359
372
|
}
|
|
360
373
|
if (Object.entries(platformConfig).length !== 0) {
|
|
361
374
|
await this.debugWarnLog(`Platform Config: ${JSON.stringify(platformConfig)}`);
|
|
@@ -379,10 +392,10 @@ export class SwitchBotPlatform {
|
|
|
379
392
|
for (const irDeviceConfig of this.config.options.irdevices) {
|
|
380
393
|
if (!irDeviceConfig.hide_device) {
|
|
381
394
|
if (!irDeviceConfig.deviceId) {
|
|
382
|
-
this.errorLog('The devices config section is missing the *Device ID* in the config. Please check your config.');
|
|
395
|
+
await this.errorLog('The devices config section is missing the *Device ID* in the config. Please check your config.');
|
|
383
396
|
}
|
|
384
397
|
if (!irDeviceConfig.deviceId && !irDeviceConfig.configRemoteType) {
|
|
385
|
-
this.errorLog('The devices config section is missing the *Device Type* in the config. Please check your config.');
|
|
398
|
+
await this.errorLog('The devices config section is missing the *Device Type* in the config. Please check your config.');
|
|
386
399
|
}
|
|
387
400
|
}
|
|
388
401
|
}
|
|
@@ -394,16 +407,16 @@ export class SwitchBotPlatform {
|
|
|
394
407
|
if (!this.config.options.refreshRate) {
|
|
395
408
|
// default 120 seconds (2 minutes)
|
|
396
409
|
this.config.options.refreshRate = 120;
|
|
397
|
-
this.debugWarnLog('Using Default Refresh Rate (2 minutes).');
|
|
410
|
+
await this.debugWarnLog('Using Default Refresh Rate (2 minutes).');
|
|
398
411
|
}
|
|
399
412
|
if (!this.config.options.pushRate) {
|
|
400
413
|
// default 100 milliseconds
|
|
401
414
|
this.config.options.pushRate = 0.1;
|
|
402
|
-
this.debugWarnLog('Using Default Push Rate.');
|
|
415
|
+
await this.debugWarnLog('Using Default Push Rate.');
|
|
403
416
|
}
|
|
404
417
|
if (!this.config.options.maxRetries) {
|
|
405
418
|
this.config.options.maxRetries = 5;
|
|
406
|
-
this.debugWarnLog('Using Default Max Retries.');
|
|
419
|
+
await this.debugWarnLog('Using Default Max Retries.');
|
|
407
420
|
}
|
|
408
421
|
else {
|
|
409
422
|
this.maxRetries = this.config.options.maxRetries;
|
|
@@ -411,23 +424,23 @@ export class SwitchBotPlatform {
|
|
|
411
424
|
if (!this.config.options.delayBetweenRetries) {
|
|
412
425
|
// default 3 seconds
|
|
413
426
|
this.config.options.delayBetweenRetries = 3000;
|
|
414
|
-
this.debugWarnLog('Using Default Delay Between Retries.');
|
|
427
|
+
await this.debugWarnLog('Using Default Delay Between Retries.');
|
|
415
428
|
}
|
|
416
429
|
else {
|
|
417
430
|
this.delayBetweenRetries = this.config.options.delayBetweenRetries * 1000;
|
|
418
431
|
}
|
|
419
432
|
if (!this.config.credentials && !this.config.options) {
|
|
420
|
-
this.debugWarnLog('Missing Credentials');
|
|
433
|
+
await this.debugWarnLog('Missing Credentials');
|
|
421
434
|
}
|
|
422
435
|
else if (this.config.credentials && !this.config.credentials.notice) {
|
|
423
436
|
if (!this.config.credentials?.token) {
|
|
424
|
-
this.debugErrorLog('Missing token');
|
|
425
|
-
this.debugWarnLog('Cloud Enabled SwitchBot Devices & IR Devices will not work');
|
|
437
|
+
await this.debugErrorLog('Missing token');
|
|
438
|
+
await this.debugWarnLog('Cloud Enabled SwitchBot Devices & IR Devices will not work');
|
|
426
439
|
}
|
|
427
440
|
if (this.config.credentials?.token) {
|
|
428
441
|
if (!this.config.credentials?.secret) {
|
|
429
|
-
this.debugErrorLog('Missing secret');
|
|
430
|
-
this.debugWarnLog('Cloud Enabled SwitchBot Devices & IR Devices will not work');
|
|
442
|
+
await this.debugErrorLog('Missing secret');
|
|
443
|
+
await this.debugWarnLog('Cloud Enabled SwitchBot Devices & IR Devices will not work');
|
|
431
444
|
}
|
|
432
445
|
}
|
|
433
446
|
}
|
|
@@ -435,7 +448,6 @@ export class SwitchBotPlatform {
|
|
|
435
448
|
/**
|
|
436
449
|
* The openToken was old config.
|
|
437
450
|
* This method saves the openToken as the token in the config.json file
|
|
438
|
-
* @param this.config.credentials.openToken
|
|
439
451
|
*/
|
|
440
452
|
async updateToken() {
|
|
441
453
|
try {
|
|
@@ -447,7 +459,7 @@ export class SwitchBotPlatform {
|
|
|
447
459
|
const currentConfig = JSON.parse(readFileSync(this.api.user.configPath(), 'utf8'));
|
|
448
460
|
// check the platforms section is an array before we do array things on it
|
|
449
461
|
if (!Array.isArray(currentConfig.platforms)) {
|
|
450
|
-
throw new
|
|
462
|
+
throw new TypeError('Cannot find platforms array in config');
|
|
451
463
|
}
|
|
452
464
|
// find this plugins current config
|
|
453
465
|
const pluginConfig = currentConfig.platforms.find((x) => x.platform === PLATFORM_NAME);
|
|
@@ -456,17 +468,15 @@ export class SwitchBotPlatform {
|
|
|
456
468
|
}
|
|
457
469
|
// check the .credentials is an object before doing object things with it
|
|
458
470
|
if (typeof pluginConfig.credentials !== 'object') {
|
|
459
|
-
throw new
|
|
471
|
+
throw new TypeError('pluginConfig.credentials is not an object');
|
|
460
472
|
}
|
|
461
473
|
// Move openToken to token
|
|
462
474
|
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');
|
|
475
|
+
await this.warnLog('This plugin has been updated to use OpenAPI v1.1, config is set with openToken, "openToken" cconfig has been moved to the "token" config');
|
|
465
476
|
this.errorLog('"secret" config is not populated, you must populate then please restart Homebridge.');
|
|
466
477
|
}
|
|
467
478
|
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.');
|
|
479
|
+
await this.warnLog('This plugin has been updated to use OpenAPI v1.1, config is set with openToken, "openToken" config has been moved to the "token" config, please restart Homebridge.');
|
|
470
480
|
}
|
|
471
481
|
// set the refresh token
|
|
472
482
|
pluginConfig.credentials.token = this.config.credentials?.openToken;
|
|
@@ -476,10 +486,10 @@ export class SwitchBotPlatform {
|
|
|
476
486
|
await this.debugWarnLog(`token: ${pluginConfig.credentials.token}`);
|
|
477
487
|
// save the config, ensuring we maintain pretty json
|
|
478
488
|
writeFileSync(this.api.user.configPath(), JSON.stringify(currentConfig, null, 4));
|
|
479
|
-
this.verifyConfig();
|
|
489
|
+
await this.verifyConfig();
|
|
480
490
|
}
|
|
481
491
|
catch (e) {
|
|
482
|
-
this.errorLog(`Update Token: ${e}`);
|
|
492
|
+
await this.errorLog(`Update Token: ${e}`);
|
|
483
493
|
}
|
|
484
494
|
}
|
|
485
495
|
generateHeaders = () => {
|
|
@@ -492,340 +502,228 @@ export class SwitchBotPlatform {
|
|
|
492
502
|
.digest();
|
|
493
503
|
const sign = signTerm.toString('base64');
|
|
494
504
|
return {
|
|
495
|
-
Authorization: this.config.credentials?.token,
|
|
496
|
-
sign: sign,
|
|
497
|
-
nonce: nonce,
|
|
498
|
-
t: t,
|
|
505
|
+
'Authorization': this.config.credentials?.token,
|
|
506
|
+
'sign': sign,
|
|
507
|
+
'nonce': nonce,
|
|
508
|
+
't': t,
|
|
499
509
|
'Content-Type': 'application/json',
|
|
500
510
|
};
|
|
501
511
|
};
|
|
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
512
|
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
|
-
}
|
|
513
|
+
if (!this.config.credentials?.token) {
|
|
514
|
+
return this.handleManualConfig();
|
|
515
|
+
}
|
|
516
|
+
let retryCount = 0;
|
|
517
|
+
const maxRetries = this.maxRetries;
|
|
518
|
+
const delayBetweenRetries = this.delayBetweenRetries;
|
|
519
|
+
await this.debugWarnLog(`Retry Count: ${retryCount}`);
|
|
520
|
+
await this.debugWarnLog(`Max Retries: ${maxRetries}`);
|
|
521
|
+
await this.debugWarnLog(`Delay Between Retries: ${delayBetweenRetries}`);
|
|
522
|
+
while (retryCount < maxRetries) {
|
|
523
|
+
try {
|
|
524
|
+
const { body, statusCode } = await request(Devices, { headers: this.generateHeaders() });
|
|
525
|
+
await this.debugWarnLog(`statusCode: ${statusCode}`);
|
|
526
|
+
const devicesAPI = await body.json();
|
|
527
|
+
await this.debugWarnLog(`devicesAPI: ${JSON.stringify(devicesAPI)}`);
|
|
528
|
+
if (this.isSuccessfulResponse(statusCode, devicesAPI.statusCode)) {
|
|
529
|
+
await this.handleDevices(devicesAPI.body.deviceList);
|
|
530
|
+
await this.handleIRDevices(devicesAPI.body.infraredRemoteList);
|
|
531
|
+
break;
|
|
629
532
|
}
|
|
630
|
-
|
|
533
|
+
else {
|
|
534
|
+
await this.handleErrorResponse(statusCode, devicesAPI.statusCode, retryCount, maxRetries, delayBetweenRetries);
|
|
631
535
|
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
536
|
}
|
|
635
537
|
}
|
|
538
|
+
catch (e) {
|
|
539
|
+
retryCount++;
|
|
540
|
+
await this.debugErrorLog(`Failed to Discover Devices, Error Message: ${JSON.stringify(e.message)}, Submit Bugs Here: https://tinyurl.com/SwitchBotBug`);
|
|
541
|
+
await this.debugErrorLog(`Failed to Discover Devices, Error: ${e}`);
|
|
542
|
+
}
|
|
636
543
|
}
|
|
637
|
-
|
|
544
|
+
}
|
|
545
|
+
async handleManualConfig() {
|
|
546
|
+
if (this.config.options?.devices) {
|
|
638
547
|
await this.debugLog(`SwitchBot Device Manual Config Set: ${JSON.stringify(this.config.options?.devices)}`);
|
|
639
|
-
const
|
|
640
|
-
const devices = deviceConfigs.map((v) => v);
|
|
548
|
+
const devices = this.config.options.devices.map((v) => v);
|
|
641
549
|
for (const device of devices) {
|
|
642
550
|
device.deviceType = device.configDeviceType;
|
|
643
551
|
device.deviceName = device.configDeviceName;
|
|
644
552
|
if (device.deviceType) {
|
|
645
|
-
this.createDevice(device);
|
|
553
|
+
await this.createDevice(device);
|
|
646
554
|
}
|
|
647
555
|
}
|
|
648
556
|
}
|
|
649
557
|
else {
|
|
650
|
-
this.errorLog('Neither SwitchBot Token or Device Config are
|
|
558
|
+
await this.errorLog('Neither SwitchBot Token or Device Config are set.');
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
isSuccessfulResponse(statusCode, apiStatusCode) {
|
|
562
|
+
return (statusCode === 200 || statusCode === 100) && (apiStatusCode === 200 || apiStatusCode === 100);
|
|
563
|
+
}
|
|
564
|
+
async handleDevices(deviceLists) {
|
|
565
|
+
if (!this.config.options?.devices) {
|
|
566
|
+
await this.debugLog(`SwitchBot Device Config Not Set: ${JSON.stringify(this.config.options?.devices)}`);
|
|
567
|
+
if (deviceLists.length === 0) {
|
|
568
|
+
await this.debugLog('SwitchBot API Has No Devices With Cloud Services Enabled');
|
|
569
|
+
}
|
|
570
|
+
else {
|
|
571
|
+
for (const device of deviceLists) {
|
|
572
|
+
if (device.deviceType) {
|
|
573
|
+
if (device.configDeviceName) {
|
|
574
|
+
device.deviceName = device.configDeviceName;
|
|
575
|
+
}
|
|
576
|
+
await this.createDevice(device);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
else {
|
|
582
|
+
await this.debugLog(`SwitchBot Device Config Set: ${JSON.stringify(this.config.options?.devices)}`);
|
|
583
|
+
const devices = this.mergeByDeviceId(deviceLists, this.config.options.devices);
|
|
584
|
+
await this.debugLog(`SwitchBot Devices: ${JSON.stringify(devices)}`);
|
|
585
|
+
for (const device of devices) {
|
|
586
|
+
if (!device.deviceType && device.configDeviceType) {
|
|
587
|
+
device.deviceType = device.configDeviceType;
|
|
588
|
+
await this.warnLog(`API is displaying no deviceType: ${device.deviceType}, So using configDeviceType: ${device.configDeviceType}`);
|
|
589
|
+
}
|
|
590
|
+
else if (!device.deviceType && !device.configDeviceName) {
|
|
591
|
+
await this.errorLog('No deviceType or configDeviceType for device. No device will be created.');
|
|
592
|
+
}
|
|
593
|
+
if (device.deviceType) {
|
|
594
|
+
if (device.configDeviceName) {
|
|
595
|
+
device.deviceName = device.configDeviceName;
|
|
596
|
+
}
|
|
597
|
+
await this.createDevice(device);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
async handleIRDevices(irDeviceLists) {
|
|
603
|
+
if (!this.config.options?.irdevices) {
|
|
604
|
+
await this.debugLog(`IR Device Config Not Set: ${JSON.stringify(this.config.options?.irdevices)}`);
|
|
605
|
+
for (const device of irDeviceLists) {
|
|
606
|
+
if (device.remoteType) {
|
|
607
|
+
await this.createIRDevice(device);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
else {
|
|
612
|
+
await this.debugLog(`IR Device Config Set: ${JSON.stringify(this.config.options?.irdevices)}`);
|
|
613
|
+
const devices = this.mergeByDeviceId(irDeviceLists, this.config.options.irdevices);
|
|
614
|
+
await this.debugLog(`IR Devices: ${JSON.stringify(devices)}`);
|
|
615
|
+
for (const device of devices) {
|
|
616
|
+
await this.createIRDevice(device);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
mergeByDeviceId(a1, a2) {
|
|
621
|
+
const normalizeDeviceId = (deviceId) => deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '');
|
|
622
|
+
return a1.map((itm) => {
|
|
623
|
+
const matchingItem = a2.find(item => normalizeDeviceId(item.deviceId) === normalizeDeviceId(itm.deviceId));
|
|
624
|
+
return { ...matchingItem, ...itm };
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
async handleErrorResponse(statusCode, apiStatusCode, retryCount, maxRetries, delayBetweenRetries) {
|
|
628
|
+
await this.statusCode(statusCode);
|
|
629
|
+
await this.statusCode(apiStatusCode);
|
|
630
|
+
if (statusCode === 500) {
|
|
631
|
+
this.infoLog(`statusCode: ${statusCode} Attempt ${retryCount + 1} of ${maxRetries}`);
|
|
632
|
+
await sleep(delayBetweenRetries);
|
|
651
633
|
}
|
|
652
634
|
}
|
|
653
635
|
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)}`);
|
|
636
|
+
const deviceTypeHandlers = {
|
|
637
|
+
'Humidifier': this.createHumidifier.bind(this),
|
|
638
|
+
'Hub 2': this.createHub2.bind(this),
|
|
639
|
+
'Bot': this.createBot.bind(this),
|
|
640
|
+
'Meter': this.createMeter.bind(this),
|
|
641
|
+
'MeterPlus': this.createMeterPlus.bind(this),
|
|
642
|
+
'Meter Plus (JP)': this.createMeterPlus.bind(this),
|
|
643
|
+
'WoIOSensor': this.createIOSensor.bind(this),
|
|
644
|
+
'Water Detector': this.createWaterDetector.bind(this),
|
|
645
|
+
'Motion Sensor': this.createMotion.bind(this),
|
|
646
|
+
'Contact Sensor': this.createContact.bind(this),
|
|
647
|
+
'Curtain': this.createCurtain.bind(this),
|
|
648
|
+
'Curtain3': this.createCurtain.bind(this),
|
|
649
|
+
'WoRollerShade': this.createCurtain.bind(this),
|
|
650
|
+
'Roller Shade': this.createCurtain.bind(this),
|
|
651
|
+
'Blind Tilt': this.createBlindTilt.bind(this),
|
|
652
|
+
'Plug': this.createPlug.bind(this),
|
|
653
|
+
'Plug Mini (US)': this.createPlug.bind(this),
|
|
654
|
+
'Plug Mini (JP)': this.createPlug.bind(this),
|
|
655
|
+
'Smart Lock': this.createLock.bind(this),
|
|
656
|
+
'Smart Lock Pro': this.createLock.bind(this),
|
|
657
|
+
'Color Bulb': this.createColorBulb.bind(this),
|
|
658
|
+
'K10+': this.createRobotVacuumCleaner.bind(this),
|
|
659
|
+
'WoSweeper': this.createRobotVacuumCleaner.bind(this),
|
|
660
|
+
'WoSweeperMini': this.createRobotVacuumCleaner.bind(this),
|
|
661
|
+
'Robot Vacuum Cleaner S1': this.createRobotVacuumCleaner.bind(this),
|
|
662
|
+
'Robot Vacuum Cleaner S1 Plus': this.createRobotVacuumCleaner.bind(this),
|
|
663
|
+
'Robot Vacuum Cleaner S10': this.createRobotVacuumCleaner.bind(this),
|
|
664
|
+
'Ceiling Light': this.createCeilingLight.bind(this),
|
|
665
|
+
'Ceiling Light Pro': this.createCeilingLight.bind(this),
|
|
666
|
+
'Strip Light': this.createStripLight.bind(this),
|
|
667
|
+
'Battery Circulator Fan': this.createFan.bind(this),
|
|
668
|
+
};
|
|
669
|
+
if (deviceTypeHandlers[device.deviceType]) {
|
|
670
|
+
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}`);
|
|
671
|
+
await deviceTypeHandlers[device.deviceType](device);
|
|
672
|
+
}
|
|
673
|
+
else if (['Hub Mini', 'Hub Plus', 'Remote', 'Indoor Cam', 'remote with screen'].includes(device.deviceType)) {
|
|
674
|
+
await this.debugLog(`Discovered ${device.deviceType}: ${device.deviceId}, is currently not supported, device: ${JSON.stringify(device)}`);
|
|
675
|
+
}
|
|
676
|
+
else {
|
|
677
|
+
await this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.deviceType}, is currently not supported. Submit Feature Requests Here: https://tinyurl.com/SwitchBotFeatureRequest, device: ${JSON.stringify(device)}`);
|
|
751
678
|
}
|
|
752
679
|
}
|
|
753
680
|
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');
|
|
681
|
+
device.connectionType = device.connectionType ?? 'OpenAPI';
|
|
682
|
+
const deviceTypeHandlers = {
|
|
683
|
+
'TV': this.createTV.bind(this),
|
|
684
|
+
'DIY TV': this.createTV.bind(this),
|
|
685
|
+
'Projector': this.createTV.bind(this),
|
|
686
|
+
'DIY Projector': this.createTV.bind(this),
|
|
687
|
+
'Set Top Box': this.createTV.bind(this),
|
|
688
|
+
'DIY Set Top Box': this.createTV.bind(this),
|
|
689
|
+
'IPTV': this.createTV.bind(this),
|
|
690
|
+
'DIY IPTV': this.createTV.bind(this),
|
|
691
|
+
'DVD': this.createTV.bind(this),
|
|
692
|
+
'DIY DVD': this.createTV.bind(this),
|
|
693
|
+
'Speaker': this.createTV.bind(this),
|
|
694
|
+
'DIY Speaker': this.createTV.bind(this),
|
|
695
|
+
'Fan': this.createIRFan.bind(this),
|
|
696
|
+
'DIY Fan': this.createIRFan.bind(this),
|
|
697
|
+
'Air Conditioner': this.createAirConditioner.bind(this),
|
|
698
|
+
'DIY Air Conditioner': this.createAirConditioner.bind(this),
|
|
699
|
+
'Light': this.createLight.bind(this),
|
|
700
|
+
'DIY Light': this.createLight.bind(this),
|
|
701
|
+
'Air Purifier': this.createAirPurifier.bind(this),
|
|
702
|
+
'DIY Air Purifier': this.createAirPurifier.bind(this),
|
|
703
|
+
'Water Heater': this.createWaterHeater.bind(this),
|
|
704
|
+
'DIY Water Heater': this.createWaterHeater.bind(this),
|
|
705
|
+
'Vacuum Cleaner': this.createVacuumCleaner.bind(this),
|
|
706
|
+
'DIY Vacuum Cleaner': this.createVacuumCleaner.bind(this),
|
|
707
|
+
'Camera': this.createCamera.bind(this),
|
|
708
|
+
'DIY Camera': this.createCamera.bind(this),
|
|
709
|
+
'Others': this.createOthers.bind(this),
|
|
710
|
+
};
|
|
711
|
+
if (deviceTypeHandlers[device.remoteType]) {
|
|
712
|
+
await this.debugLog(`Discovered ${device.remoteType}: ${device.deviceId}`);
|
|
713
|
+
if (device.remoteType.startsWith('DIY') && device.external === undefined) {
|
|
714
|
+
device.external = true;
|
|
715
|
+
}
|
|
716
|
+
await deviceTypeHandlers[device.remoteType](device);
|
|
717
|
+
}
|
|
718
|
+
else {
|
|
719
|
+
await this.warnLog(`Device: ${device.deviceName} with Device Type: ${device.remoteType}, is currently not supported. Submit Feature Requests Here: https://tinyurl.com/SwitchBotFeatureRequest, device: ${JSON.stringify(device)}`);
|
|
822
720
|
}
|
|
823
721
|
}
|
|
824
722
|
async createHumidifier(device) {
|
|
825
723
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
826
724
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
827
725
|
// the cached devices we stored in the `configureAccessory` method above
|
|
828
|
-
const existingAccessory = this.accessories.find(
|
|
726
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
829
727
|
if (existingAccessory) {
|
|
830
728
|
// the accessory already exists
|
|
831
729
|
if (await this.registerDevice(device)) {
|
|
@@ -884,7 +782,7 @@ export class SwitchBotPlatform {
|
|
|
884
782
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
885
783
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
886
784
|
// the cached devices we stored in the `configureAccessory` method above
|
|
887
|
-
const existingAccessory = this.accessories.find(
|
|
785
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
888
786
|
if (existingAccessory) {
|
|
889
787
|
// the accessory already exists
|
|
890
788
|
if (await this.registerDevice(device)) {
|
|
@@ -945,7 +843,7 @@ export class SwitchBotPlatform {
|
|
|
945
843
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
946
844
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
947
845
|
// the cached devices we stored in the `configureAccessory` method above
|
|
948
|
-
const existingAccessory = this.accessories.find(
|
|
846
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
949
847
|
if (existingAccessory) {
|
|
950
848
|
// the accessory already exists
|
|
951
849
|
if (await this.registerDevice(device)) {
|
|
@@ -1005,7 +903,7 @@ export class SwitchBotPlatform {
|
|
|
1005
903
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1006
904
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1007
905
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1008
|
-
const existingAccessory = this.accessories.find(
|
|
906
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1009
907
|
if (existingAccessory) {
|
|
1010
908
|
// the accessory already exists
|
|
1011
909
|
if (await this.registerDevice(device)) {
|
|
@@ -1066,7 +964,7 @@ export class SwitchBotPlatform {
|
|
|
1066
964
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1067
965
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1068
966
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1069
|
-
const existingAccessory = this.accessories.find(
|
|
967
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1070
968
|
if (existingAccessory) {
|
|
1071
969
|
// the accessory already exists
|
|
1072
970
|
if (await this.registerDevice(device)) {
|
|
@@ -1127,7 +1025,7 @@ export class SwitchBotPlatform {
|
|
|
1127
1025
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1128
1026
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1129
1027
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1130
|
-
const existingAccessory = this.accessories.find(
|
|
1028
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1131
1029
|
if (existingAccessory) {
|
|
1132
1030
|
// the accessory already exists
|
|
1133
1031
|
if (await this.registerDevice(device)) {
|
|
@@ -1187,7 +1085,7 @@ export class SwitchBotPlatform {
|
|
|
1187
1085
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1188
1086
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1189
1087
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1190
|
-
const existingAccessory = this.accessories.find(
|
|
1088
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1191
1089
|
if (existingAccessory) {
|
|
1192
1090
|
// the accessory already exists
|
|
1193
1091
|
if (await this.registerDevice(device)) {
|
|
@@ -1247,7 +1145,7 @@ export class SwitchBotPlatform {
|
|
|
1247
1145
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1248
1146
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1249
1147
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1250
|
-
const existingAccessory = this.accessories.find(
|
|
1148
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1251
1149
|
if (existingAccessory) {
|
|
1252
1150
|
// the accessory already exists
|
|
1253
1151
|
if (await this.registerDevice(device)) {
|
|
@@ -1307,7 +1205,7 @@ export class SwitchBotPlatform {
|
|
|
1307
1205
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1308
1206
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1309
1207
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1310
|
-
const existingAccessory = this.accessories.find(
|
|
1208
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1311
1209
|
if (existingAccessory) {
|
|
1312
1210
|
// the accessory already exists
|
|
1313
1211
|
if (await this.registerDevice(device)) {
|
|
@@ -1367,7 +1265,7 @@ export class SwitchBotPlatform {
|
|
|
1367
1265
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1368
1266
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1369
1267
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1370
|
-
const existingAccessory = this.accessories.find(
|
|
1268
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1371
1269
|
if (existingAccessory) {
|
|
1372
1270
|
// the accessory already exists
|
|
1373
1271
|
if (await this.registerDevice(device)) {
|
|
@@ -1395,8 +1293,8 @@ export class SwitchBotPlatform {
|
|
|
1395
1293
|
else if (await this.registerDevice(device)) {
|
|
1396
1294
|
if (isBlindTiltDevice(device)) {
|
|
1397
1295
|
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}`);
|
|
1296
|
+
this.debugLog('Your Curtains are grouped, '
|
|
1297
|
+
+ `, Secondary curtain automatically hidden. Main Curtain: ${device.deviceName}, deviceId: ${device.deviceId}`);
|
|
1400
1298
|
}
|
|
1401
1299
|
else {
|
|
1402
1300
|
if (device.master) {
|
|
@@ -1414,7 +1312,6 @@ export class SwitchBotPlatform {
|
|
|
1414
1312
|
// store a copy of the device object in the `accessory.context`
|
|
1415
1313
|
// the `context` property can be used to store any data about the accessory you may need
|
|
1416
1314
|
accessory.context.device = device;
|
|
1417
|
-
;
|
|
1418
1315
|
accessory.context.deviceId = device.deviceId;
|
|
1419
1316
|
accessory.context.deviceType = device.deviceType;
|
|
1420
1317
|
accessory.context.model = SwitchBotModel.BlindTilt;
|
|
@@ -1442,7 +1339,7 @@ export class SwitchBotPlatform {
|
|
|
1442
1339
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1443
1340
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1444
1341
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1445
|
-
const existingAccessory = this.accessories.find(
|
|
1342
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1446
1343
|
if (existingAccessory) {
|
|
1447
1344
|
// the accessory already exists
|
|
1448
1345
|
if (await this.registerDevice(device)) {
|
|
@@ -1470,8 +1367,8 @@ export class SwitchBotPlatform {
|
|
|
1470
1367
|
else if (await this.registerDevice(device)) {
|
|
1471
1368
|
if (isCurtainDevice(device)) {
|
|
1472
1369
|
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}`);
|
|
1370
|
+
this.debugLog('Your Curtains are grouped, '
|
|
1371
|
+
+ `, Secondary curtain automatically hidden. Main Curtain: ${device.deviceName}, deviceId: ${device.deviceId}`);
|
|
1475
1372
|
}
|
|
1476
1373
|
else {
|
|
1477
1374
|
if (device.master) {
|
|
@@ -1516,7 +1413,7 @@ export class SwitchBotPlatform {
|
|
|
1516
1413
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1517
1414
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1518
1415
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1519
|
-
const existingAccessory = this.accessories.find(
|
|
1416
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1520
1417
|
if (existingAccessory) {
|
|
1521
1418
|
// the accessory already exists
|
|
1522
1419
|
if (await this.registerDevice(device)) {
|
|
@@ -1524,8 +1421,11 @@ export class SwitchBotPlatform {
|
|
|
1524
1421
|
existingAccessory.context.device = device;
|
|
1525
1422
|
existingAccessory.context.deviceId = device.deviceId;
|
|
1526
1423
|
existingAccessory.context.deviceType = device.deviceType;
|
|
1527
|
-
existingAccessory.context.model = device.deviceType === 'Plug Mini (US)'
|
|
1528
|
-
? SwitchBotModel.
|
|
1424
|
+
existingAccessory.context.model = device.deviceType === 'Plug Mini (US)'
|
|
1425
|
+
? SwitchBotModel.PlugMiniUS
|
|
1426
|
+
: device.deviceType === 'Plug Mini (JP)'
|
|
1427
|
+
? SwitchBotModel.PlugMiniJP
|
|
1428
|
+
: SwitchBotModel.Plug;
|
|
1529
1429
|
existingAccessory.displayName = device.configDeviceName
|
|
1530
1430
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
1531
1431
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
@@ -1552,8 +1452,11 @@ export class SwitchBotPlatform {
|
|
|
1552
1452
|
accessory.context.device = device;
|
|
1553
1453
|
accessory.context.deviceId = device.deviceId;
|
|
1554
1454
|
accessory.context.deviceType = device.deviceType;
|
|
1555
|
-
accessory.context.model = device.deviceType === 'Plug Mini (US)'
|
|
1556
|
-
? SwitchBotModel.
|
|
1455
|
+
accessory.context.model = device.deviceType === 'Plug Mini (US)'
|
|
1456
|
+
? SwitchBotModel.PlugMiniUS
|
|
1457
|
+
: device.deviceType === 'Plug Mini (JP)'
|
|
1458
|
+
? SwitchBotModel.PlugMiniJP
|
|
1459
|
+
: SwitchBotModel.Plug;
|
|
1557
1460
|
accessory.displayName = device.configDeviceName
|
|
1558
1461
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
1559
1462
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
@@ -1578,7 +1481,7 @@ export class SwitchBotPlatform {
|
|
|
1578
1481
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1579
1482
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1580
1483
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1581
|
-
const existingAccessory = this.accessories.find(
|
|
1484
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1582
1485
|
if (existingAccessory) {
|
|
1583
1486
|
// the accessory already exists
|
|
1584
1487
|
if (await this.registerDevice(device)) {
|
|
@@ -1638,7 +1541,7 @@ export class SwitchBotPlatform {
|
|
|
1638
1541
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1639
1542
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1640
1543
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1641
|
-
const existingAccessory = this.accessories.find(
|
|
1544
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1642
1545
|
if (existingAccessory) {
|
|
1643
1546
|
// the accessory already exists
|
|
1644
1547
|
if (await this.registerDevice(device)) {
|
|
@@ -1698,7 +1601,7 @@ export class SwitchBotPlatform {
|
|
|
1698
1601
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1699
1602
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1700
1603
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1701
|
-
const existingAccessory = this.accessories.find(
|
|
1604
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1702
1605
|
if (existingAccessory) {
|
|
1703
1606
|
// the accessory already exists
|
|
1704
1607
|
if (await this.registerDevice(device)) {
|
|
@@ -1758,7 +1661,7 @@ export class SwitchBotPlatform {
|
|
|
1758
1661
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1759
1662
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1760
1663
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1761
|
-
const existingAccessory = this.accessories.find(
|
|
1664
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1762
1665
|
if (existingAccessory) {
|
|
1763
1666
|
// the accessory already exists
|
|
1764
1667
|
if (await this.registerDevice(device)) {
|
|
@@ -1818,7 +1721,7 @@ export class SwitchBotPlatform {
|
|
|
1818
1721
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1819
1722
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1820
1723
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1821
|
-
const existingAccessory = this.accessories.find(
|
|
1724
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1822
1725
|
if (existingAccessory) {
|
|
1823
1726
|
// the accessory already exists
|
|
1824
1727
|
if (await this.registerDevice(device)) {
|
|
@@ -1878,7 +1781,7 @@ export class SwitchBotPlatform {
|
|
|
1878
1781
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`);
|
|
1879
1782
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1880
1783
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1881
|
-
const existingAccessory = this.accessories.find(
|
|
1784
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1882
1785
|
if (existingAccessory) {
|
|
1883
1786
|
// the accessory already exists
|
|
1884
1787
|
if (await this.registerDevice(device)) {
|
|
@@ -1886,11 +1789,17 @@ export class SwitchBotPlatform {
|
|
|
1886
1789
|
existingAccessory.context.device = device;
|
|
1887
1790
|
existingAccessory.context.deviceId = device.deviceId;
|
|
1888
1791
|
existingAccessory.context.deviceType = device.deviceType;
|
|
1889
|
-
existingAccessory.context.model = device.deviceType === 'Robot Vacuum Cleaner S1'
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1792
|
+
existingAccessory.context.model = device.deviceType === 'Robot Vacuum Cleaner S1'
|
|
1793
|
+
? SwitchBotModel.RobotVacuumCleanerS1
|
|
1794
|
+
: device.deviceType === 'Robot Vacuum Cleaner S1 Plus'
|
|
1795
|
+
? SwitchBotModel.RobotVacuumCleanerS1Plus
|
|
1796
|
+
: device.deviceType === 'Robot Vacuum Cleaner S10'
|
|
1797
|
+
? SwitchBotModel.RobotVacuumCleanerS10
|
|
1798
|
+
: device.deviceType === 'WoSweeper'
|
|
1799
|
+
? SwitchBotModel.WoSweeper
|
|
1800
|
+
: device.deviceType === 'WoSweeperMini'
|
|
1801
|
+
? SwitchBotModel.WoSweeperMini
|
|
1802
|
+
: SwitchBotModel.Unknown;
|
|
1894
1803
|
existingAccessory.displayName = device.configDeviceName
|
|
1895
1804
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
1896
1805
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
@@ -1917,11 +1826,17 @@ export class SwitchBotPlatform {
|
|
|
1917
1826
|
accessory.context.device = device;
|
|
1918
1827
|
accessory.context.deviceId = device.deviceId;
|
|
1919
1828
|
accessory.context.deviceType = device.deviceType;
|
|
1920
|
-
accessory.context.model = device.deviceType === 'Robot Vacuum Cleaner S1'
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1829
|
+
accessory.context.model = device.deviceType === 'Robot Vacuum Cleaner S1'
|
|
1830
|
+
? SwitchBotModel.RobotVacuumCleanerS1
|
|
1831
|
+
: device.deviceType === 'Robot Vacuum Cleaner S1 Plus'
|
|
1832
|
+
? SwitchBotModel.RobotVacuumCleanerS1Plus
|
|
1833
|
+
: device.deviceType === 'Robot Vacuum Cleaner S10'
|
|
1834
|
+
? SwitchBotModel.RobotVacuumCleanerS10
|
|
1835
|
+
: device.deviceType === 'WoSweeper'
|
|
1836
|
+
? SwitchBotModel.WoSweeper
|
|
1837
|
+
: device.deviceType === 'WoSweeperMini'
|
|
1838
|
+
? SwitchBotModel.WoSweeperMini
|
|
1839
|
+
: SwitchBotModel.Unknown;
|
|
1925
1840
|
accessory.displayName = device.configDeviceName
|
|
1926
1841
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
1927
1842
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
@@ -1946,7 +1861,7 @@ export class SwitchBotPlatform {
|
|
|
1946
1861
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
1947
1862
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
1948
1863
|
// the cached devices we stored in the `configureAccessory` method above
|
|
1949
|
-
const existingAccessory = this.accessories.find(
|
|
1864
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
1950
1865
|
if (!device.hide_device && existingAccessory) {
|
|
1951
1866
|
// if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
|
|
1952
1867
|
existingAccessory.context.device = device;
|
|
@@ -1979,7 +1894,6 @@ export class SwitchBotPlatform {
|
|
|
1979
1894
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
1980
1895
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
1981
1896
|
accessory.context.connectionType = await this.connectionType(device);
|
|
1982
|
-
accessory.context.connectionType = device.connectionType;
|
|
1983
1897
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
1984
1898
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
1985
1899
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -1987,7 +1901,7 @@ export class SwitchBotPlatform {
|
|
|
1987
1901
|
// this is imported from `platformAccessory.ts`
|
|
1988
1902
|
new TV(this, accessory, device);
|
|
1989
1903
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
1990
|
-
this.
|
|
1904
|
+
this.externalOrPlatform(device, accessory);
|
|
1991
1905
|
this.accessories.push(accessory);
|
|
1992
1906
|
}
|
|
1993
1907
|
else {
|
|
@@ -1998,7 +1912,7 @@ export class SwitchBotPlatform {
|
|
|
1998
1912
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
1999
1913
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2000
1914
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2001
|
-
const existingAccessory = this.accessories.find(
|
|
1915
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2002
1916
|
if (existingAccessory) {
|
|
2003
1917
|
// the accessory already exists
|
|
2004
1918
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2037,7 +1951,6 @@ export class SwitchBotPlatform {
|
|
|
2037
1951
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2038
1952
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2039
1953
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2040
|
-
accessory.context.connectionType = device.connectionType;
|
|
2041
1954
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2042
1955
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2043
1956
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2046,7 +1959,7 @@ export class SwitchBotPlatform {
|
|
|
2046
1959
|
new IRFan(this, accessory, device);
|
|
2047
1960
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2048
1961
|
// publish device externally or link the accessory to your platform
|
|
2049
|
-
this.
|
|
1962
|
+
this.externalOrPlatform(device, accessory);
|
|
2050
1963
|
this.accessories.push(accessory);
|
|
2051
1964
|
}
|
|
2052
1965
|
else {
|
|
@@ -2057,7 +1970,7 @@ export class SwitchBotPlatform {
|
|
|
2057
1970
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2058
1971
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2059
1972
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2060
|
-
const existingAccessory = this.accessories.find(
|
|
1973
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2061
1974
|
if (existingAccessory) {
|
|
2062
1975
|
// the accessory already exists
|
|
2063
1976
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2096,7 +2009,6 @@ export class SwitchBotPlatform {
|
|
|
2096
2009
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2097
2010
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2098
2011
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2099
|
-
accessory.context.connectionType = device.connectionType;
|
|
2100
2012
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2101
2013
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2102
2014
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2105,7 +2017,7 @@ export class SwitchBotPlatform {
|
|
|
2105
2017
|
new Light(this, accessory, device);
|
|
2106
2018
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2107
2019
|
// publish device externally or link the accessory to your platform
|
|
2108
|
-
this.
|
|
2020
|
+
this.externalOrPlatform(device, accessory);
|
|
2109
2021
|
this.accessories.push(accessory);
|
|
2110
2022
|
}
|
|
2111
2023
|
else {
|
|
@@ -2116,7 +2028,7 @@ export class SwitchBotPlatform {
|
|
|
2116
2028
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2117
2029
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2118
2030
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2119
|
-
const existingAccessory = this.accessories.find(
|
|
2031
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2120
2032
|
if (existingAccessory) {
|
|
2121
2033
|
// the accessory already exists
|
|
2122
2034
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2155,7 +2067,6 @@ export class SwitchBotPlatform {
|
|
|
2155
2067
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2156
2068
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2157
2069
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2158
|
-
accessory.context.connectionType = device.connectionType;
|
|
2159
2070
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2160
2071
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2161
2072
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2164,7 +2075,7 @@ export class SwitchBotPlatform {
|
|
|
2164
2075
|
new AirConditioner(this, accessory, device);
|
|
2165
2076
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2166
2077
|
// publish device externally or link the accessory to your platform
|
|
2167
|
-
this.
|
|
2078
|
+
this.externalOrPlatform(device, accessory);
|
|
2168
2079
|
this.accessories.push(accessory);
|
|
2169
2080
|
}
|
|
2170
2081
|
else {
|
|
@@ -2175,7 +2086,7 @@ export class SwitchBotPlatform {
|
|
|
2175
2086
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2176
2087
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2177
2088
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2178
|
-
const existingAccessory = this.accessories.find(
|
|
2089
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2179
2090
|
if (existingAccessory) {
|
|
2180
2091
|
// the accessory already exists
|
|
2181
2092
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2214,7 +2125,6 @@ export class SwitchBotPlatform {
|
|
|
2214
2125
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2215
2126
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2216
2127
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2217
|
-
accessory.context.connectionType = device.connectionType;
|
|
2218
2128
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2219
2129
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2220
2130
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2223,7 +2133,7 @@ export class SwitchBotPlatform {
|
|
|
2223
2133
|
new AirPurifier(this, accessory, device);
|
|
2224
2134
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2225
2135
|
// publish device externally or link the accessory to your platform
|
|
2226
|
-
this.
|
|
2136
|
+
this.externalOrPlatform(device, accessory);
|
|
2227
2137
|
this.accessories.push(accessory);
|
|
2228
2138
|
}
|
|
2229
2139
|
else {
|
|
@@ -2234,7 +2144,7 @@ export class SwitchBotPlatform {
|
|
|
2234
2144
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2235
2145
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2236
2146
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2237
|
-
const existingAccessory = this.accessories.find(
|
|
2147
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2238
2148
|
if (existingAccessory) {
|
|
2239
2149
|
// the accessory already exists
|
|
2240
2150
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2273,7 +2183,6 @@ export class SwitchBotPlatform {
|
|
|
2273
2183
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2274
2184
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2275
2185
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2276
|
-
accessory.context.connectionType = device.connectionType;
|
|
2277
2186
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2278
2187
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2279
2188
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2282,7 +2191,7 @@ export class SwitchBotPlatform {
|
|
|
2282
2191
|
new WaterHeater(this, accessory, device);
|
|
2283
2192
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2284
2193
|
// publish device externally or link the accessory to your platform
|
|
2285
|
-
this.
|
|
2194
|
+
this.externalOrPlatform(device, accessory);
|
|
2286
2195
|
this.accessories.push(accessory);
|
|
2287
2196
|
}
|
|
2288
2197
|
else {
|
|
@@ -2293,7 +2202,7 @@ export class SwitchBotPlatform {
|
|
|
2293
2202
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2294
2203
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2295
2204
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2296
|
-
const existingAccessory = this.accessories.find(
|
|
2205
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2297
2206
|
if (existingAccessory) {
|
|
2298
2207
|
// the accessory already exists
|
|
2299
2208
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2332,7 +2241,6 @@ export class SwitchBotPlatform {
|
|
|
2332
2241
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2333
2242
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2334
2243
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2335
|
-
accessory.context.connectionType = device.connectionType;
|
|
2336
2244
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2337
2245
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2338
2246
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2341,7 +2249,7 @@ export class SwitchBotPlatform {
|
|
|
2341
2249
|
new VacuumCleaner(this, accessory, device);
|
|
2342
2250
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2343
2251
|
// publish device externally or link the accessory to your platform
|
|
2344
|
-
this.
|
|
2252
|
+
this.externalOrPlatform(device, accessory);
|
|
2345
2253
|
this.accessories.push(accessory);
|
|
2346
2254
|
}
|
|
2347
2255
|
else {
|
|
@@ -2352,7 +2260,7 @@ export class SwitchBotPlatform {
|
|
|
2352
2260
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2353
2261
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2354
2262
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2355
|
-
const existingAccessory = this.accessories.find(
|
|
2263
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2356
2264
|
if (existingAccessory) {
|
|
2357
2265
|
// the accessory already exists
|
|
2358
2266
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2391,7 +2299,6 @@ export class SwitchBotPlatform {
|
|
|
2391
2299
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2392
2300
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2393
2301
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2394
|
-
accessory.context.connectionType = device.connectionType;
|
|
2395
2302
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2396
2303
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2397
2304
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2400,7 +2307,7 @@ export class SwitchBotPlatform {
|
|
|
2400
2307
|
new Camera(this, accessory, device);
|
|
2401
2308
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2402
2309
|
// publish device externally or link the accessory to your platform
|
|
2403
|
-
this.
|
|
2310
|
+
this.externalOrPlatform(device, accessory);
|
|
2404
2311
|
this.accessories.push(accessory);
|
|
2405
2312
|
}
|
|
2406
2313
|
else {
|
|
@@ -2411,7 +2318,7 @@ export class SwitchBotPlatform {
|
|
|
2411
2318
|
const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.remoteType}`);
|
|
2412
2319
|
// see if an accessory with the same uuid has already been registered and restored from
|
|
2413
2320
|
// the cached devices we stored in the `configureAccessory` method above
|
|
2414
|
-
const existingAccessory = this.accessories.find(
|
|
2321
|
+
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
|
|
2415
2322
|
if (existingAccessory) {
|
|
2416
2323
|
// the accessory already exists
|
|
2417
2324
|
if (!device.hide_device && device.hubDeviceId) {
|
|
@@ -2450,7 +2357,6 @@ export class SwitchBotPlatform {
|
|
|
2450
2357
|
? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName)
|
|
2451
2358
|
: await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName);
|
|
2452
2359
|
accessory.context.connectionType = await this.connectionType(device);
|
|
2453
|
-
accessory.context.connectionType = device.connectionType;
|
|
2454
2360
|
accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0';
|
|
2455
2361
|
const newOrExternal = !device.external ? 'Adding new' : 'Loading external';
|
|
2456
2362
|
await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`);
|
|
@@ -2459,7 +2365,7 @@ export class SwitchBotPlatform {
|
|
|
2459
2365
|
new Others(this, accessory, device);
|
|
2460
2366
|
await this.debugLog(`${device.remoteType} uuid: ${device.deviceId}-${device.remoteType}, (${accessory.UUID})`);
|
|
2461
2367
|
// publish device externally or link the accessory to your platform
|
|
2462
|
-
this.
|
|
2368
|
+
this.externalOrPlatform(device, accessory);
|
|
2463
2369
|
this.accessories.push(accessory);
|
|
2464
2370
|
}
|
|
2465
2371
|
else {
|
|
@@ -2467,24 +2373,13 @@ export class SwitchBotPlatform {
|
|
|
2467
2373
|
}
|
|
2468
2374
|
}
|
|
2469
2375
|
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
2376
|
let registerWindowCovering;
|
|
2478
2377
|
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}`);
|
|
2378
|
+
await this.debugWarnLog(`deviceName: ${device.deviceName} deviceId: ${device.deviceId}, curtainDevicesIds: ${device.curtainDevicesIds},x master: ${device.master}, group: ${device.group}, disable_group: ${device.curtain?.disable_group}, connectionType: ${device.connectionType}`);
|
|
2482
2379
|
registerWindowCovering = await this.registerWindowCovering(device);
|
|
2483
2380
|
}
|
|
2484
2381
|
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}`);
|
|
2382
|
+
await this.debugWarnLog(`deviceName: ${device.deviceName} deviceId: ${device.deviceId}, blindTiltDevicesIds: ${device.blindTiltDevicesIds}, master: ${device.master}, group: ${device.group}, disable_group: ${device.curtain?.disable_group}, connectionType: ${device.connectionType}`);
|
|
2488
2383
|
registerWindowCovering = await this.registerWindowCovering(device);
|
|
2489
2384
|
}
|
|
2490
2385
|
else {
|
|
@@ -2498,36 +2393,31 @@ export class SwitchBotPlatform {
|
|
|
2498
2393
|
if (device.master && device.group) {
|
|
2499
2394
|
// OpenAPI: Master Curtains/Blind Tilt in Group
|
|
2500
2395
|
registerCurtain = true;
|
|
2501
|
-
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}
|
|
2502
|
-
+ ` device.group: ${device.group} connectionType; ${device.connectionType}`);
|
|
2396
|
+
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}, device.group: ${device.group} connectionType; ${device.connectionType}`);
|
|
2503
2397
|
await this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}`);
|
|
2504
2398
|
}
|
|
2505
2399
|
else if (!device.master && device.curtain?.disable_group) {
|
|
2506
|
-
|
|
2400
|
+
// !device.group && device.connectionType === 'BLE'
|
|
2507
2401
|
// OpenAPI: Non-Master Curtains/Blind Tilts that has Disable Grouping Checked
|
|
2508
2402
|
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}`);
|
|
2403
|
+
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}, disable_group: ${device.curtain?.disable_group}, connectionType; ${device.connectionType}`);
|
|
2511
2404
|
await this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}`);
|
|
2512
2405
|
}
|
|
2513
2406
|
else if (device.master && !device.group) {
|
|
2514
2407
|
// OpenAPI: Master Curtains/Blind Tilts not in Group
|
|
2515
2408
|
registerCurtain = true;
|
|
2516
|
-
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}
|
|
2517
|
-
+ ` device.group: ${device.group} connectionType; ${device.connectionType}`);
|
|
2409
|
+
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] device.master: ${device.master}, device.group: ${device.group} connectionType; ${device.connectionType}`);
|
|
2518
2410
|
await this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}`);
|
|
2519
2411
|
}
|
|
2520
2412
|
else if (device.connectionType === 'BLE') {
|
|
2521
2413
|
// BLE: Curtains/Blind Tilt
|
|
2522
2414
|
registerCurtain = true;
|
|
2523
|
-
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] connectionType: ${device.connectionType}, `
|
|
2524
|
-
+ ` group: ${device.group}`);
|
|
2415
|
+
await this.debugLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] connectionType: ${device.connectionType}, group: ${device.group}`);
|
|
2525
2416
|
await this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}`);
|
|
2526
2417
|
}
|
|
2527
2418
|
else {
|
|
2528
2419
|
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}`);
|
|
2420
|
+
await this.debugErrorLog(`deviceName: ${device.deviceName} [${device.deviceType} Config] disable_group: ${device.curtain?.disable_group}, device.master: ${device.master}, device.group: ${device.group}`);
|
|
2531
2421
|
await this.debugWarnLog(`Device: ${device.deviceName} registerCurtains: ${registerCurtain}, device.connectionType: ${device.connectionType}`);
|
|
2532
2422
|
}
|
|
2533
2423
|
return registerCurtain;
|
|
@@ -2545,189 +2435,93 @@ export class SwitchBotPlatform {
|
|
|
2545
2435
|
async registerDevice(device) {
|
|
2546
2436
|
device.connectionType = await this.connectionType(device);
|
|
2547
2437
|
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`);
|
|
2438
|
+
const shouldRegister = !device.hide_device && (device.connectionType === 'BLE/OpenAPI' || (device.deviceId && device.configDeviceType && device.configDeviceName && device.connectionType === 'BLE') || device.connectionType === 'OpenAPI' || device.connectionType === 'Disabled');
|
|
2439
|
+
if (shouldRegister) {
|
|
2440
|
+
registerDevice = await this.handleDeviceRegistration(device);
|
|
2626
2441
|
}
|
|
2627
2442
|
else {
|
|
2628
2443
|
registerDevice = false;
|
|
2629
|
-
await this.debugErrorLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, hide_device: `
|
|
2630
|
-
+ `${device.hide_device}, will not display in HomeKit`);
|
|
2444
|
+
await this.debugErrorLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, hide_device: ${device.hide_device}, will not display in HomeKit`);
|
|
2631
2445
|
}
|
|
2632
2446
|
return registerDevice;
|
|
2633
2447
|
}
|
|
2634
|
-
async
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2448
|
+
async handleDeviceRegistration(device) {
|
|
2449
|
+
let registerDevice;
|
|
2450
|
+
switch (device.deviceType) {
|
|
2451
|
+
case 'Curtain':
|
|
2452
|
+
case 'Curtain3':
|
|
2453
|
+
case 'Blind Tilt':
|
|
2454
|
+
registerDevice = await this.registerCurtains(device);
|
|
2455
|
+
await this.debugWarnLog(`Device: ${device.deviceName} ${device.deviceType} registerDevice: ${registerDevice}`);
|
|
2456
|
+
break;
|
|
2457
|
+
default:
|
|
2458
|
+
registerDevice = true;
|
|
2459
|
+
await this.debugWarnLog(`Device: ${device.deviceName} registerDevice: ${registerDevice}`);
|
|
2460
|
+
}
|
|
2461
|
+
if (registerDevice) {
|
|
2462
|
+
await this.debugWarnLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, will display in HomeKit`);
|
|
2643
2463
|
}
|
|
2644
2464
|
else {
|
|
2645
|
-
await this.
|
|
2646
|
-
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
|
|
2465
|
+
await this.debugErrorLog(`Device: ${device.deviceName} connectionType: ${device.connectionType}, will not display in HomeKit`);
|
|
2647
2466
|
}
|
|
2467
|
+
return registerDevice;
|
|
2648
2468
|
}
|
|
2649
2469
|
async externalOrPlatform(device, accessory) {
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2470
|
+
const { displayName } = accessory;
|
|
2471
|
+
const isExternal = device.external ?? false;
|
|
2472
|
+
if (isExternal) {
|
|
2473
|
+
await this.debugWarnLog(`${displayName} External Accessory Mode`);
|
|
2474
|
+
this.api.publishExternalAccessories(PLUGIN_NAME, [accessory]);
|
|
2653
2475
|
}
|
|
2654
2476
|
else {
|
|
2655
|
-
await this.debugLog(`${
|
|
2477
|
+
await this.debugLog(`${displayName} External Accessory Mode: ${isExternal}`);
|
|
2656
2478
|
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
|
|
2657
2479
|
}
|
|
2658
2480
|
}
|
|
2659
|
-
async externalAccessory(accessory) {
|
|
2660
|
-
this.api.publishExternalAccessories(PLUGIN_NAME, [accessory]);
|
|
2661
|
-
}
|
|
2662
2481
|
unregisterPlatformAccessories(existingAccessory) {
|
|
2482
|
+
const { displayName } = existingAccessory;
|
|
2663
2483
|
// remove platform accessories when no longer present
|
|
2664
2484
|
this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [existingAccessory]);
|
|
2665
|
-
this.warnLog(`Removing existing accessory from cache: ${
|
|
2485
|
+
this.warnLog(`Removing existing accessory from cache: ${displayName}`);
|
|
2666
2486
|
}
|
|
2487
|
+
/**
|
|
2488
|
+
* Handles the status codes returned by the device and logs appropriate messages.
|
|
2489
|
+
*
|
|
2490
|
+
* @param statusCode - The status code returned by the device.
|
|
2491
|
+
* @returns A promise that resolves when the logging is complete.
|
|
2492
|
+
*/
|
|
2667
2493
|
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`);
|
|
2494
|
+
const messages = {
|
|
2495
|
+
151: `Command not supported by this device type, statusCode: ${statusCode}, Submit Feature Request Here:
|
|
2496
|
+
https://tinyurl.com/SwitchBotFeatureRequest`,
|
|
2497
|
+
152: `Device not found, statusCode: ${statusCode}`,
|
|
2498
|
+
160: `Command is not supported, statusCode: ${statusCode}, Submit Bugs Here: https://tinyurl.com/SwitchBotBug`,
|
|
2499
|
+
161: `Device is offline, statusCode: ${statusCode}`,
|
|
2500
|
+
171: `is offline, statusCode: ${statusCode}`,
|
|
2501
|
+
190: `Requests reached the daily limit, statusCode: ${statusCode}`,
|
|
2502
|
+
100: `Command successfully sent, statusCode: ${statusCode}`,
|
|
2503
|
+
200: `Request successful, statusCode: ${statusCode}`,
|
|
2504
|
+
400: `Bad Request, The client has issued an invalid request. This is commonly used to specify validation errors in a request payload,
|
|
2505
|
+
statusCode: ${statusCode}`,
|
|
2506
|
+
401: `Unauthorized, Authorization for the API is required, but the request has not been authenticated, statusCode: ${statusCode}`,
|
|
2507
|
+
403: `Forbidden, The request has been authenticated but does not have appropriate permissions, or a requested resource is not found,
|
|
2508
|
+
statusCode: ${statusCode}`,
|
|
2509
|
+
404: `Not Found, Specifies the requested path does not exist, statusCode: ${statusCode}`,
|
|
2510
|
+
406: `Not Acceptable, The client has requested a MIME type via the Accept header for a value not supported by the server,
|
|
2511
|
+
statusCode: ${statusCode}`,
|
|
2512
|
+
415: `Unsupported Media Type, The client has defined a contentType header that is not supported by the server, statusCode: ${statusCode}`,
|
|
2513
|
+
422: `Unprocessable Entity, The client has made a valid request, but the server cannot process it. This is often used for APIs for which
|
|
2514
|
+
certain limits have been exceeded, statusCode: ${statusCode}`,
|
|
2515
|
+
429: `Too Many Requests, The client has exceeded the number of requests allowed for a given time window, statusCode: ${statusCode}`,
|
|
2516
|
+
500: `Internal Server Error, An unexpected error on the SmartThings servers has occurred. These errors should be rare,
|
|
2517
|
+
statusCode: ${statusCode}`,
|
|
2518
|
+
};
|
|
2519
|
+
const message = messages[statusCode] ?? `Unknown statusCode, statusCode: ${statusCode}, Submit Bugs Here: https://tinyurl.com/SwitchBotBug`;
|
|
2520
|
+
if ([100, 200].includes(statusCode)) {
|
|
2521
|
+
await this.debugLog(message);
|
|
2522
|
+
}
|
|
2523
|
+
else {
|
|
2524
|
+
await this.errorLog(message);
|
|
2731
2525
|
}
|
|
2732
2526
|
}
|
|
2733
2527
|
async retryRequest(deviceMaxRetries, deviceDelayBetweenRetries, url, options) {
|
|
@@ -2755,57 +2549,42 @@ export class SwitchBotPlatform {
|
|
|
2755
2549
|
}
|
|
2756
2550
|
// BLE Connection
|
|
2757
2551
|
async connectBLE(accessory, device) {
|
|
2758
|
-
let switchbot;
|
|
2759
2552
|
try {
|
|
2760
|
-
const
|
|
2761
|
-
queueScheduler.schedule(() =>
|
|
2553
|
+
const switchbot = new SwitchBot();
|
|
2554
|
+
queueScheduler.schedule(async () => switchbot);
|
|
2762
2555
|
await this.debugLog(`${device.deviceType}: ${accessory.displayName} 'node-switchbot' found: ${switchbot}`);
|
|
2556
|
+
return switchbot;
|
|
2763
2557
|
}
|
|
2764
2558
|
catch (e) {
|
|
2765
|
-
switchbot
|
|
2766
|
-
|
|
2559
|
+
await this.errorLog(`${device.deviceType}: ${accessory.displayName} 'node-switchbot' not found, Error: ${e}`);
|
|
2560
|
+
return false;
|
|
2767
2561
|
}
|
|
2768
|
-
return switchbot;
|
|
2769
2562
|
}
|
|
2770
2563
|
async getVersion() {
|
|
2771
2564
|
const json = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf-8'));
|
|
2772
2565
|
await this.debugLog(`Plugin Version: ${json.version}`);
|
|
2773
2566
|
this.version = json.version;
|
|
2567
|
+
return json.version;
|
|
2774
2568
|
}
|
|
2775
2569
|
async getPlatformConfigSettings() {
|
|
2570
|
+
const { options } = this.config;
|
|
2776
2571
|
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) {
|
|
2572
|
+
if (options) {
|
|
2573
|
+
platformConfig.logging = options.logging;
|
|
2574
|
+
platformConfig.refreshRate = options.refreshRate;
|
|
2575
|
+
platformConfig.updateRate = options.updateRate;
|
|
2576
|
+
platformConfig.pushRate = options.pushRate;
|
|
2577
|
+
this.maxRetries = options.maxRetries || 3;
|
|
2578
|
+
platformConfig.maxRetries = this.maxRetries;
|
|
2579
|
+
if (!options.maxRetries) {
|
|
2580
|
+
await this.debugWarnLog('Using Default Max Retries');
|
|
2581
|
+
}
|
|
2582
|
+
this.delayBetweenRetries = (options.delayBetweenRetries || 3) * 1000;
|
|
2583
|
+
platformConfig.delayBetweenRetries = this.delayBetweenRetries / 1000;
|
|
2584
|
+
if (!options.delayBetweenRetries) {
|
|
2585
|
+
await this.debugWarnLog('Using Default Delay Between Retries');
|
|
2586
|
+
}
|
|
2587
|
+
if (Object.keys(platformConfig).length) {
|
|
2809
2588
|
await this.debugLog(`Platform Config: ${JSON.stringify(platformConfig)}`);
|
|
2810
2589
|
}
|
|
2811
2590
|
this.platformConfig = platformConfig;
|
|
@@ -2828,31 +2607,38 @@ export class SwitchBotPlatform {
|
|
|
2828
2607
|
}
|
|
2829
2608
|
/**
|
|
2830
2609
|
* Validate and clean a string value for a Name Characteristic.
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2610
|
+
* @param displayName - The display name of the accessory.
|
|
2611
|
+
* @param name - The name of the characteristic.
|
|
2612
|
+
* @param value - The value to be validated and cleaned.
|
|
2613
|
+
* @returns The cleaned string value.
|
|
2614
|
+
*/
|
|
2836
2615
|
async validateAndCleanDisplayName(displayName, name, value) {
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2616
|
+
if (this.config.options?.allowInvalidCharacters) {
|
|
2617
|
+
return value;
|
|
2618
|
+
}
|
|
2619
|
+
else {
|
|
2620
|
+
const validPattern = /^[\p{L}\p{N}][\p{L}\p{N} ']*[\p{L}\p{N}]$/u;
|
|
2621
|
+
const invalidCharsPattern = /[^\p{L}\p{N} ']/gu;
|
|
2622
|
+
const invalidStartEndPattern = /^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/gu;
|
|
2623
|
+
if (typeof value === 'string' && !validPattern.test(value)) {
|
|
2624
|
+
await this.warnLog(`WARNING: The accessory '${displayName}' has an invalid '${name}' characteristic ('${value}'). Please use only alphanumeric, space, and apostrophe characters. Ensure it starts and ends with an alphabetic or numeric character, and avoid emojis. This may prevent the accessory from being added in the Home App or cause unresponsiveness.`);
|
|
2625
|
+
// Remove invalid characters
|
|
2626
|
+
if (invalidCharsPattern.test(value)) {
|
|
2627
|
+
const before = value;
|
|
2628
|
+
await this.warnLog(`Removing invalid characters from '${name}' characteristic, if you feel this is incorrect, please enable \'allowInvalidCharacter\' in the config to allow all characters`);
|
|
2629
|
+
value = value.replace(invalidCharsPattern, '');
|
|
2630
|
+
await this.warnLog(`${name} Before: '${before}' After: '${value}'`);
|
|
2631
|
+
}
|
|
2632
|
+
// Ensure it starts and ends with an alphanumeric character
|
|
2633
|
+
if (invalidStartEndPattern.test(value)) {
|
|
2634
|
+
const before = value;
|
|
2635
|
+
await this.warnLog(`Removing invalid starting or ending characters from '${name}' characteristic, if you feel this is incorrect, please enable \'allowInvalidCharacter\' in the config to allow all characters`);
|
|
2636
|
+
value = value.replace(invalidStartEndPattern, '');
|
|
2637
|
+
await this.warnLog(`${name} Before: '${before}' After: '${value}'`);
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
return value;
|
|
2641
|
+
}
|
|
2856
2642
|
}
|
|
2857
2643
|
/**
|
|
2858
2644
|
* If device level logging is turned on, log to log.warn
|