@switchbot/homebridge-switchbot 2.0.0-beta.18 → 2.0.0-beta.19
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/CHANGELOG.md +1 -1
- package/config.schema.json +11 -2
- package/dist/device/bot.d.ts +2 -0
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +201 -163
- package/dist/device/bot.js.map +1 -1
- package/dist/device/colorbulb.d.ts +2 -0
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +250 -218
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts +2 -0
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +85 -66
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts +2 -0
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +166 -136
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +126 -115
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/lock.d.ts +2 -0
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +156 -130
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +2 -0
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +85 -64
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +2 -0
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +78 -59
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts +2 -0
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +76 -57
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +2 -0
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +133 -107
- package/dist/device/plug.js.map +1 -1
- package/dist/device/striplight.d.ts +2 -0
- package/dist/device/striplight.d.ts.map +1 -1
- package/dist/device/striplight.js +224 -195
- package/dist/device/striplight.js.map +1 -1
- package/dist/irdevice/airconditioner.d.ts +2 -0
- package/dist/irdevice/airconditioner.d.ts.map +1 -1
- package/dist/irdevice/airconditioner.js +127 -105
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts +2 -0
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +83 -66
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts +8 -6
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +83 -68
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts +7 -5
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +90 -75
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/light.d.ts +8 -6
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +83 -68
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts +8 -6
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +93 -78
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts +8 -6
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +68 -52
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts +8 -6
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +83 -69
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts +2 -0
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +75 -60
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/settings.d.ts +12 -11
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js.map +1 -1
- package/package.json +1 -1
- package/src/device/bot.ts +200 -163
- package/src/device/colorbulb.ts +252 -221
- package/src/device/contact.ts +85 -66
- package/src/device/curtain.ts +165 -136
- package/src/device/humidifier.ts +126 -115
- package/src/device/lock.ts +156 -131
- package/src/device/meter.ts +85 -64
- package/src/device/meterplus.ts +78 -59
- package/src/device/motion.ts +76 -57
- package/src/device/plug.ts +132 -107
- package/src/device/striplight.ts +226 -198
- package/src/irdevice/airconditioner.ts +126 -103
- package/src/irdevice/airpurifier.ts +84 -66
- package/src/irdevice/camera.ts +84 -68
- package/src/irdevice/fan.ts +91 -75
- package/src/irdevice/light.ts +84 -68
- package/src/irdevice/other.ts +94 -78
- package/src/irdevice/tv.ts +69 -53
- package/src/irdevice/vacuumcleaner.ts +83 -68
- package/src/irdevice/waterheater.ts +76 -60
- package/src/settings.ts +12 -11
package/src/irdevice/fan.ts
CHANGED
|
@@ -31,6 +31,7 @@ export class Fan {
|
|
|
31
31
|
minValue?: number;
|
|
32
32
|
maxValue?: number;
|
|
33
33
|
deviceLogging!: string;
|
|
34
|
+
OpenAPI?: boolean;
|
|
34
35
|
|
|
35
36
|
constructor(private readonly platform: SwitchBotPlatform, private accessory: PlatformAccessory, public device: irdevice & irDevicesConfig) {
|
|
36
37
|
// default placeholders
|
|
@@ -93,11 +94,11 @@ export class Fan {
|
|
|
93
94
|
} else if (this.fanService.testCharacteristic(this.platform.Characteristic.RotationSpeed) && !device.irfan?.swing_mode) {
|
|
94
95
|
const characteristic = this.fanService.getCharacteristic(this.platform.Characteristic.RotationSpeed);
|
|
95
96
|
this.fanService.removeCharacteristic(characteristic);
|
|
96
|
-
this.debugLog(
|
|
97
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Rotation Speed Characteristic was removed.`);
|
|
97
98
|
} else {
|
|
98
99
|
// eslint-disable-next-line max-len
|
|
99
100
|
this.debugLog(
|
|
100
|
-
|
|
101
|
+
`${this.device.remoteType}: ${this.accessory.displayName} RotationSpeed Characteristic was not removed/added, ` +
|
|
101
102
|
`Clear Cache on ${this.accessory.displayName} to remove Chracteristic`,
|
|
102
103
|
);
|
|
103
104
|
}
|
|
@@ -108,18 +109,18 @@ export class Fan {
|
|
|
108
109
|
} else if (this.fanService.testCharacteristic(this.platform.Characteristic.SwingMode) && !device.irfan?.swing_mode) {
|
|
109
110
|
const characteristic = this.fanService.getCharacteristic(this.platform.Characteristic.SwingMode);
|
|
110
111
|
this.fanService.removeCharacteristic(characteristic);
|
|
111
|
-
this.debugLog(
|
|
112
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Swing Mode Characteristic was removed.`);
|
|
112
113
|
} else {
|
|
113
114
|
// eslint-disable-next-line max-len
|
|
114
115
|
this.debugLog(
|
|
115
|
-
|
|
116
|
+
`${this.device.remoteType}: ${this.accessory.displayName} Swing Mode Characteristic was not removed/added, ` +
|
|
116
117
|
`Clear Cache on ${this.accessory.displayName} To Remove Chracteristic`,
|
|
117
118
|
);
|
|
118
119
|
}
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
async SwingModeSet(value: CharacteristicValue): Promise<void> {
|
|
122
|
-
this.debugLog(
|
|
123
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} SwingMode: ${value}`);
|
|
123
124
|
if (value > this.SwingMode) {
|
|
124
125
|
this.SwingMode = 1;
|
|
125
126
|
await this.pushFanOnChanges();
|
|
@@ -134,27 +135,27 @@ export class Fan {
|
|
|
134
135
|
|
|
135
136
|
async updateHomeKitCharacteristics(): Promise<void> {
|
|
136
137
|
if (this.Active === undefined) {
|
|
137
|
-
this.debugLog(
|
|
138
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Active: ${this.Active}`);
|
|
138
139
|
} else {
|
|
139
140
|
this.fanService?.updateCharacteristic(this.platform.Characteristic.Active, this.Active);
|
|
140
|
-
this.debugLog(
|
|
141
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} updateCharacteristic Active: ${this.Active}`);
|
|
141
142
|
}
|
|
142
143
|
if (this.SwingMode === undefined) {
|
|
143
|
-
this.debugLog(
|
|
144
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} SwingMode: ${this.SwingMode}`);
|
|
144
145
|
} else {
|
|
145
146
|
this.fanService?.updateCharacteristic(this.platform.Characteristic.SwingMode, this.SwingMode);
|
|
146
|
-
this.debugLog(
|
|
147
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} updateCharacteristic SwingMode: ${this.SwingMode}`);
|
|
147
148
|
}
|
|
148
149
|
if (this.RotationSpeed === undefined) {
|
|
149
|
-
this.debugLog(
|
|
150
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} RotationSpeed: ${this.RotationSpeed}`);
|
|
150
151
|
} else {
|
|
151
152
|
this.fanService?.updateCharacteristic(this.platform.Characteristic.RotationSpeed, this.RotationSpeed);
|
|
152
|
-
this.debugLog(
|
|
153
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} updateCharacteristic RotationSpeed: ${this.RotationSpeed}`);
|
|
153
154
|
}
|
|
154
155
|
}
|
|
155
156
|
|
|
156
157
|
async RotationSpeedSet(value: CharacteristicValue): Promise<void> {
|
|
157
|
-
this.debugLog(
|
|
158
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} RotationSpeed: ${value}`);
|
|
158
159
|
if (value > this.RotationSpeed) {
|
|
159
160
|
this.RotationSpeed = 1;
|
|
160
161
|
this.pushFanSpeedUpChanges();
|
|
@@ -167,7 +168,7 @@ export class Fan {
|
|
|
167
168
|
}
|
|
168
169
|
|
|
169
170
|
async ActiveSet(value: CharacteristicValue): Promise<void> {
|
|
170
|
-
this.debugLog(
|
|
171
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Active: ${value}`);
|
|
171
172
|
if (value === this.platform.Characteristic.Active.INACTIVE) {
|
|
172
173
|
this.pushFanOffChanges();
|
|
173
174
|
} else {
|
|
@@ -181,11 +182,11 @@ export class Fan {
|
|
|
181
182
|
/**
|
|
182
183
|
* Pushes the requested changes to the SwitchBot API
|
|
183
184
|
* deviceType commandType Command command parameter Description
|
|
184
|
-
* Fan
|
|
185
|
-
* Fan
|
|
186
|
-
* Fan
|
|
187
|
-
* Fan
|
|
188
|
-
* Fan
|
|
185
|
+
* Fan - "command" "swing" "default" = swing
|
|
186
|
+
* Fan - "command" "timer" "default" = timer
|
|
187
|
+
* Fan - "command" "lowSpeed" "default" = fan speed to low
|
|
188
|
+
* Fan - "command" "middleSpeed" "default" = fan speed to medium
|
|
189
|
+
* Fan - "command" "highSpeed" "default" = fan speed to high
|
|
189
190
|
*/
|
|
190
191
|
async pushFanOnChanges(): Promise<void> {
|
|
191
192
|
if (this.Active !== 1) {
|
|
@@ -235,84 +236,87 @@ export class Fan {
|
|
|
235
236
|
}
|
|
236
237
|
|
|
237
238
|
async pushTVChanges(body): Promise<void> {
|
|
238
|
-
|
|
239
|
+
if (this.OpenAPI) {
|
|
240
|
+
try {
|
|
239
241
|
// Make Push On request to the API
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
242
|
+
const t = Date.now();
|
|
243
|
+
const nonce = 'requestID';
|
|
244
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
245
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
246
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
247
|
+
.digest();
|
|
248
|
+
const sign = signTerm.toString('base64');
|
|
249
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
250
|
+
this.infoLog(`${this.device.remoteType}: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
251
|
+
const options = {
|
|
252
|
+
hostname: HostDomain,
|
|
253
|
+
port: 443,
|
|
254
|
+
path: `${DevicePath}/${this.device.deviceId}/commands`,
|
|
255
|
+
method: 'POST',
|
|
256
|
+
headers: {
|
|
257
|
+
'Authorization': this.platform.config.credentials?.token,
|
|
258
|
+
'sign': sign,
|
|
259
|
+
'nonce': nonce,
|
|
260
|
+
't': t,
|
|
261
|
+
'Content-Type': 'application/json',
|
|
262
|
+
'Content-Length': body.length,
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
const req = https.request(options, res => {
|
|
266
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
267
|
+
this.statusCode({ res });
|
|
268
|
+
res.on('data', d => {
|
|
269
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} d: ${d}`);
|
|
270
|
+
});
|
|
268
271
|
});
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
272
|
+
req.on('error', (e: any) => {
|
|
273
|
+
this.errorLog(`${this.device.remoteType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
274
|
+
});
|
|
275
|
+
req.write(body);
|
|
276
|
+
req.end();
|
|
277
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} pushchanges: ${superStringify(req)}`);
|
|
278
|
+
this.updateHomeKitCharacteristics();
|
|
279
|
+
} catch (e: any) {
|
|
280
|
+
this.errorLog(`${this.device.remoteType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
|
|
281
|
+
if (this.deviceLogging.includes('debug')) {
|
|
282
|
+
this.errorLog(
|
|
283
|
+
`${this.device.remoteType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
|
|
284
|
+
+ ` Error Message: ${superStringify(e.message)}`,
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
this.apiError(e);
|
|
283
288
|
}
|
|
284
|
-
this.apiError(e);
|
|
285
289
|
}
|
|
286
290
|
}
|
|
287
291
|
|
|
288
292
|
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
289
293
|
switch (res.statusCode) {
|
|
290
294
|
case 151:
|
|
291
|
-
this.errorLog(
|
|
295
|
+
this.errorLog(`${this.device.remoteType}: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
292
296
|
break;
|
|
293
297
|
case 152:
|
|
294
|
-
this.errorLog(
|
|
298
|
+
this.errorLog(`${this.device.remoteType}: ${this.accessory.displayName} Device not found.`);
|
|
295
299
|
break;
|
|
296
300
|
case 160:
|
|
297
|
-
this.errorLog(
|
|
301
|
+
this.errorLog(`${this.device.remoteType}: ${this.accessory.displayName} Command is not supported.`);
|
|
298
302
|
break;
|
|
299
303
|
case 161:
|
|
300
|
-
this.errorLog(
|
|
304
|
+
this.errorLog(`${this.device.remoteType}: ${this.accessory.displayName} Device is offline.`);
|
|
301
305
|
break;
|
|
302
306
|
case 171:
|
|
303
|
-
this.errorLog(
|
|
307
|
+
this.errorLog(`${this.device.remoteType}: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
|
|
304
308
|
break;
|
|
305
309
|
case 190:
|
|
306
310
|
this.errorLog(
|
|
307
|
-
|
|
311
|
+
`${this.device.remoteType}: ${this.accessory.displayName} Device internal error due to device states not synchronized` +
|
|
308
312
|
` with server, Or command: ${superStringify(res)} format is invalid`,
|
|
309
313
|
);
|
|
310
314
|
break;
|
|
311
315
|
case 100:
|
|
312
|
-
this.debugLog(
|
|
316
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Command successfully sent.`);
|
|
313
317
|
break;
|
|
314
318
|
default:
|
|
315
|
-
this.debugLog(
|
|
319
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Unknown statusCode.`);
|
|
316
320
|
}
|
|
317
321
|
}
|
|
318
322
|
|
|
@@ -323,6 +327,15 @@ export class Fan {
|
|
|
323
327
|
//throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
|
|
324
328
|
}
|
|
325
329
|
|
|
330
|
+
async openAPI() {
|
|
331
|
+
if (!this.device.openAPI) {
|
|
332
|
+
this.OpenAPI = true;
|
|
333
|
+
} else {
|
|
334
|
+
this.OpenAPI = this.device.openAPI;
|
|
335
|
+
}
|
|
336
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Using OpenAPI: ${this.OpenAPI}`);
|
|
337
|
+
}
|
|
338
|
+
|
|
326
339
|
async config(device: irdevice & irDevicesConfig): Promise<void> {
|
|
327
340
|
let config = {};
|
|
328
341
|
if (device.irfan) {
|
|
@@ -331,24 +344,27 @@ export class Fan {
|
|
|
331
344
|
if (device.logging !== undefined) {
|
|
332
345
|
config['logging'] = device.logging;
|
|
333
346
|
}
|
|
347
|
+
if (device.openAPI !== undefined) {
|
|
348
|
+
config['openAPI'] = device.openAPI;
|
|
349
|
+
}
|
|
334
350
|
if (Object.entries(config).length !== 0) {
|
|
335
|
-
this.infoLog(
|
|
351
|
+
this.infoLog(`${this.device.remoteType}: ${this.accessory.displayName} Config: ${superStringify(config)}`);
|
|
336
352
|
}
|
|
337
353
|
}
|
|
338
354
|
|
|
339
355
|
async logs(device: irdevice & irDevicesConfig): Promise<void> {
|
|
340
356
|
if (this.platform.debugMode) {
|
|
341
357
|
this.deviceLogging = this.accessory.context.logging = 'debugMode';
|
|
342
|
-
this.debugLog(
|
|
358
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
|
|
343
359
|
} else if (device.logging) {
|
|
344
360
|
this.deviceLogging = this.accessory.context.logging = device.logging;
|
|
345
|
-
this.debugLog(
|
|
361
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
|
|
346
362
|
} else if (this.platform.config.options?.logging) {
|
|
347
363
|
this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
|
|
348
|
-
this.debugLog(
|
|
364
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
|
|
349
365
|
} else {
|
|
350
366
|
this.deviceLogging = this.accessory.context.logging = 'standard';
|
|
351
|
-
this.debugLog(
|
|
367
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
|
|
352
368
|
}
|
|
353
369
|
}
|
|
354
370
|
|
package/src/irdevice/light.ts
CHANGED
|
@@ -21,6 +21,7 @@ export class Light {
|
|
|
21
21
|
|
|
22
22
|
// Config
|
|
23
23
|
deviceLogging!: string;
|
|
24
|
+
OpenAPI?: boolean;
|
|
24
25
|
|
|
25
26
|
constructor(private readonly platform: SwitchBotPlatform, private accessory: PlatformAccessory, public device: irdevice & irDevicesConfig) {
|
|
26
27
|
// default placeholders
|
|
@@ -72,7 +73,7 @@ export class Light {
|
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
async OnSet(value: CharacteristicValue): Promise<void> {
|
|
75
|
-
this.debugLog(
|
|
76
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} On: ${value}`);
|
|
76
77
|
this.On = value;
|
|
77
78
|
if (this.On) {
|
|
78
79
|
await this.pushLightOnChanges();
|
|
@@ -83,22 +84,22 @@ export class Light {
|
|
|
83
84
|
|
|
84
85
|
async updateHomeKitCharacteristics(): Promise<void> {
|
|
85
86
|
if (this.On === undefined) {
|
|
86
|
-
this.debugLog(
|
|
87
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
87
88
|
} else {
|
|
88
89
|
this.lightBulbService?.updateCharacteristic(this.platform.Characteristic.On, this.On);
|
|
89
|
-
this.debugLog(
|
|
90
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
|
|
90
91
|
}
|
|
91
92
|
}
|
|
92
93
|
|
|
93
94
|
/**
|
|
94
95
|
* Pushes the requested changes to the SwitchBot API
|
|
95
96
|
* deviceType commandType Command command parameter Description
|
|
96
|
-
* Light
|
|
97
|
-
* Light
|
|
98
|
-
* Light
|
|
99
|
-
* Light
|
|
100
|
-
* Light
|
|
101
|
-
* Light
|
|
97
|
+
* Light - "command" "turnOff" "default" = set to OFF state
|
|
98
|
+
* Light - "command" "turnOn" "default" = set to ON state
|
|
99
|
+
* Light - "command" "volumeAdd" "default" = volume up
|
|
100
|
+
* Light - "command" "volumeSub" "default" = volume down
|
|
101
|
+
* Light - "command" "channelAdd" "default" = next channel
|
|
102
|
+
* Light - "command" "channelSub" "default" = previous channel
|
|
102
103
|
*/
|
|
103
104
|
async pushLightOnChanges(): Promise<void> {
|
|
104
105
|
if (this.On) {
|
|
@@ -141,86 +142,89 @@ export class Light {
|
|
|
141
142
|
}
|
|
142
143
|
|
|
143
144
|
async pushChanges(body): Promise<void> {
|
|
144
|
-
|
|
145
|
+
if (this.OpenAPI) {
|
|
146
|
+
try {
|
|
145
147
|
// Make Push On request to the API
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
148
|
+
const t = Date.now();
|
|
149
|
+
const nonce = 'requestID';
|
|
150
|
+
const data = this.platform.config.credentials?.token + t + nonce;
|
|
151
|
+
const signTerm = crypto.createHmac('sha256', this.platform.config.credentials?.secret)
|
|
152
|
+
.update(Buffer.from(data, 'utf-8'))
|
|
153
|
+
.digest();
|
|
154
|
+
const sign = signTerm.toString('base64');
|
|
155
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} sign: ${sign}`);
|
|
156
|
+
this.infoLog(`${this.device.remoteType}: ${this.accessory.displayName} Sending request to SwitchBot API. body: ${body},`);
|
|
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
|
+
'Content-Length': body.length,
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
const req = https.request(options, res => {
|
|
172
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} statusCode: ${res.statusCode}`);
|
|
173
|
+
this.statusCode({ res });
|
|
174
|
+
res.on('data', d => {
|
|
175
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} d: ${d}`);
|
|
176
|
+
});
|
|
174
177
|
});
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
178
|
+
req.on('error', (e: any) => {
|
|
179
|
+
this.errorLog(`${this.device.remoteType}: ${this.accessory.displayName} error message: ${e.message}`);
|
|
180
|
+
});
|
|
181
|
+
req.write(body);
|
|
182
|
+
req.end();
|
|
183
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} pushchanges: ${superStringify(req)}`);
|
|
184
|
+
this.OnCached = this.On;
|
|
185
|
+
this.accessory.context.On = this.OnCached;
|
|
186
|
+
this.updateHomeKitCharacteristics();
|
|
187
|
+
} catch (e: any) {
|
|
188
|
+
this.errorLog(`${this.device.remoteType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
|
|
189
|
+
if (this.deviceLogging.includes('debug')) {
|
|
190
|
+
this.errorLog(
|
|
191
|
+
`${this.device.remoteType}: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
|
|
192
|
+
+ ` Error Message: ${superStringify(e.message)}`,
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
this.apiError(e);
|
|
191
196
|
}
|
|
192
|
-
this.apiError(e);
|
|
193
197
|
}
|
|
194
198
|
}
|
|
195
199
|
|
|
196
200
|
async statusCode({ res }: { res: IncomingMessage }): Promise<void> {
|
|
197
201
|
switch (res.statusCode) {
|
|
198
202
|
case 151:
|
|
199
|
-
this.errorLog(
|
|
203
|
+
this.errorLog(`${this.device.remoteType}: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
200
204
|
break;
|
|
201
205
|
case 152:
|
|
202
|
-
this.errorLog(
|
|
206
|
+
this.errorLog(`${this.device.remoteType}: ${this.accessory.displayName} Device not found.`);
|
|
203
207
|
break;
|
|
204
208
|
case 160:
|
|
205
|
-
this.errorLog(
|
|
209
|
+
this.errorLog(`${this.device.remoteType}: ${this.accessory.displayName} Command is not supported.`);
|
|
206
210
|
break;
|
|
207
211
|
case 161:
|
|
208
|
-
this.errorLog(
|
|
212
|
+
this.errorLog(`${this.device.remoteType}: ${this.accessory.displayName} Device is offline.`);
|
|
209
213
|
break;
|
|
210
214
|
case 171:
|
|
211
|
-
this.errorLog(
|
|
215
|
+
this.errorLog(`${this.device.remoteType}: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
|
|
212
216
|
break;
|
|
213
217
|
case 190:
|
|
214
218
|
this.errorLog(
|
|
215
|
-
|
|
219
|
+
`${this.device.remoteType}: ${this.accessory.displayName} Device internal error due to device states not synchronized` +
|
|
216
220
|
` with server, Or command: ${superStringify(res)} format is invalid`,
|
|
217
221
|
);
|
|
218
222
|
break;
|
|
219
223
|
case 100:
|
|
220
|
-
this.debugLog(
|
|
224
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Command successfully sent.`);
|
|
221
225
|
break;
|
|
222
226
|
default:
|
|
223
|
-
this.debugLog(
|
|
227
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Unknown statusCode.`);
|
|
224
228
|
}
|
|
225
229
|
}
|
|
226
230
|
|
|
@@ -229,6 +233,15 @@ export class Light {
|
|
|
229
233
|
//throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
|
|
230
234
|
}
|
|
231
235
|
|
|
236
|
+
async openAPI() {
|
|
237
|
+
if (!this.device.openAPI) {
|
|
238
|
+
this.OpenAPI = true;
|
|
239
|
+
} else {
|
|
240
|
+
this.OpenAPI = this.device.openAPI;
|
|
241
|
+
}
|
|
242
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Using OpenAPI: ${this.OpenAPI}`);
|
|
243
|
+
}
|
|
244
|
+
|
|
232
245
|
async config(device: irdevice & irDevicesConfig): Promise<void> {
|
|
233
246
|
let config = {};
|
|
234
247
|
if (device.irlight) {
|
|
@@ -237,24 +250,27 @@ export class Light {
|
|
|
237
250
|
if (device.logging !== undefined) {
|
|
238
251
|
config['logging'] = device.logging;
|
|
239
252
|
}
|
|
253
|
+
if (device.openAPI !== undefined) {
|
|
254
|
+
config['openAPI'] = device.openAPI;
|
|
255
|
+
}
|
|
240
256
|
if (Object.entries(config).length !== 0) {
|
|
241
|
-
this.infoLog(
|
|
257
|
+
this.infoLog(`${this.device.remoteType}: ${this.accessory.displayName} Config: ${superStringify(config)}`);
|
|
242
258
|
}
|
|
243
259
|
}
|
|
244
260
|
|
|
245
261
|
async logs(device: irdevice & irDevicesConfig): Promise<void> {
|
|
246
262
|
if (this.platform.debugMode) {
|
|
247
263
|
this.deviceLogging = this.accessory.context.logging = 'debugMode';
|
|
248
|
-
this.debugLog(
|
|
264
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
|
|
249
265
|
} else if (device.logging) {
|
|
250
266
|
this.deviceLogging = this.accessory.context.logging = device.logging;
|
|
251
|
-
this.debugLog(
|
|
267
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
|
|
252
268
|
} else if (this.platform.config.options?.logging) {
|
|
253
269
|
this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
|
|
254
|
-
this.debugLog(
|
|
270
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
|
|
255
271
|
} else {
|
|
256
272
|
this.deviceLogging = this.accessory.context.logging = 'standard';
|
|
257
|
-
this.debugLog(
|
|
273
|
+
this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
|
|
258
274
|
}
|
|
259
275
|
}
|
|
260
276
|
|