Starting receiving the following error today 2024-01-11.
```Couldn't find any… component that can be used for 'display::DisplayBuffer'. Are you missing a hub declaration?.```
Full error (the error is also present with 2023.12.5):
```
INFO ESPHome 2023.12.3
INFO Reading configuration /config/esphome/weather-display.yaml...
INFO Detected timezone 'America/New_York'
WARNING GPIO0 is a strapping PIN and should only be used for I/O with care.
Attaching external pullup/down resistors to strapping pins can cause unexpected failures.
See https://esphome.io/guides/faq.html#why-am-i-getting-a-warning-about-strapping-pins
Failed config
binary_sensor.gpio: [source <unicode string>:96]
platform: gpio
id: boo_button
pin:
number: 0
inverted: True
mode:
input: True
output: False
open_drain: False
pullup: False
pulldown: False
ignore_strapping_warning: False
drive_strength: 20.0
name: Button 1
on_press:
- then:
- if:
condition:
Couldn't find any component that can be used for 'display::DisplayBuffer'. Are you missing a hub declaration?.
display.is_displaying_page:
page_id: magikarp
then:
- display.page.show:
id: weathertoday
else:
- display.page.show:
id: magikarp
disabled_by_default: False
binary_sensor.gpio: [source <unicode string>:110]
platform: gpio
pin:
number: 14
inverted: True
mode:
input: True
output: False
open_drain: False
pullup: False
pulldown: False
ignore_strapping_warning: False
drive_strength: 20.0
name: Button 2
id: page_button
on_press:
- then:
- if:
condition:
Couldn't find any component that can be used for 'display::DisplayBuffer'. Are you missing a hub declaration?.
display.is_displaying_page:
page_id: pokemon
then:
- display.page.show:
id: weathertoday
else:
- display.page.show_next:
ID 'weatherdisplay' of type tdisplays3::TDisplayS3 doesn't inherit from display::DisplayBuffer. Please double check your ID is pointing to the correct value.
id: weatherdisplay
disabled_by_default: False
```
And the associated yaml:
```
esphome:
name: weather-display
friendly_name: weather_display
platformio_options:
board_build.f_flash: 80000000L
board_build.partitions: default_16MB.csv
board_build.arduino.memory_type: qio_opi
external_components:
- source: github://landonr/lilygo-tdisplays3-esphome
components: [tdisplays3]
esp32:
board: esp32-s3-devkitc-1
variant: esp32s3
framework:
type: arduino
flash_size: 16MB
# Enable logging
logger:
level: info
# Enable Home Assistant API
api:
encryption:
key: "x"
ota:
password: "x"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
manual_ip:
static_ip: 192.168.x.x
gateway: 192.168.86.1
subnet: 255.255.255.0
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Weather-Display Fallback Hotspot"
password: "x"
captive_portal:
switch:
- platform: shutdown
name: "Weather Display Shutdown"
- platform: restart
name: "Weather Display Restart"
time:
- platform: homeassistant
id: esptime
binary_sensor:
- platform: gpio
id: boo_button
pin:
number: GPIO0
inverted: true
name: "Button 1"
on_press:
- if:
condition:
display.is_displaying_page: magikarp
then:
display.page.show: weathertoday
else:
display.page.show: magikarp
- platform: gpio
pin:
number: GPIO14
inverted: true
name: "Button 2"
id: page_button
on_press:
- if:
condition:
display.is_displaying_page: pokemon
then:
display.page.show: weathertoday
else:
display.page.show_next: weatherdisplay
output:
- platform: ledc
pin: GPIO38
id: gpio38
frequency: 2000
light:
- platform: monochromatic
output: gpio38
name: "Backlight"
restore_mode: RESTORE_DEFAULT_ON
text_sensor:
- platform: homeassistant
id: high_temp
entity_id: sensor.forest_hills_daily_weather_forecast
attribute: high_temp
internal: true
- platform: homeassistant
id: low_temp
entity_id: sensor.forest_hills_daily_weather_forecast
attribute: low_temp
internal: true
- platform: homeassistant
id: humidity
entity_id: sensor.forest_hills_daily_weather_forecast
attribute: humidity
internal: true
- platform: homeassistant
id: condition
entity_id: sensor.forest_hills_daily_weather_forecast
attribute: condition
internal: true
- platform: homeassistant
id: precip_prob
entity_id: sensor.forest_hills_daily_weather_forecast
attribute: precip_prob
internal: true
- platform: homeassistant
id: tomorrow_temp
entity_id: sensor.forest_hills_daily_weather_forecast
attribute: tomorrow_temp
internal: true
- platform: homeassistant
id: tomorrow_low
entity_id: sensor.forest_hills_daily_weather_forecast
attribute: tomorrow_low
internal: true
- platform: homeassistant
id: tomorrow_precip
entity_id: sensor.forest_hills_daily_weather_forecast
attribute: tomorrow_precip
internal: true
- platform: homeassistant
id: tomorrow_humidity
entity_id: sensor.forest_hills_daily_weather_forecast
attribute: tomorrow_humidity
internal: true
- platform: homeassistant
id: tomorrow_condition
entity_id: sensor.forest_hills_daily_weather_forecast
attribute: tomorrow_condition
internal: true
filters:
substitute:
- "Partlycloudy -> Partly Cloudy"
- "Clearday -> Clear"
- platform: homeassistant
id: current_temp
entity_id: sensor.pirateweather_temperature
internal: true
- platform: homeassistant
id: feels_like
entity_id: sensor.pirateweather_apparent_temperature
internal: true
- platform: homeassistant
id: current_state
entity_id: sensor.pirateweather_summary
internal: true
- platform: homeassistant
id: weather_icon
entity_id: sensor.pirateweather_icon
internal: true
- platform: homeassistant
id: qotd_q
entity_id: sensor.zen_quote_of_the_day
attribute: q
internal: true
- platform: homeassistant
id: qotd_a
entity_id: sensor.zen_quote_of_the_day
attribute: a
internal: true
- platform: homeassistant
id: tomorrow_day
entity_id: sensor.tomorrow_day
internal: true
- platform: homeassistant
id: tomorrow_date
entity_id: sensor.tomorrow_date
internal: true
- platform: homeassistant
id: potd
entity_id: sensor.pokemon_of_the_day
internal: true
filters:
substitute:
from: "-"
to: " "
- platform: homeassistant
id: potd_id
entity_id: sensor.pokemon_type_of_the_day
attribute: id
internal: true
- platform: homeassistant
id: potd_type
entity_id: sensor.pokemon_type_of_the_day
internal: true
font:
- file:
type: gfonts
family: JetBrains+Mono
weight: 300
id: jet14
size: 14
glyphs:
['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0',
'1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z','å', 'ä', 'ö', '/','?','*','#',';','$','^','`','''']
- file:
type: gfonts
family: JetBrains+Mono
weight: 300
id: jet16
size: 16
glyphs:
['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0',
'1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z','å', 'ä', 'ö', '/','?','*','#',';','$','^','`','''']
- file:
type: gfonts
family: JetBrains+Mono
weight: 400
id: jet20
size: 20
glyphs:
['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0',
'1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z','å', 'ä', 'ö', '/','?','*','#',';','$','^','`','''']
- file:
type: gfonts
family: JetBrains+Mono
weight: 400
id: jet24
size: 24
glyphs:
['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0',
'1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z','å', 'ä', 'ö', '/','?','*','#',';','$','^','`','''']
- file: "Pokemon-Solid.ttf"
id: pokemon17
size: 17
glyphs:
['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0',
'1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z','å', 'ä', 'ö', '/','?','*','#',';','$','^','`','''']
image:
- file: mdi:weather-sunny
id: clear_day
resize: 90x90
- file: mdi:weather-night
id: clear_night
resize: 90x90
- file: mdi:weather-cloudy
id: cloudy
resize: 90x90
- file: mdi:weather-pouring
id: rain
resize: 90x90
- file: mdi:weather-snowy-rainy
id: sleet
resize: 90x90
- file: mdi:weather-snowy-heavy
id: snow
resize: 90x90
- file: mdi:weather-windy-variant
id: wind
resize: 90x90
- file: mdi:weather-fog
id: fog
resize: 90x90
- file: mdi:weather-partly-cloudy
id: partly_cloudy_day
resize: 90x90
- file: mdi:weather-night-partly-cloudy
id: partly_cloudy_night
resize: 90x90
- file: mdi:cloud-alert-outline
id: error
resize: 90x90
- file: mdi:chevron-double-right
id: next_page
resize: 25x25
- file: "pokemon/potd_normal.png"
id: potd_normal
type: RGBA
resize: 80x80
- file: "pokemon/potd_shiny.png"
id: potd_shiny
type: RGBA
resize: 80x80
- file: "pokemon/pokemon_logo.png"
id: pokemon_logo
type: RGBA
- file: "pokemon/magikarp.png"
id: magikarp_image
type: RGBA
color:
- id: red
red_int: 255
green_int: 0
blue_int: 0
- id: yellow
red_int: 255
green_int: 239
blue_int: 0
- id: blue
red_int: 0
green_int: 0
blue_int: 255
- id: grey
red_int: 128
green_int: 128
blue_int: 128
- id: lightgrey
red_int: 224
green_int: 224
blue_int: 224
- id: poke_yellow
red_int: 255
green_int: 203
blue_int: 5
- id: poke_blue
red_int: 42
green_int: 117
blue_int: 187
display:
- platform: tdisplays3
id: weatherdisplay
update_interval: 1s
rotation: 0
#170x320
pages:
- id: weathertoday
lambda: |-
// Print "Weather Today" in top center.
it.printf(85, 0, id(rubik), Color(255, 203, 5), TextAlign::TOP_CENTER, "WEATHER");
// Print "Weather Today" in top center.
it.printf(85, 25, id(rubik), Color(255, 203, 5), TextAlign::TOP_CENTER, "TODAY");
// Print date in MM-DD-YYYY (from homeassistant sensor)
it.strftime(85, 55, id(jet20), TextAlign::TOP_CENTER, "%A", id(esptime).now());
// Print date in MM-DD-YYYY (from homeassistant sensor)
it.strftime(85, 75, id(jet20), TextAlign::TOP_CENTER, "%b %d %Y", id(esptime).now());
// Print time in HH:MM format
it.strftime(85, 95, id(jet20), TextAlign::TOP_CENTER, "%H:%M", id(esptime).now());
// Print current_state (from homeassistant sensor)
it.printf(85, 120, id(jet20), TextAlign::TOP_CENTER , "%s", id(current_state).state.c_str());
// Print "now" (from homeassistant sensor)
it.printf(90, 150, id(jet14), TextAlign::TOP_LEFT , "Now");
// Print current_temp (from homeassistant sensor)
it.printf(90, 160, id(jet24), TextAlign::TOP_LEFT, "%s°F", id(current_temp).state.c_str());
// Print "feels like" (from homeassistant sensor)
it.printf(90, 185, id(jet14), TextAlign::TOP_LEFT , "Feels Like");
// Print feels_like (from homeassistant sensor)
it.printf(90, 195, id(jet24), TextAlign::TOP_LEFT , "%s°F", id(feels_like).state.c_str());
// Print "high today" (from homeassistant sensor)
it.printf(0, 225, id(jet14), TextAlign::TOP_LEFT , "Hi:");
// Print high temperature (from homeassistant sensor)
it.printf(30, 225, id(jet20), TextAlign::TOP_LEFT , "%s°F", id(high_temp).state.c_str());
// Print "low today" (from homeassistant sensor)
it.printf(0, 245, id(jet14), TextAlign::TOP_LEFT , "Lo:");
// Print low temperature (from homeassistant sensor)
it.printf(30, 245, id(jet20), TextAlign::TOP_LEFT, "%s°F", id(low_temp).state.c_str());
// Print "Humid" (from homeassistant sensor)
it.printf(85, 225, id(jet14), TextAlign::TOP_LEFT , "Hum:");
// Print humidity (from homeassistant sensor)
it.printf(115, 225, id(jet20), TextAlign::TOP_LEFT, "%s%%", id(humidity).state.c_str());
// Print "Precip" (from homeassistant sensor)
it.printf(85, 245, id(jet14), TextAlign::TOP_LEFT , "Pre:");
// Print weather_icon probability (from homeassistant sensor)
it.printf(115, 245, id(jet20), TextAlign::TOP_LEFT, "%s%%", id(precip_prob).state.c_str());
// Print weather icon
// Aligned on left by default
if ( (id(weather_icon).state) == "clear-day" ) {
it.image(0, 140, id(clear_day), id(yellow));
}
else if ( (id(weather_icon).state) == "clear-night" ) {
it.image(0, 140, id(clear_night));
}
else if ( (id(weather_icon).state) == "cloudy" ) {
it.image(0, 140, id(cloudy), id(grey));
}
else if ( (id(weather_icon).state) == "rain" ) {
it.image(0, 140, id(rain), id(grey));
}
else if ( (id(weather_icon).state) == "sleet" ) {
it.image(0, 140, id(sleet));
}
else if ( (id(weather_icon).state) == "snow" ) {
it.image(0, 140, id(snow));
}
else if ( (id(weather_icon).state) == "wind" ) {
it.image(0, 140, id(wind));
}
else if ( (id(weather_icon).state) == "fog" ) {
it.image(0, 140, id(fog), id(grey));
}
else if ( (id(weather_icon).state) == "partly-cloudy-day" ) {
it.image(0, 140, id(partly_cloudy_day), id(lightgrey));
}
else if ( (id(weather_icon).state) == "partly-cloudy-night" ) {
it.image(0, 140, id(partly_cloudy_night), id(lightgrey));
}
else {
it.image(0, 140, id(error), id(red));
}
// Print next page button
it.image(165, 320, id(next_page), ImageAlign::BOTTOM_RIGHT);
- id: weathertomorrow
lambda: |-
// Print "Weather" in top center.
it.printf(85, 0, id(rubik), Color(255, 203, 5), TextAlign::TOP_CENTER, "WEATHER");
// Print "Tomorrow" in top center.
it.printf(85, 25, id(rubik), Color(255, 203, 5), TextAlign::TOP_CENTER, "TOMORROW");
// Print name of day tomorrow (from homeassistant sensor)
it.printf(85, 55, id(jet20), TextAlign::TOP_CENTER, "%s", id(tomorrow_day).state.c_str());
// Print date tomorrow
it.printf(85, 75, id(jet20), TextAlign::TOP_CENTER, "%s", id(tomorrow_date).state.c_str());
// Print tomorrorw's condition (from homeassistant sensor)
it.printf(85, 120, id(jet20), TextAlign::TOP_CENTER , "%s", id(tomorrow_condition).state.c_str());
// Print "Hi" (from homeassistant sensor)
it.printf(90, 150, id(jet14), TextAlign::TOP_LEFT , "Hi");
// Print tomorrow_temp (from homeassistant sensor)
it.printf(90, 160, id(jet24), TextAlign::TOP_LEFT, "%s°F", id(tomorrow_temp).state.c_str());
// Print "Lo" (from homeassistant sensor)
it.printf(90, 185, id(jet14), TextAlign::TOP_LEFT , "Lo");
// Print tomorrow_low (from homeassistant sensor)
it.printf(90, 195, id(jet24), TextAlign::TOP_LEFT , "%s°F", id(tomorrow_low).state.c_str());
// Print "Humid" (from homeassistant sensor)
it.printf(85, 225, id(jet14), TextAlign::TOP_LEFT , "Hum:");
// Print humidity (from homeassistant sensor)
it.printf(115, 225, id(jet20), TextAlign::TOP_LEFT, "%s%%", id(tomorrow_humidity).state.c_str());
// Print "Precip" (from homeassistant sensor)
it.printf(0, 225, id(jet14), TextAlign::TOP_LEFT , "Pre:");
// Print precip probability (from homeassistant sensor)
it.printf(30, 225, id(jet20), TextAlign::TOP_LEFT, "%s%%", id(tomorrow_precip).state.c_str());
// Print weather icon
// Aligned on left by default
if ( (id(tomorrow_condition).state) == "Sunny" ) {
it.image(0, 140, id(clear_day), id(yellow));
}
else if ( (id(tomorrow_condition).state) == "Cloudy" ) {
it.image(0, 140, id(cloudy), id(grey));
}
else if ( (id(tomorrow_condition).state) == "Rainy" ) {
it.image(0, 140, id(rain), id(grey));
}
else if ( (id(tomorrow_condition).state) == "Sleet" ) {
it.image(0, 140, id(sleet));
}
else if ( (id(tomorrow_condition).state) == "Snow" ) {
it.image(0, 140, id(snow));
}
else if ( (id(tomorrow_condition).state) == "Wind" ) {
it.image(0, 140, id(wind), id(lightgrey));
}
else if ( (id(tomorrow_condition).state) == "Fog" ) {
it.image(0, 140, id(fog), id(grey));
}
else if ( (id(tomorrow_condition).state) == "Partly Cloudy" ) {
it.image(0, 140, id(partly_cloudy_day), id(lightgrey));
}
else {
it.image(0, 140, id(error), id(red));
}
// Print next page button
it.image(165, 320, id(next_page), ImageAlign::BOTTOM_RIGHT);
- id: pokemon
lambda: |-
// Print Pokemon logo in top center.
it.image(85, 0, id(pokemon_logo), ImageAlign::TOP_CENTER);
// Print "of the day" in top center.
it.printf(85, 56, id(pokemon17), Color(id(poke_blue)), TextAlign::TOP_CENTER, "OF THE DAY");
// Print POTD with line breaks
std::string s1 = id(potd).state;
int limit = 13;
int space = 0;
int i = 0;
int line = 0;
int y = 80;
while (i < s1.length()) {
if (s1.substr(i, 1) == " " || s1.substr(i, 1) == "-") {
space = i;
}
if (line > limit - 1) {
s1 = s1.substr(0, space) + "~" + s1.substr(space + 1);
line = 0;
}
i++;
line++;
}
size_t pos = s1.find("~");
int linecount = 1;
int breakpositions[10];
breakpositions[0] = -1;
while (pos != std::string::npos) {
s1.replace(pos, 1, "\n");
breakpositions[linecount] = pos;
pos = s1.find("~");
linecount++;
}
breakpositions[linecount] = s1.length();
std::string singleline;
i = 0;
while (i < linecount) {
singleline = s1.substr(breakpositions[i] + 1, (breakpositions[i + 1] - breakpositions[i] - 1));
it.printf(85, y, id(jet20), TextAlign::TOP_CENTER, "%s", singleline.c_str());
y=y+20;
i++;
}
// Print POTD type (from homeassistant sensor)
it.printf(85, 125, id(jet16), TextAlign::TOP_CENTER , "%s type", id(potd_type).state.c_str());
// Print POTD pokedex id (from homeassistant sensor)
it.printf(85, 150, id(jet16), TextAlign::TOP_CENTER , "Pokedex #: %s", id(potd_id).state.c_str());
// Draw the image the POTDs
it.image(0, 175, id(potd_normal));
it.image(90, 175, id(potd_shiny));
// Print (from homeassistant sensor)
it.printf(45, 265, id(jet14), TextAlign::TOP_CENTER, "%s", "Normal");
it.printf(135, 265, id(jet14), TextAlign::TOP_CENTER, "%s", "Shiny");
// Print next page button
it.image(165, 320, id(next_page), ImageAlign::BOTTOM_RIGHT);
- id: magikarp
lambda: |-
// Print magikarp in top center.
it.image(85, 20, id(magikarp_image), ImageAlign::TOP_CENTER);
// Print "Gotta Catch" in top center.
it.printf(85, 220, id(pokemon17), Color(id(poke_blue)), TextAlign::TOP_CENTER, "Gotta Catch");
// Print "em all" in top center.
it.printf(85, 240, id(pokemon17), Color(id(poke_blue)), TextAlign::TOP_CENTER, "'em all!");
# // Print next page button
# it.image(165, 320, id(next_page), ImageAlign::BOTTOM_RIGHT);
```