substitutions:
  name: epaperframe
  friendly_name: "Info-Dashboard"

esphome:
  name: ${name}
  friendly_name: ${friendly_name}
  name_add_mac_suffix: false
  project:
    name: dashboard.epaper
    version: "1.0"
  min_version: 2022.4.0

  on_boot:
    priority: -10
    then:
      - delay: 10s
      - display.page.show: power # temporary for power page dev
      - component.update: epaper

esp32:
  board: nodemcu-32s
  framework:
    type: arduino

wifi:
  ssid: "Voltage-legacy"
  password: !secret voltage_legacy_psk
  use_address: epaperframe.home
  power_save_mode: high
  fast_connect: on

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Epaperframe Fallback Hotspot"
    password: !secret fallback_psk

captive_portal:

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: !secret apikey

ota:
  platform: esphome
  password: !secret ota

# Power key of li-ion charger
output:
  - platform: gpio
    pin:
      number: GPIO15
      inverted: true
      mode:
        output: true
    id: power_key

# Refresh screen on button click
binary_sensor:
  - platform: gpio
    pin:
      number: GPIO18
      mode: INPUT_PULLUP
      inverted: True
    name: "Refresh screen"
    internal: True
    on_multi_click:
      - timing:
          - ON for at most 1s
          - OFF for at most 0.3s
          - ON for at most 1s
          - OFF for at least 0.2s
        then:
          - logger.log:
              level: INFO
              format: 'Button doubleclick, rendering next page!'
          - display.page.show_next: epaper
          - component.update: epaper
      - timing:
          - ON for at most 1s
          - OFF for at least 0.5s
        then:
          - logger.log:
              level: INFO
              format: 'Button click, refreshing screen!'
          - component.update: epaper

# HA pushbutton configuration
button:
  - platform: template
    name: Refresh screen
    id: refresh_button
    icon: "mdi:refresh"
    on_press:
      - logger.log:
          level: INFO
          format: 'HA Button click, refreshing screen!'
      - component.update: epaper
  - platform: template
    name: Next screen
    id: next_button
    icon: "mdi:skip-next"
    on_press:
      - logger.log:
          level: INFO
          format: 'HA Button click, rendering next page!'
      - display.page.show_next: epaper
      - component.update: epaper

sensor:
  # WiFi signal strength
  - platform: wifi_signal
    name: "WiFi Signalstärke"
    id: wifisignal
    update_interval: 60s

  - platform: homeassistant
    entity_id: sensor.livingroom_wohnzimmer_feinstaub_pm_2_5_m
    id: pm25_livingroom

  - platform: homeassistant
    entity_id: sensor.wohnzimmer_temperatur
    id: temp_livingroom

  - platform: homeassistant
    entity_id: sensor.wohnzimmer_luftfeuchtigkeit
    id: humid_livingroom

  - platform: homeassistant
    entity_id: sensor.wohnzimmer_co2
    id: co2_livingroom

  - platform: homeassistant
    entity_id: sensor.sleepingroom_feinstaub_pm_2_5_m
    id: pm25_sleepingroom

  - platform: homeassistant
    entity_id: sensor.schlafzimmer_temperatur
    id: temp_sleepingroom

  - platform: homeassistant
    entity_id: sensor.schlafzimmer_luftfeuchtigkeit
    id: humid_sleepingroom

  - platform: homeassistant
    entity_id: sensor.schlafzimmer_co2
    id: co2_sleepingroom

  - platform: homeassistant
    entity_id: sensor.aussentemperatur
    id: temp_outdoor

  - platform: homeassistant
    entity_id: sensor.aussenluftfeuchtigkeit
    id: humid_outdoor

  - platform: homeassistant
    entity_id: sensor.serverroom_luftdruck
    id: airpressure

  - platform: homeassistant
    entity_id: sensor.serverroom_serveraum_temperatur
    id: temp_serverroom

  - platform: homeassistant
    entity_id: sensor.netzleistung
    id: power_total

  - platform: homeassistant
    entity_id: sensor.serverraum_power
    id: power_serverroom

  - platform: homeassistant
    entity_id: sensor.schreibtisch_power
    id: desk_livingroom

  - platform: homeassistant
    entity_id: sensor.wohnzimmer_heimkino_power
    id: media_livingroom

  - platform: homeassistant
    entity_id: sensor.schlafzimmer_bett_power
    id: bedlight_sleepingroom
    
  - platform: homeassistant
    entity_id: sensor.schlafzimmer_heimkino_power
    id: media_sleepingroom
  
  - platform: homeassistant
    entity_id: sensor.radioaktive_strahlungsleistung
    id: radiation

text_sensor:
  - platform: homeassistant
    name: "Sun Rising ESP"
    entity_id: sensor.sun_rising_template
    id: sun_rising
    internal: true
    
  - platform: homeassistant
    name: "Sun Setting ESP"
    entity_id: sensor.sun_setting_template
    id: sun_setting
    internal: true

  - platform: homeassistant
    entity_id: sensor.moon
    id: moonphase

  - platform: homeassistant
    entity_id: weather.zuhause
    id: weather

  - platform: homeassistant
    entity_id: sensor.schlafzimmer_co2_warnstufe
    id: szco2

  - platform: homeassistant
    entity_id: sensor.schlafzimmer_feinstaub_warnstufe
    id: szpm

  - platform: homeassistant
    entity_id: sensor.wohnzimmer_co2_warnstufe
    id: wzco2

  - platform: homeassistant
    entity_id: sensor.wohnzimmer_feinstaub_warnstufe
    id: wzpm

graph:
  - id: line_power_graph
    sensor: power_total
    duration: 2h
    width: 235
    height: 100

time:
  - platform: homeassistant
    id: homeassistant_time
    on_time:
    # Every 10 seconds
    - seconds: /10
      then:
      - logger.log:
          level: INFO
          format: 'Power button press'
      - output.turn_on: power_key
      - delay: 0.5s
      - output.turn_off: power_key
    # Every 10 minutes
    - seconds: 0
      minutes: /10
      then:
      - logger.log:
          level: INFO
          format: 'Timer based screen refresh'
      - component.update: epaper

# Font definitions
font:
  - file: 'fonts/Roboto-Medium.ttf'
    id: roboto_med_30
    size: 30

  - file: 'fonts/Roboto-Regular.ttf'
    id: footer_font
    size: 15
    glyphs:
      ['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°', 
       '1', '2', '3', '4', '5', '6', '7', '8', '9', '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', 'Ä', 'ä', 'ö', '/', 'º', 'µ', '³', 'ß', 
       'Ü', 'ü', 'Ö', '0']

  - file: 'fonts/Roboto-Regular.ttf'
    id: sensor_unit
    size: 20
    glyphs:
      ['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°',
       '1', '2', '3', '4', '5', '6', '7', '8', '9', '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', 'Ä', 'ä', 'ö', '/', 'º', 'µ', '³', 'ß', 
       'Ü', 'ü', 'Ö', '0']

  - file: 'fonts/Roboto-Medium.ttf'
    id: sub_sensor_font
    size: 30
    glyphs:
      ['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°',
       '1', '2', '3', '4', '5', '6', '7', '8', '9', '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', 'Ä', 'ä', 'ö', '/', 'º', 'µ', '³', 'ß', 
       'Ü', 'ü', 'Ö', '0']

  - file: 'fonts/Roboto-Bold.ttf'
    id: big_sensor_font
    size: 50
    glyphs:
      ['&', '@', '!', ',', '.', '"', '%', '(', ')', '+', '-', '_', ':', '°',
       '1', '2', '3', '4', '5', '6', '7', '8', '9', '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', 'Ä', 'ä', 'ö', '/', 'º', 'µ', '³', 'ß', 
       'Ü', 'ü', 'Ö', '0']

  - file: 'fonts/materialdesignicons-webfont.ttf'
    id:  mdi_small
    size: 31
    glyphs: [
      '󰔏', # mdi-thermometer
      '󰖎', # mdi-water-percent
      '󰮬', # mdi-molecule (pm2.5)
      '󰟤', # mdi-co2
      '󰊚', # mdi-gauge (air pressure)
      '󰖙', # mdi-weather-sunny
      '󰖛', # mdi-weather-sunset-down
      '󰖜', # mdi-weather-sunset-up
      '󱐋', # mdi-lightning-bolt
      '󰴾', # mdi-transmission-tower
      '󰚥', # mdi-power-plug
      '󱈹', # mdi-desk
      '󰔂', # mdi-television
      '󰐼' # mdi-radiation
      ]

  - file: 'fonts/materialdesignicons-webfont.ttf'
    id:  mdi_weather
    size: 80
    glyphs: [
      '󰽡', # mdi-moon-first-quarter
      '󰽢', # mdi-moon-full
      '󰽣', # mdi-moon-last-quarter
      '󰽤', # mdi-moon-new
      '󰽥', # mdi-moon-waning-crescent
      '󰽦', # mdi-moon-waning-gibbous
      '󰽧', # mdi-moon-waxing-crescent
      '󰽨', # mdi-moon-waxing-gibbous
      '󰖔', # mdi-weather-night
      '󰖐', # mdi-weather-cloudy
      '󰖑', # mdi-weather-fog
      '󰖒', # mdi-weather-hail
      '󰖓', # mdi-weather-lightning
      '󰙾', # mdi-weather-lightning-rainy
      '󰖕', # mdi-weather-partly-cloudy
      '󰖖', # mdi-weather-pouring
      '󰖗', # mdi-weather-rainy
      '󰖘', # mdi-weather-snowy
      '󰙿', # mdi-weather-snowy-rainy
      '󰖙', # mdi-weather-sunny
      '󰖝', # mdi-weather-windy
      '󰖞', # mdi-weather-windy-variant
      '󰳥' # mdi-weather-exceptional
      ]

  - file: 'fonts/materialdesignicons-webfont.ttf'
    id:  mdi_wifi
    size: 20
    glyphs: [
      # WiFi
      '󰤫', # mdi-wifi-strength-alert-outline
      '󰤟', # mdi-wifi-strength-1
      '󰤢', # mdi-wifi-strength-2
      '󰤥', # mdi-wifi-strength-3
      '󰤨'  # mdi-wifi-strength-4
      ]

  - file: 'fonts/materialdesignicons-webfont.ttf'
    id:  mdi_med
    size: 60
    glyphs: [
      '󰀦' # mdi-alert
      ]

image:
  - file: "epaperframe/C1024_logo_flat_bw.png"
    id: c1024_logo
    type: binary
    resize: 77x40

spi:
  clk_pin: 23
  mosi_pin: 22

display:
  - platform: waveshare_epaper
    id: epaper
    cs_pin: 19
    dc_pin: 21
    busy_pin: 16
    reset_pin: 17
    model: 7.50in
    # full_update_every: 30 # not supported on this display
    update_interval: never
    pages:
      - id: environment
        lambda: |-

          float outdoor_temp = id(temp_outdoor).state;
          int outdoor_humid = int(id(humid_outdoor).state);
          float air_pressure = id(airpressure).state;
          float outdoor_radiation = id(radiation).state;
          float livingroom_temp = id(temp_livingroom).state;
          int livingroom_humid = int(id(humid_livingroom).state);
          int livingroom_pm25 = int(id(pm25_livingroom).state);
          float livingroom_co2 = id(co2_livingroom).state;
          float sleepingroom_temp = id(temp_sleepingroom).state;
          int sleepingroom_humid = int(id(humid_sleepingroom).state);
          int sleepingroom_pm25 = int(id(pm25_sleepingroom).state);
          float sleepingroom_co2 = id(co2_sleepingroom).state;
          float serverroom_temp = id(temp_serverroom).state;
          int offsetX = 0;
          int offsetY = 0;

          /* OUTSIDE */
          it.print(10, 10, id(sensor_unit), "Umwelt");
          /*
          Draw the outline of a rectangle with the top left at [86,21],
          a width of 297 and a height of 3
          */
          it.filled_rectangle(86, 21, 297, 3);

          /* C1024 logo */
          it.image(10 , 37, id(c1024_logo));

          it.print(10, 130, id(mdi_small), TextAlign::BASELINE_LEFT, "󰊚"); // air pressure icon
          it.print(375, 80,  id(mdi_small), TextAlign::BASELINE_CENTER, "󰔏"); // thermometer icon
          it.print(375, 130, id(mdi_small), TextAlign::BASELINE_CENTER, "󰖎"); // water percent icon
          it.print(95, 80,  id(mdi_small), TextAlign::BASELINE_LEFT, "󰐼"); // radioactive icon

          if(outdoor_radiation >= 0) {
            it.printf(200, 80, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, "%2.2f", outdoor_radiation);
            it.print(205, 80, id(sensor_unit), TextAlign::BASELINE_LEFT, "µS/h");
          }
          else {
            it.print(200, 80, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, " - ");
            it.print(205, 80, id(sensor_unit), TextAlign::BASELINE_LEFT, "µS/h");
          }

          if(outdoor_temp > -100 && outdoor_temp < 100) {
            it.printf(357, 80, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, "%2.1fºC", outdoor_temp);
          }
          else {
            it.print(357, 80, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, " - ºC");
          }

          if(outdoor_humid >=0 && outdoor_humid <= 100) {
            it.printf(357, 130, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, "%3d%%", outdoor_humid);
          }
          else {
            it.print(357, 130, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, " -  %");
          }

          if(air_pressure < 1200 && air_pressure >=700) {
            it.printf(220, 130, id(big_sensor_font), TextAlign::BASELINE_RIGHT, "%4.1f", air_pressure);
            it.print(225, 130, id(sensor_unit), TextAlign::BASELINE_LEFT, "hPa");
          }
          else {
            it.print(220, 130, id(big_sensor_font), TextAlign::BASELINE_RIGHT, "- ");
            it.print(225, 130, id(sensor_unit), TextAlign::BASELINE_LEFT, "hPa");
          }


          /* Livingroom */
          offsetY = 127;
          it.print(10, 10 + offsetY, id(sensor_unit), "Wohnzimmer");
          it.filled_rectangle(136, 21 + offsetY, 247, 3);
          it.print(10, 125 + offsetY, id(mdi_small), TextAlign::BASELINE_LEFT, "󰮬"); // PM2.5
          it.print(375, 75 + offsetY,  id(mdi_small), TextAlign::BASELINE_CENTER, "󰔏"); // thermometer
          it.print(375, 125 + offsetY, id(mdi_small), TextAlign::BASELINE_CENTER, "󰖎"); // water percent
          it.print(10, 75 + offsetY, id(mdi_small), TextAlign::BASELINE_LEFT, "󰟤"); // CO2


          if(livingroom_temp > -100 && livingroom_temp < 100) {
            it.printf(357, 75 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, "%2.1fºC", livingroom_temp);
          }
          else {
            it.print(357, 75 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, " - ºC");
          }

          if(livingroom_humid >=0 && livingroom_humid <= 100) {
            it.printf(357, 125 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, "%3d%%", livingroom_humid);
          }
          else {
            it.print(357, 125 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, " -  %");
          }

          if(livingroom_co2 >=380 && livingroom_co2 <= 20000) {
            it.printf(170, 75 + offsetY, id(big_sensor_font), TextAlign::BASELINE_RIGHT, "%4.0f", livingroom_co2);
            it.print(175, 50 + offsetY, id(sensor_unit), TextAlign::BASELINE_LEFT, "ppm");
          }
          else {
            it.print(170, 75 + offsetY, id(big_sensor_font), TextAlign::BASELINE_RIGHT, "- ");
            it.print(175, 50 + offsetY, id(sensor_unit), TextAlign::BASELINE_LEFT, "ppm³");
          }

          if(livingroom_pm25 < 255 && livingroom_pm25 >=0) {
            it.printf(220, 125 + offsetY, id(big_sensor_font), TextAlign::BASELINE_RIGHT, "%3d", livingroom_pm25);
            it.print(225, 125 + offsetY, id(sensor_unit), TextAlign::BASELINE_LEFT, "µg/m³");
          }
          else {
            it.print(220, 125 + offsetY, id(big_sensor_font), TextAlign::BASELINE_RIGHT, "- ");
            it.print(225, 125 + offsetY, id(sensor_unit), TextAlign::BASELINE_LEFT, "µg/m³");
          }


          /* Sleepingroom */
          offsetY = 247;
          it.print(10, 10 + offsetY, id(sensor_unit), "Schlafzimmer");
          it.filled_rectangle(144, 21 + offsetY, 239, 3);
          it.print(10, 124 + offsetY, id(mdi_small), TextAlign::BASELINE_LEFT, "󰮬"); // PM2.5
          it.print(375, 75 + offsetY,  id(mdi_small), TextAlign::BASELINE_CENTER, "󰔏"); // thermometer
          it.print(375, 124 + offsetY, id(mdi_small), TextAlign::BASELINE_CENTER, "󰖎"); // water percent
          it.print(10, 75 + offsetY, id(mdi_small), TextAlign::BASELINE_LEFT, "󰟤"); // CO2


          if(sleepingroom_temp > -100 && sleepingroom_temp < 100) {
            it.printf(357, 75 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, "%2.1fºC", sleepingroom_temp);
          }
          else {
            it.print(357, 75 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, " - ºC");
          }

          if(sleepingroom_humid >=0 && sleepingroom_humid <= 100) {
            it.printf(357, 125 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, "%3d%%", sleepingroom_humid);
          }
          else {
            it.print(357, 125 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, " -  %");
          }

          if(sleepingroom_co2 >=380 && sleepingroom_co2 <= 20000) {
            it.printf(170, 75 + offsetY, id(big_sensor_font), TextAlign::BASELINE_RIGHT, "%4.0f", sleepingroom_co2);
            it.print(175, 50 + offsetY, id(sensor_unit), TextAlign::BASELINE_LEFT, "ppm");
          }
          else {
            it.print(170, 75 + offsetY, id(big_sensor_font), TextAlign::BASELINE_RIGHT, "- ");
            it.print(175, 50 + offsetY, id(sensor_unit), TextAlign::BASELINE_LEFT, "ppm³");
          }

          if(sleepingroom_pm25 < 255 && sleepingroom_pm25 >=0) {
            it.printf(220, 125 + offsetY, id(big_sensor_font), TextAlign::BASELINE_RIGHT, "%3d", sleepingroom_pm25);
            it.print(225, 125 + offsetY, id(sensor_unit), TextAlign::BASELINE_LEFT, "µg/m³");
          }
          else {
            it.print(220, 125 + offsetY, id(big_sensor_font), TextAlign::BASELINE_RIGHT, "- ");
            it.print(225, 125 + offsetY, id(sensor_unit), TextAlign::BASELINE_LEFT, "µg/m³");
          }

          /* Weather */
          offsetX = 390;
          it.print(10 + offsetX, 10, id(sensor_unit), "Wetter");
          it.filled_rectangle(80 + offsetX, 21, 155, 3);

          /* Current weather */
          if(id(weather).has_state()) {
            int x = 227 + offsetX;
            int y = 116;
            if (id(weather).state == "clear-night") {
                // clear night
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_RIGHT, "󰖔");
                ESP_LOGI("Weather", "clear night");
            } else if (id(weather).state  == "cloudy") {
                // cloudy
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_RIGHT, "󰖐");
                ESP_LOGI("Weather", "cloudy");
            } else if (id(weather).state  == "fog") {
                // fog
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_RIGHT, "󰖑");
                ESP_LOGI("Weather", "fog");
            } else if (id(weather).state  == "hail") {
                // hail
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_RIGHT, "󰖒");
                ESP_LOGI("Weather", "hail");
            } else if (id(weather).state  == "lightning") {
                // lightning
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_RIGHT, "󰖓");
                ESP_LOGI("Weather", "lightning");
            } else if (id(weather).state  == "lightning-rainy") {
                // lightning-rainy
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_RIGHT, "󰙾");
                ESP_LOGI("Weather", "lightning-rainy");
            } else if (id(weather).state  == "partlycloudy") {
                // partly cloudy
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_RIGHT, "󰖕");
                ESP_LOGI("Weather", "partlycloudy");
            } else if (id(weather).state  == "pouring") {
                // pouring
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_RIGHT, "󰖖");
                ESP_LOGI("Weather", "pouring");
            } else if (id(weather).state  == "rainy") {
                // rainy
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_RIGHT, "󰖗");
                ESP_LOGI("Weather", "rainy");
            } else if (id(weather).state  == "snowy") {
                // snowy
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_RIGHT, "󰖘");
                ESP_LOGI("Weather", "snowy");
            } else if (id(weather).state  == "snowy-rainy") {
                // snowy-rainy
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_RIGHT, "󰙿");
                ESP_LOGI("Weather", "snowy-rainy");
            } else if (id(weather).state  == "sunny") {
                // sunny
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_RIGHT, "󰖙");
                ESP_LOGI("Weather", "sunny");
            } else if (id(weather).state  == "windy") {
                // windy
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_RIGHT, "󰖝");
                ESP_LOGI("Weather", "windy");
            } else if (id(weather).state  == "windy-variant") {
                // windy variant
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_RIGHT, "󰖞");
                ESP_LOGI("Weather", "windy variant");
            } else if (id(weather).state  == "exceptional") {
                // exceptional
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_RIGHT, "󰳥");
                ESP_LOGI("Weather", "exceptional");
            } else {
                // N/A
                it.print(x, y, id(big_sensor_font), TextAlign::BASELINE_RIGHT, "-");
                ESP_LOGE("Weather", "No data");
            }
          }

          /* Moon phase display */
          if(id(moonphase).has_state()) {
            int x = 10 + offsetX;
            int y = 116;
            if (id(moonphase).state == "new_moon") {
                // new moon
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_LEFT, "󰽤");
                ESP_LOGI("Moonphase", "new moon");
            } else if (id(moonphase).state  == "waxing_crescent") {
                // waxing crescent
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_LEFT, "󰽧");
                ESP_LOGI("Moonphase", "waxing crescent");
            } else if (id(moonphase).state  == "first_quarter") {
                // first_quarter
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_LEFT, "󰽡");
                ESP_LOGI("Moonphase", "first quarter");
            } else if (id(moonphase).state  == "waxing_gibbous") {
                // waxing gibbous
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_LEFT, "󰽨");
                ESP_LOGI("Moonphase", "waxing gibbous");
            } else if (id(moonphase).state  == "full_moon") {
                // full moon
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_LEFT, "󰽢");
                ESP_LOGI("Moonphase", "full moon");
            } else if (id(moonphase).state  == "waning_gibbous") {
                // waning gibbous
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_LEFT, "󰽦");
                ESP_LOGI("Moonphase", "waning gibbous");
            } else if (id(moonphase).state  == "last_quarter") {
                // last quarter
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_LEFT, "󰽣");
                ESP_LOGI("Moonphase", "last quarter");
            } else if (id(moonphase).state  == "waning_crescent") {
                // waning crescent
                it.print(x, y, id(mdi_weather), TextAlign::BASELINE_LEFT, "󰽥");
                ESP_LOGI("Moonphase", "waning crescent");
            } else {
                // N/A
                it.print(x, y, id(big_sensor_font), TextAlign::BASELINE_LEFT, "-");
                ESP_LOGE("Moonphase", "No data");
            }
          }

          /* Warnings */
          if(id(szco2).state == "rot" || id(szpm).state == "rot" || id(wzco2).state == "rot" || id(wzpm).state == "rot") {
            it.print(10 + offsetX, 200, id(mdi_med), TextAlign::BASELINE_LEFT, "󰀦");
            it.print(80 + offsetX, 200, id(big_sensor_font), TextAlign::BASELINE_LEFT, "Lüften!");
          }

          it.print(10 + offsetX, 250, id(mdi_small), TextAlign::BASELINE_LEFT, "󰖜"); // sun-up
          it.printf(50 + offsetX, 250, id(sensor_unit), TextAlign::BASELINE_LEFT, "%s", id(sun_rising).state.c_str());
          it.print(135 + offsetX, 250, id(mdi_small), TextAlign::BASELINE_LEFT, "󰖛"); // sun-down
          it.printf(175 + offsetX, 250, id(sensor_unit), TextAlign::BASELINE_LEFT, "%s", id(sun_setting).state.c_str());

          /* Serverroom */
          offsetY = 247;
          it.print(10 + offsetX, 10 + offsetY, id(sensor_unit), "Serverraum");
          it.filled_rectangle(125 + offsetX, 21 + offsetY, 110, 3);

          it.print(227 + offsetX, 110 + offsetY,  id(mdi_small), TextAlign::BASELINE_CENTER, "󰔏"); // thermometer

          if(serverroom_temp > -100 && serverroom_temp < 100) {
            it.printf(207 + offsetX, 110 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, "ºC");
            it.printf(170 + offsetX, 110 + offsetY, id(big_sensor_font), TextAlign::BASELINE_RIGHT, "%2.1f", serverroom_temp);
          }
          else {
            it.print(207 + offsetX, 110 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, " - ºC");
          }

          /* FOOTER */
          it.strftime(614, 380, id(footer_font), TextAlign::BASELINE_RIGHT , "Aktualisiert um %d.%m.%Y %H:%M", id(homeassistant_time).now());

          /* WiFi Signal Strenght */
          if(id(wifisignal).has_state()) {
            int x = 630;
            int y = 384;
            if (id(wifisignal).state >= -50) {
                // Excellent
                it.print(x, y, id(mdi_wifi), TextAlign::BASELINE_CENTER, "󰤨");
                ESP_LOGI("WiFi", "Excellent");
            } else if (id(wifisignal).state  >= -60) {
                // Good
                it.print(x, y, id(mdi_wifi), TextAlign::BASELINE_CENTER, "󰤥");
                ESP_LOGI("WiFi", "Good");
            } else if (id(wifisignal).state  >= -75) {
                // Fair
                it.print(x, y, id(mdi_wifi), TextAlign::BASELINE_CENTER, "󰤢");
                ESP_LOGI("WiFi", "Fair");
            } else if (id(wifisignal).state  >= -100) {
                // Weak
                it.print(x, y, id(mdi_wifi), TextAlign::BASELINE_CENTER, "󰤟");
                ESP_LOGI("WiFi", "Weak");
            } else {
                // Unlikely working signal
                it.print(x, y, id(mdi_wifi), TextAlign::BASELINE_CENTER, "󰤫");
                ESP_LOGI("WiFi", "Unlikely");
            }
          }
      - id: power
        lambda: |-

          float total_power = id(power_total).state;
          float serverroom_power = id(power_serverroom).state;
          float livingroom_desk = id(desk_livingroom).state;
          float livingroom_media = id(media_livingroom).state;
          float sleepingroom = id(media_sleepingroom).state + id(bedlight_sleepingroom).state;
          int offsetX = 0;
          int offsetY = 0;

          /* BASEMENT */
          it.print(10, 10, id(sensor_unit), "Keller");
          /*
          Draw the outline of a rectangle with the top left at [86,21],
          a width of 297 and a height of 3
          */
          it.filled_rectangle(76, 21, 307, 3);

          /* C1024 logo */
          it.image(10 , 37, id(c1024_logo));

          /* Livingroom */
          offsetY = 127;
          it.print(10, 10 + offsetY, id(sensor_unit), "Wohnzimmer");
          it.filled_rectangle(136, 21 + offsetY, 247, 3);
          
          it.print(375, 75 + offsetY,  id(mdi_small), TextAlign::BASELINE_CENTER, "󰚥"); // power-plug
          it.print(375, 115 + offsetY, id(mdi_small), TextAlign::BASELINE_CENTER, "󰚥"); // power-plug

          it.print(20, 75 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_LEFT, "Schreibtisch");
          if(livingroom_desk >= 0) {
            it.printf(357, 75 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, "%2.1f W", livingroom_desk);
          }
          else {
            it.print(357, 75 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, " -  W");
          }

          it.print(20, 115 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_LEFT, "Heimkino");
          if(livingroom_media >= 0) {
            it.printf(357, 115 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, "%2.1f W", livingroom_media);
          }
          else {
            it.print(357, 115 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, " -  W");
          }

          /* Sleepingroom */
          offsetY = 247;
          it.print(10, 10 + offsetY, id(sensor_unit), "Schlafzimmer");
          it.filled_rectangle(144, 21 + offsetY, 239, 3);

          it.print(375, 115 + offsetY, id(mdi_small), TextAlign::BASELINE_CENTER, "󰚥"); // power-plug

          // it.print(20, 115 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_LEFT, "Heimkino");
          if(sleepingroom >= 0) {
            it.printf(357, 115 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, "%2.1f W", sleepingroom);
          }
          else {
            it.print(357, 115 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, " -  W");
          }

          /* LINEPOWER */
          offsetX = 390;
          offsetY = 65;
          it.print(10 + offsetX, 10, id(sensor_unit), "Gesamt");
          it.filled_rectangle(90 + offsetX, 21, 155, 3);

          it.print(227 + offsetX, 20 + offsetY,  id(mdi_small), TextAlign::BASELINE_CENTER, "󰴾"); // transmission-tower

          if(total_power >= 0) {
            it.printf(207 + offsetX, 20 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, "W");
            it.printf(170 + offsetX, 20 + offsetY, id(big_sensor_font), TextAlign::BASELINE_RIGHT, "%2.1f", total_power);
          }
          else {
            it.print(207 + offsetX, 20 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, " - W");
          }

          it.graph(10 + offsetX, 30 + offsetY, id(line_power_graph));

          /* Serverroom */
          offsetY = 247;
          it.print(10 + offsetX, 10 + offsetY, id(sensor_unit), "Serverraum");
          it.filled_rectangle(125 + offsetX, 21 + offsetY, 110, 3);

          it.print(227 + offsetX, 110 + offsetY,  id(mdi_small), TextAlign::BASELINE_CENTER, "󰚥"); // power-plug

          if(serverroom_power >= 0) {
            it.printf(207 + offsetX, 110 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, "W");
            it.printf(170 + offsetX, 110 + offsetY, id(big_sensor_font), TextAlign::BASELINE_RIGHT, "%2.1f", serverroom_power);
          }
          else {
            it.print(207 + offsetX, 110 + offsetY, id(sub_sensor_font), TextAlign::BASELINE_RIGHT, " - W");
          }

          /* FOOTER */
          it.strftime(614, 380, id(footer_font), TextAlign::BASELINE_RIGHT , "Aktualisiert um %d.%m.%Y %H:%M", id(homeassistant_time).now());

          /* WiFi Signal Strenght */
          if(id(wifisignal).has_state()) {
            int x = 630;
            int y = 384;
            if (id(wifisignal).state >= -50) {
                // Excellent
                it.print(x, y, id(mdi_wifi), TextAlign::BASELINE_CENTER, "󰤨");
                ESP_LOGI("WiFi", "Excellent");
            } else if (id(wifisignal).state  >= -60) {
                // Good
                it.print(x, y, id(mdi_wifi), TextAlign::BASELINE_CENTER, "󰤥");
                ESP_LOGI("WiFi", "Good");
            } else if (id(wifisignal).state  >= -75) {
                // Fair
                it.print(x, y, id(mdi_wifi), TextAlign::BASELINE_CENTER, "󰤢");
                ESP_LOGI("WiFi", "Fair");
            } else if (id(wifisignal).state  >= -100) {
                // Weak
                it.print(x, y, id(mdi_wifi), TextAlign::BASELINE_CENTER, "󰤟");
                ESP_LOGI("WiFi", "Weak");
            } else {
                // Unlikely working signal
                it.print(x, y, id(mdi_wifi), TextAlign::BASELINE_CENTER, "󰤫");
                ESP_LOGI("WiFi", "Unlikely");
            }
          }