From 5d8daa69905d48e5965c9c1dcdcf5435baaa9373 Mon Sep 17 00:00:00 2001 From: richardhopton Date: Fri, 12 May 2023 20:16:28 -0700 Subject: [PATCH] Tuya: Prevent loop when setting colors on case-sensitive dps (#4809) Co-authored-by: Samuel Sieb --- esphome/components/tuya/light/tuya_light.cpp | 46 +++++++++++--------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/esphome/components/tuya/light/tuya_light.cpp b/esphome/components/tuya/light/tuya_light.cpp index 869e20871d..7b7a974de2 100644 --- a/esphome/components/tuya/light/tuya_light.cpp +++ b/esphome/components/tuya/light/tuya_light.cpp @@ -57,37 +57,43 @@ void TuyaLight::setup() { return; } + float red, green, blue; switch (*this->color_type_) { case TuyaColorType::RGBHSV: case TuyaColorType::RGB: { - auto red = parse_hex(datapoint.value_string.substr(0, 2)); - auto green = parse_hex(datapoint.value_string.substr(2, 2)); - auto blue = parse_hex(datapoint.value_string.substr(4, 2)); - if (red.has_value() && green.has_value() && blue.has_value()) { - auto rgb_call = this->state_->make_call(); - rgb_call.set_rgb(float(*red) / 255, float(*green) / 255, float(*blue) / 255); - rgb_call.perform(); - } + auto rgb = parse_hex(datapoint.value_string.substr(0, 6)); + if (!rgb.has_value()) + return; + + red = (*rgb >> 16) / 255.0f; + green = ((*rgb >> 8) & 0xff) / 255.0f; + blue = (*rgb & 0xff) / 255.0f; break; } case TuyaColorType::HSV: { auto hue = parse_hex(datapoint.value_string.substr(0, 4)); auto saturation = parse_hex(datapoint.value_string.substr(4, 4)); auto value = parse_hex(datapoint.value_string.substr(8, 4)); - if (hue.has_value() && saturation.has_value() && value.has_value()) { - float red, green, blue; - hsv_to_rgb(*hue, float(*saturation) / 1000, float(*value) / 1000, red, green, blue); - auto rgb_call = this->state_->make_call(); - rgb_call.set_rgb(red, green, blue); - rgb_call.perform(); - } + if (!hue.has_value() || !saturation.has_value() || !value.has_value()) + return; + + hsv_to_rgb(*hue, float(*saturation) / 1000, float(*value) / 1000, red, green, blue); break; } } + + float current_red, current_green, current_blue; + this->state_->current_values_as_rgb(¤t_red, ¤t_green, ¤t_blue); + if (red == current_red && green == current_green && blue == current_blue) + return; + auto rgb_call = this->state_->make_call(); + rgb_call.set_rgb(red, green, blue); + rgb_call.perform(); }); } + if (min_value_datapoint_id_.has_value()) { - parent_->set_integer_datapoint_value(*this->min_value_datapoint_id_, this->min_value_); + this->parent_->set_integer_datapoint_value(*this->min_value_datapoint_id_, this->min_value_); } } @@ -156,7 +162,7 @@ void TuyaLight::write_state(light::LightState *state) { } if (!state->current_values.is_on() && this->switch_id_.has_value()) { - parent_->set_boolean_datapoint_value(*this->switch_id_, false); + this->parent_->set_boolean_datapoint_value(*this->switch_id_, false); return; } @@ -166,14 +172,14 @@ void TuyaLight::write_state(light::LightState *state) { if (this->color_temperature_invert_) { color_temp_int = this->color_temperature_max_value_ - color_temp_int; } - parent_->set_integer_datapoint_value(*this->color_temperature_id_, color_temp_int); + this->parent_->set_integer_datapoint_value(*this->color_temperature_id_, color_temp_int); } if (this->dimmer_id_.has_value()) { auto brightness_int = static_cast(brightness * this->max_value_); brightness_int = std::max(brightness_int, this->min_value_); - parent_->set_integer_datapoint_value(*this->dimmer_id_, brightness_int); + this->parent_->set_integer_datapoint_value(*this->dimmer_id_, brightness_int); } } @@ -210,7 +216,7 @@ void TuyaLight::write_state(light::LightState *state) { } if (this->switch_id_.has_value()) { - parent_->set_boolean_datapoint_value(*this->switch_id_, true); + this->parent_->set_boolean_datapoint_value(*this->switch_id_, true); } }