From 57a52d37a929e7c42a6b31d0136d3bdb1e8a3609 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 21 Jan 2026 18:39:08 -1000 Subject: [PATCH 1/3] schema tweaks --- esphome/components/globals/__init__.py | 5 +---- tests/components/globals/common.yaml | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/esphome/components/globals/__init__.py b/esphome/components/globals/__init__.py index eb2948db8f..08c1c38b01 100644 --- a/esphome/components/globals/__init__.py +++ b/esphome/components/globals/__init__.py @@ -40,9 +40,8 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_INITIAL_VALUE): cv.string_strict, cv.Optional(CONF_RESTORE_VALUE, default=False): cv.boolean, cv.Optional(CONF_MAX_RESTORE_DATA_LENGTH): cv.int_range(0, 254), - cv.Optional(CONF_UPDATE_INTERVAL): cv.update_interval, } - ).extend(cv.COMPONENT_SCHEMA), + ).extend(cv.polling_component_schema("1s")), validate_update_interval, ) @@ -78,8 +77,6 @@ async def to_code(config): value = value.encode() hash_ = int(hashlib.md5(value).hexdigest()[:8], 16) cg.add(glob.set_name_hash(hash_)) - if CONF_UPDATE_INTERVAL in config: - cg.add(glob.set_update_interval(config[CONF_UPDATE_INTERVAL])) @automation.register_action( diff --git a/tests/components/globals/common.yaml b/tests/components/globals/common.yaml index 224a91a270..efa3cba076 100644 --- a/tests/components/globals/common.yaml +++ b/tests/components/globals/common.yaml @@ -10,6 +10,7 @@ globals: type: int restore_value: true initial_value: "0" + update_interval: 5s - id: glob_float type: float restore_value: true From 57b3820500d18fdea83b5ad0879e35997d868012 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 21 Jan 2026 18:40:54 -1000 Subject: [PATCH 2/3] revert --- esphome/components/globals/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/globals/__init__.py b/esphome/components/globals/__init__.py index 08c1c38b01..eb2948db8f 100644 --- a/esphome/components/globals/__init__.py +++ b/esphome/components/globals/__init__.py @@ -40,8 +40,9 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_INITIAL_VALUE): cv.string_strict, cv.Optional(CONF_RESTORE_VALUE, default=False): cv.boolean, cv.Optional(CONF_MAX_RESTORE_DATA_LENGTH): cv.int_range(0, 254), + cv.Optional(CONF_UPDATE_INTERVAL): cv.update_interval, } - ).extend(cv.polling_component_schema("1s")), + ).extend(cv.COMPONENT_SCHEMA), validate_update_interval, ) @@ -77,6 +78,8 @@ async def to_code(config): value = value.encode() hash_ = int(hashlib.md5(value).hexdigest()[:8], 16) cg.add(glob.set_name_hash(hash_)) + if CONF_UPDATE_INTERVAL in config: + cg.add(glob.set_update_interval(config[CONF_UPDATE_INTERVAL])) @automation.register_action( From 1ac259e9c5b761898f153b92565070986b5e273f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 21 Jan 2026 19:04:56 -1000 Subject: [PATCH 3/3] split schema --- esphome/components/globals/__init__.py | 51 ++++++++++++++++---------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/esphome/components/globals/__init__.py b/esphome/components/globals/__init__.py index eb2948db8f..fc400c5dd1 100644 --- a/esphome/components/globals/__init__.py +++ b/esphome/components/globals/__init__.py @@ -6,10 +6,10 @@ from esphome.const import ( CONF_INITIAL_VALUE, CONF_RESTORE_VALUE, CONF_TYPE, - CONF_UPDATE_INTERVAL, CONF_VALUE, ) from esphome.core import CoroPriority, coroutine_with_priority +from esphome.types import ConfigType CODEOWNERS = ["@esphome/core"] globals_ns = cg.esphome_ns.namespace("globals") @@ -24,27 +24,40 @@ GlobalVarSetAction = globals_ns.class_("GlobalVarSetAction", automation.Action) CONF_MAX_RESTORE_DATA_LENGTH = "max_restore_data_length" +# Base schema fields shared by both variants +_BASE_SCHEMA = { + cv.Required(CONF_ID): cv.declare_id(GlobalsComponent), + cv.Required(CONF_TYPE): cv.string_strict, + cv.Optional(CONF_INITIAL_VALUE): cv.string_strict, + cv.Optional(CONF_MAX_RESTORE_DATA_LENGTH): cv.int_range(0, 254), +} -def validate_update_interval(config): - if CONF_UPDATE_INTERVAL in config and not config.get(CONF_RESTORE_VALUE, False): - raise cv.Invalid("update_interval requires restore_value to be true") - return config +# Non-restoring globals: regular Component (no polling needed) +_NON_RESTORING_SCHEMA = cv.Schema( + { + **_BASE_SCHEMA, + cv.Optional(CONF_RESTORE_VALUE, default=False): cv.boolean, + } +).extend(cv.COMPONENT_SCHEMA) + +# Restoring globals: PollingComponent with configurable update_interval +_RESTORING_SCHEMA = cv.Schema( + { + **_BASE_SCHEMA, + cv.Optional(CONF_RESTORE_VALUE, default=True): cv.boolean, + } +).extend(cv.polling_component_schema("1s")) + + +def _globals_schema(config: ConfigType) -> ConfigType: + """Select schema based on restore_value setting.""" + if config.get(CONF_RESTORE_VALUE, False): + return _RESTORING_SCHEMA(config) + return _NON_RESTORING_SCHEMA(config) MULTI_CONF = True -CONFIG_SCHEMA = cv.All( - cv.Schema( - { - cv.Required(CONF_ID): cv.declare_id(GlobalsComponent), - cv.Required(CONF_TYPE): cv.string_strict, - cv.Optional(CONF_INITIAL_VALUE): cv.string_strict, - cv.Optional(CONF_RESTORE_VALUE, default=False): cv.boolean, - cv.Optional(CONF_MAX_RESTORE_DATA_LENGTH): cv.int_range(0, 254), - cv.Optional(CONF_UPDATE_INTERVAL): cv.update_interval, - } - ).extend(cv.COMPONENT_SCHEMA), - validate_update_interval, -) +CONFIG_SCHEMA = _globals_schema # Run with low priority so that namespaces are registered first @@ -78,8 +91,6 @@ async def to_code(config): value = value.encode() hash_ = int(hashlib.md5(value).hexdigest()[:8], 16) cg.add(glob.set_name_hash(hash_)) - if CONF_UPDATE_INTERVAL in config: - cg.add(glob.set_update_interval(config[CONF_UPDATE_INTERVAL])) @automation.register_action(