mirror of
				https://github.com/esphome/esphome.git
				synced 2025-11-04 00:51:49 +00:00 
			
		
		
		
	Compare commits
	
		
			9 Commits
		
	
	
		
			2023.12.0b
			...
			2023.12.0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					cfa5e5c5a9 | ||
| 
						 | 
					8675955614 | ||
| 
						 | 
					816dcdf24f | ||
| 
						 | 
					bec1ad9396 | ||
| 
						 | 
					6a9e85438f | ||
| 
						 | 
					ab25e32509 | ||
| 
						 | 
					2ccf985de5 | ||
| 
						 | 
					a64e96e7ad | ||
| 
						 | 
					fbf3d03a33 | 
@@ -12,7 +12,7 @@ import argcomplete
 | 
			
		||||
 | 
			
		||||
from esphome import const, writer, yaml_util
 | 
			
		||||
import esphome.codegen as cg
 | 
			
		||||
from esphome.config import iter_components, read_config, strip_default_ids
 | 
			
		||||
from esphome.config import iter_component_configs, read_config, strip_default_ids
 | 
			
		||||
from esphome.const import (
 | 
			
		||||
    ALLOWED_NAME_CHARS,
 | 
			
		||||
    CONF_BAUD_RATE,
 | 
			
		||||
@@ -196,7 +196,7 @@ def write_cpp(config):
 | 
			
		||||
def generate_cpp_contents(config):
 | 
			
		||||
    _LOGGER.info("Generating C++ source...")
 | 
			
		||||
 | 
			
		||||
    for name, component, conf in iter_components(CORE.config):
 | 
			
		||||
    for name, component, conf in iter_component_configs(CORE.config):
 | 
			
		||||
        if component.to_code is not None:
 | 
			
		||||
            coro = wrap_to_code(name, component)
 | 
			
		||||
            CORE.add_job(coro, conf)
 | 
			
		||||
 
 | 
			
		||||
@@ -74,7 +74,7 @@ void EKTF2232Touchscreen::update_touches() {
 | 
			
		||||
    uint8_t *d = raw + 1 + (i * 3);
 | 
			
		||||
    x_raw = (d[0] & 0xF0) << 4 | d[1];
 | 
			
		||||
    y_raw = (d[0] & 0x0F) << 8 | d[2];
 | 
			
		||||
    this->set_raw_touch_position_(i, x_raw, y_raw);
 | 
			
		||||
    this->add_raw_touch_position_(i, x_raw, y_raw);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -94,7 +94,7 @@ class FT5x06Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice
 | 
			
		||||
 | 
			
		||||
      esph_log_d(TAG, "Read %X status, id: %d, pos %d/%d", status, id, x, y);
 | 
			
		||||
      if (status == 0 || status == 2) {
 | 
			
		||||
        this->set_raw_touch_position_(id, x, y);
 | 
			
		||||
        this->add_raw_touch_position_(id, x, y);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -53,13 +53,13 @@ void FT63X6Touchscreen::update_touches() {
 | 
			
		||||
  uint8_t touch_id = this->read_touch_id_(FT63X6_ADDR_TOUCH1_ID);  // id1 = 0 or 1
 | 
			
		||||
  int16_t x = this->read_touch_coordinate_(FT63X6_ADDR_TOUCH1_X);
 | 
			
		||||
  int16_t y = this->read_touch_coordinate_(FT63X6_ADDR_TOUCH1_Y);
 | 
			
		||||
  this->set_raw_touch_position_(touch_id, x, y);
 | 
			
		||||
  this->add_raw_touch_position_(touch_id, x, y);
 | 
			
		||||
 | 
			
		||||
  if (touch_count >= 2) {
 | 
			
		||||
    touch_id = this->read_touch_id_(FT63X6_ADDR_TOUCH2_ID);  // id2 = 0 or 1(~id1 & 0x01)
 | 
			
		||||
    x = this->read_touch_coordinate_(FT63X6_ADDR_TOUCH2_X);
 | 
			
		||||
    y = this->read_touch_coordinate_(FT63X6_ADDR_TOUCH2_Y);
 | 
			
		||||
    this->set_raw_touch_position_(touch_id, x, y);
 | 
			
		||||
    this->add_raw_touch_position_(touch_id, x, y);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -92,7 +92,7 @@ void GT911Touchscreen::update_touches() {
 | 
			
		||||
    uint16_t id = data[i][0];
 | 
			
		||||
    uint16_t x = encode_uint16(data[i][2], data[i][1]);
 | 
			
		||||
    uint16_t y = encode_uint16(data[i][4], data[i][3]);
 | 
			
		||||
    this->set_raw_touch_position_(id, x, y);
 | 
			
		||||
    this->add_raw_touch_position_(id, x, y);
 | 
			
		||||
  }
 | 
			
		||||
  auto keys = data[num_of_touches][0];
 | 
			
		||||
  for (size_t i = 0; i != 4; i++) {
 | 
			
		||||
 
 | 
			
		||||
@@ -36,6 +36,7 @@ _LOGGER = logging.getLogger(__name__)
 | 
			
		||||
DOMAIN = "image"
 | 
			
		||||
DEPENDENCIES = ["display"]
 | 
			
		||||
MULTI_CONF = True
 | 
			
		||||
MULTI_CONF_NO_DEFAULT = True
 | 
			
		||||
 | 
			
		||||
image_ns = cg.esphome_ns.namespace("image")
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -84,7 +84,7 @@ void LilygoT547Touchscreen::update_touches() {
 | 
			
		||||
    id = (buffer[i * 5] >> 4) & 0x0F;
 | 
			
		||||
    y_raw = (uint16_t) ((buffer[i * 5 + 1] << 4) | ((buffer[i * 5 + 3] >> 4) & 0x0F));
 | 
			
		||||
    x_raw = (uint16_t) ((buffer[i * 5 + 2] << 4) | (buffer[i * 5 + 3] & 0x0F));
 | 
			
		||||
    this->set_raw_touch_position_(id, x_raw, y_raw);
 | 
			
		||||
    this->add_raw_touch_position_(id, x_raw, y_raw);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  this->status_clear_warning();
 | 
			
		||||
 
 | 
			
		||||
@@ -51,7 +51,7 @@ void Touchscreen::loop() {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Touchscreen::set_raw_touch_position_(uint8_t id, int16_t x_raw, int16_t y_raw, int16_t z_raw) {
 | 
			
		||||
void Touchscreen::add_raw_touch_position_(uint8_t id, int16_t x_raw, int16_t y_raw, int16_t z_raw) {
 | 
			
		||||
  TouchPoint tp;
 | 
			
		||||
  uint16_t x, y;
 | 
			
		||||
  if (this->touches_.count(id) == 0) {
 | 
			
		||||
 
 | 
			
		||||
@@ -87,7 +87,7 @@ class Touchscreen : public PollingComponent {
 | 
			
		||||
 | 
			
		||||
  void attach_interrupt_(InternalGPIOPin *irq_pin, esphome::gpio::InterruptType type);
 | 
			
		||||
 | 
			
		||||
  void set_raw_touch_position_(uint8_t id, int16_t x_raw, int16_t y_raw, int16_t z_raw = 0);
 | 
			
		||||
  void add_raw_touch_position_(uint8_t id, int16_t x_raw, int16_t y_raw, int16_t z_raw = 0);
 | 
			
		||||
 | 
			
		||||
  void send_touches_();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -109,7 +109,7 @@ void TT21100Touchscreen::update_touches() {
 | 
			
		||||
                 i, touch->touch_type, touch->tip, touch->event_id, touch->touch_id, touch->x, touch->y,
 | 
			
		||||
                 touch->pressure, touch->major_axis_length, touch->orientation);
 | 
			
		||||
 | 
			
		||||
        this->set_raw_touch_position_(touch->tip, touch->x, touch->y, touch->pressure);
 | 
			
		||||
        this->add_raw_touch_position_(touch->tip, touch->x, touch->y, touch->pressure);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -55,7 +55,7 @@ void XPT2046Component::update_touches() {
 | 
			
		||||
 | 
			
		||||
    ESP_LOGV(TAG, "Touchscreen Update [%d, %d], z = %d", x_raw, y_raw, z_raw);
 | 
			
		||||
 | 
			
		||||
    this->set_raw_touch_position_(0, x_raw, y_raw, z_raw);
 | 
			
		||||
    this->add_raw_touch_position_(0, x_raw, y_raw, z_raw);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,17 @@ _LOGGER = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def iter_components(config):
 | 
			
		||||
    for domain, conf in config.items():
 | 
			
		||||
        component = get_component(domain)
 | 
			
		||||
        yield domain, component
 | 
			
		||||
        if component.is_platform_component:
 | 
			
		||||
            for p_config in conf:
 | 
			
		||||
                p_name = f"{domain}.{p_config[CONF_PLATFORM]}"
 | 
			
		||||
                platform = get_platform(domain, p_config[CONF_PLATFORM])
 | 
			
		||||
                yield p_name, platform
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def iter_component_configs(config):
 | 
			
		||||
    for domain, conf in config.items():
 | 
			
		||||
        component = get_component(domain)
 | 
			
		||||
        if component.multi_conf:
 | 
			
		||||
@@ -303,8 +314,10 @@ class LoadValidationStep(ConfigValidationStep):
 | 
			
		||||
            # Ignore top-level keys starting with a dot
 | 
			
		||||
            return
 | 
			
		||||
        result.add_output_path([self.domain], self.domain)
 | 
			
		||||
        result[self.domain] = self.conf
 | 
			
		||||
        component = get_component(self.domain)
 | 
			
		||||
        if component.multi_conf_no_default and isinstance(self.conf, core.AutoLoad):
 | 
			
		||||
            self.conf = []
 | 
			
		||||
        result[self.domain] = self.conf
 | 
			
		||||
        path = [self.domain]
 | 
			
		||||
        if component is None:
 | 
			
		||||
            result.add_str_error(f"Component not found: {self.domain}", path)
 | 
			
		||||
@@ -424,7 +437,10 @@ class MetadataValidationStep(ConfigValidationStep):
 | 
			
		||||
 | 
			
		||||
    def run(self, result: Config) -> None:
 | 
			
		||||
        if self.conf is None:
 | 
			
		||||
            result[self.domain] = self.conf = {}
 | 
			
		||||
            if self.comp.multi_conf and self.comp.multi_conf_no_default:
 | 
			
		||||
                result[self.domain] = self.conf = []
 | 
			
		||||
            else:
 | 
			
		||||
                result[self.domain] = self.conf = {}
 | 
			
		||||
 | 
			
		||||
        success = True
 | 
			
		||||
        for dependency in self.comp.dependencies:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
"""Constants used by esphome."""
 | 
			
		||||
 | 
			
		||||
__version__ = "2023.12.0b4"
 | 
			
		||||
__version__ = "2023.12.0"
 | 
			
		||||
 | 
			
		||||
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
 | 
			
		||||
VALID_SUBSTITUTIONS_CHARACTERS = (
 | 
			
		||||
 
 | 
			
		||||
@@ -57,6 +57,10 @@ class ComponentManifest:
 | 
			
		||||
    def multi_conf(self) -> bool:
 | 
			
		||||
        return getattr(self.module, "MULTI_CONF", False)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def multi_conf_no_default(self) -> bool:
 | 
			
		||||
        return getattr(self.module, "MULTI_CONF_NO_DEFAULT", False)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def to_code(self) -> Optional[Callable[[Any], None]]:
 | 
			
		||||
        return getattr(self.module, "to_code", None)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
import operator
 | 
			
		||||
from functools import reduce
 | 
			
		||||
import esphome.config_validation as cv
 | 
			
		||||
from esphome.core import CORE, ID
 | 
			
		||||
from esphome.core import CORE
 | 
			
		||||
 | 
			
		||||
from esphome.const import (
 | 
			
		||||
    CONF_INPUT,
 | 
			
		||||
@@ -25,15 +25,16 @@ class PinRegistry(dict):
 | 
			
		||||
    def reset(self):
 | 
			
		||||
        self.pins_used = {}
 | 
			
		||||
 | 
			
		||||
    def get_count(self, key, number):
 | 
			
		||||
    def get_count(self, key, id, number):
 | 
			
		||||
        """
 | 
			
		||||
        Get the number of places a given pin is used.
 | 
			
		||||
        :param key: The ID of the defining component
 | 
			
		||||
        :param key: The key of the registered pin schema.
 | 
			
		||||
        :param id: The ID of the defining component
 | 
			
		||||
        :param number: The pin number
 | 
			
		||||
        :return: The number of places the pin is used.
 | 
			
		||||
        """
 | 
			
		||||
        pin_key = (key, number)
 | 
			
		||||
        return self.pins_used[pin_key] if pin_key in self.pins_used else 0
 | 
			
		||||
        pin_key = (key, id, number)
 | 
			
		||||
        return len(self.pins_used[pin_key]) if pin_key in self.pins_used else 0
 | 
			
		||||
 | 
			
		||||
    def register(self, name, schema, final_validate=None):
 | 
			
		||||
        """
 | 
			
		||||
@@ -65,9 +66,10 @@ class PinRegistry(dict):
 | 
			
		||||
        result = self[key][1](conf)
 | 
			
		||||
        if CONF_NUMBER in result:
 | 
			
		||||
            # key maps to the pin schema
 | 
			
		||||
            if isinstance(key, ID):
 | 
			
		||||
                key = key.id
 | 
			
		||||
            pin_key = (key, result[CONF_NUMBER])
 | 
			
		||||
            if key != CORE.target_platform:
 | 
			
		||||
                pin_key = (key, conf[key], result[CONF_NUMBER])
 | 
			
		||||
            else:
 | 
			
		||||
                pin_key = (key, key, result[CONF_NUMBER])
 | 
			
		||||
            if pin_key not in self.pins_used:
 | 
			
		||||
                self.pins_used[pin_key] = []
 | 
			
		||||
            # client_id identifies the instance of the providing component
 | 
			
		||||
@@ -101,7 +103,7 @@ class PinRegistry(dict):
 | 
			
		||||
        Run the final validation for all pins, and check for reuse
 | 
			
		||||
        :param fconf: The full config
 | 
			
		||||
        """
 | 
			
		||||
        for (key, _), pin_list in self.pins_used.items():
 | 
			
		||||
        for (key, _, _), pin_list in self.pins_used.items():
 | 
			
		||||
            count = len(pin_list)  # number of places same pin used.
 | 
			
		||||
            final_val_fun = self[key][2]  # final validation function
 | 
			
		||||
            for pin_path, client_id, pin_config in pin_list:
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ import re
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
from typing import Union
 | 
			
		||||
 | 
			
		||||
from esphome.config import iter_components
 | 
			
		||||
from esphome.config import iter_components, iter_component_configs
 | 
			
		||||
from esphome.const import (
 | 
			
		||||
    HEADER_FILE_EXTENSIONS,
 | 
			
		||||
    SOURCE_FILE_EXTENSIONS,
 | 
			
		||||
@@ -70,14 +70,14 @@ UPLOAD_SPEED_OVERRIDE = {
 | 
			
		||||
 | 
			
		||||
def get_flags(key):
 | 
			
		||||
    flags = set()
 | 
			
		||||
    for _, component, conf in iter_components(CORE.config):
 | 
			
		||||
    for _, component, conf in iter_component_configs(CORE.config):
 | 
			
		||||
        flags |= getattr(component, key)(conf)
 | 
			
		||||
    return flags
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_include_text():
 | 
			
		||||
    include_text = '#include "esphome.h"\nusing namespace esphome;\n'
 | 
			
		||||
    for _, component, conf in iter_components(CORE.config):
 | 
			
		||||
    for _, component, conf in iter_component_configs(CORE.config):
 | 
			
		||||
        if not hasattr(component, "includes"):
 | 
			
		||||
            continue
 | 
			
		||||
        includes = component.includes
 | 
			
		||||
@@ -232,7 +232,7 @@ the custom_components folder or the external_components feature.
 | 
			
		||||
 | 
			
		||||
def copy_src_tree():
 | 
			
		||||
    source_files: list[loader.FileResource] = []
 | 
			
		||||
    for _, component, _ in iter_components(CORE.config):
 | 
			
		||||
    for _, component in iter_components(CORE.config):
 | 
			
		||||
        source_files += component.resources
 | 
			
		||||
    source_files_map = {
 | 
			
		||||
        Path(x.package.replace(".", "/") + "/" + x.resource): x for x in source_files
 | 
			
		||||
 
 | 
			
		||||
@@ -1667,7 +1667,6 @@ binary_sensor:
 | 
			
		||||
      mcp23xxx: mcp23s08_hub
 | 
			
		||||
      # Use pin number 1
 | 
			
		||||
      number: 1
 | 
			
		||||
      allow_other_uses: true
 | 
			
		||||
      # One of INPUT or INPUT_PULLUP
 | 
			
		||||
      mode: INPUT_PULLUP
 | 
			
		||||
      inverted: false
 | 
			
		||||
@@ -2149,7 +2148,6 @@ output:
 | 
			
		||||
    pin:
 | 
			
		||||
      mcp23xxx: mcp23017_hub
 | 
			
		||||
      number: 0
 | 
			
		||||
      allow_other_uses: true
 | 
			
		||||
      mode: OUTPUT
 | 
			
		||||
      inverted: false
 | 
			
		||||
  - platform: gpio
 | 
			
		||||
@@ -2157,7 +2155,6 @@ output:
 | 
			
		||||
    pin:
 | 
			
		||||
      mcp23xxx: mcp23008_hub
 | 
			
		||||
      number: 0
 | 
			
		||||
      allow_other_uses: true
 | 
			
		||||
      mode: OUTPUT
 | 
			
		||||
      inverted: false
 | 
			
		||||
  - platform: gpio
 | 
			
		||||
@@ -2597,7 +2594,6 @@ switch:
 | 
			
		||||
      mcp23xxx: mcp23s08_hub
 | 
			
		||||
      # Use pin number 0
 | 
			
		||||
      number: 0
 | 
			
		||||
      allow_other_uses: true
 | 
			
		||||
      mode: OUTPUT
 | 
			
		||||
      inverted: false
 | 
			
		||||
  - platform: gpio
 | 
			
		||||
 
 | 
			
		||||
@@ -401,7 +401,6 @@ switch:
 | 
			
		||||
    pin:
 | 
			
		||||
      mcp23xxx: mcp23017_hub
 | 
			
		||||
      number: 0
 | 
			
		||||
      allow_other_uses: true
 | 
			
		||||
      mode: OUTPUT
 | 
			
		||||
    interlock: &interlock [gpio_switch1, gpio_switch2, gpio_switch3]
 | 
			
		||||
  - platform: gpio
 | 
			
		||||
@@ -409,7 +408,6 @@ switch:
 | 
			
		||||
    pin:
 | 
			
		||||
      mcp23xxx: mcp23008_hub
 | 
			
		||||
      number: 0
 | 
			
		||||
      allow_other_uses: true
 | 
			
		||||
      mode: OUTPUT
 | 
			
		||||
    interlock: *interlock
 | 
			
		||||
  - platform: gpio
 | 
			
		||||
 
 | 
			
		||||
@@ -92,3 +92,13 @@ sensor:
 | 
			
		||||
      name: "Loop Time"
 | 
			
		||||
    psram:
 | 
			
		||||
      name: "PSRAM Free"
 | 
			
		||||
 | 
			
		||||
# Purposely test that `animation:` does auto-load `image:`
 | 
			
		||||
# Keep the `image:` undefined.
 | 
			
		||||
# image:
 | 
			
		||||
 | 
			
		||||
animation:
 | 
			
		||||
  - id: rgb565_animation
 | 
			
		||||
    file: pnglogo.png
 | 
			
		||||
    type: RGB565
 | 
			
		||||
    use_transparency: no
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user