@switchbot/homebridge-switchbot 1.15.1-beta.1 → 1.15.1-beta.10
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/ISSUE_TEMPLATE/bug-report.yml +1 -0
- package/.github/ISSUE_TEMPLATE/feature-request.yml +1 -0
- package/.github/ISSUE_TEMPLATE/support-request.yml +1 -0
- package/.prettierrc +1 -1
- package/CHANGELOG.md +9 -0
- 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 +143 -87
- 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 +10 -12
- 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 +157 -100
- package/src/settings.ts +2 -25
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import https from 'https';
|
|
2
|
+
import crypto from 'crypto';
|
|
3
|
+
import { IncomingMessage } from 'http';
|
|
2
4
|
import { SwitchBotPlatform } from '../platform';
|
|
3
|
-
import { irDevicesConfig,
|
|
5
|
+
import { irDevicesConfig, irdevice, HostDomain, DevicePath } from '../settings';
|
|
4
6
|
import { CharacteristicValue, PlatformAccessory, Service } from 'homebridge';
|
|
5
7
|
|
|
6
8
|
/**
|
|
@@ -95,7 +97,7 @@ export class WaterHeater {
|
|
|
95
97
|
commandType: 'command',
|
|
96
98
|
parameter: 'default',
|
|
97
99
|
command: 'turnOn',
|
|
98
|
-
}
|
|
100
|
+
};
|
|
99
101
|
await this.pushChanges(payload);
|
|
100
102
|
}
|
|
101
103
|
}
|
|
@@ -106,12 +108,12 @@ export class WaterHeater {
|
|
|
106
108
|
commandType: 'command',
|
|
107
109
|
parameter: 'default',
|
|
108
110
|
command: 'turnOff',
|
|
109
|
-
}
|
|
111
|
+
};
|
|
110
112
|
await this.pushChanges(payload);
|
|
111
113
|
}
|
|
112
114
|
}
|
|
113
115
|
|
|
114
|
-
async pushChanges(payload
|
|
116
|
+
async pushChanges(payload): Promise<void> {
|
|
115
117
|
try {
|
|
116
118
|
this.infoLog(
|
|
117
119
|
`Water Heater: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},` +
|
|
@@ -119,9 +121,42 @@ export class WaterHeater {
|
|
|
119
121
|
);
|
|
120
122
|
|
|
121
123
|
// Make the API request
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
this.
|
|
124
|
+
const t = Date.now();
|
|
125
|
+
const nonce = 'requestID';
|
|
126
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
127
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
128
|
+
const sign = signTerm.toString('base64');
|
|
129
|
+
this.debugLog(`Water Heater: ${this.accessory.displayName} sign: ${sign}`);
|
|
130
|
+
const options = {
|
|
131
|
+
hostname: HostDomain,
|
|
132
|
+
port: 443,
|
|
133
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
134
|
+
method: 'POST',
|
|
135
|
+
headers: {
|
|
136
|
+
Authorization: this.platform.config.credentials?.token,
|
|
137
|
+
sign: sign,
|
|
138
|
+
nonce: nonce,
|
|
139
|
+
t: t,
|
|
140
|
+
'Content-Type': 'application/json',
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const req = https.request(options, (res) => {
|
|
145
|
+
this.debugLog(`Water Heater: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
146
|
+
this.statusCode({ res });
|
|
147
|
+
res.on('data', (d) => {
|
|
148
|
+
this.debugLog(`Water Heater: ${this.accessory.displayName} d: ${d}`);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
req.on('error', (error) => {
|
|
153
|
+
this.errorLog(`Water Heater: ${this.accessory.displayName} error: ${error}`);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
req.write(payload);
|
|
157
|
+
req.end();
|
|
158
|
+
|
|
159
|
+
this.debugLog(`Water Heater: ${this.accessory.displayName} pushchanges: ${JSON.stringify(req)}`);
|
|
125
160
|
this.updateHomeKitCharacteristics();
|
|
126
161
|
} catch (e: any) {
|
|
127
162
|
this.errorLog(`Water Heater: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
|
|
@@ -134,8 +169,8 @@ export class WaterHeater {
|
|
|
134
169
|
}
|
|
135
170
|
}
|
|
136
171
|
|
|
137
|
-
async statusCode(
|
|
138
|
-
switch (
|
|
172
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
173
|
+
switch (res.statusCode) {
|
|
139
174
|
case 151:
|
|
140
175
|
this.errorLog(`Water Heater: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
141
176
|
break;
|
|
@@ -154,7 +189,7 @@ export class WaterHeater {
|
|
|
154
189
|
case 190:
|
|
155
190
|
this.errorLog(
|
|
156
191
|
`Water Heater: ${this.accessory.displayName} Device internal error due to device states not synchronized` +
|
|
157
|
-
` with server, Or command: ${JSON.stringify(
|
|
192
|
+
` with server, Or command: ${JSON.stringify(res)} format is invalid`,
|
|
158
193
|
);
|
|
159
194
|
break;
|
|
160
195
|
case 100:
|
package/src/platform.ts
CHANGED
|
@@ -18,12 +18,13 @@ import { AirPurifier } from './irdevice/airpurifier';
|
|
|
18
18
|
import { WaterHeater } from './irdevice/waterheater';
|
|
19
19
|
import { VacuumCleaner } from './irdevice/vacuumcleaner';
|
|
20
20
|
import { AirConditioner } from './irdevice/airconditioner';
|
|
21
|
-
import
|
|
21
|
+
import https from 'https';
|
|
22
|
+
import crypto from 'crypto';
|
|
23
|
+
import { Buffer } from 'buffer';
|
|
22
24
|
import fakegato from 'fakegato-history';
|
|
23
25
|
import { readFileSync, writeFileSync } from 'fs';
|
|
24
|
-
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
|
|
25
26
|
import { API, DynamicPlatformPlugin, Logger, PlatformAccessory, Service, Characteristic } from 'homebridge';
|
|
26
|
-
import { PLATFORM_NAME, PLUGIN_NAME,
|
|
27
|
+
import { PLATFORM_NAME, PLUGIN_NAME, irdevice, device, SwitchBotPlatformConfig, devicesConfig, DevicePath, HostDomain } from './settings';
|
|
27
28
|
|
|
28
29
|
/**
|
|
29
30
|
* HomebridgePlatform
|
|
@@ -37,12 +38,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
37
38
|
// this is used to track restored cached accessories
|
|
38
39
|
public readonly accessories: PlatformAccessory[] = [];
|
|
39
40
|
|
|
40
|
-
public axios: AxiosInstance = axios.create({
|
|
41
|
-
responseType: 'json',
|
|
42
|
-
});
|
|
43
|
-
|
|
44
41
|
version = require('../package.json').version || '1.12.8'; // eslint-disable-line @typescript-eslint/no-var-requires
|
|
45
|
-
deviceStatus!:
|
|
42
|
+
deviceStatus!: any;
|
|
46
43
|
registeringDevice!: boolean;
|
|
47
44
|
debugMode!: boolean;
|
|
48
45
|
platformLogging?: string;
|
|
@@ -51,6 +48,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
51
48
|
|
|
52
49
|
constructor(public readonly log: Logger, public readonly config: SwitchBotPlatformConfig, public readonly api: API) {
|
|
53
50
|
this.logs();
|
|
51
|
+
|
|
54
52
|
this.debugLog('Finished initializing platform:', this.config.name);
|
|
55
53
|
// only load if configured
|
|
56
54
|
if (!this.config) {
|
|
@@ -74,16 +72,6 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
74
72
|
return;
|
|
75
73
|
}
|
|
76
74
|
|
|
77
|
-
// setup axios interceptor to add headers / api key to each request
|
|
78
|
-
this.axios.interceptors.request.use((request: AxiosRequestConfig) => {
|
|
79
|
-
request.headers!.Authorization = this.config.credentials?.token;
|
|
80
|
-
request.headers!.sign = String(sha256(this.config.credentials!.token + Date.now(), this.config.credentials!.secret)).toUpperCase();
|
|
81
|
-
request.headers!.t = String(Date.now());
|
|
82
|
-
request.headers!.nonce = '';
|
|
83
|
-
request.headers!['Content-Type'] = 'application/json; charset=utf8';
|
|
84
|
-
return request;
|
|
85
|
-
});
|
|
86
|
-
|
|
87
75
|
// import fakegato-history module
|
|
88
76
|
this.fakegatoAPI = fakegato(api);
|
|
89
77
|
|
|
@@ -288,90 +276,128 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
288
276
|
async discoverDevices() {
|
|
289
277
|
try {
|
|
290
278
|
if (this.config.credentials?.token) {
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
this.
|
|
279
|
+
const t = Date.now();
|
|
280
|
+
const nonce = 'requestID';
|
|
281
|
+
const data = this.config.credentials?.token + t + nonce;
|
|
282
|
+
const signTerm = crypto.createHmac('sha256', this.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
283
|
+
const sign = signTerm.toString('base64');
|
|
284
|
+
this.debugLog(sign);
|
|
285
|
+
const options = {
|
|
286
|
+
hostname: HostDomain,
|
|
287
|
+
port: 443,
|
|
288
|
+
path: DevicePath,
|
|
289
|
+
method: 'GET',
|
|
290
|
+
headers: {
|
|
291
|
+
'Authorization': this.config.credentials?.token,
|
|
292
|
+
'sign': sign,
|
|
293
|
+
'nonce': nonce,
|
|
294
|
+
't': t,
|
|
295
|
+
'Content-Type': 'application/json',
|
|
296
|
+
},
|
|
297
|
+
};
|
|
298
|
+
const req = https.request(options, (res) => {
|
|
299
|
+
this.debugLog(`statusCode: ${res.statusCode}`);
|
|
300
|
+
this.debugLog(`headers: ${JSON.stringify(res.headers)}`);
|
|
301
|
+
let rawData = '';
|
|
302
|
+
res.on('data', (d) => {
|
|
303
|
+
rawData += d;
|
|
304
|
+
this.debugLog(`d: ${d}`);
|
|
305
|
+
});
|
|
306
|
+
res.on('end', () => {
|
|
307
|
+
try {
|
|
308
|
+
const devicesAPI = JSON.parse(rawData);
|
|
309
|
+
this.debugLog(`devicesAPI: ${JSON.stringify(devicesAPI.body)}`);
|
|
310
|
+
|
|
311
|
+
// SwitchBot Devices
|
|
312
|
+
if (devicesAPI.body.deviceList.length !== 0) {
|
|
313
|
+
this.infoLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
|
|
314
|
+
} else {
|
|
315
|
+
this.debugLog(`Total SwitchBot Devices Found: ${devicesAPI.body.deviceList.length}`);
|
|
316
|
+
}
|
|
317
|
+
const deviceLists = devicesAPI.body.deviceList;
|
|
318
|
+
if (!this.config.options?.devices) {
|
|
319
|
+
this.debugLog(`SwitchBot Device Config Not Set: ${JSON.stringify(this.config.options?.devices)}`);
|
|
320
|
+
const devices = deviceLists.map((v: any) => v);
|
|
321
|
+
for (const device of devices) {
|
|
322
|
+
if (device.deviceType) {
|
|
323
|
+
if (device.configDeviceName) {
|
|
324
|
+
device.deviceName = device.configDeviceName;
|
|
325
|
+
}
|
|
326
|
+
this.createDevice(device);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
} else if (this.config.credentials?.token && this.config.options.devices) {
|
|
330
|
+
this.debugLog(`SwitchBot Device Config Set: ${JSON.stringify(this.config.options?.devices)}`);
|
|
331
|
+
const deviceConfigs = this.config.options?.devices;
|
|
332
|
+
|
|
333
|
+
const mergeBydeviceId = (a1: { deviceId: string }[], a2: any[]) =>
|
|
334
|
+
a1.map((itm: { deviceId: string }) => ({
|
|
335
|
+
...a2.find(
|
|
336
|
+
(item: { deviceId: string }) =>
|
|
337
|
+
item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item,
|
|
338
|
+
),
|
|
339
|
+
...itm,
|
|
340
|
+
}));
|
|
341
|
+
|
|
342
|
+
const devices = mergeBydeviceId(deviceLists, deviceConfigs);
|
|
343
|
+
this.debugLog(`SwitchBot Devices: ${JSON.stringify(devices)}`);
|
|
344
|
+
for (const device of devices) {
|
|
345
|
+
if (device.deviceType) {
|
|
346
|
+
if (device.configDeviceName) {
|
|
347
|
+
device.deviceName = device.configDeviceName;
|
|
348
|
+
}
|
|
349
|
+
this.createDevice(device);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
} else {
|
|
353
|
+
this.errorLog('SwitchBot Token Supplied, Issue with Auth.');
|
|
354
|
+
}
|
|
294
355
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
}
|
|
301
|
-
const deviceLists = devicesAPI.body.deviceList;
|
|
302
|
-
if (!this.config.options?.devices) {
|
|
303
|
-
this.debugLog(`SwitchBot Device Config Not Set: ${JSON.stringify(this.config.options?.devices)}`);
|
|
304
|
-
const devices = deviceLists.map((v: any) => v);
|
|
305
|
-
for (const device of devices) {
|
|
306
|
-
if (device.deviceType) {
|
|
307
|
-
if (device.configDeviceName) {
|
|
308
|
-
device.deviceName = device.configDeviceName;
|
|
356
|
+
// IR Devices
|
|
357
|
+
if (devicesAPI.body.infraredRemoteList.length !== 0) {
|
|
358
|
+
this.infoLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
|
|
359
|
+
} else {
|
|
360
|
+
this.debugLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
|
|
309
361
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
(
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
362
|
+
const irDeviceLists = devicesAPI.body.infraredRemoteList;
|
|
363
|
+
if (!this.config.options?.irdevices) {
|
|
364
|
+
this.debugLog(`IR Device Config Not Set: ${JSON.stringify(this.config.options?.irdevices)}`);
|
|
365
|
+
const devices = irDeviceLists.map((v: any) => v);
|
|
366
|
+
for (const device of devices) {
|
|
367
|
+
if (device.remoteType) {
|
|
368
|
+
this.createIRDevice(device);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
} else {
|
|
372
|
+
this.debugLog(`IR Device Config Set: ${JSON.stringify(this.config.options?.irdevices)}`);
|
|
373
|
+
const irDeviceConfig = this.config.options?.irdevices;
|
|
374
|
+
|
|
375
|
+
const mergeIRBydeviceId = (a1: { deviceId: string }[], a2: any[]) =>
|
|
376
|
+
a1.map((itm: { deviceId: string }) => ({
|
|
377
|
+
...a2.find(
|
|
378
|
+
(item: { deviceId: string }) =>
|
|
379
|
+
item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item,
|
|
380
|
+
),
|
|
381
|
+
...itm,
|
|
382
|
+
}));
|
|
383
|
+
|
|
384
|
+
const devices = mergeIRBydeviceId(irDeviceLists, irDeviceConfig);
|
|
385
|
+
this.debugLog(`IR Devices: ${JSON.stringify(devices)}`);
|
|
386
|
+
for (const device of devices) {
|
|
387
|
+
if (device.remoteType) {
|
|
388
|
+
this.createIRDevice(device);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
332
391
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
}
|
|
336
|
-
} else {
|
|
337
|
-
this.errorLog('Neither SwitchBot Token or Device Config are not set.');
|
|
338
|
-
}
|
|
339
|
-
// IR Devices
|
|
340
|
-
if (devicesAPI.body.infraredRemoteList.length !== 0) {
|
|
341
|
-
this.infoLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
|
|
342
|
-
} else {
|
|
343
|
-
this.debugLog(`Total IR Devices Found: ${devicesAPI.body.infraredRemoteList.length}`);
|
|
344
|
-
}
|
|
345
|
-
const irDeviceLists = devicesAPI.body.infraredRemoteList;
|
|
346
|
-
if (!this.config.options?.irdevices) {
|
|
347
|
-
this.debugLog(`IR Device Config Not Set: ${JSON.stringify(this.config.options?.irdevices)}`);
|
|
348
|
-
const devices = irDeviceLists.map((v: any) => v);
|
|
349
|
-
for (const device of devices) {
|
|
350
|
-
if (device.remoteType) {
|
|
351
|
-
this.createIRDevice(device);
|
|
392
|
+
} catch (e:any) {
|
|
393
|
+
this.errorLog(e.message);
|
|
352
394
|
}
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
a1.map((itm: { deviceId: string }) => ({
|
|
360
|
-
...a2.find(
|
|
361
|
-
(item: { deviceId: string }) =>
|
|
362
|
-
item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') && item,
|
|
363
|
-
),
|
|
364
|
-
...itm,
|
|
365
|
-
}));
|
|
366
|
-
|
|
367
|
-
const devices = mergeIRBydeviceId(irDeviceLists, irDeviceConfig);
|
|
368
|
-
this.debugLog(`IR Devices: ${JSON.stringify(devices)}`);
|
|
369
|
-
for (const device of devices) {
|
|
370
|
-
if (device.remoteType) {
|
|
371
|
-
this.createIRDevice(device);
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
}
|
|
395
|
+
});
|
|
396
|
+
});
|
|
397
|
+
req.on('error', (error) => {
|
|
398
|
+
this.errorLog(error);
|
|
399
|
+
});
|
|
400
|
+
req.end();
|
|
375
401
|
} else if (!this.config.credentials?.token && this.config.options?.devices) {
|
|
376
402
|
this.debugLog(`SwitchBot Device Manual Config Set: ${JSON.stringify(this.config.options?.devices)}`);
|
|
377
403
|
const deviceConfigs = this.config.options?.devices;
|
|
@@ -1744,7 +1770,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
1744
1770
|
this.warnLog(`Removing existing accessory from cache: ${existingAccessory.displayName}`);
|
|
1745
1771
|
}
|
|
1746
1772
|
|
|
1747
|
-
public deviceListInfo(devices
|
|
1773
|
+
public deviceListInfo(devices) {
|
|
1748
1774
|
if (this.platformLogging?.includes('debug')) {
|
|
1749
1775
|
this.warnLog(`deviceListInfoStatus: ${JSON.stringify(devices)}`);
|
|
1750
1776
|
}
|
|
@@ -1753,7 +1779,38 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
|
|
|
1753
1779
|
public async deviceInfo(device: (irdevice & devicesConfig) | (device & devicesConfig)) {
|
|
1754
1780
|
if (this.platformLogging?.includes('debug')) {
|
|
1755
1781
|
this.warnLog(JSON.stringify(device));
|
|
1756
|
-
|
|
1782
|
+
|
|
1783
|
+
const t = Date.now();
|
|
1784
|
+
const nonce = 'requestID';
|
|
1785
|
+
const data = this.config.credentials?.token + t + nonce;
|
|
1786
|
+
const signTerm = crypto.createHmac('sha256', this.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
1787
|
+
const sign = signTerm.toString('base64');
|
|
1788
|
+
this.debugLog(sign);
|
|
1789
|
+
const options = {
|
|
1790
|
+
hostname: HostDomain,
|
|
1791
|
+
port: 443,
|
|
1792
|
+
path: `${DevicePath}/${device.deviceId}/status`,
|
|
1793
|
+
method: 'GET',
|
|
1794
|
+
headers: {
|
|
1795
|
+
Authorization: this.config.credentials?.token,
|
|
1796
|
+
sign: sign,
|
|
1797
|
+
nonce: nonce,
|
|
1798
|
+
t: t,
|
|
1799
|
+
'Content-Type': 'application/json',
|
|
1800
|
+
},
|
|
1801
|
+
};
|
|
1802
|
+
const req = https.request(options, (res) => {
|
|
1803
|
+
this.debugLog(`statusCode: ${res.statusCode}`);
|
|
1804
|
+
res.on('data', (d) => {
|
|
1805
|
+
process.stdout.write(d);
|
|
1806
|
+
});
|
|
1807
|
+
});
|
|
1808
|
+
req.on('error', (error) => {
|
|
1809
|
+
this.errorLog(error);
|
|
1810
|
+
});
|
|
1811
|
+
req.end();
|
|
1812
|
+
|
|
1813
|
+
this.deviceStatus = req;
|
|
1757
1814
|
if (this.deviceStatus.message === 'success') {
|
|
1758
1815
|
this.warnLog(`${device.deviceName} deviceInfoStatus: ${JSON.stringify(this.deviceStatus)}`);
|
|
1759
1816
|
} else {
|
package/src/settings.ts
CHANGED
|
@@ -13,12 +13,12 @@ export const PLUGIN_NAME = '@switchbot/homebridge-switchbot';
|
|
|
13
13
|
/**
|
|
14
14
|
* This is the main url used to access SwitchBot API
|
|
15
15
|
*/
|
|
16
|
-
export const
|
|
16
|
+
export const HostDomain = 'api.switch-bot.com';
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* This is the main url used to access SwitchBot API
|
|
20
20
|
*/
|
|
21
|
-
export const
|
|
21
|
+
export const DevicePath = '/v1.1/devices';
|
|
22
22
|
|
|
23
23
|
//Config
|
|
24
24
|
export interface SwitchBotPlatformConfig extends PlatformConfig {
|
|
@@ -177,23 +177,6 @@ export type other = {
|
|
|
177
177
|
commandOff?: string;
|
|
178
178
|
};
|
|
179
179
|
|
|
180
|
-
export type payload = {
|
|
181
|
-
commandType: string;
|
|
182
|
-
parameter: string;
|
|
183
|
-
command: string;
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
export interface AxiosRequestConfig {
|
|
187
|
-
params?: Record<string, unknown>;
|
|
188
|
-
headers?: any;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
export type deviceResponses = {
|
|
192
|
-
statusCode: number | string;
|
|
193
|
-
message: string;
|
|
194
|
-
body: deviceList | infraredRemoteList;
|
|
195
|
-
};
|
|
196
|
-
|
|
197
180
|
//a list of physical devices.
|
|
198
181
|
export type deviceList = {
|
|
199
182
|
device: Array<device>;
|
|
@@ -236,12 +219,6 @@ export type irdevice = {
|
|
|
236
219
|
hubDeviceId: string; //remote device's parent Hub ID
|
|
237
220
|
};
|
|
238
221
|
|
|
239
|
-
export type deviceStatusResponse = {
|
|
240
|
-
statusCode: number;
|
|
241
|
-
message: string;
|
|
242
|
-
body: deviceStatus;
|
|
243
|
-
};
|
|
244
|
-
|
|
245
222
|
export type deviceStatus = {
|
|
246
223
|
//device ID.
|
|
247
224
|
deviceId: string;
|