@switchbot/homebridge-switchbot 1.15.1-beta.7 → 1.15.1-beta.9
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/.prettierrc +1 -1
- package/dist/device/bot.d.ts +8 -7
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +97 -21
- package/dist/device/bot.js.map +1 -1
- package/dist/device/colorbulb.d.ts +8 -7
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +221 -56
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts +3 -3
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +50 -7
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts +9 -8
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +95 -21
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/humidifier.d.ts +8 -7
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +180 -59
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/lock.d.ts +8 -7
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +98 -22
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +4 -4
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +51 -8
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +3 -3
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +49 -6
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts +3 -3
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +49 -9
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +8 -7
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +96 -20
- package/dist/device/plug.js.map +1 -1
- package/dist/device/striplight.d.ts +8 -7
- package/dist/device/striplight.d.ts.map +1 -1
- package/dist/device/striplight.js +186 -47
- package/dist/device/striplight.js.map +1 -1
- package/dist/irdevice/airconditioner.d.ts +7 -6
- package/dist/irdevice/airconditioner.d.ts.map +1 -1
- package/dist/irdevice/airconditioner.js +40 -6
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts +7 -6
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +46 -11
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts +7 -6
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +40 -6
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts +8 -7
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +40 -6
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/light.d.ts +7 -6
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +40 -6
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts +7 -6
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +40 -6
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts +8 -7
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +40 -6
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts +7 -6
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +40 -6
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts +7 -6
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +40 -6
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +3 -5
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +141 -95
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +2 -21
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +3 -3
- package/dist/settings.js.map +1 -1
- package/package.json +6 -7
- package/src/device/bot.ts +97 -30
- package/src/device/colorbulb.ts +225 -93
- package/src/device/contact.ts +49 -10
- package/src/device/curtain.ts +98 -31
- package/src/device/humidifier.ts +182 -77
- package/src/device/lock.ts +97 -30
- package/src/device/meter.ts +51 -12
- package/src/device/meterplus.ts +48 -9
- package/src/device/motion.ts +48 -12
- package/src/device/plug.ts +97 -29
- package/src/device/striplight.ts +189 -68
- package/src/irdevice/airconditioner.ts +44 -9
- package/src/irdevice/airpurifier.ts +52 -17
- package/src/irdevice/camera.ts +46 -11
- package/src/irdevice/fan.ts +50 -15
- package/src/irdevice/light.ts +48 -13
- package/src/irdevice/other.ts +46 -11
- package/src/irdevice/tv.ts +56 -21
- package/src/irdevice/vacuumcleaner.ts +46 -11
- package/src/irdevice/waterheater.ts +46 -11
- package/src/platform.ts +154 -108
- package/src/settings.ts +2 -25
package/src/device/lock.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import https from 'https';
|
|
2
|
+
import crypto from 'crypto';
|
|
3
|
+
import { Context } from 'vm';
|
|
4
|
+
import { IncomingMessage } from 'http';
|
|
2
5
|
import { interval, Subject } from 'rxjs';
|
|
3
6
|
import { SwitchBotPlatform } from '../platform';
|
|
4
7
|
import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
|
|
5
8
|
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
|
6
|
-
import {
|
|
7
|
-
import { Context } from 'vm';
|
|
9
|
+
import { device, devicesConfig, deviceStatus, HostDomain, DevicePath } from '../settings';
|
|
8
10
|
|
|
9
11
|
export class Lock {
|
|
10
12
|
// Services
|
|
@@ -19,7 +21,7 @@ export class Lock {
|
|
|
19
21
|
// OpenAPI Others
|
|
20
22
|
doorState!: deviceStatus['doorState'];
|
|
21
23
|
lockState!: deviceStatus['lockState'];
|
|
22
|
-
deviceStatus!: deviceStatusResponse;
|
|
24
|
+
deviceStatus!: any; //deviceStatusResponse;
|
|
23
25
|
|
|
24
26
|
// Config
|
|
25
27
|
scanDuration!: number;
|
|
@@ -151,12 +153,49 @@ export class Lock {
|
|
|
151
153
|
|
|
152
154
|
async refreshStatus(): Promise<void> {
|
|
153
155
|
try {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
this.
|
|
156
|
+
const t = Date.now();
|
|
157
|
+
const nonce = 'requestID';
|
|
158
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
159
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
160
|
+
const sign = signTerm.toString('base64');
|
|
161
|
+
this.debugLog(`Lock: ${this.accessory.displayName} sign: ${sign}`);
|
|
162
|
+
const options = {
|
|
163
|
+
hostname: HostDomain,
|
|
164
|
+
port: 443,
|
|
165
|
+
path: `${DevicePath}/${this.device.deviceId}/status`,
|
|
166
|
+
method: 'GET',
|
|
167
|
+
headers: {
|
|
168
|
+
Authorization: this.platform.config.credentials?.token,
|
|
169
|
+
sign: sign,
|
|
170
|
+
nonce: nonce,
|
|
171
|
+
t: t,
|
|
172
|
+
'Content-Type': 'application/json',
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
const req = https.request(options, (res) => {
|
|
176
|
+
this.debugLog(`Lock: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
177
|
+
let rawData = '';
|
|
178
|
+
res.on('data', (d) => {
|
|
179
|
+
rawData += d;
|
|
180
|
+
this.debugLog(`Lock: ${this.accessory.displayName} d: ${d}`);
|
|
181
|
+
});
|
|
182
|
+
res.on('end', () => {
|
|
183
|
+
try {
|
|
184
|
+
this.deviceStatus = JSON.parse(rawData);
|
|
185
|
+
this.debugLog(`Lock: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
|
|
186
|
+
this.lockState = this.deviceStatus.body.lockState;
|
|
187
|
+
this.doorState = this.deviceStatus.body.doorState;
|
|
188
|
+
this.parseStatus();
|
|
189
|
+
this.updateHomeKitCharacteristics();
|
|
190
|
+
} catch (e: any) {
|
|
191
|
+
this.errorLog(`Lock: ${this.accessory.displayName} error message: ${e.message}`);
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
req.on('error', (e: any) => {
|
|
196
|
+
this.errorLog(`Lock: ${this.accessory.displayName} error message: ${e.message}`);
|
|
197
|
+
});
|
|
198
|
+
req.end();
|
|
160
199
|
} catch (e: any) {
|
|
161
200
|
this.errorLog(`Lock: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
|
|
162
201
|
if (this.deviceLogging.includes('debug')) {
|
|
@@ -175,26 +214,54 @@ export class Lock {
|
|
|
175
214
|
* Lock - "command" "unlock" "default" = set to ???? state - LockCurrentState
|
|
176
215
|
*/
|
|
177
216
|
async pushChanges(): Promise<void> {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
217
|
+
// Make Push On request to the API
|
|
218
|
+
const t = Date.now();
|
|
219
|
+
const nonce = 'requestID';
|
|
220
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
221
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
222
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
223
|
+
.digest();
|
|
224
|
+
const sign = signTerm.toString('base64');
|
|
225
|
+
this.debugLog(`Lock: ${this.accessory.displayName} sign: ${sign}`);
|
|
226
|
+
let command = '';
|
|
183
227
|
if (this.LockTargetState) {
|
|
184
|
-
|
|
228
|
+
command = 'lock';
|
|
185
229
|
} else {
|
|
186
|
-
|
|
230
|
+
command = 'unlock';
|
|
187
231
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
);
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
232
|
+
const body = JSON.stringify({
|
|
233
|
+
'command': `${command}`,
|
|
234
|
+
'parameter': 'default',
|
|
235
|
+
'commandType': 'command',
|
|
236
|
+
});
|
|
237
|
+
this.infoLog(`Lock: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
238
|
+
const options = {
|
|
239
|
+
hostname: HostDomain,
|
|
240
|
+
port: 443,
|
|
241
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
242
|
+
method: 'POST',
|
|
243
|
+
headers: {
|
|
244
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
245
|
+
'sign': sign,
|
|
246
|
+
'nonce': nonce,
|
|
247
|
+
't': t,
|
|
248
|
+
'Content-Type': 'application/json',
|
|
249
|
+
'Content-Length': body.length,
|
|
250
|
+
},
|
|
251
|
+
};
|
|
252
|
+
const req = https.request(options, res => {
|
|
253
|
+
this.debugLog(`Lock: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
254
|
+
this.statusCode({ res });
|
|
255
|
+
res.on('data', d => {
|
|
256
|
+
this.debugLog(`Lock: ${this.accessory.displayName} d: ${d}`);
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
req.on('error', (e: any) => {
|
|
260
|
+
this.errorLog(`Lock: ${this.accessory.displayName} error message: ${e.message}`);
|
|
261
|
+
});
|
|
262
|
+
req.write(body);
|
|
263
|
+
req.end();
|
|
264
|
+
this.debugLog(`Lock: ${this.accessory.displayName} pushchanges: ${JSON.stringify(req)}`);
|
|
198
265
|
this.accessory.context.On = this.LockTargetState;
|
|
199
266
|
interval(5000)
|
|
200
267
|
.pipe(take(1))
|
|
@@ -235,8 +302,8 @@ export class Lock {
|
|
|
235
302
|
//throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
|
|
236
303
|
}
|
|
237
304
|
|
|
238
|
-
async statusCode(
|
|
239
|
-
switch (
|
|
305
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
306
|
+
switch (res.statusCode) {
|
|
240
307
|
case 151:
|
|
241
308
|
this.errorLog(`Lock: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
242
309
|
break;
|
|
@@ -255,7 +322,7 @@ export class Lock {
|
|
|
255
322
|
case 190:
|
|
256
323
|
this.errorLog(
|
|
257
324
|
`Lock: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
258
|
-
` Or command: ${JSON.stringify(
|
|
325
|
+
` Or command: ${JSON.stringify(res)} format is invalid`,
|
|
259
326
|
);
|
|
260
327
|
break;
|
|
261
328
|
case 100:
|
package/src/device/meter.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
import https from 'https';
|
|
2
|
+
import crypto from 'crypto';
|
|
3
|
+
import { Context } from 'vm';
|
|
4
|
+
import { hostname } from 'os';
|
|
5
|
+
import { MqttClient } from 'mqtt';
|
|
6
|
+
import { connectAsync } from 'async-mqtt';
|
|
1
7
|
import { interval, Subject } from 'rxjs';
|
|
2
8
|
import { skipWhile } from 'rxjs/operators';
|
|
3
9
|
import { SwitchBotPlatform } from '../platform';
|
|
4
10
|
import { Service, PlatformAccessory, Units, CharacteristicValue } from 'homebridge';
|
|
5
|
-
import {
|
|
6
|
-
import { Context } from 'vm';
|
|
7
|
-
import { MqttClient } from 'mqtt';
|
|
8
|
-
import { connectAsync } from 'async-mqtt';
|
|
9
|
-
import { hostname } from 'os';
|
|
11
|
+
import { device, devicesConfig, serviceData, ad, switchbot, temperature, deviceStatus, HostDomain, DevicePath } from '../settings';
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* Platform Accessory
|
|
@@ -33,7 +35,7 @@ export class Meter {
|
|
|
33
35
|
// OpenAPI Others
|
|
34
36
|
Temperature: deviceStatus['temperature'];
|
|
35
37
|
Humidity: deviceStatus['humidity'];
|
|
36
|
-
deviceStatus!: deviceStatusResponse;
|
|
38
|
+
deviceStatus!: any; //deviceStatusResponse;
|
|
37
39
|
|
|
38
40
|
// BLE Others
|
|
39
41
|
connected?: boolean;
|
|
@@ -407,12 +409,49 @@ export class Meter {
|
|
|
407
409
|
if (this.platform.config.credentials?.token) {
|
|
408
410
|
this.debugLog(`Meter: ${this.accessory.displayName} OpenAPI RefreshStatus`);
|
|
409
411
|
try {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
this.
|
|
412
|
+
const t = Date.now();
|
|
413
|
+
const nonce = 'requestID';
|
|
414
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
415
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
416
|
+
const sign = signTerm.toString('base64');
|
|
417
|
+
this.debugLog(`Meter: ${this.accessory.displayName} sign: ${sign}`);
|
|
418
|
+
const options = {
|
|
419
|
+
hostname: HostDomain,
|
|
420
|
+
port: 443,
|
|
421
|
+
path: `${DevicePath}/${this.device.deviceId}/status`,
|
|
422
|
+
method: 'GET',
|
|
423
|
+
headers: {
|
|
424
|
+
Authorization: this.platform.config.credentials?.token,
|
|
425
|
+
sign: sign,
|
|
426
|
+
nonce: nonce,
|
|
427
|
+
t: t,
|
|
428
|
+
'Content-Type': 'application/json',
|
|
429
|
+
},
|
|
430
|
+
};
|
|
431
|
+
const req = https.request(options, (res) => {
|
|
432
|
+
this.debugLog(`Meter: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
433
|
+
let rawData = '';
|
|
434
|
+
res.on('data', (d) => {
|
|
435
|
+
rawData += d;
|
|
436
|
+
this.debugLog(`Meter: ${this.accessory.displayName} d: ${d}`);
|
|
437
|
+
});
|
|
438
|
+
res.on('end', () => {
|
|
439
|
+
try {
|
|
440
|
+
this.deviceStatus = JSON.parse(rawData);
|
|
441
|
+
this.debugLog(`Meter: ${this.accessory.displayName} openAPIRefreshStatus: ${JSON.stringify(this.deviceStatus)}`);
|
|
442
|
+
this.Humidity = this.deviceStatus.body.humidity!;
|
|
443
|
+
this.Temperature = this.deviceStatus.body.temperature!;
|
|
444
|
+
this.parseStatus();
|
|
445
|
+
this.updateHomeKitCharacteristics();
|
|
446
|
+
} catch (e: any) {
|
|
447
|
+
this.errorLog(`Meter: ${this.accessory.displayName} error message: ${e.message}`);
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
});
|
|
451
|
+
req.on('error', (e: any) => {
|
|
452
|
+
this.errorLog(`Meter: ${this.accessory.displayName} error message: ${e.message}`);
|
|
453
|
+
});
|
|
454
|
+
req.end();
|
|
416
455
|
} catch (e: any) {
|
|
417
456
|
this.errorLog(`Meter: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
|
|
418
457
|
if (this.deviceLogging.includes('debug')) {
|
package/src/device/meterplus.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import https from 'https';
|
|
2
|
+
import crypto from 'crypto';
|
|
3
|
+
import { Context } from 'vm';
|
|
1
4
|
import { interval, Subject } from 'rxjs';
|
|
2
5
|
import { skipWhile } from 'rxjs/operators';
|
|
3
6
|
import { SwitchBotPlatform } from '../platform';
|
|
4
7
|
import { Service, PlatformAccessory, Units, CharacteristicValue } from 'homebridge';
|
|
5
|
-
import {
|
|
6
|
-
import { Context } from 'vm';
|
|
8
|
+
import { device, devicesConfig, serviceData, ad, switchbot, temperature, deviceStatus, HostDomain, DevicePath } from '../settings';
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Platform Accessory
|
|
@@ -30,7 +32,7 @@ export class MeterPlus {
|
|
|
30
32
|
// OpenAPI Others
|
|
31
33
|
Temperature: deviceStatus['temperature'];
|
|
32
34
|
Humidity: deviceStatus['humidity'];
|
|
33
|
-
deviceStatus!: deviceStatusResponse;
|
|
35
|
+
deviceStatus!: any; //deviceStatusResponse;
|
|
34
36
|
|
|
35
37
|
// BLE Others
|
|
36
38
|
connected?: boolean;
|
|
@@ -344,12 +346,49 @@ export class MeterPlus {
|
|
|
344
346
|
if (this.platform.config.credentials?.token) {
|
|
345
347
|
this.debugLog(`Meter Plus: ${this.accessory.displayName} OpenAPI RefreshStatus`);
|
|
346
348
|
try {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
this.
|
|
349
|
+
const t = Date.now();
|
|
350
|
+
const nonce = 'requestID';
|
|
351
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
352
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
353
|
+
const sign = signTerm.toString('base64');
|
|
354
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} sign: ${sign}`);
|
|
355
|
+
const options = {
|
|
356
|
+
hostname: HostDomain,
|
|
357
|
+
port: 443,
|
|
358
|
+
path: `${DevicePath}/${this.device.deviceId}/status`,
|
|
359
|
+
method: 'GET',
|
|
360
|
+
headers: {
|
|
361
|
+
Authorization: this.platform.config.credentials?.token,
|
|
362
|
+
sign: sign,
|
|
363
|
+
nonce: nonce,
|
|
364
|
+
t: t,
|
|
365
|
+
'Content-Type': 'application/json',
|
|
366
|
+
},
|
|
367
|
+
};
|
|
368
|
+
const req = https.request(options, (res) => {
|
|
369
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
370
|
+
let rawData = '';
|
|
371
|
+
res.on('data', (d) => {
|
|
372
|
+
rawData += d;
|
|
373
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} d: ${d}`);
|
|
374
|
+
});
|
|
375
|
+
res.on('end', () => {
|
|
376
|
+
try {
|
|
377
|
+
this.deviceStatus = JSON.parse(rawData);
|
|
378
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} openAPIRefreshStatus: ${JSON.stringify(this.deviceStatus)}`);
|
|
379
|
+
this.Humidity = this.deviceStatus.body.humidity!;
|
|
380
|
+
this.Temperature = this.deviceStatus.body.temperature!;
|
|
381
|
+
this.parseStatus();
|
|
382
|
+
this.updateHomeKitCharacteristics();
|
|
383
|
+
} catch (e: any) {
|
|
384
|
+
this.errorLog(`Meter Plus: ${this.accessory.displayName} error message: ${e.message}`);
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
req.on('error', (e: any) => {
|
|
389
|
+
this.errorLog(`Meter Plus: ${this.accessory.displayName} error message: ${e.message}`);
|
|
390
|
+
});
|
|
391
|
+
req.end();
|
|
353
392
|
} catch (e: any) {
|
|
354
393
|
this.errorLog(`Meter Plus: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
|
|
355
394
|
if (this.deviceLogging.includes('debug')) {
|
package/src/device/motion.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import https from 'https';
|
|
2
|
+
import crypto from 'crypto';
|
|
3
|
+
import { Context } from 'vm';
|
|
1
4
|
import { interval, Subject } from 'rxjs';
|
|
2
5
|
import { skipWhile } from 'rxjs/operators';
|
|
3
6
|
import { SwitchBotPlatform } from '../platform';
|
|
4
7
|
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
|
5
|
-
import {
|
|
6
|
-
import { Context } from 'vm';
|
|
8
|
+
import { device, devicesConfig, serviceData, switchbot, deviceStatus, ad, HostDomain, DevicePath } from '../settings';
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Platform Accessory
|
|
@@ -23,7 +25,7 @@ export class Motion {
|
|
|
23
25
|
StatusLowBattery?: CharacteristicValue;
|
|
24
26
|
|
|
25
27
|
// OpenAPI Others
|
|
26
|
-
deviceStatus!: deviceStatusResponse;
|
|
28
|
+
deviceStatus!: any; //deviceStatusResponse;
|
|
27
29
|
moveDetected: deviceStatus['moveDetected'];
|
|
28
30
|
brightness: deviceStatus['brightness'];
|
|
29
31
|
|
|
@@ -326,15 +328,49 @@ export class Motion {
|
|
|
326
328
|
if (this.platform.config.credentials?.token) {
|
|
327
329
|
this.debugLog(`Motion Sensor: ${this.accessory.displayName} OpenAPI RefreshStatus`);
|
|
328
330
|
try {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
this.
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
331
|
+
const t = Date.now();
|
|
332
|
+
const nonce = 'requestID';
|
|
333
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
334
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
335
|
+
const sign = signTerm.toString('base64');
|
|
336
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} sign: ${sign}`);
|
|
337
|
+
const options = {
|
|
338
|
+
hostname: HostDomain,
|
|
339
|
+
port: 443,
|
|
340
|
+
path: `${DevicePath}/${this.device.deviceId}/status`,
|
|
341
|
+
method: 'GET',
|
|
342
|
+
headers: {
|
|
343
|
+
Authorization: this.platform.config.credentials?.token,
|
|
344
|
+
sign: sign,
|
|
345
|
+
nonce: nonce,
|
|
346
|
+
t: t,
|
|
347
|
+
'Content-Type': 'application/json',
|
|
348
|
+
},
|
|
349
|
+
};
|
|
350
|
+
const req = https.request(options, (res) => {
|
|
351
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
352
|
+
let rawData = '';
|
|
353
|
+
res.on('data', (d) => {
|
|
354
|
+
rawData += d;
|
|
355
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} d: ${d}`);
|
|
356
|
+
});
|
|
357
|
+
res.on('end', () => {
|
|
358
|
+
try {
|
|
359
|
+
this.deviceStatus = JSON.parse(rawData);
|
|
360
|
+
this.debugLog(`Motion Sensor: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
|
|
361
|
+
this.moveDetected = this.deviceStatus.body.moveDetected;
|
|
362
|
+
this.brightness = this.deviceStatus.body.brightness;
|
|
363
|
+
this.parseStatus();
|
|
364
|
+
this.updateHomeKitCharacteristics();
|
|
365
|
+
} catch (e: any) {
|
|
366
|
+
this.errorLog(`Motion Sensor: ${this.accessory.displayName} error message: ${e.message}`);
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
req.on('error', (e: any) => {
|
|
371
|
+
this.errorLog(`Motion Sensor: ${this.accessory.displayName} error message: ${e.message}`);
|
|
372
|
+
});
|
|
373
|
+
req.end();
|
|
338
374
|
} catch (e: any) {
|
|
339
375
|
this.errorLog(`Motion Sensor: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
|
|
340
376
|
if (this.deviceLogging.includes('debug')) {
|
package/src/device/plug.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import https from 'https';
|
|
2
|
+
import crypto from 'crypto';
|
|
3
|
+
import { Context } from 'vm';
|
|
4
|
+
import { IncomingMessage } from 'http';
|
|
2
5
|
import { interval, Subject } from 'rxjs';
|
|
3
6
|
import { SwitchBotPlatform } from '../platform';
|
|
4
7
|
import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
|
|
5
8
|
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
|
6
|
-
import {
|
|
7
|
-
import { Context } from 'vm';
|
|
9
|
+
import { device, devicesConfig, deviceStatus, ad, serviceData, switchbot, HostDomain, DevicePath } from '../settings';
|
|
8
10
|
|
|
9
11
|
export class Plug {
|
|
10
12
|
// Services
|
|
@@ -16,7 +18,7 @@ export class Plug {
|
|
|
16
18
|
|
|
17
19
|
// OpenAPI Others
|
|
18
20
|
power: deviceStatus['power'];
|
|
19
|
-
deviceStatus!: deviceStatusResponse;
|
|
21
|
+
deviceStatus!: any; //deviceStatusResponse;
|
|
20
22
|
|
|
21
23
|
// BLE Others
|
|
22
24
|
connected?: boolean;
|
|
@@ -281,11 +283,48 @@ export class Plug {
|
|
|
281
283
|
|
|
282
284
|
async openAPIRefreshStatus() {
|
|
283
285
|
try {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
this.
|
|
288
|
-
|
|
286
|
+
const t = Date.now();
|
|
287
|
+
const nonce = 'requestID';
|
|
288
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
289
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
290
|
+
const sign = signTerm.toString('base64');
|
|
291
|
+
this.debugLog(`Plug: ${this.accessory.displayName} sign: ${sign}`);
|
|
292
|
+
const options = {
|
|
293
|
+
hostname: HostDomain,
|
|
294
|
+
port: 443,
|
|
295
|
+
path: `${DevicePath}/${this.device.deviceId}/status`,
|
|
296
|
+
method: 'GET',
|
|
297
|
+
headers: {
|
|
298
|
+
Authorization: this.platform.config.credentials?.token,
|
|
299
|
+
sign: sign,
|
|
300
|
+
nonce: nonce,
|
|
301
|
+
t: t,
|
|
302
|
+
'Content-Type': 'application/json',
|
|
303
|
+
},
|
|
304
|
+
};
|
|
305
|
+
const req = https.request(options, (res) => {
|
|
306
|
+
this.debugLog(`Plug: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
307
|
+
let rawData = '';
|
|
308
|
+
res.on('data', (d) => {
|
|
309
|
+
rawData += d;
|
|
310
|
+
this.debugLog(`Plug: ${this.accessory.displayName} d: ${d}`);
|
|
311
|
+
});
|
|
312
|
+
res.on('end', () => {
|
|
313
|
+
try {
|
|
314
|
+
this.deviceStatus = JSON.parse(rawData);
|
|
315
|
+
this.debugLog(`Plug: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
|
|
316
|
+
this.power = this.deviceStatus.body.power;
|
|
317
|
+
this.parseStatus();
|
|
318
|
+
this.updateHomeKitCharacteristics();
|
|
319
|
+
} catch (e: any) {
|
|
320
|
+
this.errorLog(`Plug: ${this.accessory.displayName} error message: ${e.message}`);
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
req.on('error', (e: any) => {
|
|
325
|
+
this.errorLog(`Plug: ${this.accessory.displayName} error message: ${e.message}`);
|
|
326
|
+
});
|
|
327
|
+
req.end();
|
|
289
328
|
} catch (e: any) {
|
|
290
329
|
this.errorLog(`Plug: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
|
|
291
330
|
if (this.deviceLogging.includes('debug')) {
|
|
@@ -376,27 +415,56 @@ export class Plug {
|
|
|
376
415
|
async openAPIpushChanges() {
|
|
377
416
|
if (this.platform.config.credentials?.token) {
|
|
378
417
|
if (this.On !== this.OnCached) {
|
|
418
|
+
// Make Push On request to the API
|
|
379
419
|
this.debugLog(`Plug: ${this.accessory.displayName} OpenAPI pushChanges`);
|
|
380
|
-
const
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
420
|
+
const t = Date.now();
|
|
421
|
+
const nonce = 'requestID';
|
|
422
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
423
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
424
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
425
|
+
.digest();
|
|
426
|
+
const sign = signTerm.toString('base64');
|
|
427
|
+
this.debugLog(`Plug: ${this.accessory.displayName} sign: ${sign}`);
|
|
428
|
+
|
|
429
|
+
let command = '';
|
|
385
430
|
if (this.On) {
|
|
386
|
-
|
|
431
|
+
command = 'turnOn';
|
|
387
432
|
} else {
|
|
388
|
-
|
|
433
|
+
command = 'turnOff';
|
|
389
434
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
);
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
435
|
+
const body = JSON.stringify({
|
|
436
|
+
'command': `${command}`,
|
|
437
|
+
'parameter': 'default',
|
|
438
|
+
'commandType': 'command',
|
|
439
|
+
});
|
|
440
|
+
this.infoLog(`Plug: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
441
|
+
const options = {
|
|
442
|
+
hostname: HostDomain,
|
|
443
|
+
port: 443,
|
|
444
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
445
|
+
method: 'POST',
|
|
446
|
+
headers: {
|
|
447
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
448
|
+
'sign': sign,
|
|
449
|
+
'nonce': nonce,
|
|
450
|
+
't': t,
|
|
451
|
+
'Content-Type': 'application/json',
|
|
452
|
+
'Content-Length': body.length,
|
|
453
|
+
},
|
|
454
|
+
};
|
|
455
|
+
const req = https.request(options, res => {
|
|
456
|
+
this.debugLog(`Plug: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
457
|
+
this.statusCode({ res });
|
|
458
|
+
res.on('data', d => {
|
|
459
|
+
this.debugLog(`Plug: ${this.accessory.displayName} d: ${d}`);
|
|
460
|
+
});
|
|
461
|
+
});
|
|
462
|
+
req.on('error', (e: any) => {
|
|
463
|
+
this.errorLog(`Plug: ${this.accessory.displayName} error message: ${e.message}`);
|
|
464
|
+
});
|
|
465
|
+
req.write(body);
|
|
466
|
+
req.end();
|
|
467
|
+
this.debugLog(`Plug: ${this.accessory.displayName} openAPIpushChanges: ${JSON.stringify(req)}`);
|
|
400
468
|
this.OnCached = this.On;
|
|
401
469
|
this.accessory.context.On = this.OnCached;
|
|
402
470
|
}
|
|
@@ -422,8 +490,8 @@ export class Plug {
|
|
|
422
490
|
//throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
|
|
423
491
|
}
|
|
424
492
|
|
|
425
|
-
async statusCode(
|
|
426
|
-
switch (
|
|
493
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
494
|
+
switch (res.statusCode) {
|
|
427
495
|
case 151:
|
|
428
496
|
this.errorLog(`Plug: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
429
497
|
break;
|
|
@@ -444,7 +512,7 @@ export class Plug {
|
|
|
444
512
|
case 190:
|
|
445
513
|
this.errorLog(
|
|
446
514
|
`Plug: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
447
|
-
` Or command: ${JSON.stringify(
|
|
515
|
+
` Or command: ${JSON.stringify(res)} format is invalid`,
|
|
448
516
|
);
|
|
449
517
|
break;
|
|
450
518
|
case 100:
|