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