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!!!