diff --git a/esphome/components/touchscreen/__init__.py b/esphome/components/touchscreen/__init__.py index 5417878b1c..400ba7d5ad 100644 --- a/esphome/components/touchscreen/__init__.py +++ b/esphome/components/touchscreen/__init__.py @@ -7,6 +7,7 @@ from esphome import automation from esphome.const import ( CONF_ON_TOUCH, CONF_ON_RELEASE, + CONF_ON_UPDATE, CONF_SWAP_XY, CONF_MIRROR_X, CONF_MIRROR_Y, @@ -33,7 +34,6 @@ TouchListener = touchscreen_ns.class_("TouchListener") CONF_DISPLAY = "display" CONF_TOUCHSCREEN_ID = "touchscreen_id" CONF_REPORT_INTERVAL = "report_interval" # not used yet: -CONF_ON_UPDATE = "on_update" CONF_TOUCH_TIMEOUT = "touch_timeout" diff --git a/esphome/const.py b/esphome/const.py index 044465de7b..ed0fdf4fa9 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -537,6 +537,7 @@ CONF_ON_TOUCH = "on_touch" CONF_ON_TURN_OFF = "on_turn_off" CONF_ON_TURN_ON = "on_turn_on" CONF_ON_UNLOCK = "on_unlock" +CONF_ON_UPDATE = "on_update" CONF_ON_VALUE = "on_value" CONF_ON_VALUE_RANGE = "on_value_range" CONF_ONE = "one" diff --git a/esphome/core/base_automation.h b/esphome/core/base_automation.h index 50087f3efd..b0ae0aff84 100644 --- a/esphome/core/base_automation.h +++ b/esphome/core/base_automation.h @@ -2,6 +2,8 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" +#include "esphome/core/defines.h" +#include "esphome/core/preferences.h" #include @@ -125,6 +127,27 @@ class LoopTrigger : public Trigger<>, public Component { float get_setup_priority() const override { return setup_priority::DATA; } }; +#ifdef ESPHOME_PROJECT_NAME +class ProjectUpdateTrigger : public Trigger, public Component { + public: + void setup() override { + uint32_t hash = fnv1_hash(ESPHOME_PROJECT_NAME); + ESPPreferenceObject pref = global_preferences->make_preference(hash, true); + char previous_version[30]; + char current_version[30] = ESPHOME_PROJECT_VERSION; + if (pref.load(&previous_version)) { + int cmp = strcmp(previous_version, current_version); + if (cmp < 0) { + this->trigger(previous_version); + } + } + pref.save(¤t_version); + global_preferences->sync(); + } + float get_setup_priority() const override { return setup_priority::PROCESSOR; } +}; +#endif + template class DelayAction : public Action, public Component { public: explicit DelayAction() = default; diff --git a/esphome/core/config.py b/esphome/core/config.py index 7449d8850b..792f9da6dd 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -24,6 +24,7 @@ from esphome.const import ( CONF_ON_BOOT, CONF_ON_LOOP, CONF_ON_SHUTDOWN, + CONF_ON_UPDATE, CONF_PLATFORM, CONF_PLATFORMIO_OPTIONS, CONF_PRIORITY, @@ -52,6 +53,9 @@ ShutdownTrigger = cg.esphome_ns.class_( LoopTrigger = cg.esphome_ns.class_( "LoopTrigger", cg.Component, automation.Trigger.template() ) +ProjectUpdateTrigger = cg.esphome_ns.class_( + "ProjectUpdateTrigger", cg.Component, automation.Trigger.template(cg.std_string) +) VERSION_REGEX = re.compile(r"^[0-9]+\.[0-9]+\.[0-9]+(?:[ab]\d+)?$") @@ -151,6 +155,13 @@ CONFIG_SCHEMA = cv.All( cv.string_strict, valid_project_name ), cv.Required(CONF_VERSION): cv.string_strict, + cv.Optional(CONF_ON_UPDATE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + ProjectUpdateTrigger + ), + } + ), } ), cv.Optional(CONF_MIN_VERSION, default=ESPHOME_VERSION): cv.All( @@ -380,9 +391,15 @@ async def to_code(config): if config[CONF_INCLUDES]: CORE.add_job(add_includes, config[CONF_INCLUDES]) - if CONF_PROJECT in config: - cg.add_define("ESPHOME_PROJECT_NAME", config[CONF_PROJECT][CONF_NAME]) - cg.add_define("ESPHOME_PROJECT_VERSION", config[CONF_PROJECT][CONF_VERSION]) + if project_conf := config.get(CONF_PROJECT): + cg.add_define("ESPHOME_PROJECT_NAME", project_conf[CONF_NAME]) + cg.add_define("ESPHOME_PROJECT_VERSION", project_conf[CONF_VERSION]) + for conf in project_conf.get(CONF_ON_UPDATE, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID]) + await cg.register_component(trigger, conf) + await automation.build_automation( + trigger, [(cg.std_string, "version")], conf + ) if config[CONF_PLATFORMIO_OPTIONS]: CORE.add_job(_add_platformio_options, config[CONF_PLATFORMIO_OPTIONS])