Funciona con ESPHome en Home Assistant

Introducción a Home Assistant
Home Assistant es una potente plataforma de automatización del hogar de código abierto que te permite controlar y monitorizar tus dispositivos inteligentes desde una única interfaz unificada. Actúa como el centro principal de tu hogar inteligente, permitiéndote automatizar rutinas, monitorizar sensores y crear un espacio de vida más inteligente.

¿Por qué Home Assistant?
- Control Local: A diferencia de muchas soluciones basadas en la nube, Home Assistant se ejecuta localmente en tu red, asegurando que tus datos permanezcan privados y tus automatizaciones funcionen incluso sin conexión a Internet.
- Soporte Extenso de Dispositivos: Home Assistant se integra con miles de dispositivos y servicios de domótica, lo que lo hace muy versátil y preparado para el futuro.
- Automatización Potente: Crea reglas de automatización sofisticadas que pueden responder a diversos disparadores como hora, estado de dispositivos, lecturas de sensores y más.
- Panel Personalizable: Diseña tu propia interfaz para mostrar la información que más te importe.
¿Por qué usar una pantalla ePaper con Home Assistant?
El panel ePaper de 7.5" para XIAO es un complemento excelente para Home Assistant por varias razones:
- Eficiencia Energética: La pantalla ePaper solo consume energía al actualizar el contenido, lo que la hace perfecta para mostrar información persistente como pronósticos del tiempo, eventos del calendario o estado del sistema.
- Visibilidad Clara: A diferencia de las pantallas LCD, las ePaper son legibles en cualquier condición de luz, incluso a plena luz solar, ideales para paneles de control montados en pared.
- Larga Duración de Batería: Combinada con el modo de bajo consumo, la pantalla puede funcionar durante meses con una sola carga, brindando información siempre visible.
- Integración Flexible: A través de ESPHome, la pantalla se integra sin problemas con Home Assistant, permitiéndote mostrar cualquier dato de tu sistema de domótica de forma elegante y siempre visible.
Integración con ESPHome
ESPHome es una herramienta de firmware de código abierto diseñada para dispositivos ESP8266/ESP32. Permite crear firmware personalizado mediante simples archivos de configuración YAML, que luego se flashean en el dispositivo. Para el panel ePaper de 7.5", ESPHome actúa como middleware esencial que habilita la comunicación entre el dispositivo y Home Assistant.
El sistema convierte tu configuración YAML en un firmware completo que se ejecuta en el dispositivo ESP. Este firmware gestiona tareas complejas como conectarse a la red, comunicarse con Home Assistant y controlar la pantalla ePaper. Combinado con Home Assistant, ESPHome brinda una plataforma robusta para crear paneles de control y visualización de domótica sofisticados.
Primeros Pasos
Antes de comenzar el tutorial, asegúrate de tener el siguiente hardware listo.
Materiales Requeridos
XIAO 7.5" ePaper Panel | Home Assistant Green |
---|---|
![]() | ![]() |
Home Assistant Green es la forma más sencilla y enfocada en la privacidad para automatizar tu hogar. Ofrece una configuración sin complicaciones y permite controlar todos tus dispositivos inteligentes desde un solo sistema, almacenando todos los datos localmente por defecto. Este dispositivo se beneficia del próspero ecosistema de Home Assistant y recibe mejoras mensuales de la comunidad open source.
Recomendamos usar Home Assistant Green como host para este tutorial, o cualquier otro host con Supervisor de Home Assistant.
Instalación de Home Assistant
Si usas un dispositivo Seeed Studio, consulta nuestras guías:
Para otras plataformas, revisa la instalación oficial.
Paso 1. Instalar ESPHome
Si ya lo tienes instalado, puedes omitir este paso.
Ve a Configuración → Complementos → TIENDA DE COMPLEMENTOS.


Busca ESPHome, haz clic en él y pulsa INSTALAR, luego INICIAR.
Si no ves ESPHome, asegúrate de usar una instalación compatible con complementos (OS o supervisada). Para Home Assistant Container, usa ESPHome Device Builder con Docker. Consulta la documentación oficial.

Posteriormente en ESPHome Builder aparecerá la barra lateral.

Paso 2. Añadir un nuevo dispositivo
En ESPHome, haz clic en NUEVO DISPOSITIVO.

Ponle un nombre y haz clic en SIGUIENTE.



Después de crear el dispositivo, haz clic en EDITAR.

Paso 3. Instalar el firmware
Este ejemplo básico mostrará "Hello World!" en la pantalla.
Copia el siguiente código y pégalo después de captive_portal
en tu configuración YAML de ESPHome:
Haz clic aquí para ver el código completo
# define font to display words
font:
- file: "gfonts://Inter@700"
id: font1
size: 24
# define SPI interface
spi:
clk_pin: GPIO8
mosi_pin: GPIO10
display:
- platform: waveshare_epaper
cs_pin: GPIO3
dc_pin: GPIO5
busy_pin:
number: GPIO4
inverted: true
reset_pin: GPIO2
model: 7.50inv2
update_interval: 30s
lambda: |-
it.print(0, 0, id(font1), "Hello World!");

Haz clic en INSTALL para instalar el código en el dispositivo y verás la siguiente imagen.
- Instalar desde el navegador
- Instalar desde el host
- Instalar vía Wi-Fi
Si tu host de Home Assistant (Raspberry Pi/Green/Yellow, etc.) está lejos de ti, te recomendamos usar este método. Puedes instalarlo desde la computadora que tengas a la mano.
Primero, haz clic en Manual download para descargar el firmware compilado.

Abre este sitio web donde subiremos el firmware al panel ePaper.

Regresa a ESPHome para descargar el firmware.

Selecciona formato de fábrica.

Usa un cable USB para conectar el panel ePaper a tu computadora y haz clic en CONNECT.

Selecciona usbmodemxxx (en Windows es COMxxx) y haz clic en conectar. ¿Tuviste un problema? Haz clic aquí.

Haz clic en INSTALL y selecciona el firmware que acabas de descargar.

Espera un momento y verás 'Hello world!' en la pantalla ~


Si tu host de Home Assistant (Raspberry Pi/Green/Yellow, etc.) está cerca de ti, te recomendamos este método por ser más sencillo.
Antes de instalar el código en el dispositivo, usa un cable USB para conectar este dispositivo a tu Raspberry Pi o HA Green/Yellow, etc., que esté ejecutando Home Assistant.
Haz clic en las opciones siguiendo la imagen para instalar el código en el dispositivo. ¿No encuentras el puerto cuando el dispositivo está en modo de suspensión profunda?


Espera un momento y verás un mensaje como en la imagen. Significa que el código se está ejecutando correctamente.


Este es el método más sencillo, pero requiere que la primera vez subas el programa al panel ePaper usando alguno de los métodos anteriores. Después de eso, puedes actualizarlo por Wi-Fi. Asegúrate de que tu configuración YAML incluya correctamente las secciones ota
y api
con las claves de cifrado válidas.
Con este método no necesitas conectar el panel ePaper a nada, solo asegúrate de que esté en línea.
Haz clic en la opción y el firmware se instalará automáticamente en el panel ePaper.

Espera un momento y verás un mensaje como en la imagen. Si falla, puede deberse a una señal débil. Acerca el dispositivo a tu router. ¿Tuviste un problema? Haz clic aquí.


Usos básicos
1. Mostrar forma
Este ejemplo mostrará una figura en la pantalla.
Después de instalar ESPHome y agregar un nuevo dispositivo, puedes copiar el siguiente código y pegarlo en la sección captive_portal, como se muestra en la imagen:
Haz clic aquí para copiar el código.
spi:
clk_pin: GPIO8
mosi_pin: GPIO10
display:
- platform: waveshare_epaper
model: 7.50inv2
cs_pin: GPIO3
dc_pin: GPIO5
reset_pin: GPIO2
busy_pin:
number: GPIO4
inverted: true
update_interval: 5min
lambda: |-
it.rectangle(10, 10, 100, 50);
it.rectangle(150, 10, 50, 50);
it.circle(250, 35, 25);
it.filled_rectangle(10, 80, 100, 50);
it.filled_rectangle(150, 80, 50, 50);
it.filled_circle(250, 105, 25);

Cuando veas una retroalimentación como la siguiente imagen, significa que el código se está ejecutando correctamente.
También puedes hacer clic aquí para ver más usos.

2. Mostrar información en Home Assistant
Este ejemplo mostrará la información de Home Assistant en la pantalla.
Primero, necesitas agregar este dispositivo a Home Assistant. De lo contrario, no podrás obtener información desde HA.
Si HA no muestra el dispositivo, deberías ejecutar primero la demostración anterior. Después de ejecutarla, podrás ver el dispositivo en HA.


Luego, haz clic en SUBMIT y FINISH.


Después de instalar ESPHome y agregar un nuevo dispositivo, puedes copiar el siguiente código y pegarlo después de captive_portal
como se muestra a continuación.
Haz clic aquí para ver el código completo
# Define font to show info
font:
- file: "gfonts://Inter@700"
id: myFont
size: 24
# Get info from HA, as string format
text_sensor:
- platform: homeassistant
entity_id: weather.forecast_home
id: myWeather
internal: true
- platform: homeassistant
entity_id: weather.forecast_home
id: myTemperature
attribute: "temperature"
internal: true
# Get info from HA, as float format
sensor:
- platform: homeassistant
entity_id: weather.forecast_home
id: myPressure
attribute: "pressure"
internal: true
# Display info via SPI
spi:
clk_pin: GPIO8
mosi_pin: GPIO10
display:
- platform: waveshare_epaper
cs_pin: GPIO3
dc_pin: GPIO5
busy_pin:
number: GPIO4
inverted: true
reset_pin: GPIO2
model: 7.50inv2
update_interval: 30s
lambda: |-
//print info in log
ESP_LOGD("epaper", "weather: %s", id(myWeather).state.c_str());
ESP_LOGD("epaper", "temperature: %s", id(myTemperature).state.c_str());
ESP_LOGD("epaper", "pressure: %.1f", id(myPressure).state);
//display info in epaper screen
it.printf(100, 100, id(myFont), "%s", id(myWeather).state.c_str());
it.printf(100, 150, id(myFont), "%s", id(myTemperature).state.c_str());
it.printf(100, 200, id(myFont), "%.1f", id(myPressure).state);
Instala esos códigos en tu dispositivo.

La función del código es obtener clima, temperatura y presión desde Home Assistant y mostrarlos en la pantalla.

Cuando veas una retroalimentación como la siguiente imagen, significa que el código se está ejecutando correctamente.


3. Mostrar íconos
Este ejemplo mostrará un ícono en la pantalla.
Primero, necesitamos instalar el complemento File Editor. Busca Studio Code Server y haz clic en él. Luego haz clic en INSTALL y START.


Después, crea una nueva carpeta llamada fonts y descarga este archivo, luego colócalo dentro de la carpeta fonts.

Después de instalar ESPHome y agregar un nuevo dispositivo, puedes copiar el siguiente código y pegarlo después de captive_portal
como se muestra a continuación.
Haz clic aquí para ver el código completo
font:
- file: 'fonts/materialdesignicons-webfont.ttf' #here is the directory to save ttf file
id: font_mdi_large
size: 200 # big size icon
glyphs: &mdi-weather-glyphs
- "\U000F0595" # weather cloudy
- "\U000F0592" # weather hail
- file: 'fonts/materialdesignicons-webfont.ttf'
id: font_mdi_medium # small size icon
size: 40
glyphs: *mdi-weather-glyphs
spi:
clk_pin: GPIO8
mosi_pin: GPIO10
display:
- platform: waveshare_epaper
cs_pin: GPIO3
dc_pin: GPIO5
busy_pin:
number: GPIO4
inverted: true
reset_pin: GPIO2
model: 7.50inv2
update_interval: 30s
lambda: |-
it.printf(100, 200, id(font_mdi_medium), TextAlign::CENTER, "\U000F0595");
it.printf(400, 200, id(font_mdi_large), TextAlign::CENTER, "\U000F0592");

Cuando veas una retroalimentación como la siguiente imagen, significa que el código se está ejecutando correctamente.

Si deseas usar otros íconos, puedes hacer clic en el siguiente botón para explorar más opciones.
Selecciona un ícono que desees.

Copia el código y pégalo en la parte de captive_portal, como se muestra en la siguiente imagen.


4. Mostrar imagen
Este ejemplo mostrará cualquier imagen que te guste en la pantalla.
Al igual que en el ejemplo anterior, necesitamos instalar Studio Code Server y crear una nueva carpeta llamada image para guardar la imagen.
Luego coloca una imagen dentro de la carpeta image. Puedes hacer clic en el siguiente botón para descargar una imagen de prueba.

Después de instalar ESPHome y agregar un nuevo dispositivo, puedes copiar el siguiente código y pegarlo después de captive_portal
, como se muestra a continuación.
Haz clic aquí para ver el código completo
image:
- file: /config/esphome/image/wifi.jpg # the path where you save the image, png or jpg format
id: myImage
type: BINARY
resize: 800x480 # how big you want to show, the biggest size should be as same as ePaper Penal pixel(800x480)
invert_alpha: true # invert color
spi:
clk_pin: GPIO8
mosi_pin: GPIO10
display:
- platform: waveshare_epaper
cs_pin: GPIO3
dc_pin: GPIO5
busy_pin:
number: GPIO4
inverted: true
reset_pin: GPIO2
model: 7.50inv2
update_interval: 30s
lambda: |-
it.image(0, 0, id(myImage));

Cuando veas una retroalimentación como la siguiente imagen, significa que el código se está ejecutando correctamente.

Demo 1. Tomar una captura de pantalla del panel de control de Home Assistant
Este ejemplo mostrará la captura de pantalla de HA en la pantalla.
Primero, necesitas instalar un complemento de captura de pantalla llamado Puppet, haz clic aquí para instalarlo.

Ten en cuenta que la versión debe ser igual o superior a la 1.11.4. Después de la instalación, ve a la página de Configuración. Necesitamos crear un access_token
para este complemento.

Sigue el siguiente paso para crear un token y pegarlo aquí.

Ve al final de la página de Seguridad y crea un token, luego cópialo y pégalo en el complemento Puppet.

Recuerda reiniciar el complemento Puppet.

Al iniciar el complemento se lanzará un nuevo servidor en el puerto 10000. Cualquier ruta que solicites devolverá una captura de pantalla de esa página. Necesitarás especificar el tamaño del viewport que deseas.
Por ejemplo, para obtener una captura de pantalla de 1000px x 1000px de tu panel predeterminado, solicita:
# http://192.168.1.191:10000/lovelace/0?viewport=1000x1000(My address)
http://homeassistant.local:10000/lovelace/0?viewport=1000x1000
Para reducir la paleta de colores para pantallas E Ink®, puedes agregar el parámetro eink
. El valor representa la cantidad de colores (incluyendo negro) a usar. Por ejemplo, para una pantalla E Ink® de 2 colores:
http://homeassistant.local:10000/lovelace/0?viewport=1000x1000&eink=2
Si usas eink=2
, también puedes invertir los colores agregando el parámetro invert
:
http://homeassistant.local:10000/lovelace/0?viewport=1000x1000&eink=2&invert
Además, también puedes tomar capturas de otras páginas, por ejemplo, la página de Listas de tareas en HA:
http://192.168.1.191:10000/todo?viewport=800x480&eink=2&invert
Puedes ver el efecto de la captura de pantalla introduciendo este enlace en tu navegador.

Después de instalar ESPHome y agregar un nuevo dispositivo, puedes copiar el siguiente código y pegarlo después de captive_portal
, como se muestra a continuación.
Haz clic aquí para ver el código completo
http_request:
verify_ssl: false
timeout: 10s
watchdog_timeout: 15s
online_image:
- id: dashboard_image
format: PNG
type: BINARY
buffer_size: 30000
url: http://192.168.1.191:10000/todo?viewport=800x480&eink=2&invert #change this link to your screenshot link
update_interval: 30s
on_download_finished:
- delay: 0ms
- component.update: main_display
spi:
clk_pin: GPIO8
mosi_pin: GPIO10
display:
- platform: waveshare_epaper
id: main_display
cs_pin: GPIO3
dc_pin: GPIO5
busy_pin:
number: GPIO4
inverted: true
reset_pin: GPIO2
model: 7.50inv2
update_interval: never
lambda: |-
it.image(0, 0, id(dashboard_image));

Cuando veas una retroalimentación como la siguiente imagen, significa que el código se está ejecutando correctamente.

Demo 2. Modo de suspensión profunda
Durante el modo de suspensión profunda, no puedes subir código directamente al dispositivo. Necesitas entrar en el modo de descarga. Haz clic aquí para ir a la pregunta 3.
Este ejemplo mostrará cómo usar el modo de suspensión profunda para ahorrar energía. Actualiza la información cada 6 horas. Una batería de 2000mAh puede durar alrededor de 3 meses.
Después de instalar ESPHome y agregar un nuevo dispositivo, puedes copiar el siguiente código y pegarlo después de captive_portal
como se muestra a continuación.
Haz clic aquí para ver el código completo
globals:
- id: sleep_counter
type: int
restore_value: yes # key parameter, to use RTC storage
initial_value: '0'
# Here is deep sleep part
deep_sleep:
id: deep_sleep_1
run_duration: 30s # Device wake up and run 30s (enough to display)
sleep_duration: 3min # deep sleep for 3min
interval:
- interval: 29s # run this command before the end of run_duration
then:
- logger.log: "Entering deep sleep now..."
font:
- file: "gfonts://Inter@700"
id: font1
size: 24
spi:
clk_pin: GPIO8
mosi_pin: GPIO10
display:
- platform: waveshare_epaper
cs_pin: GPIO3
dc_pin: GPIO5
busy_pin:
number: GPIO4
inverted: true
reset_pin: GPIO2
model: 7.50inv2
update_interval: 3min
lambda: |-
id(sleep_counter) += 1;
ESP_LOGD("main", "Wakeup count: %d", id(sleep_counter));
it.printf(100, 100, id(font1), "Wakeup count: %d", id(sleep_counter));

Verás un contador. Se incrementará en uno cada vez que el dispositivo despierte.

Demo 3. Ejemplo completo
Para que lo entiendas mejor, te recomendamos encarecidamente que ejecutes primero los usos básicos mencionados arriba.
Este ejemplo mostrará cómo obtener información del clima y del calendario desde Home Assistant y mostrarlos en la pantalla. Además, utilizará el modo de suspensión profunda para ahorrar energía. Actualiza la información cada 6 horas. Una batería de 2000mAh puede durar alrededor de 3 meses.
Primero, necesitas verificar si tienes el componente de clima en Home Assistant. Normalmente lo tendrás al instalar HA.

También puedes ir a Herramientas para desarrolladores -> ESTADOS para comprobar si tienes información del clima en HA. Esta es la información que obtendrás más adelante.

Segundo, necesitas instalar el componente de calendario en HA.
Ve a Configuración -> Dispositivos y Servicios -> Integraciones -> Agregar Integración


Selecciona Local Calendar y haz clic en el botón SUBMIT.


Después de eso, verás el Calendario Local en la parte de Configurado y en tu barra lateral.

Haz clic en Calendario en tu barra lateral y crea 3 calendarios nuevos llamados calendar, epaper_event y new_calendar. También puedes usar otros nombres, pero por favor mantén los mismos nombres en tu código después.


Antes de copiar el código, por favor coloca wifi.jpg, el archivo icon ttf y el archivo font ttf dentro de la carpeta image y fonts respectivamente.
Haz clic aquí para ver el código completo
esphome:
name: dashboard
friendly_name: dashboard
esp32:
board: esp32-c3-devkitm-1
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "jBgx0v+Y9eKiQmYTk0SCnHgtDowNDZqgFU26Z2VTYzM="
ota:
- platform: esphome
password: "9f78b53ef216c5d689f7408bb1ebe728"
# -------------------------------------- Keep your code above, change your code below --------------------------------------
globals:
- id: wifi_status
type: int
restore_value: no
initial_value: "0"
- id: first_update_done
type: bool
restore_value: no
initial_value: "false"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
on_connect:
then:
- lambda: |-
id(wifi_status) = 1;
on_disconnect:
then:
- lambda: |-
id(wifi_status) = 0;
captive_portal:
# Here is deep sleep part
deep_sleep:
id: deep_sleep_1
run_duration: 1min # Device wake up and run 60s (enough to pull data and update)
sleep_duration: 60min # deep sleep for 1h
script:
- id: update_display
then:
- component.update: my_display
interval:
# Condition: wifi connected && data retrieved && first time
- interval: 10s # Check every second
then:
- if:
condition:
and:
- wifi.connected:
- lambda: "return !id(ha_calendar_event_1).state.empty();"
- lambda: "return !id(first_update_done);"
then:
- lambda: |-
ESP_LOGD("Display", "Updating Display...");
- script.execute: update_display # Refresh immediately
- lambda: "id(first_update_done) = true;"
- interval: 59s # run this command before 1s of run_duration end
then:
- logger.log: "Entering deep sleep now..."
image:
- file: image/wifi.jpg
type: BINARY
id: esphome_logo
resize: 400x240
invert_alpha: true
# Connect to Home Assistant to get time
time:
- platform: homeassistant
id: homeassistant_time
text_sensor:
- platform: homeassistant
id: ha_calendar_event_1
entity_id: calendar.calendar
attribute: "message"
- platform: homeassistant
id: ha_calendar_start_time_1
entity_id: calendar.calendar
attribute: "start_time"
- platform: homeassistant
id: ha_calendar_end_time_1
entity_id: calendar.calendar
attribute: "end_time"
- platform: homeassistant
id: ha_calendar_event_2
entity_id: calendar.epaper_event
attribute: "message"
- platform: homeassistant
id: ha_calendar_start_time_2
entity_id: calendar.epaper_event
attribute: "start_time"
- platform: homeassistant
id: ha_calendar_end_time_2
entity_id: calendar.epaper_event
attribute: "end_time"
- platform: homeassistant
id: ha_calendar_event_3
entity_id: calendar.new_calendar
attribute: "message"
- platform: homeassistant
id: ha_calendar_start_time_3
entity_id: calendar.new_calendar
attribute: "start_time"
- platform: homeassistant
id: ha_calendar_end_time_3
entity_id: calendar.new_calendar
attribute: "end_time"
- platform: homeassistant
entity_id: weather.forecast_home
id: myWeather
- platform: homeassistant
entity_id: weather.forecast_home
id: temp
attribute: "temperature"
- platform: homeassistant
entity_id: weather.forecast_home
id: humi
attribute: "humidity"
- platform: homeassistant
entity_id: weather.forecast_home
id: press
attribute: "pressure"
- platform: homeassistant
entity_id: weather.forecast_home
id: wind
attribute: "wind_speed"
font:
- file: "fonts/Montserrat-Black.ttf"
id: web_font
size: 20
- file: "fonts/Montserrat-Black.ttf"
id: data_font
size: 30
- file: "fonts/Montserrat-Black.ttf"
id: sensor_font
size: 22
- file: "gfonts://Inter@700" #
id: font1
size: 24
- file: 'fonts/materialdesignicons-webfont.ttf' # Directory to save ttf file
id: font_mdi_large
size: 200
glyphs: &mdi-weather-glyphs # https://pictogrammers.com/library/mdi/
- "\U000F050F" # Thermometer
- "\U000F058E" # Humidity
- "\U000F059D" # Wind speed
- "\U000F0D60" # Atmospheric pressure
- "\U000F0590" # Cloudy weather
- "\U000F0596" # Rainy weather
- "\U000F0598" # Snowy weather
- "\U000F0599" # Sunny weather
- file: 'fonts/materialdesignicons-webfont.ttf'
id: font_weather # Copy the above icon and change the size to 40
size: 200
glyphs: *mdi-weather-glyphs
- file: 'fonts/materialdesignicons-webfont.ttf'
id: img_font_sensor # Copy the above icon and change the size to 40
size: 70
glyphs: *mdi-weather-glyphs
spi:
clk_pin: GPIO8
mosi_pin: GPIO10
display:
- platform: waveshare_epaper
id: my_display
cs_pin: GPIO3
dc_pin: GPIO5
busy_pin:
number: GPIO4
inverted: true
reset_pin: GPIO2
model: 7.50inv2
update_interval: 50s
lambda: |-
if(id(wifi_status) == 0){
it.image(180, 0, id(esphome_logo));
it.print(230, 300, id(data_font), "WI-FI CONNECTING");
}else{
// Draw weather images here
std::string weather_string = id(myWeather).state.c_str();
if(weather_string == "rainy" || weather_string == "lightning" || weather_string == "pouring"){
// Draw rainy weather image
it.printf(120, 85, id(font_weather), TextAlign::CENTER, "\U000F0596");
}else if(weather_string == "snowy"){
// Draw snowy weather image
it.printf(120, 85, id(font_weather), TextAlign::CENTER, "\U000F0598");
}else if(weather_string == "sunny" || weather_string == "windy"){
// Draw sunny weather image
it.printf(120, 85, id(font_weather), TextAlign::CENTER, "\U000F0599");
}else{
// Draw cloudy weather image
it.printf(120, 85, id(font_weather), TextAlign::CENTER, "\U000F0590");
}
auto time_now = id(homeassistant_time).now();
// Month conversion
const char* months[] = {
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
};
const char* month_str = months[time_now.month - 1]; // Month index starts from 0
// Get the day
int day = time_now.day_of_month;
// Draw the date
it.printf(250, 110, id(data_font), "%s %d", month_str, day);
// Get the day of the week
const char* days[] = {"Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"};
const char* day_of_week = days[time_now.day_of_week];
it.printf(250, 70, id(data_font), "%s", day_of_week);
int x = 20, y = 180, w = 180, h = 120, r = 10, thickness = 4;
// Draw four borders
it.filled_rectangle(x + r, y, w - 2 * r, thickness); // Top border
it.filled_rectangle(x + r, y + h - thickness, w - 2 * r, thickness); // Bottom border
it.filled_rectangle(x, y + r, thickness, h - 2 * r); // Left border
it.filled_rectangle(x + w - thickness, y + r, thickness, h - 2 * r); // Right border
// Draw four rounded corners
it.filled_circle(x + r, y + r, r); // Top-left corner
it.filled_circle(x + w - r, y + r, r); // Top-right corner
it.filled_circle(x + r, y + h - r, r); // Bottom-left corner
it.filled_circle(x + w - r, y + h - r, r); // Bottom-right corner
// Fill the inside with black to form a border
it.filled_rectangle(x + thickness, y + thickness, w - 2 * thickness, h - 2 * thickness, COLOR_OFF);
// Temperature
it.printf(x+10, y+10, id(sensor_font), "Temperature");
it.printf(x+45, y+75, id(img_font_sensor), TextAlign::CENTER, "\U000F050F");
// Get temperature data
it.printf(x+75,y+65, id(data_font), "%s°F", id(temp).state.c_str());
x = 220;
y = 180;
// Draw four borders
it.filled_rectangle(x + r, y, w - 2 * r, thickness); // Top border
it.filled_rectangle(x + r, y + h - thickness, w - 2 * r, thickness); // Bottom border
it.filled_rectangle(x, y + r, thickness, h - 2 * r); // Left border
it.filled_rectangle(x + w - thickness, y + r, thickness, h - 2 * r); // Right border
// Draw four rounded corners
it.filled_circle(x + r, y + r, r); // Top-left corner
it.filled_circle(x + w - r, y + r, r); // Top-right corner
it.filled_circle(x + r, y + h - r, r); // Bottom-left corner
it.filled_circle(x + w - r, y + h - r, r); // Bottom-right corner
// Fill the inside with black to form a border
it.filled_rectangle(x + thickness, y + thickness, w - 2 * thickness, h - 2 * thickness, COLOR_OFF);
// Humidity
it.printf(x+10, y+10, id(sensor_font), "Humidity");
it.printf(x+45, y+75, id(img_font_sensor), TextAlign::CENTER, "\U000F058E");
// Get humidity data
it.printf(x+75,y+65, id(data_font), "%s%%", id(humi).state.c_str());
x = 20;
y = 320;
// Draw four borders
it.filled_rectangle(x + r, y, w - 2 * r, thickness); // Top border
it.filled_rectangle(x + r, y + h - thickness, w - 2 * r, thickness); // Bottom border
it.filled_rectangle(x, y + r, thickness, h - 2 * r); // Left border
it.filled_rectangle(x + w - thickness, y + r, thickness, h - 2 * r); // Right border
// Draw four rounded corners
it.filled_circle(x + r, y + r, r); // Top-left corner
it.filled_circle(x + w - r, y + r, r); // Top-right corner
it.filled_circle(x + r, y + h - r, r); // Bottom-left corner
it.filled_circle(x + w - r, y + h - r, r); // Bottom-right corner
// Fill the inside with black to form a border
it.filled_rectangle(x + thickness, y + thickness, w - 2 * thickness, h - 2 * thickness, COLOR_OFF);
// Air Pressure
it.printf(x+10, y+10, id(sensor_font), "Air Pressure");
it.printf(x+45, y+75, id(img_font_sensor), TextAlign::CENTER, "\U000F0D60");
// Get atmospheric pressure data
it.printf(x+85,y+50, id(data_font), "%s", id(press).state.c_str());
it.printf(x+85,y+78, id(sensor_font), "inHg");
x = 220;
y = 320;
// Draw four borders
it.filled_rectangle(x + r, y, w - 2 * r, thickness); // Top border
it.filled_rectangle(x + r, y + h - thickness, w - 2 * r, thickness); // Bottom border
it.filled_rectangle(x, y + r, thickness, h - 2 * r); // Left border
it.filled_rectangle(x + w - thickness, y + r, thickness, h - 2 * r); // Right border
// Draw four rounded corners
it.filled_circle(x + r, y + r, r); // Top-left corner
it.filled_circle(x + w - r, y + r, r); // Top-right corner
it.filled_circle(x + r, y + h - r, r); // Bottom-left corner
it.filled_circle(x + w - r, y + h - r, r); // Bottom-right corner
// Fill the inside with black to form a border
it.filled_rectangle(x + thickness, y + thickness, w - 2 * thickness, h - 2 * thickness, COLOR_OFF);
// Wind Speed
it.printf(x+10, y+10, id(sensor_font), "Wind Speed");
it.printf(x+45, y+75, id(img_font_sensor), TextAlign::CENTER, "\U000F059D");
// Get wind speed data
it.printf(x+85,y+50, id(data_font), "%s", id(wind).state.c_str());
it.printf(x+85,y+78, id(sensor_font), "mph");
// Draw a vertical line
it.filled_rectangle(430, 30, 5, 430);
// Right section
it.printf(540, 40, id(data_font), "Calendar");
// Define event structure
struct Event {
std::string message;
std::string start_time;
std::string end_time;
time_t start_timestamp;
};
// Parse time string to time_t (UNIX timestamp)
auto parse_time = [](const std::string &time_str) -> time_t {
struct tm timeinfo = {};
if (strptime(time_str.c_str(), "%Y-%m-%d %H:%M:%S", &timeinfo) == nullptr) {
return 0; // Invalid time
}
return mktime(&timeinfo);
};
// Create event list
std::vector<Event> events = {
{id(ha_calendar_event_1).state, id(ha_calendar_start_time_1).state, id(ha_calendar_end_time_1).state, parse_time(id(ha_calendar_start_time_1).state)},
{id(ha_calendar_event_2).state, id(ha_calendar_start_time_2).state, id(ha_calendar_end_time_2).state, parse_time(id(ha_calendar_start_time_2).state)},
{id(ha_calendar_event_3).state, id(ha_calendar_start_time_3).state, id(ha_calendar_end_time_3).state, parse_time(id(ha_calendar_start_time_3).state)}
};
ESP_LOGD("myCalendar", "Start Time: %s -> %ld", id(ha_calendar_start_time_1).state.c_str(), parse_time(id(ha_calendar_start_time_1).state));
ESP_LOGD("myCalendar", "Start Time: %s -> %ld", id(ha_calendar_start_time_2).state.c_str(), parse_time(id(ha_calendar_start_time_2).state));
ESP_LOGD("myCalendar", "Start Time: %s -> %ld", id(ha_calendar_start_time_3).state.c_str(), parse_time(id(ha_calendar_start_time_3).state));
// Filter invalid events (start_timestamp == 0)
events.erase(std::remove_if(events.begin(), events.end(), [](const Event &e) { return e.start_timestamp == 0; }), events.end());
// Sort by `start_timestamp` (earliest to latest)
std::sort(events.begin(), events.end(), [](const Event &a, const Event &b) {
return a.start_timestamp < b.start_timestamp;
});
// Define a function to format time
auto format_time = [](std::string time_str) -> std::string {
struct tm timeinfo;
if (strptime(time_str.c_str(), "%Y-%m-%d %H:%M:%S", &timeinfo) == nullptr) {
return "Invalid";
}
char buffer[10];
strftime(buffer, sizeof(buffer), "%I:%M%p", &timeinfo); // Convert to 12-hour format
return std::string(buffer);
};
// Parse date
auto format_date = [](const std::string &time_str) -> std::string {
struct tm timeinfo = {};
if (strptime(time_str.c_str(), "%Y-%m-%d %H:%M:%S", &timeinfo) == nullptr) {
return "Invalid";
}
char buffer[6]; // Need to store "MM-DD\0"
strftime(buffer, sizeof(buffer), "%m-%d", &timeinfo);
return std::string(buffer);
};
// Draw events
int even_x_start_offset = 460;
int even_y_start_offset = 80;
for (const auto &event : events) {
if(even_y_start_offset >= 420){
break;
}
// Format time
std::string formatted_date = format_date(event.start_time);
std::string formatted_start_time = format_time(event.start_time);
std::string formatted_end_time = format_time(event.end_time);
// Combine time range string
std::string time_range = formatted_start_time + " - " + formatted_end_time;
time_range = formatted_date + " " + time_range;
if(formatted_start_time == "Invalid" || formatted_end_time == "Invalid"){
time_range.clear();
}
// Display time range, e.g., "10:00AM - 11:00AM"
it.printf(even_x_start_offset, even_y_start_offset, id(sensor_font), "%s", time_range.c_str());
even_y_start_offset += 30;
// Display event name
it.printf(even_x_start_offset, even_y_start_offset, id(sensor_font), "%s", event.message.c_str());
even_y_start_offset += 40;
}
}
Cuando veas una retroalimentación como la siguiente imagen, significa que el código se está ejecutando correctamente.

Preguntas frecuentes (FAQ)
P1: ¿Por qué no hay datos?

En este caso, debes ir a Configuración -> Dispositivos y Servicios -> Integraciones para RECONFIGURAR el dispositivo. ¿No encuentras tu panel ePaper? Intenta reiniciar Home Assistant.

P2: ¿Por qué no puedo obtener esos datos en Home Assistant?
En este caso, debes ir a Configuración -> Dispositivos y Servicios -> Integraciones para AGREGAR tu dispositivo a HA.

P3: ¿Cómo puedo subir un nuevo programa cuando el dispositivo está en modo de suspensión profunda?


Cuando el dispositivo está en modo de suspensión profunda, no puedes subir un nuevo programa directamente.
-
Primero, asegúrate de que el dispositivo esté encendido, y luego presiona el botón Boot en la parte trasera de la placa.
-
Pulsa una vez el botón Reset y suelta el botón Boot.
-
Después, apaga el interruptor de la batería y desconecta el cable de alimentación.
-
Finalmente, vuelve a conectar el cable y sube el nuevo programa.
P4: ¿Cuánto dura la batería?
Recuerda encender el botón de la batería al cargarla. De lo contrario, la batería no podrá cargarse.
Después de nuestras pruebas, refrescando la pantalla cada 6 horas, la batería durará aproximadamente 3 meses en modo de suspensión profunda.
P5: ¿El panel ePaper no se conecta a tu computadora?

Intenta desconectarlo y volverlo a conectar varias veces, o simplemente instala el controlador según las indicaciones.
P6: ¿Falló la carga del programa vía Wi-Fi?

En este caso, tu panel ePaper está desconectado o en modo de suspensión profunda. Por favor, ponlo en línea o despiértalo.
Recursos
Soporte Técnico y Discusión del Producto
¡Gracias por elegir nuestros productos! Estamos aquí para brindarte diferentes tipos de soporte para asegurar que tu experiencia con nuestros productos sea lo más fluida posible. Ofrecemos varios canales de comunicación para adaptarnos a distintas preferencias y necesidades.