From e39f8f1072b3ef5bbe8a74ad226e3a65d91a3e77 Mon Sep 17 00:00:00 2001 From: Oliver Kleinecke Date: Wed, 19 Feb 2025 16:35:53 +0100 Subject: [PATCH] fix: update save mode handling and enhance timer restoration logic --- esphome/components/dynamic_lamp/__init__.py | 2 +- .../components/dynamic_lamp/dynamic_lamp.cpp | 100 +++++++++++++++--- .../components/dynamic_lamp/dynamic_lamp.h | 8 +- 3 files changed, 92 insertions(+), 18 deletions(-) diff --git a/esphome/components/dynamic_lamp/__init__.py b/esphome/components/dynamic_lamp/__init__.py index 64478ecf5b..5cc07288cd 100644 --- a/esphome/components/dynamic_lamp/__init__.py +++ b/esphome/components/dynamic_lamp/__init__.py @@ -23,7 +23,7 @@ CONFIG_SCHEMA = cv.Schema({ cv.Required(CONF_RTC): cv.use_id(RealTimeClock), cv.Required(CONF_FRAM): cv.use_id(FRAMComponent), cv.Required(CONF_AVAILABLE_OUTPUTS): [cv.use_id(output.FloatOutput)], - cv.Optional(CONF_SAVE_MODE, default=0): cv.int_range(0, 1), + cv.Optional(CONF_SAVE_MODE, default=0): cv.int_range(0, 2), }).extend(cv.COMPONENT_SCHEMA) diff --git a/esphome/components/dynamic_lamp/dynamic_lamp.cpp b/esphome/components/dynamic_lamp/dynamic_lamp.cpp index c1db3d9cad..5d9e6400f6 100644 --- a/esphome/components/dynamic_lamp/dynamic_lamp.cpp +++ b/esphome/components/dynamic_lamp/dynamic_lamp.cpp @@ -23,17 +23,8 @@ void DynamicLampComponent::setup() { } void DynamicLampComponent::begin() { - uint8_t i = 0; - bool valid = true; - if(this->save_mode_ == 0) { - for (i=0; i < 16; i++) { - this->active_lamps_[i].active = false; - } - } else { - while(i < 16) { - this->restore_lamp_values_(i); - } - } + this->restore_lamp_settings_(); + this->restore_timers_(); /* keep example for future reference this->add_lamp("First Lamp"); this->add_output_to_lamp("First Lamp", &this->available_outputs_[0]); @@ -274,8 +265,20 @@ bool DynamicLampComponent::add_timer(std::string timer_desc, std::string lamp_li ESP_LOGV(TAG, "Added new timer %s with lamp-list %s, active %d, action %d, hour %d, minute %d, monday %d, tuesday %d, wednesday %d, thursday %d, friday %d, saturday %d, sunday %d", new_timer.timer_desc, lamp_list_str.c_str(), new_timer.active, new_timer.action, new_timer.hour, new_timer.minute, new_timer.monday, new_timer.tuesday, new_timer.wednesday, new_timer.thursday, new_timer.friday, new_timer.saturday, new_timer.sunday); - ESP_LOGV(TAG, "Size of struct is %" PRIu8 "", static_cast(sizeof(new_timer))); - this->fram_->write((2048), timer_as_bytes, 64); + //ESP_LOGV(TAG, "Size of struct is %" PRIu8 "", static_cast(sizeof(new_timer))); + uint8_t save_slot; + for (save_slot = 0; save_slot < 256; save_slot++) { + if (!this->timers_[save_slot].in_use) { + break; + } + } + if (save_slot == 256) { + ESP_LOGW(TAG, "No more timer slots available, max 256 timers supported!"); + this->status_set_warning(); + return false; + } + this->timers_[save_slot] = new_timer; + this->fram_->write((0x4000 + (save_slot * 64)), timer_as_bytes, 64); return true; } @@ -338,8 +341,75 @@ void DynamicLampComponent::set_lamp_values_(uint8_t lamp_number, bool active, ui } -void DynamicLampComponent::restore_lamp_values_(uint8_t lamp_number) { - this->active_lamps_[lamp_number].active = false; +void DynamicLampComponent::restore_lamp_settings_() { + switch (this->save_mode_) { + case SAVE_MODE_NONE: + for (uint8_t i=0; i < 16; i++) { + this->active_lamps_[i].active = false; + } + break; + case SAVE_MODE_LOCAL: + // ToDo - yet to be implemented + ESP_LOGW(TAG, "Save mode LOCAL not implemented yet, sorry"); + this->status_set_warning(); + break; + case SAVE_MODE_FRAM: + // ToDo - yet to be implemented + //ESP_LOGW(TAG, "Save mode FRAM not implemented yet, sorry"); + //this->status_set_warning(); + break; + default: + ESP_LOGW(TAG, "Currently only NONE(0), LOCAL(1) & FRAM(2) save modes supported, ignoring value %" PRIu8 " and defaulting to NONE!", this->save_mode_); + this->save_mode_ = 0; + } +} + +void DynamicLampComponent::restore_timers_() { + switch (this->save_mode_) { + case SAVE_MODE_NONE: + for (uint8_t i = 0; i < 256; i++) { + this->timers_[i] = Dynamic_LampTimer(); + this->timers_[i].in_use = false; + } + break; + case SAVE_MODE_LOCAL: + // ToDo - yet to be implemented + ESP_LOGW(TAG, "Save mode LOCAL not implemented yet, sorry"); + this->status_set_warning(); + break; + case SAVE_MODE_FRAM: + DynamicLampTimer timer; + std::string lamp_names_str; + for (uint8_t i = 0; i < 256; i++) { + this->fram_->read((0x4000h + (i * 64)), reinterpret_cast(&timer), 64); + if (timer.validation_bytes == {'V', 'D', 'L', 'T'} && timer.in_use) { + this->timers_[i] = timer; + lamp_names_str = ""; + for (uint8_t j = 0; j < 16; j++) { + bool lamp_included = static_cast(timer.lamp_list[j / 8] & (1 << (j % 8))); + if (lamp_included && this->active_lamps_[j].active) { + if (lamp_names_str.length() > 0) { + lamp_names_str += ", "; + } + lamp_names_str += this->active_lamps_[j].name; + } + } + ESP_LOGVV(TAG, "Restored valid timer record %s in save slot %" PRIu8 "", i, timer.timer_desc); + ESP_LOGVV(TAG, "Timer %s found: [ active: %d, action: %d, hour: %d, minute: %d, monday: %d, tuesday: %d, wednesday: %d, thursday: %d, friday: %d, saturday: %d, sunday: %d ]", + timer.timer_desc, timer.active, timer.action, timer.hour, timer.minute, timer.monday, timer.tuesday, + timer.wednesday, timer.thursday, timer.friday, timer.saturday, timer.sunday); + ESP_LOGVV(TAG, "Timer active for lamps %s", lamp_names_str.c_str()); + } else { + this->timers_[i] = Dynamic_LampTimer(); + this->timers_[i].in_use = false; + ESP_LOGVV(TAG, "Timer save slot %" PRIu8 " did not contain valid record, initializing unused empty timer slot", i); + } + } + break; + default: + ESP_LOGW(TAG, "Currently only NONE(0), LOCAL(1) & FRAM(2) save modes supported, ignoring value %" PRIu8 " and defaulting to NONE!", this->save_mode_); + this->save_mode_ = 0; + } } std::vector DynamicLampComponent::split_to_int_vector_(std::string lamp_list_str) { diff --git a/esphome/components/dynamic_lamp/dynamic_lamp.h b/esphome/components/dynamic_lamp/dynamic_lamp.h index 35392315fa..7bfcccadfe 100644 --- a/esphome/components/dynamic_lamp/dynamic_lamp.h +++ b/esphome/components/dynamic_lamp/dynamic_lamp.h @@ -69,8 +69,10 @@ struct CombinedLamp { }; struct DynamicLampTimer { - unsigned char timer_desc[40]; + unsigned char validation_bytes[4] = {'V', 'D', 'L', 'T'}; + unsigned char timer_desc[36]; unsigned char lamp_list[2]; + bool in_use : 1; uint8_t action : 3; uint8_t hour : 5; uint8_t minute : 6; @@ -113,7 +115,8 @@ class DynamicLampComponent : public Component { friend class DynamicLamp; time::RealTimeClock *rtc_; fram::FRAM *fram_; - void restore_lamp_values_(uint8_t lamp_number); + void restore_lamp_settings_(uint8_t lamp_number); + void restore_timers_(uint8_t lamp_number); void set_lamp_values_(uint8_t lamp_number, bool active, uint16_t selected_outputs, uint8_t mode, uint8_t mode_value); bool write_state_(uint8_t lamp_number, float state); uint8_t get_lamp_index_by_name_(std::string lamp_name); @@ -123,6 +126,7 @@ class DynamicLampComponent : public Component { CombinedLamp active_lamps_[16]; LinkedOutput available_outputs_[16]; + Dynamic_LampTimer timers_[256]; uint8_t save_mode_; uint8_t lamp_count_ = 0; };