OPIS
Przedstawiam projekt pogodynki na ekranie e-ink z układem ESP32.
Kod nie jest mój, jest to zlepek kilku projektów i dostosowany do moich danych w Home Assistant.
Ekran odświeża się domyślnie przy wykryciu ruchu w pomieszczeniu, jeśli dane z czujników się zmieniły.
Ja zrobiłem pomocnika przełącznik, który robi za fałszywy czujnik ruchu, wtedy ekran odświeża się przy odebraniu danych, pozwala mi to na wyłączanie odświeżania ekranu, jeśli nikogo nie ma w domu, czy podczas snu.
Sam projekt można przerobić na układ z baterią i użyć funkcji deep sleep.
W samym Home Assistant mamy podgląd ilości, czasu odświeżania itp.
Sprzęt
- Waveshare 7.5" eink
- ESP32 Driver Board
- Ramka IKEA RIBBA 13x18
- Przewód micro USB
Oprogramowanie
- ESPHome
- Home Assistant
Źródła danych
- Integracja Met.no
- Integracja Thermal Comfort
- Integracja sun oraz moon
- Lokalny czujnik temperatury, wilgotności oraz ciśnienia
- Sensor z dniem, nazwą tygodnia i miesiąca link
Instalacja
Nie jest wymagane lutowanie, ponieważ ekran e-ink należy połączyć taśmą z płytą ESP32.
Skopiować /font
do folderu /config/esphome/
font.zip (727,8 KB)
Utworzyć w Home Assistant template
- binary_sensor:
- name: Weatherman Motion Detected
unique_id: "dfa78de7-d761-425f-9731-86f1af332eac"
device_class: "occupancy"
delay_off: 1min
state: >-
{%- if states('input_boolean.eink_czujnik_ruchu') == 'on' %}
on
{%- else -%}
off
{%- endif -%}
# Bundle up all the data to send over to Weatherman (ESPHome device).
- trigger:
platform: time_pattern
minutes: "/1"
action:
- service: weather.get_forecasts
data:
type: hourly
target:
entity_id: weather.forecast_home
response_variable: hourly
sensor:
- name: Weatherman Data
state: "OK"
attributes:
weather_condition_now: >
{% set cond_now = states('weather.forecast_home') %}
{% 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 = hourly["weather.forecast_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(hourly["weather.forecast_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 %}
weather_temperature_0: >
{{ hourly["weather.forecast_home"].forecast[0].temperature | round }}
weather_timestamp_0: >
{{ as_timestamp(hourly["weather.forecast_home"].forecast[0].datetime) | timestamp_custom('%H') | int }}
weather_condition_1: >
{% set cond1 = hourly["weather.forecast_home"].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(hourly["weather.forecast_home"].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: >
{{ hourly["weather.forecast_home"].forecast[1].temperature | round }}
weather_timestamp_1: >
{{ as_timestamp(hourly["weather.forecast_home"].forecast[1].datetime) | timestamp_custom('%H') | int }}
weather_condition_2: >
{% set cond2 = hourly["weather.forecast_home"].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(hourly["weather.forecast_home"].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: >
{{ hourly["weather.forecast_home"].forecast[2].temperature | round }}
weather_timestamp_2: >
{{ as_timestamp(hourly["weather.forecast_home"].forecast[2].datetime) | timestamp_custom('%H') | int }}
weather_condition_3: >
{% set cond3 = hourly["weather.forecast_home"].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(hourly["weather.forecast_home"].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: >
{{ hourly["weather.forecast_home"].forecast[3].temperature | round }}
weather_timestamp_3: >
{{ as_timestamp(hourly["weather.forecast_home"].forecast[3].datetime) | timestamp_custom('%H') | int }}
Zainstalować poniższy kod na płytę ESP32 za pomocą ESPHome.
# WEATHERMAN DASHBOARD
# For Home Assistant and ESPHome
# Designed by Madelena Mak 2022 - https://mmak.es
# Cue "Blame it on the Weatherman" by B*Witched!
esphome:
name: eink
friendly_name: eink
on_boot:
priority: 200.0
then:
- component.update: eink_display
- wait_until:
condition:
lambda: 'return id(data_updated) == true;'
# Poczekaj trochę dłużej, aby wszystkie elementy zostały odebrane
- delay: 5s
- logger.log: "Odebrano wstępne dane czujnika: Odświeżanie ekranu..."
- lambda: 'id(initial_data_received) = true;'
- script.execute: update_screen
esp32:
board: esp32dev
framework:
type: arduino
logger:
api:
encryption:
key: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
ota:
password: "xxxxxxxxxxxxxxxxxxxxxxx"
web_server:
port: 80
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: "Eink Fallback Hotspot"
password: "xxxxxxxxx"
captive_portal:
# Dołącz czas
# Sprawdź, czy wyświetlacz wymaga odświeżania co minutę,
# w zależności od tego, czy odebrano nowe dane, czy wykryto ruch. (Thanks @paviro!)
time:
- platform: homeassistant
id: homeassistant_time
on_time:
- seconds: 0
minutes: /30
then:
- if:
condition:
lambda: 'return id(data_updated) == true;'
then:
- if:
condition:
binary_sensor.is_on: motion_detected
then:
- logger.log: "Zaktualizowano dane czujnika i wykryto aktywność w domu: odświeżanie wyświetlacza..."
- script.execute: update_screen
else:
- logger.log: "Dane czujnika zostały zaktualizowane, ale w domu brak aktywności – pominięto odświeżanie wyświetlacza."
else:
- logger.log: "Brak aktualizacji czujników – pominięto odświeżanie wyświetlacza."
# Przyciski
button:
- platform: shutdown
name: "eink - Wyłączenie"
- platform: restart
name: "eink - Restart"
- platform: template
name: "eink - Odświeżanie ekranu"
entity_category: config
on_press:
- script.execute: update_screen
# Zmienne globalne do wykrywania, czy ekran wymaga odświeżenia. (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'
# Skrypt do aktualizacji ekranu - Odśwież wyświetlacz i opublikuj liczbę i czas odświeżenia. (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);'
# Dołącz niestandardową czcionkę
font:
- file: 'font/GothamRnd-Bold.ttf'
id: font_large_bold
size: 125
- file: 'font/GothamRnd-Bold.ttf'
id: font_large_bold_c
size: 90
- file: 'font/GothamRnd-Book.ttf'
id: font_time
size: 150
- file: 'font/RobotoCondensed-Regular.ttf'
id: font_weekday
size: 50
glyphs: ['A', 'B', 'C', 'D', 'E',
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'Ł', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', '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', 'w', 'x', 'y', 'z','ż', 'ź', 'ę', 'ą', 'ś', 'ć', 'ń', 'ó']
- file: 'font/RobotoCondensed-Light.ttf'
id: font_day
size: 50
glyphs: ['A', 'B', 'C', 'D', 'E',
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'Ł', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', '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', 'w', 'x', 'y', 'z','ż', 'ź', 'ę', 'ą', 'ś', 'ć', 'ń', 'ó']
- file: 'font/GothamRnd-Bold.ttf'
id: font_month
size: 50
- file: 'font/GothamRnd-Bold.ttf'
id: font_medium_bold
size: 42
- file: 'font/GothamRnd-Bold.ttf'
id: font_small_bold
size: 22
# Dołącz czcionkę Material Design Icons
# Dzięki https://community.home-assistant.io/t/display-materialdesign-icons-on-esphome-attached-to-screen/199790/16
- file: 'font/materialdesignicons-webfont.ttf'
id: font_mdi_extra_large
size: 140
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
- "\U000F058E" # mdi-water-percent
- "\U000F04C5" # mdi-spedometer
- "\U000F0F29" # mdi-snowflake-alert
- "\U000F002A" # mdi-alert-outline
- "\U000F15FA" # mdi-windsock
- "\U000F19B3" # mdi-arrow-down-thin
- "\U000F19B2" # mdi-arrow-up-thin
- "\U000F19B4" # mdi-arrow-top-right-thin
- "\U000F19B7" # mdi-arrow-bottom-right-thin
- "\U000F00A5" # mdi-binoculars
- "\U000F018C" # mdi-compass-outline
- "\U000F0E03" # mdi-thermometer-chevron-up
- "\U000F0E02" # mdi-thermometer-chevron-down
- "\U000F1A09" # mdi-triangle-small-down
- "\U000F1A0A" # mdi-triangle-small-up
- "\U000F02CA" # mdi-hadrdisk
- "\U000F029A" # mdi-gauge
- file: 'font/materialdesignicons-webfont.ttf'
id: font_mdi_moon
size: 60
glyphs:
- "\U000F058E" # mdi-water-percent
- "\U000F04C5" # mdi-spedometer
- "\U000F0F29" # mdi-snowflake-alert
- "\U000F002A" # mdi-alert-outline
- "\U000F15FA" # mdi-windsock
- "\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
- file: 'font/materialdesignicons-webfont.ttf'
id: font_mdi_medium
size: 50
glyphs: *mdi-weather-glyphs
- file: 'font/materialdesignicons-webfont.ttf'
id: font_mdi_large
size: 80
glyphs: *mdi-weather-glyphs
# Sprawdź, czy w salonie wykryto ruch. (czy załączony pomocnik ruch)
binary_sensor:
- platform: homeassistant
entity_id: input_boolean.eink_czujnik_ruchu
id: motion_detected
# Czujniki pogodowe z HA
sensor:
# Twórz czujniki do zdalnego monitorowania Weatherman.
- platform: template
name: "eink - Czas aktualizacji wyświetlacza"
device_class: timestamp
entity_category: "diagnostic"
id: display_last_update
- platform: template
name: "eink - Zarejestrowane Oswieżanie wyświetlacza"
accuracy_decimals: 0
unit_of_measurement: "Odświeżenia"
state_class: "total_increasing"
entity_category: "diagnostic"
lambda: 'return id(recorded_display_refresh);'
# Temperatura — moja stacja pogodowa
- platform: homeassistant
entity_id: sensor.netatmo_ogrod_temperature
id: weather_temperature
on_value:
then:
- lambda: 'id(data_updated) = true;'
# Wilgotność - moja stacja pogodowa
- platform: homeassistant
entity_id: sensor.netatmo_ogrod_humidity
id: weather_humidity
on_value:
then:
- lambda: 'id(data_updated) = true;'
# Ciśnienie - moja stacja pogodowa
- platform: homeassistant
entity_id: sensor.netatmo_wewnatrz_pressure
id: weather_pressure
on_value:
then:
- lambda: 'id(data_updated) = true;'
# Ilość opadu deszczu
- platform: homeassistant
entity_id: sensor.netatmo_czujnik_deszczu_rain_today
id: ilosc_opadu
on_value:
then:
- lambda: 'id(data_updated) = true;'
# Weatherman encje
- platform: homeassistant
entity_id: sensor.weatherman_data
attribute: weather_temperature_0
id: weather_temperature_0
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.weatherman_data
attribute: weather_temperature_1
id: weather_temperature_1
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.weatherman_data
attribute: weather_temperature_2
id: weather_temperature_2
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.weatherman_data
attribute: weather_temperature_3
id: weather_temperature_3
on_value:
then:
- lambda: 'id(data_updated) = true;'
text_sensor:
# Dzień tygodnia
- platform: homeassistant
entity_id: sensor.dzien_tygodnia
id: nazwa_dnia
on_value:
then:
- lambda: 'id(data_updated) = true;'
# Miesiąc
- platform: homeassistant
entity_id: sensor.miesiac
id: miesiac
on_value:
then:
- lambda: 'id(data_updated) = true;'
# Dzień
- platform: homeassistant
entity_id: sensor.dzien_miesiaca
id: dzien
on_value:
then:
- lambda: 'id(data_updated) = true;'
# Weatherman encje
- platform: homeassistant
entity_id: sensor.weatherman_data
attribute: weather_condition_now
id: weather_condition_now
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.weatherman_data
attribute: weather_condition_0
id: weather_condition_0
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.weatherman_data
attribute: weather_timestamp_0
id: weather_timestamp_0
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.weatherman_data
attribute: weather_condition_1
id: weather_condition_1
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.weatherman_data
attribute: weather_timestamp_1
id: weather_timestamp_1
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.weatherman_data
attribute: weather_condition_2
id: weather_condition_2
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.weatherman_data
attribute: weather_timestamp_2
id: weather_timestamp_2
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.weatherman_data
attribute: weather_condition_3
id: weather_condition_3
on_value:
then:
- lambda: 'id(data_updated) = true;'
- platform: homeassistant
entity_id: sensor.weatherman_data
attribute: weather_timestamp_3
id: weather_timestamp_3
on_value:
then:
- lambda: 'id(data_updated) = true;'
# Wschód słońca
- platform: homeassistant
entity_id: sensor.czas_wschodu_slonca
id: sun_sunrise
on_value:
then:
- lambda: 'id(data_updated) = true;'
# Zachód słońca
- platform: homeassistant
entity_id: sensor.czas_zachodu_slonca
id: sun_sunset
on_value:
then:
- lambda: 'id(data_updated) = true;'
# Ryzyko mrozu
- platform: homeassistant
entity_id: sensor.thermal_comfort_frostrisk
id: frost_risk
on_value:
then:
- lambda: 'id(data_updated) = true;'
# Meteoalarm
- platform: homeassistant
entity_id: binary_sensor.meteoalarm
id: meteoalarm
on_value:
then:
- lambda: 'id(data_updated) = true;'
# Faza Księżyca
- platform: homeassistant
entity_id: sensor.ksiezyc
id: moon_phase
on_value:
then:
- lambda: 'id(data_updated) = true;'
# Poprawka odświeżania
#external_components:
# - source:
# type: git
# url: https://github.com/prapador/esphome_waveshare_fix
# ref: dev
# components: [ waveshare_epaper ]
# Zdefiniuj kolory
color:
- id: color_black
red: 0%
green: 0%
blue: 0%
white: 50%
- id: color_white
red: 0%
green: 0%
blue: 0%
white: 0%
# Piny Waveshare ePaper ESP Board
spi:
clk_pin: GPIO13
mosi_pin: GPIO14
# Teraz wyrenderuj wszystko na ekranie ePaper.
display:
- platform: waveshare_epaper
id: eink_display
cs_pin: GPIO15
dc_pin: GPIO27
busy_pin: GPIO25
reset_pin: GPIO26
reset_duration: 2ms
model: 7.50inV2alt
update_interval: never
rotation: 90°
auto_clear_enabled: false
lambda: |-
// Map weather states to MDI characters.
std::map<std::string, std::string> moon_icon_map
{
{"first_quarter", "\U000F0F61"},
{"full_moon", "\U000F0F62"},
{"last_quarter", "\U000F0F63"},
{"new_moon", "\U000F0F64"},
{"waning_crescent", "\U000F0F65"},
{"waning_gibbous", "\U000F0F66"},
{"waxing_crescent", "\U000F0F67"},
{"waxing_gibbous", "\U000F0F68"},
};
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"},
};
// Wypełnij tło
it.fill(color_white);
// ------------------------------------------------------------Pokaż ekran ładowania przed odebraniem danych. ------------------------------------------------------
if (id(initial_data_received) == false) {
it.printf(300, 250, id(font_mdi_extra_large), color_black, TextAlign::CENTER_RIGHT, "\U000F02CA");
it.printf(240, 390, id(font_medium_bold), color_black, TextAlign::TOP_CENTER, "Czekam na dane...");
} else {
// ----------------------------------------------------------------------------------- Dzień tygodnia ------------------------------------------------------------
it.printf(210, 70, id(font_weekday), color_black, TextAlign::TOP_LEFT, "%s", id(nazwa_dnia).state.c_str());
// ----------------------------------------------------------------------------------- Dzień miesiąca duże ------------------------------------------------------
it.printf(220, 65, id(font_time), color_black, TextAlign::TOP_RIGHT, "%s", id(dzien).state.c_str());
// ----------------------------------------------------------------------------------- Miesiąc ------------------------------------------------------------------
it.printf(210, 140, id(font_day), color_black, TextAlign::TOP_LEFT, "%s", id(miesiac).state.c_str());
// ----------------------------------------------------------------------------------- Wschód słońca ------------------------------------------------------------
if(id(sun_sunrise).has_state ()) {
it.printf(95, 235, id(font_mdi_medium), color_black, TextAlign::CENTER_RIGHT, "\U000F059C");
it.printf(105, 235, id(font_small_bold), color_black, TextAlign::CENTER_LEFT, "%s", id(sun_sunrise).state.c_str());
}
// ----------------------------------------------------------------------------------- Zachód słońca ------------------------------------------------------------
if(id(sun_sunset).has_state ()) {
it.printf(450, 235, id(font_mdi_medium), color_black, TextAlign::CENTER_RIGHT, "\U000F059B");
it.printf(395, 235, id(font_small_bold), color_black, TextAlign::CENTER_RIGHT, "%s", id(sun_sunset).state.c_str());
}
// ----------------------------------------------------------------------------------- Faza księżyca ikona ------------------------------------------------------
if(id(moon_phase).has_state ()) {
it.printf(255, 240, id(font_mdi_moon), color_black, TextAlign::CENTER, "%s", moon_icon_map[id(moon_phase).state.c_str()].c_str());
}
// ----------------------------------------------------------------------------------- Wilgotność ----------------------------------------------------------------
if(id(weather_humidity).has_state ()) {
it.printf(88, 332, id(font_mdi_medium), color_black, TextAlign::BASELINE_RIGHT, "\U000F058E");
it.printf(151, 330, id(font_month), color_black, TextAlign::BASELINE_RIGHT, "%2.0f", id(weather_humidity).state);
it.printf(155, 330, id(font_small_bold), color_black, TextAlign::BASELINE_LEFT, "%s", "%");
}
// ----------------------------------------------------------------------------------- Ciśnienie -----------------------------------------------------------------
if(id(weather_pressure).has_state ()) {
it.printf(293, 332, id(font_mdi_medium), color_black, TextAlign::BASELINE_RIGHT, "\U000F04C5");
it.printf(415, 330, id(font_month), color_black, TextAlign::BASELINE_RIGHT, "%2.0f", id(weather_pressure).state);
it.printf(420, 330, id(font_small_bold), color_black, TextAlign::BASELINE_LEFT, "hPa");
}
// ----------------------------------------------------------------------------------- Meteoalarm ----------------------------------------------------------------
if(id(meteoalarm).has_state ()) {
if(id(meteoalarm).state != "off") {
it.printf(350, 440, id(font_mdi_large), color_black, TextAlign::BASELINE_LEFT, "\U000F002A");
}
}
// ----------------------------------------------------------------------------------- Ostrzeżenie przed mrozem --------------------------------------------------
if(id(frost_risk).has_state ()) {
if(id(frost_risk).state != "no_risk") {
it.printf(75, 440, id(font_mdi_large), color_black, TextAlign::BASELINE_LEFT, "\U000F0F29");
}
}
// ----------------------------------------------------------------------------------- Ilość opadu deszczu -------------------------------------------------------
if(id(ilosc_opadu).has_state ()) {
if(id(ilosc_opadu).state > 0) {
it.printf(370, 470, id(font_small_bold), color_black, TextAlign::BASELINE_RIGHT, "%.1f", id(ilosc_opadu).state);
it.printf(375, 470, id(font_small_bold), color_black, TextAlign::BASELINE_LEFT, "mm");
}
}
// ----------------------------------------------------------------------------------- Stan pogody ikona ---------------------------------------------------------
it.printf(252, 340, id(font_mdi_extra_large), color_black, TextAlign::TOP_CENTER, "%s", weather_icon_map[id(weather_condition_now).state.c_str()].c_str());
// ----------------------------------------------------------------------------------- TEMPERATURA ---------------------------------------------------------------
it.printf(330, 482, id(font_large_bold), color_black, TextAlign::TOP_RIGHT, "%.1f", id(weather_temperature).state);
it.printf(460, 508, id(font_large_bold_c), color_black, TextAlign::TOP_RIGHT, "°C");
// ----------------------------------------------------------------------------------- Prognoza + 1 ---------------------------------------------------------------
if(id(weather_temperature_0).has_state ()) {
it.printf(83, 602, id(font_small_bold), color_black, TextAlign::TOP_CENTER, "%s", id(weather_timestamp_0).state.c_str());
it.printf(83, 630, id(font_mdi_medium), color_black, TextAlign::TOP_CENTER, "%s", weather_icon_map[id(weather_condition_0).state.c_str()].c_str());
it.printf(83, 680, id(font_small_bold), color_black, TextAlign::TOP_CENTER, "%2.0f°C", id(weather_temperature_0).state);
}
// ----------------------------------------------------------------------------------- Prognoza + 2 ---------------------------------------------------------------
if(id(weather_temperature_1).has_state ()) {
it.printf(195, 602, id(font_small_bold), color_black, TextAlign::TOP_CENTER, "%s", id(weather_timestamp_1).state.c_str());
it.printf(195, 630, id(font_mdi_medium), color_black, TextAlign::TOP_CENTER, "%s", weather_icon_map[id(weather_condition_1).state.c_str()].c_str());
it.printf(195, 680, id(font_small_bold), color_black, TextAlign::TOP_CENTER, "%2.0f°C", id(weather_temperature_1).state);
}
// ----------------------------------------------------------------------------------- Prognoza + 3 ---------------------------------------------------------------
if(id(weather_temperature_2).has_state ()) {
it.printf(305, 602, id(font_small_bold), color_black, TextAlign::TOP_CENTER, "%s", id(weather_timestamp_2).state.c_str());
it.printf(305, 630, id(font_mdi_medium), color_black, TextAlign::TOP_CENTER, "%s", weather_icon_map[id(weather_condition_2).state.c_str()].c_str());
it.printf(305, 680, id(font_small_bold), color_black, TextAlign::TOP_CENTER, "%2.0f°C", id(weather_temperature_2).state);
}
// ----------------------------------------------------------------------------------- Prognoza + 4 ---------------------------------------------------------------
if(id(weather_temperature_3).has_state ()) {
it.printf(415, 602, id(font_small_bold), color_black, TextAlign::TOP_CENTER, "%s", id(weather_timestamp_3).state.c_str());
it.printf(415, 630, id(font_mdi_medium), color_black, TextAlign::TOP_CENTER, "%s", weather_icon_map[id(weather_condition_3).state.c_str()].c_str());
it.printf(415, 680, id(font_small_bold), color_black, TextAlign::TOP_CENTER, "%2.0f°C", id(weather_temperature_3).state);
}
}