mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Tuya status gpio support (#3466)
This commit is contained in:
		
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							fea05e9d33
						
					
				
				
					commit
					0665acd190
				
			| @@ -1,5 +1,6 @@ | ||||
| from esphome.components import time | ||||
| from esphome import automation | ||||
| from esphome import pins | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import uart | ||||
| @@ -11,6 +12,7 @@ CONF_IGNORE_MCU_UPDATE_ON_DATAPOINTS = "ignore_mcu_update_on_datapoints" | ||||
|  | ||||
| CONF_ON_DATAPOINT_UPDATE = "on_datapoint_update" | ||||
| CONF_DATAPOINT_TYPE = "datapoint_type" | ||||
| CONF_STATUS_PIN = "status_pin" | ||||
|  | ||||
| tuya_ns = cg.esphome_ns.namespace("tuya") | ||||
| Tuya = tuya_ns.class_("Tuya", cg.Component, uart.UARTDevice) | ||||
| @@ -88,6 +90,7 @@ CONFIG_SCHEMA = ( | ||||
|             cv.Optional(CONF_IGNORE_MCU_UPDATE_ON_DATAPOINTS): cv.ensure_list( | ||||
|                 cv.uint8_t | ||||
|             ), | ||||
|             cv.Optional(CONF_STATUS_PIN): pins.gpio_output_pin_schema, | ||||
|             cv.Optional(CONF_ON_DATAPOINT_UPDATE): automation.validate_automation( | ||||
|                 { | ||||
|                     cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( | ||||
| @@ -114,6 +117,9 @@ async def to_code(config): | ||||
|     if CONF_TIME_ID in config: | ||||
|         time_ = await cg.get_variable(config[CONF_TIME_ID]) | ||||
|         cg.add(var.set_time_id(time_)) | ||||
|     if CONF_STATUS_PIN in config: | ||||
|         status_pin_ = await cg.gpio_pin_expression(config[CONF_STATUS_PIN]) | ||||
|         cg.add(var.set_status_pin(status_pin_)) | ||||
|     if CONF_IGNORE_MCU_UPDATE_ON_DATAPOINTS in config: | ||||
|         for dp in config[CONF_IGNORE_MCU_UPDATE_ON_DATAPOINTS]: | ||||
|             cg.add(var.add_ignore_mcu_update_on_datapoints(dp)) | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| #include "esphome/components/network/util.h" | ||||
| #include "esphome/core/helpers.h" | ||||
| #include "esphome/core/util.h" | ||||
| #include "esphome/core/gpio.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace tuya { | ||||
| @@ -13,6 +14,9 @@ static const int RECEIVE_TIMEOUT = 300; | ||||
|  | ||||
| void Tuya::setup() { | ||||
|   this->set_interval("heartbeat", 15000, [this] { this->send_empty_command_(TuyaCommandType::HEARTBEAT); }); | ||||
|   if (this->status_pin_.has_value()) { | ||||
|     this->status_pin_.value()->digital_write(false); | ||||
|   } | ||||
| } | ||||
|  | ||||
| void Tuya::loop() { | ||||
| @@ -49,9 +53,12 @@ void Tuya::dump_config() { | ||||
|       ESP_LOGCONFIG(TAG, "  Datapoint %u: unknown", info.id); | ||||
|     } | ||||
|   } | ||||
|   if ((this->gpio_status_ != -1) || (this->gpio_reset_ != -1)) { | ||||
|     ESP_LOGCONFIG(TAG, "  GPIO Configuration: status: pin %d, reset: pin %d (not supported)", this->gpio_status_, | ||||
|                   this->gpio_reset_); | ||||
|   if ((this->status_pin_reported_ != -1) || (this->reset_pin_reported_ != -1)) { | ||||
|     ESP_LOGCONFIG(TAG, "  GPIO Configuration: status: pin %d, reset: pin %d (not supported)", | ||||
|                   this->status_pin_reported_, this->reset_pin_reported_); | ||||
|   } | ||||
|   if (this->status_pin_.has_value()) { | ||||
|     LOG_PIN("  Status Pin: ", this->status_pin_.value()); | ||||
|   } | ||||
|   ESP_LOGCONFIG(TAG, "  Product: '%s'", this->product_.c_str()); | ||||
|   this->check_uart_settings(9600); | ||||
| @@ -164,16 +171,27 @@ void Tuya::handle_command_(uint8_t command, uint8_t version, const uint8_t *buff | ||||
|     } | ||||
|     case TuyaCommandType::CONF_QUERY: { | ||||
|       if (len >= 2) { | ||||
|         this->gpio_status_ = buffer[0]; | ||||
|         this->gpio_reset_ = buffer[1]; | ||||
|         this->status_pin_reported_ = buffer[0]; | ||||
|         this->reset_pin_reported_ = buffer[1]; | ||||
|       } | ||||
|       if (this->init_state_ == TuyaInitState::INIT_CONF) { | ||||
|         // If mcu returned status gpio, then we can omit sending wifi state | ||||
|         if (this->gpio_status_ != -1) { | ||||
|         if (this->status_pin_reported_ != -1) { | ||||
|           this->init_state_ = TuyaInitState::INIT_DATAPOINT; | ||||
|           this->send_empty_command_(TuyaCommandType::DATAPOINT_QUERY); | ||||
|           bool is_pin_equals = | ||||
|               this->status_pin_.has_value() && this->status_pin_.value()->get_pin() == this->status_pin_reported_; | ||||
|           // Configure status pin toggling (if reported and configured) or WIFI_STATE periodic send | ||||
|           if (is_pin_equals) { | ||||
|             ESP_LOGV(TAG, "Configured status pin %i", this->status_pin_reported_); | ||||
|             this->set_interval("wifi", 1000, [this] { this->set_status_pin_(); }); | ||||
|           } else { | ||||
|             ESP_LOGW(TAG, "Supplied status_pin does not equals the reported pin %i. TuyaMcu will work in limited mode.", | ||||
|                      this->status_pin_reported_); | ||||
|           } | ||||
|         } else { | ||||
|           this->init_state_ = TuyaInitState::INIT_WIFI; | ||||
|           ESP_LOGV(TAG, "Configured WIFI_STATE periodic send"); | ||||
|           this->set_interval("wifi", 1000, [this] { this->send_wifi_status_(); }); | ||||
|         } | ||||
|       } | ||||
| @@ -397,18 +415,21 @@ void Tuya::send_empty_command_(TuyaCommandType command) { | ||||
|   send_command_(TuyaCommand{.cmd = command, .payload = std::vector<uint8_t>{}}); | ||||
| } | ||||
|  | ||||
| void Tuya::set_status_pin_() { | ||||
|   bool is_network_ready = network::is_connected() && remote_is_connected(); | ||||
|   this->status_pin_.value()->digital_write(is_network_ready); | ||||
| } | ||||
|  | ||||
| void Tuya::send_wifi_status_() { | ||||
|   uint8_t status = 0x02; | ||||
|   if (network::is_connected()) { | ||||
|     status = 0x03; | ||||
|  | ||||
|     // Protocol version 3 also supports specifying when connected to "the cloud" | ||||
|     if (this->protocol_version_ >= 0x03) { | ||||
|       if (remote_is_connected()) { | ||||
|     if (this->protocol_version_ >= 0x03 && remote_is_connected()) { | ||||
|       status = 0x04; | ||||
|     } | ||||
|   } | ||||
|   } | ||||
|  | ||||
|   if (status == this->wifi_status_) { | ||||
|     return; | ||||
|   | ||||
| @@ -79,6 +79,7 @@ class Tuya : public Component, public uart::UARTDevice { | ||||
|   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_status_pin(InternalGPIOPin *status_pin) { this->status_pin_ = status_pin; } | ||||
|   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); | ||||
| @@ -115,6 +116,7 @@ class Tuya : public Component, public uart::UARTDevice { | ||||
|   void set_string_datapoint_value_(uint8_t datapoint_id, const std::string &value, bool forced); | ||||
|   void set_raw_datapoint_value_(uint8_t datapoint_id, const std::vector<uint8_t> &value, bool forced); | ||||
|   void send_datapoint_command_(uint8_t datapoint_id, TuyaDatapointType datapoint_type, std::vector<uint8_t> data); | ||||
|   void set_status_pin_(); | ||||
|   void send_wifi_status_(); | ||||
|  | ||||
| #ifdef USE_TIME | ||||
| @@ -123,8 +125,9 @@ class Tuya : public Component, public uart::UARTDevice { | ||||
| #endif | ||||
|   TuyaInitState init_state_ = TuyaInitState::INIT_HEARTBEAT; | ||||
|   uint8_t protocol_version_ = -1; | ||||
|   int gpio_status_ = -1; | ||||
|   int gpio_reset_ = -1; | ||||
|   optional<InternalGPIOPin *> status_pin_{}; | ||||
|   int status_pin_reported_ = -1; | ||||
|   int reset_pin_reported_ = -1; | ||||
|   uint32_t last_command_timestamp_ = 0; | ||||
|   uint32_t last_rx_char_timestamp_ = 0; | ||||
|   std::string product_ = ""; | ||||
|   | ||||
| @@ -57,6 +57,9 @@ time: | ||||
|  | ||||
| tuya: | ||||
|   time_id: sntp_time | ||||
|   status_pin: | ||||
|     number: 14 | ||||
|     inverted: true | ||||
|  | ||||
| pipsolar: | ||||
|     id: inverter0 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user