@switchbot/homebridge-switchbot 1.15.1-beta.1 → 1.15.1-beta.11
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 +65 -28
- 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 +65 -28
- 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 +58 -22
- 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 +76 -40
- 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 +71 -35
- 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 +58 -22
- 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 +112 -76
- 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 +58 -22
- 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 +58 -22
- 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 +64 -34
- package/src/irdevice/airpurifier.ts +64 -36
- package/src/irdevice/camera.ts +57 -27
- package/src/irdevice/fan.ts +76 -46
- package/src/irdevice/light.ts +69 -39
- package/src/irdevice/other.ts +57 -27
- package/src/irdevice/tv.ts +112 -82
- package/src/irdevice/vacuumcleaner.ts +57 -27
- package/src/irdevice/waterheater.ts +57 -27
- package/src/platform.ts +157 -100
- package/src/settings.ts +2 -25
package/src/irdevice/light.ts
CHANGED
|
@@ -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
|
/**
|
|
@@ -99,55 +101,83 @@ export class Light {
|
|
|
99
101
|
*/
|
|
100
102
|
async pushLightOnChanges(): Promise<void> {
|
|
101
103
|
if (this.On) {
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
parameter: 'default',
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
await this.pushChanges(
|
|
104
|
+
const body = JSON.stringify({
|
|
105
|
+
'command': 'turnOn',
|
|
106
|
+
'parameter': 'default',
|
|
107
|
+
'commandType': 'command',
|
|
108
|
+
});
|
|
109
|
+
await this.pushChanges(body);
|
|
108
110
|
}
|
|
109
111
|
}
|
|
110
112
|
|
|
111
113
|
async pushLightOffChanges(): Promise<void> {
|
|
112
114
|
if (!this.On) {
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
parameter: 'default',
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
await this.pushChanges(
|
|
115
|
+
const body = JSON.stringify({
|
|
116
|
+
'command': 'turnOff',
|
|
117
|
+
'parameter': 'default',
|
|
118
|
+
'commandType': 'command',
|
|
119
|
+
});
|
|
120
|
+
await this.pushChanges(body);
|
|
119
121
|
}
|
|
120
122
|
}
|
|
121
123
|
|
|
122
124
|
async pushLightBrightnessUpChanges(): Promise<void> {
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
parameter: 'default',
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
await this.pushChanges(
|
|
125
|
+
const body = JSON.stringify({
|
|
126
|
+
'command': 'brightnessUp',
|
|
127
|
+
'parameter': 'default',
|
|
128
|
+
'commandType': 'command',
|
|
129
|
+
});
|
|
130
|
+
await this.pushChanges(body);
|
|
129
131
|
}
|
|
130
132
|
|
|
131
133
|
async pushLightBrightnessDownChanges(): Promise<void> {
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
parameter: 'default',
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
await this.pushChanges(
|
|
134
|
+
const body = JSON.stringify({
|
|
135
|
+
'command': 'brightnessDown',
|
|
136
|
+
'parameter': 'default',
|
|
137
|
+
'commandType': 'command',
|
|
138
|
+
});
|
|
139
|
+
await this.pushChanges(body);
|
|
138
140
|
}
|
|
139
141
|
|
|
140
|
-
async pushChanges(
|
|
142
|
+
async pushChanges(body): Promise<void> {
|
|
141
143
|
try {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
this.
|
|
144
|
+
// Make Push On request to the API
|
|
145
|
+
const t = Date.now();
|
|
146
|
+
const nonce = 'requestID';
|
|
147
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
148
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
149
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
150
|
+
.digest();
|
|
151
|
+
const sign = signTerm.toString('base64');
|
|
152
|
+
this.debugLog(`Light: ${this.accessory.displayName} sign: ${sign}`);
|
|
153
|
+
this.infoLog(`Light: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
154
|
+
const options = {
|
|
155
|
+
hostname: HostDomain,
|
|
156
|
+
port: 443,
|
|
157
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
158
|
+
method: 'POST',
|
|
159
|
+
headers: {
|
|
160
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
161
|
+
'sign': sign,
|
|
162
|
+
'nonce': nonce,
|
|
163
|
+
't': t,
|
|
164
|
+
'Content-Type': 'application/json',
|
|
165
|
+
'Content-Length': body.length,
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
const req = https.request(options, res => {
|
|
169
|
+
this.debugLog(`Light: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
170
|
+
this.statusCode({ res });
|
|
171
|
+
res.on('data', d => {
|
|
172
|
+
this.debugLog(`Light: ${this.accessory.displayName} d: ${d}`);
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
req.on('error', (e: any) => {
|
|
176
|
+
this.errorLog(`Light: ${this.accessory.displayName} error message: ${e.message}`);
|
|
177
|
+
});
|
|
178
|
+
req.write(body);
|
|
179
|
+
req.end();
|
|
180
|
+
this.debugLog(`Light: ${this.accessory.displayName} pushchanges: ${JSON.stringify(req)}`);
|
|
151
181
|
this.OnCached = this.On;
|
|
152
182
|
this.accessory.context.On = this.OnCached;
|
|
153
183
|
this.updateHomeKitCharacteristics();
|
|
@@ -162,8 +192,8 @@ export class Light {
|
|
|
162
192
|
}
|
|
163
193
|
}
|
|
164
194
|
|
|
165
|
-
async statusCode(
|
|
166
|
-
switch (
|
|
195
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
196
|
+
switch (res.statusCode) {
|
|
167
197
|
case 151:
|
|
168
198
|
this.errorLog(`Light: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
169
199
|
break;
|
|
@@ -182,7 +212,7 @@ export class Light {
|
|
|
182
212
|
case 190:
|
|
183
213
|
this.errorLog(
|
|
184
214
|
`Light: ${this.accessory.displayName} Device internal error due to device states not synchronized` +
|
|
185
|
-
` with server, Or command: ${JSON.stringify(
|
|
215
|
+
` with server, Or command: ${JSON.stringify(res)} format is invalid`,
|
|
186
216
|
);
|
|
187
217
|
break;
|
|
188
218
|
case 100:
|
package/src/irdevice/other.ts
CHANGED
|
@@ -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
|
/**
|
|
@@ -97,12 +99,12 @@ export class Others {
|
|
|
97
99
|
if (this.device.other) {
|
|
98
100
|
if (this.device.other.commandOn) {
|
|
99
101
|
if (!this.Active) {
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
parameter: 'default',
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
await this.pushChanges(
|
|
102
|
+
const body = JSON.stringify({
|
|
103
|
+
'command': `${this.device.other.commandOn}`,
|
|
104
|
+
'parameter': 'default',
|
|
105
|
+
'commandType': 'customize',
|
|
106
|
+
});
|
|
107
|
+
await this.pushChanges(body);
|
|
106
108
|
}
|
|
107
109
|
} else {
|
|
108
110
|
this.errorLog(`Other: ${this.accessory.displayName} On Command not set, commandOn: ${this.device.other.commandOn}`);
|
|
@@ -120,12 +122,12 @@ export class Others {
|
|
|
120
122
|
if (this.device.other) {
|
|
121
123
|
if (this.device.other.commandOff) {
|
|
122
124
|
if (this.Active) {
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
parameter: 'default',
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
await this.pushChanges(
|
|
125
|
+
const body = JSON.stringify({
|
|
126
|
+
'command': `${this.device.other.commandOff}`,
|
|
127
|
+
'parameter': 'default',
|
|
128
|
+
'commandType': 'customize',
|
|
129
|
+
});
|
|
130
|
+
await this.pushChanges(body);
|
|
129
131
|
}
|
|
130
132
|
} else {
|
|
131
133
|
this.errorLog(`Other: ${this.accessory.displayName} Off Command not set, commandOff: ${this.device.other.commandOff}`);
|
|
@@ -138,17 +140,45 @@ export class Others {
|
|
|
138
140
|
}
|
|
139
141
|
}
|
|
140
142
|
|
|
141
|
-
async pushChanges(
|
|
143
|
+
async pushChanges(body): Promise<void> {
|
|
142
144
|
try {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
this.
|
|
145
|
+
// Make Push On request to the API
|
|
146
|
+
const t = Date.now();
|
|
147
|
+
const nonce = 'requestID';
|
|
148
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
149
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
150
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
151
|
+
.digest();
|
|
152
|
+
const sign = signTerm.toString('base64');
|
|
153
|
+
this.debugLog(`Other: ${this.accessory.displayName} sign: ${sign}`);
|
|
154
|
+
this.infoLog(`Other: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
155
|
+
const options = {
|
|
156
|
+
hostname: HostDomain,
|
|
157
|
+
port: 443,
|
|
158
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
159
|
+
method: 'POST',
|
|
160
|
+
headers: {
|
|
161
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
162
|
+
'sign': sign,
|
|
163
|
+
'nonce': nonce,
|
|
164
|
+
't': t,
|
|
165
|
+
'Content-Type': 'application/json',
|
|
166
|
+
'Content-Length': body.length,
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
const req = https.request(options, res => {
|
|
170
|
+
this.debugLog(`Other: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
171
|
+
this.statusCode({ res });
|
|
172
|
+
res.on('data', d => {
|
|
173
|
+
this.debugLog(`Other: ${this.accessory.displayName} d: ${d}`);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
req.on('error', (e: any) => {
|
|
177
|
+
this.errorLog(`Other: ${this.accessory.displayName} error message: ${e.message}`);
|
|
178
|
+
});
|
|
179
|
+
req.write(body);
|
|
180
|
+
req.end();
|
|
181
|
+
this.debugLog(`Other: ${this.accessory.displayName} pushchanges: ${JSON.stringify(req)}`);
|
|
152
182
|
this.updateHomeKitCharacteristics();
|
|
153
183
|
} catch (e: any) {
|
|
154
184
|
this.errorLog(`Other: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
|
|
@@ -161,8 +191,8 @@ export class Others {
|
|
|
161
191
|
}
|
|
162
192
|
}
|
|
163
193
|
|
|
164
|
-
async statusCode(
|
|
165
|
-
switch (
|
|
194
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
195
|
+
switch (res.statusCode) {
|
|
166
196
|
case 151:
|
|
167
197
|
this.errorLog(`Other: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
168
198
|
break;
|
|
@@ -181,7 +211,7 @@ export class Others {
|
|
|
181
211
|
case 190:
|
|
182
212
|
this.errorLog(
|
|
183
213
|
`Other: ${this.accessory.displayName} Device internal error due to device states not synchronized` +
|
|
184
|
-
` with server, Or command: ${JSON.stringify(
|
|
214
|
+
` with server, Or command: ${JSON.stringify(res)} format is invalid`,
|
|
185
215
|
);
|
|
186
216
|
break;
|
|
187
217
|
case 100:
|
package/src/irdevice/tv.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import https from 'https';
|
|
2
|
+
import crypto from 'crypto';
|
|
3
|
+
import { IncomingMessage } from 'http';
|
|
2
4
|
import { SwitchBotPlatform } from '../platform';
|
|
3
5
|
import { CharacteristicValue, PlatformAccessory, Service } from 'homebridge';
|
|
4
|
-
import {
|
|
6
|
+
import { irdevice, irDevicesConfig, HostDomain, DevicePath } from '../settings';
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* Platform Accessory
|
|
@@ -19,7 +21,7 @@ export class TV {
|
|
|
19
21
|
ActiveIdentifier!: CharacteristicValue;
|
|
20
22
|
|
|
21
23
|
// Others
|
|
22
|
-
deviceStatus!:
|
|
24
|
+
deviceStatus!: any;
|
|
23
25
|
|
|
24
26
|
// Config
|
|
25
27
|
deviceLogging!: string;
|
|
@@ -235,116 +237,144 @@ export class TV {
|
|
|
235
237
|
*/
|
|
236
238
|
async pushTvOnChanges(): Promise<void> {
|
|
237
239
|
if (this.Active !== 1) {
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
parameter: 'default',
|
|
241
|
-
|
|
242
|
-
}
|
|
243
|
-
await this.pushTVChanges(
|
|
240
|
+
const body = JSON.stringify({
|
|
241
|
+
'command': 'turnOn',
|
|
242
|
+
'parameter': 'default',
|
|
243
|
+
'commandType': 'command',
|
|
244
|
+
});
|
|
245
|
+
await this.pushTVChanges(body);
|
|
244
246
|
}
|
|
245
247
|
}
|
|
246
248
|
|
|
247
249
|
async pushTvOffChanges(): Promise<void> {
|
|
248
|
-
const
|
|
249
|
-
|
|
250
|
-
parameter: 'default',
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
await this.pushTVChanges(
|
|
250
|
+
const body = JSON.stringify({
|
|
251
|
+
'command': 'turnOff',
|
|
252
|
+
'parameter': 'default',
|
|
253
|
+
'commandType': 'command',
|
|
254
|
+
});
|
|
255
|
+
await this.pushTVChanges(body);
|
|
254
256
|
}
|
|
255
257
|
|
|
256
258
|
async pushOkChanges(): Promise<void> {
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
parameter: 'default',
|
|
260
|
-
|
|
261
|
-
}
|
|
262
|
-
await this.pushTVChanges(
|
|
259
|
+
const body = JSON.stringify({
|
|
260
|
+
'command': 'Ok',
|
|
261
|
+
'parameter': 'default',
|
|
262
|
+
'commandType': 'command',
|
|
263
|
+
});
|
|
264
|
+
await this.pushTVChanges(body);
|
|
263
265
|
}
|
|
264
266
|
|
|
265
267
|
async pushBackChanges(): Promise<void> {
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
parameter: 'default',
|
|
269
|
-
|
|
270
|
-
}
|
|
271
|
-
await this.pushTVChanges(
|
|
268
|
+
const body = JSON.stringify({
|
|
269
|
+
'command': 'Back',
|
|
270
|
+
'parameter': 'default',
|
|
271
|
+
'commandType': 'command',
|
|
272
|
+
});
|
|
273
|
+
await this.pushTVChanges(body);
|
|
272
274
|
}
|
|
273
275
|
|
|
274
276
|
async pushMenuChanges(): Promise<void> {
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
parameter: 'default',
|
|
278
|
-
|
|
279
|
-
}
|
|
280
|
-
await this.pushTVChanges(
|
|
277
|
+
const body = JSON.stringify({
|
|
278
|
+
'command': 'Menu',
|
|
279
|
+
'parameter': 'default',
|
|
280
|
+
'commandType': 'command',
|
|
281
|
+
});
|
|
282
|
+
await this.pushTVChanges(body);
|
|
281
283
|
}
|
|
282
284
|
|
|
283
285
|
async pushUpChanges(): Promise<void> {
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
parameter: 'default',
|
|
287
|
-
|
|
288
|
-
}
|
|
289
|
-
await this.pushTVChanges(
|
|
286
|
+
const body = JSON.stringify({
|
|
287
|
+
'command': 'Up',
|
|
288
|
+
'parameter': 'default',
|
|
289
|
+
'commandType': 'command',
|
|
290
|
+
});
|
|
291
|
+
await this.pushTVChanges(body);
|
|
290
292
|
}
|
|
291
293
|
|
|
292
294
|
async pushDownChanges(): Promise<void> {
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
parameter: 'default',
|
|
296
|
-
|
|
297
|
-
}
|
|
298
|
-
await this.pushTVChanges(
|
|
295
|
+
const body = JSON.stringify({
|
|
296
|
+
'command': 'Down',
|
|
297
|
+
'parameter': 'default',
|
|
298
|
+
'commandType': 'command',
|
|
299
|
+
});
|
|
300
|
+
await this.pushTVChanges(body);
|
|
299
301
|
}
|
|
300
302
|
|
|
301
303
|
async pushRightChanges(): Promise<void> {
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
parameter: 'default',
|
|
305
|
-
|
|
306
|
-
}
|
|
307
|
-
await this.pushTVChanges(
|
|
304
|
+
const body = JSON.stringify({
|
|
305
|
+
'command': 'Right',
|
|
306
|
+
'parameter': 'default',
|
|
307
|
+
'commandType': 'command',
|
|
308
|
+
});
|
|
309
|
+
await this.pushTVChanges(body);
|
|
308
310
|
}
|
|
309
311
|
|
|
310
312
|
async pushLeftChanges(): Promise<void> {
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
parameter: 'default',
|
|
314
|
-
|
|
315
|
-
}
|
|
316
|
-
await this.pushTVChanges(
|
|
313
|
+
const body = JSON.stringify({
|
|
314
|
+
'command': 'Left',
|
|
315
|
+
'parameter': 'default',
|
|
316
|
+
'commandType': 'command',
|
|
317
|
+
});
|
|
318
|
+
await this.pushTVChanges(body);
|
|
317
319
|
}
|
|
318
320
|
|
|
319
321
|
async pushVolumeUpChanges(): Promise<void> {
|
|
320
|
-
const
|
|
321
|
-
|
|
322
|
-
parameter: 'default',
|
|
323
|
-
|
|
324
|
-
}
|
|
325
|
-
await this.pushTVChanges(
|
|
322
|
+
const body = JSON.stringify({
|
|
323
|
+
'command': 'volumeAdd',
|
|
324
|
+
'parameter': 'default',
|
|
325
|
+
'commandType': 'command',
|
|
326
|
+
});
|
|
327
|
+
await this.pushTVChanges(body);
|
|
326
328
|
}
|
|
327
329
|
|
|
328
330
|
async pushVolumeDownChanges(): Promise<void> {
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
parameter: 'default',
|
|
332
|
-
|
|
333
|
-
}
|
|
334
|
-
await this.pushTVChanges(
|
|
331
|
+
const body = JSON.stringify({
|
|
332
|
+
'command': 'volumeSub',
|
|
333
|
+
'parameter': 'default',
|
|
334
|
+
'commandType': 'command',
|
|
335
|
+
});
|
|
336
|
+
await this.pushTVChanges(body);
|
|
335
337
|
}
|
|
336
338
|
|
|
337
|
-
async pushTVChanges(
|
|
339
|
+
async pushTVChanges(body): Promise<void> {
|
|
338
340
|
try {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
this.
|
|
341
|
+
// Make Push On request to the API
|
|
342
|
+
const t = Date.now();
|
|
343
|
+
const nonce = 'requestID';
|
|
344
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
345
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
346
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
347
|
+
.digest();
|
|
348
|
+
const sign = signTerm.toString('base64');
|
|
349
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
350
|
+
this.infoLog(`${this.device.remoteType}: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
351
|
+
const options = {
|
|
352
|
+
hostname: HostDomain,
|
|
353
|
+
port: 443,
|
|
354
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
355
|
+
method: 'POST',
|
|
356
|
+
headers: {
|
|
357
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
358
|
+
'sign': sign,
|
|
359
|
+
'nonce': nonce,
|
|
360
|
+
't': t,
|
|
361
|
+
'Content-Type': 'application/json',
|
|
362
|
+
'Content-Length': body.length,
|
|
363
|
+
},
|
|
364
|
+
};
|
|
365
|
+
const req = https.request(options, res => {
|
|
366
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
367
|
+
this.statusCode({ res });
|
|
368
|
+
res.on('data', d => {
|
|
369
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} d: ${d}`);
|
|
370
|
+
});
|
|
371
|
+
});
|
|
372
|
+
req.on('error', (e: any) => {
|
|
373
|
+
this.errorLog(`${this.device.remoteType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
374
|
+
});
|
|
375
|
+
req.write(body);
|
|
376
|
+
req.end();
|
|
377
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} pushchanges: ${JSON.stringify(req)}`);
|
|
348
378
|
this.updateHomeKitCharacteristics();
|
|
349
379
|
} catch (e: any) {
|
|
350
380
|
this.errorLog(`${this.device.remoteType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
|
|
@@ -358,8 +388,8 @@ export class TV {
|
|
|
358
388
|
}
|
|
359
389
|
}
|
|
360
390
|
|
|
361
|
-
async statusCode(
|
|
362
|
-
switch (
|
|
391
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
392
|
+
switch (res.statusCode) {
|
|
363
393
|
case 151:
|
|
364
394
|
this.errorLog(`${this.device.remoteType}: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
365
395
|
break;
|
|
@@ -379,7 +409,7 @@ export class TV {
|
|
|
379
409
|
this.errorLog(
|
|
380
410
|
`${this.device.remoteType}: ` +
|
|
381
411
|
`${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
382
|
-
` Or command: ${JSON.stringify(
|
|
412
|
+
` Or command: ${JSON.stringify(res)} format is invalid`,
|
|
383
413
|
);
|
|
384
414
|
break;
|
|
385
415
|
case 100:
|
|
@@ -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
|
/**
|
|
@@ -84,37 +86,65 @@ export class VacuumCleaner {
|
|
|
84
86
|
*/
|
|
85
87
|
async pushOnChanges(): Promise<void> {
|
|
86
88
|
if (this.On) {
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
parameter: 'default',
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
await this.pushChanges(
|
|
89
|
+
const body = JSON.stringify({
|
|
90
|
+
'command': 'turnOn',
|
|
91
|
+
'parameter': 'default',
|
|
92
|
+
'commandType': 'command',
|
|
93
|
+
});
|
|
94
|
+
await this.pushChanges(body);
|
|
93
95
|
}
|
|
94
96
|
}
|
|
95
97
|
|
|
96
98
|
async pushOffChanges(): Promise<void> {
|
|
97
99
|
if (!this.On) {
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
parameter: 'default',
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
await this.pushChanges(
|
|
100
|
+
const body = JSON.stringify({
|
|
101
|
+
'command': 'turnOff',
|
|
102
|
+
'parameter': 'default',
|
|
103
|
+
'commandType': 'command',
|
|
104
|
+
});
|
|
105
|
+
await this.pushChanges(body);
|
|
104
106
|
}
|
|
105
107
|
}
|
|
106
108
|
|
|
107
|
-
async pushChanges(
|
|
109
|
+
async pushChanges(body): Promise<void> {
|
|
108
110
|
try {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
this.
|
|
111
|
+
// Make Push On request to the API
|
|
112
|
+
const t = Date.now();
|
|
113
|
+
const nonce = 'requestID';
|
|
114
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
115
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
116
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
117
|
+
.digest();
|
|
118
|
+
const sign = signTerm.toString('base64');
|
|
119
|
+
this.debugLog(`Vacuum Cleaner: ${this.accessory.displayName} sign: ${sign}`);
|
|
120
|
+
this.infoLog(`Vacuum Cleaner: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
121
|
+
const options = {
|
|
122
|
+
hostname: HostDomain,
|
|
123
|
+
port: 443,
|
|
124
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
125
|
+
method: 'POST',
|
|
126
|
+
headers: {
|
|
127
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
128
|
+
'sign': sign,
|
|
129
|
+
'nonce': nonce,
|
|
130
|
+
't': t,
|
|
131
|
+
'Content-Type': 'application/json',
|
|
132
|
+
'Content-Length': body.length,
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
const req = https.request(options, res => {
|
|
136
|
+
this.debugLog(`Vacuum Cleaner: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
137
|
+
this.statusCode({ res });
|
|
138
|
+
res.on('data', d => {
|
|
139
|
+
this.debugLog(`Vacuum Cleaner: ${this.accessory.displayName} d: ${d}`);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
req.on('error', (e: any) => {
|
|
143
|
+
this.errorLog(`Vacuum Cleaner: ${this.accessory.displayName} error message: ${e.message}`);
|
|
144
|
+
});
|
|
145
|
+
req.write(body);
|
|
146
|
+
req.end();
|
|
147
|
+
this.debugLog(`Vacuum Cleaner: ${this.accessory.displayName} pushchanges: ${JSON.stringify(req)}`);
|
|
118
148
|
this.OnCached = this.On;
|
|
119
149
|
this.accessory.context.On = this.OnCached;
|
|
120
150
|
this.updateHomeKitCharacteristics();
|
|
@@ -130,8 +160,8 @@ export class VacuumCleaner {
|
|
|
130
160
|
}
|
|
131
161
|
}
|
|
132
162
|
|
|
133
|
-
async statusCode(
|
|
134
|
-
switch (
|
|
163
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
164
|
+
switch (res.statusCode) {
|
|
135
165
|
case 151:
|
|
136
166
|
this.errorLog(`Vacuum Cleaner: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
137
167
|
break;
|
|
@@ -150,7 +180,7 @@ export class VacuumCleaner {
|
|
|
150
180
|
case 190:
|
|
151
181
|
this.errorLog(
|
|
152
182
|
`Vacuum Cleaner: ${this.accessory.displayName} Device internal error due to device states not synchronized` +
|
|
153
|
-
` with server, Or command: ${JSON.stringify(
|
|
183
|
+
` with server, Or command: ${JSON.stringify(res)} format is invalid`,
|
|
154
184
|
);
|
|
155
185
|
break;
|
|
156
186
|
case 100:
|