UNPKG

homebridge-sonoff-tasmota-mqtt-hsb

Version:

A homebridge plugin for RGB LED devices running the Sonoff-Tasmota firmware, such as the MagicHome LED strip controller.

198 lines (181 loc) 5.45 kB
"use strict"; let Service, Characteristic; const mqtt = require("mqtt"); const contextEnum = Object.freeze({ fromSetValue: "fromSetValue" }); module.exports = homebridge => { Service = homebridge.hap.Service; Characteristic = homebridge.hap.Characteristic; homebridge.registerAccessory( "homebridge-sonoff-tasmota-mqtt-hsb", "sonoff-tasmota-mqtt-hsb", SonoffTasmotaMqttHsb ); }; class SonoffTasmotaMqttHsb { constructor(log, config) { this.log = log; this.name = config["name"]; this.url = config["url"]; this.client_Id = "mqttjs_" + Math.random() .toString(16) .substr(2, 8); this.options = { keepalive: 10, clientId: this.client_Id, protocolId: "MQTT", protocolVersion: 4, clean: true, reconnectPeriod: 1000, connectTimeout: 30 * 1000, will: { topic: "WillMsg", payload: "Connection Closed abnormally..!", qos: 0, retain: false }, username: config["username"], password: config["password"], rejectUnauthorized: false }; this.caption = config["caption"]; this.retain = config["retain"]; this.topics = config["topics"]; // Accessory status this.on = false; this.hue = 0; // 0-360 this.saturation = 0; // 0-100 this.brightness = 0; // 0-100 this.service = new Service.Lightbulb(this.name); this.service .getCharacteristic(Characteristic.On) .on("get", this.getStatus.bind(this)) .on("set", this.setStatus.bind(this)); this.service .getCharacteristic(Characteristic.Brightness) .on("get", this.getBrightness.bind(this)) .on("set", this.setBrightness.bind(this)); this.service .getCharacteristic(Characteristic.Hue) .on("get", this.getHue.bind(this)) .on("set", this.setHue.bind(this)); this.service .getCharacteristic(Characteristic.Saturation) .on("get", this.getSaturation.bind(this)) .on("set", this.setSaturation.bind(this)); // connect to MQTT broker this.client = mqtt.connect( this.url, this.options ); this.client.on("error", err => { this.log("Error event on MQTT:", err); }); this.client.on("message", this.mqttHandleMessage.bind(this)); this.client.subscribe(this.topics.status); } mqttHandleMessage(topic, messageBuffer) { if (topic !== this.topics.status) return; const message = messageBuffer.toString(); try { // Pull the HSB and power values from the message // eg message: {"POWER":"ON","Dimmer":100,"Color":"FF7F81","HSBColor":"359,50,100","Channel":[100,50,51]} const { HSBColor: hsb, POWER: power } = JSON.parse(message); if (power !== undefined) { this.on = power === "ON"; } if (hsb !== undefined) { [this.hue, this.saturation, this.brightness] = hsb.split(","); if (this.brightness <= 0) this.on = false; } // Update the accessory's state this.service .getCharacteristic(Characteristic.On) .setValue(this.on, undefined, contextEnum.fromSetValue); this.service .getCharacteristic(Characteristic.Hue) .setValue(this.hue, undefined, contextEnum.fromSetValue); this.service .getCharacteristic(Characteristic.Saturation) .setValue(this.saturation, undefined, contextEnum.fromSetValue); this.service .getCharacteristic(Characteristic.Brightness) .setValue(this.brightness, undefined, contextEnum.fromSetValue); this.log( `Recieved message: power: ${this.on}, hue:${this.hue}, saturation:${ this.saturation }, brightness:${this.brightness}` ); } catch (error) { this.log( `Error parsing message from ${this.topics.status} topic:`, message, error ); } } mqttPublishHsb() { const message = `${this.hue},${this.saturation},${this.brightness},`; this.client.publish(this.topics.setHsb, message, { retain: this.retain }); this.log( `Sent command: hue:${this.hue}, saturation:${ this.saturation }, brightness:${this.brightness}` ); } mqttPublishStatus() { const message = this.on ? "ON" : "OFF"; this.client.publish(this.topics.setOn, message, { retain: this.retain }); this.log(`Sent command: turn ${this.on ? "on" : "off"}`); } getStatus(callback) { callback(null, this.on); } setStatus(status, callback, context) { if (context !== contextEnum.fromSetValue) { this.on = status; this.mqttPublishStatus(); } callback(); } getBrightness(callback) { callback(null, this.brightness); } setBrightness(brightness, callback, context) { if (context !== contextEnum.fromSetValue) { this.brightness = brightness; this.mqttPublishHsb(); } callback(); } getHue(callback) { callback(null, this.hue); } setHue(hue, callback, context) { if (context !== contextEnum.fromSetValue) { this.hue = hue; this.mqttPublishHsb(); } callback(); } getSaturation(callback) { callback(null, this.saturation); } setSaturation(saturation, callback, context) { if (context !== contextEnum.fromSetValue) { this.saturation = saturation; this.mqttPublishHsb(); } callback(); } getServices() { return [this.service]; } }