@switchbot/homebridge-switchbot 1.4.0 → 1.4.1-beta.3
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 +18 -0
- package/config.schema.json +83 -11
- package/dist/devices/bots.d.ts +13 -3
- package/dist/devices/bots.d.ts.map +1 -1
- package/dist/devices/bots.js +162 -105
- package/dist/devices/bots.js.map +1 -1
- package/dist/devices/colorbulb.d.ts +13 -3
- package/dist/devices/colorbulb.d.ts.map +1 -1
- package/dist/devices/colorbulb.js +161 -96
- package/dist/devices/colorbulb.js.map +1 -1
- package/dist/devices/contact.d.ts +13 -3
- package/dist/devices/contact.d.ts.map +1 -1
- package/dist/devices/contact.js +117 -63
- package/dist/devices/contact.js.map +1 -1
- package/dist/devices/curtains.d.ts +14 -5
- package/dist/devices/curtains.d.ts.map +1 -1
- package/dist/devices/curtains.js +198 -140
- package/dist/devices/curtains.js.map +1 -1
- package/dist/devices/humidifiers.d.ts +13 -3
- package/dist/devices/humidifiers.d.ts.map +1 -1
- package/dist/devices/humidifiers.js +180 -127
- package/dist/devices/humidifiers.js.map +1 -1
- package/dist/devices/meters.d.ts +13 -3
- package/dist/devices/meters.d.ts.map +1 -1
- package/dist/devices/meters.js +121 -63
- package/dist/devices/meters.js.map +1 -1
- package/dist/devices/motion.d.ts +13 -3
- package/dist/devices/motion.d.ts.map +1 -1
- package/dist/devices/motion.js +104 -45
- package/dist/devices/motion.js.map +1 -1
- package/dist/devices/plugs.d.ts +13 -3
- package/dist/devices/plugs.d.ts.map +1 -1
- package/dist/devices/plugs.js +99 -35
- package/dist/devices/plugs.js.map +1 -1
- package/dist/irdevices/airconditioners.d.ts +11 -3
- package/dist/irdevices/airconditioners.d.ts.map +1 -1
- package/dist/irdevices/airconditioners.js +80 -45
- package/dist/irdevices/airconditioners.js.map +1 -1
- package/dist/irdevices/airpurifiers.d.ts +11 -3
- package/dist/irdevices/airpurifiers.d.ts.map +1 -1
- package/dist/irdevices/airpurifiers.js +68 -31
- package/dist/irdevices/airpurifiers.js.map +1 -1
- package/dist/irdevices/cameras.d.ts +11 -3
- package/dist/irdevices/cameras.d.ts.map +1 -1
- package/dist/irdevices/cameras.js +64 -24
- package/dist/irdevices/cameras.js.map +1 -1
- package/dist/irdevices/fans.d.ts +11 -3
- package/dist/irdevices/fans.d.ts.map +1 -1
- package/dist/irdevices/fans.js +74 -35
- package/dist/irdevices/fans.js.map +1 -1
- package/dist/irdevices/lights.d.ts +11 -3
- package/dist/irdevices/lights.d.ts.map +1 -1
- package/dist/irdevices/lights.js +65 -25
- package/dist/irdevices/lights.js.map +1 -1
- package/dist/irdevices/others.d.ts +11 -3
- package/dist/irdevices/others.d.ts.map +1 -1
- package/dist/irdevices/others.js +71 -31
- package/dist/irdevices/others.js.map +1 -1
- package/dist/irdevices/tvs.d.ts +11 -3
- package/dist/irdevices/tvs.d.ts.map +1 -1
- package/dist/irdevices/tvs.js +81 -42
- package/dist/irdevices/tvs.js.map +1 -1
- package/dist/irdevices/vacuumcleaners.d.ts +11 -3
- package/dist/irdevices/vacuumcleaners.d.ts.map +1 -1
- package/dist/irdevices/vacuumcleaners.js +64 -24
- package/dist/irdevices/vacuumcleaners.js.map +1 -1
- package/dist/irdevices/waterheaters.d.ts +11 -3
- package/dist/irdevices/waterheaters.d.ts.map +1 -1
- package/dist/irdevices/waterheaters.js +64 -24
- package/dist/irdevices/waterheaters.js.map +1 -1
- package/dist/platform.d.ts +10 -10
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +290 -307
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +4 -1
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js.map +1 -1
- package/nodemon.json +1 -1
- package/package.json +70 -66
- package/src/devices/bots.ts +169 -105
- package/src/devices/colorbulb.ts +170 -99
- package/src/devices/contact.ts +124 -64
- package/src/devices/curtains.ts +207 -145
- package/src/devices/humidifiers.ts +187 -129
- package/src/devices/meters.ts +128 -64
- package/src/devices/motion.ts +110 -45
- package/src/devices/plugs.ts +104 -36
- package/src/irdevices/airconditioners.ts +85 -45
- package/src/irdevices/airpurifiers.ts +73 -31
- package/src/irdevices/cameras.ts +69 -24
- package/src/irdevices/fans.ts +79 -36
- package/src/irdevices/lights.ts +70 -25
- package/src/irdevices/others.ts +76 -31
- package/src/irdevices/tvs.ts +86 -42
- package/src/irdevices/vacuumcleaners.ts +69 -24
- package/src/irdevices/waterheaters.ts +69 -24
- package/src/platform.ts +285 -302
- package/src/settings.ts +4 -1
- package/dist/devices/indoorcam.d.ts +0 -64
- package/dist/devices/indoorcam.d.ts.map +0 -1
- package/dist/devices/indoorcam.js +0 -249
- package/dist/devices/indoorcam.js.map +0 -1
- package/src/devices/indoorcam.ts +0 -309
package/src/devices/motion.ts
CHANGED
|
@@ -2,7 +2,7 @@ import Switchbot from 'node-switchbot';
|
|
|
2
2
|
import { interval, Subject } from 'rxjs';
|
|
3
3
|
import { skipWhile } from 'rxjs/operators';
|
|
4
4
|
import { SwitchBotPlatform } from '../platform';
|
|
5
|
-
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
|
5
|
+
import { Service, PlatformAccessory, CharacteristicValue, HAPStatus } from 'homebridge';
|
|
6
6
|
import { DeviceURL, device, devicesConfig, serviceData, switchbot, deviceStatusResponse } from '../settings';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -34,8 +34,8 @@ export class Motion {
|
|
|
34
34
|
lightLevel!: serviceData['lightLevel'];
|
|
35
35
|
|
|
36
36
|
// Config
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
deviceLogging!: string;
|
|
38
|
+
deviceRefreshRate!: number;
|
|
39
39
|
|
|
40
40
|
// Updates
|
|
41
41
|
motionUbpdateInProgress!: boolean;
|
|
@@ -47,6 +47,8 @@ export class Motion {
|
|
|
47
47
|
public device: device & devicesConfig,
|
|
48
48
|
) {
|
|
49
49
|
// default placeholders
|
|
50
|
+
this.refreshRate();
|
|
51
|
+
this.logs();
|
|
50
52
|
this.MotionDetected = false;
|
|
51
53
|
|
|
52
54
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
@@ -102,13 +104,46 @@ export class Motion {
|
|
|
102
104
|
this.updateHomeKitCharacteristics();
|
|
103
105
|
|
|
104
106
|
// Start an update interval
|
|
105
|
-
interval(this.
|
|
107
|
+
interval(this.deviceRefreshRate * 1000)
|
|
106
108
|
.pipe(skipWhile(() => this.motionUbpdateInProgress))
|
|
107
109
|
.subscribe(() => {
|
|
108
110
|
this.refreshStatus();
|
|
109
111
|
});
|
|
110
112
|
}
|
|
111
113
|
|
|
114
|
+
refreshRate() {
|
|
115
|
+
if (this.device.refreshRate) {
|
|
116
|
+
this.deviceRefreshRate = this.accessory.context.refreshRate = this.device.refreshRate;
|
|
117
|
+
if (this.platform.debugMode) {
|
|
118
|
+
this.warnLog(`Using Device Config refreshRate: ${this.deviceRefreshRate}`);
|
|
119
|
+
}
|
|
120
|
+
} else if (this.platform.config.options!.refreshRate) {
|
|
121
|
+
this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
|
|
122
|
+
if (this.platform.debugMode) {
|
|
123
|
+
this.warnLog(`Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
logs() {
|
|
129
|
+
if (this.device.logging) {
|
|
130
|
+
this.deviceLogging = this.accessory.context.logging = this.device.logging;
|
|
131
|
+
if (this.platform.debugMode) {
|
|
132
|
+
this.warnLog(`Using Device Config Logging: ${this.deviceLogging}`);
|
|
133
|
+
}
|
|
134
|
+
} else if (this.platform.config.options?.logging) {
|
|
135
|
+
this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
|
|
136
|
+
if (this.platform.debugMode) {
|
|
137
|
+
this.warnLog(`Using Platform Config Logging: ${this.deviceLogging}`);
|
|
138
|
+
}
|
|
139
|
+
} else {
|
|
140
|
+
this.deviceLogging = this.accessory.context.logging = 'standard';
|
|
141
|
+
if (this.platform.debugMode) {
|
|
142
|
+
this.warnLog('Using Device Standard Logging');
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
112
147
|
/**
|
|
113
148
|
* Parse the device status from the SwitchBot api
|
|
114
149
|
*/
|
|
@@ -121,9 +156,9 @@ export class Motion {
|
|
|
121
156
|
}
|
|
122
157
|
|
|
123
158
|
private async BLEparseStatus() {
|
|
124
|
-
this.
|
|
159
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} BLE parseStatus`);
|
|
125
160
|
this.MotionDetected = Boolean(this.movement);
|
|
126
|
-
this.
|
|
161
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
|
|
127
162
|
// Light Level
|
|
128
163
|
switch (this.lightLevel) {
|
|
129
164
|
case 'dark':
|
|
@@ -144,9 +179,9 @@ export class Motion {
|
|
|
144
179
|
|
|
145
180
|
private async openAPIparseStatus() {
|
|
146
181
|
if (this.platform.config.credentials?.openToken) {
|
|
147
|
-
this.
|
|
182
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} OpenAPI parseStatus`);
|
|
148
183
|
this.MotionDetected = Boolean(this.deviceStatus.body.moveDetected);
|
|
149
|
-
this.
|
|
184
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
|
|
150
185
|
}
|
|
151
186
|
}
|
|
152
187
|
|
|
@@ -164,12 +199,12 @@ export class Motion {
|
|
|
164
199
|
private connectBLE() {
|
|
165
200
|
const switchbot = new Switchbot();
|
|
166
201
|
this.device.bleMac = ((this.device.deviceId!.match(/.{1,2}/g))!.join(':')).toLowerCase();
|
|
167
|
-
this.
|
|
202
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
168
203
|
return switchbot;
|
|
169
204
|
}
|
|
170
205
|
|
|
171
206
|
private async BLERefreshStatus() {
|
|
172
|
-
this.
|
|
207
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} BLE RefreshStatus`);
|
|
173
208
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
174
209
|
const switchbot = this.connectBLE();
|
|
175
210
|
// Start to monitor advertisement packets
|
|
@@ -183,16 +218,16 @@ export class Motion {
|
|
|
183
218
|
this.movement = ad.serviceData.movement;
|
|
184
219
|
this.battery = ad.serviceData.battery;
|
|
185
220
|
this.lightLevel = ad.serviceData.lightLevel;
|
|
186
|
-
this.
|
|
187
|
-
this.
|
|
221
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
|
|
222
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} movement: ${ad.serviceData.movement}, lightLevel: `
|
|
188
223
|
+ `${ad.serviceData.lightLevel}, battery: ${ad.serviceData.battery}`);
|
|
189
224
|
|
|
190
225
|
if (this.serviceData) {
|
|
191
226
|
this.connected = true;
|
|
192
|
-
this.
|
|
227
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} connected: ${this.connected}`);
|
|
193
228
|
} else {
|
|
194
229
|
this.connected = false;
|
|
195
|
-
this.
|
|
230
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} connected: ${this.connected}`);
|
|
196
231
|
}
|
|
197
232
|
};
|
|
198
233
|
// Wait 10 seconds
|
|
@@ -204,49 +239,49 @@ export class Motion {
|
|
|
204
239
|
this.parseStatus();
|
|
205
240
|
this.updateHomeKitCharacteristics();
|
|
206
241
|
} else {
|
|
207
|
-
this.
|
|
242
|
+
this.errorLog(`Motion Sensor: ${this.accessory.displayName} wasn't able to establish BLE Connection`);
|
|
208
243
|
if (this.platform.config.credentials?.openToken) {
|
|
209
|
-
this.
|
|
244
|
+
this.warnLog(`Motion Sensor: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
210
245
|
await this.openAPIRefreshStatus();
|
|
211
246
|
}
|
|
212
247
|
}
|
|
213
248
|
}).catch(async (e: any) => {
|
|
214
|
-
this.
|
|
215
|
-
if (this.
|
|
216
|
-
this.
|
|
249
|
+
this.errorLog(`Motion Sensor: ${this.accessory.displayName} failed refreshStatus with BLE Connection`);
|
|
250
|
+
if (this.deviceLogging === 'debug') {
|
|
251
|
+
this.errorLog(`Motion Sensor: ${this.accessory.displayName} failed refreshStatus with BLE Connection,`
|
|
217
252
|
+ ` Error Message: ${JSON.stringify(e.message)}`);
|
|
218
253
|
}
|
|
219
|
-
if (this.
|
|
220
|
-
this.
|
|
254
|
+
if (this.platform.debugMode) {
|
|
255
|
+
this.errorLog(`Motion Sensor: ${this.accessory.displayName} failed refreshStatus with BLE Connection,`
|
|
221
256
|
+ ` Error: ${JSON.stringify(e)}`);
|
|
222
257
|
}
|
|
223
258
|
if (this.platform.config.credentials?.openToken) {
|
|
224
|
-
this.
|
|
259
|
+
this.warnLog(`Motion Sensor: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
225
260
|
await this.openAPIRefreshStatus();
|
|
226
261
|
}
|
|
227
|
-
this.apiError(
|
|
262
|
+
this.apiError();
|
|
228
263
|
});
|
|
229
264
|
}
|
|
230
265
|
|
|
231
266
|
private async openAPIRefreshStatus() {
|
|
232
267
|
if (this.platform.config.credentials?.openToken) {
|
|
233
|
-
this.
|
|
268
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} OpenAPI RefreshStatus`);
|
|
234
269
|
try {
|
|
235
270
|
this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
|
|
236
|
-
this.
|
|
271
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
|
|
237
272
|
this.parseStatus();
|
|
238
273
|
this.updateHomeKitCharacteristics();
|
|
239
274
|
} catch (e: any) {
|
|
240
|
-
this.
|
|
241
|
-
if (this.
|
|
242
|
-
this.
|
|
275
|
+
this.errorLog(`Motion Sensor: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
|
|
276
|
+
if (this.deviceLogging === 'debug') {
|
|
277
|
+
this.errorLog(`Motion Sensor: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
|
|
243
278
|
+ ` Error Message: ${JSON.stringify(e.message)}`);
|
|
244
279
|
}
|
|
245
|
-
if (this.
|
|
246
|
-
this.
|
|
280
|
+
if (this.platform.debugMode) {
|
|
281
|
+
this.errorLog(`Motion Sensor: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
|
|
247
282
|
+ ` Error: ${JSON.stringify(e)}`);
|
|
248
283
|
}
|
|
249
|
-
this.apiError(
|
|
284
|
+
this.apiError();
|
|
250
285
|
}
|
|
251
286
|
}
|
|
252
287
|
}
|
|
@@ -256,40 +291,70 @@ export class Motion {
|
|
|
256
291
|
*/
|
|
257
292
|
updateHomeKitCharacteristics() {
|
|
258
293
|
if (this.MotionDetected === undefined) {
|
|
259
|
-
this.
|
|
294
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} MotionDetected: ${this.MotionDetected}`);
|
|
260
295
|
} else {
|
|
261
296
|
this.service.updateCharacteristic(this.platform.Characteristic.MotionDetected, this.MotionDetected);
|
|
262
|
-
this.
|
|
297
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} updateCharacteristic MotionDetected: ${this.MotionDetected}`);
|
|
263
298
|
}
|
|
264
299
|
if (this.device.ble) {
|
|
265
300
|
if (this.BatteryLevel === undefined) {
|
|
266
|
-
this.
|
|
301
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
|
|
267
302
|
} else {
|
|
268
303
|
this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, this.BatteryLevel);
|
|
269
|
-
this.
|
|
304
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
|
|
270
305
|
}
|
|
271
306
|
if (this.StatusLowBattery === undefined) {
|
|
272
|
-
this.
|
|
307
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
|
|
273
308
|
} else {
|
|
274
309
|
this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.StatusLowBattery);
|
|
275
|
-
this.
|
|
310
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
|
|
276
311
|
}
|
|
277
312
|
if (this.CurrentAmbientLightLevel === undefined) {
|
|
278
|
-
this.
|
|
313
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
|
|
279
314
|
} else {
|
|
280
315
|
this.lightSensorService?.updateCharacteristic(this.platform.Characteristic.CurrentAmbientLightLevel, this.CurrentAmbientLightLevel);
|
|
281
|
-
this.
|
|
316
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName}`
|
|
282
317
|
+ ` updateCharacteristic CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`);
|
|
283
318
|
}
|
|
284
319
|
}
|
|
285
320
|
}
|
|
286
321
|
|
|
287
|
-
public apiError(
|
|
288
|
-
this.
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
322
|
+
public apiError() {
|
|
323
|
+
throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Logging for Device
|
|
328
|
+
*/
|
|
329
|
+
infoLog(...log: any[]) {
|
|
330
|
+
if (this.enablingDeviceLogging()) {
|
|
331
|
+
this.platform.log.info(String(...log));
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
warnLog(...log: any[]) {
|
|
336
|
+
if (this.enablingDeviceLogging()) {
|
|
337
|
+
this.platform.log.warn(String(...log));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
errorLog(...log: any[]) {
|
|
342
|
+
if (this.enablingDeviceLogging()) {
|
|
343
|
+
this.platform.log.error(String(...log));
|
|
293
344
|
}
|
|
294
345
|
}
|
|
346
|
+
|
|
347
|
+
debugLog(...log: any[]) {
|
|
348
|
+
if (this.enablingDeviceLogging()) {
|
|
349
|
+
if (this.deviceLogging === 'debug') {
|
|
350
|
+
this.platform.log.info('[DEBUG]', String(...log));
|
|
351
|
+
} else {
|
|
352
|
+
this.platform.log.debug(String(...log));
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
enablingDeviceLogging(): boolean {
|
|
358
|
+
return this.deviceLogging === 'debug' || this.deviceLogging === 'standard';
|
|
359
|
+
}
|
|
295
360
|
}
|
package/src/devices/plugs.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { AxiosResponse } from 'axios';
|
|
|
3
3
|
import { interval, Subject } from 'rxjs';
|
|
4
4
|
import { SwitchBotPlatform } from '../platform';
|
|
5
5
|
import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
|
|
6
|
-
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
|
6
|
+
import { Service, PlatformAccessory, CharacteristicValue, HAPStatus } from 'homebridge';
|
|
7
7
|
import { DeviceURL, device, devicesConfig, deviceStatusResponse, payload } from '../settings';
|
|
8
8
|
|
|
9
9
|
export class Plug {
|
|
@@ -18,8 +18,8 @@ export class Plug {
|
|
|
18
18
|
deviceStatus!: deviceStatusResponse;
|
|
19
19
|
|
|
20
20
|
// Config
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
deviceLogging!: string;
|
|
22
|
+
deviceRefreshRate!: number;
|
|
23
23
|
|
|
24
24
|
// Updates
|
|
25
25
|
plugUpdateInProgress!: boolean;
|
|
@@ -30,16 +30,18 @@ export class Plug {
|
|
|
30
30
|
private accessory: PlatformAccessory,
|
|
31
31
|
public device: device & devicesConfig,
|
|
32
32
|
) {
|
|
33
|
-
// Bot Config
|
|
34
|
-
this.platform.device(`Plug: ${this.accessory.displayName} Config: (offline: ${device.offline})`);
|
|
35
|
-
|
|
36
33
|
// default placeholders
|
|
34
|
+
this.refreshRate();
|
|
35
|
+
this.logs();
|
|
37
36
|
if (this.On === undefined) {
|
|
38
37
|
this.On = false;
|
|
39
38
|
} else {
|
|
40
39
|
this.On = this.accessory.context.On;
|
|
41
40
|
}
|
|
42
41
|
|
|
42
|
+
// Plug Config
|
|
43
|
+
this.debugLog(`Plug: ${this.accessory.displayName} Config: (offline: ${device.offline})`);
|
|
44
|
+
|
|
43
45
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
44
46
|
this.doPlugUpdate = new Subject();
|
|
45
47
|
this.plugUpdateInProgress = false;
|
|
@@ -78,7 +80,7 @@ export class Plug {
|
|
|
78
80
|
this.updateHomeKitCharacteristics();
|
|
79
81
|
|
|
80
82
|
// Start an update interval
|
|
81
|
-
interval(this.
|
|
83
|
+
interval(this.deviceRefreshRate * 1000)
|
|
82
84
|
.pipe(skipWhile(() => this.plugUpdateInProgress))
|
|
83
85
|
.subscribe(() => {
|
|
84
86
|
this.refreshStatus();
|
|
@@ -97,21 +99,54 @@ export class Plug {
|
|
|
97
99
|
try {
|
|
98
100
|
await this.pushChanges();
|
|
99
101
|
} catch (e: any) {
|
|
100
|
-
this.
|
|
101
|
-
if (this.
|
|
102
|
-
this.
|
|
102
|
+
this.errorLog(`Plug: ${this.accessory.displayName} failed pushChanges`);
|
|
103
|
+
if (this.deviceLogging === 'debug') {
|
|
104
|
+
this.errorLog(`Plug: ${this.accessory.displayName} failed pushChanges,`
|
|
103
105
|
+ ` Error Message: ${JSON.stringify(e.message)}`);
|
|
104
106
|
}
|
|
105
|
-
if (this.
|
|
106
|
-
this.
|
|
107
|
+
if (this.platform.debugMode) {
|
|
108
|
+
this.errorLog(`Plug: ${this.accessory.displayName} failed pushChanges,`
|
|
107
109
|
+ ` Error: ${JSON.stringify(e)}`);
|
|
108
110
|
}
|
|
109
|
-
this.apiError(
|
|
111
|
+
this.apiError();
|
|
110
112
|
}
|
|
111
113
|
this.plugUpdateInProgress = false;
|
|
112
114
|
});
|
|
113
115
|
}
|
|
114
116
|
|
|
117
|
+
refreshRate() {
|
|
118
|
+
if (this.device.refreshRate) {
|
|
119
|
+
this.deviceRefreshRate = this.accessory.context.refreshRate = this.device.refreshRate;
|
|
120
|
+
if (this.platform.debugMode) {
|
|
121
|
+
this.warnLog(`Using Device Config refreshRate: ${this.deviceRefreshRate}`);
|
|
122
|
+
}
|
|
123
|
+
} else if (this.platform.config.options!.refreshRate) {
|
|
124
|
+
this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
|
|
125
|
+
if (this.platform.debugMode) {
|
|
126
|
+
this.warnLog(`Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
logs() {
|
|
132
|
+
if (this.device.logging) {
|
|
133
|
+
this.deviceLogging = this.accessory.context.logging = this.device.logging;
|
|
134
|
+
if (this.platform.debugMode) {
|
|
135
|
+
this.warnLog(`Using Device Config Logging: ${this.deviceLogging}`);
|
|
136
|
+
}
|
|
137
|
+
} else if (this.platform.config.options?.logging) {
|
|
138
|
+
this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
|
|
139
|
+
if (this.platform.debugMode) {
|
|
140
|
+
this.warnLog(`Using Platform Config Logging: ${this.deviceLogging}`);
|
|
141
|
+
}
|
|
142
|
+
} else {
|
|
143
|
+
this.deviceLogging = this.accessory.context.logging = 'standard';
|
|
144
|
+
if (this.platform.debugMode) {
|
|
145
|
+
this.warnLog('Using Device Standard Logging');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
115
150
|
parseStatus() {
|
|
116
151
|
switch (this.deviceStatus.body.power) {
|
|
117
152
|
case 'on':
|
|
@@ -120,26 +155,26 @@ export class Plug {
|
|
|
120
155
|
default:
|
|
121
156
|
this.On = false;
|
|
122
157
|
}
|
|
123
|
-
this.
|
|
158
|
+
this.debugLog(`Plug ${this.accessory.displayName} On: ${this.On}`);
|
|
124
159
|
}
|
|
125
160
|
|
|
126
161
|
private async refreshStatus() {
|
|
127
162
|
try {
|
|
128
163
|
this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
|
|
129
|
-
this.
|
|
164
|
+
this.debugLog(`Plug: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
|
|
130
165
|
this.parseStatus();
|
|
131
166
|
this.updateHomeKitCharacteristics();
|
|
132
167
|
} catch (e: any) {
|
|
133
|
-
this.
|
|
134
|
-
if (this.
|
|
135
|
-
this.
|
|
168
|
+
this.errorLog(`Plug: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
|
|
169
|
+
if (this.deviceLogging === 'debug') {
|
|
170
|
+
this.errorLog(`Plug: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
|
|
136
171
|
+ ` Error Message: ${JSON.stringify(e.message)}`);
|
|
137
172
|
}
|
|
138
|
-
if (this.
|
|
139
|
-
this.
|
|
173
|
+
if (this.platform.debugMode) {
|
|
174
|
+
this.errorLog(`Plug: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
|
|
140
175
|
+ ` Error: ${JSON.stringify(e)}`);
|
|
141
176
|
}
|
|
142
|
-
this.apiError(
|
|
177
|
+
this.apiError();
|
|
143
178
|
}
|
|
144
179
|
}
|
|
145
180
|
|
|
@@ -162,12 +197,12 @@ export class Plug {
|
|
|
162
197
|
payload.command = 'turnOff';
|
|
163
198
|
}
|
|
164
199
|
|
|
165
|
-
this.
|
|
200
|
+
this.infoLog(`Plug: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
|
|
166
201
|
+ ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
|
|
167
202
|
|
|
168
203
|
// Make the API request
|
|
169
204
|
const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
|
|
170
|
-
this.
|
|
205
|
+
this.debugLog(`Plug: ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
|
|
171
206
|
this.statusCode(push);
|
|
172
207
|
this.OnCached = this.On;
|
|
173
208
|
this.accessory.context.On = this.OnCached;
|
|
@@ -182,45 +217,45 @@ export class Plug {
|
|
|
182
217
|
|
|
183
218
|
updateHomeKitCharacteristics() {
|
|
184
219
|
if (this.On === undefined) {
|
|
185
|
-
this.
|
|
220
|
+
this.debugLog(`Plug: ${this.accessory.displayName} On: ${this.On}`);
|
|
186
221
|
} else {
|
|
187
222
|
this.service.updateCharacteristic(this.platform.Characteristic.On, this.On);
|
|
188
|
-
this.
|
|
223
|
+
this.debugLog(`Plug: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
|
|
189
224
|
}
|
|
190
225
|
}
|
|
191
226
|
|
|
192
|
-
public apiError(
|
|
193
|
-
this.
|
|
227
|
+
public apiError() {
|
|
228
|
+
throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
|
|
194
229
|
}
|
|
195
230
|
|
|
196
231
|
private statusCode(push: AxiosResponse<{ statusCode: number; }>) {
|
|
197
232
|
switch (push.data.statusCode) {
|
|
198
233
|
case 151:
|
|
199
|
-
this.
|
|
234
|
+
this.errorLog(`Plug: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
200
235
|
break;
|
|
201
236
|
case 152:
|
|
202
|
-
this.
|
|
237
|
+
this.errorLog(`Plug: ${this.accessory.displayName} Device not found.`);
|
|
203
238
|
break;
|
|
204
239
|
case 160:
|
|
205
|
-
this.
|
|
240
|
+
this.errorLog(`Plug: ${this.accessory.displayName} Command is not supported.`);
|
|
206
241
|
break;
|
|
207
242
|
case 161:
|
|
208
|
-
this.
|
|
243
|
+
this.errorLog(`Plug: ${this.accessory.displayName} Device is offline.`);
|
|
209
244
|
this.offlineOff();
|
|
210
245
|
break;
|
|
211
246
|
case 171:
|
|
212
|
-
this.
|
|
247
|
+
this.errorLog(`Plug: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
|
|
213
248
|
this.offlineOff();
|
|
214
249
|
break;
|
|
215
250
|
case 190:
|
|
216
|
-
this.
|
|
251
|
+
this.errorLog(`Plug: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
|
|
217
252
|
+ ` Or command: ${JSON.stringify(push.data)} format is invalid`);
|
|
218
253
|
break;
|
|
219
254
|
case 100:
|
|
220
|
-
this.
|
|
255
|
+
this.debugLog(`Plug: ${this.accessory.displayName} Command successfully sent.`);
|
|
221
256
|
break;
|
|
222
257
|
default:
|
|
223
|
-
this.
|
|
258
|
+
this.debugLog(`Plug: ${this.accessory.displayName} Unknown statusCode.`);
|
|
224
259
|
}
|
|
225
260
|
}
|
|
226
261
|
|
|
@@ -235,11 +270,44 @@ export class Plug {
|
|
|
235
270
|
* Handle requests to set the value of the "On" characteristic
|
|
236
271
|
*/
|
|
237
272
|
OnSet(value: CharacteristicValue) {
|
|
238
|
-
this.
|
|
273
|
+
this.debugLog(`Plug: ${this.accessory.displayName} - Set On: ${value}`);
|
|
239
274
|
|
|
240
275
|
this.On = value;
|
|
241
276
|
this.doPlugUpdate.next();
|
|
242
277
|
}
|
|
243
278
|
|
|
279
|
+
/**
|
|
280
|
+
* Logging for Device
|
|
281
|
+
*/
|
|
282
|
+
infoLog(...log: any[]) {
|
|
283
|
+
if (this.enablingDeviceLogging()) {
|
|
284
|
+
this.platform.log.info(String(...log));
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
warnLog(...log: any[]) {
|
|
289
|
+
if (this.enablingDeviceLogging()) {
|
|
290
|
+
this.platform.log.warn(String(...log));
|
|
291
|
+
}
|
|
292
|
+
}
|
|
244
293
|
|
|
294
|
+
errorLog(...log: any[]) {
|
|
295
|
+
if (this.enablingDeviceLogging()) {
|
|
296
|
+
this.platform.log.error(String(...log));
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
debugLog(...log: any[]) {
|
|
301
|
+
if (this.enablingDeviceLogging()) {
|
|
302
|
+
if (this.deviceLogging === 'debug') {
|
|
303
|
+
this.platform.log.info('[DEBUG]', String(...log));
|
|
304
|
+
} else {
|
|
305
|
+
this.platform.log.debug(String(...log));
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
enablingDeviceLogging(): boolean {
|
|
311
|
+
return this.deviceLogging === 'debug' || this.deviceLogging === 'standard';
|
|
312
|
+
}
|
|
245
313
|
}
|