UNPKG

homebridge-platform-orbit

Version:

Orbit Irrigation System platform plugin for [HomeBridge](https://github.com/nfarina/homebridge).

211 lines (176 loc) 6.5 kB
import { Logger } from "homebridge"; import bent from 'bent'; import WS from 'ws'; import ReconnectingWebSocket from 'reconnecting-websocket'; const endpoint = 'https://api.orbitbhyve.com/v1'; const ws_endpoint = 'wss://api.orbitbhyve.com/v1'; const WSpingINTERVAL = 25000 // Websocket get's timed out after 30s, so ping every 25s export class OrbitAPI { private readonly log: Logger; private readonly email: string; private readonly password: string; private token: string; constructor(log: Logger, email: string, password: string) { this.log = log; this.email = email; this.password = password; this.token = ""; } async login() { // Log in try { const postJSON = bent('POST', 'json'); let response = await postJSON(endpoint + "/session", { "session": { "email": this.email, "password": this.password } }, { "orbit-app-id": "Orbit Support Dashboard", "orbit-api-key": "null" }); this.token = response['orbit_api_key']; } catch (error) { throw error; } } async getDevices(): Promise<OrbitDevice[]> { let devices: OrbitDevice[] = []; // Get the device details try { const getJSON = bent('GET', 'json'); let response = await getJSON(endpoint + "/devices", {}, { "orbit-app-id": "Orbit Support Dashboard", "orbit-api-key": this.token }); response.forEach((result: any) => { if (result['type'] == "sprinkler_timer") { // Create the device let device = new OrbitDevice(this.log, this.token, result['id'], result['name'], result['hardware_version'], result['firmware_version'], result['is_connected']); // Create zones result['zones'].forEach((zone: any) => { device.addZone(zone['station'], zone['name']); }); devices.push(device); } }); return devices; } catch (error) { throw error; } } } export class OrbitDevice { private readonly log: Logger; private readonly token: string; public readonly id: string; public readonly name: string; public readonly hardware_version: string; public readonly firmware_version: string; public readonly is_connected: boolean; public readonly zones: {}[]; private messageQueue: string[]; private rws: ReconnectingWebSocket; constructor(log: Logger, token: string, id: string, name: string, hardware_version: string, firmware_version: string, is_connected: boolean) { this.log = log; this.token = token; this.id = id; this.name = name; this.hardware_version = hardware_version; this.firmware_version = firmware_version; this.is_connected = is_connected; this.zones = []; this.messageQueue = [] // Create the Reconnecting Web Socket this.rws = new ReconnectingWebSocket(`${ws_endpoint}/events`, [], { WebSocket: WS, connectionTimeout: 10000, maxReconnectionDelay: 64000, minReconnectionDelay: 2000, reconnectionDelayGrowFactor: 2 }); // Intercept send events for logging and queuing const origSend = this.rws.send.bind(this.rws); this.rws.send = (data: string) => { if (this.rws.readyState === WS.OPEN) { this.log.debug('TX', data); origSend(data); } else { this.messageQueue.push(data); } }; // Ping setInterval(() => { this.rws.send(JSON.stringify({ event: 'ping' })); }, WSpingINTERVAL); // On Open, process any queued messages this.rws.onopen = (openEvent: WS.OpenEvent) => { this.log.debug('WebSocket', openEvent.type); while (this.messageQueue.length > 0) { let data: string = this.messageQueue.shift()!; this.log.debug('TX', data); origSend(data); } }; // On Close this.rws.onclose = (closeEvent: WS.CloseEvent) => { this.log.debug('WebSocket', closeEvent.type); }; // On Error this.rws.onerror = (errorEvent: WS.ErrorEvent) => { this.log.error('WebSocket Error', errorEvent); this.rws.close(); }; } addZone(station: string, name: string) { this.zones.push({ "station": station, "name": name }); } openConnection() { this.log.debug('openConnection'); this.rws.send(JSON.stringify({ event: "app_connection", orbit_session_token: this.token, subscribe_device_id: this.id })); } onMessage(listner: Function) { this.log.debug('onMessage'); this.rws.onmessage = (messageEvent: MessageEvent) => { this.log.debug('RX', messageEvent.data); listner(messageEvent.data); }; } sync() { this.log.debug('sync'); this.rws.send(JSON.stringify({ event: "sync", device_id: this.id })); } startZone(station: number, run_time: number) { this.log.debug('startZone', station, run_time); this.rws.send(JSON.stringify({ event: "change_mode", mode: "manual", device_id: this.id, timestamp: new Date().toISOString(), stations: [ { "station": station, "run_time": run_time } ] })); } stopZone() { this.log.debug('stopZone'); this.rws.send(JSON.stringify({ event: "change_mode", mode: "manual", device_id: this.id, timestamp: new Date().toISOString(), stations: [] })); } }