substitutions: device_name: "esp32-75epaper-keuken" friendly_name: "Epaper display keuken" comment: "7,5inch epaper displau keuken" location: "Keuken" api_password: !secret eink_display_api ota_password: !secret ota_password wifi_ssid: !secret wifi_ssid wifi_password: !secret wifi_password gateway: !secret ip_gateway subnet: !secret ip_subnet ip: !secret eink_display_ip packages: board: !include boards/esp32_wroom_arduino.yaml connection: !include common/wifi_nosens.yaml logger: !include templates/logger.yaml #bt_proxy: !include common/bluetooth.yaml #no space esphome: name: ${device_name} comment: ${comment} friendly_name: ${friendly_name} includes: - include/epaper75.h external_components: # - source: # type: git # url: https://github.com/atomicmike/esphome.git # ref: waveshare-color-2022.6 # components: [waveshare_epaper] - source: components/waveshare-epaper-c sun: latitude: !secret home_latitude longitude: !secret home_longitude globals: - id: data_updated type: bool restore_value: no initial_value: 'false' - id: initial_data_received type: bool restore_value: no initial_value: 'false' - id: recorded_display_refresh type: int restore_value: yes initial_value: '0' time: - platform: homeassistant id: esptime on_time_sync: - then: - component.update: sunrise - component.update: sunset - logger.log: Time has been set and is valid! on_time: - minutes: 5 then: - if: condition: lambda: 'return id(data_updated) == true;' then: - lambda: 'id(initial_data_received) = true;' - logger.log: "Sensor data updated: Refreshing display..." - component.update: eink_display - lambda: 'id(data_updated) = false;' - lambda: 'id(recorded_display_refresh) += 1;' - lambda: 'id(display_last_update).publish_state(id(esptime).now().timestamp);' else: - logger.log: "No sensors updated - skipping display refresh." button: - platform: template name: "Refresh screen" id: refresh icon: "mdi:emoticon-outline" on_press: - logger.log: "Button pressed" - component.update: eink_display # deep_sleep: # run_duration: 15s # sleep_duration: 1min # Include custom fonts font: # - file: 'fonts/GothamRnd-Book.ttf' # id: font_small_book # size: 18 - file: 'fonts/GothamRnd-Bold.ttf' id: font_large_bold size: 108 glyphs: ['-',' ', '°', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'C', 'a', 'n'] # - file: 'fonts/GothamRnd-Bold.ttf' # id: font_medium_bold # size: 30 # glyphs: [' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'M', 'I', 'N'] - file: 'fonts/GothamRnd-Bold.ttf' id: font_small_bold size: 18 # glyphs: ['°', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'C', 'M', 'I', 'N'] # - file: 'fonts/GothamRnd-Bold.ttf' # id: font_time # size: 90 # glyphs: [' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':'] - file: 'fonts/GothamRnd-Book.ttf' id: font_weekday size: 30 glyphs: ['a', 'd', 'e','F', 'h', 'i','M', 'n', 'o', 'r', 's','S', 't','T', 'u', 'W', 'y'] - file: 'fonts/GothamRnd-Book.ttf' id: font_day size: 65 glyphs: [' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] - file: 'fonts/GothamRnd-Bold.ttf' id: font_month size: 40 # - file: fonts/materialdesignicons-webfont.ttf # id: font_wifi # size: 20 # glyphs: # - "\U000F091F" # - "\U000F0922" # - "\U000F0925" # - "\U000F0928" # - "\U000F092B" # Include Material Design Icons font # Thanks to https://community.home-assistant.io/t/display-materialdesign-icons-on-esphome-attached-to-screen/199790/16 - file: 'fonts/materialdesignicons-webfont.ttf' id: font_mdi_large size: 96 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 - "\U000f010b" # mdi-car - "\U000f0819" # trash # - file: 'fonts/materialdesignicons-webfont.ttf' # id: font_mdi_medlarge # size: 60 # glyphs: # - "\U000f0f64" # new moon # - "\U000f0f67" # mdi-moon-waxing-crescent # - "\U000F0F61" # mdi-moon-first-quarter # - "\U000F0F68" # mdi-moon-waxing-gibbous # - "\U000F0F62" # mdi-moon-full # - "\U000F0F66" # mdi-moon-waning-gibbous # - "\U000F0F63" # mdi-moon-last-quarter # - "\U000F0F65" # mdi-moon-waning-crescent - file: 'fonts/materialdesignicons-webfont.ttf' id: font_mdi_medium size: 36 glyphs: *mdi-weather-glyphs sensor: - platform: template name: "${device_name} Last Update" device_class: timestamp id: display_last_update - platform: homeassistant entity_id: weather.forecast_home attribute: temperature id: weather_temperature on_value: then: - lambda: 'id(data_updated) = true;' - !include { file: sensors/homeassistant.yaml, vars: { id: weather_temperature_0, entity_id: sensor.e_ink_display_data }} - !include { file: sensors/homeassistant.yaml, vars: { id: weather_temperature_1, entity_id: sensor.e_ink_display_data }} - !include { file: sensors/homeassistant.yaml, vars: { id: weather_temperature_2, entity_id: sensor.e_ink_display_data }} - !include { file: sensors/homeassistant.yaml, vars: { id: weather_temperature_3, entity_id: sensor.e_ink_display_data }} - !include { file: sensors/homeassistant.yaml, vars: { id: travel_Best_time, entity_id: sensor.e_ink_display_data }} - !include { file: sensors/homeassistant.yaml, vars: { id: travel_ASML_time, entity_id: sensor.e_ink_display_data }} - !include { file: sensors/homeassistant.yaml, vars: { id: travel_euretco_time, entity_id: sensor.e_ink_display_data }} - platform: wifi_signal id: sensor_wifi_signal name: "${device_name} WiFi" update_interval: 60s on_value: - component.update: sensor_wifi_signal_percentage - platform: template id: sensor_wifi_signal_percentage name: "${device_name} Wi-Fi Signal Percentage" icon: "mdi:wifi" unit_of_measurement: "%" update_interval: never lambda: |- if (id(sensor_wifi_signal).state) { if (id(sensor_wifi_signal).state <= -100 ) { return 0; } else if (id(sensor_wifi_signal).state >= -50) { return 100; } else { return 2 * (id(sensor_wifi_signal).state + 100); } } else { return NAN; } - platform: template name: "${device_name} Recorded Display Refresh" lambda: 'return id(recorded_display_refresh);' unit_of_measurement: "refreshes" text_sensor: - platform: homeassistant entity_id: weather.forecast_home id: weather_state - !include { file: sensors/homeassistant.yaml, vars: { id: weather_condition_now, entity_id: sensor.e_ink_display_data }} - !include { file: sensors/homeassistant.yaml, vars: { id: weather_condition_0, entity_id: sensor.e_ink_display_data}} - !include { file: sensors/homeassistant.yaml, vars: { id: weather_timestamp_0, entity_id: sensor.e_ink_display_data }} - !include { file: sensors/homeassistant.yaml, vars: { id: weather_condition_1, entity_id: sensor.e_ink_display_data }} - !include { file: sensors/homeassistant.yaml, vars: { id: weather_timestamp_1, entity_id: sensor.e_ink_display_data }} - !include { file: sensors/homeassistant.yaml, vars: { id: weather_condition_2, entity_id: sensor.e_ink_display_data }} - !include { file: sensors/homeassistant.yaml, vars: { id: weather_timestamp_2, entity_id: sensor.e_ink_display_data }} - !include { file: sensors/homeassistant.yaml, vars: { id: weather_condition_3, entity_id: sensor.e_ink_display_data }} - !include { file: sensors/homeassistant.yaml, vars: { id: weather_timestamp_3, entity_id: sensor.e_ink_display_data }} - !include { file: sensors/homeassistant.yaml, vars: { id: afval_today, entity_id: sensor.e_ink_display_data }} - !include { file: sensors/homeassistant.yaml, vars: { id: afval_tomorrow, entity_id: sensor.e_ink_display_data }} - !include { file: sensors/homeassistant.yaml, vars: { id: travel_Best_name, entity_id: sensor.e_ink_display_data }} - !include { file: sensors/homeassistant.yaml, vars: { id: travel_ASML_name, entity_id: sensor.e_ink_display_data }} - !include { file: sensors/homeassistant.yaml, vars: { id: travel_euretco_name, entity_id: sensor.e_ink_display_data }} - platform: homeassistant entity_id: sensor.moon_phase #attribute: icon id: moon_phase on_value: then: - lambda: 'id(data_updated) = true;' - platform: homeassistant entity_id: sensor.moon id: moon internal: true # Sunrise - platform: sun type: sunrise id: sun_sunrise format: "%H:%M" on_value: then: - lambda: 'id(data_updated) = true;' # Sunset - platform: sun type: sunset id: sun_sunset format: "%H:%M" on_value: then: - lambda: 'id(data_updated) = true;' - platform: wifi_info ssid: name: "${device_name} Connected SSID" id: ssid icon: mdi:wifi-strength-2 entity_category: diagnostic bssid: name: "${device_name} Connected BSSID" id: bssid icon: mdi:wifi-strength-2 entity_category: diagnostic mac_address: name: "${device_name} WiFi Mac Address" id: macaddress icon: mdi:wifi-strength-2 entity_category: diagnostic - platform: sun id: sunrise name: Sun Next Sunrise type: sunrise format: "%H:%M" internal: true update_interval: 12h - platform: sun id: sunset name: Sun Next Sunset type: sunset format: "%H:%M" internal: true update_interval: 12h # Define colors # This design is white on black so this is necessary. color: - id: color_black red: 0% green: 0% blue: 0% white: 50% - id: color_white red: 0% green: 0% blue: 0% white: 0% - id: COLOR_RED red: 100% green: 0% blue: 0% white: 0% # Pins for Waveshare ePaper ESP Board spi: clk_pin: GPIO13 mosi_pin: GPIO14 # Now render everything on the ePaper screen. display: - platform: waveshare_epaper cs_pin: GPIO27 dc_pin: GPIO16 busy_pin: GPIO25 reset_pin: GPIO26 model: 7.50in-bV2 #model: 7.50inv2b #model: 7.50inv2 #model: 7.50inV2alt update_interval: 30min id: eink_display rotation: 90° lambda: |- int xres = it.get_width(); int yres = it.get_height(); #define x_pad 10 // border padding #define y_pad 10 // border padding int wifi_x_a = xres-x_pad; int wifi_y_a = yres-y_pad+2; // Fill background in black. it.fill(COLOR_OFF); // wifi strength // if (id(sensor_wifi_signal).has_state()) // { // if (id(sensor_wifi_signal).state >= -50) { // //Excellent // it.print(wifi_x_a, wifi_y_a, id(font_wifi), TextAlign::BASELINE_RIGHT, "󰤨"); // ESP_LOGI("WiFi", "Excellent"); // } else if (id(sensor_wifi_signal).state >= -60) { // //Good // it.print(wifi_x_a, wifi_y_a, id(font_wifi), TextAlign::BASELINE_RIGHT, "󰤥"); // ESP_LOGI("WiFi", "Good"); // } else if (id(sensor_wifi_signal).state >= -67) { // //Fair // it.print(wifi_x_a, wifi_y_a, id(font_wifi), TextAlign::BASELINE_RIGHT, "󰤢"); // ESP_LOGI("WiFi", "Fair"); // } else if (id(sensor_wifi_signal).state >= -70) { // //Weak // it.print(wifi_x_a, wifi_y_a, id(font_wifi), TextAlign::BASELINE_RIGHT, "󰤟"); // ESP_LOGI("WiFi", "Weak"); // } else { // //Unlikely working signal // it.print(wifi_x_a, wifi_y_a, id(font_wifi), TextAlign::BASELINE_RIGHT, "󰤫"); // ESP_LOGI("WiFi", "Unlikely"); // } //} // clock section int clk_yoffset = 50; int clk_xoffset = 310; // Print full weekday name it.strftime(clk_xoffset, clk_yoffset, id(font_weekday), TextAlign::TOP_RIGHT, "%A", id(esptime).now()); // Print time in HH:MM format 335 // it.strftime(clk_xoffset, clk_yoffset+105, id(font_time), TextAlign::BASELINE_RIGHT, "%H:%M", id(esptime).now()); // Print day of the month it.strftime(clk_xoffset+100, clk_yoffset, id(font_day), TextAlign::TOP_RIGHT, "%d", id(esptime).now()); // Print abbreviated month name it.strftime(clk_xoffset+100, clk_yoffset+105, id(font_month), TextAlign::BASELINE_RIGHT, "%b", id(esptime).now()); int sry_offset = 200; //sunrise/set y-offset // Print sunrise it.printf(60, sry_offset, id(font_mdi_medium), COLOR_RED, TextAlign::CENTER_RIGHT, "\U000F059C"); if(id(sun_sunrise).has_state ()) { it.printf(65, sry_offset, id(font_small_bold), TextAlign::CENTER_LEFT, "%s", id(sun_sunrise).state.c_str()); } // Print sunset it.printf(425, sry_offset, id(font_mdi_medium), COLOR_RED, TextAlign::CENTER_RIGHT, "\U000F059B"); if(id(sun_sunset).has_state ()) { it.printf(385, sry_offset, id(font_small_bold), TextAlign::CENTER_RIGHT, "%s", id(sun_sunset).state.c_str()); } // Moonphae //it.printf(265, sry_offset, id(font_mdi_medlarge), TextAlign::CENTER, "%s", moon_icon_map[id(moon_phase).state.c_str()].c_str()); it.line(30, sry_offset+30, 420, sry_offset+30); // Weather Section int wy_offset = sry_offset + 60; //weather y offset // WEATHER STATE ICON it.printf(80, wy_offset, id(font_mdi_large), COLOR_RED, TextAlign::TOP_CENTER, "%s", weather_icon_map[id(weather_condition_now).state.c_str()].c_str()); // TEMPERATURE it.printf(410, wy_offset, id(font_large_bold), TextAlign::TOP_RIGHT, "%2.0f°C", id(weather_temperature).state); int forecast_yoffset = wy_offset+30+108; int fcst_xstart = 90; int fcst_offset = 90; it.printf(fcst_xstart, forecast_yoffset, id(font_small_bold), TextAlign::TOP_CENTER, "%s", id(weather_timestamp_0).state.c_str()); it.printf(fcst_xstart, forecast_yoffset+20, id(font_mdi_medium), COLOR_RED, TextAlign::TOP_CENTER, "%s", weather_icon_map[id(weather_condition_0).state.c_str()].c_str()); it.printf(fcst_xstart, forecast_yoffset+72, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f°C", id(weather_temperature_0).state); fcst_xstart += fcst_offset; it.printf(fcst_xstart, forecast_yoffset, id(font_small_bold), TextAlign::TOP_CENTER, "%s", id(weather_timestamp_1).state.c_str()); it.printf(fcst_xstart, forecast_yoffset+20, id(font_mdi_medium), COLOR_RED, TextAlign::TOP_CENTER, "%s", weather_icon_map[id(weather_condition_1).state.c_str()].c_str()); it.printf(fcst_xstart, forecast_yoffset+72, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f°C", id(weather_temperature_1).state); fcst_xstart += fcst_offset; it.printf(fcst_xstart, forecast_yoffset, id(font_small_bold), TextAlign::TOP_CENTER, "%s", id(weather_timestamp_2).state.c_str()); it.printf(fcst_xstart, forecast_yoffset+20, id(font_mdi_medium), COLOR_RED, TextAlign::TOP_CENTER, "%s", weather_icon_map[id(weather_condition_2).state.c_str()].c_str()); it.printf(fcst_xstart, forecast_yoffset+72, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f°C", id(weather_temperature_2).state); fcst_xstart += fcst_offset; it.printf(fcst_xstart, forecast_yoffset, id(font_small_bold), TextAlign::TOP_CENTER, "%s", id(weather_timestamp_3).state.c_str()); it.printf(fcst_xstart, forecast_yoffset+20, id(font_mdi_medium), COLOR_RED, TextAlign::TOP_CENTER, "%s", weather_icon_map[id(weather_condition_3).state.c_str()].c_str()); it.printf(fcst_xstart, forecast_yoffset+72, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f°C", id(weather_temperature_3).state); it.line(30, forecast_yoffset+102, 420, forecast_yoffset+102); int drvtime_yoffset = forecast_yoffset+132; int drvtime_xoffset = 40; it.printf(drvtime_xoffset, drvtime_yoffset, id(font_mdi_medium), COLOR_RED, TextAlign::TOP_CENTER, "%s", weather_icon_map["car"].c_str()); it.printf(drvtime_xoffset+90, drvtime_yoffset, id(font_small_bold), TextAlign::TOP_CENTER, "%s", id(travel_Best_name).state.c_str()); it.printf(drvtime_xoffset+90, drvtime_yoffset+30, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f min", id(travel_Best_time).state); it.printf(drvtime_xoffset+210, drvtime_yoffset, id(font_small_bold), TextAlign::TOP_CENTER, "%s", id(travel_ASML_name).state.c_str()); it.printf(drvtime_xoffset+210, drvtime_yoffset+30, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f min", id(travel_ASML_time).state); it.printf(drvtime_xoffset+330, drvtime_yoffset, id(font_small_bold), TextAlign::TOP_CENTER, "%s", id(travel_euretco_name).state.c_str()); it.printf(drvtime_xoffset+330, drvtime_yoffset+30, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f min", id(travel_euretco_time).state); it.line(30, drvtime_yoffset+60, 420, drvtime_yoffset+60); int waste_yoffset = drvtime_yoffset+90; int waste_xoffset = 60; it.printf(waste_xoffset, waste_yoffset, id(font_mdi_medium), COLOR_RED, TextAlign::TOP_CENTER, "%s", weather_icon_map["trash"].c_str()); it.printf(waste_xoffset+100, waste_yoffset, id(font_small_bold), TextAlign::TOP_CENTER, "Vandaag:"); it.printf(waste_xoffset+260, waste_yoffset, id(font_small_bold), TextAlign::TOP_CENTER, "Morgen:"); it.printf(waste_xoffset+95, waste_yoffset+30, id(font_small_bold), TextAlign::TOP_CENTER, "%s", id(afval_today).state.c_str()); it.printf(waste_xoffset+255, waste_yoffset+30, id(font_small_bold), TextAlign::TOP_CENTER, "%s", id(afval_tomorrow).state.c_str()); // it.line(30, 400, 440, 400); // it.printf(30, 520, id(font_mdi_medium), color_white, TextAlign::TOP_CENTER, "%s", moon_icon_map[id(moon_phace_icon).state.c_str()].c_str()); captive_portal: