UNPKG

homebridge-otgw

Version:

Homebridge plugin for OpenTherm Gateway

84 lines (75 loc) 2.34 kB
// homebridge-otgw/lib/OtmClient.js // Copyright © 2019-2025 Erik Baauw. All rights reserved. // // Homebridege plugin for OpenTherm Gateway. import WebSocket from 'ws' import { timeout } from 'homebridge-lib' import { HttpClient } from 'homebridge-lib/HttpClient' const maxRetries = 5 // Client to OpenTherm Monitor web server. class OtmClient extends HttpClient { constructor (params = {}) { const host = params.hostname + ':' + params.port super({ host, keepAlive: true, maxSockets: 1, path: '/command?', text: true }) this._host = host this._messageUri = 'ws://' + this._host + '/message.ws' } async connect () { // Somehow, events.once(this._ws, 'open') doesn't work as expected, when an // 'error' event is emitted. Probably because ws library handles events // in a funny way. For now, use traditional promise to handle this. return new Promise((resolve, reject) => { this._ws = new WebSocket(this._messageUri, { origin: 'localhost' }) this._ws .on('message', (message, isBinary) => { this.emit('message', message.toString().slice(17)) }) .on('close', () => { if (this._ws != null) { this._ws.removeAllListeners() } delete this._ws this.emit('close') }) .once('error', (error) => { // 'close' event will follow, so no cleanup here. reject(error) }) .once('open', () => { this._ws.removeAllListeners('error') this._ws.on('error', (error) => { this.emit('error', error) }) resolve(this._messageUri) }) }) } close () { if (this._ws != null) { this._ws.close() } } // Send a command to the OTM and return its reponse. async command (command) { for (let retries = 0; retries <= maxRetries; retries++) { this.emit('command', command, retries) const response = await this.get(command) const a = response.body.split(': ') if (a[0] === command.split('=')[0]) { this.emit('commandResponse', command, a[1]) return a[1] } await timeout(1000) } throw new Error( `command ${command}: no response after ${maxRetries} retries` ) } } export { OtmClient }