mirror of
https://github.com/esphome/esphome.git
synced 2024-11-10 09:17:46 +01:00
Break the Tuya set_datapoint_value method into separate methods per datapoint type (#2059)
Co-authored-by: Chris Nussbaum <chris.nussbaum@protolabs.com> Co-authored-by: Trevor North <trevor@freedisc.co.uk>
This commit is contained in:
parent
1771e673d2
commit
6144ce1fe0
6 changed files with 83 additions and 42 deletions
|
@ -54,14 +54,14 @@ void TuyaClimate::control(const climate::ClimateCall &call) {
|
||||||
if (call.get_mode().has_value()) {
|
if (call.get_mode().has_value()) {
|
||||||
const bool switch_state = *call.get_mode() != climate::CLIMATE_MODE_OFF;
|
const bool switch_state = *call.get_mode() != climate::CLIMATE_MODE_OFF;
|
||||||
ESP_LOGV(TAG, "Setting switch: %s", ONOFF(switch_state));
|
ESP_LOGV(TAG, "Setting switch: %s", ONOFF(switch_state));
|
||||||
this->parent_->set_datapoint_value(*this->switch_id_, switch_state);
|
this->parent_->set_boolean_datapoint_value(*this->switch_id_, switch_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (call.get_target_temperature().has_value()) {
|
if (call.get_target_temperature().has_value()) {
|
||||||
const float target_temperature = *call.get_target_temperature();
|
const float target_temperature = *call.get_target_temperature();
|
||||||
ESP_LOGV(TAG, "Setting target temperature: %.1f", target_temperature);
|
ESP_LOGV(TAG, "Setting target temperature: %.1f", target_temperature);
|
||||||
this->parent_->set_datapoint_value(*this->target_temperature_id_,
|
this->parent_->set_integer_datapoint_value(*this->target_temperature_id_,
|
||||||
(int) (target_temperature / this->target_temperature_multiplier_));
|
(int) (target_temperature / this->target_temperature_multiplier_));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,20 +67,20 @@ void TuyaFan::dump_config() {
|
||||||
void TuyaFan::write_state() {
|
void TuyaFan::write_state() {
|
||||||
if (this->switch_id_.has_value()) {
|
if (this->switch_id_.has_value()) {
|
||||||
ESP_LOGV(TAG, "Setting switch: %s", ONOFF(this->fan_->state));
|
ESP_LOGV(TAG, "Setting switch: %s", ONOFF(this->fan_->state));
|
||||||
this->parent_->set_datapoint_value(*this->switch_id_, this->fan_->state);
|
this->parent_->set_boolean_datapoint_value(*this->switch_id_, this->fan_->state);
|
||||||
}
|
}
|
||||||
if (this->oscillation_id_.has_value()) {
|
if (this->oscillation_id_.has_value()) {
|
||||||
ESP_LOGV(TAG, "Setting oscillating: %s", ONOFF(this->fan_->oscillating));
|
ESP_LOGV(TAG, "Setting oscillating: %s", ONOFF(this->fan_->oscillating));
|
||||||
this->parent_->set_datapoint_value(*this->oscillation_id_, this->fan_->oscillating);
|
this->parent_->set_boolean_datapoint_value(*this->oscillation_id_, this->fan_->oscillating);
|
||||||
}
|
}
|
||||||
if (this->direction_id_.has_value()) {
|
if (this->direction_id_.has_value()) {
|
||||||
bool enable = this->fan_->direction == fan::FAN_DIRECTION_REVERSE;
|
bool enable = this->fan_->direction == fan::FAN_DIRECTION_REVERSE;
|
||||||
ESP_LOGV(TAG, "Setting reverse direction: %s", ONOFF(enable));
|
ESP_LOGV(TAG, "Setting reverse direction: %s", ONOFF(enable));
|
||||||
this->parent_->set_datapoint_value(*this->direction_id_, enable);
|
this->parent_->set_boolean_datapoint_value(*this->direction_id_, enable);
|
||||||
}
|
}
|
||||||
if (this->speed_id_.has_value()) {
|
if (this->speed_id_.has_value()) {
|
||||||
ESP_LOGV(TAG, "Setting speed: %d", this->fan_->speed);
|
ESP_LOGV(TAG, "Setting speed: %d", this->fan_->speed);
|
||||||
this->parent_->set_datapoint_value(*this->speed_id_, this->fan_->speed - 1);
|
this->parent_->set_integer_datapoint_value(*this->speed_id_, this->fan_->speed - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ void TuyaLight::setup() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (min_value_datapoint_id_.has_value()) {
|
if (min_value_datapoint_id_.has_value()) {
|
||||||
parent_->set_datapoint_value(*this->min_value_datapoint_id_, this->min_value_);
|
parent_->set_integer_datapoint_value(*this->min_value_datapoint_id_, this->min_value_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,9 +66,9 @@ void TuyaLight::write_state(light::LightState *state) {
|
||||||
if (brightness == 0.0f) {
|
if (brightness == 0.0f) {
|
||||||
// turning off, first try via switch (if exists), then dimmer
|
// turning off, first try via switch (if exists), then dimmer
|
||||||
if (switch_id_.has_value()) {
|
if (switch_id_.has_value()) {
|
||||||
parent_->set_datapoint_value(*this->switch_id_, false);
|
parent_->set_boolean_datapoint_value(*this->switch_id_, false);
|
||||||
} else if (dimmer_id_.has_value()) {
|
} else if (dimmer_id_.has_value()) {
|
||||||
parent_->set_datapoint_value(*this->dimmer_id_, 0);
|
parent_->set_integer_datapoint_value(*this->dimmer_id_, 0);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -78,17 +78,17 @@ void TuyaLight::write_state(light::LightState *state) {
|
||||||
static_cast<uint32_t>(this->color_temperature_max_value_ *
|
static_cast<uint32_t>(this->color_temperature_max_value_ *
|
||||||
(state->current_values.get_color_temperature() - this->cold_white_temperature_) /
|
(state->current_values.get_color_temperature() - this->cold_white_temperature_) /
|
||||||
(this->warm_white_temperature_ - this->cold_white_temperature_));
|
(this->warm_white_temperature_ - this->cold_white_temperature_));
|
||||||
parent_->set_datapoint_value(*this->color_temperature_id_, color_temp_int);
|
parent_->set_integer_datapoint_value(*this->color_temperature_id_, color_temp_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto brightness_int = static_cast<uint32_t>(brightness * this->max_value_);
|
auto brightness_int = static_cast<uint32_t>(brightness * this->max_value_);
|
||||||
brightness_int = std::max(brightness_int, this->min_value_);
|
brightness_int = std::max(brightness_int, this->min_value_);
|
||||||
|
|
||||||
if (this->dimmer_id_.has_value()) {
|
if (this->dimmer_id_.has_value()) {
|
||||||
parent_->set_datapoint_value(*this->dimmer_id_, brightness_int);
|
parent_->set_integer_datapoint_value(*this->dimmer_id_, brightness_int);
|
||||||
}
|
}
|
||||||
if (this->switch_id_.has_value()) {
|
if (this->switch_id_.has_value()) {
|
||||||
parent_->set_datapoint_value(*this->switch_id_, true);
|
parent_->set_boolean_datapoint_value(*this->switch_id_, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ void TuyaSwitch::setup() {
|
||||||
|
|
||||||
void TuyaSwitch::write_state(bool state) {
|
void TuyaSwitch::write_state(bool state) {
|
||||||
ESP_LOGV(TAG, "Setting switch %u: %s", this->switch_id_, ONOFF(state));
|
ESP_LOGV(TAG, "Setting switch %u: %s", this->switch_id_, ONOFF(state));
|
||||||
this->parent_->set_datapoint_value(this->switch_id_, state);
|
this->parent_->set_boolean_datapoint_value(this->switch_id_, state);
|
||||||
this->publish_state(state);
|
this->publish_state(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -437,42 +437,38 @@ void Tuya::send_local_time_() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Tuya::set_datapoint_value(uint8_t datapoint_id, uint32_t value) {
|
void Tuya::set_raw_datapoint_value(uint8_t datapoint_id, const std::vector<uint8_t> &value) {
|
||||||
ESP_LOGD(TAG, "Setting datapoint %u to %u", datapoint_id, value);
|
ESP_LOGD(TAG, "Setting datapoint %u to %s", datapoint_id, hexencode(value).c_str());
|
||||||
optional<TuyaDatapoint> datapoint = this->get_datapoint_(datapoint_id);
|
optional<TuyaDatapoint> datapoint = this->get_datapoint_(datapoint_id);
|
||||||
if (!datapoint.has_value()) {
|
if (!datapoint.has_value()) {
|
||||||
ESP_LOGE(TAG, "Attempt to set unknown datapoint %u", datapoint_id);
|
ESP_LOGW(TAG, "Setting unknown datapoint %u", datapoint_id);
|
||||||
|
} else if (datapoint->type != TuyaDatapointType::RAW) {
|
||||||
|
ESP_LOGE(TAG, "Attempt to set datapoint %u with incorrect type", datapoint_id);
|
||||||
return;
|
return;
|
||||||
}
|
} else if (datapoint->value_raw == value) {
|
||||||
if (datapoint->value_uint == value) {
|
|
||||||
ESP_LOGV(TAG, "Not sending unchanged value");
|
ESP_LOGV(TAG, "Not sending unchanged value");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this->send_datapoint_command_(datapoint_id, TuyaDatapointType::RAW, value);
|
||||||
std::vector<uint8_t> data;
|
|
||||||
switch (datapoint->len) {
|
|
||||||
case 4:
|
|
||||||
data.push_back(value >> 24);
|
|
||||||
data.push_back(value >> 16);
|
|
||||||
case 2:
|
|
||||||
data.push_back(value >> 8);
|
|
||||||
case 1:
|
|
||||||
data.push_back(value >> 0);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ESP_LOGE(TAG, "Unexpected datapoint length %zu", datapoint->len);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->send_datapoint_command_(datapoint->id, datapoint->type, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tuya::set_datapoint_value(uint8_t datapoint_id, const std::string &value) {
|
void Tuya::set_boolean_datapoint_value(uint8_t datapoint_id, bool value) {
|
||||||
|
this->set_numeric_datapoint_value_(datapoint_id, TuyaDatapointType::BOOLEAN, value, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tuya::set_integer_datapoint_value(uint8_t datapoint_id, uint32_t value) {
|
||||||
|
this->set_numeric_datapoint_value_(datapoint_id, TuyaDatapointType::INTEGER, value, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tuya::set_string_datapoint_value(uint8_t datapoint_id, const std::string &value) {
|
||||||
ESP_LOGD(TAG, "Setting datapoint %u to %s", datapoint_id, value.c_str());
|
ESP_LOGD(TAG, "Setting datapoint %u to %s", datapoint_id, value.c_str());
|
||||||
optional<TuyaDatapoint> datapoint = this->get_datapoint_(datapoint_id);
|
optional<TuyaDatapoint> datapoint = this->get_datapoint_(datapoint_id);
|
||||||
if (!datapoint.has_value()) {
|
if (!datapoint.has_value()) {
|
||||||
ESP_LOGE(TAG, "Attempt to set unknown datapoint %u", datapoint_id);
|
ESP_LOGW(TAG, "Setting unknown datapoint %u", datapoint_id);
|
||||||
}
|
} else if (datapoint->type != TuyaDatapointType::STRING) {
|
||||||
if (datapoint->value_string == value) {
|
ESP_LOGE(TAG, "Attempt to set datapoint %u with incorrect type", datapoint_id);
|
||||||
|
return;
|
||||||
|
} else if (datapoint->value_string == value) {
|
||||||
ESP_LOGV(TAG, "Not sending unchanged value");
|
ESP_LOGV(TAG, "Not sending unchanged value");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -483,6 +479,14 @@ void Tuya::set_datapoint_value(uint8_t datapoint_id, const std::string &value) {
|
||||||
this->send_datapoint_command_(datapoint->id, datapoint->type, data);
|
this->send_datapoint_command_(datapoint->id, datapoint->type, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Tuya::set_enum_datapoint_value(uint8_t datapoint_id, uint8_t value) {
|
||||||
|
this->set_numeric_datapoint_value_(datapoint_id, TuyaDatapointType::ENUM, value, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tuya::set_bitmask_datapoint_value(uint8_t datapoint_id, uint32_t value, uint8_t length) {
|
||||||
|
this->set_numeric_datapoint_value_(datapoint_id, TuyaDatapointType::BITMASK, value, length);
|
||||||
|
}
|
||||||
|
|
||||||
optional<TuyaDatapoint> Tuya::get_datapoint_(uint8_t datapoint_id) {
|
optional<TuyaDatapoint> Tuya::get_datapoint_(uint8_t datapoint_id) {
|
||||||
for (auto &datapoint : this->datapoints_)
|
for (auto &datapoint : this->datapoints_)
|
||||||
if (datapoint.id == datapoint_id)
|
if (datapoint.id == datapoint_id)
|
||||||
|
@ -490,6 +494,37 @@ optional<TuyaDatapoint> Tuya::get_datapoint_(uint8_t datapoint_id) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Tuya::set_numeric_datapoint_value_(uint8_t datapoint_id, TuyaDatapointType datapoint_type, const uint32_t value,
|
||||||
|
uint8_t length) {
|
||||||
|
ESP_LOGD(TAG, "Setting datapoint %u to %u", datapoint_id, value);
|
||||||
|
optional<TuyaDatapoint> datapoint = this->get_datapoint_(datapoint_id);
|
||||||
|
if (!datapoint.has_value()) {
|
||||||
|
ESP_LOGW(TAG, "Setting unknown datapoint %u", datapoint_id);
|
||||||
|
} else if (datapoint->type != datapoint_type) {
|
||||||
|
ESP_LOGE(TAG, "Attempt to set datapoint %u with incorrect type", datapoint_id);
|
||||||
|
return;
|
||||||
|
} else if (datapoint->value_uint == value) {
|
||||||
|
ESP_LOGV(TAG, "Not sending unchanged value");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
switch (length) {
|
||||||
|
case 4:
|
||||||
|
data.push_back(value >> 24);
|
||||||
|
data.push_back(value >> 16);
|
||||||
|
case 2:
|
||||||
|
data.push_back(value >> 8);
|
||||||
|
case 1:
|
||||||
|
data.push_back(value >> 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG, "Unexpected datapoint length %u", length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->send_datapoint_command_(datapoint_id, datapoint_type, data);
|
||||||
|
}
|
||||||
|
|
||||||
void Tuya::send_datapoint_command_(uint8_t datapoint_id, TuyaDatapointType datapoint_type, std::vector<uint8_t> data) {
|
void Tuya::send_datapoint_command_(uint8_t datapoint_id, TuyaDatapointType datapoint_type, std::vector<uint8_t> data) {
|
||||||
std::vector<uint8_t> buffer;
|
std::vector<uint8_t> buffer;
|
||||||
buffer.push_back(datapoint_id);
|
buffer.push_back(datapoint_id);
|
||||||
|
|
|
@ -17,7 +17,7 @@ enum class TuyaDatapointType : uint8_t {
|
||||||
INTEGER = 0x02, // 4 byte
|
INTEGER = 0x02, // 4 byte
|
||||||
STRING = 0x03, // variable length
|
STRING = 0x03, // variable length
|
||||||
ENUM = 0x04, // 1 byte
|
ENUM = 0x04, // 1 byte
|
||||||
BITMASK = 0x05, // 2 bytes
|
BITMASK = 0x05, // 1/2/4 bytes
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TuyaDatapoint {
|
struct TuyaDatapoint {
|
||||||
|
@ -75,8 +75,12 @@ class Tuya : public Component, public uart::UARTDevice {
|
||||||
void loop() override;
|
void loop() override;
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
void register_listener(uint8_t datapoint_id, const std::function<void(TuyaDatapoint)> &func);
|
void register_listener(uint8_t datapoint_id, const std::function<void(TuyaDatapoint)> &func);
|
||||||
void set_datapoint_value(uint8_t datapoint_id, uint32_t value);
|
void set_raw_datapoint_value(uint8_t datapoint_id, const std::vector<uint8_t> &value);
|
||||||
void set_datapoint_value(uint8_t datapoint_id, const std::string &value);
|
void set_boolean_datapoint_value(uint8_t datapoint_id, bool value);
|
||||||
|
void set_integer_datapoint_value(uint8_t datapoint_id, uint32_t value);
|
||||||
|
void set_string_datapoint_value(uint8_t datapoint_id, const std::string &value);
|
||||||
|
void set_enum_datapoint_value(uint8_t datapoint_id, uint8_t value);
|
||||||
|
void set_bitmask_datapoint_value(uint8_t datapoint_id, uint32_t value, uint8_t length);
|
||||||
#ifdef USE_TIME
|
#ifdef USE_TIME
|
||||||
void set_time_id(time::RealTimeClock *time_id) { this->time_id_ = time_id; }
|
void set_time_id(time::RealTimeClock *time_id) { this->time_id_ = time_id; }
|
||||||
#endif
|
#endif
|
||||||
|
@ -95,6 +99,8 @@ class Tuya : public Component, public uart::UARTDevice {
|
||||||
void process_command_queue_();
|
void process_command_queue_();
|
||||||
void send_command_(const TuyaCommand &command);
|
void send_command_(const TuyaCommand &command);
|
||||||
void send_empty_command_(TuyaCommandType command);
|
void send_empty_command_(TuyaCommandType command);
|
||||||
|
void set_numeric_datapoint_value_(uint8_t datapoint_id, TuyaDatapointType datapoint_type, uint32_t value,
|
||||||
|
uint8_t length);
|
||||||
void send_datapoint_command_(uint8_t datapoint_id, TuyaDatapointType datapoint_type, std::vector<uint8_t> data);
|
void send_datapoint_command_(uint8_t datapoint_id, TuyaDatapointType datapoint_type, std::vector<uint8_t> data);
|
||||||
void send_wifi_status_();
|
void send_wifi_status_();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue