homebridge-otgw
Version:
Homebridge plugin for OpenTherm Gateway
80 lines (71 loc) • 2.15 kB
JavaScript
// homebridge-otgw/lib/OtgwClient.js
// Copyright © 2019-2026 Erik Baauw. All rights reserved.
//
// Homebridege plugin for OpenTherm Gateway.
import { EventEmitter, once } from 'node:events'
import { createConnection } from 'node:net'
import { timeout } from 'homebridge-lib'
const maxRetries = 5
// Client to OpenTherm Gateway's NodeMCU serial server.
class OtgwClient extends EventEmitter {
constructor (options = {}) {
super()
this._hostname = options.hostname
this._port = options.port
}
async connect () {
this._socket = createConnection(this._port, this._hostname)
let line = ''
this._socket
.on('error', (error) => {
this.emit(error, 'error')
this.close()
})
.on('data', (data) => {
this.emit('data', data)
line += data.toString()
const messages = line.split('\r\n')
if (messages.length > 1) {
line = messages.pop()
for (const message of messages) {
this.emit('message', message)
}
}
})
.on('end', () => { this.close() })
.on('close', () => { this.close() })
await once(this._socket, 'ready')
return `${this._hostname}:${this._port}`
}
close () {
if (this._socket) {
if (!this._socket.destroyed) {
this._socket.destroy()
}
this._socket.removeAllListeners()
delete this._socket
this.emit('close')
}
}
// Send a command to the OTGW and return its reponse
async command (command, retries = 0) {
for (let retries = 0; retries <= maxRetries; retries++) {
if (this._socket == null) {
throw new Error(`command ${command}: connection closed`)
}
this.emit('command', command, retries)
this._socket.write(command + '\r\n')
const [message] = await once(this, 'message')
const a = message.split(': ')
if (a[0] === command.split('=')[0]) {
this.emit('response', command, a[1])
return a[1]
}
await timeout(1000)
}
throw new Error(
`command ${command}: no response after ${maxRetries} retries`
)
}
}
export { OtgwClient }