├── images
└── background.png
├── fonts
├── GothamRnd-Bold.ttf
├── GothamRnd-Book.ttf
└── materialdesigniconswebfont.ttf
├── eink_dashboard_sensor.yaml
├── README_zh-tw.md
├── README.md
└── eink-weather-board.yaml
/images/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xangin/eink-weather-board/HEAD/images/background.png
--------------------------------------------------------------------------------
/fonts/GothamRnd-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xangin/eink-weather-board/HEAD/fonts/GothamRnd-Bold.ttf
--------------------------------------------------------------------------------
/fonts/GothamRnd-Book.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xangin/eink-weather-board/HEAD/fonts/GothamRnd-Book.ttf
--------------------------------------------------------------------------------
/fonts/materialdesigniconswebfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xangin/eink-weather-board/HEAD/fonts/materialdesigniconswebfont.ttf
--------------------------------------------------------------------------------
/eink_dashboard_sensor.yaml:
--------------------------------------------------------------------------------
1 | ###########################################################
2 | ##
3 | ## Weather Forecast Sensors
4 | ## !!Only for HA 2023.12.0 or later
5 | ##
6 | ###########################################################
7 | template:
8 | - trigger:
9 | # update interval for the forecast
10 | # every hour at 1 min will get forecast
11 | # ex: 10:01, 11:01, 12:01 ...
12 | - platform: time_pattern
13 | hours: "/1"
14 | minutes: 1
15 | action:
16 | - service: weather.get_forecasts
17 | target:
18 | entity_id: weather.myhome #replace with your weather forecast entity id
19 | data:
20 | type: hourly #make sure your weather entity support hourly forecast
21 | response_variable: hourly
22 | sensor:
23 | - name: "eink_sensors"
24 | unique_id: eink_sensors
25 | # use forecast[0] as this hour's weather condition
26 | # replace below 'weather.myhome' with your weather forecast entity id
27 | # The today_precipitation field should be populated based on the attribute name provided by the weather forecast service.
28 | state: >
29 | {{ hourly['weather.myhome'].forecast[0].condition }}
30 | attributes:
31 | today_temperature: >
32 | {{ hourly['weather.myhome'].forecast[0].temperature | round }}°C
33 | today_humidity: >
34 | {{ hourly['weather.myhome'].forecast[0].humidity | round }}%
35 | today_precipitation: >
36 | {{ hourly['weather.myhome'].forecast[0].precipitation_probability | round }}%
37 |
38 | forecast_weekday_1: >
39 | {{ as_timestamp(hourly['weather.myhome'].forecast[1].datetime) | timestamp_custom('%I') | int }}{{ as_timestamp(hourly['weather.myhome'].forecast[1].datetime) | timestamp_custom('%p') }}
40 | forecast_condition_1: >
41 | {{ hourly['weather.myhome'].forecast[1].condition }}
42 | forecast_temperature_1: >
43 | {{ hourly['weather.myhome'].forecast[1].temperature | round }}°
44 |
45 | forecast_weekday_2: >
46 | {{ as_timestamp(hourly['weather.myhome'].forecast[2].datetime) | timestamp_custom('%I') | int }}{{ as_timestamp(hourly['weather.myhome'].forecast[2].datetime) | timestamp_custom('%p') }}
47 | forecast_condition_2: >
48 | {{ hourly['weather.myhome'].forecast[2].condition }}
49 | forecast_temperature_2: >
50 | {{ hourly['weather.myhome'].forecast[2].temperature | round }}°
51 |
52 | forecast_weekday_3: >
53 | {{ as_timestamp(hourly['weather.myhome'].forecast[3].datetime) | timestamp_custom('%I') | int }}{{ as_timestamp(hourly['weather.myhome'].forecast[3].datetime) | timestamp_custom('%p') }}
54 | forecast_condition_3: >
55 | {{ hourly['weather.myhome'].forecast[3].condition }}
56 | forecast_temperature_3: >
57 | {{ hourly['weather.myhome'].forecast[3].temperature | round }}°
58 |
59 | forecast_weekday_4: >
60 | {{ as_timestamp(hourly['weather.myhome'].forecast[4].datetime) | timestamp_custom('%I') | int }}{{ as_timestamp(hourly['weather.myhome'].forecast[4].datetime) | timestamp_custom('%p') }}
61 | forecast_condition_4: >
62 | {{ hourly['weather.myhome'].forecast[4].condition }}
63 | forecast_temperature_4: >
64 | {{ hourly['weather.myhome'].forecast[4].temperature | round }}°
65 |
66 |
--------------------------------------------------------------------------------
/README_zh-tw.md:
--------------------------------------------------------------------------------
1 | # ESPHome E-ink Weather board
2 |
3 |
4 |
5 | [English](https://github.com/xangin/eink-weather-board/blob/main/README.md) | 正體中文
6 |
7 | 感謝[Madelena](https://github.com/Madelena/esphome-weatherman-dashboard/)提供本專案硬體架構與程式碼的發想
8 |
9 | Thanks [Madelena](https://github.com/Madelena/esphome-weatherman-dashboard/) for inspired this project ideas and source code of weather data
10 |
11 | 本專案為直式的E-ink天氣預報資訊板放在玄關處,在指定的時段內每格固定,會自動更新顯示內容
12 |
13 | 另有橫式除了天氣資訊外,還能將個房間的溫濕度等資訊顯示在E-ink上: [E-ink Dashboard](https://github.com/xangin/esphome-eink-dashboard)
14 |
15 |
16 |
17 | 直式天氣資訊板顯示內容包括:
18 | - 今天日期
19 | - 當下天氣預報
20 | - 未來四小時天氣預報
21 |
22 |
23 |
24 | 以下將說明硬體架構、ESPHome yaml code與Home assistant yaml code
25 |
26 | ## Hardware 硬體架構
27 |
28 | - [微雪 7.5吋黑白墨水屏裸屏](https://detail.tmall.com/item.htm?id=606005913066) - 不帶外殼
29 | - [微雪 墨水屏裸屏 SPI驅動板 ESP32](https://detail.tmall.com/item.htm?id=605757128869) - wifi+藍牙版本(ESP32)
30 | - [IKEA RÖDALM 相框 13x18公分](https://www.ikea.com.tw/zh/products/wall-decoration/frames/rodalm-art-50550033) - 外框有木黑白三色,**注意裱框紙開孔較小,需要挖大**
31 |
32 | ## Installation 安裝方式
33 |
34 | 1. 將`/fonts`資料夾內的檔案及`e-ink-weather-board.yaml`放到HA/config/esphome的資料夾內
35 | 2. 將`eink_dashboard_sensor.yaml`放到HA/config/packages內
36 | 3. 將`/images`內的`background.png`放到HA/config/esphome/images的資料夾內
37 | 4. 將`e-ink-weather-board.yaml`及`eink_dashboard_sensor.yaml`的內容修改成自己HA裡的實體ID,**解說在下方**
38 | 5. HA檢查YAML code有無錯誤
39 | 1. 開發工具>YAML>檢查設定內容,確認左下角通知沒有出現錯誤
40 | 2. YAML 設定新載入中>模板實體
41 | 3. 開發工具>狀態>檢查`sensor.eink_sensors`有確實出現,以及內容是自己想要的
42 | 6. 在ESPhome將`e-ink-weather-board.yaml`燒錄至ESP32模組
43 | 7. 完成!
44 |
45 | ## ESPHome yaml 說明
46 |
47 | ### 在HA內手動更新面板
48 |
49 | ```YAML
50 | button:
51 | - platform: template
52 | name: '${devicename} Refresh'
53 | icon: 'mdi:update'
54 | on_press:
55 | then:
56 | - component.update: 'my_display'
57 | internal: false
58 | ```
59 |
60 |
61 | ### 將HA的時間帶進ESPHome
62 |
63 | ```YAML
64 | time:
65 | - platform: homeassistant
66 | id: ha_time
67 | ```
68 |
69 |
70 | ### 面板更新時機
71 |
72 | 請注意,此面板長時間通電會導致越刷越模糊,黑底會變成不是純黑,建議只有刷新時才將ESP32通電,或是刷新完進入Deep sleep以避免此情形發生
73 |
74 | 因為預設螢幕不會自動更新`update_interval: never`,是由HA內建自動化根據想要的間隔時間來按下更新面板按鈕
75 |
76 | 自動化流程如下:
77 |
78 | #### 1. 每隔多久時間觸發一次自動化:
79 |
80 | ```YAML
81 | trigger:
82 | - platform: time_pattern
83 | # /2 表示每2個小時,要每小時就寫 /1
84 | hours: "/2"
85 | # 1 表示在該小時的1分時執行,如06:01、08:01、10:01
86 | minutes: 1
87 | ```
88 |
89 | #### 2. 條件:
90 |
91 | 在HA設定>裝置與服務>助手>新增助手>"每日定時感測器">設定想要更新的時段,名稱填`eink_refresh_time`
92 |
93 | ```YAML
94 | condition:
95 | #在可更新的時段內才更新
96 | - condition: state
97 | entity_id: binary_sensor.eink_refresh_time
98 | state: 'on'
99 | ```
100 |
101 | #### 3. 動作:
102 |
103 | ```YAML
104 | action:
105 | #按下更新螢幕的按鈕,記得更換為自己的實體ID
106 | - service: button.press
107 | data:
108 | entity_id: button.eink_weather_board_screen_refresh
109 | ```
110 |
111 | 自動化設定完記得至開發工具>YAML>檢查設定
112 |
113 | 確定都對後在`YAML 設定新載入中`按下`自動化`重新載入自動化才會生效
114 |
115 | ## HA template sensor 說明
116 |
117 | **要先確認在已經將以下程式碼寫在`configuration.yaml`內,這樣`eink_dashboard_sensor_new.yaml`檔案放進去才會生效**
118 |
119 | 
120 |
121 | 在HA 2023.12之後,天氣預報改由呼叫service來取得未來的資訊,所以利用此template sensor將想要的資料格式化後再丟給天氣板顯示
122 |
123 | 由於預設是顯示取得每小時的預報,**請先確認目前用的天氣整合有支援小時預報 (內建的met.no有)**
124 |
125 | 以下YAML表示每小時的1分將會呼叫取得"每小時"的天氣預報服務,同時更新內容在sensor.eink_sensors裡面
126 |
127 | 要注意更新面板的時機要在更新天氣預報之後,不然都會看到前一個小時的預報
128 |
129 | ```YAML
130 |
131 | - trigger:
132 | - platform: time_pattern
133 | hours: "/1"
134 | minutes: 1
135 | action:
136 | - service: weather.get_forecasts
137 | target:
138 | entity_id: weather.myhome #replace with your weather forecast entity id
139 | data:
140 | type: hourly
141 | response_variable: hourly
142 |
143 | ```
144 |
145 | 會使用天氣預報回傳結果的第1組當作這小時的預報,並顯示第2~5組做未來每小時的預報
146 |
147 | `attributes`是將要使用的資訊從天氣預報拆分成出來,分別是:
148 | - 這小時的氣溫: `today_temperature`
149 | - 這小時的濕度: `today_humidity`
150 | - 這小時的降雨機率: `today_precipitation`
151 | - 未來四小時的時間: `forecast_weekday_1`, `forecast_weekday_2`, `forecast_weekday_3`, `forecast_weekday_4`
152 | - 未來四小時的天氣圖示: `forecast_condition_1`, `forecast_condition_2`, `forecast_condition_3`, `forecast_condition_4`
153 | - 未來四小時的氣溫: `forecast_temperature_1`, `forecast_temperature_2`, `forecast_temperature_3`, `forecast_temperature_4`
154 |
155 |
156 | ## References
157 | - https://github.com/Madelena/esphome-weatherman-dashboard/
158 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ESPHome E-ink Weather board
2 |
3 |
4 |
5 | English | [正體中文](https://github.com/xangin/eink-weather-board/blob/main/README_zh-tw.md)
6 |
7 | Thanks to [Madelena](https://github.com/Madelena/esphome-weatherman-dashboard/) for inspiring this project and providing the source code for weather data.
8 |
9 | This project is a vertical E-ink weather forecast board placed at the entrance, automatically updating and displaying content at specified intervals.
10 |
11 | There is also a horizontal version that can display temperature and humidity information for individual rooms on the E-ink: [E-ink Dashboard](https://github.com/xangin/esphome-eink-dashboard)
12 |
13 |
14 |
15 | The vertical weather board displays:
16 | - Today's date
17 | - Current weather forecast
18 | - Weather forecast for the next four hours
19 |
20 |
21 |
22 | Below are the hardware structure, ESPHome yaml code, and Home assistant yaml code.
23 |
24 | ## Hardware
25 |
26 | - [Waveshare 7.5-inch black and white E-ink screen](https://detail.tmall.com/item.htm?id=606005913066) - bare screen without casing
27 | - [Waveshare E-ink screen SPI driver board ESP32](https://detail.tmall.com/item.htm?id=605757128869) - WiFi + Bluetooth version (ESP32)
28 | - [IKEA RÖDALM Frame 13x18 cm](https://www.ikea.com.tw/zh/products/wall-decoration/frames/rodalm-art-50550033) - available in black, white, and wooden color. Note: The mat opening is small and needs to be enlarged
29 |
30 | ## Installation
31 |
32 | 1. Place the files in the `/fonts` folder and `e-ink-weather-board.yaml`in the HA/config/esphome folder.
33 | 2. Place `eink_dashboard_sensor.yaml` in the HA/config/packages folder.
34 | 3. Place `background.png` from the `/images` folder in the HA/config/esphome/images folder.
35 | 4. Modify `e-ink-weather-board.yaml` and `eink_dashboard_sensor.yaml` to match your HA entity IDs. **Instructions are below**
36 | 5. Check for YAML code errors in HA.
37 | 1. Developer Tools > YAML > Check Configuration, ensure no errors in the bottom left notification.
38 | 2. YAML Configuration Reloading > Template Entities
39 | 3. Developer Tools > States > Check `sensor.eink_sensors` to ensure it appears and contains the desired content.
40 | 6. Flash e-ink-weather-board.yaml to the ESP32 module in ESPHome.
41 | 7. Done!
42 |
43 | ## ESPHome yaml Explanation
44 |
45 | ### Manually update the panel in HA
46 |
47 | ```YAML
48 | button:
49 | - platform: template
50 | name: '${devicename} Refresh'
51 | icon: 'mdi:update'
52 | on_press:
53 | then:
54 | - component.update: 'my_display'
55 | internal: false
56 | ```
57 |
58 |
59 | ### Pass HA time to ESPHome
60 |
61 | ```YAML
62 | time:
63 | - platform: homeassistant
64 | id: ha_time
65 | ```
66 |
67 |
68 | ### Panel update timing
69 |
70 | Note: Long-term power to this panel may cause increasing blurriness. It is recommended to power the ESP32 only when refreshing or enter Deep Sleep to avoid this issue.
71 |
72 | The default screen does not automatically update `update_interval: never`. It is updated by HA automation based on the desired interval.
73 |
74 | Automation process:
75 |
76 | #### 1. Trigger automation at intervals:
77 |
78 | ```YAML
79 | trigger:
80 | - platform: time_pattern
81 | # /2 means every 2 hours, use /1 for every hour
82 | hours: "/2"
83 | # 1 means it runs at the 1st minute of the hour, like 06:01, 08:01, 10:01
84 | minutes: 1
85 | ```
86 |
87 | #### 2. Condition:
88 |
89 | Set the update period in HA > Settings > Devices & Services > Helpers > Add Helper > "Daily Timer" > Set the desired update period, name it `eink_refresh_time`.
90 |
91 | ```YAML
92 | condition:
93 | #Update only during allowed periods
94 | - condition: state
95 | entity_id: binary_sensor.eink_refresh_time
96 | state: 'on'
97 | ```
98 |
99 | #### 3. Action:
100 |
101 | ```YAML
102 | action:
103 | #Press the update button, replace with your entity ID
104 | - service: button.press
105 | data:
106 | entity_id: button.eink_weather_board_screen_refresh
107 | ```
108 |
109 | Remember to check the configuration in Developer Tools > YAML > Check Configuration.
110 |
111 | Once everything is correct, reload the automation in YAML Configuration Reloading > Automation.
112 |
113 | ## HA template sensor Explanation
114 |
115 | **Ensure the following code is written in`configuration.yaml` for `eink_dashboard_sensor_new.yaml`to take effect**
116 |
117 | 
118 |
119 | Ensure the weather integration supports hourly forecasts (built-in met.no does).
120 |
121 | The following YAML calls the "hourly" weather forecast service at 1 minute past every hour and updates sensor.eink_sensors with the content.
122 |
123 | Update the panel after updating the weather forecast to avoid seeing the previous hour's forecast.
124 |
125 | ```YAML
126 |
127 | - trigger:
128 | - platform: time_pattern
129 | hours: "/1"
130 | minutes: 1
131 | action:
132 | - service: weather.get_forecasts
133 | target:
134 | entity_id: weather.myhome #replace with your weather forecast entity id
135 | data:
136 | type: hourly
137 | response_variable: hourly
138 |
139 | ```
140 |
141 | Use the first set of the weather forecast as this hour's forecast and display the 2nd to 5th sets for the next four hours.
142 |
143 | `attributes`separates the information from the weather forecast as:
144 | - Temperature for this hour: `today_temperature`
145 | - Humidity for this hour: `today_humidity`
146 | - Precipitation probability for this hour: `today_precipitation`
147 | - Time for the next four hours: `forecast_weekday_1`, `forecast_weekday_2`, `forecast_weekday_3`, `forecast_weekday_4`
148 | - Weather icons for the next four hours: `forecast_condition_1`, `forecast_condition_2`, `forecast_condition_3`, `forecast_condition_4`
149 | - Temperature for the next four hours: `forecast_temperature_1`, `forecast_temperature_2`, `forecast_temperature_3`, `forecast_temperature_4`
150 |
151 | ## References
152 | - https://github.com/Madelena/esphome-weatherman-dashboard/
153 |
--------------------------------------------------------------------------------
/eink-weather-board.yaml:
--------------------------------------------------------------------------------
1 | substitutions:
2 | device_name: eink-weather-board
3 |
4 | esp32:
5 | board: esp32dev
6 |
7 | esphome:
8 | name: eink-weather-board
9 |
10 | # Enable logging
11 | logger:
12 |
13 | # Enable Home Assistant API
14 | api:
15 |
16 | ota:
17 | - platform: esphome
18 | password: !secret ota_password #remeber add ota_password in your secret.yaml
19 |
20 | wifi:
21 | networks:
22 | - ssid: !secret my_ap_ssid
23 | password: !secret my_ap_password
24 |
25 | # Enable fallback hotspot (captive portal) in case wifi connection fails
26 | ap:
27 | ssid: ${device_name}
28 | password: "12345678"
29 |
30 | # Include custom fonts
31 | font:
32 |
33 | - file: 'fonts/GothamRnd-Book.ttf'
34 | id: font_year
35 | size: 60
36 | glyphs:
37 | ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
38 |
39 | - file: 'fonts/GothamRnd-Book.ttf'
40 | id: font_month
41 | size: 80
42 | glyphs:
43 | ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
44 | 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
45 | 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
46 | 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
47 | 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
48 |
49 | - file: 'fonts/GothamRnd-Bold.ttf'
50 | id: font_day
51 | size: 100
52 | glyphs:
53 | ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
54 |
55 | - file: 'fonts/GothamRnd-Bold.ttf'
56 | id: font_weekday
57 | size: 70
58 | glyphs:
59 | ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
60 | 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
61 | 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
62 | 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
63 | 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', ' ']
64 |
65 | - file: 'fonts/materialdesigniconswebfont.ttf'
66 | id: icon_today
67 | size: 220
68 | glyphs: &mdi-weather-glyphs
69 | - "\U000F0590" # mdi-weather-cloudy
70 | - "\U000F0F2F" # mdi-weather-cloudy-alert
71 | - "\U000F0E6E" # mdi-weather-cloudy-arrow-right
72 | - "\U000F0593" # mdi-weather-lightning
73 | - "\U000F067E" # mdi-weather-lightning-rainy
74 | - "\U000F0594" # mdi-weather-night
75 | - "\U000F0F31" # mdi-weather-night-partly-cloudy
76 | - "\U000F0595" # mdi-weather-partly-cloudy
77 | - "\U000F0F32" # mdi-weather-partly-lightning
78 | - "\U000F0F33" # mdi-weather-partly-rainy
79 | - "\U000F0596" # mdi-weather-pouring
80 | - "\U000F0597" # mdi-weather-rainy
81 | - "\U000F0599" # mdi-weather-sunny
82 | - "\U000F0F37" # mdi-weather-sunny-alert
83 | - "\U000F14E4" # mdi-weather-sunny-off
84 | - "\U000F059A" # mdi-weather-sunset
85 | - "\U000F059B" # mdi-weather-sunset-down
86 | - "\U000F059C" # mdi-weather-sunset-up
87 | - "\U000F059D" # mdi-weather-windy
88 | - "\U000F059E" # mdi-weather-windy-variant
89 | - "\U000F0591" # mdi-weather-fog
90 | - "\U000F0592" # mdi-weather-hail
91 | - "\U000F0F30" # mdi-weather-hazy
92 |
93 | #today temp
94 | - file: 'fonts/GothamRnd-Bold.ttf'
95 | id: font_today_temp
96 | size: 70
97 | glyphs:
98 | ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '°', 'C', '%']
99 |
100 | #forecast time & temp
101 | - file: 'fonts/GothamRnd-Bold.ttf'
102 | id: font_medium_bold
103 | size: 40
104 | glyphs:
105 | ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '°', 'A', 'M', 'P']
106 |
107 | #forecast icon
108 | - file: 'fonts/materialdesigniconswebfont.ttf'
109 | id: icon_forecast
110 | size: 70
111 | glyphs: *mdi-weather-glyphs
112 |
113 | #update time
114 | - file: 'fonts/GothamRnd-Book.ttf'
115 | id: font_smallest
116 | size: 12
117 | glyphs:
118 | ['/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ', ':']
119 |
120 | # Include Background
121 | image:
122 | - file: "images/background.png"
123 | id: eink_pannel
124 | type: BINARY
125 |
126 |
127 | time:
128 | - platform: homeassistant
129 | id: ha_time
130 |
131 | text_sensor:
132 |
133 | - platform: homeassistant
134 | entity_id: sensor.eink_sensors
135 | id: today_weather
136 |
137 | - platform: homeassistant
138 | entity_id: sensor.eink_sensors
139 | attribute: today_temperature
140 | id: today_temperature
141 |
142 | - platform: homeassistant
143 | entity_id: sensor.eink_sensors
144 | attribute: today_humidity
145 | id: today_humidity
146 |
147 | - platform: homeassistant
148 | entity_id: sensor.eink_sensors
149 | attribute: today_precipitation
150 | id: today_precipitation
151 |
152 | - platform: homeassistant
153 | entity_id: sensor.eink_sensors
154 | attribute: forecast_weekday_1
155 | id: forecast_weekday_1
156 |
157 | - platform: homeassistant
158 | entity_id: sensor.eink_sensors
159 | attribute: forecast_condition_1
160 | id: forecast_weather_1
161 |
162 | - platform: homeassistant
163 | entity_id: sensor.eink_sensors
164 | attribute: forecast_temperature_1
165 | id: forecast_temperature_1
166 |
167 | - platform: homeassistant
168 | entity_id: sensor.eink_sensors
169 | attribute: forecast_weekday_2
170 | id: forecast_weekday_2
171 |
172 | - platform: homeassistant
173 | entity_id: sensor.eink_sensors
174 | attribute: forecast_condition_2
175 | id: forecast_weather_2
176 |
177 | - platform: homeassistant
178 | entity_id: sensor.eink_sensors
179 | attribute: forecast_temperature_2
180 | id: forecast_temperature_2
181 |
182 | - platform: homeassistant
183 | entity_id: sensor.eink_sensors
184 | attribute: forecast_weekday_3
185 | id: forecast_weekday_3
186 |
187 | - platform: homeassistant
188 | entity_id: sensor.eink_sensors
189 | attribute: forecast_condition_3
190 | id: forecast_weather_3
191 |
192 | - platform: homeassistant
193 | entity_id: sensor.eink_sensors
194 | attribute: forecast_temperature_3
195 | id: forecast_temperature_3
196 |
197 | - platform: homeassistant
198 | entity_id: sensor.eink_sensors
199 | attribute: forecast_weekday_4
200 | id: forecast_weekday_4
201 |
202 | - platform: homeassistant
203 | entity_id: sensor.eink_sensors
204 | attribute: forecast_condition_4
205 | id: forecast_weather_4
206 |
207 | - platform: homeassistant
208 | entity_id: sensor.eink_sensors
209 | attribute: forecast_temperature_4
210 | id: forecast_temperature_4
211 |
212 | button:
213 | - platform: template
214 | name: '${device_name} Screen Refresh'
215 | icon: 'mdi:update'
216 | on_press:
217 | then:
218 | - component.update: 'my_display'
219 | internal: false
220 |
221 | binary_sensor:
222 | - platform: status
223 | name: "${device_name} WiFi Status"
224 |
225 | color:
226 | - id: color_black
227 | red: 0%
228 | green: 0%
229 | blue: 0%
230 | white: 50%
231 | - id: color_white
232 | red: 0%
233 | green: 0%
234 | blue: 0%
235 | white: 0%
236 |
237 |
238 | # Pins for Waveshare ePaper ESP Board
239 | spi:
240 | clk_pin: GPIO13
241 | mosi_pin: GPIO14
242 |
243 | # Now render everything on the ePaper screen.
244 | display:
245 | - platform: waveshare_epaper
246 | cs_pin: GPIO15
247 | dc_pin: GPIO27
248 | busy_pin:
249 | number: GPIO25
250 | inverted: true
251 | reset_pin: GPIO26
252 | model: 7.50inV2
253 | update_interval: never
254 | id: my_display
255 | rotation: 270°
256 | lambda: |-
257 | // Map weather states to MDI characters.
258 | std::map weather_icon_map
259 | {
260 | {"cloudy", "\U000F0590"},
261 | {"cloudy-alert", "\U000F0F2F"},
262 | {"fog", "\U000F0591"},
263 | {"hail", "\U000F0592"},
264 | {"hazy", "\U000F0F30"},
265 | {"lightning", "\U000F0593"},
266 | {"lightning-rainy", "\U000F067E"},
267 | {"clear-night", "\U000F0594"},
268 | {"night", "\U000F0594"},
269 | {"night-partly-cloudy", "\U000F0F31"},
270 | {"partlycloudy", "\U000F0595"},
271 | {"partly-lightning", "\U000F0F32"},
272 | {"partly-rainy", "\U000F0F33"},
273 | {"pouring", "\U000F0596"},
274 | {"rainy", "\U000F0597"},
275 | {"sunny", "\U000F0599"},
276 | {"sunny-alert", "\U000F0F37"},
277 | {"sunny-off", "\U000F14E4"},
278 | {"sunset", "\U000F059A"},
279 | {"sunset-down", "\U000F059B"},
280 | {"sunset-up", "\U000F059C"},
281 | {"windy", "\U000F059D"},
282 | {"windy-variant", "\U000F059E"},
283 | };
284 | //background
285 | it.image(0, 0, id(eink_pannel));
286 |
287 | //************************ TODAY ************************
288 |
289 | //month
290 | it.strftime(20, 75, id(font_month),id(color_black), TextAlign::TOP_LEFT, "%b", id(ha_time).now());
291 |
292 | //day
293 | it.strftime(245, 62, id(font_day),id(color_black), TextAlign::TOP_CENTER, "%d", id(ha_time).now());
294 |
295 | //year
296 | it.strftime(390, 93, id(font_year),id(color_black), TextAlign::TOP_CENTER, "%Y", id(ha_time).now());
297 |
298 | //weekday
299 | it.strftime(240, 170, id(font_weekday),id(color_black), TextAlign::TOP_CENTER, "%A", id(ha_time).now());
300 |
301 | //************************ TODAY WEATHER ************************
302 | int today_temp_y=305;
303 | //icon
304 | it.printf(105, 310, id(icon_today),id(color_black), TextAlign::TOP_CENTER, "%s", weather_icon_map[id(today_weather).state.c_str()].c_str());
305 |
306 | //temperature
307 | it.printf(285, today_temp_y, id(font_today_temp),id(color_black), TextAlign::TOP_LEFT, "%s", id(today_temperature).state.c_str());
308 |
309 | //humidity
310 | it.printf(285, today_temp_y+80, id(font_today_temp),id(color_black), TextAlign::TOP_LEFT, "%s", id(today_humidity).state.c_str());
311 |
312 | //precipitation
313 | it.printf(285, today_temp_y+160, id(font_today_temp),id(color_black), TextAlign::TOP_LEFT, "%s", id(today_precipitation).state.c_str());
314 |
315 | //************************ FORECAST ************************
316 | int forecast_y=610;
317 | int forecast_icon_gap=45;
318 | int forecast_data_gap=130;
319 |
320 | //HOUR1
321 | //weekday
322 | it.printf(60, forecast_y, id(font_medium_bold),id(color_black), TextAlign::TOP_CENTER, "%s", id(forecast_weekday_1).state.c_str());
323 | //icon
324 | it.printf(60, forecast_y+forecast_icon_gap, id(icon_forecast),id(color_black), TextAlign::TOP_CENTER, "%s", weather_icon_map[id(forecast_weather_1).state.c_str()].c_str());
325 | //temperature
326 | it.printf(60, forecast_y+forecast_data_gap, id(font_medium_bold),id(color_black), TextAlign::TOP_CENTER, "%s", id(forecast_temperature_1).state.c_str());
327 |
328 |
329 | //HOUR2
330 | //weekday
331 | it.printf(180, forecast_y, id(font_medium_bold),id(color_black), TextAlign::TOP_CENTER, "%s", id(forecast_weekday_2).state.c_str());
332 | //icon
333 | it.printf(180, forecast_y+forecast_icon_gap, id(icon_forecast),id(color_black), TextAlign::TOP_CENTER, "%s", weather_icon_map[id(forecast_weather_2).state.c_str()].c_str());
334 | //temperature
335 | it.printf(183, forecast_y+forecast_data_gap, id(font_medium_bold),id(color_black), TextAlign::TOP_CENTER, "%s", id(forecast_temperature_2).state.c_str());
336 |
337 | //HOUR3
338 | //weekday
339 | it.printf(300, forecast_y, id(font_medium_bold),id(color_black), TextAlign::TOP_CENTER, "%s", id(forecast_weekday_3).state.c_str());
340 | //icon
341 | it.printf(300, forecast_y+forecast_icon_gap, id(icon_forecast),id(color_black), TextAlign::TOP_CENTER, "%s", weather_icon_map[id(forecast_weather_3).state.c_str()].c_str());
342 | //temperature
343 | it.printf(303, forecast_y+forecast_data_gap, id(font_medium_bold),id(color_black), TextAlign::TOP_CENTER, "%s", id(forecast_temperature_3).state.c_str());
344 |
345 |
346 | //HOUR4
347 | //weekday
348 | it.printf(425, forecast_y, id(font_medium_bold),id(color_black), TextAlign::TOP_CENTER, "%s", id(forecast_weekday_4).state.c_str());
349 | //icon
350 | it.printf(425, forecast_y+forecast_icon_gap, id(icon_forecast),id(color_black), TextAlign::TOP_CENTER, "%s", weather_icon_map[id(forecast_weather_4).state.c_str()].c_str());
351 | //temperature
352 | it.printf(425, forecast_y+forecast_data_gap, id(font_medium_bold),id(color_black), TextAlign::TOP_CENTER, "%s", id(forecast_temperature_4).state.c_str());
353 |
354 | //last update time
355 | it.strftime(2, 786, id(font_smallest),id(color_black), TextAlign::TOP_LEFT, "%m/%d %H:%M", id(ha_time).now());
356 |
--------------------------------------------------------------------------------