xiaomi-mqtt
Version:
Bridge between Xiaomi Mi Smart Home Gateway and Mqtt broker.
139 lines (109 loc) • 3.59 kB
JavaScript
;
var mqtt = require('mqtt');
var Utils = require('./utils.js').Utils;
var topic_from, topic_mode, topic_to;
var config, package_name;
var get_id_list, read, write, log;
var client;
module.exports = {
Mqtt: Mqtt
}
function Mqtt(params) {
config = params.config;
package_name = params.package_name;
get_id_list = params.get_id_list;
read = params.read;
write = params.write;
log = params.log;
log.trace("config " + JSON.stringify(config, null, 2));
}
Mqtt.prototype.connect = function() {
var options = {}
var url = config.mqtt.url;
var topic_prefix = config.mqtt.topic_prefix || "xiaomi";
topic_mode = config.mqtt.topic_mode || "short";
topic_from = topic_prefix + '/from';
topic_to = topic_prefix + '/to';
options.username = config.mqtt.username || null;
options.password = config.mqtt.password || null;
options.port = config.mqtt.port || 1883;
options.clientId = package_name+"_"+Math.random().toString(16).substr(2, 8);
log.info("clientId = " + options.clientId);
client = mqtt.connect(url, options);
var signals = { 'SIGINT': 2, 'SIGTERM': 15 };
Object.keys(signals).forEach(function (signal) {
process.on(signal, function () {
log.info("Got " + signal + " closing mqtt connection.");
this.end();
}.bind(this));
}.bind(this));
var timeout = setTimeout(function() {
if (!client.connected) {
log.error("Mqtt connect error! url = "+url+":"+options.port);
}
}, 5000);
client.on('connect', function () {
log.info("Mqtt connected, url = "+url+":"+options.port);
client.subscribe(topic_to+"/#");
log.info("Mqtt subscribe " + topic_to+"/#");
var payload = {"cmd":"xm" ,"msg":"xiaomi-mqtt started."};
client.publish(topic_from, JSON.stringify(payload));
});
client.on('message', function (topic, buffer) {
var payload = buffer.toString();
var msg;
try {
payload = JSON.parse(payload);
log.trace("Mqtt to " + payload);
} catch(e) {
msg = "invalid JSON format >"+payload+"<";
payload = {"cmd":"xm" ,"msg":msg};
log.warn(msg);
client.publish(topic_from, JSON.stringify(payload));
return;
}
switch(topic) {
case topic_to+"/read":
read(payload.sid);
break;
case topic_to+"/get_id_list":
get_id_list(payload.sid);
break;
case topic_to+"/write":
write(payload);
break;
default:
log.warn("Mqtt topic unknown.");
}
});
client.on('close', function() {
log.info(package_name+"-client closed, shutting down.");
process.exit();
});
}
Mqtt.prototype.end = function() {
var payload = {"cmd":"xm" ,"msg":"xiaomi-mqtt stopped."};
client.publish(topic_from, JSON.stringify(payload));
client.end();
}
Mqtt.prototype.publish = function(payload) {
if (topic_mode == 'short' || topic_mode == 'both') {
client.publish(topic_from, JSON.stringify(payload));
}
if (topic_mode == 'full' || topic_mode == 'both') {
if (payload.sid && payload.cmd && payload.model) {
var ft = topic_from +'/'+ payload.sid +'/'+ payload.cmd +'/'+ payload.model;
if (payload.data.status) {
client.publish(ft +'/status', JSON.stringify(payload));
} else {
client.publish(ft, JSON.stringify(payload));
}
} else {
// Legacy if we send nothing
if (topic_mode == 'full' ) {
client.publish(topic_from, JSON.stringify(payload));
}
}
}
log.trace("Mqtt from " + JSON.stringify(payload));
}