Files
ring-mqtt/lib/mqtt.js
2022-03-08 21:45:35 -05:00

99 lines
3.5 KiB
JavaScript

const mqttApi = require('mqtt')
const debug = require('debug')('ring-mqtt')
const colors = require('colors/safe')
const utils = require('./utils')
class Mqtt {
constructor() {
this.client = false
this.connected = false
// Configure event listeners
utils.event.on('ringState', async (state) => {
if (!this.client && state === 'connected') {
// Ring API connected, short wait before starting MQTT client
await utils.sleep(2)
this.init()
}
})
utils.event.on('mqttPublish', (topic, message) => {
this.client.publish(topic, (typeof message === 'number') ? message.toString() : message, { qos: 1 }, () => {
// Just a dummy callback to prevent MQTT memory leak in 4.3.5/4.3.6
})
})
utils.event.on('mqttSubscribe', (topic) => {
this.client.subscribe(topic)
})
}
async init() {
try {
debug('Attempting connection to MQTT broker...')
this.client = await this.connect()
this.start()
// Subscribe to configured/default/legacay Home Assistant status topics
this.client.subscribe(utils.config.hass_topic)
this.client.subscribe('hass/status')
this.client.subscribe('hassio/status')
} catch (error) {
debug(error)
debug(colors.red(`Could not authenticate to MQTT broker. Please check the broker and configuration settings.`))
process.exit(1)
}
}
// Initiate the connection to MQTT broker
async connect() {
const mqttClient = await mqttApi.connect({
username: utils.config.mqtt_user ? utils.config.mqtt_user : null,
password: utils.config.mqtt_pass ? utils.config.mqtt_pass : null,
host: utils.config.host,
port: utils.config.port
});
return mqttClient
}
start() {
// On MQTT connect/reconnect send config/state information after delay
this.client.on('connect', () => {
if (!this.connected) {
this.connected = true
utils.event.emit('mqttState', 'connected')
}
})
this.client.on('reconnect', () => {
if (this.connected) {
debug('Connection to MQTT broker lost. Attempting to reconnect...')
} else {
debug('Attempting to reconnect to MQTT broker...')
}
this.connected = false
utils.event.emit('mqttState', 'disconnected')
})
this.client.on('error', (error) => {
debug('Unable to connect to MQTT broker', error.message)
this.connected = false
utils.event.emit('mqttState', 'disconnected')
})
// Process MQTT messages from subscribed command topics
this.client.on('message', (topic, message) => {
message = message.toString()
if (topic === utils.config.hass_topic || topic === 'hass/status' || topic === 'hassio/status') {
utils.event.emit('haStatus', topic, message)
} else {
// Parse topic to get location/device ID
const deviceTopicLevels = (topic.substring(utils.config.ring_topic.length)).replace(/^\/+/, '').split('/')
const eventId = `${deviceTopicLevels[0]}_${deviceTopicLevels[2]}`
utils.event.emit(eventId, topic.split("/").slice(-2).join("/"), message)
}
})
}
}
module.exports = new Mqtt()