RGBTW light fixes

This commit is contained in:
tsightler
2020-10-03 13:32:48 -04:00
parent 9176b8f85c
commit df01beb8fc
3 changed files with 49 additions and 39 deletions

View File

@@ -11,7 +11,6 @@ class GenericDevice extends TuyaDevice {
// Map generic DPS topics to device specific topic names // Map generic DPS topics to device specific topic names
this.deviceTopics = this.config.template this.deviceTopics = this.config.template
} else { } else {
this.deviceTopics = {}
// Try to get schema to at least know what DPS keys to get initial update // Try to get schema to at least know what DPS keys to get initial update
const result = await this.device.get({"schema": true}) const result = await this.device.get({"schema": true})
if (!utils.isJsonString(result)) { if (!utils.isJsonString(result)) {

View File

@@ -15,6 +15,8 @@ class RGBTWLight extends TuyaDevice {
this.deviceData.mdl = 'RGBTW Light' this.deviceData.mdl = 'RGBTW Light'
this.isRgbtwLight = true
// Map generic DPS topics to device specific topic names // Map generic DPS topics to device specific topic names
this.deviceTopics = { this.deviceTopics = {
state: { state: {

View File

@@ -33,10 +33,13 @@ class TuyaDevice {
mf: 'Tuya' mf: 'Tuya'
} }
// Variables to hold device state data // Property to hold device state data
this.dps = {} // Current dps state data for device this.dps = {} // Current dps state data for device
this.dpsPub = {} // Published dps state data for device this.dpsPub = {} // Published dps state data for device
this.color = {'h': 0, 's': 0, 'b': 0, 't': 0, 'w': 0} // Current color values (Hue, Saturation, Brightness, White Temp, White Level) this.color = {'h': 0, 's': 0, 'b': 0} // HSB color value cache
// Property to hold friendly topics template
this.deviceTopics = {}
// Build the MQTT topic for this device (friendly name or device id) // Build the MQTT topic for this device (friendly name or device id)
if (this.options.name) { if (this.options.name) {
@@ -158,7 +161,7 @@ class TuyaDevice {
break; break;
case 'hsb': case 'hsb':
if (this.dps[key]) { if (this.dps[key]) {
state = this.getColorState(this.dps[key], topic) state = this.convertFromTuyaHsbColor(this.dps[key], topic)
} }
break; break;
case 'str': case 'str':
@@ -305,80 +308,87 @@ class TuyaDevice {
} }
break; break;
case 'hsb': case 'hsb':
tuyaCommand.set = this.getColorCommand(command, deviceTopic) tuyaCommand.set = this.convertToTuyaHsbColor(command, deviceTopic)
this.setLightMode(deviceTopic)
break; break;
} }
if (tuyaCommand.set === '!!!INVALID!!!') { if (tuyaCommand.set === '!!!INVALID!!!') {
return false return false
} else { } else {
if (this.config.dpsWhiteValue === deviceTopic.key) { if (this.isRgbtwLight) {
this.setLightMode(deviceTopic) this.setLight(deviceTopic, tuyaCommand)
} else {
this.set(tuyaCommand)
} }
this.set(tuyaCommand)
return true return true
} }
} }
// Takes the current Tuya color and splits it into component parts // Takes the current Tuya color and splits it into HSB component parts
// Updates cached color state for device and returns decimal format // Updates cached color state for device and returns decimal format
// comma delimeted string of components for selected topic // comma delimeted string of components for selected friendly topic
getColorState(value, topic) { convertFromTuyaHsbColor(value, topic) {
// Split Tuya HSB value into component parts
const [, h, s, b] = (value || '000003e803e8').match(/^([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})$/i) || [0, '0', '3e8', '3e8']; const [, h, s, b] = (value || '000003e803e8').match(/^([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})$/i) || [0, '0', '3e8', '3e8'];
// Convert from Hex to Decimal and cache values
this.color.h = parseInt(h, 16) this.color.h = parseInt(h, 16)
this.color.s = Math.round(parseInt(s, 16) / 10) this.color.s = Math.round(parseInt(s, 16) / 10)
this.color.b = parseInt(b, 16) this.color.b = parseInt(b, 16)
// Return comma separate array of component values for specific topic
const color = new Array() const color = new Array()
const components = this.deviceTopics[topic].components.split(',') const components = this.deviceTopics[topic].components.split(',')
for (let i in components) { for (let i in components) {
if (components.hasOwnProperty([components[i]])) { color.push(this.color[components[i]])
color.push(decimalColor[components[i]])
}
} }
return (color.join(',')) return (color.join(','))
} }
// Takes provided decimal HSB components from MQTT topic, combine with existing // Takes provided decimal HSB components from MQTT topic, combines with cached
// settings for unchanged values since brightness is sometimes sent separately // unchanged values since, for example, brightness is sometimes sent separately
// Convert to Tuya hex format and return value // then convers to Tuya hex format and returns value
getColorCommand(value, topic) { convertToTuyaHsbColor(value, topic) {
const [, h, s, b] = (this.dps[topic.key] || '000003e803e8').match(/^([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})$/i) || [0, '0', '3e8', '3e8']; // Start with cached color values
const decimalColor = { const newColor = this.color
h: parseInt(h, 16),
s: Math.round(parseInt(s, 16) / 10), // Update any HSB component with a changed value
b: parseInt(b, 16)
}
const components = topic.components.split(',') const components = topic.components.split(',')
const values = value.split(',') const values = value.split(',')
for (let i in components) { for (let i in components) {
decimalColor[components[i]] = Math.round(values[i]) newColor[components[i]] = Math.round(values[i])
} }
const hexColor = decimalColor.h.toString(16).padStart(4, '0') + (10 * decimalColor.s).toString(16).padStart(4, '0') + (decimalColor.b).toString(16).padStart(4, '0')
// Convert new HSB color to Tuya style HSB format
const hexColor = newColor.h.toString(16).padStart(4, '0') + (10 * newColor.s).toString(16).padStart(4, '0') + (newColor.b).toString(16).padStart(4, '0')
return hexColor return hexColor
} }
// Set light mode based on received command // Set light based on received command
async setLightMode(topic) { async setLight(topic, command) {
const currentMode = this.dps[this.config.dpsMode] let targetMode = undefined
let targetMode
if (this.config.dpsWhiteValue === topic.key) { if (this.config.dpsWhiteValue === topic.key) {
// If setting white level, switch to white mode // If setting white level, or saturation = 0, target is white mode
targetMode = 'white' targetMode = 'white'
} else if (this.config.dpsColor === topic.key) { } else if (this.config.dpsColor === topic.key) {
// If setting an HSB value, switch to colour mode // Split Tuya HSB value into component parts
targetMode = 'colour' const [, h, s, b] = (command.set || '000003e803e8').match(/^([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})$/i) || [0, '0', '3e8', '3e8'];
if (s > 0) {
// If setting an HSB value, switch to colour mode
targetMode = 'colour'
} else {
targetMode = 'white'
}
} }
// Set the correct light mode // Set the correct light mode
if (targetMode && targetMode !== currentMode) { if (targetMode) {
const tuyaCommand = { const tuyaCommand = {
dps: this.config.dpsMode, dps: this.config.dpsMode,
set: targetMode set: targetMode
} }
await this.set(tuyaCommand) await this.set(tuyaCommand)
} }
this.set(command)
} }
// Simple function to help debug output // Simple function to help debug output
@@ -387,10 +397,9 @@ class TuyaDevice {
} }
set(command) { set(command) {
debug('Set device '+this.options.id+' -> '+command) debug('Set device '+this.options.id+' -> '+JSON.stringify(command))
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.device.set(command).then((result) => { this.device.set(command).then((result) => {
debug(result)
resolve(result) resolve(result)
}) })
}) })