Pular para o conteúdo principal

Cookbook ESPHome: XIAO 7,5" ePaper Panel

Leia primeiro o guia principal de ESPHome

Esta página é o cookbook de ESPHome específico para o XIAO 7,5" Panel. O conteúdo compartilhado — escolher um método de gravação, o esqueleto genérico de YAML, conexão com o Home Assistant — está em Work with ESPHome. Dê uma olhada nele primeiro se você é novo em ESPHome nos ePaper da Seeed; esta página foca no que é específico para o painel baseado em XIAO ESP32-C3.


Introdução ao Home Assistant​

Home Assistant é uma poderosa plataforma de automação residencial de código aberto que permite controlar e monitorar seus dispositivos de casa inteligente a partir de uma interface única e unificada. Ele atua como o hub central da sua casa inteligente, permitindo automatizar rotinas, monitorar sensores e criar um ambiente mais inteligente.

Por que usar o Home Assistant?​

  • Controle local: Diferente de muitas soluções baseadas em nuvem, o Home Assistant roda localmente na sua rede, garantindo que seus dados permaneçam privados e que suas automações funcionem mesmo sem acesso à internet.

  • Amplo suporte a dispositivos: O Home Assistant integra-se a milhares de diferentes dispositivos e serviços de casa inteligente, tornando-o altamente versátil e preparado para o futuro.

  • Automação poderosa: Crie regras de automação sofisticadas que podem responder a vários gatilhos, como horário, estados de dispositivos, leituras de sensores e muito mais.

  • Dashboard personalizável: Projete sua própria interface de usuário para exibir as informações que mais importam para você.

Por que usar um display E-Paper com o Home Assistant?​

O XIAO 7,5" ePaper Panel é um excelente companheiro para o Home Assistant por vários motivos:

  1. Eficiência energética: O display e-paper só consome energia ao atualizar o conteúdo, sendo perfeito para exibir informações persistentes como previsões do tempo, eventos de calendário ou status do sistema.

  2. Ótima visibilidade: Diferente das telas LCD, os displays e-paper são facilmente legíveis em qualquer condição de iluminação, incluindo luz solar direta, tornando-os ideais para painéis de controle de parede.

  3. Longa duração de bateria: Combinado com o modo de sono profundo, o display pode operar por meses com uma única carga de bateria, ainda fornecendo informações valiosas de relance.

  4. Integração flexível: Através do ESPHome, o display se integra perfeitamente ao Home Assistant, permitindo mostrar qualquer dado do seu sistema de casa inteligente em um formato elegante e sempre visível.

Essas vantagens fazem do XIAO 7,5" ePaper Panel uma escolha ideal para criar um display de informações sempre ligado e energeticamente eficiente para sua configuração de Home Assistant.

Integração com ESPHome​

ESPHome é uma ferramenta de criação de firmware de código aberto projetada especificamente para dispositivos ESP8266/ESP32. Ela permite criar firmware personalizado usando simples arquivos de configuração YAML, que podem então ser gravados no seu dispositivo. Para o XIAO 7,5" ePaper Panel, o ESPHome atua como o middleware essencial que habilita a comunicação entre o dispositivo e o Home Assistant.

O sistema funciona convertendo sua configuração YAML em um firmware completo que roda no seu dispositivo ESP. Esse firmware lida com todas as tarefas complexas de conexão à sua rede, comunicação com o Home Assistant e controle do display ePaper. Quando combinado com o Home Assistant, o ESPHome fornece uma plataforma robusta para criar displays e controles sofisticados de automação residencial.

Vamos explorar como configurá-lo e tirar o máximo proveito desse display versátil.

Primeiros passos​

Antes de começar o conteúdo do tutorial deste artigo, você pode precisar ter o seguinte hardware preparado.

Materiais necessários​

XIAO 7,5" ePaper PanelHome Assistant Green

Home Assistant Green é a maneira mais fácil e com maior foco em privacidade para automatizar sua casa. Ele oferece uma configuração simples e permite controlar todos os dispositivos inteligentes com apenas um sistema, onde todos os dados são armazenados localmente por padrão. Esta placa se beneficia do próspero ecossistema do Home Assistant e será aprimorada todos os meses pela comunidade de código aberto.

Recomendamos usar o Home Assistant Green como host do Home Assistant para este tutorial, ou você pode usar qualquer host de Home Assistant com Supervisor.

instalar o Home Assistant

Também escrevemos como instalar o Home Assistant para alguns produtos da Seeed Studio, consulte-os.

Se você não estiver usando um produto Seeed Studio, também pode verificar e aprender como instalar o Home Assistant para outros produtos no site oficial do Home Assistant.

Etapa 1. Instalar o ESPHome​

Se você já instalou o ESPHome, pode pular esta etapa.

Vá em Settings -> Add-ons -> ADD-ON STORE

Pesquise por ESPHome e clique nele. Clique em INSTALL e START.

dica

Se você não encontrar o ESPHome na loja de add-ons, certifique-se de que está usando uma instalação do Home Assistant que suporte add-ons (como Home Assistant OS ou instalações supervisionadas). Para outros tipos de instalação (como Home Assistant Container), talvez seja necessário executar o ESPHome Device Builder de forma independente usando Docker. Consulte a documentação oficial do ESPHome para mais detalhes.

Em seguida, o ESPHome Builder aparecerá na barra lateral.

Etapa 2. Adicionar um novo dispositivo​

Vá para o ESPHome e clique em NEW DEVICE.

Dê ao dispositivo um nome de sua preferência e clique em NEXT.

Depois de criar um novo dispositivo, clique em EDIT.

Etapa 3. Instalar o firmware​

Este é um exemplo bem básico e mostrará "Hello World!" no display.

O principal objetivo é mostrar diferentes maneiras de instalar o firmware no dispositivo.

Depois de instalar o ESPHome e adicionar um novo dispositivo, você pode copiar o código abaixo e colá-lo após captive_portal como mostrado abaixo.

Clique aqui para visualizar o 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!");

Clique em INSTALL para instalar o código no dispositivo e você verá a imagem a seguir.

dica

Se o seu Home Assistant Host (Raspberry PI/Green/Yellow etc.) estiver longe de você, recomendamos usar este método. Você pode instalá-lo com o computador que tiver em mãos.

Primeiro, você precisa clicar em Manual download para baixar o firmware compilado.

Abra este site onde faremos o upload do firmware para o painel ePaper.

Volte para o ESPHome para baixar o firmware.

Selecione Factory format.

Use um cabo USB para conectar o painel ePaper ao seu computador e clique em CONNECT.

Selecione usbmodemxxx (no Windows é COMxxx) e clique em connect. Encontrou um problema? Clique aqui.

Clique em INSTALL e selecione o firmware que você acabou de baixar.

Aguarde um momento e você verá 'Hello world!' no display ~

Usos básicos​

1. Exibir forma​

Este exemplo mostrará uma forma no display.

Depois de instalar o ESPHome e adicionar um novo dispositivo, você pode copiar o código abaixo e colá-lo na parte captive_portal, como na imagem a seguir.

Clique aqui para copiar o 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);

Quando você vir o retorno como na imagem a seguir, isso significa que o código está sendo executado com sucesso.

Você também pode clicar aqui para ver mais usos.

2. Exibir informações no HA​

Este exemplo mostrará no display as informações do HA.

Antes de tudo, você precisa adicionar este dispositivo ao HA. Caso contrário, você não poderá obter as informações do HA.

Se o HA não mostrar o dispositivo, você deve executar primeiro o demo acima. Depois de executar o demo acima, você poderá ver o dispositivo no HA.

Em seguida, clique em SUBMIT e FINISH.

Depois de instalar o ESPHome e adicionar um novo dispositivo, você pode copiar o código abaixo e colá-lo após captive_portal, como mostrado abaixo.

Clique aqui para visualizar o 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);

Instale esses códigos no seu dispositivo.

A função do código é obter clima, temperatura e pressão do HA e exibi-los no display.

Quando você vir o retorno como na imagem a seguir, isso significa que o código está sendo executado com sucesso.

3. Exibir ícone​

Este exemplo irá mostrar um ícone na tela.

Primeiro, precisamos instalar o complemento File Editor. Pesquise por Studio Code Server e clique nele. Clique em INSTALL e START.

E então, crie uma nova pasta chamada fonts e baixe este arquivo e coloque-o na pasta fonts.

Depois de instalar o ESPHome e adicionar um novo dispositivo, você pode copiar o código abaixo e colá-lo após captive_portal, como mostrado abaixo.

Clique aqui para visualizar o 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");

Quando você vir o retorno como na imagem a seguir, significa que o código está sendo executado com sucesso.

Se você quiser usar outros ícones, pode clicar no botão abaixo para explorar mais.

Selecione o ícone que você quiser.

Copie o código e cole-o na parte de captive_portal, como na imagem a seguir.

4. Exibir imagem​

Este exemplo irá mostrar quaisquer imagens que você quiser na tela.

Como no exemplo anterior, precisamos instalar o Studio Code Server e criar uma nova pasta chamada image para salvar a imagem.

Em seguida, coloque uma imagem na pasta image. Você pode clicar no botão abaixo para baixar uma imagem e fazer um teste.

Depois de instalar o ESPHome e adicionar um novo dispositivo, você pode copiar o código abaixo e colá-lo após captive_portal, como mostrado abaixo.

Clique aqui para visualizar o 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));

Quando você vir o retorno como na imagem a seguir, significa que o código está sendo executado com sucesso.

Demo 1. Tirar um screenshot do painel do Home Assistant​

Este exemplo irá mostrar o screenshot do HA na tela.

Primeiro, você precisa instalar um complemento de screenshot, o Puppet, clique aqui para instalar.

Observe que a versão deve ser maior ou igual a 1.11.4. Após a instalação, vá para a página Configuration. Precisamos criar um access_token para este complemento.

Veja o próximo passo para criar um token e colá-lo aqui.

Vá até o final da página Security e crie um token e, em seguida, copie e cole-o no complemento Puppet.

Lembre-se de reiniciar o complemento Puppet.

Iniciar o complemento irá lançar um novo servidor na porta 10000. Qualquer caminho que você solicitar retornará um screenshot dessa página. Você precisará especificar o tamanho da viewport desejada.

Por exemplo, para obter um screenshot de 1000px x 1000px do seu painel padrão, busque:

# http://192.168.1.191:10000/lovelace/0?viewport=1000x1000(My address)

http://homeassistant.local:10000/lovelace/0?viewport=1000x1000

Para reduzir a paleta de cores para telas E Ink®, você pode adicionar o parâmetro eink. O valor representa o número de cores (incluindo preto) a serem usadas. Por exemplo, para uma tela E Ink® de 2 cores:

http://homeassistant.local:10000/lovelace/0?viewport=1000x1000&eink=2

Se você estiver usando eink=2, também pode inverter as cores adicionando o parâmetro invert:

http://homeassistant.local:10000/lovelace/0?viewport=1000x1000&eink=2&invert

Além disso, você também pode tirar screenshot de outra página, por exemplo a página de To-do lists no HA:

http://192.168.1.191:10000/todo?viewport=800x480&eink=2&invert

Você pode dar uma olhada no efeito do screenshot inserindo este link no seu navegador.

Depois de instalar o ESPHome e adicionar um novo dispositivo, você pode copiar o código abaixo e colá-lo após captive_portal, como mostrado abaixo.

Clique aqui para visualizar o 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));

Quando você vir o feedback como na imagem a seguir, isso significa que o código está sendo executado com sucesso.

Demo2. Modo de sono profundo​

dica

Durante o modo de sono profundo, você não pode enviar código para o dispositivo diretamente. Você precisa entrar no modo de download. Clique aqui para pular para Q3.

Este exemplo mostrará como usar o modo de sono profundo para economizar energia. Atualize as informações a cada 6 horas. Uma bateria de 2000mAh pode durar cerca de 3 meses.

Depois de instalar o ESPHome e adicionar um novo dispositivo, você pode copiar o código abaixo e colá-lo após captive_portal, como mostrado abaixo.

Clique aqui para visualizar o 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));

Você verá um contador. Ele será incrementado em um a cada vez que o dispositivo acordar.

Demo 3. Exemplo abrangente​

dica

Para que você entenda melhor, recomendamos fortemente que execute primeiro os usos básicos acima.

Este exemplo mostrará como obter informações de clima e informações de calendário do HA e exibi-las na tela. Além disso, ele usará o modo de sono profundo para economizar energia. Atualize as informações a cada 6 horas. Uma bateria de 2000mAh pode durar cerca de 3 meses.

Primeiro, você precisa verificar se possui o componente de clima no HA. Normalmente, você terá um quando instalar o HA.

Você também pode ir para Developer Tools -> STATES para verificar se você tem informações de clima no HA. Aqui estão as informações que você obterá depois.

Em segundo lugar, você precisa instalar o componente de calendário no HA.

Vá para Settings -> Devices & Services -> Integrations -> Add Integration

Selecione Local Calendar e clique no botão SUBMIT.

Depois disso, você verá o Local Calendar na parte Configured e na sua barra lateral.

Clique em Calendar na sua barra lateral e crie 3 novos calendários chamados calendar, epaper_event e new_calendar. Você também pode usar outros nomes, mas mantenha o mesmo nome no seu código depois.

dica

Antes de copiar o código, coloque wifi.jpg, arquivo ttf de ícone e arquivo ttf de fonte na pasta image e na pasta fonts.

Clique aqui para visualizar o 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;
}
}


Quando você vir o feedback como na imagem a seguir, isso significa que o código está sendo executado com sucesso.

FAQ​

P1: Por que não há dados?​

Nesse caso, você deve ir em Settings -> Devices & Services -> Integrations para RECONGFIGURE o dispositivo. Não encontrou seu ePaper Penal? Tente reiniciar o HA.

P2: Por que não consigo obter esses dados no Home Assistant?​

Nesse caso, você deve ir em Settings -> Devices & Services -> Integrations para ADD seu dispositivo ao HA.

P3: Como posso enviar um novo programa quando o dispositivo está em modo de sono profundo?​

Quando o dispositivo está em modo de sono profundo, você não pode enviar um novo programa diretamente.

  1. Primeiro, certifique-se de que o dispositivo está ligado e, em seguida, pressione o botão Boot na parte de trás da placa.

  2. Clique uma vez no botão Reset e solte o botão Boot.

  3. Depois disso, desligue o interruptor da bateria e desconecte o cabo de alimentação.

  4. Por fim, conecte o cabo novamente e envie um novo programa.

P4: Quanto tempo dura a bateria?​

dica

Lembre-se de ligar o botão da bateria ao carregar. Caso contrário, a bateria não poderá ser carregada.

Após nossos testes, atualizando a tela a cada 6 horas, a bateria dura cerca de 3 meses em modo de sono profundo.

P5: ePaper Penel não consegue se conectar ao seu computador?​

Tente desconectar e reconectar várias vezes ou simplesmente instalar o driver de acordo com as instruções.

P6: Falha ao enviar programa via Wi‑Fi?​

Nesse caso, seu epaper penal está offline ou em modo de sono profundo. Coloque-o online ou acorde-o.

Recursos​

Suporte Técnico e Discussão de Produto​

Obrigado por escolher nossos produtos! Estamos aqui para fornecer diferentes tipos de suporte para garantir que sua experiência com nossos produtos seja a mais tranquila possível. Oferecemos vários canais de comunicação para atender a diferentes preferências e necessidades.

Loading Comments...