esphome-wordclock/components/wordclock/wordclock.h

227 lines
9.4 KiB
C++

#pragma once
#include "esphome.h"
// By now only loosely based on https://github.com/leinich/ha-wordclock-esphome
// esphome dependencies:
// needs: esphome time --> id: current_time
// needs: esphome fastled --> id: fastledlight
// #ifdef USE_ESP32
namespace esphome {
namespace wordclock {
///// Word Table /////
// .line(0,0,1,0, color);
// .line(2,0,3,0, color);
// int WORD_IT_IS[5][2] = {{4,0}, {0,0}, {0,1}, {0,3}, {0,4}};
// // .line(2,1,8,1, color);
// int WORD_QUARTER[8][2] = {{7,0}, {1,2}, {1,3}, {1,4}, {1,5}, {1,6}, {1,7}, {1,8}};
// // .line(0,2, 5,2, color);
// int WORD_TWENTY[7][2] = {{6,0}, {2,0}, {2,1}, {2,2}, {2,3}, {2,4}, {2,5}};
// // .line(6,2, 9,2, color);
// int WORD_FIVE_MINUTES[5][2] = {{4,0}, {2,6}, {2,7}, {2,8}, {2,9}};
// // .line(0,3, 3,3, color);
// int WORD_HALF[5][2] = {{4,0}, {3,0}, {3,1}, {3,2}, {3,3}};
// // .line(5,3, 7,3, color);
// int WORD_TEN_MINUTES[4][2] = {{3,0}, {3,5}, {3,6}, {3,7}};
// // .line(9,3, 10,3, color);
// int WORD_TO[3][2] = {{2,0}, {3,9}, {3,10}};
// // .line(0,4, 3,4, color);
// int WORD_PAST[5][2] = {{4,0}, {4,0}, {4,1}, {4,2}, {4,3}};
// int WORD_NINE[5][2] = {{4,0}, {4,7}, {4,8}, {4,9}, {4,10}};
// int WORD_ONE[4][2] = {{3,0}, {5,0}, {5,1}, {5,2}};
// int WORD_SIX[4][2] = {{3,0}, {5,3}, {5,4}, {5,5}};
// int WORD_THREE[6][2] = {{5,0}, {5,6}, {5,7}, {5,8}, {5,9}, {5,10}};
// int WORD_FOUR[5][2] = {{4,0}, {6,0}, {6,1}, {6,2}, {6,3}};
// int WORD_FIVE[5][2] = {{4,0}, {6,4}, {6,5}, {6,6}, {6,7}};
// int WORD_TWO[4][2] = {{3,0}, {6,8}, {6,9}, {6,10}};
// int WORD_EIGHT[6][2] = {{5,0}, {7,0}, {7,1}, {7,2}, {7,3}, {7,4}};
// int WORD_ELEVEN[7][2] = {{6,0}, {7,5}, {7,6}, {7,7}, {7,8}, {7,9}, {7,10}};
// int WORD_SEVEN[6][2] = {{5,0}, {8,0}, {8,1}, {8,2}, {8,3}, {8,4}};
// int WORD_TWELFE[7][2] = {{6,0}, {8,5}, {8,6}, {8,7}, {8,8}, {8,9}, {8,10}};
// int WORD_TEN[4][2] = {{3,0}, {9,0}, {9,1}, {9,2}};
// int WORD_OCLOCK[7][2] = {{6,0}, {9,5}, {9,6}, {9,7}, {9,8}, {9,9}, {9,10}};
// using display_writer_t = std::function<void(esphome::Dieplay::Display &)>;
struct SegmentCoords {
uint16_t x1;
uint16_t x2;
uint16_t y1;
uint16_t y2;
};
class Wordclock : public esphome::PollingComponent {
public:
Wordclock();
Wordclock(esphome::time::RealTimeClock *time, esphome::addressable_light::AddressableLightDisplay *display, esphome::light::AddressableLightState *light_state);
void add_segment(SegmentCoords segment);
void add_hour(uint8_t index, std::vector<uint16_t> *segments);
void add_minute(uint8_t index, std::vector<uint16_t> *segments);
void add_static(uint16_t segment_id);
void add_hour_offset(uint8_t index, int8_t offset);
void setup();
void update();
// void setup() override {
// }
// void set_writer(display_writer_t &&writer);
// void display_word(const int word[][2], const CRGB& c) {
// for (int i=1; i < word[0][0] + 1; i++) {
// leds[map_coords_to_strip(word[i][0], word[i][1])].setRGB(c.r, c.g, c.b);
// }
// }
// void display_minutes(int minutes, const CRGB& color) {
// int five_minute_chunk = minutes / 5;
// switch (five_minute_chunk)
// {
// case 0: // sharp
// display_word(WORD_OCLOCK, color); ESP_LOGD("minute", "oclock "); break;
// case 1: // five past
// display_word(WORD_FIVE_MINUTES, color); ESP_LOGD("minute", "five past "); break;
// case 2: // ten past
// display_word(WORD_TEN_MINUTES, color); ESP_LOGD("minute", "ten past "); break;
// case 3: // quarter past
// display_word(WORD_QUARTER, color); ESP_LOGD("minute", "quarter past "); break;
// case 4: // twenty past
// display_word(WORD_TWENTY, color); ESP_LOGD("minute", "twenty past "); break;
// case 5: // twenty five past
// display_word(WORD_TWENTY, color); display_word(WORD_FIVE_MINUTES, color);
// ESP_LOGD("minute", "twenty five past "); break;
// case 6: // half past
// display_word(WORD_HALF, color); ESP_LOGD("minute", "half past "); break;
// case 7: // twenty five to
// display_word(WORD_TWENTY, color); display_word(WORD_FIVE_MINUTES, color);
// ESP_LOGD("minute", "twenty five to "); break;
// case 8: // twenty to
// display_word(WORD_TWENTY, color); ESP_LOGD("minute", "twenty to "); break;
// case 9: // quarter to
// display_word(WORD_QUARTER, color); ESP_LOGD("minute", "quarter to "); break;
// case 10: // ten to
// display_word(WORD_TEN_MINUTES, color); ESP_LOGD("minute", "ten to "); break;
// case 11: // five to
// display_word(WORD_FIVE_MINUTES, color); ESP_LOGD("minute", "five to "); break;
// default:
// break;
// }
// if (five_minute_chunk > 6) {
// display_word(WORD_TO, color);
// } else if (five_minute_chunk > 0) {
// display_word(WORD_PAST, color);
// }
// }
// void display_hour(int hour, int minutes, const CRGB& color) {
// int five_minute_chunk = minutes / 5;
// if (five_minute_chunk > 6) {
// hour += 1;
// }
// switch (hour % 12)
// {
// case 0: // twelve
// display_word(WORD_TWELFE, color); ESP_LOGD("hour", "twelve "); break;
// case 1: // one
// display_word(WORD_ONE, color); ESP_LOGD("hour", "one "); break;
// case 2: // two
// display_word(WORD_TWO, color); ESP_LOGD("hour", "two "); break;
// case 3: // three
// display_word(WORD_THREE, color); ESP_LOGD("hour", "three "); break;
// case 4: // four
// display_word(WORD_FOUR, color); ESP_LOGD("hour", "four "); break;
// case 5: // five
// display_word(WORD_FIVE, color); ESP_LOGD("hour", "five "); break;
// case 6: // six
// display_word(WORD_SIX, color); ESP_LOGD("hour", "six "); break;
// case 7: // seven
// display_word(WORD_SEVEN, color); ESP_LOGD("hour", "seven "); break;
// case 8: // eight
// display_word(WORD_EIGHT, color); ESP_LOGD("hour", "eight "); break;
// case 9: // nine
// display_word(WORD_NINE, color); ESP_LOGD("hour", "nine "); break;
// case 10: // ten
// display_word(WORD_TEN, color); ESP_LOGD("hour", "ten "); break;
// case 11: // eleven
// display_word(WORD_ELEVEN, color); ESP_LOGD("hour", "eleven "); break;
// default:
// break;
// }
// }
// void display_time(int hour, int minutes, const CRGB& color) {
// // clear_all_leds();
// display_word(WORD_IT_IS, color);
// display_hour(hour, minutes, color);
// display_minutes(minutes, color);
// // FastLED.show();
// }
// void loop() override {
// // auto time = id(current_time).now();
// // https://www.esphome.io/api/classesphome_1_1light_1_1_light_color_values.html LightColorValues Class
// // auto fastledlight2 = id(fastledlight).current_values;
// //convert float 0.0 till 1.0 into int 0 till 255
// red = (int) (fastledlight2.get_red() * 125);
// green = (int) (fastledlight2.get_green() * 125);
// blue = (int) (fastledlight2.get_blue() * 125);
// brightness = 0;
// //check if light is on and set brightness
// if (fastledlight2.get_state() > 0 ) {
// brightness = (int) (fastledlight2.get_brightness()*125);
// } else {
// // ESP_LOGD("loop", "fastledlight state off - b: %i rgb %i %i %i", brightness, red, green, blue); delay(100);
// }
// FastLED.setBrightness(brightness);
// FastLED.show();
// //check if valid time. Blink red,green,blue until valid time is present
// }
protected:
void draw_segment(uint16_t segment_id);
int8_t find_hour(uint8_t hour);
int8_t find_minute(uint8_t minute);
// std::vector<uint16_t> * find_hour(uint8_t hour);
// std::vector<uint16_t> * find_minute(uint8_t minute);
std::vector<std::vector<uint16_t>> *minutes;
std::vector<std::vector<uint16_t>> *hours;
std::vector<uint16_t> *static_segments;
std::vector<int8_t> *hour_offsets;
void start_idle_animation();
void end_idle_animation();
// uint16_t **minutes;
// uint16_t **hours;
bool valid_time{true};
std::vector<SegmentCoords> *segments;
esphome::time::RealTimeClock *time;
esphome::light::AddressableLight *light;
esphome::light::AddressableLightState *light_state;
esphome::addressable_light::AddressableLightDisplay *display;
light::AddressableRainbowLightEffect *rainbow;
light::AddressableTwinkleEffect *twinkle;
light::AddressableRandomTwinkleEffect *randomTwinkle;
};
} // namespace wordclock
} // namespace esphome