Files
tuya-mqtt/tuya-mqtt.js
2019-02-09 17:24:24 +01:00

248 lines
7.1 KiB
JavaScript

const mqtt = require('mqtt');
const TuyaDevice = require('./tuya-device');
const debug = require('debug')('tuya-mqtt');
const debugColor = require('debug')('color');
const debugMqtt = require('debug')('mqtt');
const debugTuya = require('debug')('tuyAPI-Events');
const debugError = require('debug')('error');
var cleanup = require('./cleanup').Cleanup(onExit);
function bmap(istate) {
return istate ? 'ON' : "OFF";
}
function boolToString(istate) {
return istate ? 'true' : "false";
}
var connected = undefined;
var CONFIG = undefined;
try {
CONFIG = require("./config");
} catch (e) {
console.error("Configuration file not found")
debugError(e)
process.exit(1)
}
if (typeof CONFIG.qos == "undefined") {
CONFIG.qos = 2;
}
if (typeof CONFIG.retain == "undefined") {
CONFIG.retain = false;
}
const mqtt_client = mqtt.connect({
host: CONFIG.host,
port: CONFIG.port,
username: CONFIG.mqtt_user,
password: CONFIG.mqtt_pass,
});
mqtt_client.on('connect', function (err) {
debugMqtt("Verbindung mit MQTT-Server hergestellt");
connected = true;
var topic = CONFIG.topic + '#';
mqtt_client.subscribe(topic, {
retain: CONFIG.retain,
qos: CONFIG.qos
});
});
mqtt_client.on("reconnect", function (error) {
if (connected) {
debugMqtt("Verbindung mit MQTT-Server wurde unterbrochen. Erneuter Verbindungsversuch!");
} else {
debugMqtt("Verbindung mit MQTT-Server konnte nicht herrgestellt werden.");
}
connected = false;
});
mqtt_client.on("error", function (error) {
debugMqtt("Verbindung mit MQTT-Server konnte nicht herrgestellt werden.", error);
connected = false;
});
/**
* execute function on topic message
*/
function boolToString(istate) {
return istate == 1 ? 'on' : "off";
}
function convertMessage(message) {
var status = message.toString();
status = boolToString(status);
status = status.toLowerCase();
return status;
}
mqtt_client.on('message', function (topic, message) {
try {
var cMessage = convertMessage(message);
var topic = topic.split("/");
var options = {
type: topic[1],
id: topic[2],
key: topic[3],
ip: topic[4],
};
var exec = topic[5];
if (options.type == "socket" || options.type == "lightbulb") {
debug("device", options);
debug("message", cMessage);
var device = new TuyaDevice(options);
if (exec == "command") {
var status = topic[6];
if (status == null) {
device.switch(cMessage);
} else {
device.switch(status);
}
}
if (exec == "color") {
var color = message.toString();
color = color.toLowerCase();
debugColor("topic: ", topic);
debugColor("onColor: ", color);
device.setColor(color);
}
}
} catch (e) {
debugError(e);
}
});
/**
* Publish current TuyaDevice state to MQTT-Topic
* @param {TuyaDevice} device
* @param {boolean} status
*/
function publishStatus(device, status) {
if (mqtt_client.connected == true) {
try {
var type = device.type;
var tuyaID = device.options.id;
var tuyaKey = device.options.key;
var tuyaIP = device.options.ip;
if (typeof tuyaID != "undefined" && typeof tuyaKey != "undefined" && typeof tuyaIP != "undefined") {
var topic = CONFIG.topic + type + "/" + tuyaID + "/" + tuyaKey + "/" + tuyaIP + "/state";
mqtt_client.publish(topic, status, {
retain: CONFIG.retain,
qos: CONFIG.qos
});
debugTuya("mqtt status updated to:" + topic + " -> " + status);
} else {
debugTuya("mqtt status not updated");
}
} catch (e) {
debugError(e);
}
}
}
function publishColorState(device, state) {
}
/**
* publish all dps-values to topic
* @param {TuyaDevice} device
* @param {Object} dps
*/
function publishDPS(device, dps) {
if (mqtt_client.connected == true) {
try {
var type = device.type;
var tuyaID = device.options.id;
var tuyaKey = device.options.key;
var tuyaIP = device.options.ip;
if (typeof tuyaID != "undefined" && typeof tuyaKey != "undefined" && typeof tuyaIP != "undefined") {
var topic = CONFIG.topic + type + "/" + tuyaID + "/" + tuyaKey + "/" + tuyaIP + "/dps";
var data = JSON.stringify(dps);
debugTuya("mqtt dps updated to:" + topic + " -> ", data);
mqtt_client.publish(topic, data, {
retain: CONFIG.retain,
qos: CONFIG.qos
});
Object.keys(dps).forEach(function (key) {
var topic = CONFIG.topic + type + "/" + tuyaID + "/" + tuyaKey + "/" + tuyaIP + "/dps/" + key;
var data = JSON.stringify(dps[key]);
debugTuya("mqtt dps updated to:" + topic + " -> dps[" + key + "]", data);
mqtt_client.publish(topic, data, {
retain: CONFIG.retain,
qos: CONFIG.qos
});
});
} else {
debugTuya("mqtt dps not updated");
}
} catch (e) {
debugError(e);
}
}
}
/**
* event fires if TuyaDevice sends data
* @see TuyAPI (https://github.com/codetheweb/tuyapi)
*/
TuyaDevice.onAll('data', function (data) {
try {
debugTuya('Data from device ' + this.type + ' :', data);
var status = data.dps['1'];
if (typeof status != "undefined") {
publishStatus(this, bmap(status));
}
publishDPS(this, data.dps);
} catch (e) {
debugError(e);
}
});
/**
* MQTT connection tester
*/
function MQTT_Tester() {
this.interval = null;
function mqttConnectionTest() {
if (mqtt_client.connected != connected) {
connected = mqtt_client.connected;
if (connected) {
debugMqtt('MQTT-Server verbunden.');
} else {
debugMqtt('MQTT-Server nicht verbunden.');
}
}
}
this.destroy = function () {
clearInterval(this.interval);
this.interval = undefined;
}
this.connect = function () {
this.interval = setInterval(mqttConnectionTest, 1500);
mqttConnectionTest();
}
var constructor = (function (that) {
that.connect.call(that);
})(this);
}
var tester = new MQTT_Tester();
/**
* Function call on script exit
*/
function onExit() {
TuyaDevice.disconnectAll();
if (tester) tester.destroy();
};