2018-04-18 09:25:40 -07:00
|
|
|
const mqtt = require('mqtt');
|
|
|
|
const logger = require('./util/logger');
|
|
|
|
const settings = require('./util/settings');
|
|
|
|
|
|
|
|
class MQTT {
|
|
|
|
constructor() {
|
|
|
|
this.handleConnect = this.handleConnect.bind(this);
|
|
|
|
this.handleMessage = this.handleMessage.bind(this);
|
|
|
|
}
|
|
|
|
|
2018-04-25 11:54:41 -07:00
|
|
|
connect(onMessage, subscriptions, callback) {
|
2018-04-18 09:25:40 -07:00
|
|
|
const mqttSettings = settings.get().mqtt;
|
|
|
|
logger.info(`Connecting to MQTT server at ${mqttSettings.server}`);
|
|
|
|
|
2018-08-09 09:23:04 -07:00
|
|
|
const options = {
|
|
|
|
will: {
|
|
|
|
topic: this.prefixTopic('bridge/state'),
|
|
|
|
payload: 'offline',
|
|
|
|
retain: true,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2018-04-18 09:25:40 -07:00
|
|
|
if (mqttSettings.user && mqttSettings.password) {
|
|
|
|
options.username = mqttSettings.user;
|
|
|
|
options.password = mqttSettings.password;
|
|
|
|
}
|
|
|
|
|
2018-06-26 10:33:26 -07:00
|
|
|
if (mqttSettings.client_id) {
|
|
|
|
logger.debug(`Using MQTT client ID: '${mqttSettings.client_id}'`);
|
|
|
|
options.clientId = mqttSettings.client_id;
|
|
|
|
}
|
|
|
|
|
2018-08-17 09:39:45 -07:00
|
|
|
if (mqttSettings.hasOwnProperty('reject_unauthorized') && !mqttSettings.reject_unauthorized) {
|
|
|
|
logger.debug(`MQTT reject_unauthorized set false, ignoring certificate warnings.`);
|
2018-08-17 09:22:27 -07:00
|
|
|
options.rejectUnauthorized = false;
|
2018-08-17 09:15:44 -07:00
|
|
|
}
|
2018-06-26 10:33:26 -07:00
|
|
|
|
2018-04-18 09:25:40 -07:00
|
|
|
this.client = mqtt.connect(mqttSettings.server, options);
|
|
|
|
|
|
|
|
// Register callbacks.
|
2018-04-23 09:17:47 -07:00
|
|
|
this.client.on('connect', () => {
|
|
|
|
this.handleConnect();
|
|
|
|
callback();
|
|
|
|
});
|
2018-04-25 11:54:41 -07:00
|
|
|
|
2018-04-18 09:25:40 -07:00
|
|
|
this.client.on('message', this.handleMessage);
|
|
|
|
|
|
|
|
// Set timer at interval to check if connected to MQTT server.
|
|
|
|
const interval = 10 * 1000; // seconds * 1000.
|
|
|
|
this.connectionTimer = setInterval(() => {
|
|
|
|
if (this.client.reconnecting) {
|
|
|
|
logger.error('Not connected to MQTT server!');
|
|
|
|
}
|
|
|
|
}, interval);
|
|
|
|
|
|
|
|
this.onMessage = onMessage;
|
2018-04-25 11:54:41 -07:00
|
|
|
this.subscriptions = subscriptions;
|
2018-04-18 09:25:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
disconnect() {
|
|
|
|
clearTimeout(this.connectionTimer);
|
|
|
|
this.connectionTimer = null;
|
|
|
|
|
2018-05-15 09:42:26 -07:00
|
|
|
this.publish('bridge/state', 'offline', {retain: true, qos: 0}, () => {
|
2018-04-18 11:53:22 -07:00
|
|
|
logger.info('Disconnecting from MQTT server');
|
|
|
|
this.client.end();
|
|
|
|
});
|
2018-04-18 09:25:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
handleConnect() {
|
|
|
|
logger.info('Connected to MQTT server');
|
2018-05-15 09:42:26 -07:00
|
|
|
this.publish('bridge/state', 'online', {retain: true, qos: 0});
|
2018-08-28 12:55:00 -07:00
|
|
|
this.subscriptions.forEach((topic) => this.subscribe(topic));
|
|
|
|
}
|
|
|
|
|
|
|
|
subscribe(topic) {
|
|
|
|
this.client.subscribe(topic);
|
2018-04-18 09:25:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
handleMessage(topic, message) {
|
|
|
|
if (this.onMessage) {
|
|
|
|
this.onMessage(topic, message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-17 08:20:46 -07:00
|
|
|
publish(topic, payload, options, callback, baseTopic) {
|
2018-08-09 09:23:04 -07:00
|
|
|
topic = this.prefixTopic(topic, baseTopic);
|
2018-04-18 09:25:40 -07:00
|
|
|
|
|
|
|
if (!this.client || this.client.reconnecting) {
|
|
|
|
logger.error(`Not connected to MQTT server!`);
|
|
|
|
logger.error(`Cannot send message: topic: '${topic}', payload: '${payload}`);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
logger.info(`MQTT publish, topic: '${topic}', payload: '${payload}'`);
|
2018-05-15 09:42:26 -07:00
|
|
|
this.client.publish(topic, payload, options, callback);
|
2018-04-18 09:25:40 -07:00
|
|
|
}
|
2018-05-30 09:09:24 -07:00
|
|
|
|
2018-08-09 09:23:04 -07:00
|
|
|
prefixTopic(topic, baseTopic) {
|
|
|
|
baseTopic = baseTopic ? baseTopic : settings.get().mqtt.base_topic;
|
|
|
|
return `${baseTopic}/${topic}`;
|
|
|
|
}
|
|
|
|
|
2018-05-30 09:09:24 -07:00
|
|
|
log(type, message) {
|
|
|
|
const payload = {type: type, message: message};
|
|
|
|
this.publish('bridge/log', JSON.stringify(payload), {retain: false});
|
|
|
|
}
|
2018-04-18 09:25:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = MQTT;
|