@switchbot/homebridge-switchbot 2.6.0-beta.3 → 2.6.0-beta.5
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/.github/workflows/dependabot.yml +2 -0
- package/.vscode/tasks.json +13 -0
- package/dist/device/blindtilt.d.ts +1 -5
- package/dist/device/blindtilt.d.ts.map +1 -1
- package/dist/device/blindtilt.js +80 -140
- package/dist/device/blindtilt.js.map +1 -1
- package/dist/device/bot.d.ts +1 -5
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +79 -138
- package/dist/device/bot.js.map +1 -1
- package/dist/device/ceilinglight.d.ts +2 -6
- package/dist/device/ceilinglight.d.ts.map +1 -1
- package/dist/device/ceilinglight.js +157 -304
- package/dist/device/ceilinglight.js.map +1 -1
- package/dist/device/colorbulb.d.ts +2 -6
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +164 -311
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts +1 -5
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +36 -72
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts +1 -5
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +78 -138
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/hub.d.ts +2 -6
- package/dist/device/hub.d.ts.map +1 -1
- package/dist/device/hub.js +30 -63
- package/dist/device/hub.js.map +1 -1
- package/dist/device/humidifier.d.ts +1 -5
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +115 -228
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/iosensor.d.ts +1 -5
- package/dist/device/iosensor.d.ts.map +1 -1
- package/dist/device/iosensor.js +38 -74
- package/dist/device/iosensor.js.map +1 -1
- package/dist/device/lock.d.ts +1 -5
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +66 -126
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +1 -5
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +38 -74
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +1 -5
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +39 -75
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts +1 -5
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +35 -72
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +1 -5
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +65 -126
- package/dist/device/plug.js.map +1 -1
- package/dist/device/robotvacuumcleaner.d.ts +1 -5
- package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
- package/dist/device/robotvacuumcleaner.js +79 -151
- package/dist/device/robotvacuumcleaner.js.map +1 -1
- package/dist/device/striplight.d.ts +1 -9
- package/dist/device/striplight.d.ts.map +1 -1
- package/dist/device/striplight.js +137 -193
- package/dist/device/striplight.js.map +1 -1
- package/dist/irdevice/airconditioner.d.ts +3 -7
- package/dist/irdevice/airconditioner.d.ts.map +1 -1
- package/dist/irdevice/airconditioner.js +34 -62
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts +3 -7
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +31 -59
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts +1 -5
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +30 -57
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts +2 -6
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +39 -66
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/light.d.ts +1 -5
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +32 -59
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts +1 -5
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +30 -57
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts +3 -7
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +46 -76
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts +2 -6
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +30 -58
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts +7 -23
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +41 -74
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +14 -5
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +153 -146
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +4 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +5 -1
- package/dist/settings.js.map +1 -1
- package/nodemon.json +1 -1
- package/package.json +10 -10
- package/src/device/blindtilt.ts +122 -181
- package/src/device/bot.ts +96 -149
- package/src/device/ceilinglight.ts +172 -315
- package/src/device/colorbulb.ts +178 -324
- package/src/device/contact.ts +48 -78
- package/src/device/curtain.ts +93 -148
- package/src/device/hub.ts +34 -63
- package/src/device/humidifier.ts +135 -243
- package/src/device/iosensor.ts +49 -79
- package/src/device/lock.ts +78 -134
- package/src/device/meter.ts +48 -78
- package/src/device/meterplus.ts +50 -80
- package/src/device/motion.ts +46 -77
- package/src/device/plug.ts +76 -134
- package/src/device/robotvacuumcleaner.ts +91 -159
- package/src/device/striplight.ts +148 -200
- package/src/irdevice/airconditioner.ts +56 -81
- package/src/irdevice/airpurifier.ts +41 -67
- package/src/irdevice/camera.ts +35 -60
- package/src/irdevice/fan.ts +46 -71
- package/src/irdevice/light.ts +38 -63
- package/src/irdevice/other.ts +35 -60
- package/src/irdevice/tv.ts +52 -80
- package/src/irdevice/vacuumcleaner.ts +36 -62
- package/src/irdevice/waterheater.ts +46 -76
- package/src/platform.ts +143 -157
- package/src/settings.ts +5 -0
package/src/device/iosensor.ts
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
import https from 'https';
|
|
2
|
-
import crypto from 'crypto';
|
|
3
1
|
import { Context } from 'vm';
|
|
4
2
|
import { hostname } from 'os';
|
|
3
|
+
import { request } from 'undici';
|
|
4
|
+
import { sleep } from '../utils';
|
|
5
5
|
import { MqttClient } from 'mqtt';
|
|
6
6
|
import { connectAsync } from 'async-mqtt';
|
|
7
7
|
import { interval, Subject } from 'rxjs';
|
|
8
8
|
import { skipWhile } from 'rxjs/operators';
|
|
9
|
-
import superStringify from 'super-stringify';
|
|
10
9
|
import { SwitchBotPlatform } from '../platform';
|
|
11
10
|
import { Service, PlatformAccessory, Units, CharacteristicValue } from 'homebridge';
|
|
12
|
-
import { device, devicesConfig, serviceData, ad, switchbot, temperature, deviceStatus,
|
|
13
|
-
import { IncomingMessage } from 'http';
|
|
14
|
-
import { sleep } from '../utils';
|
|
11
|
+
import { device, devicesConfig, serviceData, ad, switchbot, temperature, deviceStatus, Devices } from '../settings';
|
|
15
12
|
|
|
16
13
|
/**
|
|
17
14
|
* Platform Accessory
|
|
@@ -186,7 +183,7 @@ export class IOSensor {
|
|
|
186
183
|
} else {
|
|
187
184
|
await this.offlineOff();
|
|
188
185
|
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
189
|
-
|
|
186
|
+
+ ` ${this.device.connectionType}, parseStatus will not happen.`);
|
|
190
187
|
}
|
|
191
188
|
}
|
|
192
189
|
|
|
@@ -254,7 +251,7 @@ export class IOSensor {
|
|
|
254
251
|
} else {
|
|
255
252
|
await this.offlineOff();
|
|
256
253
|
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
257
|
-
|
|
254
|
+
+ ` ${this.device.connectionType}, refreshStatus will not happen.`);
|
|
258
255
|
}
|
|
259
256
|
}
|
|
260
257
|
|
|
@@ -280,7 +277,7 @@ export class IOSensor {
|
|
|
280
277
|
switchbot.onadvertisement = async (ad: ad) => {
|
|
281
278
|
this.address = ad.address;
|
|
282
279
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac},`
|
|
283
|
-
|
|
280
|
+
+ ` BLE Address Found: ${this.address}`);
|
|
284
281
|
if (ad.serviceData.humidity! > 0) {
|
|
285
282
|
// reject unreliable data
|
|
286
283
|
this.humidity = ad.serviceData.humidity;
|
|
@@ -290,11 +287,11 @@ export class IOSensor {
|
|
|
290
287
|
this.celsius = ad.serviceData.temperature!.c;
|
|
291
288
|
this.fahrenheit = ad.serviceData.temperature!.f;
|
|
292
289
|
this.battery = ad.serviceData.battery;
|
|
293
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${
|
|
290
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
|
|
294
291
|
this.debugLog(
|
|
295
292
|
`${this.device.deviceType}: ${this.accessory.displayName} model: ${ad.serviceData.model}, modelName: ${ad.serviceData.modelName}, ` +
|
|
296
|
-
|
|
297
|
-
|
|
293
|
+
`temperature: ${JSON.stringify(ad.serviceData.temperature?.c)}, humidity: ${ad.serviceData.humidity}, ` +
|
|
294
|
+
`battery: ${ad.serviceData.battery}`,
|
|
298
295
|
);
|
|
299
296
|
|
|
300
297
|
if (this.serviceData) {
|
|
@@ -316,7 +313,7 @@ export class IOSensor {
|
|
|
316
313
|
.catch(async (e: any) => {
|
|
317
314
|
this.apiError(e);
|
|
318
315
|
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}`
|
|
319
|
-
|
|
316
|
+
+ ` Connection, Error Message: ${JSON.stringify(e.message)}`);
|
|
320
317
|
await this.BLERefreshConnection(switchbot);
|
|
321
318
|
});
|
|
322
319
|
} else {
|
|
@@ -327,54 +324,26 @@ export class IOSensor {
|
|
|
327
324
|
async openAPIRefreshStatus(): Promise<void> {
|
|
328
325
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
|
|
329
326
|
try {
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
const data = this.platform.config.credentials?.token + t + nonce;
|
|
333
|
-
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
334
|
-
const sign = signTerm.toString('base64');
|
|
335
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
336
|
-
const options = {
|
|
337
|
-
hostname: HostDomain,
|
|
338
|
-
port: 443,
|
|
339
|
-
path: `${DevicePath}/${this.device.deviceId}/status`,
|
|
340
|
-
method: 'GET',
|
|
341
|
-
headers: {
|
|
342
|
-
Authorization: this.platform.config.credentials?.token,
|
|
343
|
-
sign: sign,
|
|
344
|
-
nonce: nonce,
|
|
345
|
-
t: t,
|
|
346
|
-
'Content-Type': 'application/json',
|
|
347
|
-
},
|
|
348
|
-
};
|
|
349
|
-
const req = https.request(options, (res) => {
|
|
350
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus statusCode: ${res.statusCode}`);
|
|
351
|
-
let rawData = '';
|
|
352
|
-
res.on('data', (d) => {
|
|
353
|
-
rawData += d;
|
|
354
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
|
|
355
|
-
});
|
|
356
|
-
res.on('end', () => {
|
|
357
|
-
try {
|
|
358
|
-
this.deviceStatus = JSON.parse(rawData);
|
|
359
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus: ${superStringify(this.deviceStatus)}`);
|
|
360
|
-
this.Humidity = this.deviceStatus.body.humidity!;
|
|
361
|
-
this.Temperature = this.deviceStatus.body.temperature!;
|
|
362
|
-
this.Battery = this.deviceStatus.body.battery!;
|
|
363
|
-
this.parseStatus();
|
|
364
|
-
this.updateHomeKitCharacteristics();
|
|
365
|
-
} catch (e: any) {
|
|
366
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
367
|
-
}
|
|
368
|
-
});
|
|
369
|
-
});
|
|
370
|
-
req.on('error', (e: any) => {
|
|
371
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
327
|
+
const { body, statusCode, headers } = await request(`${Devices}/${this.device.deviceId}/status`, {
|
|
328
|
+
headers: this.platform.generateHeaders(),
|
|
372
329
|
});
|
|
373
|
-
|
|
330
|
+
const deviceStatus = await body.json();
|
|
331
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Devices: ${JSON.stringify(deviceStatus.body)}`);
|
|
332
|
+
this.statusCode(statusCode);
|
|
333
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Headers: ${JSON.stringify(headers)}`);
|
|
334
|
+
this.debugLog(
|
|
335
|
+
`${this.device.deviceType}: ${this.accessory.displayName
|
|
336
|
+
} refreshStatus: ${JSON.stringify(deviceStatus)}`,
|
|
337
|
+
);
|
|
338
|
+
this.Humidity = deviceStatus.body.humidity!;
|
|
339
|
+
this.Temperature = deviceStatus.body.temperature!;
|
|
340
|
+
this.Battery = deviceStatus.body.battery!;
|
|
341
|
+
this.openAPIparseStatus();
|
|
342
|
+
this.updateHomeKitCharacteristics();
|
|
374
343
|
} catch (e: any) {
|
|
375
344
|
this.apiError(e);
|
|
376
345
|
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
|
|
377
|
-
|
|
346
|
+
+ ` Connection, Error Message: ${JSON.stringify(e.message)}`);
|
|
378
347
|
}
|
|
379
348
|
}
|
|
380
349
|
|
|
@@ -391,7 +360,7 @@ export class IOSensor {
|
|
|
391
360
|
this.accessory.context.CurrentRelativeHumidity = this.CurrentRelativeHumidity;
|
|
392
361
|
this.humidityservice?.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, this.CurrentRelativeHumidity);
|
|
393
362
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
|
|
394
|
-
|
|
363
|
+
+ ` updateCharacteristic CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
|
|
395
364
|
if (this.device.mqttURL) {
|
|
396
365
|
mqttmessage.push(`"humidity": ${this.CurrentRelativeHumidity}`);
|
|
397
366
|
}
|
|
@@ -407,7 +376,7 @@ export class IOSensor {
|
|
|
407
376
|
if (this.device.mqttURL) {
|
|
408
377
|
mqttmessage.push(`"temperature": ${this.CurrentTemperature}`);
|
|
409
378
|
}
|
|
410
|
-
if (this.device.history){
|
|
379
|
+
if (this.device.history) {
|
|
411
380
|
entry['temp'] = this.CurrentTemperature;
|
|
412
381
|
}
|
|
413
382
|
this.accessory.context.CurrentTemperature = this.CurrentTemperature;
|
|
@@ -457,7 +426,7 @@ export class IOSensor {
|
|
|
457
426
|
?.join(':');
|
|
458
427
|
const options = this.device.mqttPubOptions || {};
|
|
459
428
|
this.mqttClient?.publish(`homebridge-switchbot/meter/${mac}`, `${message}`, options);
|
|
460
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT message: ${message} options:${
|
|
429
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT message: ${message} options:${JSON.stringify(options)}`);
|
|
461
430
|
}
|
|
462
431
|
|
|
463
432
|
/*
|
|
@@ -514,7 +483,7 @@ export class IOSensor {
|
|
|
514
483
|
});
|
|
515
484
|
// Set an event handler
|
|
516
485
|
switchbot.onadvertisement = (ad: any) => {
|
|
517
|
-
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${
|
|
486
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${JSON.stringify(ad, null, ' ')}`);
|
|
518
487
|
};
|
|
519
488
|
await sleep(10000);
|
|
520
489
|
// Stop to monitor
|
|
@@ -545,40 +514,41 @@ export class IOSensor {
|
|
|
545
514
|
}
|
|
546
515
|
}
|
|
547
516
|
|
|
548
|
-
async statusCode(
|
|
549
|
-
switch (
|
|
517
|
+
async statusCode(statusCode: number): Promise<void> {
|
|
518
|
+
switch (statusCode) {
|
|
550
519
|
case 151:
|
|
551
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this
|
|
520
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this deviceType, statusCode: ${statusCode}`);
|
|
552
521
|
break;
|
|
553
522
|
case 152:
|
|
554
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found
|
|
523
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found, statusCode: ${statusCode}`);
|
|
555
524
|
break;
|
|
556
525
|
case 160:
|
|
557
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported
|
|
526
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported, statusCode: ${statusCode}`);
|
|
558
527
|
break;
|
|
559
528
|
case 161:
|
|
560
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline
|
|
561
|
-
|
|
529
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline, statusCode: ${statusCode}`);
|
|
530
|
+
this.offlineOff();
|
|
562
531
|
break;
|
|
563
532
|
case 171:
|
|
564
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} is offline
|
|
565
|
-
|
|
533
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Hub Device is offline, statusCode: ${statusCode}. `
|
|
534
|
+
+ `Hub: ${this.device.hubDeviceId}`);
|
|
535
|
+
this.offlineOff();
|
|
566
536
|
break;
|
|
567
537
|
case 190:
|
|
568
538
|
this.errorLog(
|
|
569
539
|
`${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
570
|
-
|
|
540
|
+
` Or command format is invalid, statusCode: ${statusCode}`,
|
|
571
541
|
);
|
|
572
542
|
break;
|
|
573
543
|
case 100:
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
544
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent, statusCode: ${statusCode}`);
|
|
545
|
+
break;
|
|
546
|
+
case 200:
|
|
547
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Request successful, statusCode: ${statusCode}`);
|
|
577
548
|
break;
|
|
578
549
|
default:
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
}
|
|
550
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode: `
|
|
551
|
+
+ `${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`);
|
|
582
552
|
}
|
|
583
553
|
}
|
|
584
554
|
|
|
@@ -603,7 +573,7 @@ export class IOSensor {
|
|
|
603
573
|
FirmwareRevision(accessory: PlatformAccessory<Context>, device: device & devicesConfig): CharacteristicValue {
|
|
604
574
|
let FirmwareRevision: string;
|
|
605
575
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
|
|
606
|
-
|
|
576
|
+
+ ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
|
|
607
577
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
|
|
608
578
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
|
|
609
579
|
if (accessory.context.FirmwareRevision) {
|
|
@@ -674,7 +644,7 @@ export class IOSensor {
|
|
|
674
644
|
config['scanDuration'] = device.scanDuration;
|
|
675
645
|
}
|
|
676
646
|
if (Object.entries(config).length !== 0) {
|
|
677
|
-
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${
|
|
647
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
|
|
678
648
|
}
|
|
679
649
|
}
|
|
680
650
|
|
package/src/device/lock.ts
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
import https from 'https';
|
|
2
|
-
import crypto from 'crypto';
|
|
3
1
|
import { Context } from 'vm';
|
|
4
|
-
import {
|
|
2
|
+
import { request } from 'undici';
|
|
3
|
+
import { sleep } from '../utils';
|
|
5
4
|
import { interval, Subject } from 'rxjs';
|
|
6
|
-
import superStringify from 'super-stringify';
|
|
7
5
|
import { SwitchBotPlatform } from '../platform';
|
|
8
6
|
import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
|
|
9
7
|
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
|
10
|
-
import { device, devicesConfig, deviceStatus,
|
|
11
|
-
import { sleep } from '../utils';
|
|
8
|
+
import { device, devicesConfig, deviceStatus, switchbot, ad, serviceData, Devices } from '../settings';
|
|
12
9
|
|
|
13
10
|
export class Lock {
|
|
14
11
|
// Services
|
|
@@ -144,7 +141,7 @@ export class Lock {
|
|
|
144
141
|
} catch (e: any) {
|
|
145
142
|
this.apiError(e);
|
|
146
143
|
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with ${this.device.connectionType} Connection,`
|
|
147
|
-
|
|
144
|
+
+ ` Error Message: ${JSON.stringify(e.message)}`);
|
|
148
145
|
}
|
|
149
146
|
this.lockUpdateInProgress = false;
|
|
150
147
|
});
|
|
@@ -163,7 +160,7 @@ export class Lock {
|
|
|
163
160
|
} else {
|
|
164
161
|
await this.offlineOff();
|
|
165
162
|
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
166
|
-
|
|
163
|
+
+ ` ${this.device.connectionType}, parseStatus will not happen.`);
|
|
167
164
|
}
|
|
168
165
|
}
|
|
169
166
|
|
|
@@ -222,7 +219,7 @@ export class Lock {
|
|
|
222
219
|
} else {
|
|
223
220
|
await this.offlineOff();
|
|
224
221
|
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
225
|
-
|
|
222
|
+
+ ` ${this.device.connectionType}, refreshStatus will not happen.`);
|
|
226
223
|
}
|
|
227
224
|
}
|
|
228
225
|
|
|
@@ -248,7 +245,7 @@ export class Lock {
|
|
|
248
245
|
switchbot.onadvertisement = async (ad: any) => {
|
|
249
246
|
this.address = ad.address;
|
|
250
247
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac},`
|
|
251
|
-
|
|
248
|
+
+ ` BLE Address Found: ${this.address}`);
|
|
252
249
|
this.serviceData = ad.serviceData;
|
|
253
250
|
this.battery = ad.serviceData.battery;
|
|
254
251
|
this.calibration = ad.serviceData.calibration;
|
|
@@ -259,11 +256,11 @@ export class Lock {
|
|
|
259
256
|
this.unclosed_alarm = ad.serviceData.unclosed_alarm;
|
|
260
257
|
this.unlocked_alarm = ad.serviceData.unlocked_alarm;
|
|
261
258
|
this.auto_lock_paused = ad.serviceData.auto_lock_paused;
|
|
262
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${
|
|
259
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
|
|
263
260
|
this.debugLog(
|
|
264
261
|
`${this.device.deviceType}: ${this.accessory.displayName} battery: ${ad.serviceData.battery}, ` +
|
|
265
|
-
|
|
266
|
-
|
|
262
|
+
`calibration: ${ad.serviceData.calibration}, status: ${ad.serviceData.status}, battery: ${ad.serviceData.battery}, ` +
|
|
263
|
+
`door_open: ${ad.serviceData.door_open}`);
|
|
267
264
|
|
|
268
265
|
if (this.serviceData) {
|
|
269
266
|
this.connected = true;
|
|
@@ -284,7 +281,7 @@ export class Lock {
|
|
|
284
281
|
.catch(async (e: any) => {
|
|
285
282
|
this.apiError(e);
|
|
286
283
|
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}`
|
|
287
|
-
|
|
284
|
+
+ ` Connection, Error Message: ${JSON.stringify(e.message)}`);
|
|
288
285
|
await this.BLERefreshConnection(switchbot);
|
|
289
286
|
});
|
|
290
287
|
} else {
|
|
@@ -295,53 +292,25 @@ export class Lock {
|
|
|
295
292
|
async openAPIRefreshStatus(): Promise<void> {
|
|
296
293
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
|
|
297
294
|
try {
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
const data = this.platform.config.credentials?.token + t + nonce;
|
|
301
|
-
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
302
|
-
const sign = signTerm.toString('base64');
|
|
303
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
304
|
-
const options = {
|
|
305
|
-
hostname: HostDomain,
|
|
306
|
-
port: 443,
|
|
307
|
-
path: `${DevicePath}/${this.device.deviceId}/status`,
|
|
308
|
-
method: 'GET',
|
|
309
|
-
headers: {
|
|
310
|
-
Authorization: this.platform.config.credentials?.token,
|
|
311
|
-
sign: sign,
|
|
312
|
-
nonce: nonce,
|
|
313
|
-
t: t,
|
|
314
|
-
'Content-Type': 'application/json',
|
|
315
|
-
},
|
|
316
|
-
};
|
|
317
|
-
const req = https.request(options, (res) => {
|
|
318
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus statusCode: ${res.statusCode}`);
|
|
319
|
-
let rawData = '';
|
|
320
|
-
res.on('data', (d) => {
|
|
321
|
-
rawData += d;
|
|
322
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
|
|
323
|
-
});
|
|
324
|
-
res.on('end', () => {
|
|
325
|
-
try {
|
|
326
|
-
this.deviceStatus = JSON.parse(rawData);
|
|
327
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus: ${superStringify(this.deviceStatus)}`);
|
|
328
|
-
this.lockState = this.deviceStatus.body.lockState;
|
|
329
|
-
this.doorState = this.deviceStatus.body.doorState;
|
|
330
|
-
this.openAPIparseStatus();
|
|
331
|
-
this.updateHomeKitCharacteristics();
|
|
332
|
-
} catch (e: any) {
|
|
333
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
334
|
-
}
|
|
335
|
-
});
|
|
336
|
-
});
|
|
337
|
-
req.on('error', (e: any) => {
|
|
338
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
295
|
+
const { body, statusCode, headers } = await request(`${Devices}/${this.device.deviceId}/status`, {
|
|
296
|
+
headers: this.platform.generateHeaders(),
|
|
339
297
|
});
|
|
340
|
-
|
|
298
|
+
const deviceStatus = await body.json();
|
|
299
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Devices: ${JSON.stringify(deviceStatus.body)}`);
|
|
300
|
+
this.statusCode(statusCode);
|
|
301
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Headers: ${JSON.stringify(headers)}`);
|
|
302
|
+
this.debugLog(
|
|
303
|
+
`${this.device.deviceType}: ${this.accessory.displayName
|
|
304
|
+
} refreshStatus: ${JSON.stringify(deviceStatus)}`,
|
|
305
|
+
);
|
|
306
|
+
this.lockState = deviceStatus.body.lockState;
|
|
307
|
+
this.doorState = deviceStatus.body.doorState;
|
|
308
|
+
this.openAPIparseStatus();
|
|
309
|
+
this.updateHomeKitCharacteristics();
|
|
341
310
|
} catch (e: any) {
|
|
342
311
|
this.apiError(e);
|
|
343
312
|
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
|
|
344
|
-
|
|
313
|
+
+ ` Connection, Error Message: ${JSON.stringify(e.message)}`);
|
|
345
314
|
}
|
|
346
315
|
}
|
|
347
316
|
|
|
@@ -361,7 +330,7 @@ export class Lock {
|
|
|
361
330
|
} else {
|
|
362
331
|
await this.offlineOff();
|
|
363
332
|
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
364
|
-
|
|
333
|
+
+ ` ${this.device.connectionType}, pushChanges will not happen.`);
|
|
365
334
|
}
|
|
366
335
|
// Refresh the status from the API
|
|
367
336
|
interval(15000)
|
|
@@ -376,7 +345,7 @@ export class Lock {
|
|
|
376
345
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
|
|
377
346
|
if (this.LockTargetState !== this.accessory.context.LockTargetState) {
|
|
378
347
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges LockTargetState: ${this.LockTargetState}`
|
|
379
|
-
|
|
348
|
+
+ ` LockTargetStateCached: ${this.accessory.context.LockTargetState}`);
|
|
380
349
|
const switchbot = await this.platform.connectBLE();
|
|
381
350
|
// Convert to BLE Address
|
|
382
351
|
this.device.bleMac = this.device
|
|
@@ -396,80 +365,50 @@ export class Lock {
|
|
|
396
365
|
.catch(async (e: any) => {
|
|
397
366
|
this.apiError(e);
|
|
398
367
|
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
|
|
399
|
-
|
|
368
|
+
+ ` Connection, Error Message: ${JSON.stringify(e.message)}`);
|
|
400
369
|
await this.BLEPushConnection();
|
|
401
370
|
});
|
|
402
371
|
} else {
|
|
403
372
|
this.debugLog(
|
|
404
373
|
`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges.` + `LockTargetState: ${this.LockTargetState}, `
|
|
405
|
-
|
|
374
|
+
+ `LockTargetStateCached: ${this.accessory.context.LockTargetState}`,
|
|
406
375
|
);
|
|
407
376
|
}
|
|
408
377
|
}
|
|
409
378
|
|
|
410
379
|
async openAPIpushChanges(): Promise<void> {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
}
|
|
427
|
-
command = 'unlock';
|
|
428
|
-
}
|
|
429
|
-
const body = superStringify({
|
|
430
|
-
'command': `${command}`,
|
|
431
|
-
'parameter': 'default',
|
|
432
|
-
'commandType': 'command',
|
|
433
|
-
});
|
|
434
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${body},`);
|
|
435
|
-
const options = {
|
|
436
|
-
hostname: HostDomain,
|
|
437
|
-
port: 443,
|
|
438
|
-
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
380
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
|
|
381
|
+
if (this.LockTargetState !== this.accessory.context.LockTargetState) {
|
|
382
|
+
let command = '';
|
|
383
|
+
if (this.LockTargetState) {
|
|
384
|
+
command = 'lock';
|
|
385
|
+
} else {
|
|
386
|
+
command = 'unlock';
|
|
387
|
+
}
|
|
388
|
+
const body = JSON.stringify({
|
|
389
|
+
'command': `${command}`,
|
|
390
|
+
'parameter': 'default',
|
|
391
|
+
'commandType': 'command',
|
|
392
|
+
});
|
|
393
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${body},`);
|
|
394
|
+
try {
|
|
395
|
+
const { body, statusCode, headers } = await request(`${Devices}/${this.device.deviceId}/commands`, {
|
|
439
396
|
method: 'POST',
|
|
440
|
-
headers:
|
|
441
|
-
'Authorization': this.platform.config.credentials?.token,
|
|
442
|
-
'sign': sign,
|
|
443
|
-
'nonce': nonce,
|
|
444
|
-
't': t,
|
|
445
|
-
'Content-Type': 'application/json',
|
|
446
|
-
'Content-Length': body.length,
|
|
447
|
-
},
|
|
448
|
-
};
|
|
449
|
-
const req = https.request(options, res => {
|
|
450
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges statusCode: ${res.statusCode}`);
|
|
451
|
-
this.statusCode({ res });
|
|
452
|
-
res.on('data', d => {
|
|
453
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} d: ${d}`);
|
|
454
|
-
});
|
|
455
|
-
});
|
|
456
|
-
req.on('error', (e: any) => {
|
|
457
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
397
|
+
headers: this.platform.generateHeaders(),
|
|
458
398
|
});
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
this.
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
399
|
+
const deviceStatus = await body.json();
|
|
400
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Devices: ${JSON.stringify(deviceStatus.body)}`);
|
|
401
|
+
this.statusCode(statusCode);
|
|
402
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Headers: ${JSON.stringify(headers)}`);
|
|
403
|
+
} catch (e: any) {
|
|
404
|
+
this.apiError(e);
|
|
405
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
|
|
406
|
+
+ ` Connection, Error Message: ${JSON.stringify(e.message)}`,
|
|
466
407
|
);
|
|
467
408
|
}
|
|
468
|
-
}
|
|
469
|
-
this.
|
|
470
|
-
|
|
471
|
-
+ ` Connection, Error Message: ${superStringify(e.message)}`,
|
|
472
|
-
);
|
|
409
|
+
} else {
|
|
410
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges.` + `LockTargetState: ${this.LockTargetState}, `
|
|
411
|
+
+ `LockTargetStateCached: ${this.accessory.context.LockTargetState}`);
|
|
473
412
|
}
|
|
474
413
|
}
|
|
475
414
|
|
|
@@ -532,7 +471,7 @@ export class Lock {
|
|
|
532
471
|
});
|
|
533
472
|
// Set an event handler
|
|
534
473
|
switchbot.onadvertisement = (ad: any) => {
|
|
535
|
-
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${
|
|
474
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${JSON.stringify(ad, null, ' ')}`);
|
|
536
475
|
};
|
|
537
476
|
await sleep(10000);
|
|
538
477
|
// Stop to monitor
|
|
@@ -570,36 +509,41 @@ export class Lock {
|
|
|
570
509
|
}
|
|
571
510
|
}
|
|
572
511
|
|
|
573
|
-
async statusCode(
|
|
574
|
-
switch (
|
|
512
|
+
async statusCode(statusCode: number): Promise<void> {
|
|
513
|
+
switch (statusCode) {
|
|
575
514
|
case 151:
|
|
576
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this
|
|
515
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this deviceType, statusCode: ${statusCode}`);
|
|
577
516
|
break;
|
|
578
517
|
case 152:
|
|
579
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found
|
|
518
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found, statusCode: ${statusCode}`);
|
|
580
519
|
break;
|
|
581
520
|
case 160:
|
|
582
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported
|
|
521
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported, statusCode: ${statusCode}`);
|
|
583
522
|
break;
|
|
584
523
|
case 161:
|
|
585
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline
|
|
586
|
-
|
|
524
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline, statusCode: ${statusCode}`);
|
|
525
|
+
this.offlineOff();
|
|
587
526
|
break;
|
|
588
527
|
case 171:
|
|
589
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Hub Device is offline
|
|
590
|
-
|
|
528
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Hub Device is offline, statusCode: ${statusCode}. `
|
|
529
|
+
+ `Hub: ${this.device.hubDeviceId}`);
|
|
530
|
+
this.offlineOff();
|
|
591
531
|
break;
|
|
592
532
|
case 190:
|
|
593
533
|
this.errorLog(
|
|
594
534
|
`${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
595
|
-
|
|
535
|
+
` Or command format is invalid, statusCode: ${statusCode}`,
|
|
596
536
|
);
|
|
597
537
|
break;
|
|
598
538
|
case 100:
|
|
599
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent
|
|
539
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent, statusCode: ${statusCode}`);
|
|
540
|
+
break;
|
|
541
|
+
case 200:
|
|
542
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Request successful, statusCode: ${statusCode}`);
|
|
600
543
|
break;
|
|
601
544
|
default:
|
|
602
|
-
this.
|
|
545
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode: `
|
|
546
|
+
+ `${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`);
|
|
603
547
|
}
|
|
604
548
|
}
|
|
605
549
|
|
|
@@ -621,7 +565,7 @@ export class Lock {
|
|
|
621
565
|
FirmwareRevision(accessory: PlatformAccessory<Context>, device: device & devicesConfig): CharacteristicValue {
|
|
622
566
|
let FirmwareRevision: string;
|
|
623
567
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
|
|
624
|
-
|
|
568
|
+
+ ` accessory.context.FirmwareRevision: ${accessory.context.FirmwareRevision}`);
|
|
625
569
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} device.firmware: ${device.firmware}`);
|
|
626
570
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} this.platform.version: ${this.platform.version}`);
|
|
627
571
|
if (accessory.context.FirmwareRevision) {
|
|
@@ -673,7 +617,7 @@ export class Lock {
|
|
|
673
617
|
config['scanDuration'] = device.scanDuration;
|
|
674
618
|
}
|
|
675
619
|
if (Object.entries(config).length !== 0) {
|
|
676
|
-
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${
|
|
620
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
|
|
677
621
|
}
|
|
678
622
|
}
|
|
679
623
|
|