@switchbot/homebridge-switchbot 2.10.0-beta.0 → 2.10.0-beta.2
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 +9 -0
- package/dist/device/hub.d.ts.map +1 -1
- package/dist/device/hub.js +24 -0
- package/dist/device/hub.js.map +1 -1
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +24 -0
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +24 -0
- package/dist/device/meterplus.js.map +1 -1
- package/dist/platform.d.ts +12 -0
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +180 -0
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +5 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js.map +1 -1
- package/package.json +2 -2
- package/src/device/hub.ts +24 -0
- package/src/device/meter.ts +24 -0
- package/src/device/meterplus.ts +24 -0
- package/src/platform.ts +182 -0
- package/src/settings.ts +5 -0
package/dist/platform.js
CHANGED
|
@@ -58,6 +58,8 @@ const buffer_1 = require("buffer");
|
|
|
58
58
|
const rxjs_1 = require("rxjs");
|
|
59
59
|
const fakegato_history_1 = __importDefault(require("fakegato-history"));
|
|
60
60
|
const homebridge_lib_1 = require("homebridge-lib");
|
|
61
|
+
const async_mqtt_1 = require("async-mqtt");
|
|
62
|
+
const http = __importStar(require("http"));
|
|
61
63
|
const fs_1 = require("fs");
|
|
62
64
|
const settings_1 = require("./settings");
|
|
63
65
|
/**
|
|
@@ -75,6 +77,9 @@ class SwitchBotPlatform {
|
|
|
75
77
|
// this is used to track restored cached accessories
|
|
76
78
|
this.accessories = [];
|
|
77
79
|
this.version = process.env.npm_package_version || '2.9.0';
|
|
80
|
+
this.webhookEventListener = null;
|
|
81
|
+
this.mqttClient = null;
|
|
82
|
+
this.webhookEventHandler = {};
|
|
78
83
|
this.generateHeaders = () => {
|
|
79
84
|
const t = `${Date.now()}`;
|
|
80
85
|
const nonce = (0, crypto_1.randomUUID)();
|
|
@@ -140,6 +145,181 @@ class SwitchBotPlatform {
|
|
|
140
145
|
this.debugErrorLog(`Failed to Discover, Error: ${e}`);
|
|
141
146
|
}
|
|
142
147
|
});
|
|
148
|
+
this.setupMqtt();
|
|
149
|
+
this.setupwebhook();
|
|
150
|
+
}
|
|
151
|
+
async setupMqtt() {
|
|
152
|
+
if (this.config.options?.mqttURL) {
|
|
153
|
+
try {
|
|
154
|
+
this.mqttClient = await (0, async_mqtt_1.connectAsync)(this.config.options?.mqttURL, this.config.options.mqttOptions || {});
|
|
155
|
+
this.debugLog('MQTT connection has been established successfully.');
|
|
156
|
+
this.mqttClient.on('error', (e) => {
|
|
157
|
+
this.errorLog(`Failed to publish MQTT messages. ${e}`);
|
|
158
|
+
});
|
|
159
|
+
if (!this.config.options?.webhookURL) {
|
|
160
|
+
// receive webhook events via MQTT
|
|
161
|
+
this.infoLog(`Webhook is configured to be received through ${this.config.options.mqttURL}/homebridge-switchbot/webhook.`);
|
|
162
|
+
this.mqttClient.subscribe('homebridge-switchbot/webhook/+');
|
|
163
|
+
this.mqttClient.on('message', async (topic, message) => {
|
|
164
|
+
try {
|
|
165
|
+
this.debugLog(`Received Webhook via MQTT: ${topic}=${message}`);
|
|
166
|
+
const context = JSON.parse(message.toString());
|
|
167
|
+
await this.webhookEventHandler[context.deviceMac]?.(context);
|
|
168
|
+
}
|
|
169
|
+
catch (e) {
|
|
170
|
+
this.errorLog(`Failed to handle webhook event. Error:${e}`);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
catch (e) {
|
|
176
|
+
this.mqttClient = null;
|
|
177
|
+
this.errorLog(`Failed to establish MQTT connection. ${e}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
async setupwebhook() {
|
|
182
|
+
//webhook configutation
|
|
183
|
+
if (this.config.options?.webhookURL) {
|
|
184
|
+
const url = this.config.options?.webhookURL;
|
|
185
|
+
try {
|
|
186
|
+
const xurl = new URL(url);
|
|
187
|
+
const port = Number(xurl.port);
|
|
188
|
+
const path = xurl.pathname;
|
|
189
|
+
this.webhookEventListener = http.createServer((request, response) => {
|
|
190
|
+
try {
|
|
191
|
+
if (request.url === path && request.method === 'POST') {
|
|
192
|
+
request.on('data', async (data) => {
|
|
193
|
+
try {
|
|
194
|
+
const body = JSON.parse(data);
|
|
195
|
+
this.debugLog(`Received Webhook: ${JSON.stringify(body)}`);
|
|
196
|
+
if (this.config.options?.mqttURL) {
|
|
197
|
+
const mac = body.context.deviceMac
|
|
198
|
+
?.toLowerCase()
|
|
199
|
+
.match(/[\s\S]{1,2}/g)
|
|
200
|
+
?.join(':');
|
|
201
|
+
const options = this.config.options?.mqttPubOptions || {};
|
|
202
|
+
this.mqttClient?.publish(`homebridge-switchbot/webhook/${mac}`, `${JSON.stringify(body.context)}`, options);
|
|
203
|
+
}
|
|
204
|
+
await this.webhookEventHandler[body.context.deviceMac]?.(body.context);
|
|
205
|
+
}
|
|
206
|
+
catch (e) {
|
|
207
|
+
this.errorLog(`Failed to handle webhook event. Error:${e}`);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
response.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
211
|
+
response.end('OK');
|
|
212
|
+
}
|
|
213
|
+
// else {
|
|
214
|
+
// response.writeHead(403, {'Content-Type': 'text/plain'});
|
|
215
|
+
// response.end(`NG`);
|
|
216
|
+
// }
|
|
217
|
+
}
|
|
218
|
+
catch (e) {
|
|
219
|
+
this.errorLog(`Failed to handle webhook event. Error:${e}`);
|
|
220
|
+
}
|
|
221
|
+
}).listen(port ? port : 80);
|
|
222
|
+
}
|
|
223
|
+
catch (e) {
|
|
224
|
+
this.errorLog(`Failed to create webhook listener. Error:${e.message}`);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
try {
|
|
228
|
+
const { body, statusCode, headers } = await (0, undici_1.request)('https://api.switch-bot.com/v1.1/webhook/setupWebhook', {
|
|
229
|
+
method: 'POST',
|
|
230
|
+
headers: this.generateHeaders(),
|
|
231
|
+
body: JSON.stringify({
|
|
232
|
+
'action': 'setupWebhook',
|
|
233
|
+
'url': url,
|
|
234
|
+
'deviceList': 'ALL',
|
|
235
|
+
}),
|
|
236
|
+
});
|
|
237
|
+
const response = await body.json();
|
|
238
|
+
this.debugLog(`setupWebhook: url:${url}`);
|
|
239
|
+
this.debugLog(`setupWebhook: body:${JSON.stringify(response)}`);
|
|
240
|
+
this.debugLog(`setupWebhook: statusCode:${statusCode}`);
|
|
241
|
+
this.debugLog(`setupWebhook: headers:${JSON.stringify(headers)}`);
|
|
242
|
+
if (statusCode !== 200 || response?.statusCode !== 100) {
|
|
243
|
+
this.errorLog(`Failed to configure webhook. Existing webhook well be overridden. HTTP:${statusCode} API:${response?.statusCode} `
|
|
244
|
+
+ `message:${response?.message}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
catch (e) {
|
|
248
|
+
this.errorLog(`Failed to configure webhook. Error: ${e.message}`);
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
const { body, statusCode, headers } = await (0, undici_1.request)('https://api.switch-bot.com/v1.1/webhook/updateWebhook', {
|
|
252
|
+
method: 'POST',
|
|
253
|
+
headers: this.generateHeaders(),
|
|
254
|
+
body: JSON.stringify({
|
|
255
|
+
'action': 'updateWebhook',
|
|
256
|
+
'config': {
|
|
257
|
+
'url': url,
|
|
258
|
+
'enable': true,
|
|
259
|
+
},
|
|
260
|
+
}),
|
|
261
|
+
});
|
|
262
|
+
const response = await body.json();
|
|
263
|
+
this.debugLog(`updateWebhook: url:${url}`);
|
|
264
|
+
this.debugLog(`updateWebhook: body:${JSON.stringify(response)}`);
|
|
265
|
+
this.debugLog(`updateWebhook: statusCode:${statusCode}`);
|
|
266
|
+
this.debugLog(`updateWebhook: headers:${JSON.stringify(headers)}`);
|
|
267
|
+
if (statusCode !== 200 || response?.statusCode !== 100) {
|
|
268
|
+
this.errorLog(`Failed to update webhook. HTTP:${statusCode} API:${response?.statusCode} message:${response?.message}`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
catch (e) {
|
|
272
|
+
this.errorLog(`Failed to update webhook. Error:${e.message}`);
|
|
273
|
+
}
|
|
274
|
+
try {
|
|
275
|
+
const { body, statusCode, headers } = await (0, undici_1.request)('https://api.switch-bot.com/v1.1/webhook/queryWebhook', {
|
|
276
|
+
method: 'POST',
|
|
277
|
+
headers: this.generateHeaders(),
|
|
278
|
+
body: JSON.stringify({
|
|
279
|
+
'action': 'queryUrl',
|
|
280
|
+
}),
|
|
281
|
+
});
|
|
282
|
+
const response = await body.json();
|
|
283
|
+
this.debugLog(`queryWebhook: body:${JSON.stringify(response)}`);
|
|
284
|
+
this.debugLog(`queryWebhook: statusCode:${statusCode}`);
|
|
285
|
+
this.debugLog(`queryWebhook: headers:${JSON.stringify(headers)}`);
|
|
286
|
+
if (statusCode !== 200 || response?.statusCode !== 100) {
|
|
287
|
+
this.errorLog(`Failed to query webhook. HTTP:${statusCode} API:${response?.statusCode} message:${response?.message}`);
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
this.infoLog(`Listening webhook on ${response?.body?.urls[0]}`);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
catch (e) {
|
|
294
|
+
this.errorLog(`Failed to query webhook. Error:${e}`);
|
|
295
|
+
}
|
|
296
|
+
this.api.on('shutdown', async () => {
|
|
297
|
+
try {
|
|
298
|
+
const { body, statusCode, headers } = await (0, undici_1.request)('https://api.switch-bot.com/v1.1/webhook/deleteWebhook', {
|
|
299
|
+
method: 'POST',
|
|
300
|
+
headers: this.generateHeaders(),
|
|
301
|
+
body: JSON.stringify({
|
|
302
|
+
'action': 'deleteWebhook',
|
|
303
|
+
'url': url,
|
|
304
|
+
}),
|
|
305
|
+
});
|
|
306
|
+
const response = await body.json();
|
|
307
|
+
this.debugLog(`deleteWebhook: url:${url}`);
|
|
308
|
+
this.debugLog(`deleteWebhook: body:${JSON.stringify(response)}`);
|
|
309
|
+
this.debugLog(`deleteWebhook: statusCode:${statusCode}`);
|
|
310
|
+
this.debugLog(`deleteWebhook: headers:${JSON.stringify(headers)}`);
|
|
311
|
+
if (statusCode !== 200 || response?.statusCode !== 100) {
|
|
312
|
+
this.errorLog(`Failed to delete webhook. HTTP:${statusCode} API:${response?.statusCode} message:${response?.message}`);
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
this.infoLog('Unregistered webhook to close listening.');
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
catch (e) {
|
|
319
|
+
this.errorLog(`Failed to delete webhook. Error:${e.message}`);
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
}
|
|
143
323
|
}
|
|
144
324
|
/**
|
|
145
325
|
* This function is invoked when homebridge restores cached accessories from disk at startup.
|