mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	| @@ -1,15 +1,27 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import pins | ||||
| from esphome.const import CONF_BAUD_RATE, CONF_ID, CONF_RX_PIN, CONF_TX_PIN, CONF_UART_ID | ||||
| from esphome import pins, automation | ||||
| from esphome.const import CONF_BAUD_RATE, CONF_ID, CONF_RX_PIN, CONF_TX_PIN, CONF_UART_ID, CONF_DATA | ||||
| from esphome.core import CORE, coroutine | ||||
| from esphome.py_compat import text_type, binary_type, char_to_byte | ||||
|  | ||||
| uart_ns = cg.esphome_ns.namespace('uart') | ||||
| UARTComponent = uart_ns.class_('UARTComponent', cg.Component) | ||||
| UARTDevice = uart_ns.class_('UARTDevice') | ||||
| UARTWriteAction = uart_ns.class_('UARTWriteAction', automation.Action) | ||||
| MULTI_CONF = True | ||||
|  | ||||
|  | ||||
| def validate_raw_data(value): | ||||
|     if isinstance(value, text_type): | ||||
|         return value.encode('utf-8') | ||||
|     if isinstance(value, str): | ||||
|         return value | ||||
|     if isinstance(value, list): | ||||
|         return cv.Schema([cv.hex_uint8_t])(value) | ||||
|     raise cv.Invalid("data must either be a string wrapped in quotes or a list of bytes") | ||||
|  | ||||
|  | ||||
| def validate_rx_pin(value): | ||||
|     value = pins.input_pin(value) | ||||
|     if CORE.is_esp8266 and value >= 16: | ||||
| @@ -51,3 +63,22 @@ def register_uart_device(var, config): | ||||
|     """ | ||||
|     parent = yield cg.get_variable(config[CONF_UART_ID]) | ||||
|     cg.add(var.set_uart_parent(parent)) | ||||
|  | ||||
|  | ||||
| @automation.register_action('uart.write', UARTWriteAction, cv.maybe_simple_value({ | ||||
|     cv.GenerateID(): cv.use_id(UARTComponent), | ||||
|     cv.Required(CONF_DATA): cv.templatable(validate_raw_data), | ||||
| }, key=CONF_DATA)) | ||||
| def uart_write_to_code(config, action_id, template_arg, args): | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     yield cg.register_parented(var, config[CONF_ID]) | ||||
|     data = config[CONF_DATA] | ||||
|     if isinstance(data, binary_type): | ||||
|         data = [char_to_byte(x) for x in data] | ||||
|  | ||||
|     if cg.is_template(data): | ||||
|         templ = yield cg.templatable(data, args, cg.std_vector.template(cg.uint8)) | ||||
|         cg.add(var.set_data_template(templ)) | ||||
|     else: | ||||
|         cg.add(var.set_data_static(data)) | ||||
|     yield var | ||||
|   | ||||
							
								
								
									
										36
									
								
								esphome/components/uart/automation.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								esphome/components/uart/automation.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "uart.h" | ||||
| #include "esphome/core/automation.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace uart { | ||||
|  | ||||
| template<typename... Ts> class UARTWriteAction : public Action<Ts...>, public Parented<UARTComponent> { | ||||
|  public: | ||||
|   void set_data_template(std::function<std::vector<uint8_t>(Ts...)> func) { | ||||
|     this->data_func_ = func; | ||||
|     this->static_ = false; | ||||
|   } | ||||
|   void set_data_static(const std::vector<uint8_t> &data) { | ||||
|     this->data_static_ = data; | ||||
|     this->static_ = true; | ||||
|   } | ||||
|  | ||||
|   void play(Ts... x) override { | ||||
|     if (this->static_) { | ||||
|       this->parent_->write_array(this->data_static_); | ||||
|     } else { | ||||
|       auto val = this->data_func_(x...); | ||||
|       this->parent_->write_array(val); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|  protected: | ||||
|   bool static_{false}; | ||||
|   std::function<std::vector<uint8_t>(Ts...)> data_func_{}; | ||||
|   std::vector<uint8_t> data_static_{}; | ||||
| }; | ||||
|  | ||||
| }  // namespace uart | ||||
| }  // namespace esphome | ||||
| @@ -3,27 +3,17 @@ import esphome.config_validation as cv | ||||
| from esphome.components import switch, uart | ||||
| from esphome.const import CONF_DATA, CONF_ID, CONF_INVERTED | ||||
| from esphome.core import HexInt | ||||
| from esphome.py_compat import text_type, binary_type, char_to_byte | ||||
| from .. import uart_ns | ||||
| from esphome.py_compat import binary_type, char_to_byte | ||||
| from .. import uart_ns, validate_raw_data | ||||
|  | ||||
| DEPENDENCIES = ['uart'] | ||||
|  | ||||
| UARTSwitch = uart_ns.class_('UARTSwitch', switch.Switch, uart.UARTDevice, cg.Component) | ||||
|  | ||||
|  | ||||
| def validate_data(value): | ||||
|     if isinstance(value, text_type): | ||||
|         return value.encode('utf-8') | ||||
|     if isinstance(value, str): | ||||
|         return value | ||||
|     if isinstance(value, list): | ||||
|         return cv.Schema([cv.hex_uint8_t])(value) | ||||
|     raise cv.Invalid("data must either be a string wrapped in quotes or a list of bytes") | ||||
|  | ||||
|  | ||||
| CONFIG_SCHEMA = switch.SWITCH_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(UARTSwitch), | ||||
|     cv.Required(CONF_DATA): validate_data, | ||||
|     cv.Required(CONF_DATA): validate_raw_data, | ||||
|     cv.Optional(CONF_INVERTED): cv.invalid("UART switches do not support inverted mode!"), | ||||
| }).extend(uart.UART_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|   | ||||
| @@ -49,6 +49,7 @@ class UARTComponent : public Component, public Stream { | ||||
|   void write_byte(uint8_t data); | ||||
|  | ||||
|   void write_array(const uint8_t *data, size_t len); | ||||
|   void write_array(const std::vector<uint8_t> &data) { this->write_array(&data[0], data.size()); } | ||||
|  | ||||
|   void write_str(const char *str); | ||||
|  | ||||
| @@ -97,6 +98,7 @@ class UARTDevice : public Stream { | ||||
|   void write_byte(uint8_t data) { this->parent_->write_byte(data); } | ||||
|  | ||||
|   void write_array(const uint8_t *data, size_t len) { this->parent_->write_array(data, len); } | ||||
|   void write_array(const std::vector<uint8_t> &data) { this->parent_->write_array(data); } | ||||
|  | ||||
|   void write_str(const char *str) { this->parent_->write_str(str); } | ||||
|  | ||||
|   | ||||
| @@ -1210,13 +1210,14 @@ def validate_registry(name, registry): | ||||
|     return ensure_list(validate_registry_entry(name, registry)) | ||||
|  | ||||
|  | ||||
| def maybe_simple_value(*validators): | ||||
| def maybe_simple_value(*validators, **kwargs): | ||||
|     key = kwargs.pop('key', CONF_VALUE) | ||||
|     validator = All(*validators) | ||||
|  | ||||
|     def validate(value): | ||||
|         if isinstance(value, dict) and CONF_VALUE in value: | ||||
|         if isinstance(value, dict) and key in value: | ||||
|             return validator(value) | ||||
|         return validator({CONF_VALUE: value}) | ||||
|         return validator({key: value}) | ||||
|  | ||||
|     return validate | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user