Help Fixing my code please. $ offer wordclok

So I have an error on my ESPHome upgrade:

I need to convert a “custom” component to a external component.

This project was inspired on https://github.com/leinich/ha-wordclock-esphome. an awesome wordclock.

Now my project…

The ESPHome wc.yaml code is:

esphome:
  name: wordclock
  friendly_name: wordclock_1
  includes:
    - wordclock.h
  on_boot:
    priority: 800
    then:
      - light.turn_on: 
          id: fastledlight


esp8266:
  board: nodemcuv2
#  framework:
#    version: 2.7.4

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "qpyJxtctmirRbNR3SXDT1f/7P99zxrLq3Ue7o/tz5KA="
  reboot_timeout: 120hours

ota:
  - password: "67506f30187199231f751e134f0e593a"
    platform: esphome
wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Word-Clock Fallback Hotspot"
    password: !secret wifi_password

captive_portal:
  
external_components:
  - source: github://pr#4257
    components: [fastled]
    refresh: always

light:
  - platform: fastled
    id: fastledlight
    chipset: WS2812
    data_pin: GPIO03
    num_leds: 144
    rgb_order: BRG
    name: "Word Clock"
    restore_mode: ALWAYS_OFF
    on_turn_on:
      - light.turn_on:
          id: fastledlight
          red: 100%
          green: 53%
          blue: 5%

 
time:
  - platform: homeassistant
#    timezone: UTC−03:00
    id: current_time

sensor:
  - platform: adc
    pin: A0
    name: "Wordclock LDR"
    update_interval: 10s
    id: "ldr"
    filters:
      - multiply: 3.3

  - platform: template
    name: "Wordclock Brillo"
    update_interval: 10s
    unit_of_measurement: "%"
    lambda:
      |- 
        if (id(ldr).state>=1) 
        {
          return 100;
        }
        else
        {
          return id(ldr).state * 100;
        }
  
  - platform: wifi_signal
    id: wifi_signal_db
    internal: true
    update_interval: 60s

  - platform: copy # Reports the WiFi signal strength in %
    source_id: wifi_signal_db
    name: "WiFi Signal Percent"
    filters:
      - lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
    unit_of_measurement: "Signal %"
    entity_category: "diagnostic"

switch:
  - platform: template
    name: wc_timbre
    id: wc_timbre
    restore_mode: ALWAYS_OFF
    optimistic: true

  - platform: restart
    name: restart

select:
  - platform: template
    name: brightness type
    optimistic: true
    options:
      - ldr
      - light
    initial_option: ldr
    id: selecttype


  

custom_component:
- lambda: |-
    auto wordclock = new Wordclock();
    return {wordclock};

And the wordclock.h is:

#include "esphome.h"
#include <FastLED.h>

#define NUM_LEDS 144
#define DATA_PIN D1

// esphome dependencies:
// needs: esphome time --> id: current_time
// needs: esphome fastled --> id: fastledlight

// Layout of Clock (X not used chars) - PIN Layout
// ESXISTXFÜNF    1.......11
// ZEHNZWANZIG    22......12
// DREIVIERTEL    23......33
// XXNACHVORXX    44......34
// HALBXZWÖLFX    45......55
// ZWEIXSIEBEN    ....
// XDREIXXFÜNF    ....
// ELFNEUNVIER    ....
// XACHTZEHNRS    ....
// XSECHSXXUHR    109.......101
// ICONS          110.......120
// MINUTES        124.......121

uint8_t hue = 0;
//DEFINE_GRADIENT_PALETTE (heatmap_gp){
//    0,  255,  255,  255,
//    84,   0,  155,  255,
//    168,255,  255,  0
//};

DEFINE_GRADIENT_PALETTE (heatmap_gp){
  0,     0,  0,  0,   //black
128,   255,  0,  0,   //red
224,   255,255,  0,   //bright yellow
255,   255,255,255 };

CRGBPalette16 myPal = heatmap_gp;

int leds_skiped[] = {}; // Check Line 101
int leds_time_minutes[][20] = {
    
    {128,129,143,142,141,140,139,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},// EN PUNTO
    {84,122,123,124,125,126,138,137,136,135,134,133,132, -1, -1, -1, -1, -1, -1, -1},// Y CINCO MINUTOS
    {84,118,117,116,115,138,137,136,135,134,133,132, -1, -1, -1, -1, -1, -1, -1, -1},// Y DIEZ MINUTOS
    {84,113,112,111,110,109,108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},// Y CUARTO
    {84, 97, 98, 99,100,101,102,138,137,136,135,134,133,132, -1, -1, -1, -1, -1, -1}, // Y VEINTE MINUTOS
    {97, 98, 99,100,101,102,120,122,123,124,125,126,138,137,136,135,134,133,132, -1}, // Y VEINTE Y CINCO MINUTOS
    {84,103,104,105,106,107, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},// Y MEDIA
    {17, 16, 15, 14, 13, 12, 25, 31, 32, 33, 34, 35, 47, 46, 45, 44, -1, -1, -1, -1}, // VEINTE Y CINCO PARA
    {17, 16, 15, 14, 13, 12, 47, 46, 45, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},// VEINTE PARA
    {10, 11, 23, 22, 21, 20, 19, 18, 47, 46, 45, 44, -1, -1, -1, -1, -1, -1, -1, -1},// UN CUARTO PARA
    {26, 27, 28, 29, 47, 46, 45, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // DIEZ PARA
    {31, 32, 33, 34, 35, 47, 46, 45, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},// CINCO PARA
    {84, 97, 98, 99,100,101,102,120,122,123,124,125,126,138,137,136,135,134,133,132},
};


int leds_time_hours[][9] = {
    { 40, 39, 38, 95, 94, 93, 92, -1, -1},// LAS DOCE
    { 40, 39, 65, 64, 63, -1, -1, -1, -1},// LA UNA
    { 40, 39, 38, 62, 61, 60, -1, -1, -1},// LAS DOS
    { 40, 39, 38, 48, 49, 50, 51, -1, -1},// LAS TRES
    { 40, 39, 38, 71, 70, 69, 68, 67, 66},// LAS CUATRO
    {  7,  8,  9, 31, 32, 33, 34, 35, -1},// LAS CINCO
    { 40, 39, 38, 52, 53, 54, 55, -1, -1},// LAS SEIS
    { 40, 39, 38, 73, 74, 75, 76, 77, -1},// LAS SIETE
    { 40, 39, 38, 56, 57, 58, 59, -1, -1},// LAS OCHO
    { 40, 39, 38, 90, 89, 88, 87, 86, -1},// LAS NUEVE
    {  7,  8,  9, 26, 27, 28, 29, -1, -1},// LAS DIEZ
    { 40, 39, 38, 79, 80, 81, 82, -1, -1} // LAS ONCE
};

int leds_time_hours_para_las[][9] = {
    { 40, 39, 38, 95, 94, 93, 92, -1, -1},// LAS DOCE
    { 40, 39, 65, 64, 63, -1, -1, -1, -1},// LA UNA
    { 40, 39, 38, 62, 61, 60, -1, -1, -1},// LAS DOS
    { 40, 39, 38, 48, 49, 50, 51, -1, -1},// LAS TRES
    { 40, 39, 38, 71, 70, 69, 68, 67, 66},// LAS CUATRO
    { 40, 39, 38,122,123,124,125,126, -1},// LAS CINCO
    { 40, 39, 38, 52, 53, 54, 55, -1, -1},// LAS SEIS
    { 40, 39, 38, 73, 74, 75, 76, 77, -1},// LAS SIETE
    { 40, 39, 38, 56, 57, 58, 59, -1, -1},// LAS OCHO
    { 40, 39, 38, 90, 89, 88, 87, 86, -1},// LAS NUEVE
    { 40, 39, 38,118,117,116,115, -1, -1},// LAS DIEZ
    { 40, 39, 38, 79, 80, 81, 82, -1, -1} // LAS ONCE
};

CRGB leds[NUM_LEDS];
int hour = -1;
int minute = -1;
int count = 0;
int red = 124;
int green = 124;
int blue = 124;
int brightness = 50;
bool change = false;


class Wordclock : public Component, public CustomAPIDevice {
        public:
        void setup() override {
            FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
            FastLED.setBrightness(brightness);
            // Start all LED with on and default color and brightness to check if everything is working...
            for(int i = 0; i < NUM_LEDS; i++) { leds[i].setRGB(red, 0, 0); FastLED.show(); delay(10); }
            for(int i = 0; i < NUM_LEDS; i++) { leds[i].setRGB(0, green, 0); FastLED.show(); delay(10); }
            for(int i = 0; i < NUM_LEDS; i++) { leds[i].setRGB(0, 0, blue); FastLED.show(); delay(10); }
            for(int i = 0; i < NUM_LEDS; i++) { leds[i].setRGB(0, 0, 0); }
            FastLED.show();
            register_service(&Wordclock::on_setled, "setled", {"number","red", "blue", "green"});
        }
        void on_setled(int number, int red, int blue, int green) {
            if (number < NUM_LEDS || number > 0) {
                ESP_LOGD("setled", "Setting led number %d to color %i %i %i", number, red, green, blue );
                leds[number].setRGB(red, green, blue);
                FastLED.show();
                }
            else { ESP_LOGE("setled", "Not a valid LED Number - out of range"); }
        }
        void loop() override {
            auto time = id(current_time).now();
            auto ldr2 = id(ldr);
            auto selecttype2 = id(selecttype);
            // https://www.esphome.io/api/classesphome_1_1light_1_1_light_color_values.html LightColorValues Class
            auto fastledlight2 = id(fastledlight).current_values;
            auto timbre = id(wc_timbre).state;
            
            int h = time.hour;
            int m = time.minute;
            
            //convert float 0.0 till 1.0 into int 0 till 255
            red = (int)(fastledlight2.get_red()*255);
            green = (int)(fastledlight2.get_green()*255);
            blue = (int)(fastledlight2.get_blue()*255);
            
            if(timbre)
            {
                brightness = 100;
                FastLED.setBrightness(brightness);
                for(int j =0; j <=5;j++)
                {
                    for(int i = 0; i <= 11; i++)
                    {
//                        leds[24*j+i] = CHSV(hue + (i*10),255,255);
//                        leds[24*(j+1)-(i+1)]= CHSV(hue + (i*10),255,255);
                        leds[24*j+i] = ColorFromPalette(myPal, hue );
                        leds[24*(j+1)-(i+1)] = ColorFromPalette(myPal, hue );
                    }
                }

                EVERY_N_MILLISECONDS(15){
                    hue++;
                    count++;
                }
//                brightness = 50;
                FastLED.show();
                
                if(m != minute && count >= 1000/15*20)
                {
                ESP_LOGE("loop", "RGB: r:%i g:%i b:%i", red, green,blue );
                    id(wc_timbre).turn_off();
                    count = 0;
                    ///////////////////////////////////////////////////////////////////////////
                hour = h;
                minute = m;
                if (hour >= 0 && time.is_valid() == true){
                    int tmp_hour = hour;
                    int tmp_minute = (minute - (minute % 5));
                    if(tmp_minute >= 35) { tmp_hour += 1; }
                    tmp_minute = tmp_minute / 5;
                    tmp_hour = tmp_hour % 12;
                    int minutessum = minute % 5;
                    if (fastledlight2.get_state() > 0 ) 
                    { 
                        if (selecttype2.state == "ldr") {
                            int brightness2 = (int)(ldr2.get_state()*255);
                            if (brightness != brightness2) { 
                                change = 1; 
                                brightness = brightness2;
                            }
                            if (brightness == 0) {
                                change = 1;
                                brightness = 1;
                            }
                        }
                        else {
                            brightness = (int)(fastledlight2.get_brightness()*255); 
                        }
                    }
                    else { 
                        brightness = 0;
                        //ESP_LOGD("loop", "fastledlight state off - b: %i rgb %i %i %i", brightness, red, green, blue); 
                        //delay(500);
                    }
                    FastLED.setBrightness(brightness);
                    for(int i = 0; i <= 11; i++)
                    {
                        for(int j =0; j <=5;j++)
                        {
                            leds[24*j+i].setRGB(red, green, blue);
                            leds[24*(j+1)-(i+1)].setRGB(red, green, blue);
                        }
                    FastLED.show(); 
                    delay(200);
                    }
                    for(int i = 0; i <= 11; i++)
                    {
                        leds[i].setRGB(0, 0, 0);
                        leds[23-i].setRGB(0, 0, 0);
                        leds[24+i].setRGB(0, 0, 0);
                        leds[47-i].setRGB(0, 0, 0);
                        leds[48+i].setRGB(0, 0, 0);
                        leds[71-i].setRGB(0, 0, 0);
                        leds[72+i].setRGB(0, 0, 0);
                        leds[95-i].setRGB(0, 0, 0);
                        leds[96+i].setRGB(0, 0, 0);
                        leds[119-i].setRGB(0, 0, 0);
                        leds[120+i].setRGB(0, 0, 0);
                        leds[143-i].setRGB(0, 0, 0);

                        if(tmp_hour == 1) // ES
                        {
                            leds[1].setRGB(red, green, blue); 
                            leds[2].setRGB(red, green, blue);
                        }
                        if(tmp_hour != 1) // SON
                        {
                            leds[3].setRGB(red, green, blue);
                            leds[4].setRGB(red, green, blue);
                            leds[5].setRGB(red, green, blue);
                        }
                        
                        for(int i = 0; i < 20; i++) 
                        {           
                            if(leds_time_minutes[tmp_minute][i] >= 0) 
                            { 
                                leds[leds_time_minutes[tmp_minute][i]].setRGB(red, green, blue); 
                            } 
                        }
                        
                        if(minute >= 35)
                        {
                            for(int i = 0; i < 9; i++) 
                            {            
                                if(leds_time_hours_para_las[tmp_hour][i] >= 0) 
                                { 
                                    leds[leds_time_hours_para_las[tmp_hour][i]].setRGB(red, green, blue); 
                                } 
                            }
                        }
                        else
                        {
                            for(int i = 0; i < 9; i++) 
                            {            
                                if(leds_time_hours[tmp_hour][i] >= 0) 
                                { 
                                    leds[leds_time_hours[tmp_hour][i]].setRGB(red, green, blue); 
                                } 
                            }                            
                        }
                        FastLED.show(); 
                        delay(200);
                    }
                }
                    ///////////////////////////////////////////////////////////////////////////
                }
            }
            else
            {
                //check if light is on and set brightness
                if (fastledlight2.get_state() > 0 ) 
                { 
                    if (selecttype2.state == "ldr") {
                        int brightness2 = (int)(ldr2.get_state()*255);
                        if (brightness != brightness2) { 
                            change = 1; 
                            brightness = brightness2;
                        }
                        if (brightness == 0) {
                            change = 1;
                            brightness = 1;
                        }
                    }
                    else {
                        brightness = (int)(fastledlight2.get_brightness()*255); 
                    }
                }
                else { 
                    brightness = 0;
                    //ESP_LOGD("loop", "fastledlight state off - b: %i rgb %i %i %i", brightness, red, green, blue); 
                    //delay(500);
                }
                FastLED.setBrightness(brightness);
                //check if valid time. Blink red,green,blue until valid time is present
                if (time.is_valid() == false) {
                    ESP_LOGE("loop", "Got invalid time from current_time Time: %i:%i", h, m );
                    leds[0].setRGB(255, 0, 0); FastLED.show(); delay(250);
                    leds[0].setRGB(0, 255, 0); FastLED.show(); delay(250);
                    leds[0].setRGB(0, 0, 255); FastLED.show(); delay(250);
                    leds[0].setRGB(0, 0, 0);   FastLED.show();
                }
                else 
                {
                    
                    // only update once in a Minute
                    if(h != hour || m != minute) 
                    {
                        ESP_LOGD("loop", "Using b: %i rgb %i %i %i", brightness, red, green, blue);
                        hour = h;
                        minute = m;
                        if (hour >= 0 && time.is_valid() == true)
                        {
                            int tmp_hour = hour;
                            int tmp_minute = (minute - (minute % 5));
                            if(tmp_minute >= 35) { tmp_hour += 1; }
                            tmp_minute = tmp_minute / 5;
                            tmp_hour = tmp_hour % 12;
                            int minutessum = minute % 5;
                            // Reset all LED, but skip LED 110 till 120
                            
                            if(minutessum == 0 ) //if(1) 
                            {
                                for(int i = 0; i <= 11; i++)
                                {
                                    for(int j =0; j <=5;j++)
                                    {
                                        leds[24*j+i].setRGB(red, green, blue);
                                        leds[24*(j+1)-(i+1)].setRGB(red, green, blue);
                                    }
                                FastLED.show(); 
                                delay(200);
                                }
                                for(int i = 0; i <= 11; i++)
                                {
                                    leds[i].setRGB(0, 0, 0);
                                    leds[23-i].setRGB(0, 0, 0);
                                    leds[24+i].setRGB(0, 0, 0);
                                    leds[47-i].setRGB(0, 0, 0);
                                    leds[48+i].setRGB(0, 0, 0);
                                    leds[71-i].setRGB(0, 0, 0);
                                    leds[72+i].setRGB(0, 0, 0);
                                    leds[95-i].setRGB(0, 0, 0);
                                    leds[96+i].setRGB(0, 0, 0);
                                    leds[119-i].setRGB(0, 0, 0);
                                    leds[120+i].setRGB(0, 0, 0);
                                    leds[143-i].setRGB(0, 0, 0);
                                    
                                    if(tmp_hour == 1) // ES
                                    {
                                        leds[1].setRGB(red, green, blue); 
                                        leds[2].setRGB(red, green, blue);
                                    }
                                    if(tmp_hour != 1) // SON
                                    {
                                        leds[3].setRGB(red, green, blue);
                                        leds[4].setRGB(red, green, blue);
                                        leds[5].setRGB(red, green, blue);
                                    }
                                    
                                    for(int i = 0; i < 20; i++) 
                                    {           
                                        if(leds_time_minutes[tmp_minute][i] >= 0) 
                                        { 
                                            leds[leds_time_minutes[tmp_minute][i]].setRGB(red, green, blue); 
                                        } 
                                    }
                                    
                                    if(minute >= 35)
                                    {
                                        for(int i = 0; i < 9; i++) 
                                        {            
                                            if(leds_time_hours_para_las[tmp_hour][i] >= 0) 
                                            { 
                                                leds[leds_time_hours_para_las[tmp_hour][i]].setRGB(red, green, blue); 
                                            } 
                                        }
                                    }
                                    else
                                    {
                                        for(int i = 0; i < 9; i++) 
                                        {            
                                            if(leds_time_hours[tmp_hour][i] >= 0) 
                                            { 
                                                leds[leds_time_hours[tmp_hour][i]].setRGB(red, green, blue); 
                                            } 
                                        }                            
                                    }
                                    FastLED.show(); 
                                    delay(200);
                                }
                                ESP_LOGD("loop", "Update Time: %i:%i  Brightness: %i RGB: %i-%i-%i", hour, minute, brightness, red, green, blue);
                                ESP_LOGD("loop", "Using tmp_hour: %i tmp_minute: %i minutessum: %i", tmp_hour, tmp_minute, minutessum);
                            } 
                        }
                    }
                }
            }
        }
};  

I’m willing to offer some money because I know I am not asking for help but for someone that convert the code…
Thanks!!!

Rather than offer money, why not give the developer time to reply to the issue that you someone raised on github an hour before this topic was created?

I’m sure the developer would appreciate your money if you think this project is so awesome.

PS - the fix seems to be pretty easy if you read the ESPHome docs.

Looks like you need to replace the custom_component part with this:

external_components:
  - source:
      type: git
      url: https://github.com/leinich/ha-wordclock-esphome

If everything else fails, just restore a backup (if you made one) of ESPHome to downgrade to the previous version. Make sure to disable the update entity of your device so you won’t update it again.

I try to create an external component my self o. My GitHub but I could not figure it out. It’s just over my actual capacities.

Sadly, that’s not how it works, a custom component is completely different from an external component, it’s not just a difference in configuration.

I’ve created an external component that brings back support for custom components: GitHub - robertklep/esphome-custom-component: Brings back support for custom ESPHome components

You should only have to add some additional YAML code to get it working again (although I only created this component this morning and it’s not been very well tested yet).

Thanks Robert!! I´ll take a look!

no yet ready my friend:

My bad, I forgot to add the custom_component component in the README:

external_components:
  - source:
      type: git
      url: https://github.com/robertklep/esphome-custom-component
    components: [ custom, custom_component ]

It seams to work ok!. I´ll test it at home and let you know!

1 Like

Thanks my friend!! You brought my word clock alive!!

3 Likes

Well done!

1 Like

Nice! :+1:

This is the first time I’m seeing this idea and a search for more if these brought me to this project which I want to share: This incredible word clock is controlled by 114 servos

That project is friking awesome!!

Yes, thought so too, that’s why I wanted to show it here.
He has put a lot of time into it and the result is :star_struck: :star_struck: :star_struck:

Would you mind adding word clock to the thread title so others might bump on this too?

I can help anyone to do one like mine… it’s very cool too. All my friends want me to make one for them but no way jose!
Hahahaha

powerful :grinning: