mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	wip
This commit is contained in:
		| @@ -23,6 +23,9 @@ from esphome.const import ( | ||||
| from .. import template_ns | ||||
|  | ||||
| TemplateCover = template_ns.class_("TemplateCover", cover.Cover, cg.Component) | ||||
| StatelessTemplateCover = template_ns.class_( | ||||
|     "StatelessTemplateCover", cover.Cover, cg.Component | ||||
| ) | ||||
|  | ||||
| TemplateCoverRestoreMode = template_ns.enum("TemplateCoverRestoreMode") | ||||
| RESTORE_MODES = { | ||||
| @@ -63,13 +66,22 @@ CONFIG_SCHEMA = ( | ||||
|  | ||||
|  | ||||
| async def to_code(config): | ||||
|     var = await cover.new_cover(config) | ||||
|     await cg.register_component(var, config) | ||||
|     if CONF_LAMBDA in config: | ||||
|         # Use new_lambda_pvariable to create either TemplateCover or StatelessTemplateCover | ||||
|         template_ = await cg.process_lambda( | ||||
|             config[CONF_LAMBDA], [], return_type=cg.optional.template(float) | ||||
|         ) | ||||
|         cg.add(var.set_state_lambda(template_)) | ||||
|         var = automation.new_lambda_pvariable( | ||||
|             config[CONF_ID], template_, StatelessTemplateCover | ||||
|         ) | ||||
|         # Manually register as cover since we didn't use new_cover | ||||
|         await cover.register_cover(var, config) | ||||
|         await cg.register_component(var, config) | ||||
|     else: | ||||
|         # No state lambda - just create the base template cover | ||||
|         var = await cover.new_cover(config) | ||||
|         await cg.register_component(var, config) | ||||
|  | ||||
|     if CONF_OPEN_ACTION in config: | ||||
|         await automation.build_automation( | ||||
|             var.get_open_trigger(), [], config[CONF_OPEN_ACTION] | ||||
|   | ||||
| @@ -76,7 +76,8 @@ template<typename StateF, typename TiltF> void TemplateCoverBase<StateF, TiltF>: | ||||
|  | ||||
|   this->publish_state(); | ||||
| } | ||||
| CoverTraits TemplateCover::get_traits() { | ||||
|  | ||||
| template<typename StateF, typename TiltF> CoverTraits TemplateCoverBase<StateF, TiltF>::get_traits() { | ||||
|   auto traits = CoverTraits(); | ||||
|   traits.set_is_assumed_state(this->assumed_state_); | ||||
|   traits.set_supports_stop(this->has_stop_); | ||||
| @@ -85,19 +86,16 @@ CoverTraits TemplateCover::get_traits() { | ||||
|   traits.set_supports_tilt(this->has_tilt_); | ||||
|   return traits; | ||||
| } | ||||
| Trigger<float> *TemplateCover::get_position_trigger() const { return this->position_trigger_; } | ||||
| Trigger<float> *TemplateCover::get_tilt_trigger() const { return this->tilt_trigger_; } | ||||
| void TemplateCover::set_tilt_lambda(std::function<optional<float>()> &&tilt_f) { this->tilt_f_ = tilt_f; } | ||||
| void TemplateCover::set_has_stop(bool has_stop) { this->has_stop_ = has_stop; } | ||||
| void TemplateCover::set_has_toggle(bool has_toggle) { this->has_toggle_ = has_toggle; } | ||||
| void TemplateCover::set_has_position(bool has_position) { this->has_position_ = has_position; } | ||||
| void TemplateCover::set_has_tilt(bool has_tilt) { this->has_tilt_ = has_tilt; } | ||||
| void TemplateCover::stop_prev_trigger_() { | ||||
|  | ||||
| template<typename StateF, typename TiltF> void TemplateCoverBase<StateF, TiltF>::stop_prev_trigger_() { | ||||
|   if (this->prev_command_trigger_ != nullptr) { | ||||
|     this->prev_command_trigger_->stop_action(); | ||||
|     this->prev_command_trigger_ = nullptr; | ||||
|   } | ||||
| } | ||||
|  | ||||
| template class TemplateCoverBase<std::function<optional<float>()>, std::function<optional<float>()>>; | ||||
| template class TemplateCoverBase<optional<float> (*)(), optional<float> (*)()>; | ||||
|  | ||||
| }  // namespace template_ | ||||
| }  // namespace esphome | ||||
|   | ||||
| @@ -16,6 +16,9 @@ from esphome.const import ( | ||||
| from .. import template_ns | ||||
|  | ||||
| TemplateLock = template_ns.class_("TemplateLock", lock.Lock, cg.Component) | ||||
| StatelessTemplateLock = template_ns.class_( | ||||
|     "StatelessTemplateLock", lock.Lock, cg.Component | ||||
| ) | ||||
|  | ||||
| TemplateLockPublishAction = template_ns.class_( | ||||
|     "TemplateLockPublishAction", | ||||
|   | ||||
| @@ -8,19 +8,8 @@ using namespace esphome::lock; | ||||
|  | ||||
| static const char *const TAG = "template.lock"; | ||||
|  | ||||
| TemplateLock::TemplateLock() | ||||
|     : lock_trigger_(new Trigger<>()), unlock_trigger_(new Trigger<>()), open_trigger_(new Trigger<>()) {} | ||||
|  | ||||
| void TemplateLock::loop() { | ||||
|   if (!this->f_.has_value()) | ||||
|     return; | ||||
|   auto val = (*this->f_)(); | ||||
|   if (!val.has_value()) | ||||
|     return; | ||||
|  | ||||
|   this->publish_state(*val); | ||||
| } | ||||
| void TemplateLock::control(const lock::LockCall &call) { | ||||
| // Template instantiations | ||||
| template<typename F> void TemplateLockBase<F>::control(const lock::LockCall &call) { | ||||
|   if (this->prev_trigger_ != nullptr) { | ||||
|     this->prev_trigger_->stop_action(); | ||||
|   } | ||||
| @@ -37,23 +26,22 @@ void TemplateLock::control(const lock::LockCall &call) { | ||||
|   if (this->optimistic_) | ||||
|     this->publish_state(state); | ||||
| } | ||||
| void TemplateLock::open_latch() { | ||||
|  | ||||
| template<typename F> void TemplateLockBase<F>::open_latch() { | ||||
|   if (this->prev_trigger_ != nullptr) { | ||||
|     this->prev_trigger_->stop_action(); | ||||
|   } | ||||
|   this->prev_trigger_ = this->open_trigger_; | ||||
|   this->open_trigger_->trigger(); | ||||
| } | ||||
| void TemplateLock::set_optimistic(bool optimistic) { this->optimistic_ = optimistic; } | ||||
| void TemplateLock::set_state_lambda(std::function<optional<lock::LockState>()> &&f) { this->f_ = f; } | ||||
| float TemplateLock::get_setup_priority() const { return setup_priority::HARDWARE; } | ||||
| Trigger<> *TemplateLock::get_lock_trigger() const { return this->lock_trigger_; } | ||||
| Trigger<> *TemplateLock::get_unlock_trigger() const { return this->unlock_trigger_; } | ||||
| Trigger<> *TemplateLock::get_open_trigger() const { return this->open_trigger_; } | ||||
| void TemplateLock::dump_config() { | ||||
|  | ||||
| template<typename F> void TemplateLockBase<F>::dump_config() { | ||||
|   LOG_LOCK("", "Template Lock", this); | ||||
|   ESP_LOGCONFIG(TAG, "  Optimistic: %s", YESNO(this->optimistic_)); | ||||
| } | ||||
|  | ||||
| template class TemplateLockBase<std::function<optional<lock::LockState>()>>; | ||||
| template class TemplateLockBase<optional<lock::LockState> (*)()>; | ||||
|  | ||||
| }  // namespace template_ | ||||
| }  // namespace esphome | ||||
|   | ||||
| @@ -7,26 +7,35 @@ | ||||
| namespace esphome { | ||||
| namespace template_ { | ||||
|  | ||||
| class TemplateLock : public lock::Lock, public Component { | ||||
| template<typename F> class TemplateLockBase : public lock::Lock, public Component { | ||||
|  public: | ||||
|   TemplateLock(); | ||||
|   TemplateLockBase() | ||||
|       : lock_trigger_(new Trigger<>()), unlock_trigger_(new Trigger<>()), open_trigger_(new Trigger<>()) {} | ||||
|  | ||||
|   void loop() override { | ||||
|     if (!this->f_.has_value()) | ||||
|       return; | ||||
|     auto val = (*this->f_)(); | ||||
|     if (!val.has_value()) | ||||
|       return; | ||||
|  | ||||
|     this->publish_state(*val); | ||||
|   } | ||||
|  | ||||
|   void dump_config() override; | ||||
|  | ||||
|   void set_state_lambda(std::function<optional<lock::LockState>()> &&f); | ||||
|   Trigger<> *get_lock_trigger() const; | ||||
|   Trigger<> *get_unlock_trigger() const; | ||||
|   Trigger<> *get_open_trigger() const; | ||||
|   void set_optimistic(bool optimistic); | ||||
|   void loop() override; | ||||
|   Trigger<> *get_lock_trigger() const { return this->lock_trigger_; } | ||||
|   Trigger<> *get_unlock_trigger() const { return this->unlock_trigger_; } | ||||
|   Trigger<> *get_open_trigger() const { return this->open_trigger_; } | ||||
|   void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; } | ||||
|  | ||||
|   float get_setup_priority() const override; | ||||
|   float get_setup_priority() const override { return setup_priority::HARDWARE; } | ||||
|  | ||||
|  protected: | ||||
|   void control(const lock::LockCall &call) override; | ||||
|   void open_latch() override; | ||||
|  | ||||
|   optional<std::function<optional<lock::LockState>()>> f_; | ||||
|   optional<F> f_; | ||||
|   bool optimistic_{false}; | ||||
|   Trigger<> *lock_trigger_; | ||||
|   Trigger<> *unlock_trigger_; | ||||
| @@ -34,5 +43,20 @@ class TemplateLock : public lock::Lock, public Component { | ||||
|   Trigger<> *prev_trigger_{nullptr}; | ||||
| }; | ||||
|  | ||||
| class TemplateLock : public TemplateLockBase<std::function<optional<lock::LockState>()>> { | ||||
|  public: | ||||
|   void set_state_lambda(std::function<optional<lock::LockState>()> &&f) { this->f_ = f; } | ||||
| }; | ||||
|  | ||||
| /** Optimized template lock for stateless lambdas (no capture). | ||||
|  * | ||||
|  * Uses function pointers instead of std::function to reduce memory overhead. | ||||
|  * Memory: 4 bytes (function pointer on 32-bit) vs 32 bytes (std::function) per lambda. | ||||
|  */ | ||||
| class StatelessTemplateLock : public TemplateLockBase<optional<lock::LockState> (*)()> { | ||||
|  public: | ||||
|   explicit StatelessTemplateLock(optional<lock::LockState> (*f)()) { this->f_ = f; } | ||||
| }; | ||||
|  | ||||
| }  // namespace template_ | ||||
| }  // namespace esphome | ||||
|   | ||||
		Reference in New Issue
	
	Block a user