@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.
Files changed (116) hide show
  1. package/.github/ISSUE_TEMPLATE/bug-report.yml +1 -0
  2. package/.github/ISSUE_TEMPLATE/feature-request.yml +1 -0
  3. package/.github/ISSUE_TEMPLATE/support-request.yml +1 -0
  4. package/.prettierrc +1 -1
  5. package/CHANGELOG.md +9 -0
  6. package/dist/device/bot.d.ts +8 -7
  7. package/dist/device/bot.d.ts.map +1 -1
  8. package/dist/device/bot.js +97 -21
  9. package/dist/device/bot.js.map +1 -1
  10. package/dist/device/colorbulb.d.ts +8 -7
  11. package/dist/device/colorbulb.d.ts.map +1 -1
  12. package/dist/device/colorbulb.js +221 -56
  13. package/dist/device/colorbulb.js.map +1 -1
  14. package/dist/device/contact.d.ts +3 -3
  15. package/dist/device/contact.d.ts.map +1 -1
  16. package/dist/device/contact.js +50 -7
  17. package/dist/device/contact.js.map +1 -1
  18. package/dist/device/curtain.d.ts +9 -8
  19. package/dist/device/curtain.d.ts.map +1 -1
  20. package/dist/device/curtain.js +95 -21
  21. package/dist/device/curtain.js.map +1 -1
  22. package/dist/device/humidifier.d.ts +8 -7
  23. package/dist/device/humidifier.d.ts.map +1 -1
  24. package/dist/device/humidifier.js +180 -59
  25. package/dist/device/humidifier.js.map +1 -1
  26. package/dist/device/lock.d.ts +8 -7
  27. package/dist/device/lock.d.ts.map +1 -1
  28. package/dist/device/lock.js +98 -22
  29. package/dist/device/lock.js.map +1 -1
  30. package/dist/device/meter.d.ts +4 -4
  31. package/dist/device/meter.d.ts.map +1 -1
  32. package/dist/device/meter.js +51 -8
  33. package/dist/device/meter.js.map +1 -1
  34. package/dist/device/meterplus.d.ts +3 -3
  35. package/dist/device/meterplus.d.ts.map +1 -1
  36. package/dist/device/meterplus.js +49 -6
  37. package/dist/device/meterplus.js.map +1 -1
  38. package/dist/device/motion.d.ts +3 -3
  39. package/dist/device/motion.d.ts.map +1 -1
  40. package/dist/device/motion.js +49 -9
  41. package/dist/device/motion.js.map +1 -1
  42. package/dist/device/plug.d.ts +8 -7
  43. package/dist/device/plug.d.ts.map +1 -1
  44. package/dist/device/plug.js +96 -20
  45. package/dist/device/plug.js.map +1 -1
  46. package/dist/device/striplight.d.ts +8 -7
  47. package/dist/device/striplight.d.ts.map +1 -1
  48. package/dist/device/striplight.js +186 -47
  49. package/dist/device/striplight.js.map +1 -1
  50. package/dist/irdevice/airconditioner.d.ts +7 -6
  51. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  52. package/dist/irdevice/airconditioner.js +65 -28
  53. package/dist/irdevice/airconditioner.js.map +1 -1
  54. package/dist/irdevice/airpurifier.d.ts +7 -6
  55. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  56. package/dist/irdevice/airpurifier.js +65 -28
  57. package/dist/irdevice/airpurifier.js.map +1 -1
  58. package/dist/irdevice/camera.d.ts +7 -6
  59. package/dist/irdevice/camera.d.ts.map +1 -1
  60. package/dist/irdevice/camera.js +58 -22
  61. package/dist/irdevice/camera.js.map +1 -1
  62. package/dist/irdevice/fan.d.ts +8 -7
  63. package/dist/irdevice/fan.d.ts.map +1 -1
  64. package/dist/irdevice/fan.js +76 -40
  65. package/dist/irdevice/fan.js.map +1 -1
  66. package/dist/irdevice/light.d.ts +7 -6
  67. package/dist/irdevice/light.d.ts.map +1 -1
  68. package/dist/irdevice/light.js +71 -35
  69. package/dist/irdevice/light.js.map +1 -1
  70. package/dist/irdevice/other.d.ts +7 -6
  71. package/dist/irdevice/other.d.ts.map +1 -1
  72. package/dist/irdevice/other.js +58 -22
  73. package/dist/irdevice/other.js.map +1 -1
  74. package/dist/irdevice/tv.d.ts +8 -7
  75. package/dist/irdevice/tv.d.ts.map +1 -1
  76. package/dist/irdevice/tv.js +112 -76
  77. package/dist/irdevice/tv.js.map +1 -1
  78. package/dist/irdevice/vacuumcleaner.d.ts +7 -6
  79. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  80. package/dist/irdevice/vacuumcleaner.js +58 -22
  81. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  82. package/dist/irdevice/waterheater.d.ts +7 -6
  83. package/dist/irdevice/waterheater.d.ts.map +1 -1
  84. package/dist/irdevice/waterheater.js +58 -22
  85. package/dist/irdevice/waterheater.js.map +1 -1
  86. package/dist/platform.d.ts +3 -5
  87. package/dist/platform.d.ts.map +1 -1
  88. package/dist/platform.js +143 -87
  89. package/dist/platform.js.map +1 -1
  90. package/dist/settings.d.ts +2 -21
  91. package/dist/settings.d.ts.map +1 -1
  92. package/dist/settings.js +3 -3
  93. package/dist/settings.js.map +1 -1
  94. package/package.json +10 -12
  95. package/src/device/bot.ts +97 -30
  96. package/src/device/colorbulb.ts +225 -93
  97. package/src/device/contact.ts +49 -10
  98. package/src/device/curtain.ts +98 -31
  99. package/src/device/humidifier.ts +182 -77
  100. package/src/device/lock.ts +97 -30
  101. package/src/device/meter.ts +51 -12
  102. package/src/device/meterplus.ts +48 -9
  103. package/src/device/motion.ts +48 -12
  104. package/src/device/plug.ts +97 -29
  105. package/src/device/striplight.ts +189 -68
  106. package/src/irdevice/airconditioner.ts +64 -34
  107. package/src/irdevice/airpurifier.ts +64 -36
  108. package/src/irdevice/camera.ts +57 -27
  109. package/src/irdevice/fan.ts +76 -46
  110. package/src/irdevice/light.ts +69 -39
  111. package/src/irdevice/other.ts +57 -27
  112. package/src/irdevice/tv.ts +112 -82
  113. package/src/irdevice/vacuumcleaner.ts +57 -27
  114. package/src/irdevice/waterheater.ts +57 -27
  115. package/src/platform.ts +157 -100
  116. package/src/settings.ts +2 -25
@@ -1,6 +1,8 @@
1
- import { AxiosResponse } from 'axios';
1
+ import https from 'https';
2
+ import crypto from 'crypto';
3
+ import { IncomingMessage } from 'http';
2
4
  import { SwitchBotPlatform } from '../platform';
3
- import { irDevicesConfig, DeviceURL, irdevice, payload } from '../settings';
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 payload = {
103
- commandType: 'command',
104
- parameter: 'default',
105
- command: 'turnOn',
106
- } as payload;
107
- await this.pushChanges(payload);
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 payload = {
114
- commandType: 'command',
115
- parameter: 'default',
116
- command: 'turnOff',
117
- } as payload;
118
- await this.pushChanges(payload);
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 payload = {
124
- commandType: 'command',
125
- parameter: 'default',
126
- command: 'brightnessUp',
127
- } as payload;
128
- await this.pushChanges(payload);
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 payload = {
133
- commandType: 'command',
134
- parameter: 'default',
135
- command: 'brightnessDown',
136
- } as payload;
137
- await this.pushChanges(payload);
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(payload: payload): Promise<void> {
142
+ async pushChanges(body): Promise<void> {
141
143
  try {
142
- this.infoLog(
143
- `Light: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},` +
144
- ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`,
145
- );
146
-
147
- // Make the API request
148
- const push = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
149
- this.debugLog(`Light: ${this.accessory.displayName} pushChanges: ${push.data}`);
150
- this.statusCode(push);
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(push: AxiosResponse<{ statusCode: number }>): Promise<void>{
166
- switch (push.data.statusCode) {
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(push.data)} format is invalid`,
215
+ ` with server, Or command: ${JSON.stringify(res)} format is invalid`,
186
216
  );
187
217
  break;
188
218
  case 100:
@@ -1,6 +1,8 @@
1
- import { AxiosResponse } from 'axios';
1
+ import https from 'https';
2
+ import crypto from 'crypto';
3
+ import { IncomingMessage } from 'http';
2
4
  import { SwitchBotPlatform } from '../platform';
3
- import { irDevicesConfig, DeviceURL, irdevice, payload } from '../settings';
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 payload = {
101
- commandType: 'customize',
102
- parameter: 'default',
103
- command: `${this.device.other.commandOn}`,
104
- } as payload;
105
- await this.pushChanges(payload);
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 payload = {
124
- commandType: 'customize',
125
- parameter: 'default',
126
- command: `${this.device.other.commandOff}`,
127
- } as payload;
128
- await this.pushChanges(payload);
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(payload: payload): Promise<void> {
143
+ async pushChanges(body): Promise<void> {
142
144
  try {
143
- this.infoLog(
144
- `Other: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},` +
145
- ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`,
146
- );
147
-
148
- // Make the API request
149
- const push = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
150
- this.debugLog(`Other: ${this.accessory.displayName} pushChanges: ${push.data}`);
151
- this.statusCode(push);
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(push: AxiosResponse<{ statusCode: number }>): Promise<void>{
165
- switch (push.data.statusCode) {
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(push.data)} format is invalid`,
214
+ ` with server, Or command: ${JSON.stringify(res)} format is invalid`,
185
215
  );
186
216
  break;
187
217
  case 100:
@@ -1,7 +1,9 @@
1
- import { AxiosResponse } from 'axios';
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 { DeviceURL, irdevice, deviceStatusResponse, irDevicesConfig, payload } from '../settings';
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!: deviceStatusResponse;
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 payload = {
239
- commandType: 'command',
240
- parameter: 'default',
241
- command: 'turnOn',
242
- } as payload;
243
- await this.pushTVChanges(payload);
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 payload = {
249
- commandType: 'command',
250
- parameter: 'default',
251
- command: 'turnOff',
252
- } as payload;
253
- await this.pushTVChanges(payload);
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 payload = {
258
- commandType: 'command',
259
- parameter: 'default',
260
- command: 'Ok',
261
- } as payload;
262
- await this.pushTVChanges(payload);
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 payload = {
267
- commandType: 'command',
268
- parameter: 'default',
269
- command: 'Back',
270
- } as payload;
271
- await this.pushTVChanges(payload);
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 payload = {
276
- commandType: 'command',
277
- parameter: 'default',
278
- command: 'Menu',
279
- } as payload;
280
- await this.pushTVChanges(payload);
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 payload = {
285
- commandType: 'command',
286
- parameter: 'default',
287
- command: 'Up',
288
- } as payload;
289
- await this.pushTVChanges(payload);
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 payload = {
294
- commandType: 'command',
295
- parameter: 'default',
296
- command: 'Down',
297
- } as payload;
298
- await this.pushTVChanges(payload);
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 payload = {
303
- commandType: 'command',
304
- parameter: 'default',
305
- command: 'Right',
306
- } as payload;
307
- await this.pushTVChanges(payload);
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 payload = {
312
- commandType: 'command',
313
- parameter: 'default',
314
- command: 'Left',
315
- } as payload;
316
- await this.pushTVChanges(payload);
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 payload = {
321
- commandType: 'command',
322
- parameter: 'default',
323
- command: 'volumeAdd',
324
- } as payload;
325
- await this.pushTVChanges(payload);
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 payload = {
330
- commandType: 'command',
331
- parameter: 'default',
332
- command: 'volumeSub',
333
- } as payload;
334
- await this.pushTVChanges(payload);
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(payload: payload): Promise<void> {
339
+ async pushTVChanges(body): Promise<void> {
338
340
  try {
339
- this.infoLog(
340
- `${this.device.remoteType}: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},` +
341
- ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`,
342
- );
343
-
344
- // Make the API request
345
- const push = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
346
- this.debugLog(`${this.device.remoteType}: ${this.accessory.displayName} pushChanges: ${push.data}`);
347
- this.statusCode(push);
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(push: AxiosResponse<{ statusCode: number }>): Promise<void>{
362
- switch (push.data.statusCode) {
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(push.data)} format is invalid`,
412
+ ` Or command: ${JSON.stringify(res)} format is invalid`,
383
413
  );
384
414
  break;
385
415
  case 100:
@@ -1,6 +1,8 @@
1
- import { AxiosResponse } from 'axios';
1
+ import https from 'https';
2
+ import crypto from 'crypto';
3
+ import { IncomingMessage } from 'http';
2
4
  import { SwitchBotPlatform } from '../platform';
3
- import { irDevicesConfig, DeviceURL, irdevice, payload } from '../settings';
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 payload = {
88
- commandType: 'command',
89
- parameter: 'default',
90
- command: 'turnOn',
91
- } as payload;
92
- await this.pushChanges(payload);
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 payload = {
99
- commandType: 'command',
100
- parameter: 'default',
101
- command: 'turnOff',
102
- } as payload;
103
- await this.pushChanges(payload);
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(payload: payload): Promise<void> {
109
+ async pushChanges(body): Promise<void> {
108
110
  try {
109
- this.infoLog(
110
- `Vacuum Cleaner: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},` +
111
- ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`,
112
- );
113
-
114
- // Make the API request
115
- const push = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
116
- this.debugLog(`Vacuum Cleaner: ${this.accessory.displayName} pushChanges: ${push.data}`);
117
- this.statusCode(push);
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(push: AxiosResponse<{ statusCode: number }>): Promise<void>{
134
- switch (push.data.statusCode) {
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(push.data)} format is invalid`,
183
+ ` with server, Or command: ${JSON.stringify(res)} format is invalid`,
154
184
  );
155
185
  break;
156
186
  case 100: