#include "wordclock.h" namespace esphome { namespace wordclock { void Wordclock::setup() { this->valid_time = this->time->now().is_valid(); if (!this->valid_time) { this->start_idle_animation(); } // this->valid_time = true; } void Wordclock::update() { esphome::time::ESPTime time = this->time->now(); if (!time.is_valid()) { if (this->valid_time) { ESP_LOGD("wordclock.cpp", "time is not valid [%02i:%02i:%02i]", time.hour, time.minute, time.second); this->start_idle_animation(); this->valid_time = false; return; } } else { if (!this->valid_time) { ESP_LOGD("wordclock.cpp", "time is valid [%02i:%02i:%02i]", time.hour, time.minute, time.second); this->end_idle_animation(); this->valid_time = true; return; } bool dirty = false; int8_t minute = this->find_minute(time.minute); int8_t hour = this->find_hour((time.hour + this->minutes->at(minute).hour_offset) % 24); if (hour != this->current_hour) { this->current_hour = hour; dirty = true; } if (minute != this->current_minute) { this->current_minute = minute; dirty = true; } if (dirty) { this->previous_segments->clear(); for (uint16_t segment_idx : *this->current_segments) { this->previous_segments->push_back(segment_idx); } // std::sort(this->previous_segments->begin(), this->previous_segments->end()); // std::sort(s.begin(), s.end(), [](int a, int b) // { // return a > b; // }); this->current_segments->clear(); for (uint16_t segment_idx : *this->static_segments) { this->current_segments->push_back(segment_idx); // this->draw_segment(segment_idx); } for (uint16_t segment_idx : *(this->minutes->at(minute).segments)) { this->current_segments->push_back(segment_idx); // this->draw_segment(segment_idx); } for (uint16_t segment_idx : *(this->hours->at(hour).segments)) { this->current_segments->push_back(segment_idx); // this->draw_segment(segment_idx); } std::sort(this->current_segments->begin(), this->current_segments->end()); this->find_difference(this->previous_segments, this->current_segments); // ESP_LOGD("wordclock.cpp", "reset"); this->on_transformer->reset(); this->off_transformer->reset(); } // Color on = this->on_color * this->on_transformer->apply().value_or(255); // Color off = this->off_color * this->off_transformer->apply().value_or(255); this->current_position = 0; uint8_t transition_progress = this->on_transformer->apply().value_or(255); // uint8_t on_progress = this->on_transformer->apply().value_or(255); // uint8_t off_progress = this->off_transformer->apply().value_or(255); // ESP_LOGD("wordclock.cpp", "off progress [%d]", off_progress); // Color added_color = this->off_color.gradient(this->on_color, transition_progress); Color removed_color = this->on_color.gradient(this->off_color, transition_progress); // ESP_LOGD("wordclock.cpp", "transition progress [%d], added [0x%06x], removed [0x%06x]", transition_progress, added_color.raw_32, removed_color.raw_32); for (uint16_t segment_idx : *this->removed_segments) { // ESP_LOGD("wordclock.cpp", "off [%d]", segment_idx); // this->disable_segment(segment_idx, this->off_color, transition_progress); this->disable_segment_effect(segment_idx, this->off_color, transition_progress); // this->disable_segment(segment_idx, removed_color); // this->draw_segment(segment_idx, off_progress); } for (uint16_t segment_idx : *this->added_segments) { // ESP_LOGD("wordclock.cpp", "on [%d]", segment_idx); // this->segment_effect_base(segment_idx, this->off_color, transition_progress); this->enable_segment_effect(segment_idx, this->off_color, transition_progress); // this->draw_segment(segment_idx, on_progress); } for (uint16_t segment_idx : *this->staying_segments) { this->apply_segment_effect(segment_idx); } } } void Wordclock::find_difference(std::vector *a_vec, std::vector *b_vec) { // for (uint16_t segment_idx : a) { // this->current_segments->push_back(segment_idx); // } this->added_segments->clear(); this->removed_segments->clear(); this->staying_segments->clear(); auto a = a_vec->begin(); auto b = b_vec->begin(); while (!(a == a_vec->end() && b == b_vec->end())) { if (a == a_vec->end()) { this->added_segments-> push_back(*b); b++; } else if (b == b_vec->end()) { this->removed_segments->push_back(*a); a++; } else if (*a > *b) { this->added_segments-> push_back(*b); b++; } else if (*a < *b) { this->removed_segments->push_back(*a); a++; } else if (*a == *b) { this->staying_segments->push_back(*a); a++; b++; } } } Color Wordclock::get_next_color(uint32_t position, const Color ¤t_color) { uint32_t speed_ = 3; uint16_t width_ = 100; // uint16_t width_ = 50; esphome::light::ESPHSVColor hsv; hsv.value = 255; hsv.saturation = 240; hsv.hue = ((millis() * speed_ + (position * (0xFFFF / width_))) % 0xFFFF) >> 8; // hsv.hue = hue >> 8; return hsv.to_rgb(); } int8_t Wordclock::find_hour(uint8_t target_value) { std::vector *elements = this->hours; for (int i = 0; i < elements->size(); i++) { if (elements->at(i).hour == target_value) { return i; } else if (elements->at(i).hour > target_value) { return i - 1; } } return elements->size() - 1; // uint16_t last_defined_index = -1; // for (int i = 0; i < elements->size(); i++) { // if (elements->at(i).size()) { // last_defined_index = i; // } // if (i >= target_value) break; // } // return last_defined_index; } int8_t Wordclock::find_minute(uint8_t target_value) { std::vector *elements = this->minutes; for (int i = 0; i < elements->size(); i++) { if (elements->at(i).minute == target_value) { return i; } else if (elements->at(i).minute > target_value) { return i - 1; } } return elements->size() - 1; } void Wordclock::setup_transitions(uint32_t milliseconds) { this->on_transformer->setup(0, this->brightness, milliseconds); this->off_transformer->setup(this->brightness, 0, milliseconds); } // Wordclock::Wordclock() : PollingComponent(1000) { // } Wordclock::Wordclock( esphome::time::RealTimeClock *time, esphome::addressable_light::AddressableLightDisplay *display, esphome::light::AddressableLightState *light_state) { this->time = time; this->display = display; this->light_state = light_state; this->light_state->set_default_transition_length(1); this->minutes = new std::vector(); this->hours = new std::vector(); this->segments = new std::vector(); this->static_segments = new std::vector(); this->previous_segments = new std::vector(); this->current_segments = new std::vector(); this->added_segments = new std::vector(); this->removed_segments = new std::vector(); this->staying_segments = new std::vector(); this->on_transformer = new BrightnessTransitionTransformer(); // this->on_transformer->setup(0, this->brightness, 700); this->off_transformer = new BrightnessTransitionTransformer(); // this->off_transformer->setup(this->brightness, 0, 700); // wordclock_wordclock->add_segment(wordclock::SegmentCoords{ // .x1 = 0, // .x2 = 4, // .y1 = 8, // .y2 = 8, // }); // this->hour_offsets = new std::vector(60, 0); // this->minutes = new std::vector>(60, std::vector()); // this->hours = new std::vector>(24, std::vector()); } } // namespace wordclock } // namespace esphome