Update Tuya component to match the eventual state of the ESPHome version (#13)

This commit is contained in:
Chris Nussbaum 2021-07-25 09:33:16 -05:00 committed by GitHub
parent e0a37dac9d
commit ae2ef5d478
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 80 additions and 66 deletions

View File

@ -11,7 +11,7 @@ static const int COMMAND_DELAY = 50;
static const int RECEIVE_TIMEOUT = 300;
void Tuya::setup() {
this->set_interval("heartbeat", 10000, [this] { this->send_empty_command_(TuyaCommandType::HEARTBEAT); });
this->set_interval("heartbeat", 15000, [this] { this->send_empty_command_(TuyaCommandType::HEARTBEAT); });
}
void Tuya::loop() {
@ -379,7 +379,7 @@ void Tuya::send_command_(TuyaCommand command) {
}
void Tuya::send_empty_command_(TuyaCommandType command) {
send_command_(TuyaCommand{.cmd = command, .payload = std::vector<uint8_t>{0x04}});
send_command_(TuyaCommand{.cmd = command, .payload = std::vector<uint8_t>{}});
}
void Tuya::send_wifi_status_() {
@ -432,42 +432,38 @@ void Tuya::send_local_time_() {
}
#endif
void Tuya::set_datapoint_value(uint8_t datapoint_id, uint32_t value) {
ESP_LOGD(TAG, "Setting datapoint %u to %u", datapoint_id, value);
void Tuya::set_raw_datapoint_value(uint8_t datapoint_id, const std::vector<uint8_t> &value) {
ESP_LOGD(TAG, "Setting datapoint %u to %s", datapoint_id, hexencode(value).c_str());
optional<TuyaDatapoint> datapoint = this->get_datapoint_(datapoint_id);
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;
}
if (datapoint->value_uint == value) {
} else if (datapoint->value_raw == value) {
ESP_LOGV(TAG, "Not sending unchanged value");
return;
}
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);
this->send_datapoint_command_(datapoint_id, TuyaDatapointType::RAW, value);
}
void Tuya::set_datapoint_value(uint8_t datapoint_id, 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());
optional<TuyaDatapoint> datapoint = this->get_datapoint_(datapoint_id);
if (!datapoint.has_value()) {
ESP_LOGE(TAG, "Attempt to set unknown datapoint %u", datapoint_id);
}
if (datapoint->value_string == value) {
ESP_LOGW(TAG, "Setting unknown datapoint %u", datapoint_id);
} else if (datapoint->type != TuyaDatapointType::STRING) {
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");
return;
}
@ -478,20 +474,12 @@ void Tuya::set_datapoint_value(uint8_t datapoint_id, std::string value) {
this->send_datapoint_command_(datapoint->id, datapoint->type, data);
}
void Tuya::set_datapoint_value(uint8_t datapoint_id, bool value) {
ESP_LOGD(TAG, "Setting datapoint %u to %s", datapoint_id, TRUEFALSE(value));
optional<TuyaDatapoint> datapoint = this->get_datapoint_(datapoint_id);
if (!datapoint.has_value()) {
ESP_LOGE(TAG, "Attempt to set unknown datapoint %u", datapoint_id);
}
else if (datapoint->value_bool == value) {
ESP_LOGV(TAG, "Not sending unchanged value");
return;
}
void Tuya::set_enum_datapoint_value(uint8_t datapoint_id, uint8_t value) {
this->set_numeric_datapoint_value_(datapoint_id, TuyaDatapointType::ENUM, value, 1);
}
std::vector<uint8_t> data;
data.push_back(value >> 0);
this->send_datapoint_command_(datapoint_id, TuyaDatapointType::BOOLEAN, data);
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) {
@ -501,6 +489,37 @@ optional<TuyaDatapoint> Tuya::get_datapoint_(uint8_t datapoint_id) {
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) {
std::vector<uint8_t> buffer;
buffer.push_back(datapoint_id);

View File

@ -75,9 +75,12 @@ class Tuya : public Component, public uart::UARTDevice {
void loop() override;
void dump_config() override;
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_datapoint_value(uint8_t datapoint_id, std::string value);
void set_datapoint_value(uint8_t datapoint_id, bool value);
void set_raw_datapoint_value(uint8_t datapoint_id, const std::vector<uint8_t> &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
void set_time_id(time::RealTimeClock *time_id) { this->time_id_ = time_id; }
#endif
@ -96,6 +99,8 @@ class Tuya : public Component, public uart::UARTDevice {
void process_command_queue_();
void send_command_(TuyaCommand 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_wifi_status_();
@ -114,7 +119,7 @@ class Tuya : public Component, public uart::UARTDevice {
std::vector<uint8_t> rx_message_;
std::vector<uint8_t> ignore_mcu_update_on_datapoints_{};
std::vector<TuyaCommand> command_queue_;
optional<TuyaCommandType> expected_response_{};
optional<TuyaCommandType> expected_response_{};
uint8_t wifi_status_ = -1;
};

View File

@ -20,14 +20,14 @@ void TuyaDimmerAsFan::setup() {
this->parent_->register_listener(*this->dimmer_id_, [this](const TuyaDatapoint &datapoint) {
if (datapoint.value_int != this->dimmer_max_value_)
{
this->parent_->set_datapoint_value(*this->dimmer_id_, this->dimmer_max_value_);
this->parent_->set_integer_datapoint_value(*this->dimmer_id_, this->dimmer_max_value_);
}
});
this->fan_->add_on_state_callback([this]() { this->parent_->set_datapoint_value(*this->switch_id_, this->fan_->state); });
this->fan_->add_on_state_callback([this]() { this->parent_->set_boolean_datapoint_value(*this->switch_id_, this->fan_->state); });
// Make sure we start at the max value
this->parent_->set_datapoint_value(*this->dimmer_id_, this->dimmer_max_value_);
this->parent_->set_integer_datapoint_value(*this->dimmer_id_, this->dimmer_max_value_);
}
void TuyaDimmerAsFan::dump_config() {

View File

@ -12,7 +12,7 @@ void TuyaLightPlus::setup()
this->parent_->register_listener(*this->switch_id_, [this](tuya::TuyaDatapoint datapoint) { this->handle_tuya_datapoint_(datapoint); });
this->parent_->register_listener(*this->dimmer_id_, [this](tuya::TuyaDatapoint datapoint) { this->handle_tuya_datapoint_(datapoint); });
if (this->min_value_datapoint_id_.has_value()) {
this->parent_->set_datapoint_value(*this->min_value_datapoint_id_, this->min_value_);
this->parent_->set_integer_datapoint_value(*this->min_value_datapoint_id_, this->min_value_);
}
this->register_service(&TuyaLightPlus::set_default_brightness, "set_default_brightness", {"brightness"});
@ -52,13 +52,13 @@ void TuyaLightPlus::write_state(light::LightState *state)
if (brightness == 0.0f) {
this->tuya_state_is_on_ = false;
this->parent_->set_datapoint_value(*this->switch_id_, false);
this->parent_->set_boolean_datapoint_value(*this->switch_id_, false);
}
else
{
this->tuya_state_is_on_ = true;
this->parent_->set_datapoint_value(*this->dimmer_id_, this->brightness_to_tuya_level_(brightness));
this->parent_->set_datapoint_value(*this->switch_id_, true);
this->parent_->set_integer_datapoint_value(*this->dimmer_id_, this->brightness_to_tuya_level_(brightness));
this->parent_->set_boolean_datapoint_value(*this->switch_id_, true);
}
}
@ -134,7 +134,7 @@ void TuyaLightPlus::handle_tuya_datapoint_(tuya::TuyaDatapoint datapoint)
{
ESP_LOGD(TAG, "Switch was double clicked while on");
this->parent_->set_datapoint_value(*this->switch_id_, false);
this->parent_->set_boolean_datapoint_value(*this->switch_id_, false);
this->double_click_while_on_timeout_ = 0;
this->double_click_while_on_callback_.call();
@ -149,7 +149,7 @@ void TuyaLightPlus::handle_tuya_datapoint_(tuya::TuyaDatapoint datapoint)
if (this->double_click_while_off_timeout_ == 0)
{
// Turn the light back off and wait to see if we get a double click
this->parent_->set_datapoint_value(*this->switch_id_, false);
this->parent_->set_boolean_datapoint_value(*this->switch_id_, false);
this->double_click_while_off_timeout_ = millis() + DOUBLE_CLICK_TIMEOUT;
return;
}
@ -164,7 +164,7 @@ void TuyaLightPlus::handle_tuya_datapoint_(tuya::TuyaDatapoint datapoint)
// Double click while off can be configured to result in the light being off or on
if (this->double_click_while_off_stays_off_)
{
this->parent_->set_datapoint_value(*this->switch_id_, false);
this->parent_->set_boolean_datapoint_value(*this->switch_id_, false);
return;
}
}
@ -173,7 +173,7 @@ void TuyaLightPlus::handle_tuya_datapoint_(tuya::TuyaDatapoint datapoint)
// When the light is turned on at the switch the level of the Tuya device will stll be 0 so we set it to the current state value
float brightness;
this->state_->current_values_as_brightness(&brightness);
this->parent_->set_datapoint_value(*this->dimmer_id_, this->brightness_to_tuya_level_(brightness));
this->parent_->set_integer_datapoint_value(*this->dimmer_id_, this->brightness_to_tuya_level_(brightness));
}
// Turned off with the physical button
@ -195,7 +195,7 @@ void TuyaLightPlus::handle_tuya_datapoint_(tuya::TuyaDatapoint datapoint)
// default brightness set the current brightness value to the default so that if it is turned on remotely it will be at the default value
if (!datapoint.value_bool)
{
this->parent_->set_datapoint_value(*this->dimmer_id_, static_cast<uint32_t>(0));
this->parent_->set_integer_datapoint_value(*this->dimmer_id_, 0);
if (this->default_brightness_.has_value())
{
this->state_->current_values.set_brightness(*this->default_brightness_);

View File

@ -6,11 +6,6 @@ substitutions:
api_pwd: !secret office_light_api_pwd
ap_wifi_pwd: !secret office_light_ap_wifi_pwd
script:
- id: double_click
then:
- logger.log: "Double click script has been run!"
packages:
feit_dimmer: !include ../packages/feit_dimmer.yaml
@ -31,8 +26,3 @@ light:
night_default_brightness: 1
day_auto_off_time: 0 min
night_auto_off_time: 15 min
on_double_click_while_off:
- script.execute: double_click
double_click_while_off_stays_off: true
on_double_click_while_on:
- script.execute: double_click