TRMNL 7.5inch(OG) DIY Kit 与 ESPHome 配合工作

Home Assistant 简介
Home Assistant 是一个功能强大的开源家庭自动化平台,允许您从一个统一的界面控制和监控智能家居设备。它充当智能家居的中央枢纽,使您能够自动化日常任务、监控传感器并创建更智能的生活空间。

为什么选择 Home Assistant?
-
本地控制:与许多基于云的解决方案不同,Home Assistant 在您的网络上本地运行,确保您的数据保持私密,即使没有互联网连接,您的自动化也能正常工作。
-
广泛的设备支持:Home Assistant 与数千种不同的智能家居设备和服务集成,使其具有高度的通用性和面向未来的特性。
-
强大的自动化:创建复杂的自动化规则,可以响应各种触发器,如时间、设备状态、传感器读数等。
-
可定制的仪表板:设计您自己的用户界面,显示对您最重要的信息。
为什么 TRMNL 7.5inch(OG) DIY Kit 与 Home Assistant 配合使用?
TRMNL 7.5inch(OG) DIY Kit 是 Home Assistant 的绝佳伴侣,原因如下:
-
节能高效:电子纸显示屏仅在更新内容时消耗电力,非常适合显示持久信息,如天气预报、日历事件或系统状态。
-
清晰可见:与 LCD 屏幕不同,电子纸显示屏在任何光照条件下都易于阅读,包括直射阳光,使其成为壁挂式家庭控制面板的理想选择。
-
长电池续航:结合深度睡眠模式,显示屏可以在单次电池充电下运行数月,同时仍能一目了然地提供有价值的信息。
-
灵活集成:通过 ESPHome,显示屏与 Home Assistant 无缝集成,允许您以优雅、始终可见的格式显示智能家居系统中的任何数据。
这些优势使 TRMNL 7.5inch(OG) DIY Kit 成为为您的 Home Assistant 设置创建节能、始终在线信息显示的理想选择。
ESPHome 集成
ESPHome 是专为 ESP8266/ESP32 设备设计的开源固件创建工具。它允许您使用简单的 YAML 配置文件创建自定义固件,然后可以刷写到您的设备上。对于 TRMNL 7.5inch(OG) DIY Kit,ESPHome 充当设备与 Home Assistant 之间通信的重要中间件。
该系统通过将您的 YAML 配置转换为在 ESP 设备上运行的功能齐全的固件来工作。该固件处理连接到网络、与 Home Assistant 通信以及控制电子纸显示屏的所有复杂任务。当与 Home Assistant 结合使用时,ESPHome 为创建复杂的家庭自动化显示和控制提供了强大的平台。
让我们探索如何设置并充分利用这个多功能显示屏。
入门指南
在本文的教程内容开始之前,您可能需要准备以下硬件。
所需材料
Home Assistant Green 是自动化家居最简单、最注重隐私的方式。它提供轻松的设置,允许您用一个系统控制所有智能设备,默认情况下所有数据都存储在本地。该板受益于蓬勃发展的 Home Assistant 生态系统,并将通过开源每月改进。
我们建议在本教程中使用 Home Assistant Green 作为 Home Assistant 主机,或者您可以使用任何带有 Supervisor 的 Home Assistant 主机。
我们还为一些 Seeed Studio 产品编写了如何安装 Home Assistant 的教程,请参考它们。
- 在 ODYSSEY-X86 上开始使用 Home Assistant
- 在 reTerminal 上开始使用 Home Assistant
- 在 LinkStar H68K/reRouter CM4 上开始使用 Home Assistant
如果您没有使用 Seeed Studio 产品,您也可以在 Home Assistant 官方网站上查看并学习如何为其他产品安装 Home Assistant。
设备安装
步骤 1. 将显示屏连接到驱动板
将 FPC 电缆与 XIAO ePaper Display Board 上的连接器对齐,然后固定锁扣以确保牢固连接。
FPC 电缆的金属面应朝上,否则不会显示任何内容。
请按照下面的安装教程操作,很多人都搞错了。

步骤 2. 连接电池
将电池电缆连接到驱动板上的 JST 连接器,确保极性正确(红线接 +,黑线接 -)。

步骤 3. 外壳组装(可选)
请注意屏幕的柔性电缆非常脆弱。操作时要小心。如果损坏,整个屏幕将停止工作。
从资源部分打印开源外壳部件并在内部组装组件。

首先,组装驱动板和电池。
测试 TRMNL 套件是否工作正常。
将屏幕插入外壳并使 FPC 能够伸出。
连接 FPC 延长电缆并组装整个外壳。
L 形外壳非常相似。
如果您的 TRMNL 套件距离路由器很远,您可以将天线移到外壳外面。这样会有更好的性能。
步骤 1. 安装 ESPHome
如果您已经安装了 ESPHome,可以跳过此步骤。
转到 Settings -> Add-ons -> ADD-ON STORE


搜索 ESPHome 并点击它。点击 INSTALL 和 START。
如果您在附加组件商店中找不到 ESPHome,请确保您使用的是支持附加组件的 Home Assistant 安装(如 Home Assistant OS 或监督安装)。对于其他安装类型(如 Home Assistant Container),您可能需要使用 Docker 独立运行 ESPHome Device Builder。有关更多详细信息,请参阅 官方 ESPHome 文档。

然后,ESPHome Builder 将出现在侧边栏中。

步骤 2. 添加新设备
转到 ESPHome 并点击 NEW DEVICE。

为设备起一个您喜欢的名称,选择 ESP32-S3 作为芯片类型,然后点击 SKIP。



创建新设备后,点击 EDIT。

在默认生成的代码中,esp32 的框架可能是 esp-idf
,我们需要将其更改为 arduino
。

步骤 3. 安装固件
这是一个非常基本的示例,将在显示屏上显示"Hello World!"。
主要目的是向您展示将固件安装到设备的不同方法。
现在您可以复制下面的代码并将其粘贴到 captive_portal
之后,如下所示。
# define font to display words
font:
- file: "gfonts://Inter@700"
id: font1
size: 24
# define SPI interface
spi:
clk_pin: GPIO7
mosi_pin: GPIO9
display:
- platform: waveshare_epaper
model: 7.50inv2
cs_pin: GPIO44
dc_pin: GPIO10
reset_pin: GPIO38
busy_pin:
number: GPIO4
inverted: true
update_interval: 30s
lambda: |-
it.print(0, 0, id(font1), "Hello World!");

点击 INSTALL 将代码安装到设备,您将看到以下图像。
- Install through browser
- Install through host
- Install through Wi-Fi
如果您的 Home Assistant 主机(树莓派/Green/Yellow 等)距离您很远,我们建议使用此方法。您可以使用手边的计算机进行安装。
首先,您需要点击 Manual download 下载编译好的固件。

打开这个网站,我们将在这里上传固件到电子纸面板。

返回 ESPHome 下载固件。

选择 Factory 格式。

使用 USB 线缆将电子纸面板连接到您的计算机并点击 CONNECT。

选择 usbmodemxxx(Windows 是 COMxxx)并点击连接。遇到问题?点击这里。

点击 INSTALL 并选择您刚刚下载的固件。

稍等片刻,您将在显示屏上看到"Hello world!"~


如果您的 Home Assistant 主机(树莓派/Green/Yellow 等)就在附近,我们建议使用此方法,因为它更简单。
在将代码安装到设备之前,您需要使用 USB 线缆将此设备连接到运行 Home Assistant 的树莓派或 HA Green(Yellow)等。
按照图像中的选项点击以将代码安装到设备。设备在深度睡眠模式下找不到端口?


稍等片刻,您将看到如下图所示的反馈。这意味着代码运行成功。


这是最简单的方法,但前提是在第一次安装程序时,您应该首先使用左侧的方法将程序上传到电子纸面板。之后,您可以通过 wifi 上传。另外,请确保您的 YAML 配置包含正确配置的 ota
和 api
部分以及有效的加密密钥,以便此方法正常工作。
通过这种方式,您不需要将电子纸面板连接到任何设备,只需确保它在线即可。
点击选项,然后固件将自动安装到电子纸面板。

稍等片刻,您将看到如下图所示的反馈。如果失败,可能是由于信号较弱。请将设备移近您的路由器。遇到问题?点击这里。


基本用法
1. 显示形状
此示例将在显示屏上显示形状。
您可以复制下面的代码并将其粘贴到 captive_portal 部分,如下图所示。
spi:
clk_pin: GPIO7
mosi_pin: GPIO9
display:
- platform: waveshare_epaper
model: 7.50inv2
cs_pin: GPIO44
dc_pin: GPIO10
reset_pin: GPIO38
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);
当您看到如下图所示的反馈时,表示代码运行成功。
您也可以点击这里查看更多用法。

2. 在 HA 中显示信息
此示例将在显示屏上显示 HA 中的信息。
首先,您需要将此设备添加到 HA。否则,您无法从 HA 获取信息。
如果 HA 没有显示设备,您应该先运行上面的演示。运行上面的演示后,您可以在 HA 中看到设备。


然后,点击 SUBMIT 和 FINISH。


安装 ESPHome 并添加新设备后,您可以复制下面的代码并将其粘贴到 captive_portal
之后,如下所示。
# 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: GPIO7
mosi_pin: GPIO9
display:
- platform: waveshare_epaper
model: 7.50inv2
cs_pin: GPIO44
dc_pin: GPIO10
reset_pin: GPIO38
busy_pin:
number: GPIO4
inverted: true
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);
将这些代码安装到您的设备上。

代码的功能是从 HA 获取天气、温度和气压信息并在显示屏上显示。

如果您发现您的 Home Assistant 没有天气相关组件,您可以从集成中下载一个名为 Open-Meteo 的集成。

当您看到如下图所示的反馈时,说明代码运行成功。


3. 显示图标
此示例将在显示屏上显示图标。
首先,我们需要安装一个文件编辑器插件。搜索 Studio Code Server 并点击它。点击 INSTALL 和 START。


然后,创建一个名为 fonts 的新文件夹,下载此文件并将其放入 fonts 文件夹。

您可以复制下面的代码并将其粘贴到 captive_portal
之后,如下所示。
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: GPIO7
mosi_pin: GPIO9
display:
- platform: waveshare_epaper
model: 7.50inv2
cs_pin: GPIO44
dc_pin: GPIO10
reset_pin: GPIO38
busy_pin:
number: GPIO4
inverted: true
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");
当您看到如下图所示的反馈时,说明代码运行成功。

如果您想使用其他图标,可以点击下面的按钮探索更多。
选择您想要的图标。

复制代码并将其粘贴到 captive_portal 部分,如下图所示。


4. 显示图像
此示例将在显示屏上显示您喜欢的任何图像。
与前面的示例一样,我们需要安装 Studio Code Server 并创建一个名为 image 的新文件夹来保存图像。
然后将图像放入 image 文件夹。您可以点击下面的按钮下载一张图像来试试。

您可以复制下面的代码并将其粘贴到 captive_portal
之后,如下所示。
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: GPIO7
mosi_pin: GPIO9
display:
- platform: waveshare_epaper
model: 7.50inv2
cs_pin: GPIO44
dc_pin: GPIO10
reset_pin: GPIO38
busy_pin:
number: GPIO4
inverted: true
update_interval: 30s
lambda: |-
it.image(0, 0, id(myImage));
当您看到如下图所示的反馈时,说明代码运行成功。

演示 1. 将 Home Assistant 仪表板截图
此示例将在显示屏上显示 HA 的截图。
首先,您需要安装一个截图插件 Puppet,点击此处安装。

请注意版本应该高于或等于 1.11.4。安装后,转到 Configuration page。我们需要为此插件创建一个 access_token。

请参阅下一步创建令牌并粘贴到此处。

转到 Security page 底部并创建一个令牌,然后复制并粘贴到 Puppet 插件中。

记得重启 Puppet 插件。

启动插件将在端口 10000 上启动一个新服务器。您请求的任何路径都将返回该页面的截图。您需要指定所需的视口大小。
例如,要获取默认仪表板的 1000px x 1000px 截图,请获取:
# http://192.168.1.191:10000/lovelace/0?viewport=1000x1000(My address)
http://homeassistant.local:10000/lovelace/0?viewport=1000x1000
要为 E Ink® 显示屏减少调色板,您可以添加 eink 参数。该值表示要使用的颜色数量(包括黑色)。例如,对于 2 色 E Ink® 显示屏:
http://homeassistant.local:10000/lovelace/0?viewport=1000x1000&eink=2
如果您使用 eink=2,您还可以通过添加 invert 参数来反转颜色:
http://homeassistant.local:10000/lovelace/0?viewport=1000x1000&eink=2&invert
此外,您还可以截取其他页面,例如 HA 中的 To-do lists 页面:
http://192.168.1.191:10000/todo?viewport=800x480&eink=2&invert
您可以在浏览器中输入此链接来查看截图效果。

您可以复制下面的代码并将其粘贴到 captive_portal
之后,如下所示。
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: GPIO7
mosi_pin: GPIO9
display:
- platform: waveshare_epaper
id: main_display
model: 7.50inv2
cs_pin: GPIO44
dc_pin: GPIO10
reset_pin: GPIO38
busy_pin:
number: GPIO4
inverted: true
update_interval: never
lambda: |-
it.image(0, 0, id(dashboard_image));
当您看到如下图所示的反馈时,说明代码运行成功。

演示 2. 深度睡眠模式
在深度睡眠模式下,您无法直接向设备上传代码。您需要进入下载模式。点击此处跳转到 Q3。
此示例将展示如何使用深度睡眠模式来节省电力。每 6 小时更新一次信息。
您可以复制下面的代码并将其粘贴到 captive_portal
之后,如下所示。
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: GPIO7
mosi_pin: GPIO9
display:
- platform: waveshare_epaper
model: 7.50inv2
cs_pin: GPIO44
dc_pin: GPIO10
reset_pin: GPIO38
busy_pin:
number: GPIO4
inverted: true
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));
您将看到一个计数器。每次唤醒时它都会增加一。

演示 3. 综合示例
为了让您更好地理解,我们强烈建议您首先运行上面的基本用法。
此示例演示了 TRMNL 7.5 英寸电子纸 DIY 套件的综合 ESPHome 配置。YAML 代码集成了多个功能,创建了一个与 Home Assistant 无缝协作的智能交互式显示面板。
目的和功能:
-
该配置使设备能够连接到 Wi-Fi 和 Home Assistant,支持 API 和 OTA 更新以便于管理。
-
它设置电子纸显示屏在两个可切换页面上显示不同类型的信息,由物理按钮控制。
-
设备读取电池电压,计算电池百分比,并显示相应的电池图标和数值。
-
天气状况和温度从 Home Assistant 获取,并显示相应的图标和单位。
-
当前时间和日期也会显示,与 Home Assistant 同步。
此示例展示了如何结合传感器读数、Home Assistant 数据和用户输入,使用 ESPHome 和 TRMNL 7.5 英寸电子纸套件构建功能丰富的常亮智能显示屏。
点击此处预览完整代码
esphome:
name: obdy
friendly_name: obdy
on_boot:
priority: 600
then:
- output.turn_on: bsp_battery_enable
- delay: 200ms
- component.update: battery_voltage
- component.update: battery_level
esp32:
board: esp32-s3-devkitc-1
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "j0V30kuJ6Zdij9SU6Ee+7ruwid+7SQOxtinjld2PRc0="
ota:
- platform: esphome
password: "db786195ae6f9748f5b57ea9bd1d4161"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Obdy Fallback Hotspot"
password: "IOfapF7hXq55"
captive_portal:
# Deep-sleep, wake by GPIO4
# deep_sleep:
# id: deep_sleep_1
# run_duration: 1min
# sleep_duration: 60min
# wakeup_pin: GPIO4
# wakeup_pin_mode: INVERT_WAKEUP
spi:
clk_pin: GPIO7
mosi_pin: GPIO9
# Fonts
font:
- file: "gfonts://Inter@700"
id: small_font
size: 24
- file: "gfonts://Inter@700"
id: mid_font
size: 36
- file: "gfonts://Inter@700"
id: big_font
size: 180
- file: "gfonts://Inter@700"
id: time_font
size: 96 # for the big time display
- file: 'fonts/materialdesignicons-webfont.ttf'
id: font_bat_icon
size: 24
glyphs:
- "\U000F007A" # mdi-battery-10
- "\U000F007B" # mdi-battery-20
- "\U000F007C" # mdi-battery-30
- "\U000F007D" # mdi-battery-40
- "\U000F007E" # mdi-battery-50
- "\U000F007F" # mdi-battery-60
- "\U000F0080" # mdi-battery-70
- "\U000F0081" # mdi-battery-80
- "\U000F0082" # mdi-battery-90
- "\U000F0079" # mdi-battery
- file: "fonts/materialdesignicons-webfont.ttf" # <-- 替换成你的字体文件路径
id: weather_icon_font
size: 100
glyphs:
- "\U000F0599" # weather-sunny
- "\U000F0595" # weather-partly-cloudy
- "\U000F0F2F" # weather-cloudy
- "\U000F0597" # weather-rainy
- "\U000F0598" # weather-snowy
- "\U000F059B" # weather-windy
- "\U000F0594" # weather-fog
- "\U000F0596" # weather-lightning
globals:
- id: page_index
type: int
restore_value: true
initial_value: '0'
- id: battery_glyph
type: std::string
restore_value: no
initial_value: "\"\\U000F0079\"" # default full battery
sensor:
- platform: adc
pin: GPIO1
name: "Battery Voltage"
id: battery_voltage
update_interval: 60s
attenuation: 12db
filters:
- multiply: 2.0
- platform: template
name: "Battery Level"
id: battery_level
unit_of_measurement: "%"
icon: "mdi:battery"
device_class: battery
state_class: measurement
lambda: 'return id(battery_voltage).state;'
update_interval: 60s
on_value:
then:
- lambda: |-
int pct = int(x);
if (pct <= 10) id(battery_glyph) = "\U000F007A";
else if (pct <= 20) id(battery_glyph) = "\U000F007B";
else if (pct <= 30) id(battery_glyph) = "\U000F007C";
else if (pct <= 40) id(battery_glyph) = "\U000F007D";
else if (pct <= 50) id(battery_glyph) = "\U000F007E";
else if (pct <= 60) id(battery_glyph) = "\U000F007F";
else if (pct <= 70) id(battery_glyph) = "\U000F0080";
else if (pct <= 80) id(battery_glyph) = "\U000F0081";
else if (pct <= 90) id(battery_glyph) = "\U000F0082";
else id(battery_glyph) = "\U000F0079";
filters:
- calibrate_linear:
- 4.15 -> 100.0
- 3.96 -> 90.0
- 3.91 -> 80.0
- 3.85 -> 70.0
- 3.80 -> 60.0
- 3.75 -> 50.0
- 3.68 -> 40.0
- 3.58 -> 30.0
- 3.49 -> 20.0
- 3.41 -> 10.0
- 3.30 -> 5.0
- 3.27 -> 0.0
- clamp:
min_value: 0
max_value: 100
output:
- platform: gpio
pin: GPIO6
id: bsp_battery_enable
binary_sensor:
- platform: gpio # Next page KEY1
pin:
number: GPIO2
mode: INPUT_PULLUP
inverted: true
id: key1
name: "Key1"
on_press:
then:
- lambda: |-
id(page_index) = (id(page_index) + 1) % 2;
id(epaper_display).update();
- platform: gpio # Prev page KEY2
pin:
number: GPIO3
mode: INPUT_PULLUP
inverted: true
id: key2
name: "Key2"
on_press:
then:
- lambda: |-
id(page_index) = (id(page_index) - 1 + 2) % 2;
id(epaper_display).update();
# - platform: gpio
# pin:
# number: GPIO5 # KEY3
# mode: INPUT_PULLUP
# inverted: true
# id: key2
# name: "Key2"
# on_press:
# then:
# Home Assistant time
time:
- platform: homeassistant
id: ha_time
text_sensor:
- platform: homeassistant
entity_id: weather.home
id: myWeather
- platform: homeassistant
entity_id: weather.home
id: temp
attribute: "temperature"
display:
- platform: waveshare_epaper
id: epaper_display
model: 7.50inv2
cs_pin: GPIO44
dc_pin: GPIO10
reset_pin: GPIO38
busy_pin:
number: GPIO4
inverted: true
update_interval: never
lambda: |-
// ---------- PAGE 0 ----------
if (id(page_index) == 0) {
// Screen dimension constants for easy adjustment
const int scr_w = 800;
const int scr_h = 480;
const int center_x = scr_w / 2; // Center X-coordinate of the screen (400)
// --- Top-right: Battery Info ---
// Display the battery icon using an icon font
it.printf(scr_w - 130, 13, id(font_bat_icon), "%s", id(battery_glyph).c_str());
// Display the battery percentage text
it.printf(scr_w - 100, 10, id(small_font), "%.0f%%", id(battery_level).state);
// --- Draw the vertical separator line ---
// Draw a vertical line in the middle to separate left and right areas
it.filled_rectangle(center_x, 100, 2, 280);
// ==================================================
// LEFT AREA: WEATHER INFO
// ==================================================
// Calculate the center X-coordinate of the left area for alignment
const int left_center_x = center_x / 2; // 200
// 1. Display the title "Weather" at the top of the left area
it.printf(left_center_x, 110, id(mid_font), TextAlign::TOP_CENTER, "Weather");
// 2. Get the weather condition and select the corresponding icon
std::string weather_condition = id(myWeather).state;
std::string weather_icon = "\U000F0599"; // Default icon (sunny), as a fallback for unknown states
if (weather_condition == "partlycloudy") {
weather_icon = "\U000F0595"; // weather-partly-cloudy
} else if (weather_condition == "cloudy") {
weather_icon = "\U000F0F2F"; // weather-cloudy
} else if (weather_condition == "rainy") {
weather_icon = "\U000F0597"; // weather-rainy
} else if (weather_condition == "snowy") {
weather_icon = "\U000F0598"; // weather-snowy
} else if (weather_condition == "windy") {
weather_icon = "\U000F059B"; // weather-windy
} else if (weather_condition == "fog") {
weather_icon = "\U000F0594"; // weather-fog
} else if (weather_condition == "lightning") {
weather_icon = "\U000F0596"; // weather-lightning
}
// Display the weather icon in the center of the left area
it.printf(left_center_x, 240, id(weather_icon_font), TextAlign::CENTER, "%s", weather_icon.c_str());
// 3. Display the weather condition text below the icon
it.printf(left_center_x, 400, id(mid_font), TextAlign::BOTTOM_CENTER, "%s", weather_condition.c_str());
// ==================================================
// RIGHT AREA: TEMPERATURE INFO
// ==================================================
// Calculate the center X-coordinate of the right area for alignment
const int right_center_x = center_x + (center_x / 2); // 600
// 1. Display the title "Temperature" at the top of the right area
it.printf(right_center_x, 110, id(mid_font), TextAlign::TOP_CENTER, "Temperature");
// 3. Display the temperature reading below the icon, with one decimal place
float temp_c = stof(id(temp).state);
double temp_f = temp_c * 9.0 / 5.0 + 32.0;
it.printf(right_center_x, 250, id(mid_font), TextAlign::CENTER, "%.0f°F", temp_f);
it.printf(right_center_x, 380, id(mid_font), TextAlign::CENTER, "%.1f°C", temp_c);
}
// ---------- PAGE 1 ----------
else{
// Battery top-right
it.printf(670, 13, id(font_bat_icon), "%s", id(battery_glyph).c_str());
it.printf(700, 10, id(small_font), "%.0f%%", id(battery_level).state);
auto now = id(ha_time).now();
struct tm timeinfo = now.to_c_tm();
// centering time HH:MM
char timeStr[6];
strftime(timeStr, sizeof(timeStr), "%H:%M", &timeinfo);
it.printf(400, 180, id(time_font), TextAlign::CENTER, timeStr);
// Date: Day of week
const char *weekday[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
const char *wday = weekday[timeinfo.tm_wday];
// Date: month - day
char dateStr[12];
strftime(dateStr, sizeof(dateStr), "%b %d", &timeinfo); // e.g. Jun 15
// Day of the week + date below the time
it.printf(400, 280, id(mid_font), TextAlign::CENTER, "%s, %s", wday, dateStr);
}
当您看到如下图所示的反馈时,说明代码运行成功。

常见问题
Q1: 为什么没有数据?
在这种情况下,您应该转到 Settings -> Devices & Services -> Integrations 来重新配置设备。没有找到您的电子纸面板?尝试重启 HA。

Q2: 为什么我无法在 Home Assistant 中获取这些数据?
在这种情况下,您应该转到 Settings -> Devices & Services -> Integrations 来添加您的设备到 HA。

Q3: 当设备处于深度睡眠模式时,如何上传新程序?


当设备处于深度睡眠模式时,您无法直接上传新程序。
-
首先,确保设备已开启。然后,按住位于 XIAO ESP32-S3 Plus 上 USB-C 端口旁边的 Boot 按钮。
-
在按住 Boot 按钮的同时,按一次 Reset 按钮,然后松开 Boot 按钮。
-
之后,关闭电池开关并拔掉电源线。
-
最后,重新插入电缆并上传新程序。
Q4: TRMNL 7.5inch(OG) DIY Kit 无法连接到您的计算机?

尝试多次拔插,或者根据提示安装驱动程序。
Q5: Wi-Fi 上传程序失败?

在这种情况下,您的电子纸面板处于离线状态或深度睡眠模式。请让它上线或唤醒它。
技术支持与产品讨论
感谢您选择我们的产品!我们在这里为您提供不同的支持,以确保您使用我们产品的体验尽可能顺畅。我们提供多种沟通渠道,以满足不同的偏好和需求。