mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	| @@ -12,7 +12,7 @@ import argcomplete | |||||||
|  |  | ||||||
| from esphome import const, writer, yaml_util | from esphome import const, writer, yaml_util | ||||||
| import esphome.codegen as cg | 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 ( | from esphome.const import ( | ||||||
|     ALLOWED_NAME_CHARS, |     ALLOWED_NAME_CHARS, | ||||||
|     CONF_BAUD_RATE, |     CONF_BAUD_RATE, | ||||||
| @@ -196,7 +196,7 @@ def write_cpp(config): | |||||||
| def generate_cpp_contents(config): | def generate_cpp_contents(config): | ||||||
|     _LOGGER.info("Generating C++ source...") |     _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: |         if component.to_code is not None: | ||||||
|             coro = wrap_to_code(name, component) |             coro = wrap_to_code(name, component) | ||||||
|             CORE.add_job(coro, conf) |             CORE.add_job(coro, conf) | ||||||
|   | |||||||
| @@ -36,6 +36,7 @@ _LOGGER = logging.getLogger(__name__) | |||||||
| DOMAIN = "image" | DOMAIN = "image" | ||||||
| DEPENDENCIES = ["display"] | DEPENDENCIES = ["display"] | ||||||
| MULTI_CONF = True | MULTI_CONF = True | ||||||
|  | MULTI_CONF_NO_DEFAULT = True | ||||||
|  |  | ||||||
| image_ns = cg.esphome_ns.namespace("image") | image_ns = cg.esphome_ns.namespace("image") | ||||||
|  |  | ||||||
|   | |||||||
| @@ -39,6 +39,17 @@ _LOGGER = logging.getLogger(__name__) | |||||||
|  |  | ||||||
|  |  | ||||||
| def iter_components(config): | 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(): |     for domain, conf in config.items(): | ||||||
|         component = get_component(domain) |         component = get_component(domain) | ||||||
|         if component.multi_conf: |         if component.multi_conf: | ||||||
| @@ -303,8 +314,10 @@ class LoadValidationStep(ConfigValidationStep): | |||||||
|             # Ignore top-level keys starting with a dot |             # Ignore top-level keys starting with a dot | ||||||
|             return |             return | ||||||
|         result.add_output_path([self.domain], self.domain) |         result.add_output_path([self.domain], self.domain) | ||||||
|         result[self.domain] = self.conf |  | ||||||
|         component = get_component(self.domain) |         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] |         path = [self.domain] | ||||||
|         if component is None: |         if component is None: | ||||||
|             result.add_str_error(f"Component not found: {self.domain}", path) |             result.add_str_error(f"Component not found: {self.domain}", path) | ||||||
| @@ -424,7 +437,10 @@ class MetadataValidationStep(ConfigValidationStep): | |||||||
|  |  | ||||||
|     def run(self, result: Config) -> None: |     def run(self, result: Config) -> None: | ||||||
|         if self.conf is 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 |         success = True | ||||||
|         for dependency in self.comp.dependencies: |         for dependency in self.comp.dependencies: | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| """Constants used by esphome.""" | """Constants used by esphome.""" | ||||||
|  |  | ||||||
| __version__ = "2023.12.0b5" | __version__ = "2023.12.0b6" | ||||||
|  |  | ||||||
| ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" | ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" | ||||||
| VALID_SUBSTITUTIONS_CHARACTERS = ( | VALID_SUBSTITUTIONS_CHARACTERS = ( | ||||||
|   | |||||||
| @@ -57,6 +57,10 @@ class ComponentManifest: | |||||||
|     def multi_conf(self) -> bool: |     def multi_conf(self) -> bool: | ||||||
|         return getattr(self.module, "MULTI_CONF", False) |         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 |     @property | ||||||
|     def to_code(self) -> Optional[Callable[[Any], None]]: |     def to_code(self) -> Optional[Callable[[Any], None]]: | ||||||
|         return getattr(self.module, "to_code", None) |         return getattr(self.module, "to_code", None) | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import operator | import operator | ||||||
| from functools import reduce | from functools import reduce | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.core import CORE, ID | from esphome.core import CORE | ||||||
|  |  | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_INPUT, |     CONF_INPUT, | ||||||
| @@ -25,15 +25,16 @@ class PinRegistry(dict): | |||||||
|     def reset(self): |     def reset(self): | ||||||
|         self.pins_used = {} |         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. |         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 |         :param number: The pin number | ||||||
|         :return: The number of places the pin is used. |         :return: The number of places the pin is used. | ||||||
|         """ |         """ | ||||||
|         pin_key = (key, number) |         pin_key = (key, id, number) | ||||||
|         return self.pins_used[pin_key] if pin_key in self.pins_used else 0 |         return len(self.pins_used[pin_key]) if pin_key in self.pins_used else 0 | ||||||
|  |  | ||||||
|     def register(self, name, schema, final_validate=None): |     def register(self, name, schema, final_validate=None): | ||||||
|         """ |         """ | ||||||
| @@ -65,9 +66,10 @@ class PinRegistry(dict): | |||||||
|         result = self[key][1](conf) |         result = self[key][1](conf) | ||||||
|         if CONF_NUMBER in result: |         if CONF_NUMBER in result: | ||||||
|             # key maps to the pin schema |             # key maps to the pin schema | ||||||
|             if isinstance(key, ID): |             if key != CORE.target_platform: | ||||||
|                 key = key.id |                 pin_key = (key, conf[key], result[CONF_NUMBER]) | ||||||
|             pin_key = (key, result[CONF_NUMBER]) |             else: | ||||||
|  |                 pin_key = (key, key, result[CONF_NUMBER]) | ||||||
|             if pin_key not in self.pins_used: |             if pin_key not in self.pins_used: | ||||||
|                 self.pins_used[pin_key] = [] |                 self.pins_used[pin_key] = [] | ||||||
|             # client_id identifies the instance of the providing component |             # 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 |         Run the final validation for all pins, and check for reuse | ||||||
|         :param fconf: The full config |         :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. |             count = len(pin_list)  # number of places same pin used. | ||||||
|             final_val_fun = self[key][2]  # final validation function |             final_val_fun = self[key][2]  # final validation function | ||||||
|             for pin_path, client_id, pin_config in pin_list: |             for pin_path, client_id, pin_config in pin_list: | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ import re | |||||||
| from pathlib import Path | from pathlib import Path | ||||||
| from typing import Union | from typing import Union | ||||||
|  |  | ||||||
| from esphome.config import iter_components | from esphome.config import iter_components, iter_component_configs | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     HEADER_FILE_EXTENSIONS, |     HEADER_FILE_EXTENSIONS, | ||||||
|     SOURCE_FILE_EXTENSIONS, |     SOURCE_FILE_EXTENSIONS, | ||||||
| @@ -70,14 +70,14 @@ UPLOAD_SPEED_OVERRIDE = { | |||||||
|  |  | ||||||
| def get_flags(key): | def get_flags(key): | ||||||
|     flags = set() |     flags = set() | ||||||
|     for _, component, conf in iter_components(CORE.config): |     for _, component, conf in iter_component_configs(CORE.config): | ||||||
|         flags |= getattr(component, key)(conf) |         flags |= getattr(component, key)(conf) | ||||||
|     return flags |     return flags | ||||||
|  |  | ||||||
|  |  | ||||||
| def get_include_text(): | def get_include_text(): | ||||||
|     include_text = '#include "esphome.h"\nusing namespace esphome;\n' |     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"): |         if not hasattr(component, "includes"): | ||||||
|             continue |             continue | ||||||
|         includes = component.includes |         includes = component.includes | ||||||
| @@ -232,7 +232,7 @@ the custom_components folder or the external_components feature. | |||||||
|  |  | ||||||
| def copy_src_tree(): | def copy_src_tree(): | ||||||
|     source_files: list[loader.FileResource] = [] |     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 += component.resources | ||||||
|     source_files_map = { |     source_files_map = { | ||||||
|         Path(x.package.replace(".", "/") + "/" + x.resource): x for x in source_files |         Path(x.package.replace(".", "/") + "/" + x.resource): x for x in source_files | ||||||
|   | |||||||
| @@ -1667,7 +1667,6 @@ binary_sensor: | |||||||
|       mcp23xxx: mcp23s08_hub |       mcp23xxx: mcp23s08_hub | ||||||
|       # Use pin number 1 |       # Use pin number 1 | ||||||
|       number: 1 |       number: 1 | ||||||
|       allow_other_uses: true |  | ||||||
|       # One of INPUT or INPUT_PULLUP |       # One of INPUT or INPUT_PULLUP | ||||||
|       mode: INPUT_PULLUP |       mode: INPUT_PULLUP | ||||||
|       inverted: false |       inverted: false | ||||||
| @@ -2149,7 +2148,6 @@ output: | |||||||
|     pin: |     pin: | ||||||
|       mcp23xxx: mcp23017_hub |       mcp23xxx: mcp23017_hub | ||||||
|       number: 0 |       number: 0 | ||||||
|       allow_other_uses: true |  | ||||||
|       mode: OUTPUT |       mode: OUTPUT | ||||||
|       inverted: false |       inverted: false | ||||||
|   - platform: gpio |   - platform: gpio | ||||||
| @@ -2157,7 +2155,6 @@ output: | |||||||
|     pin: |     pin: | ||||||
|       mcp23xxx: mcp23008_hub |       mcp23xxx: mcp23008_hub | ||||||
|       number: 0 |       number: 0 | ||||||
|       allow_other_uses: true |  | ||||||
|       mode: OUTPUT |       mode: OUTPUT | ||||||
|       inverted: false |       inverted: false | ||||||
|   - platform: gpio |   - platform: gpio | ||||||
| @@ -2597,7 +2594,6 @@ switch: | |||||||
|       mcp23xxx: mcp23s08_hub |       mcp23xxx: mcp23s08_hub | ||||||
|       # Use pin number 0 |       # Use pin number 0 | ||||||
|       number: 0 |       number: 0 | ||||||
|       allow_other_uses: true |  | ||||||
|       mode: OUTPUT |       mode: OUTPUT | ||||||
|       inverted: false |       inverted: false | ||||||
|   - platform: gpio |   - platform: gpio | ||||||
|   | |||||||
| @@ -401,7 +401,6 @@ switch: | |||||||
|     pin: |     pin: | ||||||
|       mcp23xxx: mcp23017_hub |       mcp23xxx: mcp23017_hub | ||||||
|       number: 0 |       number: 0 | ||||||
|       allow_other_uses: true |  | ||||||
|       mode: OUTPUT |       mode: OUTPUT | ||||||
|     interlock: &interlock [gpio_switch1, gpio_switch2, gpio_switch3] |     interlock: &interlock [gpio_switch1, gpio_switch2, gpio_switch3] | ||||||
|   - platform: gpio |   - platform: gpio | ||||||
| @@ -409,7 +408,6 @@ switch: | |||||||
|     pin: |     pin: | ||||||
|       mcp23xxx: mcp23008_hub |       mcp23xxx: mcp23008_hub | ||||||
|       number: 0 |       number: 0 | ||||||
|       allow_other_uses: true |  | ||||||
|       mode: OUTPUT |       mode: OUTPUT | ||||||
|     interlock: *interlock |     interlock: *interlock | ||||||
|   - platform: gpio |   - platform: gpio | ||||||
|   | |||||||
| @@ -92,3 +92,13 @@ sensor: | |||||||
|       name: "Loop Time" |       name: "Loop Time" | ||||||
|     psram: |     psram: | ||||||
|       name: "PSRAM Free" |       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