mirror of
https://github.com/tsightler/ring-mqtt.git
synced 2025-10-05 16:57:04 +08:00
99 lines
3.5 KiB
JavaScript
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() |