@switchbot/homebridge-switchbot 1.15.1-beta.0 → 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/config.schema.json +11 -4
- package/dist/device/bot.d.ts +8 -7
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +104 -28
- 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 +223 -58
- 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 +54 -11
- 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 +102 -28
- 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 +187 -66
- 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 +55 -12
- 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 +53 -10
- 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 +53 -13
- 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 +100 -24
- 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 +10 -6
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +211 -93
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +4 -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 +12 -12
- package/src/device/bot.ts +104 -37
- package/src/device/colorbulb.ts +227 -95
- package/src/device/contact.ts +53 -14
- package/src/device/curtain.ts +105 -38
- package/src/device/humidifier.ts +189 -84
- package/src/device/lock.ts +97 -30
- package/src/device/meter.ts +55 -16
- package/src/device/meterplus.ts +52 -13
- package/src/device/motion.ts +52 -16
- package/src/device/plug.ts +101 -33
- 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 +232 -107
- package/src/settings.ts +4 -25
package/src/irdevice/fan.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
|
|
@@ -21,7 +23,7 @@ export class Fan {
|
|
|
21
23
|
RotationDirection!: CharacteristicValue;
|
|
22
24
|
|
|
23
25
|
// Others
|
|
24
|
-
deviceStatus!:
|
|
26
|
+
deviceStatus!: any;
|
|
25
27
|
|
|
26
28
|
// Config
|
|
27
29
|
minStep?: number;
|
|
@@ -190,7 +192,7 @@ export class Fan {
|
|
|
190
192
|
commandType: 'command',
|
|
191
193
|
parameter: 'default',
|
|
192
194
|
command: 'turnOn',
|
|
193
|
-
}
|
|
195
|
+
};
|
|
194
196
|
await this.pushTVChanges(payload);
|
|
195
197
|
}
|
|
196
198
|
}
|
|
@@ -200,7 +202,7 @@ export class Fan {
|
|
|
200
202
|
commandType: 'command',
|
|
201
203
|
parameter: 'default',
|
|
202
204
|
command: 'turnOff',
|
|
203
|
-
}
|
|
205
|
+
};
|
|
204
206
|
await this.pushTVChanges(payload);
|
|
205
207
|
}
|
|
206
208
|
|
|
@@ -209,7 +211,7 @@ export class Fan {
|
|
|
209
211
|
commandType: 'command',
|
|
210
212
|
parameter: 'default',
|
|
211
213
|
command: 'highSpeed',
|
|
212
|
-
}
|
|
214
|
+
};
|
|
213
215
|
await this.pushTVChanges(payload);
|
|
214
216
|
}
|
|
215
217
|
|
|
@@ -218,7 +220,7 @@ export class Fan {
|
|
|
218
220
|
commandType: 'command',
|
|
219
221
|
parameter: 'default',
|
|
220
222
|
command: 'lowSpeed',
|
|
221
|
-
}
|
|
223
|
+
};
|
|
222
224
|
await this.pushTVChanges(payload);
|
|
223
225
|
}
|
|
224
226
|
|
|
@@ -227,11 +229,11 @@ export class Fan {
|
|
|
227
229
|
commandType: 'command',
|
|
228
230
|
parameter: 'default',
|
|
229
231
|
command: 'swing',
|
|
230
|
-
}
|
|
232
|
+
};
|
|
231
233
|
await this.pushTVChanges(payload);
|
|
232
234
|
}
|
|
233
235
|
|
|
234
|
-
async pushTVChanges(payload
|
|
236
|
+
async pushTVChanges(payload): Promise<void> {
|
|
235
237
|
try {
|
|
236
238
|
this.infoLog(
|
|
237
239
|
`Fan: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},` +
|
|
@@ -239,9 +241,42 @@ export class Fan {
|
|
|
239
241
|
);
|
|
240
242
|
|
|
241
243
|
// Make the API request
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
this.
|
|
244
|
+
const t = Date.now();
|
|
245
|
+
const nonce = 'requestID';
|
|
246
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
247
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
248
|
+
const sign = signTerm.toString('base64');
|
|
249
|
+
this.debugLog(`Fan: ${this.accessory.displayName} sign: ${sign}`);
|
|
250
|
+
const options = {
|
|
251
|
+
hostname: HostDomain,
|
|
252
|
+
port: 443,
|
|
253
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
254
|
+
method: 'POST',
|
|
255
|
+
headers: {
|
|
256
|
+
Authorization: this.platform.config.credentials?.token,
|
|
257
|
+
sign: sign,
|
|
258
|
+
nonce: nonce,
|
|
259
|
+
t: t,
|
|
260
|
+
'Content-Type': 'application/json',
|
|
261
|
+
},
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
const req = https.request(options, (res) => {
|
|
265
|
+
this.debugLog(`Fan: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
266
|
+
this.statusCode({ res });
|
|
267
|
+
res.on('data', (d) => {
|
|
268
|
+
this.debugLog(`an: ${this.accessory.displayName} d: ${d}`);
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
req.on('error', (error) => {
|
|
273
|
+
this.errorLog(`Fan: ${this.accessory.displayName} error: ${error}`);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
req.write(payload);
|
|
277
|
+
req.end();
|
|
278
|
+
|
|
279
|
+
this.debugLog(`Fan: ${this.accessory.displayName} pushchanges: ${JSON.stringify(req)}`);
|
|
245
280
|
this.updateHomeKitCharacteristics();
|
|
246
281
|
} catch (e: any) {
|
|
247
282
|
this.errorLog(`Fan: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
|
|
@@ -254,8 +289,8 @@ export class Fan {
|
|
|
254
289
|
}
|
|
255
290
|
}
|
|
256
291
|
|
|
257
|
-
async statusCode(
|
|
258
|
-
switch (
|
|
292
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
293
|
+
switch (res.statusCode) {
|
|
259
294
|
case 151:
|
|
260
295
|
this.errorLog(`Fan: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
261
296
|
break;
|
|
@@ -274,7 +309,7 @@ export class Fan {
|
|
|
274
309
|
case 190:
|
|
275
310
|
this.errorLog(
|
|
276
311
|
`Fan: ${this.accessory.displayName} Device internal error due to device states not synchronized` +
|
|
277
|
-
` with server, Or command: ${JSON.stringify(
|
|
312
|
+
` with server, Or command: ${JSON.stringify(res)} format is invalid`,
|
|
278
313
|
);
|
|
279
314
|
break;
|
|
280
315
|
case 100:
|
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
|
/**
|
|
@@ -103,7 +105,7 @@ export class Light {
|
|
|
103
105
|
commandType: 'command',
|
|
104
106
|
parameter: 'default',
|
|
105
107
|
command: 'turnOn',
|
|
106
|
-
}
|
|
108
|
+
};
|
|
107
109
|
await this.pushChanges(payload);
|
|
108
110
|
}
|
|
109
111
|
}
|
|
@@ -114,7 +116,7 @@ export class Light {
|
|
|
114
116
|
commandType: 'command',
|
|
115
117
|
parameter: 'default',
|
|
116
118
|
command: 'turnOff',
|
|
117
|
-
}
|
|
119
|
+
};
|
|
118
120
|
await this.pushChanges(payload);
|
|
119
121
|
}
|
|
120
122
|
}
|
|
@@ -124,7 +126,7 @@ export class Light {
|
|
|
124
126
|
commandType: 'command',
|
|
125
127
|
parameter: 'default',
|
|
126
128
|
command: 'brightnessUp',
|
|
127
|
-
}
|
|
129
|
+
};
|
|
128
130
|
await this.pushChanges(payload);
|
|
129
131
|
}
|
|
130
132
|
|
|
@@ -133,11 +135,11 @@ export class Light {
|
|
|
133
135
|
commandType: 'command',
|
|
134
136
|
parameter: 'default',
|
|
135
137
|
command: 'brightnessDown',
|
|
136
|
-
}
|
|
138
|
+
};
|
|
137
139
|
await this.pushChanges(payload);
|
|
138
140
|
}
|
|
139
141
|
|
|
140
|
-
async pushChanges(payload
|
|
142
|
+
async pushChanges(payload): Promise<void> {
|
|
141
143
|
try {
|
|
142
144
|
this.infoLog(
|
|
143
145
|
`Light: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},` +
|
|
@@ -145,9 +147,42 @@ export class Light {
|
|
|
145
147
|
);
|
|
146
148
|
|
|
147
149
|
// Make the API request
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
this.
|
|
150
|
+
const t = Date.now();
|
|
151
|
+
const nonce = 'requestID';
|
|
152
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
153
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
154
|
+
const sign = signTerm.toString('base64');
|
|
155
|
+
this.debugLog(`Light: ${this.accessory.displayName} sign: ${sign}`);
|
|
156
|
+
const options = {
|
|
157
|
+
hostname: HostDomain,
|
|
158
|
+
port: 443,
|
|
159
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
160
|
+
method: 'POST',
|
|
161
|
+
headers: {
|
|
162
|
+
Authorization: this.platform.config.credentials?.token,
|
|
163
|
+
sign: sign,
|
|
164
|
+
nonce: nonce,
|
|
165
|
+
t: t,
|
|
166
|
+
'Content-Type': 'application/json',
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const req = https.request(options, (res) => {
|
|
171
|
+
this.debugLog(`Light: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
172
|
+
this.statusCode({ res });
|
|
173
|
+
res.on('data', (d) => {
|
|
174
|
+
this.debugLog(`Light: ${this.accessory.displayName} d: ${d}`);
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
req.on('error', (error) => {
|
|
179
|
+
this.errorLog(`Light: ${this.accessory.displayName} error: ${error}`);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
req.write(payload);
|
|
183
|
+
req.end();
|
|
184
|
+
|
|
185
|
+
this.debugLog(`Light: ${this.accessory.displayName} pushchanges: ${JSON.stringify(req)}`);
|
|
151
186
|
this.OnCached = this.On;
|
|
152
187
|
this.accessory.context.On = this.OnCached;
|
|
153
188
|
this.updateHomeKitCharacteristics();
|
|
@@ -162,8 +197,8 @@ export class Light {
|
|
|
162
197
|
}
|
|
163
198
|
}
|
|
164
199
|
|
|
165
|
-
async statusCode(
|
|
166
|
-
switch (
|
|
200
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
201
|
+
switch (res.statusCode) {
|
|
167
202
|
case 151:
|
|
168
203
|
this.errorLog(`Light: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
169
204
|
break;
|
|
@@ -182,7 +217,7 @@ export class Light {
|
|
|
182
217
|
case 190:
|
|
183
218
|
this.errorLog(
|
|
184
219
|
`Light: ${this.accessory.displayName} Device internal error due to device states not synchronized` +
|
|
185
|
-
` with server, Or command: ${JSON.stringify(
|
|
220
|
+
` with server, Or command: ${JSON.stringify(res)} format is invalid`,
|
|
186
221
|
);
|
|
187
222
|
break;
|
|
188
223
|
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
|
/**
|
|
@@ -101,7 +103,7 @@ export class Others {
|
|
|
101
103
|
commandType: 'customize',
|
|
102
104
|
parameter: 'default',
|
|
103
105
|
command: `${this.device.other.commandOn}`,
|
|
104
|
-
}
|
|
106
|
+
};
|
|
105
107
|
await this.pushChanges(payload);
|
|
106
108
|
}
|
|
107
109
|
} else {
|
|
@@ -124,7 +126,7 @@ export class Others {
|
|
|
124
126
|
commandType: 'customize',
|
|
125
127
|
parameter: 'default',
|
|
126
128
|
command: `${this.device.other.commandOff}`,
|
|
127
|
-
}
|
|
129
|
+
};
|
|
128
130
|
await this.pushChanges(payload);
|
|
129
131
|
}
|
|
130
132
|
} else {
|
|
@@ -138,7 +140,7 @@ export class Others {
|
|
|
138
140
|
}
|
|
139
141
|
}
|
|
140
142
|
|
|
141
|
-
async pushChanges(payload
|
|
143
|
+
async pushChanges(payload): Promise<void> {
|
|
142
144
|
try {
|
|
143
145
|
this.infoLog(
|
|
144
146
|
`Other: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},` +
|
|
@@ -146,9 +148,42 @@ export class Others {
|
|
|
146
148
|
);
|
|
147
149
|
|
|
148
150
|
// Make the API request
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
this.
|
|
151
|
+
const t = Date.now();
|
|
152
|
+
const nonce = 'requestID';
|
|
153
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
154
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
155
|
+
const sign = signTerm.toString('base64');
|
|
156
|
+
this.debugLog(`Other: ${this.accessory.displayName} sign: ${sign}`);
|
|
157
|
+
const options = {
|
|
158
|
+
hostname: HostDomain,
|
|
159
|
+
port: 443,
|
|
160
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
161
|
+
method: 'POST',
|
|
162
|
+
headers: {
|
|
163
|
+
Authorization: this.platform.config.credentials?.token,
|
|
164
|
+
sign: sign,
|
|
165
|
+
nonce: nonce,
|
|
166
|
+
t: t,
|
|
167
|
+
'Content-Type': 'application/json',
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const req = https.request(options, (res) => {
|
|
172
|
+
this.debugLog(`Other: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
173
|
+
this.statusCode({ res });
|
|
174
|
+
res.on('data', (d) => {
|
|
175
|
+
this.debugLog(`Other: ${this.accessory.displayName} d: ${d}`);
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
req.on('error', (error) => {
|
|
180
|
+
this.errorLog(`Other: ${this.accessory.displayName} error: ${error}`);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
req.write(payload);
|
|
184
|
+
req.end();
|
|
185
|
+
|
|
186
|
+
this.debugLog(`Other: ${this.accessory.displayName} pushchanges: ${JSON.stringify(req)}`);
|
|
152
187
|
this.updateHomeKitCharacteristics();
|
|
153
188
|
} catch (e: any) {
|
|
154
189
|
this.errorLog(`Other: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
|
|
@@ -161,8 +196,8 @@ export class Others {
|
|
|
161
196
|
}
|
|
162
197
|
}
|
|
163
198
|
|
|
164
|
-
async statusCode(
|
|
165
|
-
switch (
|
|
199
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
200
|
+
switch (res.statusCode) {
|
|
166
201
|
case 151:
|
|
167
202
|
this.errorLog(`Other: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
168
203
|
break;
|
|
@@ -181,7 +216,7 @@ export class Others {
|
|
|
181
216
|
case 190:
|
|
182
217
|
this.errorLog(
|
|
183
218
|
`Other: ${this.accessory.displayName} Device internal error due to device states not synchronized` +
|
|
184
|
-
` with server, Or command: ${JSON.stringify(
|
|
219
|
+
` with server, Or command: ${JSON.stringify(res)} format is invalid`,
|
|
185
220
|
);
|
|
186
221
|
break;
|
|
187
222
|
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;
|
|
@@ -239,7 +241,7 @@ export class TV {
|
|
|
239
241
|
commandType: 'command',
|
|
240
242
|
parameter: 'default',
|
|
241
243
|
command: 'turnOn',
|
|
242
|
-
}
|
|
244
|
+
};
|
|
243
245
|
await this.pushTVChanges(payload);
|
|
244
246
|
}
|
|
245
247
|
}
|
|
@@ -249,7 +251,7 @@ export class TV {
|
|
|
249
251
|
commandType: 'command',
|
|
250
252
|
parameter: 'default',
|
|
251
253
|
command: 'turnOff',
|
|
252
|
-
}
|
|
254
|
+
};
|
|
253
255
|
await this.pushTVChanges(payload);
|
|
254
256
|
}
|
|
255
257
|
|
|
@@ -258,7 +260,7 @@ export class TV {
|
|
|
258
260
|
commandType: 'command',
|
|
259
261
|
parameter: 'default',
|
|
260
262
|
command: 'Ok',
|
|
261
|
-
}
|
|
263
|
+
};
|
|
262
264
|
await this.pushTVChanges(payload);
|
|
263
265
|
}
|
|
264
266
|
|
|
@@ -267,7 +269,7 @@ export class TV {
|
|
|
267
269
|
commandType: 'command',
|
|
268
270
|
parameter: 'default',
|
|
269
271
|
command: 'Back',
|
|
270
|
-
}
|
|
272
|
+
};
|
|
271
273
|
await this.pushTVChanges(payload);
|
|
272
274
|
}
|
|
273
275
|
|
|
@@ -276,7 +278,7 @@ export class TV {
|
|
|
276
278
|
commandType: 'command',
|
|
277
279
|
parameter: 'default',
|
|
278
280
|
command: 'Menu',
|
|
279
|
-
}
|
|
281
|
+
};
|
|
280
282
|
await this.pushTVChanges(payload);
|
|
281
283
|
}
|
|
282
284
|
|
|
@@ -285,7 +287,7 @@ export class TV {
|
|
|
285
287
|
commandType: 'command',
|
|
286
288
|
parameter: 'default',
|
|
287
289
|
command: 'Up',
|
|
288
|
-
}
|
|
290
|
+
};
|
|
289
291
|
await this.pushTVChanges(payload);
|
|
290
292
|
}
|
|
291
293
|
|
|
@@ -294,7 +296,7 @@ export class TV {
|
|
|
294
296
|
commandType: 'command',
|
|
295
297
|
parameter: 'default',
|
|
296
298
|
command: 'Down',
|
|
297
|
-
}
|
|
299
|
+
};
|
|
298
300
|
await this.pushTVChanges(payload);
|
|
299
301
|
}
|
|
300
302
|
|
|
@@ -303,7 +305,7 @@ export class TV {
|
|
|
303
305
|
commandType: 'command',
|
|
304
306
|
parameter: 'default',
|
|
305
307
|
command: 'Right',
|
|
306
|
-
}
|
|
308
|
+
};
|
|
307
309
|
await this.pushTVChanges(payload);
|
|
308
310
|
}
|
|
309
311
|
|
|
@@ -312,7 +314,7 @@ export class TV {
|
|
|
312
314
|
commandType: 'command',
|
|
313
315
|
parameter: 'default',
|
|
314
316
|
command: 'Left',
|
|
315
|
-
}
|
|
317
|
+
};
|
|
316
318
|
await this.pushTVChanges(payload);
|
|
317
319
|
}
|
|
318
320
|
|
|
@@ -321,7 +323,7 @@ export class TV {
|
|
|
321
323
|
commandType: 'command',
|
|
322
324
|
parameter: 'default',
|
|
323
325
|
command: 'volumeAdd',
|
|
324
|
-
}
|
|
326
|
+
};
|
|
325
327
|
await this.pushTVChanges(payload);
|
|
326
328
|
}
|
|
327
329
|
|
|
@@ -330,11 +332,11 @@ export class TV {
|
|
|
330
332
|
commandType: 'command',
|
|
331
333
|
parameter: 'default',
|
|
332
334
|
command: 'volumeSub',
|
|
333
|
-
}
|
|
335
|
+
};
|
|
334
336
|
await this.pushTVChanges(payload);
|
|
335
337
|
}
|
|
336
338
|
|
|
337
|
-
async pushTVChanges(payload
|
|
339
|
+
async pushTVChanges(payload): Promise<void> {
|
|
338
340
|
try {
|
|
339
341
|
this.infoLog(
|
|
340
342
|
`${this.device.remoteType}: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},` +
|
|
@@ -342,9 +344,42 @@ export class TV {
|
|
|
342
344
|
);
|
|
343
345
|
|
|
344
346
|
// Make the API request
|
|
345
|
-
const
|
|
346
|
-
|
|
347
|
-
this.
|
|
347
|
+
const t = Date.now();
|
|
348
|
+
const nonce = 'requestID';
|
|
349
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
350
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
351
|
+
const sign = signTerm.toString('base64');
|
|
352
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
353
|
+
const options = {
|
|
354
|
+
hostname: HostDomain,
|
|
355
|
+
port: 443,
|
|
356
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
357
|
+
method: 'POST',
|
|
358
|
+
headers: {
|
|
359
|
+
Authorization: this.platform.config.credentials?.token,
|
|
360
|
+
sign: sign,
|
|
361
|
+
nonce: nonce,
|
|
362
|
+
t: t,
|
|
363
|
+
'Content-Type': 'application/json',
|
|
364
|
+
},
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
const req = https.request(options, (res) => {
|
|
368
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
369
|
+
this.statusCode({ res });
|
|
370
|
+
res.on('data', (d) => {
|
|
371
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} d: ${d}`);
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
req.on('error', (error) => {
|
|
376
|
+
this.errorLog(`${this.device.remoteType}: ${this.accessory.displayName} error: ${error}`);
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
req.write(payload);
|
|
380
|
+
req.end();
|
|
381
|
+
|
|
382
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} pushchanges: ${JSON.stringify(req)}`);
|
|
348
383
|
this.updateHomeKitCharacteristics();
|
|
349
384
|
} catch (e: any) {
|
|
350
385
|
this.errorLog(`${this.device.remoteType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
|
|
@@ -358,8 +393,8 @@ export class TV {
|
|
|
358
393
|
}
|
|
359
394
|
}
|
|
360
395
|
|
|
361
|
-
async statusCode(
|
|
362
|
-
switch (
|
|
396
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
397
|
+
switch (res.statusCode) {
|
|
363
398
|
case 151:
|
|
364
399
|
this.errorLog(`${this.device.remoteType}: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
365
400
|
break;
|
|
@@ -379,7 +414,7 @@ export class TV {
|
|
|
379
414
|
this.errorLog(
|
|
380
415
|
`${this.device.remoteType}: ` +
|
|
381
416
|
`${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
382
|
-
` Or command: ${JSON.stringify(
|
|
417
|
+
` Or command: ${JSON.stringify(res)} format is invalid`,
|
|
383
418
|
);
|
|
384
419
|
break;
|
|
385
420
|
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
|
/**
|
|
@@ -88,7 +90,7 @@ export class VacuumCleaner {
|
|
|
88
90
|
commandType: 'command',
|
|
89
91
|
parameter: 'default',
|
|
90
92
|
command: 'turnOn',
|
|
91
|
-
}
|
|
93
|
+
};
|
|
92
94
|
await this.pushChanges(payload);
|
|
93
95
|
}
|
|
94
96
|
}
|
|
@@ -99,12 +101,12 @@ export class VacuumCleaner {
|
|
|
99
101
|
commandType: 'command',
|
|
100
102
|
parameter: 'default',
|
|
101
103
|
command: 'turnOff',
|
|
102
|
-
}
|
|
104
|
+
};
|
|
103
105
|
await this.pushChanges(payload);
|
|
104
106
|
}
|
|
105
107
|
}
|
|
106
108
|
|
|
107
|
-
async pushChanges(payload
|
|
109
|
+
async pushChanges(payload): Promise<void> {
|
|
108
110
|
try {
|
|
109
111
|
this.infoLog(
|
|
110
112
|
`Vacuum Cleaner: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},` +
|
|
@@ -112,9 +114,42 @@ export class VacuumCleaner {
|
|
|
112
114
|
);
|
|
113
115
|
|
|
114
116
|
// Make the API request
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
this.
|
|
117
|
+
const t = Date.now();
|
|
118
|
+
const nonce = 'requestID';
|
|
119
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
120
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret).update(Buffer.from(data, 'utf-8')).digest();
|
|
121
|
+
const sign = signTerm.toString('base64');
|
|
122
|
+
this.debugLog(`Vacuum Cleaner: ${this.accessory.displayName} sign: ${sign}`);
|
|
123
|
+
const options = {
|
|
124
|
+
hostname: HostDomain,
|
|
125
|
+
port: 443,
|
|
126
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
127
|
+
method: 'POST',
|
|
128
|
+
headers: {
|
|
129
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
130
|
+
'sign': sign,
|
|
131
|
+
'nonce': nonce,
|
|
132
|
+
't': t,
|
|
133
|
+
'Content-Type': 'application/json',
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const req = https.request(options, (res) => {
|
|
138
|
+
this.debugLog(`Vacuum Cleaner: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
139
|
+
this.statusCode({ res });
|
|
140
|
+
res.on('data', (d) => {
|
|
141
|
+
this.debugLog(`Vacuum Cleaner: ${this.accessory.displayName} d: ${d}`);
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
req.on('error', (error) => {
|
|
146
|
+
this.errorLog(`Vacuum Cleaner: ${this.accessory.displayName} error: ${error}`);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
req.write(payload);
|
|
150
|
+
req.end();
|
|
151
|
+
|
|
152
|
+
this.debugLog(`Vacuum Cleaner: ${this.accessory.displayName} pushchanges: ${JSON.stringify(req)}`);
|
|
118
153
|
this.OnCached = this.On;
|
|
119
154
|
this.accessory.context.On = this.OnCached;
|
|
120
155
|
this.updateHomeKitCharacteristics();
|
|
@@ -130,8 +165,8 @@ export class VacuumCleaner {
|
|
|
130
165
|
}
|
|
131
166
|
}
|
|
132
167
|
|
|
133
|
-
async statusCode(
|
|
134
|
-
switch (
|
|
168
|
+
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
169
|
+
switch (res.statusCode) {
|
|
135
170
|
case 151:
|
|
136
171
|
this.errorLog(`Vacuum Cleaner: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
137
172
|
break;
|
|
@@ -150,7 +185,7 @@ export class VacuumCleaner {
|
|
|
150
185
|
case 190:
|
|
151
186
|
this.errorLog(
|
|
152
187
|
`Vacuum Cleaner: ${this.accessory.displayName} Device internal error due to device states not synchronized` +
|
|
153
|
-
` with server, Or command: ${JSON.stringify(
|
|
188
|
+
` with server, Or command: ${JSON.stringify(res)} format is invalid`,
|
|
154
189
|
);
|
|
155
190
|
break;
|
|
156
191
|
case 100:
|