UNPKG

homebridge-resideo

Version:

The Resideo plugin allows you to access your Resideo device(s) from HomeKit.

131 lines 6.61 kB
import { Buffer } from 'node:buffer'; import { exec as execCb } from 'node:child_process'; import fs from 'node:fs'; import http from 'node:http'; import util from 'node:util'; /* eslint-disable no-console */ import { HomebridgePluginUiServer } from '@homebridge/plugin-ui-utils'; const exec = util.promisify(execCb); class PluginUiServer extends HomebridgePluginUiServer { key; secret; hostname; constructor() { super(); this.onRequest('Start Resideo Login Server', () => { const runningServer = http.createServer(async (req, res) => { try { res.writeHead(200, { 'Content-Type': 'text/html' }); const reqUrl = new URL(req.url ?? '', `http://${req.headers.host}`); const action = reqUrl.pathname.replace('/', ''); const query = reqUrl.searchParams; switch (action) { case 'start': { this.key = query.get('key'); this.secret = query.get('secret'); this.hostname = query.get('host'); const redirectUrl = `http://${this.hostname}:8585/auth`; const authUrl = `https://api.honeywell.com/oauth2/authorize?response_type=code&appSelect=1&redirect_uri=${encodeURI(redirectUrl)}&client_id=${query.get('key')}`; res.end(`<script>window.location.replace('${authUrl}');</script>`); break; } case 'auth': { if (query.get('code')) { const code = query.get('code'); const auth = Buffer.from(`${this.key}:${this.secret}`).toString('base64'); let curlString = ''; curlString += 'curl -X POST '; curlString += `--header "Authorization: Basic ${auth}" `; curlString += '--header "Accept: application/json" '; curlString += '--header "Content-Type: application/x-www-form-urlencoded" '; curlString += '-d "'; curlString += 'grant_type=authorization_code&'; curlString += `code=${code}&`; curlString += `redirect_uri=${encodeURI(`http://${this.hostname}:8585/auth`)}`; curlString += '" '; curlString += '"https://api.honeywell.com/oauth2/token"'; try { const { stdout } = await exec(curlString); const response = JSON.parse(stdout); if (response.access_token) { this.pushEvent('creds-received', { key: this.key, secret: this.secret, access: response.access_token, refresh: response.refresh_token, }); res.end('Success. You can close this window now.'); } else { res.end('oops.'); } } catch (err) { res.end(`<strong>An error occurred:</strong><br>${JSON.stringify(err)}<br><br>Close this window and start again`); } } else { res.end('<strong>An error occurred:</strong><br>no code received<br><br>Close this window and start again'); } break; } default: { // should never happen res.end('welcome to the server'); break; } } } catch (err) { console.log(err); } }); runningServer.listen(8585, (err) => { if (err) { console.log(err); } else { console.log('Server is running'); } }); setTimeout(() => { runningServer.close(); }, 300000); // Return a response to satisfy the expected return type return { status: 'ok' }; }); /* A native method getCachedAccessories() was introduced in config-ui-x v4.37.0 The following is for users who have a lower version of config-ui-x */ this.onRequest('/getCachedAccessories', async () => { try { // Define the plugin and create the array to return const plugin = 'homebridge-resideo'; const devicesToReturn = []; // The path and file of the cached accessories const accFile = `${this.homebridgeStoragePath}/accessories/cachedAccessories`; // Check the file exists if (fs.existsSync(accFile)) { // Read the cached accessories file const cachedAccessoriesData = await fs.promises.readFile(accFile, 'utf8'); // Parse the JSON const cachedAccessories = JSON.parse(cachedAccessoriesData); // We only want the accessories for this plugin cachedAccessories .filter((accessory) => accessory.plugin === plugin) .forEach((accessory) => devicesToReturn.push(accessory)); } // Return the array return { status: 'ok', data: devicesToReturn }; } catch (err) { // Just return an empty accessory list in case of any errors return { status: 'error', data: [] }; } }); this.ready(); } } (() => new PluginUiServer())(); //# sourceMappingURL=server.js.map