mirror of
https://github.com/lehanspb/tuya-mqtt.git
synced 2025-12-18 16:17:30 +00:00
Release 3.0.0
3.0.0 Release Major changes from 2.1.0: * Completely new configuration engine * Completely new topic structure * New template engine for creating friendly topic structure from raw DPS values * Pre-defined templates for some common devices * Directly control devices via Tuya JSON topic or via DPS key topics
This commit is contained in:
@@ -31,6 +31,20 @@ class RGBTWLight extends TuyaDevice {
|
|||||||
this.deviceData.mdl = 'RGBTW Light'
|
this.deviceData.mdl = 'RGBTW Light'
|
||||||
this.isRgbtwLight = true
|
this.isRgbtwLight = true
|
||||||
|
|
||||||
|
// Set white value transform math
|
||||||
|
let whiteValueStateMath
|
||||||
|
let whiteValueCommandMath
|
||||||
|
if (this.config.whiteValueScale === 255) {
|
||||||
|
// Devices with brightness scale of 255 seem to not allow values
|
||||||
|
// less then 25 (10%) without producing timeout errors.
|
||||||
|
whiteValueStateMath = '/2.3-10.86'
|
||||||
|
whiteValueCommandMath = '*2.3+25'
|
||||||
|
} else {
|
||||||
|
// For other scale (usually 1000), 10-1000 seems OK.
|
||||||
|
whiteValueStateMath = '/('+this.config.whiteValueScale+'/100)'
|
||||||
|
whiteValueCommandMath = '*('+this.config.whiteValueScale+'/100)'
|
||||||
|
}
|
||||||
|
|
||||||
// Map generic DPS topics to device specific topic names
|
// Map generic DPS topics to device specific topic names
|
||||||
this.deviceTopics = {
|
this.deviceTopics = {
|
||||||
state: {
|
state: {
|
||||||
@@ -40,11 +54,10 @@ class RGBTWLight extends TuyaDevice {
|
|||||||
white_brightness_state: {
|
white_brightness_state: {
|
||||||
key: this.config.dpsWhiteValue,
|
key: this.config.dpsWhiteValue,
|
||||||
type: 'int',
|
type: 'int',
|
||||||
min: 1,
|
topicMin: 0,
|
||||||
max: 100,
|
topicMax: 100,
|
||||||
scale: this.config.whiteValueScale,
|
stateMath: whiteValueStateMath,
|
||||||
stateMath: '/('+this.config.whiteValueScale+'/100)',
|
commandMath: whiteValueCommandMath
|
||||||
commandMath: '*('+this.config.whiteValueScale+'/100)'
|
|
||||||
},
|
},
|
||||||
hs_state: {
|
hs_state: {
|
||||||
key: this.config.dpsColor,
|
key: this.config.dpsColor,
|
||||||
@@ -77,8 +90,8 @@ class RGBTWLight extends TuyaDevice {
|
|||||||
this.deviceTopics.color_temp_state = {
|
this.deviceTopics.color_temp_state = {
|
||||||
key: this.config.dpsColorTemp,
|
key: this.config.dpsColorTemp,
|
||||||
type: 'int',
|
type: 'int',
|
||||||
min: this.config.minColorTemp,
|
topicMin: this.config.minColorTemp,
|
||||||
max: this.config.maxColorTemp,
|
topicMax: this.config.maxColorTemp,
|
||||||
stateMath: '/'+scaleFactor+'*-'+rangeFactor+'+'+this.config.maxColorTemp,
|
stateMath: '/'+scaleFactor+'*-'+rangeFactor+'+'+this.config.maxColorTemp,
|
||||||
commandMath: '/'+rangeFactor+'*-'+scaleFactor+'+'+tuyaMaxColorTemp
|
commandMath: '/'+rangeFactor+'*-'+scaleFactor+'+'+tuyaMaxColorTemp
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,20 @@ class SimpleDimmer extends TuyaDevice {
|
|||||||
|
|
||||||
this.deviceData.mdl = 'Dimmer Switch'
|
this.deviceData.mdl = 'Dimmer Switch'
|
||||||
|
|
||||||
|
// Set white value transform math
|
||||||
|
let brightnessStateMath
|
||||||
|
let brightnessCommandMath
|
||||||
|
if (this.config.brightnessScale === 255) {
|
||||||
|
// Devices with brightness scale of 255 seem to not allow values
|
||||||
|
// less then 25 (10%) without producing timeout errors.
|
||||||
|
brightnessStateMath = '/2.3-10.86'
|
||||||
|
brightnessCommandMath = '*2.3+25'
|
||||||
|
} else {
|
||||||
|
// For other scale (usually 1000), 10-1000 seems OK.
|
||||||
|
brightnessStateMath = '/('+this.config.brightnessScale+'/100)'
|
||||||
|
brightnessCommandMath = '*('+this.config.brightnessScale+'/100)'
|
||||||
|
}
|
||||||
|
|
||||||
// Map generic DPS topics to device specific topic names
|
// Map generic DPS topics to device specific topic names
|
||||||
this.deviceTopics = {
|
this.deviceTopics = {
|
||||||
state: {
|
state: {
|
||||||
@@ -21,9 +35,10 @@ class SimpleDimmer extends TuyaDevice {
|
|||||||
brightness_state: {
|
brightness_state: {
|
||||||
key: this.config.dpsBrightness,
|
key: this.config.dpsBrightness,
|
||||||
type: 'int',
|
type: 'int',
|
||||||
min: (this.config.brightnessScale = 1000) ? 10 : 1,
|
topicMin: 0,
|
||||||
max: this.config.brightnessScale,
|
topicMax: 100,
|
||||||
scale: this.config.brightnessScale
|
stateMath: brightnessStateMath,
|
||||||
|
commandMath: brightnessCommandMath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,6 +59,7 @@ class SimpleDimmer extends TuyaDevice {
|
|||||||
command_topic: this.baseTopic+'command',
|
command_topic: this.baseTopic+'command',
|
||||||
brightness_state_topic: this.baseTopic+'brightness_state',
|
brightness_state_topic: this.baseTopic+'brightness_state',
|
||||||
brightness_command_topic: this.baseTopic+'brightness_command',
|
brightness_command_topic: this.baseTopic+'brightness_command',
|
||||||
|
brightness_scale: 100,
|
||||||
availability_topic: this.baseTopic+'status',
|
availability_topic: this.baseTopic+'status',
|
||||||
payload_available: 'online',
|
payload_available: 'online',
|
||||||
payload_not_available: 'offline',
|
payload_not_available: 'offline',
|
||||||
|
|||||||
@@ -409,14 +409,14 @@ class TuyaDevice {
|
|||||||
// Check if it's a number and it's not outside of defined range
|
// Check if it's a number and it's not outside of defined range
|
||||||
if (isNaN(command)) {
|
if (isNaN(command)) {
|
||||||
return invalid
|
return invalid
|
||||||
} else if (deviceTopic.hasOwnProperty('min') && command < deviceTopic.min) {
|
} else if (deviceTopic.hasOwnProperty('topicMin') && command < deviceTopic.topicMin) {
|
||||||
debugError('Received command value "'+command+'" that is less than the configured minimum value')
|
debugError('Received command value "'+command+'" that is less than the configured minimum value')
|
||||||
debugError('Overriding command with minimum value '+deviceTopic.min)
|
debugError('Overriding command with minimum value '+deviceTopic.topicMin)
|
||||||
command = deviceTopic.min
|
command = deviceTopic.topicMin
|
||||||
} else if (deviceTopic.hasOwnProperty('max') && command > deviceTopic.max) {
|
} else if (deviceTopic.hasOwnProperty('topicMax') && command > deviceTopic.topicMax) {
|
||||||
debugError('Received command value "'+command+'" that is greater than the configured maximum value')
|
debugError('Received command value "'+command+'" that is greater than the configured maximum value')
|
||||||
debugError('Overriding command with maximum value: '+deviceTopic.max)
|
debugError('Overriding command with maximum value: '+deviceTopic.topicMax)
|
||||||
command = deviceTopic.max
|
command = deviceTopic.topicMax
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform any required math transforms before returing command value
|
// Perform any required math transforms before returing command value
|
||||||
|
|||||||
@@ -46,8 +46,8 @@ Simple device with on/off and brightness functions (dimmer switches or lights)
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| state | Power state | on/off |
|
| state | Power state | on/off |
|
||||||
| command | Set power state | on/off, 0/1, true/false |
|
| command | Set power state | on/off, 0/1, true/false |
|
||||||
| brightness_state | Brightness in % | 1-100 |
|
| brightness_state | Brightness in % | 0-100 |
|
||||||
| brightness_command | set brightness in % | 1-100 |
|
| brightness_command | set brightness in % | 0-100 |
|
||||||
|
|
||||||
Manual configuration options:
|
Manual configuration options:
|
||||||
| Option | Description | Default |
|
| Option | Description | Default |
|
||||||
@@ -78,14 +78,14 @@ Tuya bulbs store their HSB color value in a single DPS key using a custom format
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| state | Power state | on/off |
|
| state | Power state | on/off |
|
||||||
| command | Set power state | on/off, 0/1, true/false |
|
| command | Set power state | on/off, 0/1, true/false |
|
||||||
| white_brightness_state | White mode brightness in % | 1-100 |
|
| white_brightness_state | White mode brightness in % | 0-100 |
|
||||||
| white_brightness_command | Set white mode brightness in % | 1-100 |
|
| white_brightness_command | Set white mode brightness in % | 0-100 |
|
||||||
| color_brightness_state | Color mode brightness in % | 1-100 |
|
| color_brightness_state | Color mode brightness in % | 0-100 |
|
||||||
| color_brightness_command | Set white mode brightness in % | 1-100 |
|
| color_brightness_command | Set white mode brightness in % | 0-100 |
|
||||||
| hs_state | Hue, saturation % | H,S (Hue 0-360, Saturation 1-100) |
|
| hs_state | Hue, saturation % | H,S (Hue 0-360, Saturation 0-100) |
|
||||||
| hs_command | Set hue, saturation % | H,S (Hue 0-360, Saturation 1-100) |
|
| hs_command | Set hue, saturation % | H,S (Hue 0-360, Saturation 0-100) |
|
||||||
| hsb_state | Hue, saturation %, brightness % | H,S,B (Hue 0-360, Saturation 1-100, Brightness 1-100) |
|
| hsb_state | Hue, saturation %, brightness % | H,S,B (Hue 0-360, Saturation 0-100, Brightness 0-100) |
|
||||||
| hsb_command | Set hue, saturation %, brightness % | H,S,B (Hue 0-360, Saturation 1-100, Brightness 1-100) |
|
| hsb_command | Set hue, saturation %, brightness % | H,S,B (Hue 0-360, Saturation 0-100, Brightness 0-100) |
|
||||||
| mode_state | White/Color mode | 'white', 'colour' (some devices also support scenes here) |
|
| mode_state | White/Color mode | 'white', 'colour' (some devices also support scenes here) |
|
||||||
| mode_command | Set white/color mode | 'white', 'colour' (some devices also support scenes here) |
|
| mode_command | Set white/color mode | 'white', 'colour' (some devices also support scenes here) |
|
||||||
| color_temp_state | Color temperature in mireds (only available if device support color temp) | 154-400 (defult range, can be overridden) |
|
| color_temp_state | Color temperature in mireds (only available if device support color temp) | 154-400 (defult range, can be overridden) |
|
||||||
|
|||||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "tuya-mqtt",
|
"name": "tuya-mqtt",
|
||||||
"version": "3.0.0-beta4",
|
"version": "3.0.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "tuya-mqtt",
|
"name": "tuya-mqtt",
|
||||||
"version": "3.0.0-beta4",
|
"version": "3.0.0",
|
||||||
"description": "Control Tuya devices locally via MQTT",
|
"description": "Control Tuya devices locally via MQTT",
|
||||||
"homepage": "https://github.com/TheAgentK/tuya-mqtt#readme",
|
"homepage": "https://github.com/TheAgentK/tuya-mqtt#readme",
|
||||||
"main": "tuya-mqtt.js",
|
"main": "tuya-mqtt.js",
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ process.on('SIGINT', processExit.bind(0))
|
|||||||
process.on('SIGTERM', processExit.bind(0))
|
process.on('SIGTERM', processExit.bind(0))
|
||||||
process.on('uncaughtException', processExit.bind(1))
|
process.on('uncaughtException', processExit.bind(1))
|
||||||
|
|
||||||
// Set unreachable status on exit
|
// Disconnect from and publish offline status for all devices on exit
|
||||||
async function processExit(exitCode) {
|
async function processExit(exitCode) {
|
||||||
for (let tuyaDevice of tuyaDevices) {
|
for (let tuyaDevice of tuyaDevices) {
|
||||||
tuyaDevice.device.disconnect()
|
tuyaDevice.device.disconnect()
|
||||||
@@ -30,6 +30,7 @@ async function processExit(exitCode) {
|
|||||||
process.exit()
|
process.exit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get new deivce based on configured type
|
||||||
function getDevice(configDevice, mqttClient) {
|
function getDevice(configDevice, mqttClient) {
|
||||||
const deviceInfo = {
|
const deviceInfo = {
|
||||||
configDevice: configDevice,
|
configDevice: configDevice,
|
||||||
@@ -57,13 +58,17 @@ function initDevices(configDevices, mqttClient) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Republish devices 2x with 30 seconds sleep if restart of HA is detected
|
||||||
async function republishDevices() {
|
async function republishDevices() {
|
||||||
// Republish devices and state after 30 seconds if restart of HA is detected
|
for (let i = 0; i < 2; i++) {
|
||||||
debug('Resending device config/state in 30 seconds')
|
debug('Resending device config/state in 30 seconds')
|
||||||
await utils.sleep(30)
|
await utils.sleep(30)
|
||||||
for (let device of tuyaDevices) {
|
for (let device of tuyaDevices) {
|
||||||
|
device.publishMqtt(device.baseTopic+'status', 'online')
|
||||||
device.init()
|
device.init()
|
||||||
}
|
}
|
||||||
|
await utils.sleep(2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main code function
|
// Main code function
|
||||||
|
|||||||
Reference in New Issue
Block a user