mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	Merge branch 'esphome:dev' into gsm
This commit is contained in:
		
							
								
								
									
										2
									
								
								.github/workflows/ci-docker.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/ci-docker.yml
									
									
									
									
										vendored
									
									
								
							| @@ -46,7 +46,7 @@ jobs: | |||||||
|         with: |         with: | ||||||
|           python-version: "3.9" |           python-version: "3.9" | ||||||
|       - name: Set up Docker Buildx |       - name: Set up Docker Buildx | ||||||
|         uses: docker/setup-buildx-action@v3.5.0 |         uses: docker/setup-buildx-action@v3.6.1 | ||||||
|       - name: Set up QEMU |       - name: Set up QEMU | ||||||
|         uses: docker/setup-qemu-action@v3.2.0 |         uses: docker/setup-qemu-action@v3.2.0 | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							| @@ -90,7 +90,7 @@ jobs: | |||||||
|           python-version: "3.9" |           python-version: "3.9" | ||||||
|  |  | ||||||
|       - name: Set up Docker Buildx |       - name: Set up Docker Buildx | ||||||
|         uses: docker/setup-buildx-action@v3.5.0 |         uses: docker/setup-buildx-action@v3.6.1 | ||||||
|       - name: Set up QEMU |       - name: Set up QEMU | ||||||
|         if: matrix.platform != 'linux/amd64' |         if: matrix.platform != 'linux/amd64' | ||||||
|         uses: docker/setup-qemu-action@v3.2.0 |         uses: docker/setup-qemu-action@v3.2.0 | ||||||
| @@ -184,7 +184,7 @@ jobs: | |||||||
|           merge-multiple: true |           merge-multiple: true | ||||||
|  |  | ||||||
|       - name: Set up Docker Buildx |       - name: Set up Docker Buildx | ||||||
|         uses: docker/setup-buildx-action@v3.5.0 |         uses: docker/setup-buildx-action@v3.6.1 | ||||||
|  |  | ||||||
|       - name: Log in to docker hub |       - name: Log in to docker hub | ||||||
|         if: matrix.registry == 'dockerhub' |         if: matrix.registry == 'dockerhub' | ||||||
|   | |||||||
| @@ -428,6 +428,7 @@ esphome/components/veml7700/* @latonita | |||||||
| esphome/components/version/* @esphome/core | esphome/components/version/* @esphome/core | ||||||
| esphome/components/voice_assistant/* @jesserockz | esphome/components/voice_assistant/* @jesserockz | ||||||
| esphome/components/wake_on_lan/* @clydebarrow @willwill2will54 | esphome/components/wake_on_lan/* @clydebarrow @willwill2will54 | ||||||
|  | esphome/components/watchdog/* @oarcher | ||||||
| esphome/components/waveshare_epaper/* @clydebarrow | esphome/components/waveshare_epaper/* @clydebarrow | ||||||
| esphome/components/web_server_base/* @OttoWinter | esphome/components/web_server_base/* @OttoWinter | ||||||
| esphome/components/web_server_idf/* @dentra | esphome/components/web_server_idf/* @dentra | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| # PYTHON_ARGCOMPLETE_OK | # PYTHON_ARGCOMPLETE_OK | ||||||
| import argparse | import argparse | ||||||
|  | from datetime import datetime | ||||||
| import functools | import functools | ||||||
| import logging | import logging | ||||||
| import os | import os | ||||||
| import re | import re | ||||||
| import sys | import sys | ||||||
| import time | import time | ||||||
| from datetime import datetime |  | ||||||
|  |  | ||||||
| import argcomplete | import argcomplete | ||||||
|  |  | ||||||
| @@ -39,14 +39,14 @@ from esphome.const import ( | |||||||
| ) | ) | ||||||
| from esphome.core import CORE, EsphomeError, coroutine | from esphome.core import CORE, EsphomeError, coroutine | ||||||
| from esphome.helpers import indent, is_ip_address | from esphome.helpers import indent, is_ip_address | ||||||
|  | from esphome.log import Fore, color, setup_log | ||||||
| from esphome.util import ( | from esphome.util import ( | ||||||
|  |     get_serial_ports, | ||||||
|  |     list_yaml_files, | ||||||
|     run_external_command, |     run_external_command, | ||||||
|     run_external_process, |     run_external_process, | ||||||
|     safe_print, |     safe_print, | ||||||
|     list_yaml_files, |  | ||||||
|     get_serial_ports, |  | ||||||
| ) | ) | ||||||
| from esphome.log import color, setup_log, Fore |  | ||||||
|  |  | ||||||
| _LOGGER = logging.getLogger(__name__) | _LOGGER = logging.getLogger(__name__) | ||||||
|  |  | ||||||
| @@ -116,6 +116,7 @@ def get_port_type(port): | |||||||
|  |  | ||||||
| def run_miniterm(config, port): | def run_miniterm(config, port): | ||||||
|     import serial |     import serial | ||||||
|  |  | ||||||
|     from esphome import platformio_api |     from esphome import platformio_api | ||||||
|  |  | ||||||
|     if CONF_LOGGER not in config: |     if CONF_LOGGER not in config: | ||||||
| @@ -596,9 +597,10 @@ def command_update_all(args): | |||||||
|  |  | ||||||
|  |  | ||||||
| def command_idedata(args, config): | def command_idedata(args, config): | ||||||
|     from esphome import platformio_api |  | ||||||
|     import json |     import json | ||||||
|  |  | ||||||
|  |     from esphome import platformio_api | ||||||
|  |  | ||||||
|     logging.disable(logging.INFO) |     logging.disable(logging.INFO) | ||||||
|     logging.disable(logging.WARNING) |     logging.disable(logging.WARNING) | ||||||
|  |  | ||||||
| @@ -747,7 +749,14 @@ def parse_args(argv): | |||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     parser = argparse.ArgumentParser( |     parser = argparse.ArgumentParser( | ||||||
|         description=f"ESPHome v{const.__version__}", parents=[options_parser] |         description=f"ESPHome {const.__version__}", parents=[options_parser] | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |     parser.add_argument( | ||||||
|  |         "--version", | ||||||
|  |         action="version", | ||||||
|  |         version=f"Version: {const.__version__}", | ||||||
|  |         help="Print the ESPHome version and exit.", | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     mqtt_options = argparse.ArgumentParser(add_help=False) |     mqtt_options = argparse.ArgumentParser(add_help=False) | ||||||
| @@ -948,67 +957,6 @@ def parse_args(argv): | |||||||
|     # a deprecation warning). |     # a deprecation warning). | ||||||
|     arguments = argv[1:] |     arguments = argv[1:] | ||||||
|  |  | ||||||
|     # On Python 3.9+ we can simply set exit_on_error=False in the constructor |  | ||||||
|     def _raise(x): |  | ||||||
|         raise argparse.ArgumentError(None, x) |  | ||||||
|  |  | ||||||
|     # First, try new-style parsing, but don't exit in case of failure |  | ||||||
|     try: |  | ||||||
|         # duplicate parser so that we can use the original one to raise errors later on |  | ||||||
|         current_parser = argparse.ArgumentParser(add_help=False, parents=[parser]) |  | ||||||
|         current_parser.set_defaults(deprecated_argv_suggestion=None) |  | ||||||
|         current_parser.error = _raise |  | ||||||
|         return current_parser.parse_args(arguments) |  | ||||||
|     except argparse.ArgumentError: |  | ||||||
|         pass |  | ||||||
|  |  | ||||||
|     # Second, try compat parsing and rearrange the command-line if it succeeds |  | ||||||
|     # Disable argparse's built-in help option and add it manually to prevent this |  | ||||||
|     # parser from printing the help messagefor the old format when invoked with -h. |  | ||||||
|     compat_parser = argparse.ArgumentParser(parents=[options_parser], add_help=False) |  | ||||||
|     compat_parser.add_argument("-h", "--help", action="store_true") |  | ||||||
|     compat_parser.add_argument("configuration", nargs="*") |  | ||||||
|     compat_parser.add_argument( |  | ||||||
|         "command", |  | ||||||
|         choices=[ |  | ||||||
|             "config", |  | ||||||
|             "compile", |  | ||||||
|             "upload", |  | ||||||
|             "logs", |  | ||||||
|             "run", |  | ||||||
|             "clean-mqtt", |  | ||||||
|             "wizard", |  | ||||||
|             "mqtt-fingerprint", |  | ||||||
|             "version", |  | ||||||
|             "clean", |  | ||||||
|             "dashboard", |  | ||||||
|             "vscode", |  | ||||||
|             "update-all", |  | ||||||
|         ], |  | ||||||
|     ) |  | ||||||
|  |  | ||||||
|     try: |  | ||||||
|         compat_parser.error = _raise |  | ||||||
|         result, unparsed = compat_parser.parse_known_args(argv[1:]) |  | ||||||
|         last_option = len(arguments) - len(unparsed) - 1 - len(result.configuration) |  | ||||||
|         unparsed = [ |  | ||||||
|             "--device" if arg in ("--upload-port", "--serial-port") else arg |  | ||||||
|             for arg in unparsed |  | ||||||
|         ] |  | ||||||
|         arguments = ( |  | ||||||
|             arguments[0:last_option] |  | ||||||
|             + [result.command] |  | ||||||
|             + result.configuration |  | ||||||
|             + unparsed |  | ||||||
|         ) |  | ||||||
|         deprecated_argv_suggestion = arguments |  | ||||||
|     except argparse.ArgumentError: |  | ||||||
|         # old-style parsing failed, don't suggest any argument |  | ||||||
|         deprecated_argv_suggestion = None |  | ||||||
|  |  | ||||||
|     # Finally, run the new-style parser again with the possibly swapped arguments, |  | ||||||
|     # and let it error out if the command is unparsable. |  | ||||||
|     parser.set_defaults(deprecated_argv_suggestion=deprecated_argv_suggestion) |  | ||||||
|     argcomplete.autocomplete(parser) |     argcomplete.autocomplete(parser) | ||||||
|     return parser.parse_args(arguments) |     return parser.parse_args(arguments) | ||||||
|  |  | ||||||
| @@ -1023,13 +971,6 @@ def run_esphome(argv): | |||||||
|         # Show timestamp for dashboard access logs |         # Show timestamp for dashboard access logs | ||||||
|         args.command == "dashboard", |         args.command == "dashboard", | ||||||
|     ) |     ) | ||||||
|     if args.deprecated_argv_suggestion is not None and args.command != "vscode": |  | ||||||
|         _LOGGER.warning( |  | ||||||
|             "Calling ESPHome with the configuration before the command is deprecated " |  | ||||||
|             "and will be removed in the future. " |  | ||||||
|         ) |  | ||||||
|         _LOGGER.warning("Please instead use:") |  | ||||||
|         _LOGGER.warning("   esphome %s", " ".join(args.deprecated_argv_suggestion)) |  | ||||||
|  |  | ||||||
|     if sys.version_info < (3, 8, 0): |     if sys.version_info < (3, 8, 0): | ||||||
|         _LOGGER.error( |         _LOGGER.error( | ||||||
|   | |||||||
| @@ -7,10 +7,10 @@ from esphome.const import ( | |||||||
|     CONF_ELSE, |     CONF_ELSE, | ||||||
|     CONF_ID, |     CONF_ID, | ||||||
|     CONF_THEN, |     CONF_THEN, | ||||||
|  |     CONF_TIME, | ||||||
|     CONF_TIMEOUT, |     CONF_TIMEOUT, | ||||||
|     CONF_TRIGGER_ID, |     CONF_TRIGGER_ID, | ||||||
|     CONF_TYPE_ID, |     CONF_TYPE_ID, | ||||||
|     CONF_TIME, |  | ||||||
|     CONF_UPDATE_INTERVAL, |     CONF_UPDATE_INTERVAL, | ||||||
| ) | ) | ||||||
| from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor | from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor | ||||||
|   | |||||||
| @@ -8,55 +8,78 @@ | |||||||
| # want to break suddenly due to a rename (this file will get backports for features). | # want to break suddenly due to a rename (this file will get backports for features). | ||||||
|  |  | ||||||
| # pylint: disable=unused-import | # pylint: disable=unused-import | ||||||
| from esphome.cpp_generator import (  # noqa | from esphome.cpp_generator import (  # noqa: F401 | ||||||
|  |     ArrayInitializer, | ||||||
|     Expression, |     Expression, | ||||||
|  |     LineComment, | ||||||
|  |     MockObj, | ||||||
|  |     MockObjClass, | ||||||
|  |     Pvariable, | ||||||
|     RawExpression, |     RawExpression, | ||||||
|     RawStatement, |     RawStatement, | ||||||
|     TemplateArguments, |  | ||||||
|     StructInitializer, |  | ||||||
|     ArrayInitializer, |  | ||||||
|     safe_exp, |  | ||||||
|     Statement, |     Statement, | ||||||
|     LineComment, |     StructInitializer, | ||||||
|     progmem_array, |     TemplateArguments, | ||||||
|     static_const_array, |  | ||||||
|     statement, |  | ||||||
|     variable, |  | ||||||
|     with_local_variable, |  | ||||||
|     new_variable, |  | ||||||
|     Pvariable, |  | ||||||
|     new_Pvariable, |  | ||||||
|     add, |     add, | ||||||
|     add_global, |  | ||||||
|     add_library, |  | ||||||
|     add_build_flag, |     add_build_flag, | ||||||
|     add_define, |     add_define, | ||||||
|  |     add_global, | ||||||
|  |     add_library, | ||||||
|     add_platformio_option, |     add_platformio_option, | ||||||
|     get_variable, |     get_variable, | ||||||
|     get_variable_with_full_id, |     get_variable_with_full_id, | ||||||
|     process_lambda, |  | ||||||
|     is_template, |     is_template, | ||||||
|  |     new_Pvariable, | ||||||
|  |     new_variable, | ||||||
|  |     process_lambda, | ||||||
|  |     progmem_array, | ||||||
|  |     safe_exp, | ||||||
|  |     statement, | ||||||
|  |     static_const_array, | ||||||
|     templatable, |     templatable, | ||||||
|     MockObj, |     variable, | ||||||
|     MockObjClass, |     with_local_variable, | ||||||
| ) | ) | ||||||
| from esphome.cpp_helpers import (  # noqa | from esphome.cpp_helpers import (  # noqa: F401 | ||||||
|     gpio_pin_expression, |  | ||||||
|     register_component, |  | ||||||
|     build_registry_entry, |     build_registry_entry, | ||||||
|     build_registry_list, |     build_registry_list, | ||||||
|     extract_registry_entry_config, |     extract_registry_entry_config, | ||||||
|     register_parented, |     gpio_pin_expression, | ||||||
|     past_safe_mode, |     past_safe_mode, | ||||||
|  |     register_component, | ||||||
|  |     register_parented, | ||||||
| ) | ) | ||||||
| from esphome.cpp_types import (  # noqa | from esphome.cpp_types import (  # noqa: F401 | ||||||
|     global_ns, |     NAN, | ||||||
|     void, |     App, | ||||||
|     nullptr, |     Application, | ||||||
|     float_, |     Component, | ||||||
|     double, |     ComponentPtr, | ||||||
|  |     Controller, | ||||||
|  |     EntityBase, | ||||||
|  |     EntityCategory, | ||||||
|  |     ESPTime, | ||||||
|  |     GPIOPin, | ||||||
|  |     InternalGPIOPin, | ||||||
|  |     JsonObject, | ||||||
|  |     JsonObjectConst, | ||||||
|  |     Parented, | ||||||
|  |     PollingComponent, | ||||||
|  |     arduino_json_ns, | ||||||
|     bool_, |     bool_, | ||||||
|  |     const_char_ptr, | ||||||
|  |     double, | ||||||
|  |     esphome_ns, | ||||||
|  |     float_, | ||||||
|  |     global_ns, | ||||||
|  |     gpio_Flags, | ||||||
|  |     int16, | ||||||
|  |     int32, | ||||||
|  |     int64, | ||||||
|     int_, |     int_, | ||||||
|  |     nullptr, | ||||||
|  |     optional, | ||||||
|  |     size_t, | ||||||
|     std_ns, |     std_ns, | ||||||
|     std_shared_ptr, |     std_shared_ptr, | ||||||
|     std_string, |     std_string, | ||||||
| @@ -66,28 +89,5 @@ from esphome.cpp_types import (  # noqa | |||||||
|     uint16, |     uint16, | ||||||
|     uint32, |     uint32, | ||||||
|     uint64, |     uint64, | ||||||
|     int16, |     void, | ||||||
|     int32, |  | ||||||
|     int64, |  | ||||||
|     size_t, |  | ||||||
|     const_char_ptr, |  | ||||||
|     NAN, |  | ||||||
|     esphome_ns, |  | ||||||
|     App, |  | ||||||
|     EntityBase, |  | ||||||
|     Component, |  | ||||||
|     ComponentPtr, |  | ||||||
|     PollingComponent, |  | ||||||
|     Application, |  | ||||||
|     optional, |  | ||||||
|     arduino_json_ns, |  | ||||||
|     JsonObject, |  | ||||||
|     JsonObjectConst, |  | ||||||
|     Controller, |  | ||||||
|     GPIOPin, |  | ||||||
|     InternalGPIOPin, |  | ||||||
|     gpio_Flags, |  | ||||||
|     EntityCategory, |  | ||||||
|     Parented, |  | ||||||
|     ESPTime, |  | ||||||
| ) | ) | ||||||
|   | |||||||
| @@ -1,7 +1,8 @@ | |||||||
| import esphome.codegen as cg | from esphome import automation | ||||||
| import esphome.config_validation as cv |  | ||||||
| from esphome.automation import maybe_simple_id | from esphome.automation import maybe_simple_id | ||||||
| from esphome.components import esp32_ble_tracker, esp32_ble_client | import esphome.codegen as cg | ||||||
|  | from esphome.components import esp32_ble_client, esp32_ble_tracker | ||||||
|  | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_CHARACTERISTIC_UUID, |     CONF_CHARACTERISTIC_UUID, | ||||||
|     CONF_ID, |     CONF_ID, | ||||||
| @@ -13,7 +14,6 @@ from esphome.const import ( | |||||||
|     CONF_TRIGGER_ID, |     CONF_TRIGGER_ID, | ||||||
|     CONF_VALUE, |     CONF_VALUE, | ||||||
| ) | ) | ||||||
| from esphome import automation |  | ||||||
|  |  | ||||||
| AUTO_LOAD = ["esp32_ble_client"] | AUTO_LOAD = ["esp32_ble_client"] | ||||||
| CODEOWNERS = ["@buxtronix", "@clydebarrow"] | CODEOWNERS = ["@buxtronix", "@clydebarrow"] | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| import esphome.config_validation as cv |  | ||||||
| from esphome.components import ble_client, esp32_ble_tracker, output | from esphome.components import ble_client, esp32_ble_tracker, output | ||||||
|  | import esphome.config_validation as cv | ||||||
| from esphome.const import CONF_CHARACTERISTIC_UUID, CONF_ID, CONF_SERVICE_UUID | from esphome.const import CONF_CHARACTERISTIC_UUID, CONF_ID, CONF_SERVICE_UUID | ||||||
|  |  | ||||||
| from .. import ble_client_ns | from .. import ble_client_ns | ||||||
|   | |||||||
| @@ -1,17 +1,18 @@ | |||||||
|  | from esphome import automation | ||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
|  | from esphome.components import ble_client, esp32_ble_tracker, sensor | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.components import sensor, ble_client, esp32_ble_tracker |  | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_CHARACTERISTIC_UUID, |     CONF_CHARACTERISTIC_UUID, | ||||||
|     CONF_LAMBDA, |     CONF_LAMBDA, | ||||||
|  |     CONF_SERVICE_UUID, | ||||||
|     CONF_TRIGGER_ID, |     CONF_TRIGGER_ID, | ||||||
|     CONF_TYPE, |     CONF_TYPE, | ||||||
|     CONF_SERVICE_UUID, |  | ||||||
|     DEVICE_CLASS_SIGNAL_STRENGTH, |     DEVICE_CLASS_SIGNAL_STRENGTH, | ||||||
|     STATE_CLASS_MEASUREMENT, |     STATE_CLASS_MEASUREMENT, | ||||||
|     UNIT_DECIBEL_MILLIWATT, |     UNIT_DECIBEL_MILLIWATT, | ||||||
| ) | ) | ||||||
| from esphome import automation |  | ||||||
| from .. import ble_client_ns | from .. import ble_client_ns | ||||||
|  |  | ||||||
| DEPENDENCIES = ["ble_client"] | DEPENDENCIES = ["ble_client"] | ||||||
|   | |||||||
| @@ -1,7 +1,8 @@ | |||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
|  | from esphome.components import ble_client, switch | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.components import switch, ble_client |  | ||||||
| from esphome.const import ICON_BLUETOOTH | from esphome.const import ICON_BLUETOOTH | ||||||
|  |  | ||||||
| from .. import ble_client_ns | from .. import ble_client_ns | ||||||
|  |  | ||||||
| BLEClientSwitch = ble_client_ns.class_( | BLEClientSwitch = ble_client_ns.class_( | ||||||
|   | |||||||
| @@ -1,13 +1,14 @@ | |||||||
|  | from esphome import automation | ||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
|  | from esphome.components import ble_client, esp32_ble_tracker, text_sensor | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.components import text_sensor, ble_client, esp32_ble_tracker |  | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_CHARACTERISTIC_UUID, |     CONF_CHARACTERISTIC_UUID, | ||||||
|     CONF_ID, |     CONF_ID, | ||||||
|     CONF_TRIGGER_ID, |  | ||||||
|     CONF_SERVICE_UUID, |     CONF_SERVICE_UUID, | ||||||
|  |     CONF_TRIGGER_ID, | ||||||
| ) | ) | ||||||
| from esphome import automation |  | ||||||
| from .. import ble_client_ns | from .. import ble_client_ns | ||||||
|  |  | ||||||
| DEPENDENCIES = ["ble_client"] | DEPENDENCIES = ["ble_client"] | ||||||
|   | |||||||
| @@ -1,13 +1,13 @@ | |||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| import esphome.config_validation as cv |  | ||||||
| from esphome.components import binary_sensor, esp32_ble_tracker | from esphome.components import binary_sensor, esp32_ble_tracker | ||||||
|  | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_MAC_ADDRESS, |  | ||||||
|     CONF_SERVICE_UUID, |  | ||||||
|     CONF_IBEACON_MAJOR, |     CONF_IBEACON_MAJOR, | ||||||
|     CONF_IBEACON_MINOR, |     CONF_IBEACON_MINOR, | ||||||
|     CONF_IBEACON_UUID, |     CONF_IBEACON_UUID, | ||||||
|  |     CONF_MAC_ADDRESS, | ||||||
|     CONF_MIN_RSSI, |     CONF_MIN_RSSI, | ||||||
|  |     CONF_SERVICE_UUID, | ||||||
|     CONF_TIMEOUT, |     CONF_TIMEOUT, | ||||||
| ) | ) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
|  | from esphome.components import esp32_ble_tracker, sensor | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.components import sensor, esp32_ble_tracker |  | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_IBEACON_MAJOR, |     CONF_IBEACON_MAJOR, | ||||||
|     CONF_IBEACON_MINOR, |     CONF_IBEACON_MINOR, | ||||||
|     CONF_IBEACON_UUID, |     CONF_IBEACON_UUID, | ||||||
|     CONF_SERVICE_UUID, |  | ||||||
|     CONF_MAC_ADDRESS, |     CONF_MAC_ADDRESS, | ||||||
|  |     CONF_SERVICE_UUID, | ||||||
|     DEVICE_CLASS_SIGNAL_STRENGTH, |     DEVICE_CLASS_SIGNAL_STRENGTH, | ||||||
|     STATE_CLASS_MEASUREMENT, |     STATE_CLASS_MEASUREMENT, | ||||||
|     UNIT_DECIBEL_MILLIWATT, |     UNIT_DECIBEL_MILLIWATT, | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
|  | from esphome.components import esp32_ble_tracker, text_sensor | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.components import text_sensor, esp32_ble_tracker |  | ||||||
|  |  | ||||||
| DEPENDENCIES = ["esp32_ble_tracker"] | DEPENDENCIES = ["esp32_ble_tracker"] | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| from esphome.components import esp32_ble_tracker, esp32_ble_client |  | ||||||
| import esphome.config_validation as cv |  | ||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| from esphome.const import CONF_ACTIVE, CONF_ID | from esphome.components import esp32_ble_client, esp32_ble_tracker | ||||||
| from esphome.components.esp32 import add_idf_sdkconfig_option | from esphome.components.esp32 import add_idf_sdkconfig_option | ||||||
|  | import esphome.config_validation as cv | ||||||
|  | from esphome.const import CONF_ACTIVE, CONF_ID | ||||||
|  |  | ||||||
| AUTO_LOAD = ["esp32_ble_client", "esp32_ble_tracker"] | AUTO_LOAD = ["esp32_ble_client", "esp32_ble_tracker"] | ||||||
| DEPENDENCIES = ["api", "esp32"] | DEPENDENCIES = ["api", "esp32"] | ||||||
|   | |||||||
| @@ -1,11 +1,12 @@ | |||||||
| from dataclasses import dataclass | from dataclasses import dataclass | ||||||
| from typing import Union, Optional |  | ||||||
| from pathlib import Path |  | ||||||
| import logging | import logging | ||||||
| import os | import os | ||||||
| import esphome.final_validate as fv | from pathlib import Path | ||||||
|  | from typing import Optional, Union | ||||||
|  |  | ||||||
| from esphome.helpers import copy_file_if_changed, write_file_if_changed, mkdir_p | from esphome import git | ||||||
|  | import esphome.codegen as cg | ||||||
|  | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_ADVANCED, |     CONF_ADVANCED, | ||||||
|     CONF_BOARD, |     CONF_BOARD, | ||||||
| @@ -15,6 +16,7 @@ from esphome.const import ( | |||||||
|     CONF_IGNORE_EFUSE_MAC_CRC, |     CONF_IGNORE_EFUSE_MAC_CRC, | ||||||
|     CONF_NAME, |     CONF_NAME, | ||||||
|     CONF_PATH, |     CONF_PATH, | ||||||
|  |     CONF_PLATFORM_VERSION, | ||||||
|     CONF_PLATFORMIO_OPTIONS, |     CONF_PLATFORMIO_OPTIONS, | ||||||
|     CONF_REF, |     CONF_REF, | ||||||
|     CONF_REFRESH, |     CONF_REFRESH, | ||||||
| @@ -32,13 +34,12 @@ from esphome.const import ( | |||||||
|     TYPE_GIT, |     TYPE_GIT, | ||||||
|     TYPE_LOCAL, |     TYPE_LOCAL, | ||||||
|     __version__, |     __version__, | ||||||
|     CONF_PLATFORM_VERSION, |  | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, HexInt, TimePeriod | from esphome.core import CORE, HexInt, TimePeriod | ||||||
| import esphome.config_validation as cv | import esphome.final_validate as fv | ||||||
| import esphome.codegen as cg | from esphome.helpers import copy_file_if_changed, mkdir_p, write_file_if_changed | ||||||
| from esphome import git |  | ||||||
|  |  | ||||||
|  | from .boards import BOARDS | ||||||
| from .const import (  # noqa | from .const import (  # noqa | ||||||
|     KEY_BOARD, |     KEY_BOARD, | ||||||
|     KEY_COMPONENTS, |     KEY_COMPONENTS, | ||||||
| @@ -54,12 +55,10 @@ from .const import (  # noqa | |||||||
|     VARIANT_FRIENDLY, |     VARIANT_FRIENDLY, | ||||||
|     VARIANTS, |     VARIANTS, | ||||||
| ) | ) | ||||||
| from .boards import BOARDS |  | ||||||
|  |  | ||||||
| # force import gpio to register pin schema | # force import gpio to register pin schema | ||||||
| from .gpio import esp32_pin_to_code  # noqa | from .gpio import esp32_pin_to_code  # noqa | ||||||
|  |  | ||||||
|  |  | ||||||
| _LOGGER = logging.getLogger(__name__) | _LOGGER = logging.getLogger(__name__) | ||||||
| CODEOWNERS = ["@esphome/core"] | CODEOWNERS = ["@esphome/core"] | ||||||
| AUTO_LOAD = ["preferences"] | AUTO_LOAD = ["preferences"] | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| from .const import VARIANT_ESP32, VARIANT_ESP32S2, VARIANT_ESP32C3, VARIANT_ESP32S3 | from .const import VARIANT_ESP32, VARIANT_ESP32C3, VARIANT_ESP32S2, VARIANT_ESP32S3 | ||||||
|  |  | ||||||
| ESP32_BASE_PINS = { | ESP32_BASE_PINS = { | ||||||
|     "TX": 1, |     "TX": 1, | ||||||
|   | |||||||
| @@ -1,22 +1,22 @@ | |||||||
| from dataclasses import dataclass | from dataclasses import dataclass | ||||||
| from typing import Any |  | ||||||
| import logging | import logging | ||||||
|  | from typing import Any | ||||||
|  |  | ||||||
|  | from esphome import pins | ||||||
|  | import esphome.codegen as cg | ||||||
|  | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_ID, |     CONF_ID, | ||||||
|  |     CONF_IGNORE_PIN_VALIDATION_ERROR, | ||||||
|  |     CONF_IGNORE_STRAPPING_WARNING, | ||||||
|     CONF_INVERTED, |     CONF_INVERTED, | ||||||
|     CONF_MODE, |     CONF_MODE, | ||||||
|     CONF_NUMBER, |     CONF_NUMBER, | ||||||
|     CONF_OPEN_DRAIN, |     CONF_OPEN_DRAIN, | ||||||
|     CONF_OUTPUT, |     CONF_OUTPUT, | ||||||
|     CONF_IGNORE_PIN_VALIDATION_ERROR, |  | ||||||
|     CONF_IGNORE_STRAPPING_WARNING, |  | ||||||
|     PLATFORM_ESP32, |     PLATFORM_ESP32, | ||||||
| ) | ) | ||||||
| from esphome import pins |  | ||||||
| from esphome.core import CORE | from esphome.core import CORE | ||||||
| import esphome.config_validation as cv |  | ||||||
| import esphome.codegen as cg |  | ||||||
|  |  | ||||||
| from . import boards | from . import boards | ||||||
| from .const import ( | from .const import ( | ||||||
| @@ -24,22 +24,21 @@ from .const import ( | |||||||
|     KEY_ESP32, |     KEY_ESP32, | ||||||
|     KEY_VARIANT, |     KEY_VARIANT, | ||||||
|     VARIANT_ESP32, |     VARIANT_ESP32, | ||||||
|     VARIANT_ESP32C3, |  | ||||||
|     VARIANT_ESP32S2, |  | ||||||
|     VARIANT_ESP32S3, |  | ||||||
|     VARIANT_ESP32C2, |     VARIANT_ESP32C2, | ||||||
|  |     VARIANT_ESP32C3, | ||||||
|     VARIANT_ESP32C6, |     VARIANT_ESP32C6, | ||||||
|     VARIANT_ESP32H2, |     VARIANT_ESP32H2, | ||||||
|  |     VARIANT_ESP32S2, | ||||||
|  |     VARIANT_ESP32S3, | ||||||
|     esp32_ns, |     esp32_ns, | ||||||
| ) | ) | ||||||
|  |  | ||||||
| from .gpio_esp32 import esp32_validate_gpio_pin, esp32_validate_supports | from .gpio_esp32 import esp32_validate_gpio_pin, esp32_validate_supports | ||||||
| from .gpio_esp32_s2 import esp32_s2_validate_gpio_pin, esp32_s2_validate_supports |  | ||||||
| from .gpio_esp32_c3 import esp32_c3_validate_gpio_pin, esp32_c3_validate_supports |  | ||||||
| from .gpio_esp32_s3 import esp32_s3_validate_gpio_pin, esp32_s3_validate_supports |  | ||||||
| from .gpio_esp32_c2 import esp32_c2_validate_gpio_pin, esp32_c2_validate_supports | from .gpio_esp32_c2 import esp32_c2_validate_gpio_pin, esp32_c2_validate_supports | ||||||
|  | from .gpio_esp32_c3 import esp32_c3_validate_gpio_pin, esp32_c3_validate_supports | ||||||
| from .gpio_esp32_c6 import esp32_c6_validate_gpio_pin, esp32_c6_validate_supports | from .gpio_esp32_c6 import esp32_c6_validate_gpio_pin, esp32_c6_validate_supports | ||||||
| from .gpio_esp32_h2 import esp32_h2_validate_gpio_pin, esp32_h2_validate_supports | from .gpio_esp32_h2 import esp32_h2_validate_gpio_pin, esp32_h2_validate_supports | ||||||
|  | from .gpio_esp32_s2 import esp32_s2_validate_gpio_pin, esp32_s2_validate_supports | ||||||
|  | from .gpio_esp32_s3 import esp32_s3_validate_gpio_pin, esp32_s3_validate_supports | ||||||
|  |  | ||||||
| ESP32InternalGPIOPin = esp32_ns.class_("ESP32InternalGPIOPin", cg.InternalGPIOPin) | ESP32InternalGPIOPin = esp32_ns.class_("ESP32InternalGPIOPin", cg.InternalGPIOPin) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| import logging | import logging | ||||||
|  |  | ||||||
|  | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_INPUT, |     CONF_INPUT, | ||||||
|     CONF_MODE, |     CONF_MODE, | ||||||
| @@ -8,10 +9,8 @@ from esphome.const import ( | |||||||
|     CONF_PULLDOWN, |     CONF_PULLDOWN, | ||||||
|     CONF_PULLUP, |     CONF_PULLUP, | ||||||
| ) | ) | ||||||
| import esphome.config_validation as cv |  | ||||||
| from esphome.pins import check_strapping_pin | from esphome.pins import check_strapping_pin | ||||||
|  |  | ||||||
|  |  | ||||||
| _ESP_SDIO_PINS = { | _ESP_SDIO_PINS = { | ||||||
|     6: "Flash Clock", |     6: "Flash Clock", | ||||||
|     7: "Flash Data 0", |     7: "Flash Data 0", | ||||||
|   | |||||||
| @@ -1,10 +1,9 @@ | |||||||
| import logging | import logging | ||||||
|  |  | ||||||
|  | import esphome.config_validation as cv | ||||||
| from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER | from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER | ||||||
| from esphome.pins import check_strapping_pin | from esphome.pins import check_strapping_pin | ||||||
|  |  | ||||||
| import esphome.config_validation as cv |  | ||||||
|  |  | ||||||
| _ESP32C2_STRAPPING_PINS = {8, 9} | _ESP32C2_STRAPPING_PINS = {8, 9} | ||||||
|  |  | ||||||
| _LOGGER = logging.getLogger(__name__) | _LOGGER = logging.getLogger(__name__) | ||||||
|   | |||||||
| @@ -1,11 +1,7 @@ | |||||||
| import logging | import logging | ||||||
|  |  | ||||||
| from esphome.const import ( |  | ||||||
|     CONF_INPUT, |  | ||||||
|     CONF_MODE, |  | ||||||
|     CONF_NUMBER, |  | ||||||
| ) |  | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
|  | from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER | ||||||
| from esphome.pins import check_strapping_pin | from esphome.pins import check_strapping_pin | ||||||
|  |  | ||||||
| _ESP32C3_SPI_PSRAM_PINS = { | _ESP32C3_SPI_PSRAM_PINS = { | ||||||
|   | |||||||
| @@ -1,8 +1,7 @@ | |||||||
| import logging | import logging | ||||||
|  |  | ||||||
| from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER |  | ||||||
|  |  | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
|  | from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER | ||||||
| from esphome.pins import check_strapping_pin | from esphome.pins import check_strapping_pin | ||||||
|  |  | ||||||
| _ESP32C6_SPI_PSRAM_PINS = { | _ESP32C6_SPI_PSRAM_PINS = { | ||||||
|   | |||||||
| @@ -1,8 +1,7 @@ | |||||||
| import logging | import logging | ||||||
|  |  | ||||||
| from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER |  | ||||||
|  |  | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
|  | from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER | ||||||
|  |  | ||||||
| _ESP32H2_SPI_FLASH_PINS = {6, 7, 15, 16, 17, 18, 19, 20, 21} | _ESP32H2_SPI_FLASH_PINS = {6, 7, 15, 16, 17, 18, 19, 20, 21} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| import logging | import logging | ||||||
|  |  | ||||||
|  | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_INPUT, |     CONF_INPUT, | ||||||
|     CONF_MODE, |     CONF_MODE, | ||||||
| @@ -8,8 +9,6 @@ from esphome.const import ( | |||||||
|     CONF_PULLDOWN, |     CONF_PULLDOWN, | ||||||
|     CONF_PULLUP, |     CONF_PULLUP, | ||||||
| ) | ) | ||||||
|  |  | ||||||
| import esphome.config_validation as cv |  | ||||||
| from esphome.pins import check_strapping_pin | from esphome.pins import check_strapping_pin | ||||||
|  |  | ||||||
| _ESP32S2_SPI_PSRAM_PINS = { | _ESP32S2_SPI_PSRAM_PINS = { | ||||||
|   | |||||||
| @@ -1,12 +1,7 @@ | |||||||
| import logging | import logging | ||||||
|  |  | ||||||
| from esphome.const import ( |  | ||||||
|     CONF_INPUT, |  | ||||||
|     CONF_MODE, |  | ||||||
|     CONF_NUMBER, |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
|  | from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER | ||||||
| from esphome.pins import check_strapping_pin | from esphome.pins import check_strapping_pin | ||||||
|  |  | ||||||
| _ESP_32S3_SPI_PSRAM_PINS = { | _ESP_32S3_SPI_PSRAM_PINS = { | ||||||
|   | |||||||
| @@ -1,9 +1,9 @@ | |||||||
| import esphome.codegen as cg |  | ||||||
| import esphome.config_validation as cv |  | ||||||
| from esphome import automation | from esphome import automation | ||||||
|  | import esphome.codegen as cg | ||||||
|  | from esphome.components.esp32 import add_idf_sdkconfig_option, const, get_esp32_variant | ||||||
|  | import esphome.config_validation as cv | ||||||
| from esphome.const import CONF_ENABLE_ON_BOOT, CONF_ID | from esphome.const import CONF_ENABLE_ON_BOOT, CONF_ID | ||||||
| from esphome.core import CORE | from esphome.core import CORE | ||||||
| from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant, const |  | ||||||
|  |  | ||||||
| DEPENDENCIES = ["esp32"] | DEPENDENCIES = ["esp32"] | ||||||
| CODEOWNERS = ["@jesserockz", "@Rapsssito"] | CODEOWNERS = ["@jesserockz", "@Rapsssito"] | ||||||
|   | |||||||
| @@ -1,10 +1,10 @@ | |||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| import esphome.config_validation as cv |  | ||||||
| from esphome.components.esp32_ble import CONF_BLE_ID |  | ||||||
| from esphome.const import CONF_ID, CONF_TYPE, CONF_UUID, CONF_TX_POWER |  | ||||||
| from esphome.core import CORE, TimePeriod |  | ||||||
| from esphome.components.esp32 import add_idf_sdkconfig_option |  | ||||||
| from esphome.components import esp32_ble | from esphome.components import esp32_ble | ||||||
|  | from esphome.components.esp32 import add_idf_sdkconfig_option | ||||||
|  | from esphome.components.esp32_ble import CONF_BLE_ID | ||||||
|  | import esphome.config_validation as cv | ||||||
|  | from esphome.const import CONF_ID, CONF_TX_POWER, CONF_TYPE, CONF_UUID | ||||||
|  | from esphome.core import CORE, TimePeriod | ||||||
|  |  | ||||||
| AUTO_LOAD = ["esp32_ble"] | AUTO_LOAD = ["esp32_ble"] | ||||||
| DEPENDENCIES = ["esp32"] | DEPENDENCIES = ["esp32"] | ||||||
|   | |||||||
| @@ -1,5 +1,4 @@ | |||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
|  |  | ||||||
| from esphome.components import esp32_ble_tracker | from esphome.components import esp32_ble_tracker | ||||||
|  |  | ||||||
| AUTO_LOAD = ["esp32_ble_tracker"] | AUTO_LOAD = ["esp32_ble_tracker"] | ||||||
|   | |||||||
| @@ -1,9 +1,9 @@ | |||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
|  | from esphome.components import esp32_ble | ||||||
|  | from esphome.components.esp32 import add_idf_sdkconfig_option | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.const import CONF_ID, CONF_MODEL | from esphome.const import CONF_ID, CONF_MODEL | ||||||
| from esphome.components import esp32_ble |  | ||||||
| from esphome.core import CORE | from esphome.core import CORE | ||||||
| from esphome.components.esp32 import add_idf_sdkconfig_option |  | ||||||
|  |  | ||||||
| AUTO_LOAD = ["esp32_ble"] | AUTO_LOAD = ["esp32_ble"] | ||||||
| CODEOWNERS = ["@jesserockz", "@clydebarrow", "@Rapsssito"] | CODEOWNERS = ["@jesserockz", "@clydebarrow", "@Rapsssito"] | ||||||
|   | |||||||
| @@ -1,10 +1,10 @@ | |||||||
| import re | import re | ||||||
|  |  | ||||||
| import esphome.codegen as cg |  | ||||||
| import esphome.config_validation as cv |  | ||||||
| from esphome import automation | from esphome import automation | ||||||
|  | import esphome.codegen as cg | ||||||
| from esphome.components import esp32_ble | from esphome.components import esp32_ble | ||||||
| from esphome.components.esp32 import add_idf_sdkconfig_option | from esphome.components.esp32 import add_idf_sdkconfig_option | ||||||
|  | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_ACTIVE, |     CONF_ACTIVE, | ||||||
|     CONF_DURATION, |     CONF_DURATION, | ||||||
|   | |||||||
| @@ -1,6 +1,4 @@ | |||||||
| from esphome import pins | from esphome import pins | ||||||
| import esphome.config_validation as cv |  | ||||||
| import esphome.final_validate as fv |  | ||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant | from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant | ||||||
| from esphome.components.esp32.const import ( | from esphome.components.esp32.const import ( | ||||||
| @@ -8,31 +6,33 @@ from esphome.components.esp32.const import ( | |||||||
|     VARIANT_ESP32S2, |     VARIANT_ESP32S2, | ||||||
|     VARIANT_ESP32S3, |     VARIANT_ESP32S3, | ||||||
| ) | ) | ||||||
|  | from esphome.components.network import IPAddress | ||||||
|  | from esphome.components.spi import CONF_INTERFACE_INDEX, get_spi_interface | ||||||
|  | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_DOMAIN, |     CONF_ADDRESS, | ||||||
|     CONF_ID, |     CONF_CLK_PIN, | ||||||
|     CONF_VALUE, |     CONF_CS_PIN, | ||||||
|     CONF_MANUAL_IP, |  | ||||||
|     CONF_STATIC_IP, |  | ||||||
|     CONF_TYPE, |  | ||||||
|     CONF_USE_ADDRESS, |  | ||||||
|     CONF_GATEWAY, |  | ||||||
|     CONF_SUBNET, |  | ||||||
|     CONF_DNS1, |     CONF_DNS1, | ||||||
|     CONF_DNS2, |     CONF_DNS2, | ||||||
|     CONF_CLK_PIN, |     CONF_DOMAIN, | ||||||
|  |     CONF_GATEWAY, | ||||||
|  |     CONF_ID, | ||||||
|  |     CONF_INTERRUPT_PIN, | ||||||
|  |     CONF_MANUAL_IP, | ||||||
|     CONF_MISO_PIN, |     CONF_MISO_PIN, | ||||||
|     CONF_MOSI_PIN, |     CONF_MOSI_PIN, | ||||||
|     CONF_CS_PIN, |     CONF_PAGE_ID, | ||||||
|     CONF_INTERRUPT_PIN, |  | ||||||
|     CONF_RESET_PIN, |     CONF_RESET_PIN, | ||||||
|     CONF_SPI, |     CONF_SPI, | ||||||
|     CONF_PAGE_ID, |     CONF_STATIC_IP, | ||||||
|     CONF_ADDRESS, |     CONF_SUBNET, | ||||||
|  |     CONF_TYPE, | ||||||
|  |     CONF_USE_ADDRESS, | ||||||
|  |     CONF_VALUE, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, coroutine_with_priority | ||||||
| from esphome.components.network import IPAddress | import esphome.final_validate as fv | ||||||
| from esphome.components.spi import get_spi_interface, CONF_INTERFACE_INDEX |  | ||||||
|  |  | ||||||
| CONFLICTS_WITH = ["wifi"] | CONFLICTS_WITH = ["wifi"] | ||||||
| DEPENDENCIES = ["esp32"] | DEPENDENCIES = ["esp32"] | ||||||
|   | |||||||
| @@ -1,9 +1,9 @@ | |||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| import esphome.config_validation as cv |  | ||||||
| from esphome.components import text_sensor | from esphome.components import text_sensor | ||||||
|  | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_IP_ADDRESS, |  | ||||||
|     CONF_DNS_ADDRESS, |     CONF_DNS_ADDRESS, | ||||||
|  |     CONF_IP_ADDRESS, | ||||||
|     CONF_MAC_ADDRESS, |     CONF_MAC_ADDRESS, | ||||||
|     ENTITY_CATEGORY_DIAGNOSTIC, |     ENTITY_CATEGORY_DIAGNOSTIC, | ||||||
| ) | ) | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ from esphome.const import ( | |||||||
| from esphome.core import CORE, Lambda | from esphome.core import CORE, Lambda | ||||||
|  |  | ||||||
| DEPENDENCIES = ["network"] | DEPENDENCIES = ["network"] | ||||||
| AUTO_LOAD = ["json"] | AUTO_LOAD = ["json", "watchdog"] | ||||||
|  |  | ||||||
| http_request_ns = cg.esphome_ns.namespace("http_request") | http_request_ns = cg.esphome_ns.namespace("http_request") | ||||||
| HttpRequestComponent = http_request_ns.class_("HttpRequestComponent", cg.Component) | HttpRequestComponent = http_request_ns.class_("HttpRequestComponent", cg.Component) | ||||||
|   | |||||||
| @@ -3,12 +3,12 @@ | |||||||
| #ifdef USE_ARDUINO | #ifdef USE_ARDUINO | ||||||
|  |  | ||||||
| #include "esphome/components/network/util.h" | #include "esphome/components/network/util.h" | ||||||
|  | #include "esphome/components/watchdog/watchdog.h" | ||||||
|  |  | ||||||
| #include "esphome/core/application.h" | #include "esphome/core/application.h" | ||||||
| #include "esphome/core/defines.h" | #include "esphome/core/defines.h" | ||||||
| #include "esphome/core/log.h" | #include "esphome/core/log.h" | ||||||
|  |  | ||||||
| #include "watchdog.h" |  | ||||||
|  |  | ||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace http_request { | namespace http_request { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,6 +3,8 @@ | |||||||
| #ifdef USE_ESP_IDF | #ifdef USE_ESP_IDF | ||||||
|  |  | ||||||
| #include "esphome/components/network/util.h" | #include "esphome/components/network/util.h" | ||||||
|  | #include "esphome/components/watchdog/watchdog.h" | ||||||
|  |  | ||||||
| #include "esphome/core/application.h" | #include "esphome/core/application.h" | ||||||
| #include "esphome/core/defines.h" | #include "esphome/core/defines.h" | ||||||
| #include "esphome/core/log.h" | #include "esphome/core/log.h" | ||||||
| @@ -11,8 +13,6 @@ | |||||||
| #include "esp_crt_bundle.h" | #include "esp_crt_bundle.h" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #include "watchdog.h" |  | ||||||
|  |  | ||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace http_request { | namespace http_request { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,11 +1,11 @@ | |||||||
| #include "ota_http_request.h" | #include "ota_http_request.h" | ||||||
| #include "../watchdog.h" |  | ||||||
|  |  | ||||||
| #include "esphome/core/application.h" | #include "esphome/core/application.h" | ||||||
| #include "esphome/core/defines.h" | #include "esphome/core/defines.h" | ||||||
| #include "esphome/core/log.h" | #include "esphome/core/log.h" | ||||||
|  |  | ||||||
| #include "esphome/components/md5/md5.h" | #include "esphome/components/md5/md5.h" | ||||||
|  | #include "esphome/components/watchdog/watchdog.h" | ||||||
| #include "esphome/components/ota/ota_backend.h" | #include "esphome/components/ota/ota_backend.h" | ||||||
| #include "esphome/components/ota/ota_backend_arduino_esp32.h" | #include "esphome/components/ota/ota_backend_arduino_esp32.h" | ||||||
| #include "esphome/components/ota/ota_backend_arduino_esp8266.h" | #include "esphome/components/ota/ota_backend_arduino_esp8266.h" | ||||||
|   | |||||||
| @@ -16,13 +16,20 @@ from esphome.final_validate import full_config | |||||||
| from esphome.helpers import write_file_if_changed | from esphome.helpers import write_file_if_changed | ||||||
|  |  | ||||||
| from . import defines as df, helpers, lv_validation as lvalid | from . import defines as df, helpers, lv_validation as lvalid | ||||||
|  | from .btn import btn_spec | ||||||
| from .label import label_spec | from .label import label_spec | ||||||
| from .lvcode import ConstantLiteral, LvContext | from .lvcode import ConstantLiteral, LvContext | ||||||
|  |  | ||||||
| # from .menu import menu_spec |  | ||||||
| from .obj import obj_spec | from .obj import obj_spec | ||||||
| from .schemas import WIDGET_TYPES, any_widget_schema, obj_schema | from .schemas import any_widget_schema, obj_schema | ||||||
| from .types import FontEngine, LvglComponent, lv_disp_t_ptr, lv_font_t, lvgl_ns | from .touchscreens import touchscreen_schema, touchscreens_to_code | ||||||
|  | from .types import ( | ||||||
|  |     WIDGET_TYPES, | ||||||
|  |     FontEngine, | ||||||
|  |     LvglComponent, | ||||||
|  |     lv_disp_t_ptr, | ||||||
|  |     lv_font_t, | ||||||
|  |     lvgl_ns, | ||||||
|  | ) | ||||||
| from .widget import LvScrActType, Widget, add_widgets, set_obj_properties | from .widget import LvScrActType, Widget, add_widgets, set_obj_properties | ||||||
|  |  | ||||||
| DOMAIN = "lvgl" | DOMAIN = "lvgl" | ||||||
| @@ -31,11 +38,8 @@ AUTO_LOAD = ("key_provider",) | |||||||
| CODEOWNERS = ("@clydebarrow",) | CODEOWNERS = ("@clydebarrow",) | ||||||
| LOGGER = logging.getLogger(__name__) | LOGGER = logging.getLogger(__name__) | ||||||
|  |  | ||||||
| for widg in ( | for w_type in (label_spec, obj_spec, btn_spec): | ||||||
|     label_spec, |     WIDGET_TYPES[w_type.name] = w_type | ||||||
|     obj_spec, |  | ||||||
| ): |  | ||||||
|     WIDGET_TYPES[widg.name] = widg |  | ||||||
|  |  | ||||||
| lv_scr_act_spec = LvScrActType() | lv_scr_act_spec = LvScrActType() | ||||||
| lv_scr_act = Widget.create( | lv_scr_act = Widget.create( | ||||||
| @@ -93,7 +97,7 @@ def final_validation(config): | |||||||
|                 "Using auto_clear_enabled: true in display config not compatible with LVGL" |                 "Using auto_clear_enabled: true in display config not compatible with LVGL" | ||||||
|             ) |             ) | ||||||
|     buffer_frac = config[CONF_BUFFER_SIZE] |     buffer_frac = config[CONF_BUFFER_SIZE] | ||||||
|     if not CORE.is_host and buffer_frac > 0.5 and "psram" not in global_config: |     if CORE.is_esp32 and buffer_frac > 0.5 and "psram" not in global_config: | ||||||
|         LOGGER.warning("buffer_size: may need to be reduced without PSRAM") |         LOGGER.warning("buffer_size: may need to be reduced without PSRAM") | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -132,7 +136,7 @@ async def to_code(config): | |||||||
|     cg.add_global(lvgl_ns.using) |     cg.add_global(lvgl_ns.using) | ||||||
|     lv_component = cg.new_Pvariable(config[CONF_ID]) |     lv_component = cg.new_Pvariable(config[CONF_ID]) | ||||||
|     await cg.register_component(lv_component, config) |     await cg.register_component(lv_component, config) | ||||||
|     Widget.create(config[CONF_ID], lv_component, WIDGET_TYPES[df.CONF_OBJ], config) |     Widget.create(config[CONF_ID], lv_component, obj_spec, config) | ||||||
|     for display in config[df.CONF_DISPLAYS]: |     for display in config[df.CONF_DISPLAYS]: | ||||||
|         cg.add(lv_component.add_display(await cg.get_variable(display))) |         cg.add(lv_component.add_display(await cg.get_variable(display))) | ||||||
|  |  | ||||||
| @@ -152,7 +156,7 @@ async def to_code(config): | |||||||
|         await cg.get_variable(font) |         await cg.get_variable(font) | ||||||
|         cg.new_Pvariable(ID(f"{font}_engine", True, type=FontEngine), MockObj(font)) |         cg.new_Pvariable(ID(f"{font}_engine", True, type=FontEngine), MockObj(font)) | ||||||
|     default_font = config[df.CONF_DEFAULT_FONT] |     default_font = config[df.CONF_DEFAULT_FONT] | ||||||
|     if default_font not in helpers.lv_fonts_used: |     if not lvalid.is_lv_font(default_font): | ||||||
|         add_define( |         add_define( | ||||||
|             "LV_FONT_CUSTOM_DECLARE", f"LV_FONT_DECLARE(*{df.DEFAULT_ESPHOME_FONT})" |             "LV_FONT_CUSTOM_DECLARE", f"LV_FONT_DECLARE(*{df.DEFAULT_ESPHOME_FONT})" | ||||||
|         ) |         ) | ||||||
| @@ -161,12 +165,15 @@ async def to_code(config): | |||||||
|             True, |             True, | ||||||
|             type=lv_font_t.operator("ptr").operator("const"), |             type=lv_font_t.operator("ptr").operator("const"), | ||||||
|         ) |         ) | ||||||
|         cg.new_variable(globfont_id, MockObj(default_font)) |         cg.new_variable( | ||||||
|  |             globfont_id, MockObj(await lvalid.lv_font.process(default_font)) | ||||||
|  |         ) | ||||||
|         add_define("LV_FONT_DEFAULT", df.DEFAULT_ESPHOME_FONT) |         add_define("LV_FONT_DEFAULT", df.DEFAULT_ESPHOME_FONT) | ||||||
|     else: |     else: | ||||||
|         add_define("LV_FONT_DEFAULT", default_font) |         add_define("LV_FONT_DEFAULT", await lvalid.lv_font.process(default_font)) | ||||||
|  |  | ||||||
|     with LvContext(): |     with LvContext(): | ||||||
|  |         await touchscreens_to_code(lv_component, config) | ||||||
|         await set_obj_properties(lv_scr_act, config) |         await set_obj_properties(lv_scr_act, config) | ||||||
|         await add_widgets(lv_scr_act, config) |         await add_widgets(lv_scr_act, config) | ||||||
|     Widget.set_completed() |     Widget.set_completed() | ||||||
| @@ -190,7 +197,7 @@ FINAL_VALIDATE_SCHEMA = final_validation | |||||||
|  |  | ||||||
| CONFIG_SCHEMA = ( | CONFIG_SCHEMA = ( | ||||||
|     cv.polling_component_schema("1s") |     cv.polling_component_schema("1s") | ||||||
|     .extend(obj_schema("obj")) |     .extend(obj_schema(obj_spec)) | ||||||
|     .extend( |     .extend( | ||||||
|         { |         { | ||||||
|             cv.GenerateID(CONF_ID): cv.declare_id(LvglComponent), |             cv.GenerateID(CONF_ID): cv.declare_id(LvglComponent), | ||||||
| @@ -207,6 +214,7 @@ CONFIG_SCHEMA = ( | |||||||
|             ), |             ), | ||||||
|             cv.Optional(df.CONF_WIDGETS): cv.ensure_list(WIDGET_SCHEMA), |             cv.Optional(df.CONF_WIDGETS): cv.ensure_list(WIDGET_SCHEMA), | ||||||
|             cv.Optional(df.CONF_TRANSPARENCY_KEY, default=0x000400): lvalid.lv_color, |             cv.Optional(df.CONF_TRANSPARENCY_KEY, default=0x000400): lvalid.lv_color, | ||||||
|  |             cv.GenerateID(df.CONF_TOUCHSCREENS): touchscreen_schema, | ||||||
|         } |         } | ||||||
|     ) |     ) | ||||||
| ).add_extra(cv.has_at_least_one_key(CONF_PAGES, df.CONF_WIDGETS)) | ).add_extra(cv.has_at_least_one_key(CONF_PAGES, df.CONF_WIDGETS)) | ||||||
|   | |||||||
							
								
								
									
										25
									
								
								esphome/components/lvgl/btn.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								esphome/components/lvgl/btn.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | from esphome.const import CONF_BUTTON | ||||||
|  | from esphome.cpp_generator import MockObjClass | ||||||
|  |  | ||||||
|  | from .defines import CONF_MAIN | ||||||
|  | from .types import LvBoolean, WidgetType | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class BtnType(WidgetType): | ||||||
|  |     def __init__(self): | ||||||
|  |         super().__init__(CONF_BUTTON, LvBoolean("lv_btn_t"), (CONF_MAIN,)) | ||||||
|  |  | ||||||
|  |     async def to_code(self, w, config): | ||||||
|  |         return [] | ||||||
|  |  | ||||||
|  |     def obj_creator(self, parent: MockObjClass, config: dict): | ||||||
|  |         """ | ||||||
|  |         LVGL 8 calls buttons `btn` | ||||||
|  |         """ | ||||||
|  |         return f"lv_btn_create({parent})" | ||||||
|  |  | ||||||
|  |     def get_uses(self): | ||||||
|  |         return ("btn",) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | btn_spec = BtnType() | ||||||
| @@ -446,6 +446,7 @@ CONF_TILE_ID = "tile_id" | |||||||
| CONF_TILES = "tiles" | CONF_TILES = "tiles" | ||||||
| CONF_TITLE = "title" | CONF_TITLE = "title" | ||||||
| CONF_TOP_LAYER = "top_layer" | CONF_TOP_LAYER = "top_layer" | ||||||
|  | CONF_TOUCHSCREENS = "touchscreens" | ||||||
| CONF_TRANSPARENCY_KEY = "transparency_key" | CONF_TRANSPARENCY_KEY = "transparency_key" | ||||||
| CONF_THEME = "theme" | CONF_THEME = "theme" | ||||||
| CONF_VISIBLE_ROW_COUNT = "visible_row_count" | CONF_VISIBLE_ROW_COUNT = "visible_row_count" | ||||||
| @@ -474,14 +475,8 @@ LV_KEYS = LvConstant( | |||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| # list of widgets and the parts allowed |  | ||||||
| WIDGET_PARTS = { |  | ||||||
|     CONF_LABEL: (CONF_MAIN, CONF_SCROLLBAR, CONF_SELECTED), |  | ||||||
|     CONF_OBJ: (CONF_MAIN,), |  | ||||||
| } |  | ||||||
|  |  | ||||||
| DEFAULT_ESPHOME_FONT = "esphome_lv_default_font" | DEFAULT_ESPHOME_FONT = "esphome_lv_default_font" | ||||||
|  |  | ||||||
|  |  | ||||||
| def join_enums(enums, prefix=""): | def join_enums(enums, prefix=""): | ||||||
|     return "|".join(f"(int){prefix}{e.upper()}" for e in enums) |     return ConstantLiteral("|".join(f"(int){prefix}{e.upper()}" for e in enums)) | ||||||
|   | |||||||
| @@ -22,7 +22,6 @@ def add_lv_use(*names): | |||||||
|  |  | ||||||
| lv_fonts_used = set() | lv_fonts_used = set() | ||||||
| esphome_fonts_used = set() | esphome_fonts_used = set() | ||||||
| REQUIRED_COMPONENTS = {} |  | ||||||
| lvgl_components_required = set() | lvgl_components_required = set() | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,16 +1,27 @@ | |||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
|  |  | ||||||
| from .defines import CONF_LABEL, CONF_LONG_MODE, CONF_RECOLOR, CONF_TEXT, LV_LONG_MODES | from .defines import ( | ||||||
|  |     CONF_LABEL, | ||||||
|  |     CONF_LONG_MODE, | ||||||
|  |     CONF_MAIN, | ||||||
|  |     CONF_RECOLOR, | ||||||
|  |     CONF_SCROLLBAR, | ||||||
|  |     CONF_SELECTED, | ||||||
|  |     CONF_TEXT, | ||||||
|  |     LV_LONG_MODES, | ||||||
|  | ) | ||||||
| from .lv_validation import lv_bool, lv_text | from .lv_validation import lv_bool, lv_text | ||||||
| from .schemas import TEXT_SCHEMA | from .schemas import TEXT_SCHEMA | ||||||
| from .types import lv_label_t | from .types import LvText, WidgetType | ||||||
| from .widget import Widget, WidgetType | from .widget import Widget | ||||||
|  |  | ||||||
|  |  | ||||||
| class LabelType(WidgetType): | class LabelType(WidgetType): | ||||||
|     def __init__(self): |     def __init__(self): | ||||||
|         super().__init__( |         super().__init__( | ||||||
|             CONF_LABEL, |             CONF_LABEL, | ||||||
|  |             LvText("lv_label_t"), | ||||||
|  |             (CONF_MAIN, CONF_SCROLLBAR, CONF_SELECTED), | ||||||
|             TEXT_SCHEMA.extend( |             TEXT_SCHEMA.extend( | ||||||
|                 { |                 { | ||||||
|                     cv.Optional(CONF_RECOLOR): lv_bool, |                     cv.Optional(CONF_RECOLOR): lv_bool, | ||||||
| @@ -19,10 +30,6 @@ class LabelType(WidgetType): | |||||||
|             ), |             ), | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|     @property |  | ||||||
|     def w_type(self): |  | ||||||
|         return lv_label_t |  | ||||||
|  |  | ||||||
|     async def to_code(self, w: Widget, config): |     async def to_code(self, w: Widget, config): | ||||||
|         """For a text object, create and set text""" |         """For a text object, create and set text""" | ||||||
|         if value := config.get(CONF_TEXT): |         if value := config.get(CONF_TEXT): | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ import esphome.config_validation as cv | |||||||
| from esphome.const import CONF_ARGS, CONF_COLOR, CONF_FORMAT | from esphome.const import CONF_ARGS, CONF_COLOR, CONF_FORMAT | ||||||
| from esphome.core import HexInt | from esphome.core import HexInt | ||||||
| from esphome.cpp_generator import MockObj | from esphome.cpp_generator import MockObj | ||||||
|  | from esphome.cpp_types import uint32 | ||||||
| from esphome.helpers import cpp_string_escape | from esphome.helpers import cpp_string_escape | ||||||
| from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor | from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor | ||||||
|  |  | ||||||
| @@ -23,6 +24,28 @@ from .lvcode import ConstantLiteral, lv_expr | |||||||
| from .types import lv_font_t | from .types import lv_font_t | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def literal_mapper(value, args=()): | ||||||
|  |     if isinstance(value, str): | ||||||
|  |         return ConstantLiteral(value) | ||||||
|  |     return value | ||||||
|  |  | ||||||
|  |  | ||||||
|  | opacity_consts = LvConstant("LV_OPA_", "TRANSP", "COVER") | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @schema_extractor("one_of") | ||||||
|  | def opacity_validator(value): | ||||||
|  |     if value == SCHEMA_EXTRACT: | ||||||
|  |         return opacity_consts.choices | ||||||
|  |     value = cv.Any(cv.percentage, opacity_consts.one_of)(value) | ||||||
|  |     if isinstance(value, float): | ||||||
|  |         return int(value * 255) | ||||||
|  |     return value | ||||||
|  |  | ||||||
|  |  | ||||||
|  | opacity = LValidator(opacity_validator, uint32, retmapper=literal_mapper) | ||||||
|  |  | ||||||
|  |  | ||||||
| @schema_extractor("one_of") | @schema_extractor("one_of") | ||||||
| def color(value): | def color(value): | ||||||
|     if value == SCHEMA_EXTRACT: |     if value == SCHEMA_EXTRACT: | ||||||
| @@ -43,16 +66,24 @@ def color_retmapper(value): | |||||||
|     return lv_expr.color_from(MockObj(value)) |     return lv_expr.color_from(MockObj(value)) | ||||||
|  |  | ||||||
|  |  | ||||||
| def pixels_or_percent(value): | lv_color = LValidator(color, ty.lv_color_t, retmapper=color_retmapper) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def pixels_or_percent_validator(value): | ||||||
|     """A length in one axis - either a number (pixels) or a percentage""" |     """A length in one axis - either a number (pixels) or a percentage""" | ||||||
|     if value == SCHEMA_EXTRACT: |     if value == SCHEMA_EXTRACT: | ||||||
|         return ["pixels", "..%"] |         return ["pixels", "..%"] | ||||||
|     if isinstance(value, int): |     if isinstance(value, int): | ||||||
|         return str(cv.int_(value)) |         return cv.int_(value) | ||||||
|     # Will throw an exception if not a percentage. |     # Will throw an exception if not a percentage. | ||||||
|     return f"lv_pct({int(cv.percentage(value) * 100)})" |     return f"lv_pct({int(cv.percentage(value) * 100)})" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | pixels_or_percent = LValidator( | ||||||
|  |     pixels_or_percent_validator, uint32, retmapper=literal_mapper | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| def zoom(value): | def zoom(value): | ||||||
|     value = cv.float_range(0.1, 10.0)(value) |     value = cv.float_range(0.1, 10.0)(value) | ||||||
|     return int(value * 256) |     return int(value * 256) | ||||||
| @@ -68,7 +99,7 @@ def angle(value): | |||||||
|  |  | ||||||
|  |  | ||||||
| @schema_extractor("one_of") | @schema_extractor("one_of") | ||||||
| def size(value): | def size_validator(value): | ||||||
|     """A size in one axis - one of "size_content", a number (pixels) or a percentage""" |     """A size in one axis - one of "size_content", a number (pixels) or a percentage""" | ||||||
|     if value == SCHEMA_EXTRACT: |     if value == SCHEMA_EXTRACT: | ||||||
|         return ["size_content", "pixels", "..%"] |         return ["size_content", "pixels", "..%"] | ||||||
| @@ -79,28 +110,42 @@ def size(value): | |||||||
|             return "LV_SIZE_CONTENT" |             return "LV_SIZE_CONTENT" | ||||||
|         raise cv.Invalid("must be 'size_content', a pixel position or a percentage") |         raise cv.Invalid("must be 'size_content', a pixel position or a percentage") | ||||||
|     if isinstance(value, int): |     if isinstance(value, int): | ||||||
|         return str(cv.int_(value)) |         return cv.int_(value) | ||||||
|     # Will throw an exception if not a percentage. |     # Will throw an exception if not a percentage. | ||||||
|     return f"lv_pct({int(cv.percentage(value) * 100)})" |     return f"lv_pct({int(cv.percentage(value) * 100)})" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | size = LValidator(size_validator, uint32, retmapper=literal_mapper) | ||||||
|  |  | ||||||
|  | radius_consts = LvConstant("LV_RADIUS_", "CIRCLE") | ||||||
|  |  | ||||||
|  |  | ||||||
| @schema_extractor("one_of") | @schema_extractor("one_of") | ||||||
| def opacity(value): | def radius_validator(value): | ||||||
|     consts = LvConstant("LV_OPA_", "TRANSP", "COVER") |  | ||||||
|     if value == SCHEMA_EXTRACT: |     if value == SCHEMA_EXTRACT: | ||||||
|         return consts.choices |         return radius_consts.choices | ||||||
|     value = cv.Any(cv.percentage, consts.one_of)(value) |     value = cv.Any(size, cv.percentage, radius_consts.one_of)(value) | ||||||
|     if isinstance(value, float): |     if isinstance(value, float): | ||||||
|         return int(value * 255) |         return int(value * 255) | ||||||
|     return value |     return value | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def id_name(value): | ||||||
|  |     if value == SCHEMA_EXTRACT: | ||||||
|  |         return "id" | ||||||
|  |     return cv.validate_id_name(value) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | radius = LValidator(radius_validator, uint32, retmapper=literal_mapper) | ||||||
|  |  | ||||||
|  |  | ||||||
| def stop_value(value): | def stop_value(value): | ||||||
|     return cv.int_range(0, 255)(value) |     return cv.int_range(0, 255)(value) | ||||||
|  |  | ||||||
|  |  | ||||||
| lv_color = LValidator(color, ty.lv_color_t, retmapper=color_retmapper) | lv_bool = LValidator( | ||||||
| lv_bool = LValidator(cv.boolean, cg.bool_, BinarySensor, "get_state()") |     cv.boolean, cg.bool_, BinarySensor, "get_state()", retmapper=literal_mapper | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| def lvms_validator_(value): | def lvms_validator_(value): | ||||||
| @@ -145,26 +190,32 @@ lv_float = LValidator(cv.float_, cg.float_, Sensor, "get_state()") | |||||||
| lv_int = LValidator(cv.int_, cg.int_, Sensor, "get_state()") | lv_int = LValidator(cv.int_, cg.int_, Sensor, "get_state()") | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def is_lv_font(font): | ||||||
|  |     return isinstance(font, str) and font.lower() in LV_FONTS | ||||||
|  |  | ||||||
|  |  | ||||||
| class LvFont(LValidator): | class LvFont(LValidator): | ||||||
|     def __init__(self): |     def __init__(self): | ||||||
|         def lv_builtin_font(value): |         def lv_builtin_font(value): | ||||||
|             fontval = cv.one_of(*LV_FONTS, lower=True)(value) |             fontval = cv.one_of(*LV_FONTS, lower=True)(value) | ||||||
|             lv_fonts_used.add(fontval) |             lv_fonts_used.add(fontval) | ||||||
|             return "&lv_font_" + fontval |             return fontval | ||||||
|  |  | ||||||
|         def validator(value): |         def validator(value): | ||||||
|             if value == SCHEMA_EXTRACT: |             if value == SCHEMA_EXTRACT: | ||||||
|                 return LV_FONTS |                 return LV_FONTS | ||||||
|             if isinstance(value, str) and value.lower() in LV_FONTS: |             if is_lv_font(value): | ||||||
|                 return lv_builtin_font(value) |                 return lv_builtin_font(value) | ||||||
|             fontval = cv.use_id(Font)(value) |             fontval = cv.use_id(Font)(value) | ||||||
|             esphome_fonts_used.add(fontval) |             esphome_fonts_used.add(fontval) | ||||||
|             return requires_component("font")(f"{fontval}_engine->get_lv_font()") |             return requires_component("font")(fontval) | ||||||
|  |  | ||||||
|         super().__init__(validator, lv_font_t) |         super().__init__(validator, lv_font_t) | ||||||
|  |  | ||||||
|     async def process(self, value, args=()): |     async def process(self, value, args=()): | ||||||
|         return ConstantLiteral(value) |         if is_lv_font(value): | ||||||
|  |             return ConstantLiteral(f"&lv_font_{value}") | ||||||
|  |         return ConstantLiteral(f"{value}_engine->get_lv_font()") | ||||||
|  |  | ||||||
|  |  | ||||||
| lv_font = LvFont() | lv_font = LvFont() | ||||||
|   | |||||||
| @@ -38,7 +38,9 @@ void LvglComponent::setup() { | |||||||
|   auto buf_bytes = buffer_pixels * LV_COLOR_DEPTH / 8; |   auto buf_bytes = buffer_pixels * LV_COLOR_DEPTH / 8; | ||||||
|   auto *buf = lv_custom_mem_alloc(buf_bytes); |   auto *buf = lv_custom_mem_alloc(buf_bytes); | ||||||
|   if (buf == nullptr) { |   if (buf == nullptr) { | ||||||
|  | #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_ERROR | ||||||
|     ESP_LOGE(TAG, "Malloc failed to allocate %zu bytes", buf_bytes); |     ESP_LOGE(TAG, "Malloc failed to allocate %zu bytes", buf_bytes); | ||||||
|  | #endif | ||||||
|     this->mark_failed(); |     this->mark_failed(); | ||||||
|     this->status_set_error("Memory allocation failure"); |     this->status_set_error("Memory allocation failure"); | ||||||
|     return; |     return; | ||||||
| @@ -85,7 +87,9 @@ size_t lv_millis(void) { return esphome::millis(); } | |||||||
| void *lv_custom_mem_alloc(size_t size) { | void *lv_custom_mem_alloc(size_t size) { | ||||||
|   auto *ptr = malloc(size);  // NOLINT |   auto *ptr = malloc(size);  // NOLINT | ||||||
|   if (ptr == nullptr) { |   if (ptr == nullptr) { | ||||||
|  | #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_ERROR | ||||||
|     esphome::ESP_LOGE(esphome::lvgl::TAG, "Failed to allocate %zu bytes", size); |     esphome::ESP_LOGE(esphome::lvgl::TAG, "Failed to allocate %zu bytes", size); | ||||||
|  | #endif | ||||||
|   } |   } | ||||||
|   return ptr; |   return ptr; | ||||||
| } | } | ||||||
| @@ -102,7 +106,9 @@ void *lv_custom_mem_alloc(size_t size) { | |||||||
|     ptr = heap_caps_malloc(size, cap_bits); |     ptr = heap_caps_malloc(size, cap_bits); | ||||||
|   } |   } | ||||||
|   if (ptr == nullptr) { |   if (ptr == nullptr) { | ||||||
|  | #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_ERROR | ||||||
|     esphome::ESP_LOGE(esphome::lvgl::TAG, "Failed to allocate %zu bytes", size); |     esphome::ESP_LOGE(esphome::lvgl::TAG, "Failed to allocate %zu bytes", size); | ||||||
|  | #endif | ||||||
|     return nullptr; |     return nullptr; | ||||||
|   } |   } | ||||||
| #ifdef ESPHOME_LOG_HAS_VERBOSE | #ifdef ESPHOME_LOG_HAS_VERBOSE | ||||||
|   | |||||||
| @@ -18,23 +18,27 @@ | |||||||
| #ifdef USE_LVGL_FONT | #ifdef USE_LVGL_FONT | ||||||
| #include "esphome/components/font/font.h" | #include "esphome/components/font/font.h" | ||||||
| #endif | #endif | ||||||
|  | #ifdef USE_LVGL_TOUCHSCREEN | ||||||
|  | #include "esphome/components/touchscreen/touchscreen.h" | ||||||
|  | #endif  // USE_LVGL_TOUCHSCREEN | ||||||
|  |  | ||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace lvgl { | namespace lvgl { | ||||||
|  |  | ||||||
| extern lv_event_code_t lv_custom_event;  // NOLINT | extern lv_event_code_t lv_custom_event;  // NOLINT | ||||||
| #ifdef USE_LVGL_COLOR | #ifdef USE_LVGL_COLOR | ||||||
| static lv_color_t lv_color_from(Color color) { return lv_color_make(color.red, color.green, color.blue); } | inline lv_color_t lv_color_from(Color color) { return lv_color_make(color.red, color.green, color.blue); } | ||||||
| #endif | #endif  // USE_LVGL_COLOR | ||||||
| #if LV_COLOR_DEPTH == 16 | #if LV_COLOR_DEPTH == 16 | ||||||
| static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_565; | static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_565; | ||||||
| #elif LV_COLOR_DEPTH == 32 | #elif LV_COLOR_DEPTH == 32 | ||||||
| static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_888; | static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_888; | ||||||
| #else | #else   // LV_COLOR_DEPTH | ||||||
| static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_332; | static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_332; | ||||||
| #endif | #endif  // LV_COLOR_DEPTH | ||||||
|  |  | ||||||
| // Parent class for things that wrap an LVGL object | // Parent class for things that wrap an LVGL object | ||||||
| class LvCompound { | class LvCompound final { | ||||||
|  public: |  public: | ||||||
|   virtual void set_obj(lv_obj_t *lv_obj) { this->obj = lv_obj; } |   virtual void set_obj(lv_obj_t *lv_obj) { this->obj = lv_obj; } | ||||||
|   lv_obj_t *obj{}; |   lv_obj_t *obj{}; | ||||||
| @@ -99,6 +103,14 @@ class LvglComponent : public PollingComponent { | |||||||
|   void set_full_refresh(bool full_refresh) { this->full_refresh_ = full_refresh; } |   void set_full_refresh(bool full_refresh) { this->full_refresh_ = full_refresh; } | ||||||
|   void set_buffer_frac(size_t frac) { this->buffer_frac_ = frac; } |   void set_buffer_frac(size_t frac) { this->buffer_frac_ = frac; } | ||||||
|   lv_disp_t *get_disp() { return this->disp_; } |   lv_disp_t *get_disp() { return this->disp_; } | ||||||
|  |   void set_paused(bool paused, bool show_snow) { | ||||||
|  |     this->paused_ = paused; | ||||||
|  |     if (!paused && lv_scr_act() != nullptr) { | ||||||
|  |       lv_disp_trig_activity(this->disp_);  // resets the inactivity time | ||||||
|  |       lv_obj_invalidate(lv_scr_act()); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   bool is_paused() const { return this->paused_; } | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   void draw_buffer_(const lv_area_t *area, const uint8_t *ptr); |   void draw_buffer_(const lv_area_t *area, const uint8_t *ptr); | ||||||
| @@ -107,13 +119,48 @@ class LvglComponent : public PollingComponent { | |||||||
|   lv_disp_draw_buf_t draw_buf_{}; |   lv_disp_draw_buf_t draw_buf_{}; | ||||||
|   lv_disp_drv_t disp_drv_{}; |   lv_disp_drv_t disp_drv_{}; | ||||||
|   lv_disp_t *disp_{}; |   lv_disp_t *disp_{}; | ||||||
|  |   bool paused_{}; | ||||||
|  |  | ||||||
|   std::vector<std::function<void(lv_disp_t *)>> init_lambdas_; |   std::vector<std::function<void(lv_disp_t *)>> init_lambdas_; | ||||||
|   size_t buffer_frac_{1}; |   size_t buffer_frac_{1}; | ||||||
|   bool full_refresh_{}; |   bool full_refresh_{}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | #ifdef USE_LVGL_TOUCHSCREEN | ||||||
|  | class LVTouchListener : public touchscreen::TouchListener, public Parented<LvglComponent> { | ||||||
|  |  public: | ||||||
|  |   LVTouchListener(uint16_t long_press_time, uint16_t long_press_repeat_time) { | ||||||
|  |     lv_indev_drv_init(&this->drv_); | ||||||
|  |     this->drv_.long_press_repeat_time = long_press_repeat_time; | ||||||
|  |     this->drv_.long_press_time = long_press_time; | ||||||
|  |     this->drv_.type = LV_INDEV_TYPE_POINTER; | ||||||
|  |     this->drv_.user_data = this; | ||||||
|  |     this->drv_.read_cb = [](lv_indev_drv_t *d, lv_indev_data_t *data) { | ||||||
|  |       auto *l = static_cast<LVTouchListener *>(d->user_data); | ||||||
|  |       if (l->touch_pressed_) { | ||||||
|  |         data->point.x = l->touch_point_.x; | ||||||
|  |         data->point.y = l->touch_point_.y; | ||||||
|  |         data->state = LV_INDEV_STATE_PRESSED; | ||||||
|  |       } else { | ||||||
|  |         data->state = LV_INDEV_STATE_RELEASED; | ||||||
|  |       } | ||||||
|  |     }; | ||||||
|  |   } | ||||||
|  |   void update(const touchscreen::TouchPoints_t &tpoints) override { | ||||||
|  |     this->touch_pressed_ = !this->parent_->is_paused() && !tpoints.empty(); | ||||||
|  |     if (this->touch_pressed_) | ||||||
|  |       this->touch_point_ = tpoints[0]; | ||||||
|  |   } | ||||||
|  |   void release() override { touch_pressed_ = false; } | ||||||
|  |   lv_indev_drv_t *get_drv() { return &this->drv_; } | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   lv_indev_drv_t drv_{}; | ||||||
|  |   touchscreen::TouchPoint touch_point_{}; | ||||||
|  |   bool touch_pressed_{}; | ||||||
|  | }; | ||||||
|  | #endif  // USE_LVGL_TOUCHSCREEN | ||||||
| }  // namespace lvgl | }  // namespace lvgl | ||||||
| }  // namespace esphome | }  // namespace esphome | ||||||
|  |  | ||||||
| #endif | #endif  // USE_LVGL | ||||||
|   | |||||||
| @@ -1,6 +1,5 @@ | |||||||
| from .defines import CONF_OBJ | from .defines import CONF_MAIN, CONF_OBJ | ||||||
| from .types import lv_obj_t | from .types import WidgetType, lv_obj_t | ||||||
| from .widget import WidgetType |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class ObjType(WidgetType): | class ObjType(WidgetType): | ||||||
| @@ -9,11 +8,7 @@ class ObjType(WidgetType): | |||||||
|     """ |     """ | ||||||
|  |  | ||||||
|     def __init__(self): |     def __init__(self): | ||||||
|         super().__init__(CONF_OBJ, schema={}, modify_schema={}) |         super().__init__(CONF_OBJ, lv_obj_t, (CONF_MAIN,), schema={}, modify_schema={}) | ||||||
|  |  | ||||||
|     @property |  | ||||||
|     def w_type(self): |  | ||||||
|         return lv_obj_t |  | ||||||
|  |  | ||||||
|     async def to_code(self, w, config): |     async def to_code(self, w, config): | ||||||
|         return [] |         return [] | ||||||
|   | |||||||
| @@ -3,15 +3,9 @@ from esphome.const import CONF_ARGS, CONF_FORMAT, CONF_ID, CONF_STATE, CONF_TYPE | |||||||
| from esphome.schema_extractors import SCHEMA_EXTRACT | from esphome.schema_extractors import SCHEMA_EXTRACT | ||||||
|  |  | ||||||
| from . import defines as df, lv_validation as lvalid, types as ty | from . import defines as df, lv_validation as lvalid, types as ty | ||||||
| from .defines import WIDGET_PARTS | from .helpers import add_lv_use, requires_component, validate_printf | ||||||
| from .helpers import ( |  | ||||||
|     REQUIRED_COMPONENTS, |  | ||||||
|     add_lv_use, |  | ||||||
|     requires_component, |  | ||||||
|     validate_printf, |  | ||||||
| ) |  | ||||||
| from .lv_validation import lv_font | from .lv_validation import lv_font | ||||||
| from .types import WIDGET_TYPES, get_widget_type | from .types import WIDGET_TYPES, WidgetType | ||||||
|  |  | ||||||
| # A schema for text properties | # A schema for text properties | ||||||
| TEXT_SCHEMA = cv.Schema( | TEXT_SCHEMA = cv.Schema( | ||||||
| @@ -46,9 +40,9 @@ STYLE_PROPS = { | |||||||
|     "bg_dither_mode": df.LvConstant("LV_DITHER_", "NONE", "ORDERED", "ERR_DIFF").one_of, |     "bg_dither_mode": df.LvConstant("LV_DITHER_", "NONE", "ORDERED", "ERR_DIFF").one_of, | ||||||
|     "bg_grad_dir": df.LvConstant("LV_GRAD_DIR_", "NONE", "HOR", "VER").one_of, |     "bg_grad_dir": df.LvConstant("LV_GRAD_DIR_", "NONE", "HOR", "VER").one_of, | ||||||
|     "bg_grad_stop": lvalid.stop_value, |     "bg_grad_stop": lvalid.stop_value, | ||||||
|     "bg_img_opa": lvalid.opacity, |     "bg_image_opa": lvalid.opacity, | ||||||
|     "bg_img_recolor": lvalid.lv_color, |     "bg_image_recolor": lvalid.lv_color, | ||||||
|     "bg_img_recolor_opa": lvalid.opacity, |     "bg_image_recolor_opa": lvalid.opacity, | ||||||
|     "bg_main_stop": lvalid.stop_value, |     "bg_main_stop": lvalid.stop_value, | ||||||
|     "bg_opa": lvalid.opacity, |     "bg_opa": lvalid.opacity, | ||||||
|     "border_color": lvalid.lv_color, |     "border_color": lvalid.lv_color, | ||||||
| @@ -60,8 +54,8 @@ STYLE_PROPS = { | |||||||
|     "border_width": cv.positive_int, |     "border_width": cv.positive_int, | ||||||
|     "clip_corner": lvalid.lv_bool, |     "clip_corner": lvalid.lv_bool, | ||||||
|     "height": lvalid.size, |     "height": lvalid.size, | ||||||
|     "img_recolor": lvalid.lv_color, |     "image_recolor": lvalid.lv_color, | ||||||
|     "img_recolor_opa": lvalid.opacity, |     "image_recolor_opa": lvalid.opacity, | ||||||
|     "line_width": cv.positive_int, |     "line_width": cv.positive_int, | ||||||
|     "line_dash_width": cv.positive_int, |     "line_dash_width": cv.positive_int, | ||||||
|     "line_dash_gap": cv.positive_int, |     "line_dash_gap": cv.positive_int, | ||||||
| @@ -108,12 +102,21 @@ STYLE_PROPS = { | |||||||
|     "max_width": lvalid.pixels_or_percent, |     "max_width": lvalid.pixels_or_percent, | ||||||
|     "min_height": lvalid.pixels_or_percent, |     "min_height": lvalid.pixels_or_percent, | ||||||
|     "min_width": lvalid.pixels_or_percent, |     "min_width": lvalid.pixels_or_percent, | ||||||
|     "radius": cv.Any(lvalid.size, df.LvConstant("LV_RADIUS_", "CIRCLE").one_of), |     "radius": lvalid.radius, | ||||||
|     "width": lvalid.size, |     "width": lvalid.size, | ||||||
|     "x": lvalid.pixels_or_percent, |     "x": lvalid.pixels_or_percent, | ||||||
|     "y": lvalid.pixels_or_percent, |     "y": lvalid.pixels_or_percent, | ||||||
| } | } | ||||||
|  |  | ||||||
|  | STYLE_REMAP = { | ||||||
|  |     "bg_image_opa": "bg_img_opa", | ||||||
|  |     "bg_image_recolor": "bg_img_recolor", | ||||||
|  |     "bg_image_recolor_opa": "bg_img_recolor_opa", | ||||||
|  |     "bg_image_src": "bg_img_src", | ||||||
|  |     "image_recolor": "img_recolor", | ||||||
|  |     "image_recolor_opa": "img_recolor_opa", | ||||||
|  | } | ||||||
|  |  | ||||||
| # Complete object style schema | # Complete object style schema | ||||||
| STYLE_SCHEMA = cv.Schema({cv.Optional(k): v for k, v in STYLE_PROPS.items()}).extend( | STYLE_SCHEMA = cv.Schema({cv.Optional(k): v for k, v in STYLE_PROPS.items()}).extend( | ||||||
|     { |     { | ||||||
| @@ -132,25 +135,23 @@ SET_STATE_SCHEMA = cv.Schema( | |||||||
|     {cv.Optional(state): lvalid.lv_bool for state in df.STATES} |     {cv.Optional(state): lvalid.lv_bool for state in df.STATES} | ||||||
| ) | ) | ||||||
| # Setting object flags | # Setting object flags | ||||||
| FLAG_SCHEMA = cv.Schema({cv.Optional(flag): cv.boolean for flag in df.OBJ_FLAGS}) | FLAG_SCHEMA = cv.Schema({cv.Optional(flag): lvalid.lv_bool for flag in df.OBJ_FLAGS}) | ||||||
| FLAG_LIST = cv.ensure_list(df.LvConstant("LV_OBJ_FLAG_", *df.OBJ_FLAGS).one_of) | FLAG_LIST = cv.ensure_list(df.LvConstant("LV_OBJ_FLAG_", *df.OBJ_FLAGS).one_of) | ||||||
|  |  | ||||||
|  |  | ||||||
| def part_schema(widget_type): | def part_schema(widget_type: WidgetType): | ||||||
|     """ |     """ | ||||||
|     Generate a schema for the various parts (e.g. main:, indicator:) of a widget type |     Generate a schema for the various parts (e.g. main:, indicator:) of a widget type | ||||||
|     :param widget_type:  The type of widget to generate for |     :param widget_type:  The type of widget to generate for | ||||||
|     :return: |     :return: | ||||||
|     """ |     """ | ||||||
|     parts = WIDGET_PARTS.get(widget_type) |     parts = widget_type.parts | ||||||
|     if parts is None: |  | ||||||
|         parts = (df.CONF_MAIN,) |  | ||||||
|     return cv.Schema({cv.Optional(part): STATE_SCHEMA for part in parts}).extend( |     return cv.Schema({cv.Optional(part): STATE_SCHEMA for part in parts}).extend( | ||||||
|         STATE_SCHEMA |         STATE_SCHEMA | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
| def obj_schema(widget_type: str): | def obj_schema(widget_type: WidgetType): | ||||||
|     """ |     """ | ||||||
|     Create a schema for a widget type itself i.e. no allowance for children |     Create a schema for a widget type itself i.e. no allowance for children | ||||||
|     :param widget_type: |     :param widget_type: | ||||||
| @@ -187,13 +188,12 @@ STYLED_TEXT_SCHEMA = cv.maybe_simple_value( | |||||||
|     STYLE_SCHEMA.extend(TEXT_SCHEMA), key=df.CONF_TEXT |     STYLE_SCHEMA.extend(TEXT_SCHEMA), key=df.CONF_TEXT | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| ALL_STYLES = { | ALL_STYLES = { | ||||||
|     **STYLE_PROPS, |     **STYLE_PROPS, | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| def container_validator(schema, widget_type): | def container_validator(schema, widget_type: WidgetType): | ||||||
|     """ |     """ | ||||||
|     Create a validator for a container given the widget type |     Create a validator for a container given the widget type | ||||||
|     :param schema: Base schema to extend |     :param schema: Base schema to extend | ||||||
| @@ -203,13 +203,16 @@ def container_validator(schema, widget_type): | |||||||
|  |  | ||||||
|     def validator(value): |     def validator(value): | ||||||
|         result = schema |         result = schema | ||||||
|         if w_sch := WIDGET_TYPES[widget_type].schema: |         if w_sch := widget_type.schema: | ||||||
|             result = result.extend(w_sch) |             result = result.extend(w_sch) | ||||||
|         if value and (layout := value.get(df.CONF_LAYOUT)): |         if value and (layout := value.get(df.CONF_LAYOUT)): | ||||||
|             if not isinstance(layout, dict): |             if not isinstance(layout, dict): | ||||||
|                 raise cv.Invalid("Layout value must be a dict") |                 raise cv.Invalid("Layout value must be a dict") | ||||||
|             ltype = layout.get(CONF_TYPE) |             ltype = layout.get(CONF_TYPE) | ||||||
|             add_lv_use(ltype) |             add_lv_use(ltype) | ||||||
|  |         result = result.extend( | ||||||
|  |             {cv.Optional(df.CONF_WIDGETS): cv.ensure_list(any_widget_schema())} | ||||||
|  |         ) | ||||||
|         if value == SCHEMA_EXTRACT: |         if value == SCHEMA_EXTRACT: | ||||||
|             return result |             return result | ||||||
|         return result(value) |         return result(value) | ||||||
| @@ -217,7 +220,7 @@ def container_validator(schema, widget_type): | |||||||
|     return validator |     return validator | ||||||
|  |  | ||||||
|  |  | ||||||
| def container_schema(widget_type, extras=None): | def container_schema(widget_type: WidgetType, extras=None): | ||||||
|     """ |     """ | ||||||
|     Create a schema for a container widget of a given type. All obj properties are available, plus |     Create a schema for a container widget of a given type. All obj properties are available, plus | ||||||
|     the extras passed in, plus any defined for the specific widget being specified. |     the extras passed in, plus any defined for the specific widget being specified. | ||||||
| @@ -225,15 +228,16 @@ def container_schema(widget_type, extras=None): | |||||||
|     :param extras:  Additional options to be made available, e.g. layout properties for children |     :param extras:  Additional options to be made available, e.g. layout properties for children | ||||||
|     :return: The schema for this type of widget. |     :return: The schema for this type of widget. | ||||||
|     """ |     """ | ||||||
|     lv_type = get_widget_type(widget_type) |     schema = obj_schema(widget_type).extend( | ||||||
|     schema = obj_schema(widget_type).extend({cv.GenerateID(): cv.declare_id(lv_type)}) |         {cv.GenerateID(): cv.declare_id(widget_type.w_type)} | ||||||
|  |     ) | ||||||
|     if extras: |     if extras: | ||||||
|         schema = schema.extend(extras) |         schema = schema.extend(extras) | ||||||
|     # Delayed evaluation for recursion |     # Delayed evaluation for recursion | ||||||
|     return container_validator(schema, widget_type) |     return container_validator(schema, widget_type) | ||||||
|  |  | ||||||
|  |  | ||||||
| def widget_schema(widget_type, extras=None): | def widget_schema(widget_type: WidgetType, extras=None): | ||||||
|     """ |     """ | ||||||
|     Create a schema for a given widget type |     Create a schema for a given widget type | ||||||
|     :param widget_type: The name of the widget |     :param widget_type: The name of the widget | ||||||
| @@ -241,9 +245,9 @@ def widget_schema(widget_type, extras=None): | |||||||
|     :return: |     :return: | ||||||
|     """ |     """ | ||||||
|     validator = container_schema(widget_type, extras=extras) |     validator = container_schema(widget_type, extras=extras) | ||||||
|     if required := REQUIRED_COMPONENTS.get(widget_type): |     if required := widget_type.required_component: | ||||||
|         validator = cv.All(validator, requires_component(required)) |         validator = cv.All(validator, requires_component(required)) | ||||||
|     return cv.Exclusive(widget_type, df.CONF_WIDGETS), validator |     return cv.Exclusive(widget_type.name, df.CONF_WIDGETS), validator | ||||||
|  |  | ||||||
|  |  | ||||||
| # All widget schemas must be defined before this is called. | # All widget schemas must be defined before this is called. | ||||||
| @@ -257,4 +261,4 @@ def any_widget_schema(extras=None): | |||||||
|     :param extras: Additional schema to be applied to each generated one |     :param extras: Additional schema to be applied to each generated one | ||||||
|     :return: |     :return: | ||||||
|     """ |     """ | ||||||
|     return cv.Any(dict(widget_schema(wt, extras) for wt in WIDGET_PARTS)) |     return cv.Any(dict(widget_schema(wt, extras) for wt in WIDGET_TYPES.values())) | ||||||
|   | |||||||
							
								
								
									
										46
									
								
								esphome/components/lvgl/touchscreens.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								esphome/components/lvgl/touchscreens.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | import esphome.codegen as cg | ||||||
|  | from esphome.components.touchscreen import CONF_TOUCHSCREEN_ID, Touchscreen | ||||||
|  | import esphome.config_validation as cv | ||||||
|  | from esphome.const import CONF_ID | ||||||
|  | from esphome.core import CORE, TimePeriod | ||||||
|  |  | ||||||
|  | from .defines import ( | ||||||
|  |     CONF_LONG_PRESS_REPEAT_TIME, | ||||||
|  |     CONF_LONG_PRESS_TIME, | ||||||
|  |     CONF_TOUCHSCREENS, | ||||||
|  | ) | ||||||
|  | from .helpers import lvgl_components_required | ||||||
|  | from .lv_validation import lv_milliseconds | ||||||
|  | from .lvcode import lv | ||||||
|  | from .types import LVTouchListener | ||||||
|  |  | ||||||
|  | PRESS_TIME = cv.All(lv_milliseconds, cv.Range(max=TimePeriod(milliseconds=65535))) | ||||||
|  | CONF_TOUCHSCREEN = "touchscreen" | ||||||
|  | TOUCHSCREENS_CONFIG = cv.maybe_simple_value( | ||||||
|  |     { | ||||||
|  |         cv.Required(CONF_TOUCHSCREEN_ID): cv.use_id(Touchscreen), | ||||||
|  |         cv.Optional(CONF_LONG_PRESS_TIME, default="400ms"): PRESS_TIME, | ||||||
|  |         cv.Optional(CONF_LONG_PRESS_REPEAT_TIME, default="100ms"): PRESS_TIME, | ||||||
|  |         cv.GenerateID(): cv.declare_id(LVTouchListener), | ||||||
|  |     }, | ||||||
|  |     key=CONF_TOUCHSCREEN_ID, | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def touchscreen_schema(config): | ||||||
|  |     value = cv.ensure_list(TOUCHSCREENS_CONFIG)(config) | ||||||
|  |     if value or CONF_TOUCHSCREEN not in CORE.loaded_integrations: | ||||||
|  |         return value | ||||||
|  |     return [TOUCHSCREENS_CONFIG(config)] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | async def touchscreens_to_code(var, config): | ||||||
|  |     for tconf in config.get(CONF_TOUCHSCREENS) or (): | ||||||
|  |         lvgl_components_required.add(CONF_TOUCHSCREEN) | ||||||
|  |         touchscreen = await cg.get_variable(tconf[CONF_TOUCHSCREEN_ID]) | ||||||
|  |         lpt = tconf[CONF_LONG_PRESS_TIME].total_milliseconds | ||||||
|  |         lprt = tconf[CONF_LONG_PRESS_REPEAT_TIME].total_milliseconds | ||||||
|  |         listener = cg.new_Pvariable(tconf[CONF_ID], lpt, lprt) | ||||||
|  |         await cg.register_parented(listener, var) | ||||||
|  |         lv.indev_drv_register(listener.get_drv()) | ||||||
|  |         cg.add(touchscreen.register_listener(listener)) | ||||||
| @@ -1,7 +1,22 @@ | |||||||
| from esphome import codegen as cg | from esphome import codegen as cg | ||||||
| from esphome.core import ID | from esphome.core import ID | ||||||
|  | from esphome.cpp_generator import MockObjClass | ||||||
|  |  | ||||||
|  | from .defines import CONF_TEXT | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class LvType(cg.MockObjClass): | ||||||
|  |     def __init__(self, *args, **kwargs): | ||||||
|  |         parens = kwargs.pop("parents", ()) | ||||||
|  |         super().__init__(*args, parents=parens + (lv_obj_base_t,)) | ||||||
|  |         self.args = kwargs.pop("largs", [(lv_obj_t_ptr, "obj")]) | ||||||
|  |         self.value = kwargs.pop("lvalue", lambda w: w.obj) | ||||||
|  |         self.has_on_value = kwargs.pop("has_on_value", False) | ||||||
|  |         self.value_property = None | ||||||
|  |  | ||||||
|  |     def get_arg_type(self): | ||||||
|  |         return self.args[0][0] if len(self.args) else None | ||||||
|  |  | ||||||
| from .defines import CONF_LABEL, CONF_OBJ, CONF_TEXT |  | ||||||
|  |  | ||||||
| uint16_t_ptr = cg.uint16.operator("ptr") | uint16_t_ptr = cg.uint16.operator("ptr") | ||||||
| lvgl_ns = cg.esphome_ns.namespace("lvgl") | lvgl_ns = cg.esphome_ns.namespace("lvgl") | ||||||
| @@ -18,25 +33,15 @@ lv_obj_base_t = cg.global_ns.class_("lv_obj_t", lv_pseudo_button_t) | |||||||
| lv_obj_t_ptr = lv_obj_base_t.operator("ptr") | lv_obj_t_ptr = lv_obj_base_t.operator("ptr") | ||||||
| lv_disp_t_ptr = cg.global_ns.struct("lv_disp_t").operator("ptr") | lv_disp_t_ptr = cg.global_ns.struct("lv_disp_t").operator("ptr") | ||||||
| lv_color_t = cg.global_ns.struct("lv_color_t") | lv_color_t = cg.global_ns.struct("lv_color_t") | ||||||
|  | LVTouchListener = lvgl_ns.class_("LVTouchListener") | ||||||
|  | LVEncoderListener = lvgl_ns.class_("LVEncoderListener") | ||||||
|  | lv_obj_t = LvType("lv_obj_t") | ||||||
|  |  | ||||||
|  |  | ||||||
| # this will be populated later, in __init__.py to avoid circular imports. | # this will be populated later, in __init__.py to avoid circular imports. | ||||||
| WIDGET_TYPES: dict = {} | WIDGET_TYPES: dict = {} | ||||||
|  |  | ||||||
|  |  | ||||||
| class LvType(cg.MockObjClass): |  | ||||||
|     def __init__(self, *args, **kwargs): |  | ||||||
|         parens = kwargs.pop("parents", ()) |  | ||||||
|         super().__init__(*args, parents=parens + (lv_obj_base_t,)) |  | ||||||
|         self.args = kwargs.pop("largs", [(lv_obj_t_ptr, "obj")]) |  | ||||||
|         self.value = kwargs.pop("lvalue", lambda w: w.obj) |  | ||||||
|         self.has_on_value = kwargs.pop("has_on_value", False) |  | ||||||
|         self.value_property = None |  | ||||||
|  |  | ||||||
|     def get_arg_type(self): |  | ||||||
|         return self.args[0][0] if len(self.args) else None |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class LvText(LvType): | class LvText(LvType): | ||||||
|     def __init__(self, *args, **kwargs): |     def __init__(self, *args, **kwargs): | ||||||
|         super().__init__( |         super().__init__( | ||||||
| @@ -48,17 +53,74 @@ class LvText(LvType): | |||||||
|         self.value_property = CONF_TEXT |         self.value_property = CONF_TEXT | ||||||
|  |  | ||||||
|  |  | ||||||
| lv_obj_t = LvType("lv_obj_t") | class LvBoolean(LvType): | ||||||
| lv_label_t = LvText("lv_label_t") |     def __init__(self, *args, **kwargs): | ||||||
|  |         super().__init__( | ||||||
| LV_TYPES = { |             *args, | ||||||
|     CONF_LABEL: lv_label_t, |             largs=[(cg.bool_, "x")], | ||||||
|     CONF_OBJ: lv_obj_t, |             lvalue=lambda w: w.is_checked(), | ||||||
| } |             has_on_value=True, | ||||||
|  |             **kwargs, | ||||||
|  |         ) | ||||||
| def get_widget_type(typestr: str) -> LvType: |  | ||||||
|     return LV_TYPES[typestr] |  | ||||||
|  |  | ||||||
|  |  | ||||||
| CUSTOM_EVENT = ID("lv_custom_event", False, type=lv_event_code_t) | CUSTOM_EVENT = ID("lv_custom_event", False, type=lv_event_code_t) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class WidgetType: | ||||||
|  |     """ | ||||||
|  |     Describes a type of Widget, e.g. "bar" or "line" | ||||||
|  |     """ | ||||||
|  |  | ||||||
|  |     def __init__(self, name, w_type, parts, schema=None, modify_schema=None): | ||||||
|  |         """ | ||||||
|  |         :param name: The widget name, e.g. "bar" | ||||||
|  |         :param w_type: The C type of the widget | ||||||
|  |         :param parts: What parts this widget supports | ||||||
|  |         :param schema: The config schema for defining a widget | ||||||
|  |         :param modify_schema: A schema to update the widget | ||||||
|  |         """ | ||||||
|  |         self.name = name | ||||||
|  |         self.w_type = w_type | ||||||
|  |         self.parts = parts | ||||||
|  |         self.schema = schema or {} | ||||||
|  |         if modify_schema is None: | ||||||
|  |             self.modify_schema = schema | ||||||
|  |         else: | ||||||
|  |             self.modify_schema = modify_schema | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def animated(self): | ||||||
|  |         return False | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def required_component(self): | ||||||
|  |         return None | ||||||
|  |  | ||||||
|  |     def is_compound(self): | ||||||
|  |         return self.w_type.inherits_from(LvCompound) | ||||||
|  |  | ||||||
|  |     async def to_code(self, w, config: dict): | ||||||
|  |         """ | ||||||
|  |         Generate code for a given widget | ||||||
|  |         :param w: The widget | ||||||
|  |         :param config: Its configuration | ||||||
|  |         :return: Generated code as a list of text lines | ||||||
|  |         """ | ||||||
|  |         raise NotImplementedError(f"No to_code defined for {self.name}") | ||||||
|  |  | ||||||
|  |     def obj_creator(self, parent: MockObjClass, config: dict): | ||||||
|  |         """ | ||||||
|  |         Create an instance of the widget type | ||||||
|  |         :param parent: The parent to which it should be attached | ||||||
|  |         :param config:  Its configuration | ||||||
|  |         :return: Generated code as a single text line | ||||||
|  |         """ | ||||||
|  |         return f"lv_{self.name}_create({parent})" | ||||||
|  |  | ||||||
|  |     def get_uses(self): | ||||||
|  |         """ | ||||||
|  |         Get a list of other widgets used by this one | ||||||
|  |         :return: | ||||||
|  |         """ | ||||||
|  |         return () | ||||||
|   | |||||||
| @@ -21,78 +21,19 @@ from .defines import ( | |||||||
| ) | ) | ||||||
| from .helpers import add_lv_use | from .helpers import add_lv_use | ||||||
| from .lvcode import ConstantLiteral, add_line_marks, lv, lv_add, lv_assign, lv_obj | from .lvcode import ConstantLiteral, add_line_marks, lv, lv_add, lv_assign, lv_obj | ||||||
| from .schemas import ALL_STYLES | from .schemas import ALL_STYLES, STYLE_REMAP | ||||||
| from .types import WIDGET_TYPES, LvCompound, lv_obj_t | from .types import WIDGET_TYPES, WidgetType, lv_obj_t | ||||||
|  |  | ||||||
| EVENT_LAMB = "event_lamb__" | EVENT_LAMB = "event_lamb__" | ||||||
|  |  | ||||||
|  |  | ||||||
| class WidgetType: |  | ||||||
|     """ |  | ||||||
|     Describes a type of Widget, e.g. "bar" or "line" |  | ||||||
|     """ |  | ||||||
|  |  | ||||||
|     def __init__(self, name, schema=None, modify_schema=None): |  | ||||||
|         """ |  | ||||||
|         :param name: The widget name, e.g. "bar" |  | ||||||
|         :param schema: The config schema for defining a widget |  | ||||||
|         :param modify_schema: A schema to update the widget |  | ||||||
|         """ |  | ||||||
|         self.name = name |  | ||||||
|         self.schema = schema or {} |  | ||||||
|         if modify_schema is None: |  | ||||||
|             self.modify_schema = schema |  | ||||||
|         else: |  | ||||||
|             self.modify_schema = modify_schema |  | ||||||
|  |  | ||||||
|     @property |  | ||||||
|     def animated(self): |  | ||||||
|         return False |  | ||||||
|  |  | ||||||
|     @property |  | ||||||
|     def w_type(self): |  | ||||||
|         """ |  | ||||||
|         Get the type associated with this widget |  | ||||||
|         :return: |  | ||||||
|         """ |  | ||||||
|         return lv_obj_t |  | ||||||
|  |  | ||||||
|     def is_compound(self): |  | ||||||
|         return self.w_type.inherits_from(LvCompound) |  | ||||||
|  |  | ||||||
|     async def to_code(self, w, config: dict): |  | ||||||
|         """ |  | ||||||
|         Generate code for a given widget |  | ||||||
|         :param w: The widget |  | ||||||
|         :param config: Its configuration |  | ||||||
|         :return: Generated code as a list of text lines |  | ||||||
|         """ |  | ||||||
|         raise NotImplementedError(f"No to_code defined for {self.name}") |  | ||||||
|  |  | ||||||
|     def obj_creator(self, parent: MockObjClass, config: dict): |  | ||||||
|         """ |  | ||||||
|         Create an instance of the widget type |  | ||||||
|         :param parent: The parent to which it should be attached |  | ||||||
|         :param config:  Its configuration |  | ||||||
|         :return: Generated code as a single text line |  | ||||||
|         """ |  | ||||||
|         return f"lv_{self.name}_create({parent})" |  | ||||||
|  |  | ||||||
|     def get_uses(self): |  | ||||||
|         """ |  | ||||||
|         Get a list of other widgets used by this one |  | ||||||
|         :return: |  | ||||||
|         """ |  | ||||||
|         return () |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class LvScrActType(WidgetType): | class LvScrActType(WidgetType): | ||||||
|     """ |     """ | ||||||
|     A "widget" representing the active screen. |     A "widget" representing the active screen. | ||||||
|     """ |     """ | ||||||
|  |  | ||||||
|     def __init__(self): |     def __init__(self): | ||||||
|         super().__init__("lv_scr_act()") |         super().__init__("lv_scr_act()", lv_obj_t, ()) | ||||||
|  |  | ||||||
|     def obj_creator(self, parent: MockObjClass, config: dict): |     def obj_creator(self, parent: MockObjClass, config: dict): | ||||||
|         return [] |         return [] | ||||||
| @@ -263,7 +204,9 @@ async def set_obj_properties(w: Widget, config): | |||||||
|             }.items(): |             }.items(): | ||||||
|                 if isinstance(ALL_STYLES[prop], LValidator): |                 if isinstance(ALL_STYLES[prop], LValidator): | ||||||
|                     value = await ALL_STYLES[prop].process(value) |                     value = await ALL_STYLES[prop].process(value) | ||||||
|                 w.set_style(prop, value, lv_state) |                     # Remapping for backwards compatibility of style names | ||||||
|  |                 prop_r = STYLE_REMAP.get(prop, prop) | ||||||
|  |                 w.set_style(prop_r, value, lv_state) | ||||||
|     flag_clr = set() |     flag_clr = set() | ||||||
|     flag_set = set() |     flag_set = set() | ||||||
|     props = parts[CONF_MAIN][CONF_DEFAULT] |     props = parts[CONF_MAIN][CONF_DEFAULT] | ||||||
| @@ -291,10 +234,10 @@ async def set_obj_properties(w: Widget, config): | |||||||
|             else: |             else: | ||||||
|                 clears.add(key) |                 clears.add(key) | ||||||
|         if adds: |         if adds: | ||||||
|             adds = ConstantLiteral(join_enums(adds, "LV_STATE_")) |             adds = join_enums(adds, "LV_STATE_") | ||||||
|             w.add_state(adds) |             w.add_state(adds) | ||||||
|         if clears: |         if clears: | ||||||
|             clears = ConstantLiteral(join_enums(clears, "LV_STATE_")) |             clears = join_enums(clears, "LV_STATE_") | ||||||
|             w.clear_state(clears) |             w.clear_state(clears) | ||||||
|         for key, value in lambs.items(): |         for key, value in lambs.items(): | ||||||
|             lamb = await cg.process_lambda(value, [], return_type=cg.bool_) |             lamb = await cg.process_lambda(value, [], return_type=cg.bool_) | ||||||
|   | |||||||
| @@ -110,7 +110,7 @@ void MitsubishiClimate::transmit_state() { | |||||||
|   // Byte 15: HVAC specfic, i.e. POWERFUL, SMART SET, PLASMA, always 0x00 |   // Byte 15: HVAC specfic, i.e. POWERFUL, SMART SET, PLASMA, always 0x00 | ||||||
|   // Byte 16: Constant 0x00 |   // Byte 16: Constant 0x00 | ||||||
|   // Byte 17: Checksum: SUM[Byte0...Byte16] |   // Byte 17: Checksum: SUM[Byte0...Byte16] | ||||||
|   uint8_t remote_state[18] = {0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x08, 0x00, 0x00, |   uint8_t remote_state[18] = {0x23, 0xCB, 0x26, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, | ||||||
|                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | ||||||
|  |  | ||||||
|   switch (this->mode) { |   switch (this->mode) { | ||||||
| @@ -136,6 +136,12 @@ void MitsubishiClimate::transmit_state() { | |||||||
|       break; |       break; | ||||||
|     case climate::CLIMATE_MODE_OFF: |     case climate::CLIMATE_MODE_OFF: | ||||||
|     default: |     default: | ||||||
|  |       remote_state[6] = MITSUBISHI_MODE_COOL; | ||||||
|  |       remote_state[8] = MITSUBISHI_MODE_A_COOL; | ||||||
|  |       if (this->supports_heat_) { | ||||||
|  |         remote_state[6] = MITSUBISHI_MODE_HEAT; | ||||||
|  |         remote_state[8] = MITSUBISHI_MODE_A_HEAT; | ||||||
|  |       } | ||||||
|       remote_state[5] = MITSUBISHI_OFF; |       remote_state[5] = MITSUBISHI_OFF; | ||||||
|       break; |       break; | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -1,10 +1,15 @@ | |||||||
|  | from esphome import automation | ||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome import automation | from esphome.const import ( | ||||||
|  |     CONF_ESPHOME, | ||||||
|  |     CONF_ON_ERROR, | ||||||
|  |     CONF_OTA, | ||||||
|  |     CONF_PLATFORM, | ||||||
|  |     CONF_TRIGGER_ID, | ||||||
|  | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, coroutine_with_priority | ||||||
|  |  | ||||||
| from esphome.const import CONF_ESPHOME, CONF_OTA, CONF_PLATFORM, CONF_TRIGGER_ID |  | ||||||
|  |  | ||||||
| CODEOWNERS = ["@esphome/core"] | CODEOWNERS = ["@esphome/core"] | ||||||
| AUTO_LOAD = ["md5", "safe_mode"] | AUTO_LOAD = ["md5", "safe_mode"] | ||||||
|  |  | ||||||
| @@ -13,7 +18,6 @@ IS_PLATFORM_COMPONENT = True | |||||||
| CONF_ON_ABORT = "on_abort" | CONF_ON_ABORT = "on_abort" | ||||||
| CONF_ON_BEGIN = "on_begin" | CONF_ON_BEGIN = "on_begin" | ||||||
| CONF_ON_END = "on_end" | CONF_ON_END = "on_end" | ||||||
| CONF_ON_ERROR = "on_error" |  | ||||||
| CONF_ON_PROGRESS = "on_progress" | CONF_ON_PROGRESS = "on_progress" | ||||||
| CONF_ON_STATE_CHANGE = "on_state_change" | CONF_ON_STATE_CHANGE = "on_state_change" | ||||||
|  |  | ||||||
|   | |||||||
| @@ -44,6 +44,8 @@ class PIDClimate : public climate::Climate, public Component { | |||||||
|   float get_kp() { return controller_.kp_; } |   float get_kp() { return controller_.kp_; } | ||||||
|   float get_ki() { return controller_.ki_; } |   float get_ki() { return controller_.ki_; } | ||||||
|   float get_kd() { return controller_.kd_; } |   float get_kd() { return controller_.kd_; } | ||||||
|  |   float get_min_integral() { return controller_.min_integral_; } | ||||||
|  |   float get_max_integral() { return controller_.max_integral_; } | ||||||
|   float get_proportional_term() const { return controller_.proportional_term_; } |   float get_proportional_term() const { return controller_.proportional_term_; } | ||||||
|   float get_integral_term() const { return controller_.integral_term_; } |   float get_integral_term() const { return controller_.integral_term_; } | ||||||
|   float get_derivative_term() const { return controller_.derivative_term_; } |   float get_derivative_term() const { return controller_.derivative_term_; } | ||||||
|   | |||||||
| @@ -1,10 +1,9 @@ | |||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| import esphome.config_validation as cv |  | ||||||
|  |  | ||||||
| from esphome.components import binary_sensor, display | from esphome.components import binary_sensor, display | ||||||
| from esphome.const import CONF_PAGE_ID | import esphome.config_validation as cv | ||||||
|  | from esphome.const import CONF_PAGE_ID, CONF_PAGES | ||||||
|  |  | ||||||
| from .. import touchscreen_ns, CONF_TOUCHSCREEN_ID, Touchscreen, TouchListener | from .. import CONF_TOUCHSCREEN_ID, TouchListener, Touchscreen, touchscreen_ns | ||||||
|  |  | ||||||
| DEPENDENCIES = ["touchscreen"] | DEPENDENCIES = ["touchscreen"] | ||||||
|  |  | ||||||
| @@ -22,7 +21,7 @@ CONF_Y_MIN = "y_min" | |||||||
| CONF_Y_MAX = "y_max" | CONF_Y_MAX = "y_max" | ||||||
|  |  | ||||||
|  |  | ||||||
| def validate_coords(config): | def _validate_coords(config): | ||||||
|     if ( |     if ( | ||||||
|         config[CONF_X_MAX] < config[CONF_X_MIN] |         config[CONF_X_MAX] < config[CONF_X_MIN] | ||||||
|         or config[CONF_Y_MAX] < config[CONF_Y_MIN] |         or config[CONF_Y_MAX] < config[CONF_Y_MIN] | ||||||
| @@ -33,6 +32,15 @@ def validate_coords(config): | |||||||
|     return config |     return config | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def _set_pages(config: dict) -> dict: | ||||||
|  |     if CONF_PAGES in config or CONF_PAGE_ID not in config: | ||||||
|  |         return config | ||||||
|  |  | ||||||
|  |     config = config.copy() | ||||||
|  |     config[CONF_PAGES] = [config.pop(CONF_PAGE_ID)] | ||||||
|  |     return config | ||||||
|  |  | ||||||
|  |  | ||||||
| CONFIG_SCHEMA = cv.All( | CONFIG_SCHEMA = cv.All( | ||||||
|     binary_sensor.binary_sensor_schema(TouchscreenBinarySensor) |     binary_sensor.binary_sensor_schema(TouchscreenBinarySensor) | ||||||
|     .extend( |     .extend( | ||||||
| @@ -42,11 +50,17 @@ CONFIG_SCHEMA = cv.All( | |||||||
|             cv.Required(CONF_X_MAX): cv.int_range(min=0, max=2000), |             cv.Required(CONF_X_MAX): cv.int_range(min=0, max=2000), | ||||||
|             cv.Required(CONF_Y_MIN): cv.int_range(min=0, max=2000), |             cv.Required(CONF_Y_MIN): cv.int_range(min=0, max=2000), | ||||||
|             cv.Required(CONF_Y_MAX): cv.int_range(min=0, max=2000), |             cv.Required(CONF_Y_MAX): cv.int_range(min=0, max=2000), | ||||||
|             cv.Optional(CONF_PAGE_ID): cv.use_id(display.DisplayPage), |             cv.Exclusive(CONF_PAGE_ID, group_of_exclusion=CONF_PAGES): cv.use_id( | ||||||
|  |                 display.DisplayPage | ||||||
|  |             ), | ||||||
|  |             cv.Exclusive(CONF_PAGES, group_of_exclusion=CONF_PAGES): cv.ensure_list( | ||||||
|  |                 cv.use_id(display.DisplayPage) | ||||||
|  |             ), | ||||||
|         } |         } | ||||||
|     ) |     ) | ||||||
|     .extend(cv.COMPONENT_SCHEMA), |     .extend(cv.COMPONENT_SCHEMA), | ||||||
|     validate_coords, |     _validate_coords, | ||||||
|  |     _set_pages, | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -64,6 +78,6 @@ async def to_code(config): | |||||||
|         ) |         ) | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     if CONF_PAGE_ID in config: |     for page_id in config.get(CONF_PAGES, []): | ||||||
|         page = await cg.get_variable(config[CONF_PAGE_ID]) |         page = await cg.get_variable(page_id) | ||||||
|         cg.add(var.set_page(page)) |         cg.add(var.add_page(page)) | ||||||
|   | |||||||
| @@ -11,8 +11,9 @@ void TouchscreenBinarySensor::setup() { | |||||||
| void TouchscreenBinarySensor::touch(TouchPoint tp) { | void TouchscreenBinarySensor::touch(TouchPoint tp) { | ||||||
|   bool touched = (tp.x >= this->x_min_ && tp.x <= this->x_max_ && tp.y >= this->y_min_ && tp.y <= this->y_max_); |   bool touched = (tp.x >= this->x_min_ && tp.x <= this->x_max_ && tp.y >= this->y_min_ && tp.y <= this->y_max_); | ||||||
|  |  | ||||||
|   if (this->page_ != nullptr) { |   if (!this->pages_.empty()) { | ||||||
|     touched &= this->page_ == this->parent_->get_display()->get_active_page(); |     auto *current_page = this->parent_->get_display()->get_active_page(); | ||||||
|  |     touched &= std::find(this->pages_.begin(), this->pages_.end(), current_page) != this->pages_.end(); | ||||||
|   } |   } | ||||||
|   if (touched) { |   if (touched) { | ||||||
|     this->publish_state(true); |     this->publish_state(true); | ||||||
|   | |||||||
| @@ -6,6 +6,8 @@ | |||||||
| #include "esphome/core/component.h" | #include "esphome/core/component.h" | ||||||
| #include "esphome/core/helpers.h" | #include "esphome/core/helpers.h" | ||||||
|  |  | ||||||
|  | #include <vector> | ||||||
|  |  | ||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace touchscreen { | namespace touchscreen { | ||||||
|  |  | ||||||
| @@ -30,14 +32,14 @@ class TouchscreenBinarySensor : public binary_sensor::BinarySensor, | |||||||
|   int16_t get_width() { return this->x_max_ - this->x_min_; } |   int16_t get_width() { return this->x_max_ - this->x_min_; } | ||||||
|   int16_t get_height() { return this->y_max_ - this->y_min_; } |   int16_t get_height() { return this->y_max_ - this->y_min_; } | ||||||
|  |  | ||||||
|   void set_page(display::DisplayPage *page) { this->page_ = page; } |   void add_page(display::DisplayPage *page) { this->pages_.push_back(page); } | ||||||
|  |  | ||||||
|   void touch(TouchPoint tp) override; |   void touch(TouchPoint tp) override; | ||||||
|   void release() override; |   void release() override; | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   int16_t x_min_, x_max_, y_min_, y_max_; |   int16_t x_min_, x_max_, y_min_, y_max_; | ||||||
|   display::DisplayPage *page_{nullptr}; |   std::vector<display::DisplayPage *> pages_{}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| }  // namespace touchscreen | }  // namespace touchscreen | ||||||
|   | |||||||
| @@ -1,18 +1,18 @@ | |||||||
| import esphome.config_validation as cv |  | ||||||
| import esphome.codegen as cg |  | ||||||
|  |  | ||||||
| from esphome.const import ( |  | ||||||
|     CONF_ID, |  | ||||||
|     CONF_MICROPHONE, |  | ||||||
|     CONF_SPEAKER, |  | ||||||
|     CONF_MEDIA_PLAYER, |  | ||||||
|     CONF_ON_CLIENT_CONNECTED, |  | ||||||
|     CONF_ON_CLIENT_DISCONNECTED, |  | ||||||
|     CONF_ON_IDLE, |  | ||||||
| ) |  | ||||||
| from esphome import automation | from esphome import automation | ||||||
| from esphome.automation import register_action, register_condition | from esphome.automation import register_action, register_condition | ||||||
| from esphome.components import microphone, speaker, media_player | import esphome.codegen as cg | ||||||
|  | from esphome.components import media_player, microphone, speaker | ||||||
|  | import esphome.config_validation as cv | ||||||
|  | from esphome.const import ( | ||||||
|  |     CONF_ID, | ||||||
|  |     CONF_MEDIA_PLAYER, | ||||||
|  |     CONF_MICROPHONE, | ||||||
|  |     CONF_ON_CLIENT_CONNECTED, | ||||||
|  |     CONF_ON_CLIENT_DISCONNECTED, | ||||||
|  |     CONF_ON_ERROR, | ||||||
|  |     CONF_ON_IDLE, | ||||||
|  |     CONF_SPEAKER, | ||||||
|  | ) | ||||||
|  |  | ||||||
| AUTO_LOAD = ["socket"] | AUTO_LOAD = ["socket"] | ||||||
| DEPENDENCIES = ["api", "microphone"] | DEPENDENCIES = ["api", "microphone"] | ||||||
| @@ -20,7 +20,6 @@ DEPENDENCIES = ["api", "microphone"] | |||||||
| CODEOWNERS = ["@jesserockz"] | CODEOWNERS = ["@jesserockz"] | ||||||
|  |  | ||||||
| CONF_ON_END = "on_end" | CONF_ON_END = "on_end" | ||||||
| CONF_ON_ERROR = "on_error" |  | ||||||
| CONF_ON_INTENT_END = "on_intent_end" | CONF_ON_INTENT_END = "on_intent_end" | ||||||
| CONF_ON_INTENT_START = "on_intent_start" | CONF_ON_INTENT_START = "on_intent_start" | ||||||
| CONF_ON_LISTENING = "on_listening" | CONF_ON_LISTENING = "on_listening" | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								esphome/components/watchdog/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								esphome/components/watchdog/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | CODEOWNERS = ["@oarcher"] | ||||||
| @@ -15,7 +15,6 @@ | |||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace http_request { |  | ||||||
| namespace watchdog { | namespace watchdog { | ||||||
| 
 | 
 | ||||||
| static const char *const TAG = "http_request.watchdog"; | static const char *const TAG = "http_request.watchdog"; | ||||||
| @@ -72,5 +71,4 @@ uint32_t WatchdogManager::get_timeout_() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| }  // namespace watchdog
 | }  // namespace watchdog
 | ||||||
| }  // namespace http_request
 |  | ||||||
| }  // namespace esphome
 | }  // namespace esphome
 | ||||||
| @@ -5,7 +5,6 @@ | |||||||
| #include <cstdint> | #include <cstdint> | ||||||
| 
 | 
 | ||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace http_request { |  | ||||||
| namespace watchdog { | namespace watchdog { | ||||||
| 
 | 
 | ||||||
| class WatchdogManager { | class WatchdogManager { | ||||||
| @@ -22,5 +21,4 @@ class WatchdogManager { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| }  // namespace watchdog
 | }  // namespace watchdog
 | ||||||
| }  // namespace http_request
 |  | ||||||
| }  // namespace esphome
 | }  // namespace esphome
 | ||||||
| @@ -1,15 +1,19 @@ | |||||||
| import esphome.codegen as cg |  | ||||||
| import esphome.config_validation as cv |  | ||||||
| import esphome.final_validate as fv |  | ||||||
| from esphome import automation | from esphome import automation | ||||||
| from esphome.automation import Condition | from esphome.automation import Condition | ||||||
|  | import esphome.codegen as cg | ||||||
|  | from esphome.components.esp32 import add_idf_sdkconfig_option, const, get_esp32_variant | ||||||
|  | from esphome.components.network import IPAddress | ||||||
|  | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_AP, |     CONF_AP, | ||||||
|     CONF_BSSID, |     CONF_BSSID, | ||||||
|  |     CONF_CERTIFICATE, | ||||||
|  |     CONF_CERTIFICATE_AUTHORITY, | ||||||
|     CONF_CHANNEL, |     CONF_CHANNEL, | ||||||
|     CONF_DNS1, |     CONF_DNS1, | ||||||
|     CONF_DNS2, |     CONF_DNS2, | ||||||
|     CONF_DOMAIN, |     CONF_DOMAIN, | ||||||
|  |     CONF_EAP, | ||||||
|     CONF_ENABLE_BTM, |     CONF_ENABLE_BTM, | ||||||
|     CONF_ENABLE_ON_BOOT, |     CONF_ENABLE_ON_BOOT, | ||||||
|     CONF_ENABLE_RRM, |     CONF_ENABLE_RRM, | ||||||
| @@ -17,29 +21,26 @@ from esphome.const import ( | |||||||
|     CONF_GATEWAY, |     CONF_GATEWAY, | ||||||
|     CONF_HIDDEN, |     CONF_HIDDEN, | ||||||
|     CONF_ID, |     CONF_ID, | ||||||
|  |     CONF_IDENTITY, | ||||||
|  |     CONF_KEY, | ||||||
|     CONF_MANUAL_IP, |     CONF_MANUAL_IP, | ||||||
|     CONF_NETWORKS, |     CONF_NETWORKS, | ||||||
|  |     CONF_ON_CONNECT, | ||||||
|  |     CONF_ON_DISCONNECT, | ||||||
|     CONF_PASSWORD, |     CONF_PASSWORD, | ||||||
|     CONF_POWER_SAVE_MODE, |     CONF_POWER_SAVE_MODE, | ||||||
|  |     CONF_PRIORITY, | ||||||
|     CONF_REBOOT_TIMEOUT, |     CONF_REBOOT_TIMEOUT, | ||||||
|     CONF_SSID, |     CONF_SSID, | ||||||
|     CONF_STATIC_IP, |     CONF_STATIC_IP, | ||||||
|     CONF_SUBNET, |     CONF_SUBNET, | ||||||
|     CONF_USE_ADDRESS, |  | ||||||
|     CONF_PRIORITY, |  | ||||||
|     CONF_IDENTITY, |  | ||||||
|     CONF_CERTIFICATE_AUTHORITY, |  | ||||||
|     CONF_CERTIFICATE, |  | ||||||
|     CONF_KEY, |  | ||||||
|     CONF_USERNAME, |  | ||||||
|     CONF_EAP, |  | ||||||
|     CONF_TTLS_PHASE_2, |     CONF_TTLS_PHASE_2, | ||||||
|     CONF_ON_CONNECT, |     CONF_USE_ADDRESS, | ||||||
|     CONF_ON_DISCONNECT, |     CONF_USERNAME, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, HexInt, coroutine_with_priority | from esphome.core import CORE, HexInt, coroutine_with_priority | ||||||
| from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant, const | import esphome.final_validate as fv | ||||||
| from esphome.components.network import IPAddress |  | ||||||
| from . import wpa2_eap | from . import wpa2_eap | ||||||
|  |  | ||||||
| AUTO_LOAD = ["network"] | AUTO_LOAD = ["network"] | ||||||
|   | |||||||
| @@ -7,16 +7,15 @@ so that it doesn't crash if it's not installed. | |||||||
| import logging | import logging | ||||||
| from pathlib import Path | from pathlib import Path | ||||||
|  |  | ||||||
| from esphome.core import CORE |  | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_USERNAME, |  | ||||||
|     CONF_IDENTITY, |  | ||||||
|     CONF_PASSWORD, |  | ||||||
|     CONF_CERTIFICATE, |     CONF_CERTIFICATE, | ||||||
|  |     CONF_IDENTITY, | ||||||
|     CONF_KEY, |     CONF_KEY, | ||||||
|  |     CONF_PASSWORD, | ||||||
|  |     CONF_USERNAME, | ||||||
| ) | ) | ||||||
|  | from esphome.core import CORE | ||||||
|  |  | ||||||
| _LOGGER = logging.getLogger(__name__) | _LOGGER = logging.getLogger(__name__) | ||||||
|  |  | ||||||
| @@ -49,8 +48,8 @@ def wrapped_load_pem_x509_certificate(value): | |||||||
| def wrapped_load_pem_private_key(value, password): | def wrapped_load_pem_private_key(value, password): | ||||||
|     validate_cryptography_installed() |     validate_cryptography_installed() | ||||||
|  |  | ||||||
|     from cryptography.hazmat.primitives.serialization import load_pem_private_key |  | ||||||
|     from cryptography.hazmat.backends import default_backend |     from cryptography.hazmat.backends import default_backend | ||||||
|  |     from cryptography.hazmat.primitives.serialization import load_pem_private_key | ||||||
|  |  | ||||||
|     if password: |     if password: | ||||||
|         password = password.encode("UTF-8") |         password = password.encode("UTF-8") | ||||||
| @@ -91,7 +90,7 @@ def _validate_load_private_key(key, cert_pw): | |||||||
|  |  | ||||||
|  |  | ||||||
| def _check_private_key_cert_match(key, cert): | def _check_private_key_cert_match(key, cert): | ||||||
|     from cryptography.hazmat.primitives.asymmetric import rsa, ec |     from cryptography.hazmat.primitives.asymmetric import ec, rsa | ||||||
|  |  | ||||||
|     def check_match_a(): |     def check_match_a(): | ||||||
|         return key.public_key().public_numbers() == cert.public_key().public_numbers() |         return key.public_key().public_numbers() == cert.public_key().public_numbers() | ||||||
|   | |||||||
| @@ -1,13 +1,13 @@ | |||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| import esphome.config_validation as cv |  | ||||||
| from esphome.components import text_sensor | from esphome.components import text_sensor | ||||||
|  | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_BSSID, |     CONF_BSSID, | ||||||
|  |     CONF_DNS_ADDRESS, | ||||||
|     CONF_IP_ADDRESS, |     CONF_IP_ADDRESS, | ||||||
|  |     CONF_MAC_ADDRESS, | ||||||
|     CONF_SCAN_RESULTS, |     CONF_SCAN_RESULTS, | ||||||
|     CONF_SSID, |     CONF_SSID, | ||||||
|     CONF_MAC_ADDRESS, |  | ||||||
|     CONF_DNS_ADDRESS, |  | ||||||
|     ENTITY_CATEGORY_DIAGNOSTIC, |     ENTITY_CATEGORY_DIAGNOSTIC, | ||||||
| ) | ) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| import esphome.config_validation as cv |  | ||||||
| from esphome.components import sensor | from esphome.components import sensor | ||||||
|  | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     DEVICE_CLASS_SIGNAL_STRENGTH, |     DEVICE_CLASS_SIGNAL_STRENGTH, | ||||||
|     ENTITY_CATEGORY_DIAGNOSTIC, |     ENTITY_CATEGORY_DIAGNOSTIC, | ||||||
|   | |||||||
| @@ -1,40 +1,38 @@ | |||||||
| from __future__ import annotations | from __future__ import annotations | ||||||
|  |  | ||||||
| import abc | import abc | ||||||
|  | from contextlib import contextmanager | ||||||
|  | import contextvars | ||||||
| import functools | import functools | ||||||
| import heapq | import heapq | ||||||
| import logging | import logging | ||||||
| import re | import re | ||||||
|  | from typing import Any, Union | ||||||
| from typing import Union, Any |  | ||||||
|  |  | ||||||
| from contextlib import contextmanager |  | ||||||
| import contextvars |  | ||||||
|  |  | ||||||
| import voluptuous as vol | import voluptuous as vol | ||||||
|  |  | ||||||
| from esphome import core, yaml_util, loader, pins | from esphome import core, loader, pins, yaml_util | ||||||
| import esphome.core.config as core_config | from esphome.config_helpers import Extend, Remove | ||||||
|  | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_ESPHOME, |     CONF_ESPHOME, | ||||||
|     CONF_ID, |  | ||||||
|     CONF_PLATFORM, |  | ||||||
|     CONF_PACKAGES, |  | ||||||
|     CONF_SUBSTITUTIONS, |  | ||||||
|     CONF_EXTERNAL_COMPONENTS, |     CONF_EXTERNAL_COMPONENTS, | ||||||
|  |     CONF_ID, | ||||||
|  |     CONF_PACKAGES, | ||||||
|  |     CONF_PLATFORM, | ||||||
|  |     CONF_SUBSTITUTIONS, | ||||||
|     TARGET_PLATFORMS, |     TARGET_PLATFORMS, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, EsphomeError, DocumentRange | from esphome.core import CORE, DocumentRange, EsphomeError | ||||||
| from esphome.helpers import indent | import esphome.core.config as core_config | ||||||
| from esphome.util import safe_print, OrderedDict |  | ||||||
|  |  | ||||||
| from esphome.config_helpers import Extend, Remove |  | ||||||
| from esphome.loader import get_component, get_platform, ComponentManifest |  | ||||||
| from esphome.yaml_util import is_secret, ESPHomeDataBase, ESPForceValue |  | ||||||
| from esphome.voluptuous_schema import ExtraKeysInvalid |  | ||||||
| from esphome.log import color, Fore |  | ||||||
| import esphome.final_validate as fv | import esphome.final_validate as fv | ||||||
| import esphome.config_validation as cv | from esphome.helpers import indent | ||||||
| from esphome.types import ConfigType, ConfigFragmentType | from esphome.loader import ComponentManifest, get_component, get_platform | ||||||
|  | from esphome.log import Fore, color | ||||||
|  | from esphome.types import ConfigFragmentType, ConfigType | ||||||
|  | from esphome.util import OrderedDict, safe_print | ||||||
|  | from esphome.voluptuous_schema import ExtraKeysInvalid | ||||||
|  | from esphome.yaml_util import ESPForceValue, ESPHomeDataBase, is_secret | ||||||
|  |  | ||||||
| _LOGGER = logging.getLogger(__name__) | _LOGGER = logging.getLogger(__name__) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,13 +1,13 @@ | |||||||
| """Helpers for config validation using voluptuous.""" | """Helpers for config validation using voluptuous.""" | ||||||
|  |  | ||||||
|  | from contextlib import contextmanager | ||||||
| from dataclasses import dataclass | from dataclasses import dataclass | ||||||
|  | from datetime import datetime | ||||||
| import logging | import logging | ||||||
| import os | import os | ||||||
| import re | import re | ||||||
| from contextlib import contextmanager |  | ||||||
| import uuid as uuid_ |  | ||||||
| from datetime import datetime |  | ||||||
| from string import ascii_letters, digits | from string import ascii_letters, digits | ||||||
|  | import uuid as uuid_ | ||||||
|  |  | ||||||
| import voluptuous as vol | import voluptuous as vol | ||||||
|  |  | ||||||
| @@ -17,37 +17,37 @@ from esphome.config_helpers import Extend, Remove | |||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     ALLOWED_NAME_CHARS, |     ALLOWED_NAME_CHARS, | ||||||
|     CONF_AVAILABILITY, |     CONF_AVAILABILITY, | ||||||
|     CONF_COMMAND_TOPIC, |  | ||||||
|     CONF_COMMAND_RETAIN, |     CONF_COMMAND_RETAIN, | ||||||
|  |     CONF_COMMAND_TOPIC, | ||||||
|  |     CONF_DAY, | ||||||
|     CONF_DISABLED_BY_DEFAULT, |     CONF_DISABLED_BY_DEFAULT, | ||||||
|     CONF_DISCOVERY, |     CONF_DISCOVERY, | ||||||
|     CONF_ENTITY_CATEGORY, |     CONF_ENTITY_CATEGORY, | ||||||
|  |     CONF_HOUR, | ||||||
|     CONF_ICON, |     CONF_ICON, | ||||||
|     CONF_ID, |     CONF_ID, | ||||||
|     CONF_INTERNAL, |     CONF_INTERNAL, | ||||||
|  |     CONF_MINUTE, | ||||||
|  |     CONF_MONTH, | ||||||
|     CONF_NAME, |     CONF_NAME, | ||||||
|  |     CONF_PASSWORD, | ||||||
|  |     CONF_PATH, | ||||||
|     CONF_PAYLOAD_AVAILABLE, |     CONF_PAYLOAD_AVAILABLE, | ||||||
|     CONF_PAYLOAD_NOT_AVAILABLE, |     CONF_PAYLOAD_NOT_AVAILABLE, | ||||||
|     CONF_RETAIN, |  | ||||||
|     CONF_QOS, |     CONF_QOS, | ||||||
|  |     CONF_REF, | ||||||
|  |     CONF_RETAIN, | ||||||
|  |     CONF_SECOND, | ||||||
|     CONF_SETUP_PRIORITY, |     CONF_SETUP_PRIORITY, | ||||||
|     CONF_STATE_TOPIC, |     CONF_STATE_TOPIC, | ||||||
|     CONF_TOPIC, |     CONF_TOPIC, | ||||||
|     CONF_YEAR, |  | ||||||
|     CONF_MONTH, |  | ||||||
|     CONF_DAY, |  | ||||||
|     CONF_HOUR, |  | ||||||
|     CONF_MINUTE, |  | ||||||
|     CONF_SECOND, |  | ||||||
|     CONF_VALUE, |  | ||||||
|     CONF_UPDATE_INTERVAL, |  | ||||||
|     CONF_TYPE_ID, |  | ||||||
|     CONF_TYPE, |     CONF_TYPE, | ||||||
|     CONF_REF, |     CONF_TYPE_ID, | ||||||
|  |     CONF_UPDATE_INTERVAL, | ||||||
|     CONF_URL, |     CONF_URL, | ||||||
|     CONF_PATH, |  | ||||||
|     CONF_USERNAME, |     CONF_USERNAME, | ||||||
|     CONF_PASSWORD, |     CONF_VALUE, | ||||||
|  |     CONF_YEAR, | ||||||
|     ENTITY_CATEGORY_CONFIG, |     ENTITY_CATEGORY_CONFIG, | ||||||
|     ENTITY_CATEGORY_DIAGNOSTIC, |     ENTITY_CATEGORY_DIAGNOSTIC, | ||||||
|     ENTITY_CATEGORY_NONE, |     ENTITY_CATEGORY_NONE, | ||||||
| @@ -71,15 +71,15 @@ from esphome.core import ( | |||||||
|     TimePeriod, |     TimePeriod, | ||||||
|     TimePeriodMicroseconds, |     TimePeriodMicroseconds, | ||||||
|     TimePeriodMilliseconds, |     TimePeriodMilliseconds, | ||||||
|  |     TimePeriodMinutes, | ||||||
|     TimePeriodNanoseconds, |     TimePeriodNanoseconds, | ||||||
|     TimePeriodSeconds, |     TimePeriodSeconds, | ||||||
|     TimePeriodMinutes, |  | ||||||
| ) | ) | ||||||
| from esphome.helpers import list_starts_with, add_class_to_obj | from esphome.helpers import add_class_to_obj, list_starts_with | ||||||
| from esphome.schema_extractors import ( | from esphome.schema_extractors import ( | ||||||
|     SCHEMA_EXTRACT, |     SCHEMA_EXTRACT, | ||||||
|     schema_extractor_list, |  | ||||||
|     schema_extractor, |     schema_extractor, | ||||||
|  |     schema_extractor_list, | ||||||
|     schema_extractor_registry, |     schema_extractor_registry, | ||||||
|     schema_extractor_typed, |     schema_extractor_typed, | ||||||
| ) | ) | ||||||
| @@ -1686,9 +1686,9 @@ class SplitDefault(Optional): | |||||||
|         if CORE.is_esp32: |         if CORE.is_esp32: | ||||||
|             from esphome.components.esp32 import get_esp32_variant |             from esphome.components.esp32 import get_esp32_variant | ||||||
|             from esphome.components.esp32.const import ( |             from esphome.components.esp32.const import ( | ||||||
|  |                 VARIANT_ESP32C3, | ||||||
|                 VARIANT_ESP32S2, |                 VARIANT_ESP32S2, | ||||||
|                 VARIANT_ESP32S3, |                 VARIANT_ESP32S3, | ||||||
|                 VARIANT_ESP32C3, |  | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
|             variant = get_esp32_variant() |             variant = get_esp32_variant() | ||||||
|   | |||||||
| @@ -539,6 +539,7 @@ CONF_ON_DOUBLE_CLICK = "on_double_click" | |||||||
| CONF_ON_ENROLLMENT_DONE = "on_enrollment_done" | CONF_ON_ENROLLMENT_DONE = "on_enrollment_done" | ||||||
| CONF_ON_ENROLLMENT_FAILED = "on_enrollment_failed" | CONF_ON_ENROLLMENT_FAILED = "on_enrollment_failed" | ||||||
| CONF_ON_ENROLLMENT_SCAN = "on_enrollment_scan" | CONF_ON_ENROLLMENT_SCAN = "on_enrollment_scan" | ||||||
|  | CONF_ON_ERROR = "on_error" | ||||||
| CONF_ON_EVENT = "on_event" | CONF_ON_EVENT = "on_event" | ||||||
| CONF_ON_FINGER_SCAN_INVALID = "on_finger_scan_invalid" | CONF_ON_FINGER_SCAN_INVALID = "on_finger_scan_invalid" | ||||||
| CONF_ON_FINGER_SCAN_MATCHED = "on_finger_scan_matched" | CONF_ON_FINGER_SCAN_MATCHED = "on_finger_scan_matched" | ||||||
| @@ -1032,11 +1033,13 @@ UNIT_KILOWATT_HOURS = "kWh" | |||||||
| UNIT_LUX = "lx" | UNIT_LUX = "lx" | ||||||
| UNIT_METER = "m" | UNIT_METER = "m" | ||||||
| UNIT_METER_PER_SECOND_SQUARED = "m/s²" | UNIT_METER_PER_SECOND_SQUARED = "m/s²" | ||||||
|  | UNIT_MICROAMP = "µA" | ||||||
| UNIT_MICROGRAMS_PER_CUBIC_METER = "µg/m³" | UNIT_MICROGRAMS_PER_CUBIC_METER = "µg/m³" | ||||||
| UNIT_MICROMETER = "µm" | UNIT_MICROMETER = "µm" | ||||||
| UNIT_MICROSIEMENS_PER_CENTIMETER = "µS/cm" | UNIT_MICROSIEMENS_PER_CENTIMETER = "µS/cm" | ||||||
| UNIT_MICROSILVERTS_PER_HOUR = "µSv/h" | UNIT_MICROSILVERTS_PER_HOUR = "µSv/h" | ||||||
| UNIT_MICROTESLA = "µT" | UNIT_MICROTESLA = "µT" | ||||||
|  | UNIT_MILLIAMP = "mA" | ||||||
| UNIT_MILLIGRAMS_PER_CUBIC_METER = "mg/m³" | UNIT_MILLIGRAMS_PER_CUBIC_METER = "mg/m³" | ||||||
| UNIT_MILLIMETER = "mm" | UNIT_MILLIMETER = "mm" | ||||||
| UNIT_MILLISECOND = "ms" | UNIT_MILLISECOND = "ms" | ||||||
|   | |||||||
| @@ -7,26 +7,29 @@ from typing import TYPE_CHECKING, Optional, Union | |||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_COMMENT, |     CONF_COMMENT, | ||||||
|     CONF_ESPHOME, |     CONF_ESPHOME, | ||||||
|     CONF_USE_ADDRESS, |  | ||||||
|     CONF_ETHERNET, |     CONF_ETHERNET, | ||||||
|  |     CONF_PORT, | ||||||
|  |     CONF_USE_ADDRESS, | ||||||
|     CONF_WEB_SERVER, |     CONF_WEB_SERVER, | ||||||
|     CONF_WIFI, |     CONF_WIFI, | ||||||
|     CONF_PORT, |  | ||||||
|     KEY_CORE, |     KEY_CORE, | ||||||
|     KEY_TARGET_FRAMEWORK, |     KEY_TARGET_FRAMEWORK, | ||||||
|     KEY_TARGET_PLATFORM, |     KEY_TARGET_PLATFORM, | ||||||
|  |     PLATFORM_BK72XX, | ||||||
|     PLATFORM_ESP32, |     PLATFORM_ESP32, | ||||||
|     PLATFORM_ESP8266, |     PLATFORM_ESP8266, | ||||||
|     PLATFORM_BK72XX, |  | ||||||
|     PLATFORM_RTL87XX, |  | ||||||
|     PLATFORM_RP2040, |  | ||||||
|     PLATFORM_HOST, |     PLATFORM_HOST, | ||||||
|  |     PLATFORM_RP2040, | ||||||
|  |     PLATFORM_RTL87XX, | ||||||
| ) | ) | ||||||
| from esphome.coroutine import FakeAwaitable as _FakeAwaitable |  | ||||||
| from esphome.coroutine import FakeEventLoop as _FakeEventLoop |  | ||||||
|  |  | ||||||
| # pylint: disable=unused-import | # pylint: disable=unused-import | ||||||
| from esphome.coroutine import coroutine, coroutine_with_priority  # noqa | from esphome.coroutine import (  # noqa: F401 | ||||||
|  |     FakeAwaitable as _FakeAwaitable, | ||||||
|  |     FakeEventLoop as _FakeEventLoop, | ||||||
|  |     coroutine, | ||||||
|  |     coroutine_with_priority, | ||||||
|  | ) | ||||||
| from esphome.helpers import ensure_unique_string, get_str_env, is_ha_addon | from esphome.helpers import ensure_unique_string, get_str_env, is_ha_addon | ||||||
| from esphome.util import OrderedDict | from esphome.util import OrderedDict | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,9 +3,9 @@ import multiprocessing | |||||||
| import os | import os | ||||||
| import re | import re | ||||||
|  |  | ||||||
|  | from esphome import automation | ||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome import automation |  | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_ARDUINO_VERSION, |     CONF_ARDUINO_VERSION, | ||||||
|     CONF_AREA, |     CONF_AREA, | ||||||
| @@ -16,11 +16,11 @@ from esphome.const import ( | |||||||
|     CONF_COMPILE_PROCESS_LIMIT, |     CONF_COMPILE_PROCESS_LIMIT, | ||||||
|     CONF_ESPHOME, |     CONF_ESPHOME, | ||||||
|     CONF_FRAMEWORK, |     CONF_FRAMEWORK, | ||||||
|  |     CONF_FRIENDLY_NAME, | ||||||
|     CONF_INCLUDES, |     CONF_INCLUDES, | ||||||
|     CONF_LIBRARIES, |     CONF_LIBRARIES, | ||||||
|     CONF_MIN_VERSION, |     CONF_MIN_VERSION, | ||||||
|     CONF_NAME, |     CONF_NAME, | ||||||
|     CONF_FRIENDLY_NAME, |  | ||||||
|     CONF_ON_BOOT, |     CONF_ON_BOOT, | ||||||
|     CONF_ON_LOOP, |     CONF_ON_LOOP, | ||||||
|     CONF_ON_SHUTDOWN, |     CONF_ON_SHUTDOWN, | ||||||
| @@ -34,8 +34,8 @@ from esphome.const import ( | |||||||
|     CONF_TYPE, |     CONF_TYPE, | ||||||
|     CONF_VERSION, |     CONF_VERSION, | ||||||
|     KEY_CORE, |     KEY_CORE, | ||||||
|     TARGET_PLATFORMS, |  | ||||||
|     PLATFORM_ESP8266, |     PLATFORM_ESP8266, | ||||||
|  |     TARGET_PLATFORMS, | ||||||
|     __version__ as ESPHOME_VERSION, |     __version__ as ESPHOME_VERSION, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, coroutine_with_priority | ||||||
|   | |||||||
| @@ -41,6 +41,7 @@ | |||||||
| #define USE_LVGL | #define USE_LVGL | ||||||
| #define USE_LVGL_FONT | #define USE_LVGL_FONT | ||||||
| #define USE_LVGL_IMAGE | #define USE_LVGL_IMAGE | ||||||
|  | #define USE_LVGL_TOUCHSCREEN | ||||||
| #define USE_MDNS | #define USE_MDNS | ||||||
| #define USE_MEDIA_PLAYER | #define USE_MEDIA_PLAYER | ||||||
| #define USE_MQTT | #define USE_MQTT | ||||||
|   | |||||||
| @@ -1,6 +1,5 @@ | |||||||
| import esphome.final_validate as fv |  | ||||||
|  |  | ||||||
| from esphome.const import CONF_ID | from esphome.const import CONF_ID | ||||||
|  | import esphome.final_validate as fv | ||||||
|  |  | ||||||
|  |  | ||||||
| def inherit_property_from(property_to_inherit, parent_id_property, transform=None): | def inherit_property_from(property_to_inherit, parent_id_property, transform=None): | ||||||
|   | |||||||
| @@ -43,13 +43,13 @@ the last `yield` expression defines what is returned. | |||||||
| """ | """ | ||||||
|  |  | ||||||
| import collections | import collections | ||||||
|  | from collections.abc import Awaitable, Generator, Iterator | ||||||
| import functools | import functools | ||||||
| import heapq | import heapq | ||||||
| import inspect | import inspect | ||||||
| import logging | import logging | ||||||
| import types | import types | ||||||
| from typing import Any, Callable | from typing import Any, Callable | ||||||
| from collections.abc import Awaitable, Generator, Iterator |  | ||||||
|  |  | ||||||
| _LOGGER = logging.getLogger(__name__) | _LOGGER = logging.getLogger(__name__) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| import abc | import abc | ||||||
|  | from collections.abc import Sequence | ||||||
| import inspect | import inspect | ||||||
| import math | import math | ||||||
| import re | import re | ||||||
| from collections.abc import Sequence |  | ||||||
| from typing import Any, Callable, Optional, Union | from typing import Any, Callable, Optional, Union | ||||||
|  |  | ||||||
| from esphome.core import ( | from esphome.core import ( | ||||||
|   | |||||||
| @@ -12,15 +12,13 @@ from esphome.const import ( | |||||||
|     CONF_UPDATE_INTERVAL, |     CONF_UPDATE_INTERVAL, | ||||||
|     KEY_PAST_SAFE_MODE, |     KEY_PAST_SAFE_MODE, | ||||||
| ) | ) | ||||||
|  | from esphome.core import CORE, ID, coroutine | ||||||
| from esphome.core import coroutine, ID, CORE |  | ||||||
| from esphome.coroutine import FakeAwaitable | from esphome.coroutine import FakeAwaitable | ||||||
| from esphome.types import ConfigType, ConfigFragmentType |  | ||||||
| from esphome.cpp_generator import add, get_variable | from esphome.cpp_generator import add, get_variable | ||||||
| from esphome.cpp_types import App | from esphome.cpp_types import App | ||||||
|  | from esphome.helpers import sanitize, snake_case | ||||||
|  | from esphome.types import ConfigFragmentType, ConfigType | ||||||
| from esphome.util import Registry, RegistryEntry | from esphome.util import Registry, RegistryEntry | ||||||
| from esphome.helpers import snake_case, sanitize |  | ||||||
|  |  | ||||||
|  |  | ||||||
| _LOGGER = logging.getLogger(__name__) | _LOGGER = logging.getLogger(__name__) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,13 +1,13 @@ | |||||||
| from __future__ import annotations | from __future__ import annotations | ||||||
|  |  | ||||||
| import asyncio | import asyncio | ||||||
|  | from collections.abc import Coroutine | ||||||
| import contextlib | import contextlib | ||||||
| import logging |  | ||||||
| import threading |  | ||||||
| from dataclasses import dataclass | from dataclasses import dataclass | ||||||
| from functools import partial | from functools import partial | ||||||
|  | import logging | ||||||
|  | import threading | ||||||
| from typing import TYPE_CHECKING, Any, Callable | from typing import TYPE_CHECKING, Any, Callable | ||||||
| from collections.abc import Coroutine |  | ||||||
|  |  | ||||||
| from ..zeroconf import DiscoveredImport | from ..zeroconf import DiscoveredImport | ||||||
| from .dns import DNSCache | from .dns import DNSCache | ||||||
|   | |||||||
| @@ -1,14 +1,14 @@ | |||||||
| from __future__ import annotations | from __future__ import annotations | ||||||
|  |  | ||||||
| import asyncio | import asyncio | ||||||
|  | from asyncio import events | ||||||
|  | from concurrent.futures import ThreadPoolExecutor | ||||||
| import logging | import logging | ||||||
| import os | import os | ||||||
| import socket | import socket | ||||||
| import threading | import threading | ||||||
| import traceback |  | ||||||
| from asyncio import events |  | ||||||
| from concurrent.futures import ThreadPoolExecutor |  | ||||||
| from time import monotonic | from time import monotonic | ||||||
|  | import traceback | ||||||
| from typing import Any | from typing import Any | ||||||
|  |  | ||||||
| from esphome.storage_json import EsphomeStorageJSON, esphome_storage_path | from esphome.storage_json import EsphomeStorageJSON, esphome_storage_path | ||||||
|   | |||||||
| @@ -1,9 +1,9 @@ | |||||||
| from __future__ import annotations | from __future__ import annotations | ||||||
|  |  | ||||||
| import asyncio | import asyncio | ||||||
|  | from collections import defaultdict | ||||||
| import logging | import logging | ||||||
| import os | import os | ||||||
| from collections import defaultdict |  | ||||||
| from typing import TYPE_CHECKING, Any | from typing import TYPE_CHECKING, Any | ||||||
|  |  | ||||||
| from esphome import const, util | from esphome import const, util | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import logging | import logging | ||||||
| import os | import os | ||||||
| import tempfile |  | ||||||
| from pathlib import Path | from pathlib import Path | ||||||
|  | import tempfile | ||||||
|  |  | ||||||
| _LOGGER = logging.getLogger(__name__) | _LOGGER = logging.getLogger(__name__) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ from __future__ import annotations | |||||||
|  |  | ||||||
| import asyncio | import asyncio | ||||||
| import base64 | import base64 | ||||||
|  | from collections.abc import Iterable | ||||||
| import datetime | import datetime | ||||||
| import functools | import functools | ||||||
| import gzip | import gzip | ||||||
| @@ -9,13 +10,12 @@ import hashlib | |||||||
| import json | import json | ||||||
| import logging | import logging | ||||||
| import os | import os | ||||||
|  | from pathlib import Path | ||||||
| import secrets | import secrets | ||||||
| import shutil | import shutil | ||||||
| import subprocess | import subprocess | ||||||
| import threading | import threading | ||||||
| import time | import time | ||||||
| from collections.abc import Iterable |  | ||||||
| from pathlib import Path |  | ||||||
| from typing import TYPE_CHECKING, Any, Callable, TypeVar | from typing import TYPE_CHECKING, Any, Callable, TypeVar | ||||||
| from urllib.parse import urlparse | from urllib.parse import urlparse | ||||||
|  |  | ||||||
| @@ -26,13 +26,13 @@ import tornado.httpserver | |||||||
| import tornado.httputil | import tornado.httputil | ||||||
| import tornado.ioloop | import tornado.ioloop | ||||||
| import tornado.iostream | import tornado.iostream | ||||||
|  | from tornado.log import access_log | ||||||
| import tornado.netutil | import tornado.netutil | ||||||
| import tornado.process | import tornado.process | ||||||
| import tornado.queues | import tornado.queues | ||||||
| import tornado.web | import tornado.web | ||||||
| import tornado.websocket | import tornado.websocket | ||||||
| import yaml | import yaml | ||||||
| from tornado.log import access_log |  | ||||||
| from yaml.nodes import Node | from yaml.nodes import Node | ||||||
|  |  | ||||||
| from esphome import const, platformio_api, yaml_util | from esphome import const, platformio_api, yaml_util | ||||||
|   | |||||||
| @@ -1,13 +1,15 @@ | |||||||
| from __future__ import annotations | from __future__ import annotations | ||||||
|  |  | ||||||
| import logging |  | ||||||
| from pathlib import Path |  | ||||||
| import os |  | ||||||
| from datetime import datetime | from datetime import datetime | ||||||
|  | import logging | ||||||
|  | import os | ||||||
|  | from pathlib import Path | ||||||
|  |  | ||||||
| import requests | import requests | ||||||
|  |  | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.core import CORE, TimePeriodSeconds |  | ||||||
| from esphome.const import __version__ | from esphome.const import __version__ | ||||||
|  | from esphome.core import CORE, TimePeriodSeconds | ||||||
|  |  | ||||||
| _LOGGER = logging.getLogger(__name__) | _LOGGER = logging.getLogger(__name__) | ||||||
| CODEOWNERS = ["@landonr"] | CODEOWNERS = ["@landonr"] | ||||||
|   | |||||||
| @@ -1,9 +1,9 @@ | |||||||
| from abc import ABC, abstractmethod | from abc import ABC, abstractmethod | ||||||
| from typing import Any |  | ||||||
| import contextvars | import contextvars | ||||||
|  | from typing import Any | ||||||
|  |  | ||||||
| from esphome.types import ConfigFragmentType, ID, ConfigPathType |  | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
|  | from esphome.types import ID, ConfigFragmentType, ConfigPathType | ||||||
|  |  | ||||||
|  |  | ||||||
| class FinalValidateConfig(ABC): | class FinalValidateConfig(ABC): | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| import hashlib |  | ||||||
| import logging |  | ||||||
| import re |  | ||||||
| import subprocess |  | ||||||
| import urllib.parse |  | ||||||
| from dataclasses import dataclass | from dataclasses import dataclass | ||||||
| from datetime import datetime | from datetime import datetime | ||||||
|  | import hashlib | ||||||
|  | import logging | ||||||
| from pathlib import Path | from pathlib import Path | ||||||
|  | import re | ||||||
|  | import subprocess | ||||||
| from typing import Callable, Optional | from typing import Callable, Optional | ||||||
|  | import urllib.parse | ||||||
|  |  | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.core import CORE, TimePeriodSeconds | from esphome.core import CORE, TimePeriodSeconds | ||||||
|   | |||||||
| @@ -1,14 +1,13 @@ | |||||||
| import codecs | import codecs | ||||||
| from contextlib import suppress | from contextlib import suppress | ||||||
|  |  | ||||||
| import logging | import logging | ||||||
| import os | import os | ||||||
| import platform |  | ||||||
| from pathlib import Path | from pathlib import Path | ||||||
| from typing import Union | import platform | ||||||
| import tempfile |  | ||||||
| from urllib.parse import urlparse |  | ||||||
| import re | import re | ||||||
|  | import tempfile | ||||||
|  | from typing import Union | ||||||
|  | from urllib.parse import urlparse | ||||||
|  |  | ||||||
| _LOGGER = logging.getLogger(__name__) | _LOGGER = logging.getLogger(__name__) | ||||||
|  |  | ||||||
| @@ -129,9 +128,10 @@ def _resolve_with_zeroconf(host): | |||||||
|  |  | ||||||
|  |  | ||||||
| def resolve_ip_address(host): | def resolve_ip_address(host): | ||||||
|     from esphome.core import EsphomeError |  | ||||||
|     import socket |     import socket | ||||||
|  |  | ||||||
|  |     from esphome.core import EsphomeError | ||||||
|  |  | ||||||
|     errs = [] |     errs = [] | ||||||
|  |  | ||||||
|     if host.endswith(".local"): |     if host.endswith(".local"): | ||||||
|   | |||||||
| @@ -1,10 +1,10 @@ | |||||||
| from datetime import datetime | from datetime import datetime | ||||||
| import hashlib | import hashlib | ||||||
|  | import json | ||||||
| import logging | import logging | ||||||
| import ssl | import ssl | ||||||
| import sys | import sys | ||||||
| import time | import time | ||||||
| import json |  | ||||||
|  |  | ||||||
| import paho.mqtt.client as mqtt | import paho.mqtt.client as mqtt | ||||||
|  |  | ||||||
| @@ -24,9 +24,9 @@ from esphome.const import ( | |||||||
|     CONF_USERNAME, |     CONF_USERNAME, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, EsphomeError | from esphome.core import CORE, EsphomeError | ||||||
| from esphome.log import color, Fore | from esphome.helpers import get_int_env, get_str_env | ||||||
|  | from esphome.log import Fore, color | ||||||
| from esphome.util import safe_print | from esphome.util import safe_print | ||||||
| from esphome.helpers import get_str_env, get_int_env |  | ||||||
|  |  | ||||||
| _LOGGER = logging.getLogger(__name__) | _LOGGER = logging.getLogger(__name__) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,20 +1,20 @@ | |||||||
| import operator |  | ||||||
| from functools import reduce | from functools import reduce | ||||||
| import esphome.config_validation as cv | import operator | ||||||
| from esphome.core import CORE |  | ||||||
|  |  | ||||||
|  | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|  |     CONF_ALLOW_OTHER_USES, | ||||||
|  |     CONF_IGNORE_STRAPPING_WARNING, | ||||||
|     CONF_INPUT, |     CONF_INPUT, | ||||||
|  |     CONF_INVERTED, | ||||||
|     CONF_MODE, |     CONF_MODE, | ||||||
|     CONF_NUMBER, |     CONF_NUMBER, | ||||||
|     CONF_OPEN_DRAIN, |     CONF_OPEN_DRAIN, | ||||||
|     CONF_OUTPUT, |     CONF_OUTPUT, | ||||||
|     CONF_PULLDOWN, |     CONF_PULLDOWN, | ||||||
|     CONF_PULLUP, |     CONF_PULLUP, | ||||||
|     CONF_IGNORE_STRAPPING_WARNING, |  | ||||||
|     CONF_ALLOW_OTHER_USES, |  | ||||||
|     CONF_INVERTED, |  | ||||||
| ) | ) | ||||||
|  | from esphome.core import CORE | ||||||
|  |  | ||||||
|  |  | ||||||
| class PinRegistry(dict): | class PinRegistry(dict): | ||||||
|   | |||||||
| @@ -1,12 +1,11 @@ | |||||||
| from dataclasses import dataclass | from dataclasses import dataclass | ||||||
| import json | import json | ||||||
| from typing import Union |  | ||||||
| from pathlib import Path |  | ||||||
|  |  | ||||||
| import logging | import logging | ||||||
| import os | import os | ||||||
|  | from pathlib import Path | ||||||
| import re | import re | ||||||
| import subprocess | import subprocess | ||||||
|  | from typing import Union | ||||||
|  |  | ||||||
| from esphome.const import CONF_COMPILE_PROCESS_LIMIT, CONF_ESPHOME, KEY_CORE | from esphome.const import CONF_COMPILE_PROCESS_LIMIT, CONF_ESPHOME, KEY_CORE | ||||||
| from esphome.core import CORE, EsphomeError | from esphome.core import CORE, EsphomeError | ||||||
| @@ -20,9 +19,10 @@ def patch_structhash(): | |||||||
|     # removed/added. This might have unintended consequences, but this improves compile |     # removed/added. This might have unintended consequences, but this improves compile | ||||||
|     # times greatly when adding/removing components and a simple clean build solves |     # times greatly when adding/removing components and a simple clean build solves | ||||||
|     # all issues |     # all issues | ||||||
|     from platformio.run import helpers, cli |  | ||||||
|     from os.path import join, isdir, getmtime |  | ||||||
|     from os import makedirs |     from os import makedirs | ||||||
|  |     from os.path import getmtime, isdir, join | ||||||
|  |  | ||||||
|  |     from platformio.run import cli, helpers | ||||||
|  |  | ||||||
|     def patched_clean_build_dir(build_dir, *args): |     def patched_clean_build_dir(build_dir, *args): | ||||||
|         from platformio import fs |         from platformio import fs | ||||||
|   | |||||||
| @@ -1,10 +1,11 @@ | |||||||
| from __future__ import annotations | from __future__ import annotations | ||||||
|  |  | ||||||
| import binascii | import binascii | ||||||
| import codecs | import codecs | ||||||
|  | from datetime import datetime | ||||||
| import json | import json | ||||||
| import logging | import logging | ||||||
| import os | import os | ||||||
| from datetime import datetime |  | ||||||
|  |  | ||||||
| from esphome import const | from esphome import const | ||||||
| from esphome.const import CONF_DISABLED, CONF_MDNS | from esphome.const import CONF_DISABLED, CONF_MDNS | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
|  |  | ||||||
| from typing import Union | from typing import Union | ||||||
|  |  | ||||||
| from esphome.core import ID, Lambda, EsphomeCore | from esphome.core import ID, EsphomeCore, Lambda | ||||||
|  |  | ||||||
| ConfigFragmentType = Union[ | ConfigFragmentType = Union[ | ||||||
|     str, |     str, | ||||||
|   | |||||||
| @@ -1,13 +1,12 @@ | |||||||
| from typing import Union |  | ||||||
|  |  | ||||||
| import collections | import collections | ||||||
| import io | import io | ||||||
| import logging | import logging | ||||||
| import os | import os | ||||||
|  | from pathlib import Path | ||||||
| import re | import re | ||||||
| import subprocess | import subprocess | ||||||
| import sys | import sys | ||||||
| from pathlib import Path | from typing import Union | ||||||
|  |  | ||||||
| from esphome import const | from esphome import const | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ import difflib | |||||||
| import itertools | import itertools | ||||||
|  |  | ||||||
| import voluptuous as vol | import voluptuous as vol | ||||||
|  |  | ||||||
| from esphome.schema_extractors import schema_extractor_extended | from esphome.schema_extractors import schema_extractor_extended | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,13 +1,14 @@ | |||||||
| from __future__ import annotations | from __future__ import annotations | ||||||
|  |  | ||||||
|  | from io import StringIO | ||||||
| import json | import json | ||||||
| import os | import os | ||||||
| from io import StringIO |  | ||||||
| from typing import Any | from typing import Any | ||||||
|  |  | ||||||
| from esphome.yaml_util import parse_yaml | from esphome.config import Config, _format_vol_invalid, validate_config | ||||||
| from esphome.config import validate_config, _format_vol_invalid, Config |  | ||||||
| from esphome.core import CORE, DocumentRange |  | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
|  | from esphome.core import CORE, DocumentRange | ||||||
|  | from esphome.yaml_util import parse_yaml | ||||||
|  |  | ||||||
|  |  | ||||||
| def _get_invalid_range(res: Config, invalid: cv.Invalid) -> DocumentRange | None: | def _get_invalid_range(res: Config, invalid: cv.Invalid) -> DocumentRange | None: | ||||||
|   | |||||||
| @@ -276,8 +276,8 @@ def wizard(path): | |||||||
|     from esphome.components.bk72xx import boards as bk72xx_boards |     from esphome.components.bk72xx import boards as bk72xx_boards | ||||||
|     from esphome.components.esp32 import boards as esp32_boards |     from esphome.components.esp32 import boards as esp32_boards | ||||||
|     from esphome.components.esp8266 import boards as esp8266_boards |     from esphome.components.esp8266 import boards as esp8266_boards | ||||||
|     from esphome.components.rtl87xx import boards as rtl87xx_boards |  | ||||||
|     from esphome.components.rp2040 import boards as rp2040_boards |     from esphome.components.rp2040 import boards as rp2040_boards | ||||||
|  |     from esphome.components.rtl87xx import boards as rtl87xx_boards | ||||||
|  |  | ||||||
|     if not path.endswith(".yaml") and not path.endswith(".yml"): |     if not path.endswith(".yaml") and not path.endswith(".yml"): | ||||||
|         safe_print( |         safe_print( | ||||||
|   | |||||||
| @@ -1,27 +1,27 @@ | |||||||
| import logging | import logging | ||||||
| import os | import os | ||||||
| import re |  | ||||||
| from pathlib import Path | from pathlib import Path | ||||||
|  | import re | ||||||
| from typing import Union | from typing import Union | ||||||
|  |  | ||||||
| from esphome.config import iter_components, iter_component_configs | from esphome import loader | ||||||
|  | from esphome.config import iter_component_configs, iter_components | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|  |     ENV_NOGITIGNORE, | ||||||
|     HEADER_FILE_EXTENSIONS, |     HEADER_FILE_EXTENSIONS, | ||||||
|     SOURCE_FILE_EXTENSIONS, |     SOURCE_FILE_EXTENSIONS, | ||||||
|     __version__, |     __version__, | ||||||
|     ENV_NOGITIGNORE, |  | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, EsphomeError | from esphome.core import CORE, EsphomeError | ||||||
| from esphome.helpers import ( | from esphome.helpers import ( | ||||||
|     mkdir_p, |  | ||||||
|     read_file, |  | ||||||
|     write_file_if_changed, |  | ||||||
|     walk_files, |  | ||||||
|     copy_file_if_changed, |     copy_file_if_changed, | ||||||
|     get_bool_env, |     get_bool_env, | ||||||
|  |     mkdir_p, | ||||||
|  |     read_file, | ||||||
|  |     walk_files, | ||||||
|  |     write_file_if_changed, | ||||||
| ) | ) | ||||||
| from esphome.storage_json import StorageJSON, storage_path | from esphome.storage_json import StorageJSON, storage_path | ||||||
| from esphome import loader |  | ||||||
|  |  | ||||||
| _LOGGER = logging.getLogger(__name__) | _LOGGER = logging.getLogger(__name__) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,16 +3,16 @@ from __future__ import annotations | |||||||
| import fnmatch | import fnmatch | ||||||
| import functools | import functools | ||||||
| import inspect | import inspect | ||||||
|  | from io import TextIOWrapper | ||||||
| import logging | import logging | ||||||
| import math | import math | ||||||
| import os | import os | ||||||
| import uuid |  | ||||||
| from io import TextIOWrapper |  | ||||||
| from typing import Any | from typing import Any | ||||||
|  | import uuid | ||||||
|  |  | ||||||
| import yaml | import yaml | ||||||
| import yaml.constructor |  | ||||||
| from yaml import SafeLoader as PurePythonLoader | from yaml import SafeLoader as PurePythonLoader | ||||||
|  | import yaml.constructor | ||||||
|  |  | ||||||
| try: | try: | ||||||
|     from yaml import CSafeLoader as FastestAvailableSafeLoader |     from yaml import CSafeLoader as FastestAvailableSafeLoader | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| from __future__ import annotations | from __future__ import annotations | ||||||
|  |  | ||||||
| import asyncio | import asyncio | ||||||
| import logging |  | ||||||
| from dataclasses import dataclass | from dataclasses import dataclass | ||||||
|  | import logging | ||||||
| from typing import Callable | from typing import Callable | ||||||
|  |  | ||||||
| from zeroconf import IPVersion, ServiceInfo, ServiceStateChange, Zeroconf | from zeroconf import IPVersion, ServiceInfo, ServiceStateChange, Zeroconf | ||||||
|   | |||||||
| @@ -0,0 +1,10 @@ | |||||||
|  | touchscreen: | ||||||
|  |   - platform: ft63x6 | ||||||
|  |     id: tft_touch | ||||||
|  |     display: tft_display | ||||||
|  |     update_interval: 50ms | ||||||
|  |     threshold: 1 | ||||||
|  |     calibration: | ||||||
|  |       x_max: 240 | ||||||
|  |       y_max: 320 | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										25
									
								
								tests/components/lvgl/logo-text.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								tests/components/lvgl/logo-text.svg
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 596.64 116.88"> | ||||||
|  |   <defs> | ||||||
|  |     <style> | ||||||
|  |       .cls-1 { | ||||||
|  |         fill: #1d2126; | ||||||
|  |         stroke-width: 0px; | ||||||
|  |       } | ||||||
|  |     </style> | ||||||
|  |   </defs> | ||||||
|  |   <g id="Layer_1-2" data-name="Layer 1"> | ||||||
|  |     <g> | ||||||
|  |       <g> | ||||||
|  |         <path class="cls-1" d="M211.37,84.7v11.25h-43.5V25.87h43.5v11.34h-31.59v18.14h28.22v10.55h-28.22v18.8h31.59Z"/> | ||||||
|  |         <path class="cls-1" d="M245.41,24.6c6.41,0,11.73,1.56,15.98,4.69,4.25,3.12,6.86,7.3,7.83,12.52l-11.2,3.05c-.63-3-2.09-5.31-4.38-6.94-2.3-1.62-5.13-2.44-8.51-2.44-3.63,0-6.5.87-8.62,2.6-2.13,1.73-3.19,4.04-3.19,6.91,0,4.53,2.81,7.47,8.44,8.81l11.44,2.86c5.91,1.53,10.33,3.96,13.27,7.29,2.94,3.33,4.41,7.43,4.41,12.3,0,6.25-2.27,11.3-6.8,15.16-4.53,3.86-10.59,5.79-18.19,5.79-6.84,0-12.63-1.61-17.34-4.83-4.66-3.34-7.41-7.75-8.25-13.22l11.2-2.91c.41,3.09,1.95,5.52,4.62,7.27,2.67,1.75,6.07,2.62,10.2,2.62s7.09-.84,9.35-2.51c2.27-1.67,3.4-3.94,3.4-6.82,0-4.5-2.81-7.47-8.44-8.91l-11.44-2.77c-5.88-1.34-10.29-3.73-13.24-7.15s-4.43-7.6-4.43-12.54c0-6.19,2.2-11.21,6.59-15.07,4.39-3.86,10.16-5.79,17.32-5.79Z"/> | ||||||
|  |         <path class="cls-1" d="M332.92,48.7c0,6.88-2.09,12.44-6.26,16.69-4.17,4.25-9.79,6.38-16.85,6.38h-15.75v24.19h-11.91V25.87h27.75c7.12,0,12.74,2.06,16.85,6.16,4.11,4.11,6.16,9.66,6.16,16.66ZM320.45,48.42c0-3.53-1.1-6.4-3.3-8.6s-5.32-3.3-9.35-3.3h-13.73v24.8h13.55c4.12,0,7.3-1.17,9.52-3.52,2.22-2.34,3.33-5.47,3.33-9.38Z"/> | ||||||
|  |         <path class="cls-1" d="M343.56,25.87h11.91v29.3l30.89.09v-29.39h12v70.08h-12v-30.14l-30.89-.09v30.23h-11.91V25.87Z"/> | ||||||
|  |         <path class="cls-1" d="M434.17,47.29c7.25,0,13.16,2.33,17.72,6.98,4.56,4.66,6.84,10.64,6.84,17.95s-2.28,13.25-6.84,17.91c-4.56,4.66-10.47,6.98-17.72,6.98s-13.25-2.33-17.81-6.98c-4.56-4.66-6.84-10.62-6.84-17.91s2.28-13.34,6.84-17.98c4.56-4.64,10.5-6.96,17.81-6.96ZM434.17,86.9c3.87,0,7.02-1.37,9.45-4.1,2.42-2.73,3.63-6.29,3.63-10.66s-1.21-7.91-3.63-10.62c-2.42-2.7-5.57-4.05-9.45-4.05s-7.17,1.35-9.61,4.05c-2.44,2.7-3.66,6.24-3.66,10.62s1.22,7.93,3.66,10.66c2.44,2.73,5.64,4.1,9.61,4.1Z"/> | ||||||
|  |         <path class="cls-1" d="M540.67,65.81v30.14h-11.02v-28.41c0-3.28-.84-5.84-2.53-7.69-1.69-1.84-3.98-2.77-6.89-2.77-3.09,0-5.56,1.01-7.41,3.02-1.84,2.02-2.77,4.84-2.77,8.46v27.38h-11.16v-28.41c0-3.28-.82-5.84-2.46-7.69-1.64-1.84-3.91-2.77-6.82-2.77-3.09,0-5.58,1.01-7.45,3.02s-2.81,4.84-2.81,8.46v27.38h-11.34v-47.34h10.55l.38,4.55c2.75-4.03,7.23-6.05,13.45-6.05,3.62,0,6.77.75,9.42,2.25,2.66,1.5,4.67,3.69,6.05,6.56,1.16-2.75,3.07-4.91,5.74-6.47,2.67-1.56,5.85-2.34,9.54-2.34,5.37,0,9.64,1.66,12.8,4.97,3.16,3.31,4.73,7.89,4.73,13.73Z"/> | ||||||
|  |         <path class="cls-1" d="M596.64,76.45h-36.28c.38,3.56,1.72,6.28,4.03,8.16,2.31,1.88,5.25,2.81,8.81,2.81,5.78,0,9.83-2.41,12.14-7.22l9.47,3.75c-1.78,4.16-4.59,7.41-8.41,9.75-3.83,2.34-8.23,3.52-13.2,3.52-7,0-12.68-2.29-17.04-6.87-4.36-4.58-6.54-10.59-6.54-18.02s2.2-13.48,6.59-18.14c4.39-4.66,10.13-6.98,17.23-6.98s12.58,2.3,16.83,6.89c4.25,4.59,6.38,10.64,6.38,18.14v4.22ZM560.55,68.48h24.56c-.22-3.84-1.38-6.77-3.49-8.79s-4.95-3.02-8.51-3.02-6.41,1.02-8.62,3.07c-2.22,2.05-3.53,4.96-3.94,8.74Z"/> | ||||||
|  |       </g> | ||||||
|  |       <path class="cls-1" d="M114.7,51.58L65.3,2.19c-2.92-2.92-7.69-2.92-10.61,0L5.3,51.58c-2.92,2.92-5.3,8.68-5.3,12.8v45c0,4.12,3.38,7.5,7.5,7.5h29.5V42.21c0-1.66,1.34-3,3-3h40c1.66,0,3,1.34,3,3v12c0,1.66-1.34,3-3,3h-25v6h25c1.66,0,3,1.34,3,3v12c0,1.66-1.34,3-3,3h-25v6h25c1.66,0,3,1.34,3,3v12c0,1.66-1.34,3-3,3h-28c-1.66,0-3-1.34-3-3s1.34-3,3-3h25v-6h-25c-1.66,0-3-1.34-3-3v-12c0-1.66,1.34-3,3-3h25v-6h-25c-1.66,0-3-1.34-3-3v-12c0-1.66,1.34-3,3-3h25v-6h-34v71.67h69.5c4.12,0,7.5-3.38,7.5-7.5v-45c0-4.12-2.39-9.89-5.3-12.8Z"/> | ||||||
|  |     </g> | ||||||
|  |   </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 3.6 KiB | 
| @@ -1,9 +1,10 @@ | |||||||
| color: |  | ||||||
|   - id: light_blue |  | ||||||
|     hex: "3340FF" |  | ||||||
|  |  | ||||||
| lvgl: | lvgl: | ||||||
|  |   log_level: TRACE | ||||||
|   bg_color: light_blue |   bg_color: light_blue | ||||||
|  |   touchscreens: | ||||||
|  |     - touchscreen_id: tft_touch | ||||||
|  |       long_press_repeat_time: 200ms | ||||||
|  |       long_press_time: 500ms | ||||||
|   widgets: |   widgets: | ||||||
|     - label: |     - label: | ||||||
|         text: Hello world |         text: Hello world | ||||||
| @@ -17,8 +18,101 @@ lvgl: | |||||||
|         text_color: 0xFFFFFF |         text_color: 0xFFFFFF | ||||||
|         align: bottom_mid |         align: bottom_mid | ||||||
|         text_font: space16 |         text_font: space16 | ||||||
|  |     - obj: | ||||||
|  |         align: center | ||||||
|  |         arc_opa: COVER | ||||||
|  |         arc_color: 0xFF0000 | ||||||
|  |         arc_rounded: false | ||||||
|  |         arc_width: 3 | ||||||
|  |         anim_time: 1s | ||||||
|  |         bg_color: light_blue | ||||||
|  |         bg_grad_color: light_blue | ||||||
|  |         bg_dither_mode: ordered | ||||||
|  |         bg_grad_dir: hor | ||||||
|  |         bg_grad_stop: 128 | ||||||
|  |         bg_image_opa: transp | ||||||
|  |         bg_image_recolor: light_blue | ||||||
|  |         bg_image_recolor_opa: 50% | ||||||
|  |         bg_main_stop: 0 | ||||||
|  |         bg_opa: 20% | ||||||
|  |         border_color: 0x00FF00 | ||||||
|  |         border_opa: cover | ||||||
|  |         border_post: true | ||||||
|  |         border_side: [bottom, left] | ||||||
|  |         border_width: 4 | ||||||
|  |         clip_corner: false | ||||||
|  |         height: 50% | ||||||
|  |         image_recolor: light_blue | ||||||
|  |         image_recolor_opa: cover | ||||||
|  |         line_width: 10 | ||||||
|  |         line_dash_width: 10 | ||||||
|  |         line_dash_gap: 10 | ||||||
|  |         line_rounded: false | ||||||
|  |         line_color: light_blue | ||||||
|  |         opa: cover | ||||||
|  |         opa_layered: cover | ||||||
|  |         outline_color: light_blue | ||||||
|  |         outline_opa: cover | ||||||
|  |         outline_pad: 10px | ||||||
|  |         outline_width: 10px | ||||||
|  |         pad_all: 10px | ||||||
|  |         pad_bottom: 10px | ||||||
|  |         pad_column: 10px | ||||||
|  |         pad_left: 10px | ||||||
|  |         pad_right: 10px | ||||||
|  |         pad_row: 10px | ||||||
|  |         pad_top: 10px | ||||||
|  |         shadow_color: light_blue | ||||||
|  |         shadow_ofs_x: 5 | ||||||
|  |         shadow_ofs_y: 5 | ||||||
|  |         shadow_opa: cover | ||||||
|  |         shadow_spread: 5 | ||||||
|  |         shadow_width: 10 | ||||||
|  |         text_align: auto | ||||||
|  |         text_color: light_blue | ||||||
|  |         text_decor: [underline, strikethrough] | ||||||
|  |         text_font: montserrat_18 | ||||||
|  |         text_letter_space: 4 | ||||||
|  |         text_line_space: 4 | ||||||
|  |         text_opa: cover | ||||||
|  |         transform_angle: 180 | ||||||
|  |         transform_height: 100 | ||||||
|  |         transform_pivot_x: 50% | ||||||
|  |         transform_pivot_y: 50% | ||||||
|  |         transform_zoom: 0.5 | ||||||
|  |         translate_x: 10 | ||||||
|  |         translate_y: 10 | ||||||
|  |         max_height: 100 | ||||||
|  |         max_width: 200 | ||||||
|  |         min_height: 20% | ||||||
|  |         min_width: 20% | ||||||
|  |         radius: circle | ||||||
|  |         width: 10px | ||||||
|  |         x: 100 | ||||||
|  |         y: 120 | ||||||
|  |     - button: | ||||||
|  |         width: 20% | ||||||
|  |         height: 10% | ||||||
|  |         pressed: | ||||||
|  |           bg_color: light_blue | ||||||
|  |         widgets: | ||||||
|  |           - label: | ||||||
|  |               text: Button | ||||||
|  |  | ||||||
| font: | font: | ||||||
|   - file: "gfonts://Roboto" |   - file: "gfonts://Roboto" | ||||||
|     id: space16 |     id: space16 | ||||||
|     bpp: 4 |     bpp: 4 | ||||||
|  |  | ||||||
|  | image: | ||||||
|  |   - id: cat_img | ||||||
|  |     resize: 256x48 | ||||||
|  |     file: $component_dir/logo-text.svg | ||||||
|  |   - id: dog_img | ||||||
|  |     file: $component_dir/logo-text.svg | ||||||
|  |     resize: 256x48 | ||||||
|  |     type: TRANSPARENT_BINARY | ||||||
|  |  | ||||||
|  | color: | ||||||
|  |   - id: light_blue | ||||||
|  |     hex: "3340FF" | ||||||
|   | |||||||
| @@ -19,7 +19,9 @@ display: | |||||||
|       mirror_y: true |       mirror_y: true | ||||||
|     data_rate: 80MHz |     data_rate: 80MHz | ||||||
|     cs_pin: GPIO20 |     cs_pin: GPIO20 | ||||||
|     dc_pin: GPIO15 |     dc_pin: | ||||||
|  |       number: GPIO15 | ||||||
|  |       ignore_strapping_warning: true | ||||||
|     auto_clear_enabled: false |     auto_clear_enabled: false | ||||||
|     invert_colors: false |     invert_colors: false | ||||||
|     update_interval: never |     update_interval: never | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user