diff --git a/esphome/epaperframe.yaml b/esphome/epaperframe.yaml index 3e9b8ac..ae86b63 100644 --- a/esphome/epaperframe.yaml +++ b/esphome/epaperframe.yaml @@ -237,6 +237,27 @@ text_sensor: entity_id: weather.zuhause id: weather + # ── Kalender-Ereignisse (from HA template sensors) ── + - platform: homeassistant + entity_id: sensor.kalender_heute_privat + id: kalender_heute_privat_text + internal: true + + - platform: homeassistant + entity_id: sensor.kalender_heute_arbeit + id: kalender_heute_arbeit_text + internal: true + + - platform: homeassistant + entity_id: sensor.kalender_heute_privat_uhrzeit + id: kalender_heute_privat_uhrzeit + internal: true + + - platform: homeassistant + entity_id: sensor.kalender_heute_arbeit_uhrzeit + id: kalender_heute_arbeit_uhrzeit + internal: true + graph: - id: line_power_graph sensor: power_total @@ -1135,45 +1156,74 @@ display: it.image(10, 37, id(c1024_logo)); /* ── LEFT PANE: Today ── */ - int leftX = 0; - int leftY = 85; // start below header row + int leftX = 10; + int leftY = 70; // start below header row - it.print(10 + leftX, 10 + leftY, id(sensor_unit), "Heute"); - it.filled_rectangle(64 + leftX, 21 + leftY, 370, 3); + it.print(15 + leftX, 10 + leftY, id(sensor_unit), "Heute"); + it.filled_rectangle(80 + leftX, 21 + leftY, 240, 3); /* Today's date strip */ it.printf(50 + leftX, 50 + leftY, id(big_sensor_font), "%d", today_day); - it.printf(130 + leftX, 45 + leftY, id(sub_sensor_font), "%s.", today_weekday_str); - it.printf(160 + leftX, 45 + leftY, id(sensor_unit), "%02d.%04d.", today_month, today_year); + it.printf(145 + leftX, 45 + leftY, id(sub_sensor_font), "%s.", today_weekday_str); + it.printf(205 + leftX, 45 + leftY, id(sensor_unit), "%02d.%04d.", today_month, today_year); - /* Event placeholder row (top) */ + /* Event lines (Privat / Arbeit) */ int eventOffsetY = 90; - it.print(10 + leftX, 50 + leftY + eventOffsetY, id(mdi_med), TextAlign::BASELINE_LEFT, "󰀦"); - it.print(40 + leftX, 50 + leftY + eventOffsetY, id(sub_sensor_font), "Eintrag 1"); - /* Event placeholder row (bottom) */ - it.print(10 + leftX, 85 + leftY + eventOffsetY, id(mdi_med), TextAlign::BASELINE_LEFT, "󰀦"); - it.print(40 + leftX, 85 + leftY + eventOffsetY, id(sub_sensor_font), "Eintrag 2"); + // Privat today + if (id(kalender_heute_privat_text).has_state() && !id(kalender_heute_privat_text).state.empty()) { + it.print(10 + leftX, 50 + leftY + eventOffsetY, id(mdi_med), TextAlign::BASELINE_LEFT, "\U0001f32e" ); + if (id(kalender_heute_privat_uhrzeit).has_state() && !id(kalender_heute_privat_uhrzeit).state.empty()) { + it.printf(40 + leftX, 50 + leftY + eventOffsetY, id(sub_sensor_font), "%s ", id(kalender_heute_privat_uhrzeit).state.substr(0, 5).c_str()); + } + size_t max_len = 38; + it.printf(40 + leftX, 50 + leftY + eventOffsetY, id(sub_sensor_font), "%s", + id(kalender_heute_privat_text).state.substr( + id(kalender_heute_privat_uhrzeit).has_state() && !id(kalender_heute_privat_uhrzeit).state.empty() + ? 6 : 0, max_len).c_str()); + } else { + it.print(10 + leftX, 50 + leftY + eventOffsetY, id(mdi_med), TextAlign::BASELINE_LEFT, "\U0001f32e" ); + it.printf(40 + leftX, 50 + leftY + eventOffsetY, id(sub_sensor_font), "Kein Termin"); + } + + // Arbeit today + if (id(kalender_heute_arbeit_text).has_state() && !id(kalender_heute_arbeit_text).state.empty()) { + it.print(10 + leftX, 85 + leftY + eventOffsetY, id(mdi_med), TextAlign::BASELINE_LEFT, "\U0001f32e" ); + if (id(kalender_heute_arbeit_uhrzeit).has_state() && !id(kalender_heute_arbeit_uhrzeit).state.empty()) { + it.printf(40 + leftX, 85 + leftY + eventOffsetY, id(sub_sensor_font), "%s ", id(kalender_heute_arbeit_uhrzeit).state.substr(0, 5).c_str()); + } + size_t max_len = 38; + it.printf(40 + leftX, 85 + leftY + eventOffsetY, id(sub_sensor_font), "%s", + id(kalender_heute_arbeit_text).state.substr( + id(kalender_heute_arbeit_uhrzeit).has_state() && !id(kalender_heute_arbeit_uhrzeit).state.empty() + ? 6 : 0, max_len).c_str()); + } else { + it.print(10 + leftX, 85 + leftY + eventOffsetY, id(mdi_med), TextAlign::BASELINE_LEFT, "\U0001f32e" ); + it.printf(40 + leftX, 85 + leftY + eventOffsetY, id(sub_sensor_font), "Kein Termin"); + } /* ── RIGHT PANE: Tomorrow ── */ - int rightX = 390; - int rightY = 85; + int rightX = 315; + int rightY = 70; - it.print(10 + rightX, 10 + rightY, id(sensor_unit), "Morgen"); - it.filled_rectangle(64 + rightX, 21 + rightY, 370, 3); + it.print(45 + rightX, 10 + rightY, id(sensor_unit), "Morgen"); + it.filled_rectangle(130 + rightX, 21 + rightY, 200, 3); /* Date strip */ it.printf(50 + rightX, 50 + rightY, id(big_sensor_font), "%d", tomorrow_day); - it.printf(130 + rightX, 45 + rightY, id(sub_sensor_font), "%s.", tomorrow_weekday_str); - it.printf(160 + rightX, 45 + rightY, id(sensor_unit), "%02d.%04d.", tomorrow_month, tomorrow_year); + it.printf(145 + rightX, 45 + rightY, id(sub_sensor_font), "%s.", tomorrow_weekday_str); + it.printf(205 + rightX, 45 + rightY, id(sensor_unit), "%02d.%04d.", tomorrow_month, tomorrow_year); - /* Event placeholder row (top) */ - it.print(10 + rightX, 50 + rightY + eventOffsetY, id(mdi_med), TextAlign::BASELINE_LEFT, "󰀦"); - it.print(40 + rightX, 50 + rightY + eventOffsetY, id(sub_sensor_font), "Eintrag 1"); - - /* Event placeholder row (bottom) */ - it.print(10 + rightX, 85 + rightY + eventOffsetY, id(mdi_med), TextAlign::BASELINE_LEFT, "󰀦"); - it.print(40 + rightX, 85 + rightY + eventOffsetY, id(sub_sensor_font), "Eintrag 2"); + /* Event lines (Privat / Arbeit) */ + // TODO: tomorrow events via HA template sensors + if (!id(kalender_heute_privat_text).has_state() || id(kalender_heute_privat_text).state.empty()) { + it.print(10 + rightX, 50 + rightY + eventOffsetY, id(mdi_med), TextAlign::BASELINE_LEFT, "\U0001f32e" ); + it.printf(40 + rightX, 50 + rightY + eventOffsetY, id(sub_sensor_font), "Kein Termin"); + } + if (!id(kalender_heute_arbeit_text).has_state() || id(kalender_heute_arbeit_text).state.empty()) { + it.print(10 + rightX, 85 + rightY + eventOffsetY, id(mdi_med), TextAlign::BASELINE_LEFT, "\U0001f32e" ); + it.printf(40 + rightX, 85 + leftY + eventOffsetY, id(sub_sensor_font), "Kein Termin"); + } /* FOOTER */ it.strftime(614, 380, id(footer_font), TextAlign::BASELINE_RIGHT, "Aktualisiert um %d.%m.%Y %H:%M", id(homeassistant_time).now()); diff --git a/template.yaml b/template.yaml index c9ad129..313a591 100644 --- a/template.yaml +++ b/template.yaml @@ -139,8 +139,48 @@ attributes: last_reset: '1970-01-01T00:00:00+00:00' - name: internet_speed_out + unique_id: '9519483670667' state: > {{ (( states('sensor.wan_out_derivative') | float * 8 / 1000000 ) | round(2)) }} unit_of_measurement: 'Mbps' attributes: last_reset: '1970-01-01T00:00:00+00:00' + +# ── Kalender-Ereignisse für epaperframe ── + - text_sensor: + # ─── HEUTE (today) ─── + # Privat heute + - name: "Kalender heute Privat" + unique_id: kalender_heute_privat + state: >- + {%- if is_state('calendar.privat', 'on') %} + {{- (state_attr('calendar.privat', 'description') | default(state_attr('calendar.privat', 'message'), true)) + | replace('\n', ', ') | trim | truncate(60) -}} + {%- endif -%} + + # Arbeit heute + - name: "Kalender heute Arbeit" + unique_id: kalender_heute_arbeit + state: >- + {%- if is_state('calendar.tkrz_kalender', 'on') %} + {{- (state_attr('calendar.tkrz_kalender', 'description') | default(state_attr('calendar.tkrz_kalender', 'message'), true)) + | replace('\n', ', ') | trim | truncate(60) -}} + {%- endif -%} + + # Zeit heute (Privat) + - name: "Kalender heute Privat Uhrzeit" + unique_id: kalender_heute_privat_uhrzeit + state: >- + {%- if is_state('calendar.privat', 'on') and state_attr('calendar.privat', 'start_time') %} + {{- as_timestamp(state_attr('calendar.privat', 'start_time')) + | timestamp_custom('%H:%M', true) -}} + {%- endif -%} + + # Zeit heute (Arbeit) + - name: "Kalender heute Arbeit Uhrzeit" + unique_id: kalender_heute_arbeit_uhrzeit + state: >- + {%- if is_state('calendar.tkrz_kalender', 'on') and state_attr('calendar.tkrz_kalender', 'start_time') %} + {{- as_timestamp(state_attr('calendar.tkrz_kalender', 'start_time')) + | timestamp_custom('%H:%M', true) -}} + {%- endif -%}