Pular para o conteúdo principal

Funciona com ESPHome no Home Assistant


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 única interface unificada. Ele atua como o hub central da sua casa inteligente, possibilitando 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 é executado 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 disparos, 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 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 consome energia apenas ao atualizar o conteúdo, tornando-o perfeito para exibir informações persistentes, como previsões do tempo, eventos de calendário ou status do sistema.

  2. Ótima visibilidade: Diferente de telas LCD, displays e-paper são facilmente legíveis em qualquer condição de iluminação, incluindo luz solar direta, o que os torna 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 em um relance.

  4. Integração flexível: Por meio do ESPHome, o display se integra perfeitamente ao Home Assistant, permitindo que você exiba 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 eficiente em energia 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 arquivos de configuração YAML simples, que podem então ser gravados no seu dispositivo. Para o XIAO 7.5" ePaper Panel, o ESPHome funciona como a camada intermediária 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 é executado 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 aproveitar ao máximo esse display versátil.

Primeiros Passos

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

Materiais Necessários

XIAO 7.5" ePaper PanelHome Assistant Green

Home Assistant Green é a forma mais fácil e com maior foco em privacidade de automatizar sua casa. Ele oferece uma configuração sem esforço 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 pelo código aberto.

Recomendamos usar o Home Assistant Green como o host do Home Assistant para este tutorial, ou você pode usar qualquer host do 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 da 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 conseguir encontrar o ESPHome na loja de complementos, certifique-se de que está usando uma instalação do Home Assistant que ofereça suporte a complementos (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 exibirá "Hello World!" no display.

O objetivo principal é mostrar a você diferentes maneiras de instalar 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 iremos enviar o firmware para o painel de ePaper.

Volte para o ESPHome para baixar o firmware.

Selecione o formato Factory.

Use um cabo USB para conectar o painel de 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.

Espere um momento e você verá “Hello world!” no display ~

Usos básicos

1. Exibir forma

Este exemplo exibirá uma forma no display.

Após instalar o ESPHome e adicionar um novo dispositivo, você pode copiar o código abaixo e colá-lo na parte de 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 um 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 exibirá no display as informações do HA.

Antes de tudo, você precisa adicionar este dispositivo ao HA. Caso contrário, você não conseguirá 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 um retorno como na imagem a seguir, isso significa que o código está sendo executado com sucesso.

3. Exibir ícone

Este exemplo vai 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 faça o download deste 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, isso significa que o código está sendo executado com sucesso.

Se quiser usar outros ícones, você 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 vai 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.

Depois, 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, isso significa que o código está sendo executado com sucesso.

Demo 1. Tirar um screenshot do dashboard do Home Assistant

Este exemplo vai mostrar o screenshot do HA na tela.

Primeiro, você precisa instalar um Add-on 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 de configuração. Precisamos criar um access_token para este add-on.

Veja o próximo passo para criar um token e colar aqui.

Vá até o final da página de segurança e crie um token e, em seguida, copie e cole-o no add-on Puppet.

Lembre-se de reiniciar o add-on Puppet.

Iniciar o add-on lançará um novo servidor na porta 10000. Qualquer caminho que você solicitar retornará um screenshot dessa página. Você precisará especificar o tamanho de viewport desejado.

Por exemplo, para obter um screenshot de 1000px x 1000px do seu dashboard 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 ver o 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 retorno 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 a Q3.

Este exemplo vai 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 acordar.

Demo 3. Exemplo abrangente

dica

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

Este exemplo vai mostrar como obter informações de clima e de calendário do HA e exibi-las no display. 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 você tem 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, por favor 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 um retorno como na imagem a seguir, isso significa que o código está sendo executado com sucesso.

FAQ

P1: Por que não há dados?

Neste 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?

Neste 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.

De acordo com nossos testes, atualizando a tela a cada 6 horas, a bateria durará 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 instale o driver de acordo com as instruções.

P6: Falha ao enviar o programa por Wi-Fi?

Neste caso, seu epaper penal está offline ou em modo de sono profundo. Por favor, coloque-o online ou acorde-o.

Recursos

Suporte Técnico & Discussão sobre o Produto

Obrigado por escolher nossos produtos! Estamos aqui para oferecer 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...