hi @brot123 can i ask you how you fixed the hourly forecast?
It´s a breaking change in the 2024.3
This will give you a sensor with hourly forecast
template:
- trigger:
- platform: time_pattern
hours: /1
- platform: homeassistant
event: start
action:
- service: weather.get_forecasts
data:
type: hourly
target:
entity_id: weather.home
response_variable: hourly
sensor:
- name: Weather Hourly
state: "{{ states('weather.home') }}"
attributes:
temperature: "{{ state_attr('weather.home', 'temperature') }}"
dew_point: "{{ state_attr('weather.home', 'dew_point') }}"
temperature_unit: "{{ state_attr('weather.home', 'temperature_unit') }}"
humidity: "{{ state_attr('weather.home', 'humidity') }}"
cloud_coverage: "{{ state_attr('weather.home', 'cloud_coverage') }}"
pressure: "{{ state_attr('weather.home', 'pressure') }}"
pressure_unit: "{{ state_attr('weather.home', 'pressure_unit') }}"
wind_bearing: "{{ state_attr('weather.home', 'wind_bearing') }}"
wind_speed: "{{ state_attr('weather.home', 'wind_speed') }}"
wind_speed_unit: "{{ state_attr('weather.home', 'wind_speed_unit') }}"
visibility_unit: "{{ state_attr('weather.home', 'visibility_unit') }}"
precipitation_unit: "{{ state_attr('weather.home', 'precipitation_unit') }}"
forecast: "{{ hourly['weather.home'].forecast }}"
@madelena : Thanks to your inspirational post and the work of others here I managed to put this together. Very dense on information so a bit less stylish (unfortunately I’m not as good a designer as you are), but I’m still very happy with the result:
Things that are here:
- Weather forecast
- Rain forecast graph
- Inside and outside temperature
- Home schematic:
- Windows and doors that are open
- Blinds that are closed
- Windows that need opening due to bad air quality
- Windows that need opening or closing due to rain or temperature difference
- Blinds that cannot close due to high wind
- Lock state of the front door
- Battery state and range of my car (the separation line doubles as a percentage bar chart)
- Car battery preservation mode (charge to 80% or 100%, the lines on the bar)
- Car plugged in or charging
- Next appointment for today for all family members
- Travel time to bring my son to school
- Solar production and prediction for today (not a good day today)
- The next evening meal
- I have a bit of space left for a train departure time, when I get the integration to provide me the right data.
Magnificent!
I’d love to see the code behind this…
That is quite a lot, not just in the esp but also preparing all kinds of sensors for window open and close advice and rain graph data. Not the prettiest of code, it kind of organically grew from an experiment to what it is now. This is the adjusted template sensor I use:
- binary_sensor:
- name: E-ink display 1 Occupancy
unique_id: "e_ink_display_1_occupancy"
device_class: "occupancy"
delay_off:
minutes: 1
state: "{{ states('binary_sensor.benedenverdieping_aanwezigheid') }}"
- trigger:
platform: time_pattern
minutes: "/1"
action:
- service: weather.get_forecasts
data:
type: hourly
target:
entity_id: weather.heemraadstraat
response_variable: hourly
sensor:
- name: E-ink display 1 Data
state: "OK"
attributes:
room_temperature: >-
{{ states('sensor.woonkamer_temperatuur_gem') | float(0) | round(1) }}
weather_condition_now: >-
{% set cond_now = states('weather.heemraadstraat') %}
{% if states('sensor.heemraadstraat_zon_fase') == 'night' %}
{% if cond_now == 'sunny' %} night {% elif cond_now == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond_now }} {% endif %}
{% else %}
{{ cond_now }}
{% endif %}
weather_temperature: >-
{{ states('sensor.gemeten_buitentemperatuur') | float(0) | round(1) }}
weather_condition_0: >-
{% set cond0 = hourly["weather.heemraadstraat"].forecast[2].condition %}
{% set next_setting = as_timestamp(states('sensor.heemraadstraat_zon_zonsondergang')) %}
{% set next_rising = as_timestamp(states('sensor.heemraadstraat_zon_zonsopkomst')) %}
{% set cond0_time = as_timestamp(hourly["weather.heemraadstraat"].forecast[2].datetime) %}
{% if cond0_time < next_rising and next_rising < next_setting %}
{% if cond0 == 'sunny' %} night {% elif cond0 == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond0 }} {% endif %}
{% else %}
{{ cond0 }}
{% endif %}
weather_temperature_0: >-
{{ hourly["weather.heemraadstraat"].forecast[2].temperature | round(1) }}
weather_timestamp_0: >-
{{ as_timestamp(hourly["weather.heemraadstraat"].forecast[2].datetime) | timestamp_custom('%H:%M') }}
weather_condition_1: >-
{% set cond1 = hourly["weather.heemraadstraat"].forecast[4].condition %}
{% set next_setting = as_timestamp(states('sensor.heemraadstraat_zon_zonsondergang')) %}
{% set next_rising = as_timestamp(states('sensor.heemraadstraat_zon_zonsopkomst')) %}
{% set cond1_time = as_timestamp(hourly["weather.heemraadstraat"].forecast[4].datetime) %}
{% if cond1_time < next_rising and next_rising < next_setting %}
{% if cond1 == 'sunny' %} night {% elif cond1 == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond1 }} {% endif %}
{% else %}
{{ cond1 }}
{% endif %}
weather_temperature_1: >-
{{ hourly["weather.heemraadstraat"].forecast[4].temperature | round(1) }}
weather_timestamp_1: >-
{{ as_timestamp(hourly["weather.heemraadstraat"].forecast[4].datetime) | timestamp_custom('%H:%M') }}
weather_condition_2: >-
{% set cond2 = hourly["weather.heemraadstraat"].forecast[6].condition %}
{% set next_setting = as_timestamp(states('sensor.heemraadstraat_zon_zonsondergang')) %}
{% set next_rising = as_timestamp(states('sensor.heemraadstraat_zon_zonsopkomst')) %}
{% set cond2_time = as_timestamp(hourly["weather.heemraadstraat"].forecast[6].datetime) %}
{% if cond2_time < next_rising and next_rising < next_setting %}
{% if cond2 == 'sunny' %} night {% elif cond2 == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond2 }} {% endif %}
{% else %}
{{ cond2 }}
{% endif %}
weather_temperature_2: >-
{{ hourly["weather.heemraadstraat"].forecast[6].temperature | round(1) }}
weather_timestamp_2: >-
{{ as_timestamp(hourly["weather.heemraadstraat"].forecast[6].datetime) | timestamp_custom('%H:%M') }}
weather_condition_3: >-
{% set cond3 = hourly["weather.heemraadstraat"].forecast[8].condition %}
{% set next_setting = as_timestamp(states('sensor.heemraadstraat_zon_zonsondergang')) %}
{% set next_rising = as_timestamp(states('sensor.heemraadstraat_zon_zonsopkomst')) %}
{% set cond3_time = as_timestamp(hourly["weather.heemraadstraat"].forecast[8].datetime) %}
{% if cond3_time < next_rising and next_rising < next_setting %}
{% if cond3 == 'sunny' %} night {% elif cond3 == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond3 }} {% endif %}
{% else %}
{{ cond3 }}
{% endif %}
weather_temperature_3: >-
{{ hourly["weather.heemraadstraat"].forecast[8].temperature | round(1) }}
weather_timestamp_3: >-
{{ as_timestamp(hourly["weather.heemraadstraat"].forecast[8].datetime) | timestamp_custom('%H:%M') }}
weather_rain_graph: >-
{% set r = state_attr('sensor.neerslag_buienalarm_regen_data','data') %}
{% set p = r.precip %}
{% set d = r.delta | int(300) %}
{% set c = p | count %}
{% set s = r.start | int(0) %}
{% set f = 5 %}
{{ s | timestamp_custom('%H:%M')
}};{{ (s + d * (c - 1) * 0.25) | timestamp_custom('%H:%M')
}};{{ (s + d * (c - 1) * 0.50) | timestamp_custom('%H:%M')
}};{{ (s + d * (c - 1) * 0.75) | timestamp_custom('%H:%M')
}};{{ (s + d * (c - 1)) | timestamp_custom('%H:%M')
}};{{ (r.levels.light | float(0) / f) | round(2)
}};{{ (r.levels.moderate | float(0) / f) | round(2)
}};{{ (r.levels.heavy | float(0) / f) | round(2)
}};{{ (p + [
r.levels.light | float(0) / f,
r.levels.moderate | float(0) / f,
r.levels.heavy | float(0) / f
]) | max | float(0) | round(2) }};{{ p | join(';')
}}
solar_forecast_today: >-
{{ (states('sensor.solcast_pv_forecast_forecast_today') | float(0)) |
round(iif(states('sensor.solcast_pv_forecast_forecast_today') | float(0) < 1,2,1)) }}
solar_production_today: >-
{{ (states('sensor.envoy_122311033724_today_s_energy_production') | float(0) / 1000) |
round(iif(states('sensor.envoy_122311033724_today_s_energy_production') | float(0) < 1000,2,1)) }}
reistijd_leo_kanner: >-
{{ states('sensor.maximale_reistijd_leo_kanner') | float(0) | round(1) }}
next_meal: >-
{% if states('calendar.maaltijden') != 'unknown' and state_attr('calendar.maaltijden', 'message') != None %}
{{ as_timestamp(state_attr('calendar.maaltijden', 'start_time')) | timestamp_custom('%a')
| replace('Mon','Ma') | replace('Tue','Di') | replace('Wed','Wo') | replace('Thu','Do') | replace('Fri','Vr') | replace('Sat','Za') | replace('Sun','Zo')
}}: {{ state_attr('calendar.maaltijden', 'message') }}
{% else %}
{% endif %}
apt_gezin: >-
{% set cal = 'calendar.gezin' %}
{% if states(cal) != 'unknown' and states(cal) != 'unavailable' %}
{% set start = as_timestamp(state_attr(cal, 'start_time')) %}
{% set msg = state_attr(cal, 'message') %}
{% if msg != None and (as_timestamp(now()) | timestamp_custom('%d-%m-%Y')) == (start | timestamp_custom('%d-%m-%Y')) %}
G: {{ start | timestamp_custom('%H:%M') | replace('00:00',' ')
}} - {{ msg }}
{% endif %}
{% endif %}
apt_edwin: >-
{% set cal = 'calendar.edwin_delsman_gmail_com' %}
{% if states(cal) != 'unknown' and states(cal) != 'unavailable' %}
{% set start = as_timestamp(state_attr(cal, 'start_time')) %}
{% set msg = state_attr(cal, 'message') %}
{% if msg != None and (as_timestamp(now()) | timestamp_custom('%d-%m-%Y')) == (start | timestamp_custom('%d-%m-%Y')) %}
E: {{ start | timestamp_custom('%H:%M') | replace('00:00',' ')
}} - {{ msg }}
{% endif %}
{% endif %}
apt_fleur: >-
{% set cal = 'calendar.fleur' %}
{% if states(cal) != 'unknown' and states(cal) != 'unavailable' %}
{% set start = as_timestamp(state_attr(cal, 'start_time')) %}
{% set msg = state_attr(cal, 'message') %}
{% if msg != None and (as_timestamp(now()) | timestamp_custom('%d-%m-%Y')) == (start | timestamp_custom('%d-%m-%Y')) %}
F: {{ start | timestamp_custom('%H:%M') | replace('00:00',' ')
}} - {{ msg }}
{% endif %}
{% endif %}
apt_rianne: >-
{% set cal = 'calendar.rianne' %}
{% if states(cal) != 'unknown' and states(cal) != 'unavailable' %}
{% set start = as_timestamp(state_attr(cal, 'start_time')) %}
{% set msg = state_attr(cal, 'message') %}
{% if msg != None and (as_timestamp(now()) | timestamp_custom('%d-%m-%Y')) == (start | timestamp_custom('%d-%m-%Y')) %}
R: {{ start | timestamp_custom('%H:%M') | replace('00:00',' ')
}} - {{ msg }}
{% endif %}
{% endif %}
apt_jasper: >-
{% set cal = 'calendar.jasper' %}
{% if states(cal) != 'unknown' and states(cal) != 'unavailable' %}
{% set start = as_timestamp(state_attr(cal, 'start_time')) %}
{% set msg = state_attr(cal, 'message') %}
{% if msg != None and (as_timestamp(now()) | timestamp_custom('%d-%m-%Y')) == (start | timestamp_custom('%d-%m-%Y')) %}
J: {{ start | timestamp_custom('%H:%M') | replace('00:00',' ')
}} - {{ msg }}
{% endif %}
{% endif %}
windows_and_screens: >-
{{ iif(is_state('binary_sensor.openclose_10','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.openclose_12','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.openclose_6','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.openclose_11','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.openclose_49','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.openclose_51','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.openclose_37','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.openclose_82','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.openclose_55','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.openclose_62','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.openclose_64','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.openclose_48','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.openclose_50','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.openclose_61','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.openclose_63','on'),'O','-','?')
}}{{ iif(state_attr('cover.zolderscherm_links','current_position') | float(0) == 100,'-','C','?')
}}{{ iif(state_attr('cover.zolderscherm_rechts','current_position') | float(0) == 100,'-','C','?')
}}{{ iif(state_attr('cover.slaapkamerscherm_links','current_position') | float(0) == 100,'-','C','?')
}}{{ iif(state_attr('cover.slaapkamerscherm_midden','current_position') | float(0) == 100,'-','C','?')
}}{{ iif(state_attr('cover.slaapkamerscherm_rechts','current_position') | float(0) == 100,'-','C','?')
}}{{ iif(state_attr('cover.keukenscherm','current_position') | float(0) == 100,'-','C','?')
}}{{ iif(is_state('binary_sensor.schuifpui_openen_advies','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.keuken_openen_advies','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.slaapkamer_links_openen_advies','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.slaapkamer_rechts_openen_advies','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.rianne_openen_advies','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.jasper_openen_advies','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.zolder_openen_advies','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.dakkapel_links_openen_advies','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.dakkapel_rechts_openen_advies','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.schuifpui_sluiten_advies','on'),'S','-','?')
}}{{ iif(is_state('binary_sensor.keuken_sluiten_advies','on'),'S','-','?')
}}{{ iif(is_state('binary_sensor.slaapkamer_links_sluiten_advies','on'),'S','-','?')
}}{{ iif(is_state('binary_sensor.slaapkamer_rechts_sluiten_advies','on'),'S','-','?')
}}{{ iif(is_state('binary_sensor.rianne_sluiten_advies','on'),'S','-','?')
}}{{ iif(is_state('binary_sensor.jasper_sluiten_advies','on'),'S','-','?')
}}{{ iif(is_state('binary_sensor.zolder_sluiten_advies','on'),'S','-','?')
}}{{ iif(is_state('binary_sensor.dakkapel_links_sluiten_advies','on'),'S','-','?')
}}{{ iif(is_state('binary_sensor.dakkapel_rechts_sluiten_advies','on'),'S','-','?')
}}{{ iif(is_state('binary_sensor.raam_open_achter_linker_slaapkamerscherm','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.raam_open_achter_rechter_slaapkamerscherm','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.raam_open_achter_zolderscherm','on'),'O','-','?')
}}{{ iif(is_state('binary_sensor.rolschermen_wind_grenswaarde','on'),'W','-','?')
}}{{ iif(is_state('binary_sensor.knikarmschermen_wind_grenswaarde','on'),'W','-','?')
}}{{ iif(state_attr('cover.dakscherm_links','current_position') | float(0) == 100,'-','C','?')
}}{{ iif(state_attr('cover.dakscherm_rechts','current_position') | float(0) == 100,'-','C','?')
}}{{ iif(is_state('lock.enyaq_door_locked','unlocked'),'O','-','?')
}}{{ iif(is_state('binary_sensor.enyaq_ramen','on'),'O','-','?')
}}{{ iif(is_state('lock.voordeur_nachtslot','locked'),'L','-','?')
}}
car_km_range: "{{ states('sensor.enyaq_electric_range') | float(0) }}"
car_battery_perc: "{{ states('sensor.enyaq_battery_level') | float(0) }}"
car_target_perc: "{{ states('input_number.enyaq_eenmalig_laadniveau') | float(0) }}"
car_charge_status: >-
{% if states('switch.enyaq_charging') in ['unavailable','unknown'] %}
?
{% elif states('sensor.wallbox_portal_status_description') == 'Disconnected' %}
Verbroken
{% elif states('switch.enyaq_charging') == 'on' %}
Laden
{% elif states('binary_sensor.enyaq_vehicle_moving') == 'on' %}
Rijden
{% elif (states('sensor.enyaq_battery_level') | int(0)) >= (states('input_number.enyaq_eenmalig_laadniveau') | int(0)) %}
{% if states('binary_sensor.enyaq_charging_cable_connected') == 'on' %}
Opgeladen
{% elif states('binary_sensor.enyaq_parking_light') == 'on' %}
Verlicht
{% else %}
Rijklaar
{% endif %}
{% elif states('binary_sensor.enyaq_charging_cable_connected') == 'on' %}
Aangesloten
{% elif states('binary_sensor.enyaq_parking_light') == 'on' %}
Verlicht
{% else %}
Losgekoppeld
{% endif %}
The ESP code is too big to post here, it got rejected.
But this is the display part:
display:
- platform: waveshare_epaper
model: 7.50in-bv2-rb
id: eink_display
cs_pin: GPIO15
dc_pin: GPIO27
busy_pin:
number: GPIO25
inverted: True
reset_pin: GPIO26
reset_duration: 2ms
update_interval: never
rotation: 0°
lambda: |-
std::map<std::string, std::string> weather_icon_map
{
{"clear-night", "\U000F0594"},
{"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"}
};
std::map<std::string, std::string> car_icon_map
{
{ "power-plug", "\U000F06A5" },
{ "power-plug-outline", "\U000F1425" },
{ "power-plug-off-outline", "\U000F1424" },
{ "connection", "\U000F1616" },
{ "car-off", "\U000F0E1C" },
{ "battery", "\U000F0079" },
{ "battery-high", "\U000F12A3" },
{ "battery-medium", "\U000F12A2" },
{ "battery-low", "\U000F12A1" },
{ "battery-outline", "\U000F008E" },
{ "battery-charging-100", "\U000F0085" },
{ "battery-charging-high", "\U000F12A6" },
{ "battery-charging-medium", "\U000F12A5" },
{ "battery-charging-low", "\U000F12A4" },
{ "battery-charging-outline", "\U000F089F" },
{ "car-outline", "\U000F14ED" },
{ "lock-open-outline", "\U000F0340" },
{ "car-wash", "\U000F010E" },
{ "solar-power", "\U000F1A73" },
{ "car-clock", "\U000F1974" },
{ "bus-clock", "\U000F08CA" },
{ "train", "\U000F052C" }
};
std::map<std::string, int> d_w_s {
{ "Pui", 0 },
{ "Voord", 1 },
{ "Schuur", 2 },
{ "KeukenRm", 3 },
{ "L SKRm", 4 },
{ "R SKRm", 5 },
{ "JasRm", 6 },
{ "RiaRm", 7 },
{ "ZDRm", 8 },
{ "L DKRm", 9 },
{ "R DKRm", 10 },
{ "L SKRm W", 11 },
{ "R SKRm W", 12 },
{ "L DKRm W", 13 },
{ "R DKRm W", 14 },
{ "ZDSch L", 15 },
{ "ZDSch R", 16 },
{ "SKSch L", 17 },
{ "SKSch M", 18 },
{ "SKSch R", 19 },
{ "KeukenSch", 20 },
{ "Pui O", 21 },
{ "KeukenRm O", 22 },
{ "SKRm L O", 23 },
{ "SKRm R O", 24 },
{ "RiaRm O", 25 },
{ "JasRm O", 26 },
{ "ZDRm O", 27 },
{ "DKRm L O", 28 },
{ "DKRm R O", 29 },
{ "Pui S", 30 },
{ "KeukenRm S", 31 },
{ "SKRm L S", 32 },
{ "SKRm R S", 33 },
{ "RiaRm S", 34 },
{ "JasRm S", 35 },
{ "ZDRm S", 36 },
{ "DKRm L S", 37 },
{ "DKRm R S", 38 },
{ "Rm OA L SKSch", 39 },
{ "Rm OA R SKSch", 40 },
{ "Rm OA ZDSch", 41 },
{ "RolSch WGrens", 42 },
{ "KnikSch WGrens", 43 },
{ "L DkSch", 44 },
{ "R DkSch", 45 },
{ "Car D", 46 },
{ "Car W", 47 },
{ "FLock", 48 }
};
it.line(0, 468, 799, 468); // bottom line
if (id(initial_data_received) == false) {
id(refreshes_skipped) = 100;
it.printf(390, 234, id(font_small_bold), C_RED, TextAlign::TOP_CENTER, "WACHT OP GEGEVENS...");
} else {
std::string stats = (id(statussen).state + "???????????????????????????????????????????????????????").c_str(); // make sure at least as many ? as needed
// windows and shutters, house outline
int hx = 400, hy = 20, w=22, h=22, g=6, s=4;
it.line(hx + 1 * w + 1 * g, hy + 7 * h + 4 * g, hx + 5 * w + 6 * g, hy + 7 * h + 4 * g); // vloer
it.line(hx + 1 * w + 1 * g, hy + 1 * h + 1 * g, hx + 1 * w + 1 * g, hy + 7 * h + 4 * g); // achtergevel
it.line(hx + 5 * w + 6 * g, hy + 0 * h + 0 * g, hx + 5 * w + 6 * g, hy + 7 * h + 4 * g); // voorgevel
it.line(hx + 1 * w + 1 * g, hy + 1 * h + 1 * g, hx + 5 * w + 6 * g, hy + 0 * h + 0 * g); // dak
it.line(hx + 1 * w + 1 * g - 1, hy + 7 * h + 4 * g - 1, hx + 5 * w + 6 * g + 1, hy + 7 * h + 4 * g - 1); // vloer
it.line(hx + 1 * w + 1 * g - 1, hy + 1 * h + 1 * g - 1, hx + 1 * w + 1 * g - 1, hy + 7 * h + 4 * g + 1); // achtergevel
it.line(hx + 5 * w + 6 * g + 1, hy + 0 * h + 0 * g - 1, hx + 5 * w + 6 * g + 1, hy + 7 * h + 4 * g + 1); // voorgevel
it.line(hx + 1 * w + 1 * g - 1, hy + 1 * h + 1 * g - 1, hx + 5 * w + 6 * g + 1, hy + 0 * h + 0 * g - 1); // dak
it.rectangle(hx + 1 * w + 2 * g + 0, hy + 1 * h + 2 * g, w, 1.5 * h, stats[d_w_s["DKRm L O"]] == 'O' ? C_RED : COLOR_ON); // linker dakkapel
it.rectangle(hx + 2 * w + 3 * g + 0, hy + 1 * h + 2 * g, w, 1.5 * h, stats[d_w_s["DKRm R O"]] == 'O' ? C_RED : COLOR_ON); // rechter dakkapel
it.rectangle(hx + 4 * w + 5 * g + 0, hy + 1 * h + 2 * g, w, 1.5 * h, stats[d_w_s["ZDRm O"]] == 'O' ? C_RED : COLOR_ON); // studeerkamer
it.rectangle(hx + 1 * w + 2 * g + 0, hy + 3 * h + 3 * g, w, 1.5 * h, stats[d_w_s["JasRm O"]] == 'O' ? C_RED : COLOR_ON); // jasper
it.rectangle(hx + 2 * w + 3 * g + 0, hy + 3 * h + 3 * g, w, 1.5 * h, stats[d_w_s["RiaRm O"]] == 'O' ? C_RED : COLOR_ON); // rianne
it.rectangle(hx + 3 * w + 4 * g + 0, hy + 3 * h + 3 * g, w, 1.5 * h, stats[d_w_s["SKRm L O"]] == 'O' ? C_RED : COLOR_ON); // slaapkamer links
it.rectangle(hx + 4 * w + 5 * g + 0, hy + 3 * h + 3 * g, w, 1.5 * h, stats[d_w_s["SKRm R O"]] == 'O' ? C_RED : COLOR_ON); // slaapkamer rechts
it.rectangle(hx + 1 * w + 2 * g + 0, hy + 5 * h + 4 * g, w, 2.0 * h, stats[d_w_s["Pui O"]] == 'O' ? C_RED : COLOR_ON); // schuifpui
it.rectangle(hx + 3 * w + 4 * g + 0, hy + 5 * h + 4 * g, w, 1.0 * h, stats[d_w_s["KeukenRm O"]] == 'O' ? C_RED : COLOR_ON); // keukenraam
it.rectangle(hx + 4 * w + 5 * g + 0, hy + 5 * h + 4 * g, w, 2.0 * h); // voordeur
it.rectangle(hx + 0 * w + 0 * g - 1, hy + 5 * h + 4 * g, w, 2.0 * h); // schuurdeur
it.circle(hx + 0.5 * w - 0 * g - 0.5 * s, hy + 1 * h + 2 * g, s); // linker dakscherm
it.circle(hx + 1.0 * w - 0 * g - 1.0 * s, hy + 1 * h + 2 * g, s); // rechter dakscherm
it.circle(hx + 5.0 * w + 7 * g + 1.0 * s, hy + 1 * h + 2 * g, s); // studeerkamerscherm links
it.circle(hx + 5.5 * w + 7 * g + 0.5 * s, hy + 1 * h + 2 * g, s); // studeerkamerscherm rechts
it.circle(hx + 5.0 * w + 7 * g + 1.0 * s, hy + 3 * h + 3 * g, s); // slaapkamerscherm links
it.circle(hx + 5.5 * w + 7 * g + 0.5 * s, hy + 3 * h + 3 * g, s); // slaapkamerscherm midden
it.circle(hx + 6.0 * w + 7 * g + 0.0 * s, hy + 3 * h + 3 * g, s); // slaapkamerscherm rechts
it.circle(hx + 5.0 * w + 7 * g + 1.0 * s, hy + 5 * h + 4 * g, s); // keukenscherm
if (stats[d_w_s["RolSch WGrens"]] == 'W') {
it.filled_circle(hx + 0.5 * w - 0 * g - 0.5 * s, hy + 1 * h + 2 * g, s, C_RED); // linker dakscherm
it.filled_circle(hx + 1.0 * w - 0 * g - 1.0 * s, hy + 1 * h + 2 * g, s, C_RED); // rechter dakscherm
it.filled_circle(hx + 5.0 * w + 7 * g + 1.0 * s, hy + 1 * h + 2 * g, s, C_RED); // studeerkamerscherm links
it.filled_circle(hx + 5.5 * w + 7 * g + 0.5 * s, hy + 1 * h + 2 * g, s, C_RED); // studeerkamerscherm rechts
it.filled_circle(hx + 5.0 * w + 7 * g + 1.0 * s, hy + 3 * h + 3 * g, s, C_RED); // slaapkamerscherm links
it.filled_circle(hx + 5.5 * w + 7 * g + 0.5 * s, hy + 3 * h + 3 * g, s, C_RED); // slaapkamerscherm midden
it.filled_circle(hx + 6.0 * w + 7 * g + 0.0 * s, hy + 3 * h + 3 * g, s, C_RED); // slaapkamerscherm rechts
}
if (stats[d_w_s["KnikSch WGrens"]] == 'W')
it.filled_circle(hx + 5.0 * w + 7 * g + 1.0 * s, hy + 5 * h + 4 * g, s, C_RED); // keukenscherm
if (stats[d_w_s["L DKRm W"]] == 'O' || stats[d_w_s["L DKRm"]] == 'O') // linker dakkapel
it.filled_rectangle(hx + 1 * w + 2 * g + 0, hy + 1 * h + 2 * g, w, (stats[d_w_s["L DKRm W"]] == 'O' ? 1.5 : 0.5) * h, stats[d_w_s["DKRm L S"]] == 'S' ? C_RED : COLOR_ON);
if (stats[d_w_s["DKRm L O"]] == 'O')
it.filled_circle(hx + 1.5 * w + 2 * g + 0, hy + 1.75 * h + 2 * g, w / 2 - s, C_RED);
if (stats[d_w_s["R DKRm W"]] == 'O' || stats[d_w_s["R DKRm"]] == 'O') // rechter dakkapel
it.filled_rectangle(hx + 2 * w + 3 * g + 0, hy + 1 * h + 2 * g, w, (stats[d_w_s["R DKRm W"]] == 'O' ? 1.5 : 0.5) * h, stats[d_w_s["DKRm R S"]] == 'S' ? C_RED : COLOR_ON);
if (stats[d_w_s["DKRm R O"]] == 'O')
it.filled_circle(hx + 2.5 * w + 3 * g + 0, hy + 1.75 * h + 2 * g, w / 2 - s, C_RED);
if (stats[d_w_s["ZDRm"]] == 'O') // studeerkamer
it.filled_rectangle(hx + 4 * w + 5 * g + 0, hy + 1 * h + 2 * g, w, 1.5 * h, stats[d_w_s["ZDRm S"]] == 'S' ? C_RED : COLOR_ON);
if (stats[d_w_s["ZDRm O"]] == 'O')
it.filled_circle(hx + 4.5 * w + 5 * g + 0, hy + 1.75 * h + 2 * g, w / 2 - s, C_RED);
if (stats[d_w_s["JasRm"]] == 'O') // jasper
it.filled_rectangle(hx + 1 * w + 2 * g + 0, hy + 3 * h + 3 * g, w, 1.5 * h, stats[d_w_s["JasRm S"]] == 'S' ? C_RED : COLOR_ON);
if (stats[d_w_s["JasRm O"]] == 'O')
it.filled_circle(hx + 1.5 * w + 2 * g + 0, hy + 3.75 * h + 3 * g, w / 2 - s, C_RED);
if (stats[d_w_s["RiaRm"]] == 'O') // rianne
it.filled_rectangle(hx + 2 * w + 3 * g + 0, hy + 3 * h + 3 * g, w, 1.5 * h, stats[d_w_s["RiaRm S"]] == 'S' ? C_RED : COLOR_ON);
if (stats[d_w_s["RiaRm O"]] == 'O')
it.filled_circle(hx + 2.5 * w + 3 * g + 0, hy + 3.75 * h + 3 * g, w / 2 - s, C_RED);
if (stats[d_w_s["L SKRm W"]] == 'O' || stats[d_w_s["L SKRm"]] == 'O') // slaapkamer links
it.filled_rectangle(hx + 3 * w + 4 * g + 0, hy + 3 * h + 3 * g, w, (stats[d_w_s["L SKRm W"]] == 'O' ? 1.5 : 0.5) * h, stats[d_w_s["SKRm L S"]] == 'S' ? C_RED : COLOR_ON);
if (stats[d_w_s["SKRm L O"]] == 'O')
it.filled_circle(hx + 3.5 * w + 4 * g + 0, hy + 3.75 * h + 3 * g, w / 2 - s, C_RED);
if (stats[d_w_s["R SKRm W"]] == 'O' || stats[d_w_s["R SKRm"]] == 'O') // slaapkamer rechts
it.filled_rectangle(hx + 4 * w + 5 * g + 0, hy + 3 * h + 3 * g, w, (stats[d_w_s["R SKRm W"]] == 'O' ? 1.5 : 0.5) * h, stats[d_w_s["SKRm R S"]] == 'S' ? C_RED : COLOR_ON);
if (stats[d_w_s["SKRm R O"]] == 'O')
it.filled_circle(hx + 4.5 * w + 5 * g + 0, hy + 3.75 * h + 3 * g, w / 2 - s, C_RED);
if (stats[d_w_s["Pui"]] == 'O') // schuifpui
it.filled_rectangle(hx + 1 * w + 2 * g + 0, hy + 5 * h + 4 * g, w, 2.0 * h, stats[d_w_s["Pui S"]] == 'S' ? C_RED : COLOR_ON);
if (stats[d_w_s["Pui O"]] == 'O')
it.filled_circle(hx + 1.5 * w + 2 * g + 0, hy + 5.75 * h + 4 * g, w / 2 - s, C_RED);
if (stats[d_w_s["KeukenRm"]] == 'O') // keukenraam
it.filled_rectangle(hx + 3 * w + 4 * g + 0, hy + 5 * h + 4 * g, w, 1.0 * h, stats[d_w_s["KeukenRm S"]] == 'S' ? C_RED : COLOR_ON);
if (stats[d_w_s["KeukenRm O"]] == 'O')
it.filled_circle(hx + 3.5 * w + 4 * g + 0, hy + 5.5 * h + 4 * g, w / 2 - s, C_RED);
if (stats[d_w_s["Voord"]] == 'O') // voordeur
it.filled_rectangle(hx + 4 * w + 5 * g + 0, hy + 5 * h + 4 * g, w, 2.0 * h);
if (stats[d_w_s["FLock"]] != '-') { // voordeur
it.filled_circle(hx + 4.5 * w + 5 * g + 0, hy + 6 * h + 4 * g, w / 2 - s, stats[d_w_s["FLock"]] == 'L' ? (stats[d_w_s["Voord"]] == 'O' ? C_WHT : COLOR_ON) : C_RED);
it.filled_circle(hx + 4.5 * w + 5 * g + 0, hy + 6 * h + 4 * g, w / 2 - s * 2, stats[d_w_s["Voord"]] == 'O' ? C_RED : C_WHT);
}
if (stats[d_w_s["Schuur"]] == 'O') // schuurdeur
it.filled_rectangle(hx + 0 * w + 0 * g - 1, hy + 5 * h + 4 * g, w, 2.0 * h);
if (stats[d_w_s["L DkSch"]] != '-') // linker dakscherm
it.filled_rectangle(hx + 0.5 * w - 0 * g - 0.5 * s - 1, hy + 1 * h + 2 * g, s, 1.5 * h, stats[d_w_s["L DkSch"]] == 'C' ? COLOR_ON : C_RED);
if (stats[d_w_s["R DkSch"]] != '-') // rechter dakscherm
it.filled_rectangle(hx + 1.0 * w - 0 * g - 1.0 * s - 1, hy + 1 * h + 2 * g, s, 1.5 * h, stats[d_w_s["R DkSch"]] == 'C' ? COLOR_ON : C_RED);
if (stats[d_w_s["ZDSch L"]] != '-') // studeerkamerscherm links
it.filled_rectangle(hx + 5.0 * w + 7 * g + 0.0 * s + 1, hy + 1 * h + 2 * g, s, 1.5 * h, stats[d_w_s["ZDSch L"]] == 'C' ? COLOR_ON : C_RED);
if (stats[d_w_s["ZDSch R"]] != '-') // studeerkamerscherm rechts
it.filled_rectangle(hx + 5.5 * w + 7 * g - 0.0 * s + 1, hy + 1 * h + 2 * g, s, 1.5 * h, stats[d_w_s["ZDSch R"]] == 'C' ? COLOR_ON : C_RED);
if (stats[d_w_s["SKSch L"]] != '-') // slaapkamerscherm links
it.filled_rectangle(hx + 5.0 * w + 7 * g + 0.0 * s + 1, hy + 3 * h + 3 * g, s, 1.5 * h, stats[d_w_s["SKSch L"]] == 'C' ? COLOR_ON : C_RED);
if (stats[d_w_s["SKSch M"]] != '-') // slaapkamerscherm midden
it.filled_rectangle(hx + 5.5 * w + 7 * g - 0.5 * s + 1, hy + 3 * h + 3 * g, s, 1.5 * h, stats[d_w_s["SKSch M"]] == 'C' ? COLOR_ON : C_RED);
if (stats[d_w_s["SKSch R"]] != '-') // slaapkamerscherm rechts
it.filled_rectangle(hx + 6.0 * w + 7 * g - 1.0 * s + 1, hy + 3 * h + 3 * g, s, 1.5 * h, stats[d_w_s["SKSch R"]] == 'C' ? COLOR_ON : C_RED);
if (stats[d_w_s["KeukenSch"]] != '-') { // keukenscherm
it.filled_rectangle(hx + 5.0 * w + 7 * g + 0.5 * s + 0.0 * h + 1, hy + 5 * h + 4 * g + 0 + 1, 0.5 * h, s, stats[d_w_s["KeukenSch"]] == 'C' ? COLOR_ON : C_RED);
it.filled_rectangle(hx + 5.0 * w + 7 * g + 0.5 * s + 0.5 * h + 1, hy + 5 * h + 4 * g + 1 + 1, 0.5 * h, s, stats[d_w_s["KeukenSch"]] == 'C' ? COLOR_ON : C_RED);
it.filled_rectangle(hx + 5.0 * w + 7 * g + 0.5 * s + 1.0 * h + 1, hy + 5 * h + 4 * g + 2 + 1, 0.5 * h, s, stats[d_w_s["KeukenSch"]] == 'C' ? COLOR_ON : C_RED);
}
// Weather Section
int wo_x = 50, wo_y = 50, ho_x = 790, hsp = 100, vsp1 = 60, vsp2 = 97, vsp3 = 140;
it.printf(wo_x + hsp * 0.50, wo_y, id(font_mdi_large), C_RED, TextAlign::CENTER, "%s", weather_icon_map[id(weather_condition_now).state.c_str()].c_str());
it.printf(wo_x + hsp * 2.85, wo_y, id(font_large_bold), id(weather_temperature).state < 0 ? C_RED : COLOR_ON, TextAlign::CENTER_RIGHT, "%1.1f", id(weather_temperature).state);
it.printf(wo_x + hsp * 3.30, wo_y + 8, id(font_medium_bold), id(weather_temperature).state < 0 ? C_RED : COLOR_ON, TextAlign::BOTTOM_RIGHT, "°C");
it.printf(wo_x, wo_y + vsp1, id(font_smaller_bold), TextAlign::CENTER, "%s", id(weather_timestamp_0).state.c_str());
it.printf(wo_x, wo_y + vsp2, id(font_mdi_medium), C_RED, TextAlign::CENTER, "%s", weather_icon_map[id(weather_condition_0).state.c_str()].c_str());
it.printf(wo_x, wo_y + vsp3, id(font_small_bold), TextAlign::CENTER, "%1.0f°C", id(weather_temperature_0).state);
it.printf(wo_x + hsp, wo_y + vsp1, id(font_smaller_bold), TextAlign::CENTER, "%s", id(weather_timestamp_1).state.c_str());
it.printf(wo_x + hsp, wo_y + vsp2, id(font_mdi_medium), C_RED, TextAlign::CENTER, "%s", weather_icon_map[id(weather_condition_1).state.c_str()].c_str());
it.printf(wo_x + hsp, wo_y + vsp3, id(font_small_bold), TextAlign::CENTER, "%1.0f°C", id(weather_temperature_1).state);
it.printf(wo_x + hsp * 2, wo_y + vsp1, id(font_smaller_bold), TextAlign::CENTER, "%s", id(weather_timestamp_2).state.c_str());
it.printf(wo_x + hsp * 2, wo_y + vsp2, id(font_mdi_medium), C_RED, TextAlign::CENTER, "%s", weather_icon_map[id(weather_condition_2).state.c_str()].c_str());
it.printf(wo_x + hsp * 2, wo_y + vsp3, id(font_small_bold), TextAlign::CENTER, "%1.0f°C", id(weather_temperature_2).state);
it.printf(wo_x + hsp * 3, wo_y + vsp1, id(font_smaller_bold), TextAlign::CENTER, "%s", id(weather_timestamp_3).state.c_str());
it.printf(wo_x + hsp * 3, wo_y + vsp2, id(font_mdi_medium), C_RED, TextAlign::CENTER, "%s", weather_icon_map[id(weather_condition_3).state.c_str()].c_str());
it.printf(wo_x + hsp * 3, wo_y + vsp3, id(font_small_bold), TextAlign::CENTER, "%1.0f°C", id(weather_temperature_3).state);
// rain graph
std::string gdata = id(rain_graph).state;
char *token = strtok (&gdata[0],";");
std::string t1 = str_until(token == NULL ? "??:??" : token,';'); token = strtok(NULL, ";");
std::string t2 = str_until(token == NULL ? "??:??" : token,';'); token = strtok(NULL, ";");
std::string t3 = str_until(token == NULL ? "??:??" : token,';'); token = strtok(NULL, ";");
std::string t4 = str_until(token == NULL ? "??:??" : token,';'); token = strtok(NULL, ";");
std::string t5 = str_until(token == NULL ? "??:??" : token,';'); token = strtok(NULL, ";");
auto g_low = parse_number<float>(str_until(token == NULL ? "0.1" : token,';')).value_or(0.0f); token = strtok(NULL, ";");
auto g_med = parse_number<float>(str_until(token == NULL ? "0.1" : token,';')).value_or(0.0f); token = strtok(NULL, ";");
auto g_hgh = parse_number<float>(str_until(token == NULL ? "0.1" : token,';')).value_or(0.0f); token = strtok(NULL, ";");
auto g_max = parse_number<float>(str_until(token == NULL ? "0.1" : token,';')).value_or(0.0f) * 1.1f; token = strtok(NULL, ";");
int g_x = 11, g_y = 250, g_w = 5, g_h = 80, g_c = 0, g_t = 5;
it.filled_rectangle(g_x, g_y + g_h - 1, 73 * g_w, 2, COLOR_ON); // x-axis
it.filled_rectangle(g_x - 1, g_y, 2, g_h, COLOR_ON); // y-axis
float prev = parse_number<float>(str_until(token == NULL ? "0.1" : token,';')).value_or(0.0f) * g_h / g_max; token = strtok(NULL, ";");
if (prev != 0) it.filled_rectangle(g_x + g_c, g_y + g_h - prev, g_w, prev, C_RED);
g_c += g_w;
while (token != NULL) {
auto g_r = parse_number<float>(str_until(token == NULL ? "0.1" : token,';')).value_or(0.0f) * g_h / g_max; token = strtok(NULL, ";");
float itv = (2 * prev + g_r) / 3;
if (itv != 0) it.filled_rectangle(g_x + g_c, g_y + g_h - itv, g_w, itv, C_RED);
g_c += g_w;
itv = (prev + 2 * g_r) / 3;
if (itv != 0) it.filled_rectangle(g_x + g_c, g_y + g_h - itv, g_w, itv, C_RED);
g_c += g_w;
if (g_r != 0) it.filled_rectangle(g_x + g_c, g_y + g_h - g_r, g_w, g_r, C_RED);
g_c += g_w;
prev = g_r;
}
it.rectangle(g_x - 1, g_y + g_h - g_hgh * g_h / g_max, g_c, 1); // high
it.rectangle(g_x - 1, g_y + g_h - g_med * g_h / g_max, g_c, 1); // medium
it.rectangle(g_x - 1, g_y + g_h - g_low * g_h / g_max, g_c, 1); // low
it.rectangle(g_x - 1, g_y + g_h, g_c, 1); // bottom
it.printf(g_x + 0.00 * g_c + 0, g_y + g_h + g_t, id(font_tiny_book), COLOR_ON, TextAlign::TOP_LEFT, "%s", t1.c_str());
it.printf(g_x + 0.25 * g_c + 7, g_y + g_h + g_t, id(font_tiny_book), COLOR_ON, TextAlign::TOP_CENTER, "%s", t2.c_str()); // smuggle bit more right because first time differs
it.printf(g_x + 0.50 * g_c + 0, g_y + g_h + g_t, id(font_tiny_book), COLOR_ON, TextAlign::TOP_CENTER, "%s", t3.c_str());
it.printf(g_x + 0.75 * g_c - 7, g_y + g_h + g_t, id(font_tiny_book), COLOR_ON, TextAlign::TOP_CENTER, "%s", t4.c_str());
it.printf(g_x + 1.00 * g_c + 0, g_y + g_h + g_t, id(font_tiny_book), COLOR_ON, TextAlign::TOP_RIGHT, "%s", t5.c_str()); // smuggle bit more left because last time differs
// Car Section
it.printf(ho_x - hsp * 0.45, wo_y, id(font_large_bold), id(room_temperature).state < 0 ? C_RED : COLOR_ON, TextAlign::CENTER_RIGHT, "%1.1f", id(room_temperature).state);
it.printf(ho_x - hsp * 0.00, wo_y + 8, id(font_medium_bold), id(room_temperature).state < 0 ? C_RED : COLOR_ON, TextAlign::BOTTOM_RIGHT, "°C");
it.printf(ho_x - hsp * 0.45, wo_y + vsp2 + 0, id(font_large_book), id(car_battery_perc).state <= 45 ? C_RED : COLOR_ON, TextAlign::BOTTOM_RIGHT, "%1.0f", id(car_battery_perc).state);
it.printf(ho_x - hsp * 0.00, wo_y + vsp2 - 5, id(font_medium_bold), id(car_battery_perc).state <= 45 ? C_RED : COLOR_ON, TextAlign::BOTTOM_RIGHT, "%%");
it.printf(ho_x - hsp * 0.45, wo_y + vsp3 + 19, id(font_large_book), id(car_km_range).state < 100 ? C_RED : COLOR_ON, TextAlign::BOTTOM_RIGHT, "%1.0f", id(car_km_range).state);
it.printf(ho_x - hsp * 0.00, wo_y + vsp3 + 14, id(font_small_bold), id(car_km_range).state < 100 ? C_RED : COLOR_ON, TextAlign::BOTTOM_RIGHT, "km");
int b_y = 225, b_x = 10, b_h = 8, l_h = 2, b_l = 800 - 2 * b_x, t_h = 12,
b_f = b_l * id(car_battery_perc).state / 100, b_t = b_l * id(car_target_perc).state / 100;
it.rectangle(b_x, b_y + (b_h - l_h) / 2, b_l, l_h, id(car_battery_perc).state <= 45 ? COLOR_ON : C_RED); // thin line
it.filled_rectangle(b_x + (b_l - b_f) / 2, b_y, b_f, b_h, id(car_battery_perc).state <= 45 ? C_RED : COLOR_ON); // battery percentage bar
it.filled_rectangle(b_x + (b_l - b_t) / 2, b_y + (b_h - t_h) / 2, l_h, t_h, id(car_battery_perc).state <= 45 ? COLOR_ON : C_RED); // target perc markers
it.filled_rectangle(b_x + (b_l + b_t) / 2, b_y + (b_h - t_h) / 2, l_h, t_h, id(car_battery_perc).state <= 45 ? COLOR_ON : C_RED);
std::string cstate = id(car_charge_status).state.c_str(), bat = "", car = "";
Color c_col = COLOR_ON, b_col = COLOR_ON;
if (cstate == "?") { bat = "connection"; b_col = C_RED; }
else if (cstate == "Laden") {
if (id(car_battery_perc).state <= 35) { bat = "battery-charging-outline"; b_col = C_RED; }
else if (id(car_battery_perc).state <= 45) { bat = "battery-charging-low"; b_col = C_RED; }
else if (id(car_battery_perc).state <= 55) { bat = "battery-charging-low"; }
else if (id(car_battery_perc).state <= 75) { bat = "battery-charging-medium"; }
else if (id(car_battery_perc).state <= 95) { bat = "battery-charging-high"; }
else bat = "battery-charging-100";
} else if (cstate == "Opgeladen") {
bat = "power-plug";
// if (id(car_battery_perc).state <= 35) { bat = "battery-outline"; b_col = C_RED; }
// else if (id(car_battery_perc).state <= 45) { bat = "battery-low"; b_col = C_RED; }
// else if (id(car_battery_perc).state <= 55) { bat = "battery-low"; }
// else if (id(car_battery_perc).state <= 75) { bat = "battery-medium"; }
// else if (id(car_battery_perc).state <= 95) { bat = "battery-high"; }
// else bat = "battery";
} else if (cstate == "Verbroken") { bat = "connection"; b_col = C_RED; }
else if (cstate == "Aangesloten") { bat = "power-plug-outline"; }
if (stats[d_w_s["Car D"]] == 'O') { car = "lock-open-outline"; c_col = C_RED; }
else if (stats[d_w_s["Car D"]] == 'O') { car = "car-wash"; c_col = C_RED; }
if (bat != "")
it.printf(ho_x - hsp * 1.5, wo_y + vsp2 - 5, id(font_mdi_title), b_col, TextAlign::BOTTOM_RIGHT, "%s", car_icon_map[bat].c_str());
if (car != "")
it.printf(ho_x - hsp * 1.5, wo_y + vsp3 + 14, id(font_mdi_title), c_col, TextAlign::BOTTOM_RIGHT, "%s", car_icon_map[car].c_str());
// calendar
int cal_x = 405, cal_y = 255, cal_dx = 30, cl = 0;
if (id(apt_gezin).state != "")
it.printf(cal_x, cal_y + cl++ * cal_dx, id(font_smaller_bold), TextAlign::TOP_LEFT, "%s", id(apt_gezin).state.c_str());
if (id(apt_edwin).state != "")
it.printf(cal_x, cal_y + cl++ * cal_dx, id(font_smaller_bold), TextAlign::TOP_LEFT, "%s", id(apt_edwin).state.c_str());
if (id(apt_fleur).state != "")
it.printf(cal_x, cal_y + cl++ * cal_dx, id(font_smaller_bold), TextAlign::TOP_LEFT, "%s", id(apt_fleur).state.c_str());
if (id(apt_rianne).state != "")
it.printf(cal_x, cal_y + cl++ * cal_dx, id(font_smaller_bold), TextAlign::TOP_LEFT, "%s", id(apt_rianne).state.c_str());
if (id(apt_jasper).state != "")
it.printf(cal_x, cal_y + cl++ * cal_dx, id(font_smaller_bold), TextAlign::TOP_LEFT, "%s", id(apt_jasper).state.c_str());
it.filled_rectangle(790, cal_y, 10, 5 * cal_dx, C_WHT); // replace by clipping
// Solar Section
int sol_y = (cal_y + cl * cal_dx) > 350 ? 430 : 420;
float prod = id(solar_production_today).state, fcast = id(solar_forecast_today).state;
it.printf(prod >= 20 ? 385 : 390, sol_y - 2, id(font_mdi_title), C_RED, TextAlign::BOTTOM_LEFT, "%s", car_icon_map["solar-power"].c_str());
it.printf(520, sol_y + 10, id(font_large_bold), COLOR_ON, TextAlign::BOTTOM_CENTER, prod > 0.005 && prod < 0.1 ? "%1.2f" : "%1.1f", prod);
it.printf(598, sol_y + 5, id(font_large_book), COLOR_ON, TextAlign::BOTTOM_LEFT, "/");
it.printf(ho_x - hsp * 0.60, sol_y + 5, id(font_large_book), COLOR_ON, TextAlign::BOTTOM_RIGHT, "%1.1f", fcast);
it.printf(ho_x + hsp * 0.05, sol_y, id(font_small_bold), COLOR_ON, TextAlign::BOTTOM_RIGHT, "kWh");
// travel section
it.printf(10, sol_y - 2, id(font_mdi_title), C_RED, TextAlign::BOTTOM_LEFT, "%s", car_icon_map["car-clock"].c_str());
it.printf(145, sol_y + 5, id(font_large_book), id(reistijd_leo_kanner).state >= 40 ? C_RED : COLOR_ON, TextAlign::BOTTOM_RIGHT, "%1.0f", id(reistijd_leo_kanner).state);
it.printf(150, sol_y, id(font_small_bold), COLOR_ON, TextAlign::BOTTOM_LEFT, "min");
it.printf(10, 458, id(font_small_bold), TextAlign::BOTTOM_LEFT, "%s", id(next_meal).state.c_str());
char str[17];
time_t currTime = id(homeassistant_time).now().timestamp;
strftime(str, sizeof(str), "%H:%M", localtime(&currTime));
it.printf(798, 463, id(font_tiny_book), id(refreshes_skipped) >= 15 ? C_RED : COLOR_ON, TextAlign::BOTTOM_RIGHT, "Laatste update: %s", str);
}
Dear Kurmu, I am interested how you solved to display the electricity prices for the next hours. YAML snippets are welcome. Many thanks
Hey! Sorry I haven’t replied. Anyway, here is my yaml configuration.
esphome:
name: "epaper-display-01"
on_boot:
priority: 200.0
then:
- component.update: eink_display
- wait_until:
condition:
lambda: 'return id(data_updated) == true;'
# Wait a bit longer so all the items are received
- delay: 5s
- logger.log: "Antureiden alustavat tiedot vastaanotettu: Päivitetään näyttö..."
- lambda: 'id(initial_data_received) = true;'
- script.execute: update_screen
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
ota:
# Enable sun integration
sun:
latitude: 60.1
longitude: 24.4
# Buttons for controlling display
button:
- platform: shutdown
name: "ePaper 01 - Shutdown"
- platform: restart
name: "ePaper 01 - Restart"
- platform: template
name: "ePaper 01 - Refresh Screen"
entity_category: config
on_press:
- script.execute: update_screen
# Global variables for detecting if the display needs to be refreshed. (Thanks @paviro!)
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'
# Script for updating screen - Refresh display and publish refresh count and time. (Thanks @paviro!)
script:
- id: update_screen
then:
- lambda: 'id(data_updated) = false;'
- component.update: eink_display
- lambda: 'id(recorded_display_refresh) += 1;'
- lambda: 'id(display_last_update).publish_state(id(homeassistant_time).now().timestamp);'
# Check whether the display needs to be refreshed every minute,
# based on whether new data is received or motion is detected. (Thanks @paviro!)
time:
- platform: homeassistant
id: homeassistant_time
# Wifi information
wifi:
ssid: "WiFi"
password: "5CDH4ZrN141I"
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Epaper-Display-01"
password: "5CDH4ZrN141I"
# Include custom fonts
font:
- file: 'fonts/GothamRnd-Book.ttf'
id: font_small_book
size: 18
glyphs: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'X', 'Y', 'Z', 'Å', 'Ä', 'Ö', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', '-', ' ', '°', '.','m', '%']
- file: 'fonts/GothamRnd-Bold.ttf'
id: font_large_bold
size: 108
glyphs: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'X', 'Y', 'Z', 'Å', 'Ä', 'Ö', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', '-', ' ', '°', '.']
- file: 'fonts/GothamRnd-Bold.ttf'
id: font_title
size: 54
glyphs: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'X', 'Y', 'Z', 'Å', 'Ä', 'Ö', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', '-', ' ', '°', '.']
- file: 'fonts/GothamRnd-Bold.ttf'
id: font_medium_bold
size: 30
glyphs: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'X', 'Y', 'Z', 'Å', 'Ä', 'Ö', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', '-', ' ', '°', '.']
- file: 'fonts/GothamRnd-Bold.ttf'
id: font_small_bold
size: 18
glyphs: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'X', 'Y', 'Z', 'Å', 'Ä', 'Ö', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'x', 'y', 'z', 'ä', 'ö', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', '-', ' ', '°', '.', '%', '/', ',', 'W']
- 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
- "\U000F0F61" # mdi-moon-first-quarter
- "\U000F0F62" # mdi-moon-full
- "\U000F0F63" # mdi-moon-last-quarter
- "\U000F0F64" # mdi-moon-new
- "\U000F0F65" # mdi-moon-waning-crescent
- "\U000F0F66" # mdi-moon-waning-gibbous
- "\U000F0F67" # mdi-moon-waxing-crescent
- "\U000F0F68" # mdi-moon-waxing-gibbous
- "\U000F050F" # lämpötila
- "\U000F029A" # ilmanpaine
- "\U000F058E" # kosteus
- "\U000F156D" # sofa
- "\U000F0FD1" # bed
- "\U000F181D" # countertop
- "\U000F09A0" # shower
- "\U000F140C" # lightning-bolt-outlin
- "\U000F1904" # home-lightning-bolt-outline
- "\U000F1A58" # meter-electric-outline
- "\U000F0E02" # thermometer-chevron-down
- "\U000F0E03" # thermometer-chevron-up
- file: 'fonts/materialdesignicons-webfont.ttf'
id: font_mdi_medium
size: 36
glyphs: *mdi-weather-glyphs
# Include Images
image:
- file: "images/majakka_s.png"
id: image_majakka
# type: BINARY
# Check if motion is detected in the living room.
binary_sensor:
- platform: homeassistant
entity_id: binary_sensor.epaper_display_01_motion_detected
id: motion_detected
# SENSORS
sensor:
# Create sensors for monitoring Weatherman remotely.
- platform: template
name: "ePaper_01 - Display Last Update"
device_class: timestamp
entity_category: "diagnostic"
id: display_last_update
- platform: template
name: "ePaper_01 - Recorded Display Refresh"
accuracy_decimals: 0
unit_of_measurement: "Refreshes"
state_class: "total_increasing"
entity_category: "diagnostic"
lambda: 'return id(recorded_display_refresh);'
- platform: wifi_signal
name: "ePaper_01 - WiFi Signal Strength"
id: wifisignal
unit_of_measurement: "dBm"
entity_category: "diagnostic"
update_interval: 60s
- platform: sun
name: Sun Elevation
type: elevation
id: solar_angle
#Valoisuusanturi P34
- platform: adc
pin: 34
name: "ePaper valoisuus"
update_interval: 30s
device_class: illuminance
unit_of_measurement: lx
accuracy_decimals: 0
filters:
- calibrate_linear:
- 0 -> 0
- 0.14 -> 0
- 1.1 -> 1.1
- lambda: |-
if (id(solar_angle).state > 2) {
return (x / 10000.0) * 2000000.0;
} else {
return 0.0;
}
- sliding_window_moving_average:
window_size: 20
send_every: 3
#DHT22 P32
- platform: dht
pin: 32
model: DHT22
temperature:
name: "ePaper lämpötila"
filters:
- multiply: 1
humidity:
name: "ePaper kosteus"
update_interval: 60s
# Sensor from HA
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: weather_temp_low
id: weather_temp_low
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: weather_temp_high
id: weather_temp_high
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: weather_temperature_0
id: weather_temperature_0
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: weather_temperature_1
id: weather_temperature_1
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: weather_temperature_2
id: weather_temperature_2
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: weather_temperature_3
id: weather_temperature_3
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: weather_temperature_4
id: weather_temperature_4
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: ulkolampotila
id: ulkolampotila
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: kosteus
id: kosteus
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: ilmanpaine
id: ilmanpaine
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: tuuli
id: tuuli
on_value:
then:
- lambda: 'id(data_updated) = true;'
# Room sensors
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: mh_lampotila
id: mh_lampotila
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: mh_kosteus
id: mh_kosteus
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: mh_valoisuus
id: mh_valoisuus
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: mh_pm25
id: mh_pm25
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: oh_lampotila
id: oh_lampotila
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: oh_kosteus
id: oh_kosteus
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: kph_lampotila
id: kph_lampotila
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: kph_kosteus
id: kph_kosteus
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: keittio_lampotila
id: keittio_lampotila
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: keittio_valoisuus
id: keittio_valoisuus
on_value:
then:
- lambda: 'id(data_updated) = true;'
#Nordpool sensors
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: nordpool_current
id: nordpool_current
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: nordpool_min
id: nordpool_min
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: nordpool_avg
id: nordpool_avg
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: nordpool_max
id: nordpool_max
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: nordpool_1h
id: nordpool_1h
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: nordpool_2h
id: nordpool_2h
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: nordpool_3h
id: nordpool_3h
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: nordpool_4h
id: nordpool_4h
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: nordpool_5h
id: nordpool_5h
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: nordpool_6h
id: nordpool_6h
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: nordpool_7h
id: nordpool_7h
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: total_hourly_energy
id: total_hourly_energy
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: total_daily_energy
id: total_daily_energy
on_value:
then:
- lambda: 'id(data_updated) = true;'
text_sensor:
- platform: homeassistant
entity_id: weather.kotkanpesa_hourly
id: weather_state
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: weather_condition_now
id: weather_condition_now
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: weather_condition_0
id: weather_condition_0
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: weather_timestamp_0
id: weather_timestamp_0
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: weather_condition_1
id: weather_condition_1
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: weather_timestamp_1
id: weather_timestamp_1
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: weather_condition_2
id: weather_condition_2
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: weather_timestamp_2
id: weather_timestamp_2
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: weather_condition_3
id: weather_condition_3
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: weather_timestamp_3
id: weather_timestamp_3
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: weather_condition_4
id: weather_condition_4
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: weather_timestamp_4
id: weather_timestamp_4
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: tuuli_suunta
id: tuuli_suunta
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: nordpool_timestamp_0
id: nordpool_timestamp_0
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: nordpool_timestamp_1
id: nordpool_timestamp_1
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: nordpool_timestamp_2
id: nordpool_timestamp_2
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: nordpool_timestamp_3
id: nordpool_timestamp_3
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: nordpool_timestamp_4
id: nordpool_timestamp_4
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: nordpool_timestamp_5
id: nordpool_timestamp_5
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: nordpool_timestamp_6
id: nordpool_timestamp_6
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: nordpool_timestamp_7
id: nordpool_timestamp_7
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.epaper_data
attribute: nordpool_text
id: nordpool_text
on_value:
then:
- lambda: 'id(data_updated) = true;'
## Sunrise
- platform: sun
type: sunrise
id: sun_sunrise
format: "%H:%M"
## Sunset
- platform: sun
type: sunset
id: sun_sunset
format: "%H:%M"
# Define colors
# This design is white on black so this is necessary.
color:
- id: color_bg
red: 0%
green: 0%
blue: 0%
white: 50%
- id: color_text
red: 0%
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
id: eink_display
cs_pin: 15
dc_pin: 27
busy_pin:
number: 25
inverted: True
reset_pin: 26
reset_duration: 2ms
model: 7.50inV2
update_interval: never
# auto_clear_enabled: false
rotation: 90°
lambda: |-
// Map weather states to MDI characters.
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"},
{"clear-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"},
};
// Fill background.
// it.fill(color_bg);
// # Show loading screen before data is received.
if (id(initial_data_received) == false) {
it.printf(240, 390, id(font_small_bold), TextAlign::TOP_CENTER, "ODOTETAAN TIETOJA...");
} else {
// # Topic section, x (vaaka), y (pysty)
// it.image(0, 88, id(title_weather));
it.printf(240, 15, id(font_title), TextAlign::TOP_CENTER, "KIRKKONUMMI");
// #Print day of the month
it.strftime(240, 75, id(font_small_bold), TextAlign::TOP_CENTER, "%d.%m.%Y", id(homeassistant_time).now());
//# Print sunrise and sunset
it.printf(60, 65, id(font_mdi_medium), TextAlign::TOP_CENTER, "\U000F059C");
it.printf(110, 75, id(font_small_bold), TextAlign::TOP_CENTER, "%s", id(sun_sunrise).state.c_str());
it.printf(360, 65, id(font_mdi_medium), TextAlign::TOP_CENTER, "\U000F059B");
it.printf(410, 75, id(font_small_bold), TextAlign::TOP_CENTER, "%s", id(sun_sunset).state.c_str());
// # line
it.rectangle(5, 100, 700, 1);
// # Weather now
it.printf(60, 100, id(font_mdi_large), TextAlign::TOP_CENTER, "%s", weather_icon_map[id(weather_condition_now).state.c_str()].c_str());
it.printf(270, 100, id(font_large_bold), TextAlign::TOP_CENTER, "%2.0f°C", id(ulkolampotila).state);
//# Temp high and low, moisture
it.printf(220, 207, id(font_mdi_medium), TextAlign::TOP_CENTER, "\U000F0E02");
it.printf(265, 217, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f°C", id(weather_temp_low).state);
it.printf(330, 207, id(font_mdi_medium), TextAlign::TOP_CENTER, "\U000F0E03");
it.printf(375, 217, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f°C", id(weather_temp_high).state);
// # Wind and pressure
it.printf(220, 252, id(font_mdi_medium), TextAlign::TOP_CENTER, "\U000F059D");
it.printf(270, 262, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0fm/s", id(tuuli).state);
it.printf(355, 262, id(font_small_bold), TextAlign::TOP_CENTER, "%s", id(tuuli_suunta).state.c_str());
// # Pressure and moisture
it.printf(220, 297, id(font_mdi_medium), TextAlign::TOP_CENTER, "\U000F029A");
it.printf(280, 307, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f hPa", id(ilmanpaine).state);
it.printf(345, 297, id(font_mdi_medium), TextAlign::TOP_CENTER, "\U000F058E");
it.printf(375, 307, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f", id(kosteus).state);
it.printf(397, 307, id(font_small_bold), TextAlign::TOP_CENTER, "%s", "%");
// # Weather next hour
it.printf(175, 342, id(font_small_book), TextAlign::TOP_CENTER, "%s", id(weather_timestamp_0).state.c_str());
it.printf(175, 366, id(font_mdi_medium), TextAlign::TOP_CENTER, "%s", weather_icon_map[id(weather_condition_0).state.c_str()].c_str());
it.printf(175, 414, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f°C", id(weather_temperature_0).state);
// # Weather +2h
it.printf(240, 342, id(font_small_book), TextAlign::TOP_CENTER, "%s", id(weather_timestamp_1).state.c_str());
it.printf(240, 366, id(font_mdi_medium), TextAlign::TOP_CENTER, "%s", weather_icon_map[id(weather_condition_1).state.c_str()].c_str());
it.printf(240, 414, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f°C", id(weather_temperature_1).state);
// # Weather +3h
it.printf(305, 342, id(font_small_book), TextAlign::TOP_CENTER, "%s", id(weather_timestamp_2).state.c_str());
it.printf(305, 366, id(font_mdi_medium), TextAlign::TOP_CENTER, "%s", weather_icon_map[id(weather_condition_2).state.c_str()].c_str());
it.printf(305, 414, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f°C", id(weather_temperature_2).state);
// # Weather +4h
it.printf(370, 342, id(font_small_book), TextAlign::TOP_CENTER, "%s", id(weather_timestamp_3).state.c_str());
it.printf(370, 366, id(font_mdi_medium), TextAlign::TOP_CENTER, "%s", weather_icon_map[id(weather_condition_3).state.c_str()].c_str());
it.printf(370, 414, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f°C", id(weather_temperature_3).state);
// # Weather +5h
it.printf(435, 342, id(font_small_book), TextAlign::TOP_CENTER, "%s", id(weather_timestamp_4).state.c_str());
it.printf(435, 366, id(font_mdi_medium), TextAlign::TOP_CENTER, "%s", weather_icon_map[id(weather_condition_4).state.c_str()].c_str());
it.printf(435, 414, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f°C", id(weather_temperature_4).state);
// # line
it.rectangle(5, 440, 700, 1);
// # Living room (450,458)
it.printf(175, 450, id(font_mdi_medium), TextAlign::TOP_CENTER, "\U000F156D");
it.printf(230, 458, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f°C,", id(oh_lampotila).state);
it.printf(271, 458, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f", id(oh_kosteus).state);
it.printf(292, 458, id(font_small_bold), TextAlign::TOP_CENTER, "%s", "%");
// # Bedroom (490,498)
it.printf(175, 490, id(font_mdi_medium), TextAlign::TOP_CENTER, "\U000F0FD1");
it.printf(230, 498, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f°C,", id(mh_lampotila).state);
it.printf(271, 498, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f", id(mh_kosteus).state);
it.printf(292, 498, id(font_small_bold), TextAlign::TOP_CENTER, "%s", "%,");
it.printf(327, 498, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0flx,", id(mh_valoisuus).state);
it.printf(395, 498, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0fug/m3", id(mh_pm25).state);
// # Kitchen, toilet and hallway (530,538)
it.printf(175, 530, id(font_mdi_medium), TextAlign::TOP_CENTER, "\U000F181D");
it.printf(230, 538, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f°C,", id(keittio_lampotila).state);
it.printf(275, 530, id(font_mdi_medium), TextAlign::TOP_CENTER, "\U000F09A0");
it.printf(325, 538, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f°C,", id(kph_lampotila).state);
it.printf(366, 538, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f", id(kph_kosteus).state);
it.printf(407, 538, id(font_small_bold), TextAlign::TOP_CENTER, "%s", "%");
// # Some stuff
it.printf(175, 570, id(font_mdi_medium), TextAlign::TOP_CENTER, "\U000F0FD1");
it.printf(230, 578, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f°C,", id(mh_lampotila).state);
it.printf(271, 578, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0f", id(mh_kosteus).state);
it.printf(292, 578, id(font_small_bold), TextAlign::TOP_CENTER, "%s", "%,");
it.printf(327, 578, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0flx,", id(mh_valoisuus).state);
it.printf(395, 578, id(font_small_bold), TextAlign::TOP_CENTER, "%2.0fug/m3", id(mh_pm25).state);
// # line
it.rectangle(5, 610, 700, 1);
// # Electricity
it.printf(45, 635, id(font_mdi_large), TextAlign::TOP_CENTER, "\U000F1904");
it.printf(240, 620, id(font_small_bold), TextAlign::TOP_CENTER, "%s", id(nordpool_text).state.c_str());
// # Nordpool min/avg/max
it.printf(144, 650, id(font_small_bold), TextAlign::TOP_CENTER, "%s", "KALLEIN:");
it.printf(280, 650, id(font_small_bold), TextAlign::TOP_CENTER, "%.1fc/kWh", id(nordpool_max).state);
it.printf(158, 675, id(font_small_bold), TextAlign::TOP_CENTER, "%s", "KESKIARVO:");
it.printf(280, 675, id(font_small_bold), TextAlign::TOP_CENTER, "%.1fc/kWh", id(nordpool_avg).state);
it.printf(140, 700, id(font_small_bold), TextAlign::TOP_CENTER, "%s", "HALVIN:");
it.printf(280, 700, id(font_small_bold), TextAlign::TOP_CENTER, "%.1fc/kWh", id(nordpool_min).state);
// # Nordpool hour
it.printf(39, 730, id(font_small_book), TextAlign::TOP_CENTER, "%s", id(nordpool_timestamp_1).state.c_str());
it.printf(39, 753, id(font_small_bold), TextAlign::TOP_CENTER, "%.1fc", id(nordpool_1h).state);
it.printf(106, 730, id(font_small_book), TextAlign::TOP_CENTER, "%s", id(nordpool_timestamp_2).state.c_str());
it.printf(106, 753, id(font_small_bold), TextAlign::TOP_CENTER, "%.1fc", id(nordpool_2h).state);
it.printf(173, 730, id(font_small_book), TextAlign::TOP_CENTER, "%s", id(nordpool_timestamp_3).state.c_str());
it.printf(173, 753, id(font_small_bold), TextAlign::TOP_CENTER, "%.1fc", id(nordpool_3h).state);
it.printf(240, 730, id(font_small_book), TextAlign::TOP_CENTER, "%s", id(nordpool_timestamp_4).state.c_str());
it.printf(240, 753, id(font_small_bold), TextAlign::TOP_CENTER, "%.1fc", id(nordpool_4h).state);
it.printf(307, 730, id(font_small_book), TextAlign::TOP_CENTER, "%s", id(nordpool_timestamp_5).state.c_str());
it.printf(307, 753, id(font_small_bold), TextAlign::TOP_CENTER, "%.1fc", id(nordpool_5h).state);
it.printf(374, 730, id(font_small_book), TextAlign::TOP_CENTER, "%s", id(nordpool_timestamp_6).state.c_str());
it.printf(374, 753, id(font_small_bold), TextAlign::TOP_CENTER, "%.1fc", id(nordpool_6h).state);
it.printf(441, 730, id(font_small_book), TextAlign::TOP_CENTER, "%s", id(nordpool_timestamp_7).state.c_str());
it.printf(441, 753, id(font_small_bold), TextAlign::TOP_CENTER, "%.1fc", id(nordpool_7h).state);
// # Consumption
it.printf(365, 642, id(font_mdi_medium), TextAlign::TOP_CENTER, "\U000F1A58");
it.printf(424, 650, id(font_small_bold), TextAlign::TOP_CENTER, "%.1fkWh", id(total_daily_energy).state);
// # IMAGES
it.image(3, 200, id(image_majakka)); //MAJAKKA IMAGE
// Refresh Timestamp
// Code by EnsconcE from https://community.home-assistant.io/t/esphome-show-time/348903
char str[17];
time_t currTime = id(homeassistant_time).now().timestamp;
strftime(str, sizeof(str), "%H:%M", localtime(&currTime));
it.printf(240, 780, id(font_small_book), TextAlign::TOP_CENTER, "PÄIVITETTY %s", str);
}
captive_portal:
And here is rest of my conf.
Sensors from templates.yaml
#================================
#=== ePaper display sensors
#================================
#template:
# Bundle up all the data to send over to ePaper (ESPHome device).
- trigger:
platform: time_pattern
minutes: "/1"
sensor:
- name: ePaper Data
state: "OK"
attributes:
weather_condition_now: >
{% set cond_now = states('sensor.weather_hourly') %}
{% if states('sun.sun') == 'below_horizon' %}
{% if cond_now == 'sunny' %} night {% elif cond_now == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond_now }} {% endif %}
{% else %}
{{ cond_now }}
{% endif %}
weather_condition_0: >
{% set cond0 = state_attr('sensor.weather_hourly', 'forecast')[0].condition %}
{% set next_setting = as_timestamp(state_attr('sun.sun', 'next_setting')) %}
{% set next_rising = as_timestamp(state_attr('sun.sun', 'next_rising')) %}
{% set cond0_time = as_timestamp(state_attr('sensor.weather_hourly', 'forecast')[0].datetime) %}
{% if cond0_time < next_rising and next_rising < next_setting %}
{% if cond0 == 'sunny' %} night {% elif cond0 == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond0 }} {% endif %}
{% else %}
{{ cond0 }}
{% endif %}
weather_temperature_0: >
{{ state_attr('sensor.weather_hourly', 'forecast')[0].temperature | round }}
weather_timestamp_0: >
{{ as_timestamp(state_attr('sensor.weather_hourly', 'forecast')[0].datetime) | timestamp_custom('%H:%M') }}
weather_condition_1: >
{% set cond1 = state_attr('sensor.weather_hourly', 'forecast')[1].condition %}
{% set next_setting = as_timestamp(state_attr('sun.sun', 'next_setting')) %}
{% set next_rising = as_timestamp(state_attr('sun.sun', 'next_rising')) %}
{% set cond1_time = as_timestamp(state_attr('sensor.weather_hourly', 'forecast')[1].datetime) %}
{% if cond1_time < next_rising and next_rising < next_setting %}
{% if cond1 == 'sunny' %} night {% elif cond1 == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond1 }} {% endif %}
{% else %}
{{ cond1 }}
{% endif %}
weather_temperature_1: >
{{ state_attr('sensor.weather_hourly', 'forecast')[1].temperature | round }}
weather_timestamp_1: >
{{ as_timestamp(state_attr('sensor.weather_hourly', 'forecast')[1].datetime) | timestamp_custom('%H:%M') }}
weather_condition_2: >
{% set cond2 = state_attr('sensor.weather_hourly', 'forecast')[2].condition %}
{% set next_setting = as_timestamp(state_attr('sun.sun', 'next_setting')) %}
{% set next_rising = as_timestamp(state_attr('sun.sun', 'next_rising')) %}
{% set cond2_time = as_timestamp(state_attr('sensor.weather_hourly', 'forecast')[2].datetime) %}
{% if cond2_time < next_rising and next_rising < next_setting %}
{% if cond2 == 'sunny' %} night {% elif cond2 == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond2 }} {% endif %}
{% else %}
{{ cond2 }}
{% endif %}
weather_temperature_2: >
{{ state_attr('sensor.weather_hourly', 'forecast')[2].temperature | round }}
weather_timestamp_2: >
{{ as_timestamp(state_attr('sensor.weather_hourly', 'forecast')[2].datetime) | timestamp_custom('%H:%M') }}
weather_condition_3: >
{% set cond3 = state_attr('sensor.weather_hourly', 'forecast')[3].condition %}
{% set next_setting = as_timestamp(state_attr('sun.sun', 'next_setting')) %}
{% set next_rising = as_timestamp(state_attr('sun.sun', 'next_rising')) %}
{% set cond3_time = as_timestamp(state_attr('sensor.weather_hourly', 'forecast')[3].datetime) %}
{% if cond3_time < next_rising and next_rising < next_setting %}
{% if cond3 == 'sunny' %} night {% elif cond3 == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond3 }} {% endif %}
{% else %}
{{ cond3 }}
{% endif %}
weather_temperature_3: >
{{ state_attr('sensor.weather_hourly', 'forecast')[3].temperature | round }}
weather_timestamp_3: >
{{ as_timestamp(state_attr('sensor.weather_hourly', 'forecast')[3].datetime) | timestamp_custom('%H:%M') }}
weather_condition_4: >
{% set cond4 = state_attr('sensor.weather_hourly', 'forecast')[4].condition %}
{% set next_setting = as_timestamp(state_attr('sun.sun', 'next_setting')) %}
{% set next_rising = as_timestamp(state_attr('sun.sun', 'next_rising')) %}
{% set cond4_time = as_timestamp(state_attr('sensor.weather_hourly', 'forecast')[4].datetime) %}
{% if cond4_time < next_rising and next_rising < next_setting %}
{% if cond4 == 'sunny' %} night {% elif cond4 == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond4 }} {% endif %}
{% else %}
{{ cond4 }}
{% endif %}
weather_temperature_4: >
{{ state_attr('sensor.weather_hourly', 'forecast')[4].temperature | round }}
weather_timestamp_4: >
{{ as_timestamp(state_attr('sensor.weather_hourly', 'forecast')[4].datetime) | timestamp_custom('%H:%M') }}
weather_temp_low: >
{%set lowof = state_attr('sensor.weather_hourly','forecast') | selectattr('datetime','search', now().timestamp() | timestamp_custom('%Y-%m-%d')) | map(attribute='temperature') | min %}{% if lowof is defined and lowof %}{{lowof}}{%endif%}
weather_temp_high: >
{%set highof = state_attr('sensor.weather_hourly','forecast') | selectattr('datetime','search', now().timestamp() | timestamp_custom('%Y-%m-%d')) | map(attribute='temperature') | max %}{% if highof is defined and highof %}{{highof}}{%endif%}
ulkolampotila: >
{{ states('sensor.sensor_2_2_temperature') }}
kosteus: >
{{ states('sensor.lumi_lumi_weather_humidity') }}
ilmanpaine: >
{{ states('sensor.lumi_lumi_weather_pressure') }}
tuuli: >
{{ states('sensor.saa_tuulen_nopeus') }}
tuuli_suunta: >
{{ states('sensor.saa_tuulen_suunta') }}
mh_lampotila: >
{{ states('sensor.makuuhuone_lampotila') }}
mh_kosteus: >
{{ states('sensor.makuuhuone_kosteus') }}
mh_valoisuus: >
{{ states('sensor.makuuhuone_valoisuus') }}
mh_pm25: >
{{ states('sensor.makuuhuone_pm25') }}
oh_lampotila: >
{{ states('sensor.sensor_4_temperature') }}
oh_kosteus: >
{{ states('sensor.sensor_4_humidity') }}
keittio_lampotila: >
{{ states('sensor.keittio_zb_motion_temperature') }}
keittio_valoisuus: >
{{ states('sensor.keittio_zb_motion_illuminance') }}
kph_lampotila: >
{{ states('sensor.sensor_3_temperature') }}
kph_kosteus: >
{{ states('sensor.sensor_3_humidity') }}
nordpool_current: >
{{ ((state_attr('sensor.nordpool_kwh_fi_eur_2_10_024','today')[now().hour])) }}
nordpool_min: >
{{ ((state_attr('sensor.nordpool_kwh_fi_eur_2_10_024', 'min')|float / 0.05) | round() * 0.05) }}
nordpool_avg: >
{{ ((state_attr('sensor.nordpool_kwh_fi_eur_2_10_024', 'average')|float / 0.05) | round() * 0.05) }}
nordpool_max: >
{{ ((state_attr('sensor.nordpool_kwh_fi_eur_2_10_024', 'max')|float / 0.05) | round() * 0.05) }}
nordpool_1h: >
{% if now().hour+1 >= 24 %}
{{ ((state_attr('sensor.nordpool_kwh_fi_eur_2_10_024','tomorrow')[now().hour+1-24])) }}
{% else %}
{{ ((state_attr('sensor.nordpool_kwh_fi_eur_2_10_024','today')[now().hour+1])) }}
{% endif %}
nordpool_2h: >
{% if now().hour+2 >= 24 %}
{{ ((state_attr('sensor.nordpool_kwh_fi_eur_2_10_024','tomorrow')[now().hour+2-24])) }}
{% else %}
{{ ((state_attr('sensor.nordpool_kwh_fi_eur_2_10_024','today')[now().hour+2])) }}
{% endif %}
nordpool_3h: >
{% if now().hour+3 >= 24 %}
{{ ((state_attr('sensor.nordpool_kwh_fi_eur_2_10_024','tomorrow')[now().hour+3-24])) }}
{% else %}
{{ ((state_attr('sensor.nordpool_kwh_fi_eur_2_10_024','today')[now().hour+3])) }}
{% endif %}
nordpool_4h: >
{% if now().hour+4 >= 24 %}
{{ ((state_attr('sensor.nordpool_kwh_fi_eur_2_10_024','tomorrow')[now().hour+4-24])) }}
{% else %}
{{ ((state_attr('sensor.nordpool_kwh_fi_eur_2_10_024','today')[now().hour+4])) }}
{% endif %}
nordpool_5h: >
{% if now().hour+5 >= 24 %}
{{ ((state_attr('sensor.nordpool_kwh_fi_eur_2_10_024','tomorrow')[now().hour+5-24])) }}
{% else %}
{{ ((state_attr('sensor.nordpool_kwh_fi_eur_2_10_024','today')[now().hour+5])) }}
{% endif %}
nordpool_6h: >
{% if now().hour+6 >= 24 %}
{{ ((state_attr('sensor.nordpool_kwh_fi_eur_2_10_024','tomorrow')[now().hour+6-24])) }}
{% else %}
{{ ((state_attr('sensor.nordpool_kwh_fi_eur_2_10_024','today')[now().hour+6])) }}
{% endif %}
nordpool_7h: >
{% if now().hour+7 >= 24 %}
{{ ((state_attr('sensor.nordpool_kwh_fi_eur_2_10_024','tomorrow')[now().hour+7-24])) }}
{% else %}
{{ ((state_attr('sensor.nordpool_kwh_fi_eur_2_10_024','today')[now().hour+7])) }}
{% endif %}
nordpool_timestamp_1: >
{{ (now()|as_timestamp + (60*60))|timestamp_custom("%H:00", True) }}
nordpool_timestamp_2: >
{{ (now()|as_timestamp + (60*120))|timestamp_custom("%H:00", True) }}
nordpool_timestamp_3: >
{{ (now()|as_timestamp + (60*180))|timestamp_custom("%H:00", True) }}
nordpool_timestamp_4: >
{{ (now()|as_timestamp + (60*240))|timestamp_custom("%H:00", True) }}
nordpool_timestamp_5: >
{{ (now()|as_timestamp + (60*320))|timestamp_custom("%H:00", True) }}
nordpool_timestamp_6: >
{{ (now()|as_timestamp + (60*360))|timestamp_custom("%H:00", True) }}
nordpool_timestamp_7: >
{{ (now()|as_timestamp + (60*420))|timestamp_custom("%H:00", True) }}
total_hourly_energy: >
{{ states('sensor.total_hourly_energy') }}
total_daily_energy: >
{{ states('sensor.total_energy_daily') }}
nordpool_text: >
{% set min_price = 10 |
float %} {% set max_price = 20 | float %} {% set current_price =
state_attr('sensor.nordpool_kwh_fi_eur_2_10_024', 'current_price') | float %}
{% if current_price < min_price %}
Sähkö on nyt halpaa, hinta on {{ states('sensor.nordpool_kwh_fi_eur_2_10_024', 'current_price') }} c/kWh
{% elif current_price > min_price and current_price < max_price %}
Sähkö on nyt keskihintaista, hinta on {{ states('sensor.nordpool_kwh_fi_eur_2_10_024', 'current_price') }} c/kWh
{% elif current_price > max_price %}
Sähkö on nyt kallista, hinta on {{ states('sensor.nordpool_kwh_fi_eur_2_10_024', 'current_price') }} c/kWh
{% endif %}
I update the display via automation twice an hour. At the second minute of every hour and when the weather forecast is updated. The weather forecast is updated at a random time approximately every hour, which is why it is updated when the latest information is available. In addition, someone has to be at home and awake for the display to be updated.
Hi All,
Ive been playing with this for the last few days, and i cant get this to work at all. I get a flashing noise screen about every second which alternates between black and white. I have tried using other people code straight as with no alterations… Just to see if i can get something on the screen… If i use Waveshare demo code that uploads a picture thats fine with no issues. so im going to guess there is something wrong with my pin set up
I have a Waveshare ESP32 and a 7.5 075bn-t7 V2 dispay screen, below is the output from the serial monitor
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:1184
load:0x40078000,len:13132
load:0x40080400,len:3036
entry 0x400805e4
[I][logger:158]: Log initialized
[C][ota:483]: There have been 2 suspected unsuccessful boot attempts.
[D][esp32.preferences:114]: Saving 1 preferences to flash...
[D][esp32.preferences:143]: Saving 1 preferences to flash: 0 cached, 1 written, 0 failed
[I][app:029]: Running through setup()...
[D][spi:039]: Setting up SPI bus...
[D][spi_device:379]: mode 0, data_rate 2000kHz
[C][wifi:038]: Setting up WiFi...
[C][wifi:051]: Starting WiFi...
[C][wifi:052]: Local MAC: 94:B5:55:19:EA:40
[D][wifi:462]: Starting scan...
[E][waveshare_epaper:159]: Timeout while displaying image!
[E][waveshare_epaper:159]: Timeout while displaying image!
[W][component:232]: Component display took a long time for an operation (2606 ms).
[W][component:233]: Components should block for at most 30 ms.
[W][wifi:152]: Warning set: unspecified
[E][waveshare_epaper:159]: Timeout while displaying image!
[W][component:232]: Component display took a long time for an operation (2451 ms).
[W][component:233]: Components should block for at most 30 ms.
[E][waveshare_epaper:159]: Timeout while displaying image!
[E][waveshare_epaper:159]: Timeout while displaying image!
[W][component:232]: Component display took a long time for an operation (2606 ms).
[W][component:233]: Components should block for at most 30 ms.
[D][wifi:477]: Found networks:
[I][wifi:521]: - 'TailWagNet' [redacted]▂▄▆█
[D][wifi:522]: Channel: 1
[D][wifi:523]: RSSI: -63 dB
[I][wifi:521]: - 'TailWagNet' [redacted]▂▄▆█
[D][wifi:522]: Channel: 6
[D][wifi:523]: RSSI: -71 dB
[D][wifi:526]: - [redacted] [redacted]▂▄▆█
[D][wifi:526]: - [redacted] [redacted]▂▄▆█
[D][wifi:526]: - [redacted] [redacted]▂▄▆█
[D][wifi:526]: - [redacted] [redacted]▂▄▆█
[D][wifi:526]: - [redacted] [redacted]▂▄▆█
[D][wifi:526]: - [redacted] [redacted]▂▄▆█
[D][wifi:526]: - [redacted] [redacted]▂▄▆█
[D][wifi:526]: - [redacted] [redacted]▂▄▆█
[D][wifi:526]: - [redacted] [redacted]▂▄▆█
[D][wifi:526]: - [redacted] [redacted]▂▄▆█
[D][wifi:526]: - [redacted] [redacted]▂▄▆█
[D][wifi:526]: - [redacted] [redacted]▂▄▆█
[D][wifi:526]: - [redacted] [redacted]▂▄▆█
[D][wifi:526]: - [redacted] [redacted]▂▄▆█
[I][wifi:303]: WiFi Connecting to 'TailWagNet'...
[E][waveshare_epaper:159]: Timeout while displaying image!
[W][component:232]: Component display took a long time for an operation (2293 ms).
[W][component:233]: Components should block for at most 30 ms.
[I][wifi:594]: WiFi Connected!
[C][wifi:408]: Local MAC: 94:B5:55:19:EA:40
[C][wifi:413]: SSID: [redacted]
[C][wifi:416]: IP Address: 192.168.1.163
[C][wifi:420]: BSSID: [redacted]
[C][wifi:421]: Hostname: 'e-paper-dashboard'
[C][wifi:423]: Signal strength: -66 dB ▂▄▆█
[C][wifi:427]: Channel: 1
[C][wifi:428]: Subnet: 255.255.255.0
[C][wifi:429]: Gateway: 192.168.1.1
[C][wifi:430]: DNS1: 192.168.1.249
[C][wifi:431]: DNS2: 0.0.0.0
[D][wifi:603]: Disabling AP...
[C][ota:096]: Over-The-Air Updates:
[C][ota:097]: Address: e-paper-dashboard.local:3232
[C][ota:100]: Using Password.
[C][ota:103]: OTA version: 2.
[W][ota:107]: Last Boot was an unhandled reset, will proceed to safe mode in 8 restarts
[C][api:025]: Setting up Home Assistant API server...
[I][app:062]: setup() finished successfully!
[E][waveshare_epaper:159]: Timeout while displaying image!
[E][waveshare_epaper:159]: Timeout while displaying image!
[W][component:232]: Component display took a long time for an operation (2606 ms).
[W][component:233]: Components should block for at most 30 ms.
[W][wifi:165]: Warning cleared
[D][api:102]: Accepted 192.168.1.185
[W][component:232]: Component api took a long time for an operation (56 ms).
[W][component:233]: Components should block for at most 30 ms.
[I][app:102]: ESPHome version 2024.3.0 compiled on Mar 23 2024, 09:12:44
[C][wifi:580]: WiFi:
[C][wifi:408]: Local MAC: 94:B5:55:19:EA:40
[C][wifi:413]: SSID: [redacted]
[C][wifi:416]: IP Address: 192.168.1.163
[C][wifi:420]: BSSID: [redacted]
[C][wifi:421]: Hostname: 'e-paper-dashboard'
[C][wifi:423]: Signal strength: -65 dB ▂▄▆█
[C][wifi:427]: Channel: 1
[C][wifi:428]: Subnet: 255.255.255.0
[C][wifi:429]: Gateway: 192.168.1.1
[C][wifi:430]: DNS1: 192.168.1.249
[C][wifi:431]: DNS2: 0.0.0.0
[E][waveshare_epaper:159]: Timeout while displaying image!
[W][component:232]: Component display took a long time for an operation (2320 ms).
[W][component:233]: Components should block for at most 30 ms.
[C][logger:166]: Logger:
[C][logger:167]: Level: DEBUG
[C][logger:169]: Log Baud Rate: 115200
[C][logger:170]: Hardware UART: UART0
[E][waveshare_epaper:159]: Timeout while displaying image!
[E][waveshare_epaper:159]: Timeout while displaying image!
[W][component:232]: Component display took a long time for an operation (2606 ms).
[W][component:233]: Components should block for at most 30 ms.
[D][api.connection:1159]: Home Assistant 2024.3.3 (192.168.1.185): Connected successfully
[C][spi:068]: SPI bus:
[C][spi:069]: CLK Pin: GPIO13
[C][spi:070]: SDI Pin:
[C][spi:071]: SDO Pin: GPIO14
[C][spi:076]: Using HW SPI: SPI
[E][waveshare_epaper:159]: Timeout while displaying image!
[W][component:232]: Component display took a long time for an operation (2426 ms).
[W][component:233]: Components should block for at most 30 ms.
[E][waveshare_epaper:159]: Timeout while displaying image!
[E][waveshare_epaper:159]: Timeout while displaying image!
[W][component:232]: Component display took a long time for an operation (2606 ms).
[W][component:233]: Components should block for at most 30 ms.
[C][waveshare_epaper:2033]: Waveshare E-Paper
[C][waveshare_epaper:2033]: Rotations: 90 °
[C][waveshare_epaper:2033]: Dimensions: 480px x 800px
[C][waveshare_epaper:2034]: Model: 7.5in-bv2
[C][waveshare_epaper:2035]: Reset Pin: GPIO26
[C][waveshare_epaper:2036]: DC Pin: GPIO17
[C][waveshare_epaper:2037]: Busy Pin: GPIO25
[C][waveshare_epaper:2038]: Update Interval: 1.0s
[E][waveshare_epaper:159]: Timeout while displaying image!
[W][component:232]: Component display took a long time for an operation (2419 ms).
[W][component:233]: Components should block for at most 30 ms.
[E][waveshare_epaper:159]: Timeout while displaying image!
[E][waveshare_epaper:159]: Timeout while displaying image!
[W][component:232]: Component display took a long time for an operation (2606 ms).
[W][component:233]: Components should block for at most 30 ms.
[C][captive_portal:088]: Captive Portal:
[E][waveshare_epaper:159]: Timeout while displaying image!
[W][component:232]: Component display took a long time for an operation (2449 ms).
[W][component:233]: Components should block for at most 30 ms.
[C][mdns:115]: mDNS:
[C][mdns:116]: Hostname: e-paper-dashboard
[E][waveshare_epaper:159]: Timeout while displaying image!
[E][waveshare_epaper:159]: Timeout while displaying image!
[W][component:232]: Component display took a long time for an operation (2606 ms).
[W][component:233]: Components should block for at most 30 ms.
[C][ota:096]: Over-The-Air Updates:
[C][ota:097]: Address: e-paper-dashboard.local:3232
[C][ota:100]: Using Password.
[C][ota:103]: OTA version: 2.
[W][ota:107]: Last Boot was an unhandled reset, will proceed to safe mode in 8 restarts
[E][waveshare_epaper:159]: Timeout while displaying image!
[W][component:232]: Component display took a long time for an operation (2432 ms).
[W][component:233]: Components should block for at most 30 ms.
[C][api:139]: API Server:
[C][api:140]: Address: e-paper-dashboard.local:6053
[C][api:142]: Using noise encryption: YES
[E][waveshare_epaper:159]: Timeout while displaying image!
[E][waveshare_epaper:159]: Timeout while displaying image!
[W][component:232]: Component display took a long time for an operation (2606 ms).
[W][component:233]: Components should block for at most 30 ms.
[E][waveshare_epaper:159]: Timeout while displaying image!
[W][component:232]: Component display took a long time for an operation (2455 ms).
[W][component:233]: Components should block for at most 30 ms.
[E][waveshare_epaper:159]: Timeout while displaying image!
[E][waveshare_epaper:159]: Timeout while displaying image!
[W][component:232]: Component display took a long time for an operation (2606 ms).
[W][component:233]: Components should block for at most 30 ms.
[E][waveshare_epaper:159]: Timeout while displaying image!
[W][component:232]: Component display took a long time for an operation (2455 ms).
[W][component:233]: Components should block for at most 30 ms.
[E][waveshare_epaper:159]: Timeout while displaying image!
[E][waveshare_epaper:159]: Timeout while displaying image!
[W][component:232]: Component display took a long time for an operation (2606 ms).
[W][component:233]: Components should block for at most 30 ms.
[E][waveshare_epaper:159]: Timeout while displaying image!
[W][component:232]: Component display took a long time for an operation (2455 ms).
[W][component:233]: Components should block for at most 30 ms.
[E][waveshare_epaper:159]: Timeout while displaying image!
[E][waveshare_epaper:159]: Timeout while displaying image!
[W][component:232]: Component display took a long time for an operation (2606 ms).
[W][component:233]: Components should block for at most 30 ms.
[E][waveshare_epaper:159]: Timeout while displaying image!
does anyone have any pointers, as already mentioned i know the screen works ok
Hi!
I updated to HA 2024.4 and got notified that I had to remove the “beat” part of “display_option” in the “time_date” platform.
Now the weatherman data is not working, se log below. How to resolve?
Logger: homeassistant.helpers.sensor
Source: helpers/trigger_template_entity.py:209
First occurred: April 5, 2024 at 15:54:00 (2398 occurrences)
Last logged: 07:51:00
Error rendering state template for sensor.weatherman_data: UndefinedError: None has no element 0
Logger: homeassistant.helpers.template
Source: helpers/template.py:2558
First occurred: April 5, 2024 at 15:54:00 (2398 occurrences)
Last logged: 07:51:00
Template variable error: None has no element 0 when rendering ‘{% set cond0 = state_attr(‘weather.home’, ‘forecast’)[0].condition %} {% set next_setting = as_timestamp(state_attr(‘sun.sun’, ‘next_setting’)) %} {% set next_rising = as_timestamp(state_attr(‘sun.sun’, ‘next_rising’)) %} {% set cond0_time = as_timestamp(state_attr(‘weather.home’, ‘forecast’)[0].datetime) %} {% if cond0_time < next_rising and next_rising < next_setting %} {% if cond0 == ‘sunny’ %} night {% elif cond0 == ‘partlycloudy’ %} night-partly-cloudy {% else %} {{ cond0 }} {% endif %} {% else %} {{ cond0 }} {% endif %}’
It´s a change in the weather integration “The previously deprecated forecast
attribute of weather entities, has now been removed. Use the weather.get_forecasts
service to get the forecast data instead.” There is no attributes anymore, this thread will give you some more information on how to use weather.get_forcasts
I haven’t found a way to call the weather.get_forcasts from ESPHome, don´t know if you can, so I have created a template sensor with all attributes
template:
- trigger:
- platform: time_pattern
hours: /1
- platform: homeassistant
event: start
action:
- service: weather.get_forecasts
data:
type: hourly
target:
entity_id: weather.forecast_home
response_variable: hourly
sensor:
- name: Weather Hourly
state: "{{ states('weather.forecast_home') }}"
attributes:
temperature: "{{ state_attr('weather.forecast_home', 'temperature') }}"
dew_point: "{{ state_attr('weather.forecast_home', 'dew_point') }}"
temperature_unit: "{{ state_attr('weather.forecast_home', 'temperature_unit') }}"
humidity: "{{ state_attr('weather.forecast_home', 'humidity') }}"
cloud_coverage: "{{ state_attr('weather.forecast_home', 'cloud_coverage') }}"
pressure: "{{ state_attr('weather.forecast_homee', 'pressure') }}"
pressure_unit: "{{ state_attr('weather.forecast_home', 'pressure_unit') }}"
wind_bearing: "{{ state_attr('weather.forecast_home', 'wind_bearing') }}"
wind_speed: "{{ state_attr('weather.forecast_home', 'wind_speed') }}"
wind_speed_unit: "{{ state_attr('weather.forecast_home', 'wind_speed_unit') }}"
visibility_unit: "{{ state_attr('weather.forecast_home', 'visibility_unit') }}"
precipitation_unit: "{{ state_attr('weather.forecast_home', 'precipitation_unit') }}"
forecast: "{{ hourly['weather.forecast_home'].forecast }}"
If someone have a better way of doing this, please let me know
@Stimo I get this error when I test in template editor: UndefinedError: ‘hourly’ is undefined. Same with Daily.
Did you ever get this problem?
In a previous post I posted my template. The top part shows how you can use the weather service directly, without first creating an extra template sensor in between like @Stimo suggested.
You can see how I changed the weather bits from the original Weatherman post in this example:
You can’t create that one in the template editor, you need to be able to get the respons_varible, so it needs to be inside an automation, script, or something similar. If you want to test it use it as a script and send it to notification or similar
Thanks to @Edwin_D I managed to sort the sensor out without using an extra sensor, I have updated my GitHub with the complete code
Hi! Are you able to provide input where things have changed in the code? I believe I have built my version on your code
The changes are made in the sensor in Home Assistant that the ESP gets its data from, the sensor.weatherman_data. When attributes were removed from the Weather integration we needed to get those attributes using the service weather.get_forecasts instead. So that is now applied in the sensor.weatherman_data
So it´s first of all the trigger to that sensor,
- trigger:
platform: time_pattern
minutes: "/1"
action:
- service: weather.get_forecasts
data:
type: hourly
target:
entity_id: weather.smhi_home
response_variable: hourly
and then in the different templates for the attributes to get the response data provided from the weather integration
weather_temperature_0: >
{{ hourly["weather.smhi_home"].forecast[0].temperature | round }}
Let me know if there is anything special you are wondering
How did you get the model of “7.50in-bv2-rb” work?
When I attempt to configure it with that I get “Unknown value ‘7.50in-bv2-rb’, did you mean ‘7.50in-bv2’, ‘7.50in-bv3’, ‘7.50inv2’?.”
I want that red lol