Hive Helper - Home Assistant epaper display
In addition to the PCB and its associated parts you'll need to source the following:
- Xiao ESP32C3 (https://www.seeedstudio.com/Seeed-XIAO-ESP32C3-p-5431.html)
- WeAct 2.9" epaper B&W display (https://www.aliexpress.us/item/3256804458201128.html)
- Heat-set inserts (https://www.adafruit.com/product/4255)
- 4x 20mm m3 screws
Steps for getting started can be seen on the associated hackster.io project page for this project: https://www.hackster.io/timo614/hive-helper-xiao-esp32c3-epaper-home-assistant-display-6583fc
template:
- trigger:
- platform: time_pattern
hours: /1
action:
- service: weather.get_forecasts
target:
entity_id: weather.forecast_home
data:
type: daily
response_variable: daily
sensor:
- name: Daily Weather
unique_id: weather_forecast_daily
state: "{{ daily['weather.forecast_home'].forecast[0]['condition'] }}"
attributes:
today_condition: "{{ daily['weather.forecast_home'].forecast[0]['condition'] }}"
today_humidity: "{{ daily['weather.forecast_home'].forecast[0]['humidity'] }}"
today_temperature: "{{ daily['weather.forecast_home'].forecast[0]['temperature'] }}"
today_precipitation: "{{ daily['weather.forecast_home'].forecast[0]['precipitation'] }}"
day1_condition: "{{ daily['weather.forecast_home'].forecast[1]['condition'] }}"
day1_humidity: "{{ daily['weather.forecast_home'].forecast[1]['humidity'] }}"
day1_temperature: "{{ daily['weather.forecast_home'].forecast[1]['temperature'] }}"
day1_precipitation: "{{ daily['weather.forecast_home'].forecast[1]['precipitation'] }}"
day2_condition: "{{ daily['weather.forecast_home'].forecast[2]['condition'] }}"
day2_humidity: "{{ daily['weather.forecast_home'].forecast[2]['humidity'] }}"
day2_temperature: "{{ daily['weather.forecast_home'].forecast[2]['temperature'] }}"
day2_precipitation: "{{ daily['weather.forecast_home'].forecast[2]['precipitation'] }}"
day3_condition: "{{ daily['weather.forecast_home'].forecast[3]['condition'] }}"
day3_humidity: "{{ daily['weather.forecast_home'].forecast[3]['humidity'] }}"
day3_temperature: "{{ daily['weather.forecast_home'].forecast[3]['temperature'] }}"
day3_precipitation: "{{ daily['weather.forecast_home'].forecast[3]['precipitation'] }}"
day4_condition: "{{ daily['weather.forecast_home'].forecast[4]['condition'] }}"
day4_humidity: "{{ daily['weather.forecast_home'].forecast[4]['humidity'] }}"
day4_temperature: "{{ daily['weather.forecast_home'].forecast[4]['temperature'] }}"
day4_precipitation: "{{ daily['weather.forecast_home'].forecast[4]['precipitation'] }}"
day5_condition: "{{ daily['weather.forecast_home'].forecast[5]['condition'] }}"
day5_humidity: "{{ daily['weather.forecast_home'].forecast[5]['humidity'] }}"
day5_temperature: "{{ daily['weather.forecast_home'].forecast[5]['temperature'] }}"
day5_precipitation: "{{ daily['weather.forecast_home'].forecast[5]['precipitation'] }}"
esphome:
name: hive-helper
friendly_name: Hive Helper
esp32:
board: esp32-c3-devkitm-1
framework:
type: arduino
external_components:
- source: github://wifwucite/esphome-grove-multi-gas-v2
# Enable logging
logger:
i2c:
sda: 6
scl: 7
scan: true
# Enable Home Assistant API
api:
encryption:
key: !secret hive_helper_api_key
ota:
- platform: esphome
password: !secret hive_helper_ota
binary_sensor:
- platform: gpio
pin:
number: 20
inverted: true
name: "Flame Alert"
- platform: gpio
pin: 9
name: "Hive Button"
id: hive_button
on_press:
then:
- display.page.show_next: my_display
- component.update: my_display
text_sensor:
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: today_condition
id: weather_condition_now
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: day1_condition
id: weather_condition_day1
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: day2_condition
id: weather_condition_day2
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: day3_condition
id: weather_condition_day3
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: day4_condition
id: weather_condition_day4
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: day5_condition
id: weather_condition_day5
sensor:
- platform: grove_multigas_v2
NO2:
name: "NO2"
id: no2_sensor
C2H5OH:
name: "EtOH"
id: etoh_sensor
VOC:
name: "VOC"
id: voc_sensor
CO:
name: "CO"
id: co_sensor
update_interval: 10s
- platform: aht10
variant: AHT20
temperature:
id: aht20_temperature
name: Hive Temperature
filters:
- offset: -2.0
humidity:
id: aht20_humidity
name: Hive Humidity
update_interval: 60s
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: today_temperature
id: weather_temperature_now
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: today_humidity
id: weather_humidity_now
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: today_precipitation
id: weather_precipitation_now
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: day1_temperature
id: weather_temperature_day1
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: day1_humidity
id: weather_humidity_day1
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: day1_precipitation
id: weather_precipitation_day1
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: day2_temperature
id: weather_temperature_day2
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: day2_humidity
id: weather_humidity_day2
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: day2_precipitation
id: weather_precipitation_day2
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: day3_temperature
id: weather_temperature_day3
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: day3_humidity
id: weather_humidity_day3
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: day3_precipitation
id: weather_precipitation_day3
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: day4_temperature
id: weather_temperature_day4
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: day4_humidity
id: weather_humidity_day4
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: day4_precipitation
id: weather_precipitation_day4
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: day5_temperature
id: weather_temperature_day5
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: day5_humidity
id: weather_humidity_day5
- platform: homeassistant
entity_id: sensor.daily_weather
attribute: day5_precipitation
id: weather_precipitation_day5
font:
- file: "fonts/BebasNeue-Regular.ttf"
id: font_time
size: 20
- file: "fonts/BebasNeue-Regular.ttf"
id: font_mini_metric
size: 18
- file: "fonts/BebasNeue-Regular.ttf"
id: font_metric
size: 30
# Include Material Design Icons font
# Thanks to https://community.home-assistant.io/t/display-materialdesign-icons-on-esphome-attached-to-screen/199790/16
# Thanks to https://community.home-assistant.io/t/use-esphome-with-e-ink-displays-to-blend-in-with-your-home-decor/435428 for reference
- file: 'fonts/materialdesignicons-webfont.ttf'
id: font_mdi
size: 26
glyphs: &mdi-weather-glyphs
- "\U000F0590" # mdi-weather-cloudy
- "\U000F0F2F" # mdi-weather-cloudy-alert
- "\U000F0E6E" # mdi-weather-cloudy-arrow-right
- "\U000F0591" # mdi-weather-fog
- "\U000F0592" # mdi-weather-hail
- "\U000F0F30" # mdi-weather-hazy
- "\U000F0898" # mdi-weather-hurricane
- "\U000F0593" # mdi-weather-lightning
- "\U000F067E" # mdi-weather-lightning-rainy
- "\U000F0594" # mdi-weather-night
- "\U000F0F31" # mdi-weather-night-partly-cloudy
- "\U000F0595" # mdi-weather-partly-cloudy
- "\U000F0F32" # mdi-weather-partly-lightning
- "\U000F0F33" # mdi-weather-partly-rainy
- "\U000F0F34" # mdi-weather-partly-snowy
- "\U000F0F35" # mdi-weather-partly-snowy-rainy
- "\U000F0596" # mdi-weather-pouring
- "\U000F0597" # mdi-weather-rainy
- "\U000F0598" # mdi-weather-snowy
- "\U000F0F36" # mdi-weather-snowy-heavy
- "\U000F067F" # mdi-weather-snowy-rainy
- "\U000F0599" # mdi-weather-sunny
- "\U000F0F37" # mdi-weather-sunny-alert
- "\U000F14E4" # mdi-weather-sunny-off
- "\U000F059A" # mdi-weather-sunset
- "\U000F059B" # mdi-weather-sunset-down
- "\U000F059C" # mdi-weather-sunset-up
- "\U000F0F38" # mdi-weather-tornado
- "\U000F059D" # mdi-weather-windy
- "\U000F059E" # mdi-weather-windy-variant
- file: 'fonts/materialdesignicons-webfont.ttf'
id: font_mdi_large
size: 35
glyphs: *mdi-weather-glyphs
spi:
clk_pin: 8
mosi_pin: 10
time:
- platform: homeassistant
id: homeassistant_time
display:
- platform: waveshare_epaper
model: 2.90inV2
cs_pin: 5
dc_pin: 4
busy_pin: 2
reset_pin: 3
rotation: 270
full_update_every: 1
update_interval: 60s
id: my_display
pages:
- id: page1
lambda: |-
auto time_now = id(homeassistant_time).now();
auto weekday_1 = time_now;
weekday_1.increment_day();
auto weekday_2 = weekday_1;
weekday_2.increment_day();
auto weekday_3 = weekday_2;
weekday_3.increment_day();
auto weekday_4 = weekday_3;
weekday_4.increment_day();
auto weekday_5 = weekday_4;
weekday_5.increment_day();
std::map<std::string, std::string> weather_icon_map
{
{"cloudy", "\U000F0590"},
{"cloudy-alert", "\U000F0F2F"},
{"cloudy-arrow-right", "\U000F0E6E"},
{"fog", "\U000F0591"},
{"hail", "\U000F0592"},
{"hazy", "\U000F0F30"},
{"hurricane", "\U000F0898"},
{"lightning", "\U000F0593"},
{"lightning-rainy", "\U000F067E"},
{"night", "\U000F0594"},
{"night-partly-cloudy", "\U000F0F31"},
{"partlycloudy", "\U000F0595"},
{"partly-lightning", "\U000F0F32"},
{"partly-rainy", "\U000F0F33"},
{"partly-snowy", "\U000F0F34"},
{"partly-snowy-rainy", "\U000F0F35"},
{"pouring", "\U000F0596"},
{"rainy", "\U000F0597"},
{"snowy", "\U000F0598"},
{"snowy-heavy", "\U000F0F36"},
{"snowy-rainy", "\U000F067F"},
{"sunny", "\U000F0599"},
{"sunny-alert", "\U000F0F37"},
{"sunny-off", "\U000F14E4"},
{"sunset", "\U000F059A"},
{"sunset-down", "\U000F059B"},
{"sunset-up", "\U000F059C"},
{"tornado", "\U000F0F38"},
{"windy", "\U000F059D"},
{"windy-variant", "\U000F059E"},
};
it.strftime(5, 10, id(font_time), "%a %B %d, %Y - %I:%M %p", time_now);
it.printf(240, 10, id(font_mdi_large), "%s", weather_icon_map[id(weather_condition_now).state.c_str()].c_str());
it.printf(230, 50, id(font_metric), "%.1f°", id(weather_temperature_now).state);
it.printf(230, 90, id(font_metric), "%.1f%%", id(weather_humidity_now).state);
it.strftime(8, 42, id(font_mini_metric), "%a", weekday_1);
it.strftime(48, 42, id(font_mini_metric), "%a", weekday_2);
it.strftime(88, 42, id(font_mini_metric), "%a", weekday_3);
it.strftime(128, 42, id(font_mini_metric), "%a", weekday_4);
it.strftime(168, 42, id(font_mini_metric), "%a", weekday_5);
it.printf(5, 60, id(font_mdi), "%s", weather_icon_map[id(weather_condition_day1).state.c_str()].c_str());
it.printf(45, 60, id(font_mdi), "%s", weather_icon_map[id(weather_condition_day2).state.c_str()].c_str());
it.printf(85, 60, id(font_mdi), "%s", weather_icon_map[id(weather_condition_day3).state.c_str()].c_str());
it.printf(125, 60, id(font_mdi), "%s", weather_icon_map[id(weather_condition_day4).state.c_str()].c_str());
it.printf(165, 60, id(font_mdi), "%s", weather_icon_map[id(weather_condition_day5).state.c_str()].c_str());
it.printf(6, 85, id(font_mini_metric), "%.1f°", id(weather_temperature_day1).state);
it.printf(46, 85, id(font_mini_metric), "%.1f°", id(weather_temperature_day2).state);
it.printf(86, 85, id(font_mini_metric), "%.1f°", id(weather_temperature_day3).state);
it.printf(126, 85, id(font_mini_metric), "%.1f°", id(weather_temperature_day4).state);
it.printf(166, 85, id(font_mini_metric), "%.1f°", id(weather_temperature_day5).state);
it.printf(6, 105, id(font_mini_metric), "%.1f%%", id(weather_humidity_day1).state);
it.printf(46, 105, id(font_mini_metric), "%.1f%%", id(weather_humidity_day2).state);
it.printf(86, 105, id(font_mini_metric), "%.1f%%", id(weather_humidity_day3).state);
it.printf(126, 105, id(font_mini_metric), "%.1f%%", id(weather_humidity_day4).state);
it.printf(166, 105, id(font_mini_metric), "%.1f%%", id(weather_humidity_day5).state);
- id: page2
lambda: |-
auto time_now = id(homeassistant_time).now();
it.strftime(5, 10, id(font_time), "%a %B %d, %Y - %I:%M %p", time_now);
it.printf(30, 45, id(font_mini_metric), "EtOH");
it.printf(20, 60, id(font_mini_metric), "%.1f ppm", id(etoh_sensor).state);
it.printf(30, 85, id(font_mini_metric), "NO2");
it.printf(20, 105, id(font_mini_metric), "%.1f ppm", id(no2_sensor).state);
it.printf(90, 45, id(font_mini_metric), "VOC");
it.printf(80, 60, id(font_mini_metric), "%.1f ppm", id(voc_sensor).state);
it.printf(90, 85, id(font_mini_metric), "CO");
it.printf(80, 105, id(font_mini_metric), "%.1f ppm", id(co_sensor).state);
it.printf(230, 10, id(font_metric), "ROOM");
it.printf(230, 50, id(font_metric), "%.1f°", id(aht20_temperature).state * 1.8 + 32);
it.printf(230, 90, id(font_metric), "%.1f%%", id(aht20_humidity).state);
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
fast_connect: true
use_address: hive-helper.wild
captive_portal:
Hive Helper - Home Assistant epaper display
Project images are for reference only. Actual production is based on the manufacturing files on the project page.
Please review the designer's notes (e.g., PCB thickness) and select the appropriate options.
PCBWay is not responsible
for issues caused by unsuitable parameter selections.
For more important ordering information, please refer to
Read More
Raspberry Pi 5 7 Inch Touch Screen IPS 1024x600 HD LCD HDMI-compatible Display for RPI 4B 3B+ OPI 5 AIDA64 PC Secondary Screen(Without Speaker)
BUY NOW- Comments(2)
- Likes(5)
-
Salvatore Esposito
May 24,2025
-
Jo Jonas
Nov 04,2024
-
Johannes Klamann
Sep 16,2024
-
Engineer
Aug 22,2024
-
Timothy Lovett
Aug 08,2024
- 0 USER VOTES
- YOUR VOTE 0.00 0.00
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
More by Timothy Lovett
-
Hive Helper - Home Assistant epaper display
In addition to the PCB and its associated parts you'll need to source the following:Xiao ESP32C3 (ht...
-
Level Up Board
A Xiao form factor board for optional level shifting with the use a jumper. I have three uses for th...
-
WLED Display Board
For this project I built out a custom PCB with 10 SK6812 mini LEDs for use with WLED. Pretty straigh...
-
Glowbug Mini
Like my Glowbug Project this PCB is designed to use WLED a firmware that works on many Espressif mic...
-
Mouse Touch Board
This board acts as a touch board with a MPR121 for use along with my mouse core board this board has...
-
Freeflow Mouse Core Board
This project utlizes a PMW3360 to act as a mouse core board. The board has two methods of connection...
-
Programmable Mist Maker - XIAO / QT PY Extension
1261 2 1 -
RadioHAT - Raspberry Pi radio development platform
1077 0 2 -
QWIIC-VL53L4CD Time-of-Flight Distance Sensor Module
1287 0 1 -
-
-
-
ARPS-2 – Arduino-Compatible Robot Project Shield for Arduino UNO
3475 0 6 -
-
A Compact Charging Breakout Board For Waveshare ESP32-C3
4124 3 8 -
AI-driven LoRa & LLM-enabled Kiosk & Food Delivery System
4503 2 2







