mirror of
https://github.com/lehanspb/tuya-mqtt.git
synced 2025-12-16 17:54:36 +00:00
Merge pull request #21 from GadgetAngel/dev
This update allows for an essential TuyAPI command to be implemented and fixes issues with the TuyaColorLight.prototype.setColor Method label:enhancement
This commit is contained in:
62
README.md
62
README.md
@@ -42,14 +42,19 @@ node tuya-mqtt.js
|
||||
|
||||
// For debugging purpose, to use DEBUG : https://www.npmjs.com/package/debug
|
||||
|
||||
//on Linux machines at the bash command prompt:
|
||||
//on Linux machines at the bash command prompt, to turn ON DEBUG:
|
||||
DEBUG=* tuya-mqtt.js
|
||||
|
||||
//on Linux machines at the bash command prompt, to turn OFF DEBUG:
|
||||
DEBUG=-* tuya-mqtt.js
|
||||
|
||||
// on Windows machines at the cmd.exe command prompt:
|
||||
Set DEBUG=* tuya-mqtt.js
|
||||
// on Windows machines at the cmd.exe command prompt, to turn ON DEBUG:
|
||||
Set DEBUG=* & node c:/openhab2/userdata/etc/scripts/tuya-mqtt.js
|
||||
|
||||
// on Windows machines at the cmd.exe command prompt, to turn OFF DEBUG:
|
||||
Set DEBUG=-* & node c:/openhab2/userdata/etc/scripts/tuya-mqtt.js
|
||||
```
|
||||
URL to [DEBUG](https://www.npmjs.com/package/debug)
|
||||
URL to install [DEBUG](https://www.npmjs.com/package/debug)
|
||||
|
||||
|
||||
|
||||
@@ -68,7 +73,12 @@ Change device state (by topic):
|
||||
- tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/command/toggle
|
||||
- tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/command/TOGGLE
|
||||
- tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/command/{ "dps": 1, "set": true }
|
||||
- tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/command/{ "dps": 7, "set": true }
|
||||
- tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/command/{ "multiple": true, "data": { "1": true, "7": true } }
|
||||
- tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/command/{ "schema": true }
|
||||
- tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/command/{ "multiple": true, "data": { "1": true, "2": "scene_4" } }
|
||||
- tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/command/{ "multiple": true, "data":
|
||||
{ "1": true, "2": "scene", "6": "c479000025ffc3" } }
|
||||
|
||||
Change device state (by payload)
|
||||
Use with OpenHAB 2.X MQTT bindings or others where only a single command topic is preferred:
|
||||
@@ -86,13 +96,18 @@ NOTE: notice that nothing follows the word command, DO NOT but a "/" in after co
|
||||
"toggle"
|
||||
"TOGGLE"
|
||||
"{ \"dps\": 1, \"set\": true }"
|
||||
"{ \"dps\": 7, \"set\": true }"
|
||||
"{ \"multiple\": true, \"data\": { \"1\": true, \"7\": true } }"
|
||||
"{ \"schema\": true }"
|
||||
"{ \"multiple\": true, \"data\": { \"1\": true, \"2\": \"scene_4\" } }"
|
||||
"{ \"multiple\": true, \"data\": { \"1\": true, \"2\": \"scene\", \"6\": \"c479000025ffc3\" } }"
|
||||
|
||||
Change color of lightbulb (payload as HSB-Color)
|
||||
tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/color
|
||||
|
||||
Example:
|
||||
64,0,100
|
||||
0,0,89
|
||||
```
|
||||
|
||||
### MQTT Topic's (read data)
|
||||
@@ -125,9 +140,9 @@ Switch tuya_kitchen_coffeemachine_mqtt "Steckdose Kaffeemaschine" <socket> (<GRO
|
||||
}
|
||||
|
||||
Switch tuya_livingroom_ledstrip_tv "LED Regal" <lightbulb> (<GROUPS>) ["Lighting"] {
|
||||
mqtt="<[broker:tuya/lightbulb/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/state:state:default:.*],
|
||||
>[broker:tuya/lightbulb/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/command/on:command:ON:true],
|
||||
>[broker:tuya/lightbulb/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/command/off:command:OFF:false]"
|
||||
mqtt="<[broker:tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/state:state:default:.*],
|
||||
>[broker:tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/command/on:command:ON:true],
|
||||
>[broker:tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/command/off:command:OFF:false]"
|
||||
}
|
||||
|
||||
```
|
||||
@@ -140,7 +155,7 @@ Group gTuyaLivingColor "Tuya color group" <lightbulb>
|
||||
Color tuya_livingroom_colorpicker "Stehlampe farbe" (LivingDining)
|
||||
|
||||
String tuya_livingroom_ledstrip_tv_color "Set color [%s]" (gTuyaLivingColor, LivingDining) {
|
||||
mqtt=">[broker:tuya/lightbulb/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/color:command:*:default]"
|
||||
mqtt=">[broker:tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/color:command:*:default]"
|
||||
}
|
||||
|
||||
|
||||
@@ -195,12 +210,12 @@ Bridge mqtt:broker:myUnsecureBroker [ host="localhost", secure=false ]
|
||||
|
||||
Thing mqtt:topic:myCustomMQTT {
|
||||
Channels:
|
||||
Type switch : tuya_kitchen_coffeemachine_mqtt "Kitchen Coffee Machine MQTT Channel" [
|
||||
Type switch : tuya_kitchen_coffeemachine_mqtt_channel "Kitchen Coffee Machine MQTT Channel" [
|
||||
stateTopic="tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/state",
|
||||
commandTopic="tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/command",
|
||||
|
||||
// optional custom mqtt-payloads for ON and OFF
|
||||
on="{ \"dps": 1, \"set\": true },
|
||||
on="{ \"dps\": 1, \"set\": true }",
|
||||
off="0"
|
||||
]
|
||||
}
|
||||
@@ -209,7 +224,7 @@ Bridge mqtt:broker:myUnsecureBroker [ host="localhost", secure=false ]
|
||||
|
||||
# *.item Example
|
||||
Switch tuya_kitchen_coffeemachine_mqtt "Kitchen Coffee Machine Switch" <socket> (gKitchen, gTuya) ["Switchable"] {
|
||||
channel="mqtt:topic:myMosquitto:tuya:coffeemachine"
|
||||
channel="mqtt:topic:myUnsecureBroker:myCustomMQTT:tuya_kitchen_coffeemachine_mqtt_channel"
|
||||
}
|
||||
|
||||
```
|
||||
@@ -221,17 +236,18 @@ For one RGB bulb you would need a separate channel with the command topic set to
|
||||
|
||||
Bridge mqtt:broker:myUnsecureBroker [ host="localhost", secure=false ]
|
||||
{
|
||||
|
||||
Type colorHSB : livingroom_floorlamp_1_color "Livingroom floorlamp color MQTT Channel" [
|
||||
stateTopic="tuya/lightbulb/05200399bcddc2e02ec9/b58cf92e8bc5c899/192.168.178.49/state",
|
||||
commandTopic="tuya/lightbulb/05200399bcddc2e02ec9/b58cf92e8bc5c899/192.168.178.49/color"
|
||||
]
|
||||
|
||||
Thing mqtt:topic:myCustomMQTT {
|
||||
Channels:
|
||||
Type colorHSB : livingroom_floorlamp_1_color "Livingroom floorlamp color MQTT Channel" [
|
||||
stateTopic="tuya/05200399bcddc2e02ec9/b58cf92e8bc5c899/192.168.178.49/state",
|
||||
commandTopic="tuya/05200399bcddc2e02ec9/b58cf92e8bc5c899/192.168.178.49/color"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
# *.item Example
|
||||
Color tuya_livingroom_colorpicker "Floorlamp colorpicker" (gLivingroom){
|
||||
channel="mqtt:topic:myMosquitto:tuya:livingroom_floorlamp_1_color"
|
||||
channel="mqtt:topic:myUnsecureBroker:myCustomMQTT:livingroom_floorlamp_1_color"
|
||||
}
|
||||
|
||||
```
|
||||
@@ -241,9 +257,15 @@ Color tuya_livingroom_colorpicker "Floorlamp colorpicker" (gLivingroom){
|
||||
|
||||
Switch item=tuya_kitchen_coffeemachine_mqtt
|
||||
|
||||
# turn the color bulb off or on
|
||||
Switch item=tuya_livingroom_colorpicker label="RGB lamp [%s]"
|
||||
|
||||
# pick the color level to send to the color bulb via MQTT color Channel
|
||||
Slider item=tuya_livingroom_colorpicker label="RGB lamp level [%s]" minValue=0 maxValue=100 step=1
|
||||
|
||||
# color picked and sent via MQTT Color channel
|
||||
Colorpicker item=tuya_livingroom_colorpicker label="RGB lamp color [%s]" icon="colorpicker" sendFrequency=30000
|
||||
|
||||
# Colorpicker for Lightbulbs
|
||||
Colorpicker item=tuya_livingroom_colorpicker label="RGB lamp color" sendFrequency=30000
|
||||
|
||||
```
|
||||
|
||||
|
||||
131
tuya-color.js
131
tuya-color.js
@@ -26,6 +26,58 @@ function TuyaColorLight() {
|
||||
this.dps = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate color value from given brightness percentage
|
||||
* @param (Integer) percentage 0-100 percentage value
|
||||
* @returns (Integer) color value from 25 - 255
|
||||
* @private
|
||||
*/
|
||||
TuyaColorLight.prototype._convertBrightnessPercentageToVal = function(brt_percentage){
|
||||
// the brightness scale does not start at 0 but starts at 25 - 255
|
||||
// this linear equation is a better fit to the conversion to 255 scale
|
||||
var tmp = Math.round(2.3206*brt_percentage+22.56);
|
||||
debug('Converted brightness percentage ' + brt_percentage + ' to: ' + tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate percentage from brightness color value
|
||||
* @param brt_val 25 - 255 brightness color value
|
||||
* @returns {Integer} 0 - 100 integer percent
|
||||
* @private
|
||||
*/
|
||||
TuyaColorLight.prototype._convertValtoBrightnessPercentage = function(brt_val){
|
||||
var tmp = Math.round( (brt_val-22.56)/2.3206);
|
||||
debug('Converted brightness value ' + brt_val + ' to: ' + tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate color value from given saturation percentage OR color temperature percentage
|
||||
* @param (Integer) temp_percentage 0-100 percentage value
|
||||
* @returns {Integer} saturation or color temperature value from 0 - 255
|
||||
* @private
|
||||
*/
|
||||
TuyaColorLight.prototype._convertSATorColorTempPercentageToVal = function(temp_percentage){
|
||||
// the saturation OR temperature scale does start at 0 - 255
|
||||
// this is a perfect linear equation fit for the saturation OR temperature scale conversion
|
||||
var tmp = Math.round(((2.5498*temp_percentage)-0.4601));
|
||||
debug('Converted saturation OR temperature percentage ' + temp_percentage + ' to: ' + tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate percentage from saturation value OR color temperature value
|
||||
* @param temp_val 0 - 255 saturation or color temperature value
|
||||
* @returns {Integer} 0 - 100 integer percent
|
||||
* @private
|
||||
*/
|
||||
TuyaColorLight.prototype._convertValtoSATorColorTempPercentage = function(temp_val){
|
||||
var tmp = Math.round( (temp_val+0.4601/2.5498));
|
||||
debug('Converted saturation OR temperature value ' + temp_val + ' to: ' + tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate color value from given percentage
|
||||
* @param {Integer} percentage 0-100 percentage value
|
||||
@@ -105,6 +157,18 @@ TuyaColorLight.prototype._ValIsHex = function (h) {
|
||||
return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(h)
|
||||
};
|
||||
|
||||
/**
|
||||
* get width Hex digits from given value
|
||||
* @param (Integer) value, decimal value to convert to hex string
|
||||
* @param (Integer) width, the number of hex digits to return
|
||||
* @returns {string} value as HEX containing (width) number of hex digits
|
||||
* @private
|
||||
*/
|
||||
TuyaColorLight.prototype._getHex = function (value,width){
|
||||
var hex = (value+Math.pow(16, width)).toString(16).slice(-width).toLowerCase();
|
||||
debug('value: ' + value + ' hex: ' + hex);
|
||||
return hex;
|
||||
}
|
||||
/**
|
||||
* get AlphaHex from percentage brightness
|
||||
* @param {Integer} brightness
|
||||
@@ -138,7 +202,8 @@ TuyaColorLight.prototype.setSaturation = function (value) {
|
||||
*/
|
||||
TuyaColorLight.prototype.setBrightness = function (value) {
|
||||
this.brightness = value;
|
||||
var newValue = this._convertPercentageToVal(value);
|
||||
//var newValue = this._convertPercentageToVal(value);
|
||||
var newValue = this._convertBrightnessPercentageToVal(value);
|
||||
debug("BRIGHTNESS from UI: " + value + ' Converted from 100 to 255 scale: ' + newValue);
|
||||
}
|
||||
|
||||
@@ -219,29 +284,65 @@ TuyaColorLight.prototype.getDps = function () {
|
||||
|
||||
var lightness = Math.round(this.brightness / 2);
|
||||
var brightness = this.brightness;
|
||||
var apiBrightness = this._convertPercentageToVal(brightness);
|
||||
var alphaBrightness = this._getAlphaHex(brightness);
|
||||
//var apiBrightness = this._convertPercentageToVal(brightness);
|
||||
var apiBrightness = this._convertBrightnessPercentageToVal(brightness);
|
||||
|
||||
//var alphaBrightness = this._getAlphaHex(brightness);
|
||||
var alphaBrightness = this._getHex(apiBrightness,2);
|
||||
|
||||
var hexColor1 = convert.hsl.hex(color.H, color.S, lightness);
|
||||
|
||||
var hexColor2 = convert.hsl.hex(0, 0, lightness);
|
||||
//var hexColor2 = convert.hsl.hex(0, 0, lightness);
|
||||
var hexColor2 = this._getHex(color.H,4);
|
||||
hexColor2 = hexColor2 + this._getHex(this._convertSATorColorTempPercentageToVal(color.S),2);
|
||||
|
||||
var colorTemperature = this.colorTemperature;
|
||||
|
||||
var lightColor = (hexColor1 + hexColor2 + alphaBrightness).toLowerCase();
|
||||
|
||||
var temperature = (this.colorMode === 'colour') ? 255 : this._convertColorTemperature(colorTemperature);
|
||||
//var temperature = (this.colorMode === 'colour') ? 255 : this._convertColorTemperature(colorTemperature);
|
||||
// color temperature percentage is at a fixed 51%
|
||||
var temperature = this._convertSATorColorTempPercentageToVal(51);
|
||||
|
||||
dpsTmp = {
|
||||
'1': true,
|
||||
'2': this.colorMode,
|
||||
'3': apiBrightness,
|
||||
'4': temperature,
|
||||
'5': lightColor
|
||||
// '6' : hexColor + hexColor + 'ff'
|
||||
};
|
||||
debug("dps", dpsTmp);
|
||||
return dpsTmp;
|
||||
// if the bulb is in colour mode than the dps 3 and dps 4 are ignored by the bulb but if you set it now
|
||||
// some tuya bulbs will ignore dps 5 because you set dps 3 or dps 4
|
||||
// FOR colour mode the bulb looks at dps 1, dps 2, and dps 5.
|
||||
// DPS 5 is in the following format:
|
||||
// HSL to HEX format are the leftmost hex digits (hex digits 14 - 9)
|
||||
// hex digits 8 - 5 are the HSB/HSL Hue value in HEX format
|
||||
// hex digits 4 - 3 are the HSB/HSL Saturation percentage as a value (converted to 0-255 scale) in HEX format
|
||||
// hex digits 2 - 1 are the HSB Brightness percentage as a value (converted to 25-255 scale) in HEX format
|
||||
|
||||
if (this.colorMode === 'colour') {
|
||||
dpsTmp = {
|
||||
'1': true,
|
||||
'2': this.colorMode,
|
||||
//'3': apiBrightness,
|
||||
//'4': temperature,
|
||||
'5': lightColor
|
||||
// '6' : hexColor + hexColor + 'ff'
|
||||
};
|
||||
debug("dps", dpsTmp);
|
||||
return dpsTmp;
|
||||
}
|
||||
|
||||
// if the bulb is in white mode then the dps 5 value is ignored by the bulb but if you set dps 5 value now
|
||||
// you may not get a response back from the bulb on the dps values
|
||||
// FOR white mode the bulb looks at dps 1, dps 2, dps 3 and dps 4
|
||||
// DPS 3 is the HSB/HSL Brightness percentage converted to a value from 25 to 255 in decimal format
|
||||
// DPS 4 is the HSB/HSL Saturation percentage converted to a value from 0 to 255 in decimal format
|
||||
if (this.colorMode === 'white'){
|
||||
dpsTmp = {
|
||||
'1': true,
|
||||
'2': this.colorMode,
|
||||
'3': apiBrightness,
|
||||
'4': temperature,
|
||||
//'5': lightColor
|
||||
// '6' : hexColor + hexColor + 'ff'
|
||||
};
|
||||
debug("dps", dpsTmp);
|
||||
return dpsTmp;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TuyaColorLight;
|
||||
@@ -265,6 +265,12 @@ var TuyaDevice = (function () {
|
||||
});
|
||||
}
|
||||
|
||||
TuyaDevice.prototype.schema = function(obj){
|
||||
return this.get(obj).then((status) => {
|
||||
debug("get", obj);
|
||||
});
|
||||
}
|
||||
|
||||
TuyaDevice.prototype.setColor = function (hexColor) {
|
||||
if (!this.connected) return;
|
||||
debugColor("Set color to: ", hexColor);
|
||||
@@ -318,4 +324,4 @@ var TuyaDevice = (function () {
|
||||
return TuyaDevice;
|
||||
}());
|
||||
|
||||
module.exports = TuyaDevice;
|
||||
module.exports = TuyaDevice;
|
||||
|
||||
18
tuya-mqtt.js
18
tuya-mqtt.js
@@ -190,6 +190,22 @@ mqtt_client.on('message', function (topic, message) {
|
||||
device.switch(command).then((data) => {
|
||||
debug("set device status completed", data);
|
||||
});
|
||||
}
|
||||
if (command.schema === true) {
|
||||
// this command is very useful. IT IS A COMMAND. It's place under the command topic.
|
||||
// It's the ONLY command that does not use device.set to get a result.
|
||||
// You have to use device.get and send the get method an exact JSON string of { schema: true }
|
||||
// This schema command does NOT
|
||||
// change the state of the device, all it does is query the device
|
||||
// as a confirmation that all communications are working properly.
|
||||
// Otherwise you have to physically change the state of the device just to
|
||||
// find out if you can talk to it. If this command returns no errors than
|
||||
// we know we are have an established communication channel. This is a native TuyAPI call that
|
||||
// the TuyAPI interface defines (its only available via the GET command.
|
||||
// this call returns a object of results
|
||||
device.schema(command).then((data) => {
|
||||
});
|
||||
debug("get (schema) device status completed");
|
||||
} else {
|
||||
device.set(command).then((data) => {
|
||||
debug("set device status completed", data);
|
||||
@@ -355,4 +371,4 @@ var tester = new MQTT_Tester();
|
||||
function onExit() {
|
||||
TuyaDevice.disconnectAll();
|
||||
if (tester) tester.destroy();
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user