diff --git a/devices/rgbtw-light.js b/devices/rgbtw-light.js index e8a4f82..53db969 100644 --- a/devices/rgbtw-light.js +++ b/devices/rgbtw-light.js @@ -31,6 +31,20 @@ class RGBTWLight extends TuyaDevice { this.deviceData.mdl = 'RGBTW Light' 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 this.deviceTopics = { state: { @@ -40,11 +54,10 @@ class RGBTWLight extends TuyaDevice { white_brightness_state: { key: this.config.dpsWhiteValue, type: 'int', - min: 1, - max: 100, - scale: this.config.whiteValueScale, - stateMath: '/('+this.config.whiteValueScale+'/100)', - commandMath: '*('+this.config.whiteValueScale+'/100)' + topicMin: 0, + topicMax: 100, + stateMath: whiteValueStateMath, + commandMath: whiteValueCommandMath }, hs_state: { key: this.config.dpsColor, @@ -77,8 +90,8 @@ class RGBTWLight extends TuyaDevice { this.deviceTopics.color_temp_state = { key: this.config.dpsColorTemp, type: 'int', - min: this.config.minColorTemp, - max: this.config.maxColorTemp, + topicMin: this.config.minColorTemp, + topicMax: this.config.maxColorTemp, stateMath: '/'+scaleFactor+'*-'+rangeFactor+'+'+this.config.maxColorTemp, commandMath: '/'+rangeFactor+'*-'+scaleFactor+'+'+tuyaMaxColorTemp } diff --git a/devices/simple-dimmer.js b/devices/simple-dimmer.js index 766117e..5cbcdd9 100644 --- a/devices/simple-dimmer.js +++ b/devices/simple-dimmer.js @@ -12,6 +12,20 @@ class SimpleDimmer extends TuyaDevice { 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 this.deviceTopics = { state: { @@ -21,9 +35,10 @@ class SimpleDimmer extends TuyaDevice { brightness_state: { key: this.config.dpsBrightness, type: 'int', - min: (this.config.brightnessScale = 1000) ? 10 : 1, - max: this.config.brightnessScale, - scale: this.config.brightnessScale + topicMin: 0, + topicMax: 100, + stateMath: brightnessStateMath, + commandMath: brightnessCommandMath } } @@ -44,6 +59,7 @@ class SimpleDimmer extends TuyaDevice { command_topic: this.baseTopic+'command', brightness_state_topic: this.baseTopic+'brightness_state', brightness_command_topic: this.baseTopic+'brightness_command', + brightness_scale: 100, availability_topic: this.baseTopic+'status', payload_available: 'online', payload_not_available: 'offline', diff --git a/devices/tuya-device.js b/devices/tuya-device.js index 0b8962a..c3a9d93 100644 --- a/devices/tuya-device.js +++ b/devices/tuya-device.js @@ -409,14 +409,14 @@ class TuyaDevice { // Check if it's a number and it's not outside of defined range if (isNaN(command)) { 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('Overriding command with minimum value '+deviceTopic.min) - command = deviceTopic.min - } else if (deviceTopic.hasOwnProperty('max') && command > deviceTopic.max) { + debugError('Overriding command with minimum value '+deviceTopic.topicMin) + command = deviceTopic.topicMin + } else if (deviceTopic.hasOwnProperty('topicMax') && command > deviceTopic.topicMax) { debugError('Received command value "'+command+'" that is greater than the configured maximum value') - debugError('Overriding command with maximum value: '+deviceTopic.max) - command = deviceTopic.max + debugError('Overriding command with maximum value: '+deviceTopic.topicMax) + command = deviceTopic.topicMax } // Perform any required math transforms before returing command value diff --git a/docs/DEVICES.md b/docs/DEVICES.md index e03df22..0acdb53 100644 --- a/docs/DEVICES.md +++ b/docs/DEVICES.md @@ -46,8 +46,8 @@ Simple device with on/off and brightness functions (dimmer switches or lights) | --- | --- | --- | | state | Power state | on/off | | command | Set power state | on/off, 0/1, true/false | -| brightness_state | Brightness in % | 1-100 | -| brightness_command | set brightness in % | 1-100 | +| brightness_state | Brightness in % | 0-100 | +| brightness_command | set brightness in % | 0-100 | Manual configuration options: | 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 | | command | Set power state | on/off, 0/1, true/false | -| white_brightness_state | White mode brightness in % | 1-100 | -| white_brightness_command | Set white mode brightness in % | 1-100 | -| color_brightness_state | Color mode brightness in % | 1-100 | -| color_brightness_command | Set white mode brightness in % | 1-100 | -| hs_state | Hue, saturation % | H,S (Hue 0-360, Saturation 1-100) | -| hs_command | Set hue, saturation % | H,S (Hue 0-360, Saturation 1-100) | -| hsb_state | 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 1-100, Brightness 1-100) | +| white_brightness_state | White mode brightness in % | 0-100 | +| white_brightness_command | Set white mode brightness in % | 0-100 | +| color_brightness_state | Color mode brightness in % | 0-100 | +| color_brightness_command | Set white mode brightness in % | 0-100 | +| hs_state | Hue, saturation % | H,S (Hue 0-360, Saturation 0-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 0-100, Brightness 0-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_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) | diff --git a/package-lock.json b/package-lock.json index 783b057..075cabb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "tuya-mqtt", - "version": "3.0.0-beta4", + "version": "3.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index a80dd3d..44d48e6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tuya-mqtt", - "version": "3.0.0-beta4", + "version": "3.0.0", "description": "Control Tuya devices locally via MQTT", "homepage": "https://github.com/TheAgentK/tuya-mqtt#readme", "main": "tuya-mqtt.js", diff --git a/tuya-mqtt.js b/tuya-mqtt.js index 811c5b1..048d8fa 100644 --- a/tuya-mqtt.js +++ b/tuya-mqtt.js @@ -20,7 +20,7 @@ process.on('SIGINT', processExit.bind(0)) process.on('SIGTERM', processExit.bind(0)) 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) { for (let tuyaDevice of tuyaDevices) { tuyaDevice.device.disconnect() @@ -30,6 +30,7 @@ async function processExit(exitCode) { process.exit() } +// Get new deivce based on configured type function getDevice(configDevice, mqttClient) { const deviceInfo = { configDevice: configDevice, @@ -57,12 +58,16 @@ function initDevices(configDevices, mqttClient) { } } +// Republish devices 2x with 30 seconds sleep if restart of HA is detected async function republishDevices() { - // Republish devices and state after 30 seconds if restart of HA is detected - debug('Resending device config/state in 30 seconds') - await utils.sleep(30) - for (let device of tuyaDevices) { - device.init() + for (let i = 0; i < 2; i++) { + debug('Resending device config/state in 30 seconds') + await utils.sleep(30) + for (let device of tuyaDevices) { + device.publishMqtt(device.baseTopic+'status', 'online') + device.init() + } + await utils.sleep(2) } }