Files
tuya-mqtt/tuya-color.js
GadgetAngel 4ea15db772 This update allows for an essential TuyAPI command to be implemented via the tuya-mqtt.exe MQTT server. {"schema": true} is the ONLY COMMAND that the TuyAPI GET method implements. Also fixes a problem with the setColor method of TuyaColorLight. When passing colorValue the curly braces are part of the colorValue string, but when you hit the .split to break up the string into Hue, Saturation and Brightness the curly braces are still considered part of the string so the Hue value was always returning a NaN value due to { was part of the Hue. Therefore I created a private function that strips off the beginning and ending curly braces so the right numeric values can be found.
{"schema": true} allows the user to establish that proper communications with the tuya device can occur WITHOUT actually changing the present STATE of the device.  This is the only command that will query the tuya device.

The current documentation says that you can query the tuya device over the "dps" TOPIC but from what I see the present state of the software does not force the tuya device to respond when using the "dps" TOPIC.

Since {"schema": true} is a command that forces a response from the tuya device, this command has been implemented under the "command" TOPIC. So "command" is the action and '{"schema": true}' becomes the command.  The response is returned just like all other commands.  I, use this command to guarantee communications has been established with the tuya device.  If this "schema" command fails, tuya-mqtt will indicate the result in the openhab.log file and then I, can find out what is physically wrong with the communications.  If this command fails the first time due to "socket" error and then goes through on the second attempt then I know that the error was due to TCP communications problem on initial startup.  This command helps as a work-a-round for the "ERROR: socket problem"
2019-04-20 17:50:38 -04:00

254 lines
7.3 KiB
JavaScript

const convert = require('color-convert');
const debug = require('debug')('TuyaColor');
/**
* Class to calculate settings for Tuya colors
*/
function TuyaColorLight() {
this.colorMode = 'white'; // or 'colour'
this.brightness = 100; // percentage value use _convertValToPercentage functions below.
this.color = {
H: 130,
S: 100,
L: 50
};
this.hue = this.color.H;
this.saturation = this.color.S;
this.lightness = this.color.L;
this.colorTemperature = 255;
this.colorTempMin = 153;
this.colorTempMax = 500;
this.dps = {};
}
/**
* calculate color value from given percentage
* @param {Integer} percentage 0-100 percentage value
* @returns {Integer} color value from 0-255
*/
TuyaColorLight.prototype._convertPercentageToVal = function (percentage) {
var tmp = Math.round(255 * (percentage / 100));
debug('Converted ' + percentage + ' to: ' + tmp);
return tmp;
};
/**
* calculate percentage from color value
* @param {Integer} val 0-255 color value
* @returns {Integer} HK-Value
*/
TuyaColorLight.prototype._convertValToPercentage = function (val) {
var tmp = Math.round((val / 255) * 100);
debug('Converted ' + val + ' to: ' + tmp);
return tmp;
};
/**
* converts color value to color temperature
* @param {Integer} val
* @returns {Integer} percentage from 0-100
*/
TuyaColorLight.prototype._convertColorTemperature = function (val) {
var tmpRange = this.colorTempMax - this.colorTempMin;
var tmpCalc = Math.round((val / this.colorTempMax) * 100);
debug('HK colorTemp Value: ' + val);
debug('HK colorTemp scale min : ' + this.colorTempMin);
debug('HK colorTemp scale max : ' + this.colorTempMax);
debug('HK colorTemp range (tmpRange): ' + tmpRange);
debug('HK colorTemp % tmpCalc: ' + tmpCalc);
var tuyaColorTemp = this._convertPercentageToVal(tmpCalc);
debug('HK tuyaColorTemp: ' + tuyaColorTemp);
return tuyaColorTemp;
};
/**
* Convert color temperature to HK
* @param {Integer} val
* @returns {Integer} HK-Value
*/
TuyaColorLight.prototype._convertColorTemperatureToHK = function (val) {
var tuyaColorTempPercent = this._convertValToPercentage(this.colorTemperature);
var tmpRange = this.colorTempMax - this.colorTempMin;
var tmpCalc = Math.round((tmpRange * (tuyaColorTempPercent / 100)) + this.colorTempMin);
var hkValue = Math.round(tmpCalc);
debug('Tuya color Temperature : ' + val);
debug('Tuya color temp Percent of 255: ' + tuyaColorTempPercent + '%');
debug('HK colorTemp scale min : ' + this.colorTempMin);
debug('HK colorTemp scale max : ' + this.colorTempMax);
debug('HK Color Temp Range: ' + tmpRange);
debug('HK range %: ' + tuyaColorTempPercent);
debug('HK Value: ' + hkValue);
return hkValue;
};
/**
* check if given String is HEX
* @param {String} h
* @returns {boolean}
*/
TuyaColorLight.prototype._ValIsHex = function (h) {
debug("Check if value is hex", h);
return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(h)
};
/**
* get AlphaHex from percentage brightness
* @param {Integer} brightness
* @return {string} brightness as HEX value
*/
TuyaColorLight.prototype._getAlphaHex = function (brightness) {
var i = brightness / 100;
var alpha = Math.round(i * 255);
var hex = (alpha + 0x10000).toString(16).substr(-2);
var perc = Math.round(i * 100);
debug('alpha percent: ' + perc + '% hex: ' + hex + ' alpha: ' + alpha);
return hex;
};
/**
* Set saturation from value
* @param {Integer} value
*/
TuyaColorLight.prototype.setSaturation = function (value) {
this.color.S = value;
this.saturation = value;
this.colorMode = 'colour';
debug('SET SATURATION: ' + value);
};
/**
* Set Brightness
* @param {Integer} value
*/
TuyaColorLight.prototype.setBrightness = function (value) {
this.brightness = value;
var newValue = this._convertPercentageToVal(value);
debug("BRIGHTNESS from UI: " + value + ' Converted from 100 to 255 scale: ' + newValue);
}
/**
* @param {} value
*/
TuyaColorLight.prototype.setHue = function (value) {
debug('SET HUE: ' + value);
debug('Saturation Value: ' + this.color.S);
this.color.H = value;
//check color and set colormode if necessary
debug("colormode", value, this.color.S);
if (value === 0 && this.color.S === 0) {
this.colorMode = 'white';
debug('SET Color Mode: \'white\'');
} else {
this.colorMode = 'colour';
debug('SET Color Mode: \'colour\' -- dahhhhhh british spelling \'coulour\' really is annoying... why you gotta be special?');
}
return {
color: this.color,
colorMode: this.colorMode,
hue: this.color.H,
saturation: this.saturation
};
};
/**
* Set HSL color
* @param {Integer} hue
* @param {Integer} saturation
* @param {Integer} brightness
*/
TuyaColorLight.prototype.setHSL = function (hue, saturation, brightness) {
this.setSaturation(saturation);
this.setBrightness(brightness);
this.setHue(hue);
}
TuyaColorLight.prototype._stripBraces = function (string) {
return string.slice(1,-1);
}
/**
* Set color from given string
* @param {String} colorValue could be HEX or HSL color type
* @returns {Object} dps settings for given color
*/
TuyaColorLight.prototype.setColor = function (colorValue) {
var colorValue2;
debug("Received color", colorValue);
colorValue2 = this._stripBraces(colorValue);
debug("colorValue2 = "+colorValue2);
if (this._ValIsHex(colorValue2)) {
debug("Color is Hex");
color = convert.hex.hsl(colorValue2);
} else {
debug("Color is HSL");
var color = colorValue2.split(",");
// convert strings to numbers
color.forEach(function (element, key) {
color[key] = parseInt(element, 10);
});
}
debug("Converted color as HSL", {
0: color[0] + " - " + typeof color[0],
1: color[1] + " - " + typeof color[1],
2: color[2] + " - " + typeof color[2]
})
this.setHSL(color[0], color[1], color[2]);
return this.getDps();
}
/**
* get dps settings for current color
* @returns {Object} dps settings
*/
TuyaColorLight.prototype.getDps = function () {
var color = this.color;
var lightness = Math.round(this.brightness / 2);
var brightness = this.brightness;
var apiBrightness = this._convertPercentageToVal(brightness);
var alphaBrightness = this._getAlphaHex(brightness);
var hexColor1 = convert.hsl.hex(color.H, color.S, lightness);
var hexColor2 = convert.hsl.hex(0, 0, lightness);
var colorTemperature = this.colorTemperature;
var lightColor = (hexColor1 + hexColor2 + alphaBrightness).toLowerCase();
var temperature = (this.colorMode === 'colour') ? 255 : this._convertColorTemperature(colorTemperature);
dpsTmp = {
'1': true,
'2': this.colorMode,
'3': apiBrightness,
'4': temperature,
'5': lightColor
// '6' : hexColor + hexColor + 'ff'
};
debug("dps", dpsTmp);
return dpsTmp;
}
module.exports = TuyaColorLight;