1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-26 07:02:21 +01:00

Merge remote-tracking branch 'upstream/dev' into integration

This commit is contained in:
J. Nick Koston
2025-09-22 16:23:13 -05:00
25 changed files with 294 additions and 35 deletions

View File

@@ -30,11 +30,16 @@ jobs:
run: | run: |
python -m pip install --upgrade pip python -m pip install --upgrade pip
pip install -e lib/home-assistant pip install -e lib/home-assistant
pip install -r requirements_test.txt pre-commit
- name: Sync - name: Sync
run: | run: |
python ./script/sync-device_class.py python ./script/sync-device_class.py
- name: Run pre-commit hooks
run: |
python script/run-in-env.py pre-commit run --all-files
- name: Commit changes - name: Commit changes
uses: peter-evans/create-pull-request@v7.0.8 uses: peter-evans/create-pull-request@v7.0.8
with: with:

View File

@@ -4,7 +4,7 @@ from esphome import core
from esphome.config_helpers import Extend, Remove, merge_config from esphome.config_helpers import Extend, Remove, merge_config
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.const import CONF_SUBSTITUTIONS, VALID_SUBSTITUTIONS_CHARACTERS from esphome.const import CONF_SUBSTITUTIONS, VALID_SUBSTITUTIONS_CHARACTERS
from esphome.yaml_util import ESPHomeDataBase, make_data_base from esphome.yaml_util import ESPHomeDataBase, ESPLiteralValue, make_data_base
from .jinja import Jinja, JinjaStr, TemplateError, TemplateRuntimeError, has_jinja from .jinja import Jinja, JinjaStr, TemplateError, TemplateRuntimeError, has_jinja
@@ -127,6 +127,8 @@ def _expand_substitutions(substitutions, value, path, jinja, ignore_missing):
def _substitute_item(substitutions, item, path, jinja, ignore_missing): def _substitute_item(substitutions, item, path, jinja, ignore_missing):
if isinstance(item, ESPLiteralValue):
return None # do not substitute inside literal blocks
if isinstance(item, list): if isinstance(item, list):
for i, it in enumerate(item): for i, it in enumerate(item):
sub = _substitute_item(substitutions, it, path + [i], jinja, ignore_missing) sub = _substitute_item(substitutions, it, path + [i], jinja, ignore_missing)

View File

@@ -215,12 +215,37 @@ void Tuya::handle_command_(uint8_t command, uint8_t version, const uint8_t *buff
this->send_empty_command_(TuyaCommandType::DATAPOINT_QUERY); this->send_empty_command_(TuyaCommandType::DATAPOINT_QUERY);
} }
break; break;
case TuyaCommandType::WIFI_RESET:
ESP_LOGE(TAG, "WIFI_RESET is not handled");
break;
case TuyaCommandType::WIFI_SELECT: case TuyaCommandType::WIFI_SELECT:
ESP_LOGE(TAG, "WIFI_SELECT is not handled"); case TuyaCommandType::WIFI_RESET: {
const bool is_select = (len >= 1);
// Send WIFI_SELECT ACK
TuyaCommand ack;
ack.cmd = is_select ? TuyaCommandType::WIFI_SELECT : TuyaCommandType::WIFI_RESET;
ack.payload.clear();
this->send_command_(ack);
// Establish pairing mode for correct first WIFI_STATE byte, EZ (0x00) default
uint8_t first = 0x00;
const char *mode_str = "EZ";
if (is_select && buffer[0] == 0x01) {
first = 0x01;
mode_str = "AP";
}
// Send WIFI_STATE response, MCU exits pairing mode
TuyaCommand st;
st.cmd = TuyaCommandType::WIFI_STATE;
st.payload.resize(1);
st.payload[0] = first;
this->send_command_(st);
st.payload[0] = 0x02;
this->send_command_(st);
st.payload[0] = 0x03;
this->send_command_(st);
st.payload[0] = 0x04;
this->send_command_(st);
ESP_LOGI(TAG, "%s received (%s), replied with WIFI_STATE confirming connection established",
is_select ? "WIFI_SELECT" : "WIFI_RESET", mode_str);
break; break;
}
case TuyaCommandType::DATAPOINT_DELIVER: case TuyaCommandType::DATAPOINT_DELIVER:
break; break;
case TuyaCommandType::DATAPOINT_REPORT_ASYNC: case TuyaCommandType::DATAPOINT_REPORT_ASYNC:

View File

@@ -1,3 +1,4 @@
import math
import re import re
from esphome import automation, pins from esphome import automation, pins
@@ -14,6 +15,7 @@ from esphome.const import (
CONF_DIRECTION, CONF_DIRECTION,
CONF_DUMMY_RECEIVER, CONF_DUMMY_RECEIVER,
CONF_DUMMY_RECEIVER_ID, CONF_DUMMY_RECEIVER_ID,
CONF_FLOW_CONTROL_PIN,
CONF_ID, CONF_ID,
CONF_INVERT, CONF_INVERT,
CONF_LAMBDA, CONF_LAMBDA,
@@ -152,6 +154,8 @@ UART_PARITY_OPTIONS = {
CONF_STOP_BITS = "stop_bits" CONF_STOP_BITS = "stop_bits"
CONF_DATA_BITS = "data_bits" CONF_DATA_BITS = "data_bits"
CONF_PARITY = "parity" CONF_PARITY = "parity"
CONF_RX_FULL_THRESHOLD = "rx_full_threshold"
CONF_RX_TIMEOUT = "rx_timeout"
UARTDirection = uart_ns.enum("UARTDirection") UARTDirection = uart_ns.enum("UARTDirection")
UART_DIRECTIONS = { UART_DIRECTIONS = {
@@ -219,8 +223,17 @@ CONFIG_SCHEMA = cv.All(
cv.Required(CONF_BAUD_RATE): cv.int_range(min=1), cv.Required(CONF_BAUD_RATE): cv.int_range(min=1),
cv.Optional(CONF_TX_PIN): pins.internal_gpio_output_pin_schema, cv.Optional(CONF_TX_PIN): pins.internal_gpio_output_pin_schema,
cv.Optional(CONF_RX_PIN): validate_rx_pin, cv.Optional(CONF_RX_PIN): validate_rx_pin,
cv.Optional(CONF_FLOW_CONTROL_PIN): cv.All(
cv.only_on_esp32, pins.internal_gpio_output_pin_schema
),
cv.Optional(CONF_PORT): cv.All(validate_port, cv.only_on(PLATFORM_HOST)), cv.Optional(CONF_PORT): cv.All(validate_port, cv.only_on(PLATFORM_HOST)),
cv.Optional(CONF_RX_BUFFER_SIZE, default=256): cv.validate_bytes, cv.Optional(CONF_RX_BUFFER_SIZE, default=256): cv.validate_bytes,
cv.Optional(CONF_RX_FULL_THRESHOLD): cv.All(
cv.only_on_esp32, cv.validate_bytes, cv.int_range(min=1, max=120)
),
cv.SplitDefault(CONF_RX_TIMEOUT, esp32=2): cv.All(
cv.only_on_esp32, cv.validate_bytes, cv.int_range(min=0, max=92)
),
cv.Optional(CONF_STOP_BITS, default=1): cv.one_of(1, 2, int=True), cv.Optional(CONF_STOP_BITS, default=1): cv.one_of(1, 2, int=True),
cv.Optional(CONF_DATA_BITS, default=8): cv.int_range(min=5, max=8), cv.Optional(CONF_DATA_BITS, default=8): cv.int_range(min=5, max=8),
cv.Optional(CONF_PARITY, default="NONE"): cv.enum( cv.Optional(CONF_PARITY, default="NONE"): cv.enum(
@@ -275,9 +288,27 @@ async def to_code(config):
if CONF_RX_PIN in config: if CONF_RX_PIN in config:
rx_pin = await cg.gpio_pin_expression(config[CONF_RX_PIN]) rx_pin = await cg.gpio_pin_expression(config[CONF_RX_PIN])
cg.add(var.set_rx_pin(rx_pin)) cg.add(var.set_rx_pin(rx_pin))
if CONF_FLOW_CONTROL_PIN in config:
flow_control_pin = await cg.gpio_pin_expression(config[CONF_FLOW_CONTROL_PIN])
cg.add(var.set_flow_control_pin(flow_control_pin))
if CONF_PORT in config: if CONF_PORT in config:
cg.add(var.set_name(config[CONF_PORT])) cg.add(var.set_name(config[CONF_PORT]))
cg.add(var.set_rx_buffer_size(config[CONF_RX_BUFFER_SIZE])) cg.add(var.set_rx_buffer_size(config[CONF_RX_BUFFER_SIZE]))
if CORE.is_esp32:
if CONF_RX_FULL_THRESHOLD not in config:
# Calculate rx_full_threshold to be 10ms
bytelength = config[CONF_DATA_BITS] + config[CONF_STOP_BITS] + 1
if config[CONF_PARITY] != "NONE":
bytelength += 1
config[CONF_RX_FULL_THRESHOLD] = max(
1,
min(
120,
math.floor((config[CONF_BAUD_RATE] / (bytelength * 1000 / 10)) - 1),
),
)
cg.add(var.set_rx_full_threshold(config[CONF_RX_FULL_THRESHOLD]))
cg.add(var.set_rx_timeout(config[CONF_RX_TIMEOUT]))
cg.add(var.set_stop_bits(config[CONF_STOP_BITS])) cg.add(var.set_stop_bits(config[CONF_STOP_BITS]))
cg.add(var.set_data_bits(config[CONF_DATA_BITS])) cg.add(var.set_data_bits(config[CONF_DATA_BITS]))
cg.add(var.set_parity(config[CONF_PARITY])) cg.add(var.set_parity(config[CONF_PARITY]))

View File

@@ -18,6 +18,12 @@ class UARTDevice {
void write_byte(uint8_t data) { this->parent_->write_byte(data); } void write_byte(uint8_t data) { this->parent_->write_byte(data); }
void set_rx_full_threshold(size_t rx_full_threshold) { this->parent_->set_rx_full_threshold(rx_full_threshold); }
void set_rx_full_threshold_ms(size_t time) { this->parent_->set_rx_full_threshold_ms(time); }
size_t get_rx_full_threshold() { return this->parent_->get_rx_full_threshold(); }
void set_rx_timeout(size_t rx_timeout) { this->parent_->set_rx_timeout(rx_timeout); }
size_t get_rx_timeout() { return this->parent_->get_rx_timeout(); }
void write_array(const uint8_t *data, size_t len) { this->parent_->write_array(data, len); } 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_array(const std::vector<uint8_t> &data) { this->parent_->write_array(data); }
template<size_t N> void write_array(const std::array<uint8_t, N> &data) { template<size_t N> void write_array(const std::array<uint8_t, N> &data) {

View File

@@ -20,5 +20,13 @@ bool UARTComponent::check_read_timeout_(size_t len) {
return true; return true;
} }
void UARTComponent::set_rx_full_threshold_ms(uint8_t time) {
uint8_t bytelength = this->data_bits_ + this->stop_bits_ + 1;
if (this->parity_ != UARTParityOptions::UART_CONFIG_PARITY_NONE)
bytelength += 1;
int32_t val = clamp<int32_t>((this->baud_rate_ / (bytelength * 1000 / time)) - 1, 1, 120);
this->set_rx_full_threshold(val);
}
} // namespace uart } // namespace uart
} // namespace esphome } // namespace esphome

View File

@@ -6,6 +6,7 @@
#include "esphome/core/component.h" #include "esphome/core/component.h"
#include "esphome/core/hal.h" #include "esphome/core/hal.h"
#include "esphome/core/log.h" #include "esphome/core/log.h"
#include "esphome/core/helpers.h"
#ifdef USE_UART_DEBUGGER #ifdef USE_UART_DEBUGGER
#include "esphome/core/automation.h" #include "esphome/core/automation.h"
#endif #endif
@@ -82,6 +83,10 @@ class UARTComponent {
// @param rx_pin Pointer to the internal GPIO pin used for reception. // @param rx_pin Pointer to the internal GPIO pin used for reception.
void set_rx_pin(InternalGPIOPin *rx_pin) { this->rx_pin_ = rx_pin; } void set_rx_pin(InternalGPIOPin *rx_pin) { this->rx_pin_ = rx_pin; }
// Sets the flow control pin for the UART bus.
// @param flow_control_pin Pointer to the internal GPIO pin used for flow control.
void set_flow_control_pin(InternalGPIOPin *flow_control_pin) { this->flow_control_pin_ = flow_control_pin; }
// Sets the size of the RX buffer. // Sets the size of the RX buffer.
// @param rx_buffer_size Size of the RX buffer in bytes. // @param rx_buffer_size Size of the RX buffer in bytes.
void set_rx_buffer_size(size_t rx_buffer_size) { this->rx_buffer_size_ = rx_buffer_size; } void set_rx_buffer_size(size_t rx_buffer_size) { this->rx_buffer_size_ = rx_buffer_size; }
@@ -90,6 +95,26 @@ class UARTComponent {
// @return Size of the RX buffer in bytes. // @return Size of the RX buffer in bytes.
size_t get_rx_buffer_size() { return this->rx_buffer_size_; } size_t get_rx_buffer_size() { return this->rx_buffer_size_; }
// Sets the RX FIFO full interrupt threshold.
// @param rx_full_threshold RX full interrupt threshold in bytes.
virtual void set_rx_full_threshold(size_t rx_full_threshold) {}
// Sets the RX FIFO full interrupt threshold.
// @param time RX full interrupt threshold in ms.
void set_rx_full_threshold_ms(uint8_t time);
// Gets the RX FIFO full interrupt threshold.
// @return RX full interrupt threshold in bytes.
size_t get_rx_full_threshold() { return this->rx_full_threshold_; }
// Sets the RX timeout interrupt threshold.
// @param rx_timeout RX timeout interrupt threshold (unit: time of sending one byte).
virtual void set_rx_timeout(size_t rx_timeout) {}
// Gets the RX timeout interrupt threshold.
// @return RX timeout interrupt threshold (unit: time of sending one byte).
size_t get_rx_timeout() { return this->rx_timeout_; }
// Sets the number of stop bits used in UART communication. // Sets the number of stop bits used in UART communication.
// @param stop_bits Number of stop bits. // @param stop_bits Number of stop bits.
void set_stop_bits(uint8_t stop_bits) { this->stop_bits_ = stop_bits; } void set_stop_bits(uint8_t stop_bits) { this->stop_bits_ = stop_bits; }
@@ -161,7 +186,10 @@ class UARTComponent {
InternalGPIOPin *tx_pin_; InternalGPIOPin *tx_pin_;
InternalGPIOPin *rx_pin_; InternalGPIOPin *rx_pin_;
InternalGPIOPin *flow_control_pin_;
size_t rx_buffer_size_; size_t rx_buffer_size_;
size_t rx_full_threshold_{1};
size_t rx_timeout_{0};
uint32_t baud_rate_; uint32_t baud_rate_;
uint8_t stop_bits_; uint8_t stop_bits_;
uint8_t data_bits_; uint8_t data_bits_;

View File

@@ -90,6 +90,12 @@ void IDFUARTComponent::setup() {
xSemaphoreTake(this->lock_, portMAX_DELAY); xSemaphoreTake(this->lock_, portMAX_DELAY);
this->load_settings(false);
xSemaphoreGive(this->lock_);
}
void IDFUARTComponent::load_settings(bool dump_config) {
uart_config_t uart_config = this->get_config_(); uart_config_t uart_config = this->get_config_();
esp_err_t err = uart_param_config(this->uart_num_, &uart_config); esp_err_t err = uart_param_config(this->uart_num_, &uart_config);
if (err != ESP_OK) { if (err != ESP_OK) {
@@ -100,6 +106,7 @@ void IDFUARTComponent::setup() {
int8_t tx = this->tx_pin_ != nullptr ? this->tx_pin_->get_pin() : -1; int8_t tx = this->tx_pin_ != nullptr ? this->tx_pin_->get_pin() : -1;
int8_t rx = this->rx_pin_ != nullptr ? this->rx_pin_->get_pin() : -1; int8_t rx = this->rx_pin_ != nullptr ? this->rx_pin_->get_pin() : -1;
int8_t flow_control = this->flow_control_pin_ != nullptr ? this->flow_control_pin_->get_pin() : -1;
uint32_t invert = 0; uint32_t invert = 0;
if (this->tx_pin_ != nullptr && this->tx_pin_->is_inverted()) if (this->tx_pin_ != nullptr && this->tx_pin_->is_inverted())
@@ -114,13 +121,21 @@ void IDFUARTComponent::setup() {
return; return;
} }
err = uart_set_pin(this->uart_num_, tx, rx, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); err = uart_set_pin(this->uart_num_, tx, rx, flow_control, UART_PIN_NO_CHANGE);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGW(TAG, "uart_set_pin failed: %s", esp_err_to_name(err)); ESP_LOGW(TAG, "uart_set_pin failed: %s", esp_err_to_name(err));
this->mark_failed(); this->mark_failed();
return; return;
} }
if (uart_is_driver_installed(this->uart_num_)) {
uart_driver_delete(this->uart_num_);
if (err != ESP_OK) {
ESP_LOGW(TAG, "uart_driver_delete failed: %s", esp_err_to_name(err));
this->mark_failed();
return;
}
}
err = uart_driver_install(this->uart_num_, /* UART RX ring buffer size. */ this->rx_buffer_size_, err = uart_driver_install(this->uart_num_, /* UART RX ring buffer size. */ this->rx_buffer_size_,
/* UART TX ring buffer size. If set to zero, driver will not use TX buffer, TX function will /* UART TX ring buffer size. If set to zero, driver will not use TX buffer, TX function will
block task until all data have been sent out.*/ block task until all data have been sent out.*/
@@ -133,17 +148,29 @@ void IDFUARTComponent::setup() {
return; return;
} }
xSemaphoreGive(this->lock_); err = uart_set_rx_full_threshold(this->uart_num_, this->rx_full_threshold_);
}
void IDFUARTComponent::load_settings(bool dump_config) {
uart_config_t uart_config = this->get_config_();
esp_err_t err = uart_param_config(this->uart_num_, &uart_config);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGW(TAG, "uart_param_config failed: %s", esp_err_to_name(err)); ESP_LOGW(TAG, "uart_set_rx_full_threshold failed: %s", esp_err_to_name(err));
this->mark_failed(); this->mark_failed();
return; return;
} else if (dump_config) { }
err = uart_set_rx_timeout(this->uart_num_, this->rx_timeout_);
if (err != ESP_OK) {
ESP_LOGW(TAG, "uart_set_rx_timeout failed: %s", esp_err_to_name(err));
this->mark_failed();
return;
}
auto mode = this->flow_control_pin_ != nullptr ? UART_MODE_RS485_HALF_DUPLEX : UART_MODE_UART;
err = uart_set_mode(this->uart_num_, mode);
if (err != ESP_OK) {
ESP_LOGW(TAG, "uart_set_mode failed: %s", esp_err_to_name(err));
this->mark_failed();
return;
}
if (dump_config) {
ESP_LOGCONFIG(TAG, "UART %u was reloaded.", this->uart_num_); ESP_LOGCONFIG(TAG, "UART %u was reloaded.", this->uart_num_);
this->dump_config(); this->dump_config();
} }
@@ -153,8 +180,13 @@ void IDFUARTComponent::dump_config() {
ESP_LOGCONFIG(TAG, "UART Bus %u:", this->uart_num_); ESP_LOGCONFIG(TAG, "UART Bus %u:", this->uart_num_);
LOG_PIN(" TX Pin: ", tx_pin_); LOG_PIN(" TX Pin: ", tx_pin_);
LOG_PIN(" RX Pin: ", rx_pin_); LOG_PIN(" RX Pin: ", rx_pin_);
LOG_PIN(" Flow Control Pin: ", flow_control_pin_);
if (this->rx_pin_ != nullptr) { if (this->rx_pin_ != nullptr) {
ESP_LOGCONFIG(TAG, " RX Buffer Size: %u", this->rx_buffer_size_); ESP_LOGCONFIG(TAG,
" RX Buffer Size: %u\n"
" RX Full Threshold: %u\n"
" RX Timeout: %u",
this->rx_buffer_size_, this->rx_full_threshold_, this->rx_timeout_);
} }
ESP_LOGCONFIG(TAG, ESP_LOGCONFIG(TAG,
" Baud Rate: %" PRIu32 " baud\n" " Baud Rate: %" PRIu32 " baud\n"
@@ -165,6 +197,28 @@ void IDFUARTComponent::dump_config() {
this->check_logger_conflict(); this->check_logger_conflict();
} }
void IDFUARTComponent::set_rx_full_threshold(size_t rx_full_threshold) {
if (this->is_ready()) {
esp_err_t err = uart_set_rx_full_threshold(this->uart_num_, rx_full_threshold);
if (err != ESP_OK) {
ESP_LOGW(TAG, "uart_set_rx_full_threshold failed: %s", esp_err_to_name(err));
return;
}
}
this->rx_full_threshold_ = rx_full_threshold;
}
void IDFUARTComponent::set_rx_timeout(size_t rx_timeout) {
if (this->is_ready()) {
esp_err_t err = uart_set_rx_timeout(this->uart_num_, rx_timeout);
if (err != ESP_OK) {
ESP_LOGW(TAG, "uart_set_rx_timeout failed: %s", esp_err_to_name(err));
return;
}
}
this->rx_timeout_ = rx_timeout;
}
void IDFUARTComponent::write_array(const uint8_t *data, size_t len) { void IDFUARTComponent::write_array(const uint8_t *data, size_t len) {
xSemaphoreTake(this->lock_, portMAX_DELAY); xSemaphoreTake(this->lock_, portMAX_DELAY);
uart_write_bytes(this->uart_num_, data, len); uart_write_bytes(this->uart_num_, data, len);

View File

@@ -15,6 +15,9 @@ class IDFUARTComponent : public UARTComponent, public Component {
void dump_config() override; void dump_config() override;
float get_setup_priority() const override { return setup_priority::BUS; } float get_setup_priority() const override { return setup_priority::BUS; }
void set_rx_full_threshold(size_t rx_full_threshold) override;
void set_rx_timeout(size_t rx_timeout) override;
void write_array(const uint8_t *data, size_t len) override; void write_array(const uint8_t *data, size_t len) override;
bool peek_byte(uint8_t *data) override; bool peek_byte(uint8_t *data) override;

View File

@@ -32,7 +32,7 @@ from esphome.log import AnsiFore, color
from esphome.types import ConfigFragmentType, ConfigType from esphome.types import ConfigFragmentType, ConfigType
from esphome.util import OrderedDict, safe_print from esphome.util import OrderedDict, safe_print
from esphome.voluptuous_schema import ExtraKeysInvalid from esphome.voluptuous_schema import ExtraKeysInvalid
from esphome.yaml_util import ESPForceValue, ESPHomeDataBase, is_secret from esphome.yaml_util import ESPHomeDataBase, ESPLiteralValue, is_secret
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@@ -306,7 +306,7 @@ def recursive_check_replaceme(value):
return cv.Schema([recursive_check_replaceme])(value) return cv.Schema([recursive_check_replaceme])(value)
if isinstance(value, dict): if isinstance(value, dict):
return cv.Schema({cv.valid: recursive_check_replaceme})(value) return cv.Schema({cv.valid: recursive_check_replaceme})(value)
if isinstance(value, ESPForceValue): if isinstance(value, ESPLiteralValue):
pass pass
if isinstance(value, str) and value == "REPLACEME": if isinstance(value, str) and value == "REPLACEME":
raise cv.Invalid( raise cv.Invalid(
@@ -314,7 +314,7 @@ def recursive_check_replaceme(value):
"Please make sure you have replaced all fields from the sample " "Please make sure you have replaced all fields from the sample "
"configuration.\n" "configuration.\n"
"If you want to use the literal REPLACEME string, " "If you want to use the literal REPLACEME string, "
'please use "!force REPLACEME"' 'please use "!literal REPLACEME"'
) )
return value return value

View File

@@ -69,7 +69,7 @@ class ESPHomeDataBase:
self._content_offset = database.content_offset self._content_offset = database.content_offset
class ESPForceValue: class ESPLiteralValue:
pass pass
@@ -348,9 +348,15 @@ class ESPHomeLoaderMixin:
return Lambda(str(node.value)) return Lambda(str(node.value))
@_add_data_ref @_add_data_ref
def construct_force(self, node: yaml.Node) -> ESPForceValue: def construct_literal(self, node: yaml.Node) -> ESPLiteralValue:
obj = self.construct_scalar(node) obj = None
return add_class_to_obj(obj, ESPForceValue) if isinstance(node, yaml.ScalarNode):
obj = self.construct_scalar(node)
elif isinstance(node, yaml.SequenceNode):
obj = self.construct_sequence(node)
elif isinstance(node, yaml.MappingNode):
obj = self.construct_mapping(node)
return add_class_to_obj(obj, ESPLiteralValue)
@_add_data_ref @_add_data_ref
def construct_extend(self, node: yaml.Node) -> Extend: def construct_extend(self, node: yaml.Node) -> Extend:
@@ -407,7 +413,7 @@ for _loader in (ESPHomeLoader, ESPHomePurePythonLoader):
"!include_dir_merge_named", _loader.construct_include_dir_merge_named "!include_dir_merge_named", _loader.construct_include_dir_merge_named
) )
_loader.add_constructor("!lambda", _loader.construct_lambda) _loader.add_constructor("!lambda", _loader.construct_lambda)
_loader.add_constructor("!force", _loader.construct_force) _loader.add_constructor("!literal", _loader.construct_literal)
_loader.add_constructor("!extend", _loader.construct_extend) _loader.add_constructor("!extend", _loader.construct_extend)
_loader.add_constructor("!remove", _loader.construct_remove) _loader.add_constructor("!remove", _loader.construct_remove)

View File

@@ -14,17 +14,23 @@ uart:
- id: uart_1 - id: uart_1
tx_pin: 4 tx_pin: 4
rx_pin: 5 rx_pin: 5
flow_control_pin: 6
baud_rate: 9600 baud_rate: 9600
data_bits: 8 data_bits: 8
rx_buffer_size: 512 rx_buffer_size: 512
rx_full_threshold: 10
rx_timeout: 1
parity: EVEN parity: EVEN
stop_bits: 2 stop_bits: 2
- id: uart_2 - id: uart_2
tx_pin: 6 tx_pin: 7
rx_pin: 7 rx_pin: 8
flow_control_pin: 9
baud_rate: 9600 baud_rate: 9600
data_bits: 8 data_bits: 8
rx_buffer_size: 512 rx_buffer_size: 512
rx_full_threshold: 10
rx_timeout: 1
parity: EVEN parity: EVEN
stop_bits: 2 stop_bits: 2

View File

@@ -14,17 +14,23 @@ uart:
- id: uart_1 - id: uart_1
tx_pin: 4 tx_pin: 4
rx_pin: 5 rx_pin: 5
flow_control_pin: 6
baud_rate: 9600 baud_rate: 9600
data_bits: 8 data_bits: 8
rx_buffer_size: 512 rx_buffer_size: 512
rx_full_threshold: 10
rx_timeout: 1
parity: EVEN parity: EVEN
stop_bits: 2 stop_bits: 2
- id: uart_2 - id: uart_2
tx_pin: 6 tx_pin: 7
rx_pin: 7 rx_pin: 8
flow_control_pin: 9
baud_rate: 9600 baud_rate: 9600
data_bits: 8 data_bits: 8
rx_buffer_size: 512 rx_buffer_size: 512
rx_full_threshold: 10
rx_timeout: 1
parity: EVEN parity: EVEN
stop_bits: 2 stop_bits: 2

View File

@@ -14,17 +14,23 @@ uart:
- id: uart_1 - id: uart_1
tx_pin: 4 tx_pin: 4
rx_pin: 5 rx_pin: 5
flow_control_pin: 6
baud_rate: 9600 baud_rate: 9600
data_bits: 8 data_bits: 8
rx_buffer_size: 512 rx_buffer_size: 512
rx_full_threshold: 10
rx_timeout: 1
parity: EVEN parity: EVEN
stop_bits: 2 stop_bits: 2
- id: uart_2 - id: uart_2
tx_pin: 6 tx_pin: 7
rx_pin: 7 rx_pin: 8
flow_control_pin: 9
baud_rate: 9600 baud_rate: 9600
data_bits: 8 data_bits: 8
rx_buffer_size: 512 rx_buffer_size: 512
rx_full_threshold: 10
rx_timeout: 1
parity: EVEN parity: EVEN
stop_bits: 2 stop_bits: 2

View File

@@ -14,17 +14,35 @@ uart:
- id: uart_1 - id: uart_1
tx_pin: 4 tx_pin: 4
rx_pin: 5 rx_pin: 5
flow_control_pin: 6
baud_rate: 9600 baud_rate: 9600
data_bits: 8 data_bits: 8
rx_buffer_size: 512 rx_buffer_size: 512
rx_full_threshold: 10
rx_timeout: 1
parity: EVEN parity: EVEN
stop_bits: 2 stop_bits: 2
- id: uart_2 - id: uart_2
tx_pin: 6 tx_pin: 7
rx_pin: 7 rx_pin: 8
flow_control_pin: 9
baud_rate: 9600 baud_rate: 9600
data_bits: 8 data_bits: 8
rx_buffer_size: 512 rx_buffer_size: 512
rx_full_threshold: 10
rx_timeout: 1
parity: EVEN
stop_bits: 2
- id: uart_3
tx_pin: 10
rx_pin: 11
flow_control_pin: 12
baud_rate: 9600
data_bits: 8
rx_buffer_size: 512
rx_full_threshold: 10
rx_timeout: 1
parity: EVEN parity: EVEN
stop_bits: 2 stop_bits: 2

View File

@@ -14,17 +14,23 @@ uart:
- id: uart_1 - id: uart_1
tx_pin: 4 tx_pin: 4
rx_pin: 5 rx_pin: 5
flow_control_pin: 6
baud_rate: 9600 baud_rate: 9600
data_bits: 8 data_bits: 8
rx_buffer_size: 512 rx_buffer_size: 512
rx_full_threshold: 10
rx_timeout: 1
parity: EVEN parity: EVEN
stop_bits: 2 stop_bits: 2
- id: uart_2 - id: uart_2
tx_pin: 6 tx_pin: 7
rx_pin: 7 rx_pin: 8
flow_control_pin: 9
baud_rate: 9600 baud_rate: 9600
data_bits: 8 data_bits: 8
rx_buffer_size: 512 rx_buffer_size: 512
rx_full_threshold: 10
rx_timeout: 1
parity: EVEN parity: EVEN
stop_bits: 2 stop_bits: 2

View File

@@ -14,17 +14,35 @@ uart:
- id: uart_1 - id: uart_1
tx_pin: 4 tx_pin: 4
rx_pin: 5 rx_pin: 5
flow_control_pin: 6
baud_rate: 9600 baud_rate: 9600
data_bits: 8 data_bits: 8
rx_buffer_size: 512 rx_buffer_size: 512
rx_full_threshold: 10
rx_timeout: 1
parity: EVEN parity: EVEN
stop_bits: 2 stop_bits: 2
- id: uart_2 - id: uart_2
tx_pin: 6 tx_pin: 7
rx_pin: 7 rx_pin: 8
flow_control_pin: 9
baud_rate: 9600 baud_rate: 9600
data_bits: 8 data_bits: 8
rx_buffer_size: 512 rx_buffer_size: 512
rx_full_threshold: 10
rx_timeout: 1
parity: EVEN
stop_bits: 2
- id: uart_3
tx_pin: 10
rx_pin: 11
flow_control_pin: 12
baud_rate: 9600
data_bits: 8
rx_buffer_size: 512
rx_full_threshold: 10
rx_timeout: 1
parity: EVEN parity: EVEN
stop_bits: 2 stop_bits: 2

View File

@@ -8,8 +8,11 @@ uart:
- id: uart_uart - id: uart_uart
tx_pin: 17 tx_pin: 17
rx_pin: 16 rx_pin: 16
flow_control_pin: 4
baud_rate: 9600 baud_rate: 9600
data_bits: 8 data_bits: 8
rx_buffer_size: 512 rx_buffer_size: 512
rx_full_threshold: 10
rx_timeout: 1
parity: EVEN parity: EVEN
stop_bits: 2 stop_bits: 2

View File

@@ -8,8 +8,11 @@ uart:
- id: uart_uart - id: uart_uart
tx_pin: 4 tx_pin: 4
rx_pin: 5 rx_pin: 5
flow_control_pin: 6
baud_rate: 9600 baud_rate: 9600
data_bits: 8 data_bits: 8
rx_buffer_size: 512 rx_buffer_size: 512
rx_full_threshold: 10
rx_timeout: 1
parity: EVEN parity: EVEN
stop_bits: 2 stop_bits: 2

View File

@@ -8,8 +8,11 @@ uart:
- id: uart_uart - id: uart_uart
tx_pin: 4 tx_pin: 4
rx_pin: 5 rx_pin: 5
flow_control_pin: 6
baud_rate: 9600 baud_rate: 9600
data_bits: 8 data_bits: 8
rx_buffer_size: 512 rx_buffer_size: 512
rx_full_threshold: 10
rx_timeout: 1
parity: EVEN parity: EVEN
stop_bits: 2 stop_bits: 2

View File

@@ -8,9 +8,12 @@ uart:
- id: uart_uart - id: uart_uart
tx_pin: 17 tx_pin: 17
rx_pin: 16 rx_pin: 16
flow_control_pin: 4
baud_rate: 9600 baud_rate: 9600
data_bits: 8 data_bits: 8
rx_buffer_size: 512 rx_buffer_size: 512
rx_full_threshold: 10
rx_timeout: 1
parity: EVEN parity: EVEN
stop_bits: 2 stop_bits: 2

View File

@@ -1,7 +1,11 @@
substitutions: substitutions:
substituted: 99
var1: '1' var1: '1'
var2: '2' var2: '2'
var21: '79' var21: '79'
value: 33
values: 44
esphome: esphome:
name: test name: test
test_list: test_list:
@@ -19,3 +23,6 @@ test_list:
- ${ undefined_var } - ${ undefined_var }
- key1: 1 - key1: 1
key2: 2 key2: 2
- Literal $values ${are not substituted}
- ["list $value", "${is not}", "${substituted}"]
- {"$dictionary": "$value", "${is not}": "${substituted}"}

View File

@@ -2,9 +2,12 @@ esphome:
name: test name: test
substitutions: substitutions:
substituted: 99
var1: "1" var1: "1"
var2: "2" var2: "2"
var21: "79" var21: "79"
value: 33
values: 44
test_list: test_list:
- "$var1" - "$var1"
@@ -21,3 +24,6 @@ test_list:
- ${ undefined_var } - ${ undefined_var }
- key${var1}: 1 - key${var1}: 1
key${var2}: 2 key${var2}: 2
- !literal Literal $values ${are not substituted}
- !literal ["list $value", "${is not}", "${substituted}"]
- !literal {"$dictionary": "$value", "${is not}": "${substituted}"}

View File

@@ -22,3 +22,6 @@ test_list:
- The pin number is 18 - The pin number is 18
- The square root is: 5.0 - The square root is: 5.0
- The number is 80 - The number is 80
- ord("a") = 97
- chr(97) = a
- len([1,2,3]) = 3

View File

@@ -20,3 +20,6 @@ test_list:
- The pin number is ${pin.number} - The pin number is ${pin.number}
- The square root is: ${math.sqrt(area)} - The square root is: ${math.sqrt(area)}
- The number is ${var${numberOne} + 1} - The number is ${var${numberOne} + 1}
- ord("a") = ${ ord("a") }
- chr(97) = ${ chr(97) }
- len([1,2,3]) = ${ len([1,2,3]) }