## You can change the friendly name if you wish on line 7 below. The friendly name is how the device will show in HA
## However the <name:> is how HA connects to the device eg. esp32-s3-box-3.local is the mDNS hostname for the device.
## Once added to HA changing the device name can lead to connection issues, between HA and the device.

substitutions:
  name: "larry"
  friendly_name: larry

  external_media_player: your_media_player  ##change this to your external media player enity_id: do not include media_player.
  home_assistant_host: http://nookie.nex:8123 ##change to the full url or IP of your HA server including port
  tts_voice_speed: "16000" #options #nabu casa "24000" #piper "16000" elevenlabs "44100" must include quotes
  
#################### ON DEVICE WAKE WORDS #######################################
####          all of the below wakewords are installed on the device        #####
####      you can use any of these without re-compiling - just say them!    #####
#################################################################################
# TO REMOVE A WAKE WORD - COMMENT OUT THE CORESPONDING LINE FROM THE CONFIG BELOW - CTRL + F to search for "models"
  micro_wake_word_model_1: okay_nabu
  micro_wake_word_model_2: "https://raw.githubusercontent.com/esphome/micro-wake-word-models/refs/heads/main/models/v2/experiments/choo_choo_homie.json"
  micro_wake_word_model_3: hey_jarvis
  micro_wake_word_model_4: "https://raw.githubusercontent.com/esphome/micro-wake-word-models/refs/heads/main/models/v2/experiments/okay_computer.json"
####################################################################

#####  Days and months #####
## Change the values on the right to match your locale ##
  monday: Monday
  tuesday: Tuesday
  wednesday: Wednesday
  thursday: Thursday
  friday: Friday
  saturday: Saturday
  sunday: Sunday

  jan: January
  feb: February
  mar: March
  apr: April
  may: May
  jun: June
  jul: July
  aug: August
  sept: September
  oct: October
  nov: November
  dec: December
#####################################################################

##### DO NOT CHANGE SUBSTITUTIONS BELOW THIS LINE ######
#####      UNLESS YOU KNOW WHAT YOU ARE DOING     ######
  font_glyphs: '&@!"''%()+=,-_.:°/$€£¥?0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyzÀàÁáÂâÃãÄäĀāĂăÅåǺǻẠạĄąÆæǼǽĆćĈĉČčĊċÇçĎďĐđÐðÈèÉéÊêẼẽĚěËëĒēĔĕĖėẸẹĘęĜĝǦǧĞğĠġĢģĤĥĦħıÌìÍíÎîĨĩÏïĪīĬĭİỊịĮįȷĴĵĶķĸĹ弾ĻļŁłĿŀŃńÑñŇňŅņƝɲŊŋʼnÒòÓóÔôÕõÖöŌōŎŏŐőỌọǪǫØøǾǿŒœŔŕŘřŖŗŚśŜŝŠšŞşȘșẞߍťŢţȚțŦŧÞþÙùÚúÛûŨũÜüŪūŬŭŮůŰűỤụŲųẀẁẂẃŴŵẄẅỲỳÝýŶŷỸỹŸÿȲȳŹźŽžŻżIJijƏə'

############# END OF SUBSTITUTIONS #################
####################################################

esphome:
  name: ${name}
  friendly_name: ${friendly_name}
  min_version: 2025.2.0
  on_boot:
    priority: 600
    then:
      - lambda: id(led).turn_on().set_brightness(id(s_default_brightness).state /100).perform();
      - display.page.show: loading_page
      - component.update: s3_box_lcd
      - script.execute: saver_enabled
      - lambda: id(time_remaining_0).publish_state ("0:00:00");
      - if:
          condition:
            switch.is_on: output_audio
          then:
            media_player.volume_set:
              id: speaker_media_player
              volume: 0
  project:
    name: "BigBobbas.s3box"
    version: "2024.09.02"
esp32:
  board: esp32s3box
  flash_size: 16MB
  framework:
    type: esp-idf
    sdkconfig_options:
      CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240: "y"
      CONFIG_ESP32S3_DATA_CACHE_64KB: "y"
      CONFIG_ESP32S3_DATA_CACHE_LINE_64B: "y"

psram:
  mode: octal
  speed: 80MHz

api:
  encryption:
    key: !secret api_key
  on_client_connected:
    - lambda: |-
        id(api_connection) = true;
    - lambda: id(led).turn_on().set_brightness(id(s_default_brightness).state /100).perform();
    - component.update: s3_box_lcd
    - script.execute: saver_enabled
  on_client_disconnected:
    - lambda: |-
        id(api_connection) = false;

ota:
  - platform: esphome
    on_begin:
      - lambda: id(led).turn_on().set_brightness(1.0).set_transition_length(0).perform();
                id(led).loop();
      - display.page.show: ota_page
      - component.update: s3_box_lcd

logger:
  hardware_uart: USB_SERIAL_JTAG
  logs:
    text_sensor: WARN
    component: ERROR

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  manual_ip:
    static_ip: 192.168.50.201
    gateway: 192.168.50.1
    subnet: 255.255.255.0

  ap:
    ssid: ${name}
    password: s3box123
  on_connect:
    - lambda: |-
        id(wifi_connection) = true;
    - display.page.show: idle_page
    - component.update: s3_box_lcd
    - switch.turn_on: speaker_enable
  on_disconnect:
    - lambda: |-
        id(wifi_connection) = false;

captive_portal:

time:
  - platform: homeassistant
    id: ha_time
    timezone: Europe/Vienna

interval:
  - interval: 30s
    then:
      - component.update: s3_box_lcd
  - interval: 10s
    then:
      - if:
          condition:
            - lambda: 'return { (id(api_connection) != true) };'
          then:
            - if:
                condition:
                  api.connected:
                then:
                  - lambda: "id(api_connection) = true;"
          else:
            - if:
                condition:
                  not:
                    api.connected:
                then:
                  - lambda: "id(api_connection) = false;"
  - interval: 10s
    then:
      - if:
          condition:
            - lambda: 'return { (id(wifi_connection) != true) };'
          then:
            - if:
                condition:
                  wifi.connected:
                then:
                  - lambda: "id(wifi_connection) = true;"
          else:
            - if:
                condition:
                  not:
                    wifi.connected:
                then:
                  - lambda: "id(wifi_connection) = false;"

select:
  - platform: template
    entity_category: config
    name: Wake word engine location
    id: wake_word_engine_location
    optimistic: true
    restore_value: true
    options:
      - In Home Assistant
      - On device
    initial_option: In Home Assistant
    on_value:
      - if:
          condition:
            lambda: return x == "In Home Assistant";
          then:
            - micro_wake_word.stop
            - delay: 500ms
            - lambda: id(va).set_use_wake_word(true);
            - voice_assistant.start_continuous:
            - text_sensor.template.publish:
                id: wakeword_location
                state: !lambda 'return "Home Assistant";'
            - component.update: s3_box_lcd
      - if:
          condition:
            lambda: return x == "On device";
          then:
            - text_sensor.template.publish:
                id: wakeword_location
                state: !lambda 'return "On Device";'
            - lambda: id(va).set_use_wake_word(false);
            - voice_assistant.stop
            - delay: 500ms
            - micro_wake_word.start
            - component.update: s3_box_lcd

  - platform: template
    entity_category: config
    name: Time Format
    id: time_format
    optimistic: true
    restore_value: true
    options:
      - 12 Hr
      - 24 Hr
    initial_option: 24 Hr
    on_value:
      then:
        - if:
            condition:
              lambda: return x == "24 Hr";
            then:
              - text_sensor.template.publish:
                  id: time_display_format
                  state: !lambda 'return "24 Hr";'
            else:
              - text_sensor.template.publish:
                  id: time_display_format
                  state: !lambda 'return "12 Hr";'
        - component.update: s3_box_lcd

script:
  - id: start_voice_assistant
    then:
      - if:
          condition:
            switch.is_off: mute_switch
          then:
            - if:
                condition:
                  lambda: return id(wake_word_engine_location).state == "In Home Assistant";
                then:
                  - lambda: id(va).set_use_wake_word(true);
                  - voice_assistant.start_continuous:
            - if:
                condition:
                  lambda: return id(wake_word_engine_location).state == "On device";
                then:
                  - lambda: id(va).set_use_wake_word(false);
                  - micro_wake_word.start

  - id: stop_voice_assistant
    then:
      - if:
          condition:
            lambda: return id(wake_word_engine_location).state == "In Home Assistant";
          then:
            - lambda: id(va).set_use_wake_word(false);
            - voice_assistant.stop:
      - if:
          condition:
            lambda: return id(wake_word_engine_location).state == "On device";
          then:
            - voice_assistant.stop:
            - micro_wake_word.stop:

  - id: set_volume
    then:
      - media_player.volume_set:
          volume: !lambda return 0.5 + id(speaker_volume) * 0.05 ;

  - id: saver_enabled
    then:
      - if:
          condition:
            switch.is_on: s_saver
          then:
            - lambda: id(led).turn_on().set_brightness(id(s_default_brightness).state /100).perform();
            - delay: !lambda return id(s_saver_delay).state * 1000;
            - lambda: id(led).turn_on().set_brightness(id(s_saver_brightness).state /100).perform();
            - display.page.show: saver_page
            - component.update: s3_box_lcd
      - if:
          condition:
            - switch.is_on: s_saver_mode
          then:
            - delay: !lambda return id(s_saver_blank_delay).state * 1000;
            - light.turn_off: led
    mode: restart

  - id: saver_enabled_manual
    then:
      - if:
          condition:
            - switch.is_on: s_saver
          then:
            - lambda: id(led).turn_on().set_brightness(id(s_saver_brightness).state /100).perform();
            - display.page.show: saver_page
            - component.update: s3_box_lcd
      - if:
          condition:
            - switch.is_on: s_saver_mode
          then:
            - delay: !lambda return id(s_saver_blank_delay).state * 1000;
            - light.turn_off: led
            - component.update: s3_box_lcd
    mode: restart

  # - id: timer_started
    # then:
      # while:
        # condition:
          # switch.is_on: timer_ringing
        # then:
          # - voice_assistant.stop
          # - delay: 150ms
          # - media_player.speaker.play_on_device_media_file:
              # media_file: wake_sound_file
              # announcement: true
          # - delay: 1s

  - id: timer_started_external
    then:
      while:
        condition:
          switch.is_on: timer_ringing
        then:
          - homeassistant.service:
              service: media_player.play_media
              data:
                entity_id: media_player.${external_media_player}
                media_content_id: '${home_assistant_host}/local/sounds/timer_finished.mp3'
                media_content_type: music
          - delay: 1700ms

  - id: timer_ending
    then:
      - wait_until:
          - lambda: return (id(time_remaining_0).state == "0:00:10");
      - script.execute: saver_enabled
      - display.page.show: time_remaining_page
      - component.update: s3_box_lcd

  - id: increment_digit_1
    then:
      - lambda: |-
          id(current_pin) += "1";
          ESP_LOGD("increment_digit_1", "Current PIN: %s", id(current_pin).c_str());

  - id: increment_digit_2
    then:
      - lambda: |-
          id(current_pin) += "2";
          ESP_LOGD("increment_digit_2", "Current PIN: %s", id(current_pin).c_str());

  - id: increment_digit_3
    then:
      - lambda: |-
          id(current_pin) += "3";
          ESP_LOGD("increment_digit_3", "Current PIN: %s", id(current_pin).c_str());

  - id: increment_digit_4
    then:
      - lambda: |-
          id(current_pin) += "4";
          ESP_LOGD("increment_digit_4", "Current PIN: %s", id(current_pin).c_str());

  - id: increment_digit_5
    then:
      - lambda: |-
          id(current_pin) += "5";
          ESP_LOGD("increment_digit_5", "Current PIN: %s", id(current_pin).c_str());

  - id: increment_digit_6
    then:
      - lambda: |-
          id(current_pin) += "6";
          ESP_LOGD("increment_digit_6", "Current PIN: %s", id(current_pin).c_str());

  - id: increment_digit_7
    then:
      - lambda: |-
          id(current_pin) += "7";
          ESP_LOGD("increment_digit_7", "Current PIN: %s", id(current_pin).c_str());

  - id: increment_digit_8
    then:
      - lambda: |-
          id(current_pin) += "8";
          ESP_LOGD("increment_digit_8", "Current PIN: %s", id(current_pin).c_str());

  - id: increment_digit_9
    then:
      - lambda: |-
          id(current_pin) += "9";
          ESP_LOGD("increment_digit_9", "Current PIN: %s", id(current_pin).c_str());

  - id: increment_digit_0
    then:
      - lambda: |-
          id(current_pin) += "0";
          ESP_LOGD("increment_digit_0", "Current PIN: %s", id(current_pin).c_str());
globals:
  - id: wifi_connection
    type: bool
    restore_value: no
    initial_value: "false"
  - id: api_connection
    type: bool
    restore_value: no
    initial_value: "false"
  - id: mute_value
    type: bool
    restore_value: no
    initial_value: "false"
  - id: speaker_volume
    type: int
    restore_value: no
    initial_value: '5'
  - id: media_state
    type: bool
    restore_value: no
    initial_value: "false"
  - id: global_first_active_timer
    type: voice_assistant::Timer
    restore_value: false
  - id: global_is_timer_active
    type: bool
    restore_value: false
  - id: global_first_timer
    type: voice_assistant::Timer
    restore_value: false
  - id: global_is_timer
    type: bool
    restore_value: false
  - id: current_pin
    type: std::string
    initial_value: ""
  - id: global_is_assisting
    type: bool
    restore_value: false

number:
  - id: s_saver_delay
    platform: template
    name: "Scr/save delay"
    icon: 'mdi:sleep'
    entity_category: config
    unit_of_measurement: 'secs'
    optimistic: true
    restore_value: true
    initial_value: 30
    step: 5
    min_value: 10
    max_value: 999999
    on_value:
      - component.update: s3_box_lcd
      - component.update: s_saver_delay
      - script.execute: saver_enabled

  - id: s_saver_blank_delay
    platform: template
    name: "Scr/off delay"
    icon: 'mdi:monitor-off'
    entity_category: config
    unit_of_measurement: 'secs'
    optimistic: true
    restore_value: true
    initial_value: 30
    step: 5
    min_value: 10
    max_value: 999999
    on_value:
      - component.update: s_saver_blank_delay
      - script.execute: saver_enabled
      - component.update: s3_box_lcd

  - id: s_saver_brightness
    platform: template
    name: "Scr/save Brightness"
    icon: 'mdi:sleep'
    entity_category: config
    unit_of_measurement: '%'
    optimistic: true
    restore_value: true
    initial_value: 30
    step: 5
    min_value: 20
    max_value: 100
    on_value:
      - component.update: s_saver_brightness
      - script.execute: saver_enabled
      - component.update: s3_box_lcd

  - id: s_default_brightness
    platform: template
    name: "Default Brightness"
    icon: 'mdi:monitor'
    entity_category: config
    unit_of_measurement: '%'
    optimistic: true
    restore_value: true
    initial_value: 100
    step: 5
    min_value: 20
    max_value: 100
    on_value:
      - component.update: s_default_brightness
      - script.execute: saver_enabled
      - component.update: s3_box_lcd
button:
  - platform: restart
    id: reboot
    name: "Reboot"
    entity_category: diagnostic

switch:
  - platform: gpio
    name: Speaker Enable
    id: speaker_enable
    pin: GPIO46
    restore_mode: ALWAYS_OFF
    entity_category: config
    disabled_by_default: true

  - platform: template
    name: Display conversation
    id: display_conversation
    optimistic: true
    restore_mode: RESTORE_DEFAULT_ON
    entity_category: config
    icon: 'mdi:chat'

  - platform: template
    name: Output audio externally
    id: output_audio
    icon: 'mdi:volume-off'
    optimistic: true
    restore_mode: RESTORE_DEFAULT_OFF
    entity_category: config
    on_turn_on:
      media_player.volume_set:
        id: speaker_media_player
        volume: 0
    on_turn_off:
      media_player.volume_set:
        id: speaker_media_player
        volume: 1.0

  - platform: template
    name: Mute
    id: mute_switch
    icon: "mdi:microphone-off"
    optimistic: true
    restore_mode: RESTORE_DEFAULT_OFF
    entity_category: config
    on_turn_on:
      then:
        - voice_assistant.stop
        - micro_wake_word.stop
    on_turn_off:
      - if:
          condition:
            not:
              - voice_assistant.is_running
          then:
            - if:
                condition:
                  lambda: return id(wake_word_engine_location).state == "In Home Assistant";
                then:
                  - lambda: id(va).set_use_wake_word(true);
                  - delay: 50ms
                  - voice_assistant.start_continuous
            - if:
                condition:
                  lambda: return id(wake_word_engine_location).state == "On device";
                then:
                  - lambda: id(va).set_use_wake_word(false);
                  - micro_wake_word.start
            - component.update: s3_box_lcd

  - platform: template
    id: media_mute
    optimistic: true
    on_turn_on:
      media_player.volume_set:
        id: speaker_media_player
        volume: 0
    on_turn_off:
      media_player.volume_set:
        id: speaker_media_player
        volume: 1.0

  - platform: template
    id: s_saver
    name: Scr/save enable
    icon: mdi:sleep
    optimistic: true
    restore_mode: RESTORE_DEFAULT_OFF
    entity_category: config

  - platform: template
    id: s_saver_mode
    name: Scr/off enable
    icon: 'mdi:monitor-off'
    optimistic: true
    restore_mode: RESTORE_DEFAULT_OFF
    entity_category: config

  - platform: template # remove for no sensor version
    id: s_saver_presc
    name: Screen wake on motion
    icon: 'mdi:motion-sensor'
    entity_category: config
    optimistic: true
    restore_mode: RESTORE_DEFAULT_OFF

  - platform: template
    id: timer_ringing
    optimistic: true
    internal: true
    restore_mode: ALWAYS_OFF

    on_turn_off:
      # Turn off the repeat mode and disable the pause between playlist items
      - lambda: |-
              id(speaker_media_player)
                ->make_call()
                .set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_REPEAT_OFF)
                .set_announcement(true)
                .perform();
              id(speaker_media_player)->set_playlist_delay_ms(speaker::AudioPipelineType::ANNOUNCEMENT, 0);
      # Stop playing the alarm
      - media_player.stop:
          announcement: true
      - if:
          condition:
            lambda: return id(wake_word_engine_location).state == "On device";
          then:
            - lambda: id(va).set_use_wake_word(false);
            - micro_wake_word.start
          else:
            - lambda: id(va).set_use_wake_word(true);
            - voice_assistant.start
    on_turn_on:
      - lambda: id(va).set_use_wake_word(false);
      - voice_assistant.stop:
      - micro_wake_word.stop:
      - delay: 150ms
      # Turn on the repeat mode and pause for 1000 ms between playlist items/repeats
      - lambda: id(led).turn_on().set_brightness(1.0).perform();
      - lambda: |-
            id(speaker_media_player)
              ->make_call()
              .set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_REPEAT_ONE)
              .set_announcement(true)
              .perform();
            id(speaker_media_player)->set_playlist_delay_ms(speaker::AudioPipelineType::ANNOUNCEMENT, 1000);
      - media_player.speaker.play_on_device_media_file:
          media_file: timer_finished_sound
          announcement: true
      - delay: 15min
      - switch.turn_off: timer_ringing

  - platform: template
    id: wake_sound
    name: Play wake sound
    icon: mdi:music
    entity_category: config
    optimistic: true
    restore_mode: RESTORE_DEFAULT_OFF

  - platform: template
    id: mute_response_switch
    name: Mute Responses
    icon: mdi:chat-sleep
    entity_category: config
    optimistic: true
    restore_mode: RESTORE_DEFAULT_OFF

  - platform: template
    id: ext_media_mute
    icon: 'mdi:volume-off'
    optimistic: true
    restore_mode: RESTORE_DEFAULT_OFF
    entity_category: config
    on_turn_on:
      then:
        - homeassistant.service:
            service: media_player.volume_mute
            data:
              entity_id: media_player.${external_media_player}
    on_turn_off:
      - homeassistant.service:
          service: media_player.volume_mute
          data:
            entity_id: media_player.${external_media_player}

output:
  - platform: ledc
    pin: GPIO47
    id: backlight_output

light:
  - platform: monochromatic
    id: led
    name: LCD Backlight
    entity_category: config
    output: backlight_output
    restore_mode: ALWAYS_ON
    default_transition_length: 50ms

# MARK: Sensors
sensor:
  - platform: aht10 # remove for no sensor version
    i2c_id: bus_b
    variant: AHT20
    temperature:
      name: "S3 Temperature"
      id: s3temp
    humidity:
      name: "S3 Humidity"
    update_interval: 60s

  - platform: adc # remove for no sensor version
    pin: GPIO10
    id: battery_voltage
    unit_of_measurement: "V"
    accuracy_decimals: 1
    device_class: "voltage"
    entity_category: "diagnostic"
    disabled_by_default: true
    update_interval: 30s
    attenuation: auto
    filters:
      - multiply: 4.11

  - platform: copy # remove for no sensor version
    id: battery_percent
    source_id: battery_voltage
    name: "Battery level"
    unit_of_measurement: "%"
    accuracy_decimals: 0
    device_class: "battery"
    entity_category: "diagnostic"
    filters:
      - lambda: return (x - 2.7) / (4.2 - 2.7) * 100;
      - clamp:
          min_value: 0
          max_value: 100

  - platform: uptime
    id: up_sens
    on_value:
      - lambda: |-
          int seconds = id(up_sens).state;
          int days = seconds / 86400;
          int hours = seconds / 3600;
          int minutes = (seconds % 3600) / 60;
          seconds %= 60;
          id(up_sens_text).publish_state(str_sprintf("%03d:%02d:%02d:%02d", days, hours, minutes, seconds));
    update_interval: 30s

  - platform: wifi_signal
    name: "WiFi db"
    id: wifi_signal_db
    update_interval: 30s

  - platform: copy
    source_id: wifi_signal_db
    name: "WiFi Signal"
    id: wifi_percent
    filters:
      - lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
    unit_of_measurement: "%"
    entity_category: "diagnostic"
    device_class: ""

  - platform: homeassistant
    name: "HA Weather Temperature"
    entity_id: weather.forecast_home
    attribute: temperature
    id: ha_weather_temp

text_sensor:
  - id: text_request
    platform: template
    on_value:
      lambda: |-
        if(id(text_request).state.length()>32) {
          std::string name = id(text_request).state.c_str();
          std::string truncated = esphome::str_truncate(name.c_str(),31);
          id(text_request).state = (truncated+"...").c_str();
        }

  - id: text_response
    platform: template
    on_value:
      lambda: |-
        if(id(text_response).state.length()>32) {
          std::string name = id(text_response).state.c_str();
          std::string truncated = esphome::str_truncate(name.c_str(),31);
          id(text_response).state = (truncated+"...").c_str();
        }
  - platform: wifi_info
    ip_address:
      name: IP Address
      id: ip_addr
      entity_category: "diagnostic"
    ssid:
      id: connected_ssid
      name: SSID
      entity_category: "diagnostic"
    bssid:
      id: connected_bssid
      name: BSSID
      entity_category: "diagnostic"
    mac_address:
      id: device_mac

  - platform: template
    id: up_sens_text
    name: Device uptime
    entity_category: "diagnostic"
    icon: mdi:clock

  - platform: template
    id: wakeword_location

  - platform: template
    id: time_remaining_0
    name: Timer
    icon: mdi:clock

  - platform: template
    id: time_remaining_1

  - platform: template
    id: time_display_format
    update_interval: never
  - platform: homeassistant
    entity_id: media_player.${external_media_player}
    id: ha_media_status
    on_value:
      component.update: s3_box_lcd

  - platform: homeassistant
    entity_id: media_player.${external_media_player}
    id: ha_media_title
    attribute: media_content_id
    on_value:
      component.update: s3_box_lcd

  - platform: homeassistant
    name: "Alarm Status"
    entity_id: alarm_control_panel.alarmo
    id: alarm_status
    on_value:
      - component.update: s3_box_lcd

  - platform: homeassistant
    name: "Weather Condition"
    entity_id: weather.forecast_home
    id: ha_weather_condition



i2s_audio:
  - id: i2s_audio_bus
    i2s_lrclk_pin:
      number: GPIO45
      ignore_strapping_warning: true
    i2s_bclk_pin: GPIO17
    i2s_mclk_pin: GPIO2

audio_adc:
  - platform: es7210
    id: es7210_adc
    i2c_id: bus_a
    bits_per_sample: 16bit
    sample_rate: 16000

audio_dac:
  - platform: es8311
    id: es8311_dac
    i2c_id: bus_a
    bits_per_sample: 16bit
    sample_rate: 48000

microphone:
  - platform: i2s_audio
    id: box_mic
    sample_rate: 16000
    i2s_din_pin: GPIO16
    bits_per_sample: 16bit
    adc_type: external

speaker:
  - id: i2s_audio_speaker
    platform: i2s_audio
    i2s_audio_id: i2s_audio_bus
    i2s_dout_pin: GPIO15
    dac_type: external
    sample_rate: 48000
    bits_per_sample: 16bit
    channel: left
    audio_dac: es8311_dac
    buffer_duration: 500ms  # Increased for stability without timeout @youkorr
  # Virtual speakers to combine the announcement and media streams together into one output
  - id: mixing_speaker
    platform: mixer
    output_speaker: i2s_audio_speaker
    source_speakers:
      - id: announcement_mixing_input
      - id: media_mixing_input
  # Vritual speakers to resample each pipelines' audio, if necessary, as the mixer speaker requires the same sample rate
  - platform: resampler
    id: announcement_resampling_speaker
    output_speaker: announcement_mixing_input
    sample_rate: 48000  # Added explicit sample rate
  - platform: resampler
    id: media_resampling_speaker
    output_speaker: media_mixing_input
    sample_rate: 48000  # Added explicit sample rate

media_player:
  - platform: speaker
    name: Media Player
    id: speaker_media_player
    volume_increment: 0.05
    volume_min: 0.5
    volume_max: 0.8
    task_stack_in_psram: true
    announcement_pipeline:
      speaker: announcement_resampling_speaker
      format: FLAC
      sample_rate: 48000
      num_channels: 1  # S3 Box only has one output channel
    media_pipeline:
      speaker: media_resampling_speaker
      format: FLAC  # FLAC is the least processor intensive codec
      num_channels: 2
      sample_rate: 48000
    files:
      - id: timer_finished_sound
        file: https://github.com/esphome/home-assistant-voice-pe/raw/dev/sounds/timer_finished.flac
      - id: wake_sound_file
        file: https://github.com/BigBobbas/ESP32-S3-Box3-Custom-ESPHome/raw/main/sounds/awake.flac
    on_state:
      then:
        - if:
            condition:
              media_player.is_playing:
            then:
              - micro_wake_word.stop
              - voice_assistant.stop
        - if:
            condition:
              and:
                - lambda: return id(global_is_assisting) == false;
                - or:
                    - media_player.is_idle
                    - media_player.is_paused
            then:
              - if:
                  condition:
                    and:
                      - switch.is_off: mute_switch
                      - lambda: return id(wake_word_engine_location).state == "On device";
                  then:
                    - micro_wake_word.start
                  else:
                    - if:
                        condition:
                          - switch.is_off: mute_switch
                        then:
                          - voice_assistant.start
        - if:
            condition:
              and:
                - switch.is_off: timer_ringing
                - not:
                    voice_assistant.is_running:
                - not:
                    media_player.is_announcing:
            then:
              - mixer_speaker.apply_ducking:
                  id: media_mixing_input
                  decibel_reduction: 0
                  duration: 1.0s
    on_play:
      - wait_until:
          - lambda: return id(global_is_assisting) == false;
    on_announcement:
      - mixer_speaker.apply_ducking:
          id: media_mixing_input
          decibel_reduction: 20
          duration: 0.0s

micro_wake_word:
  vad:
  models:
    - model: ${micro_wake_word_model_1}
    - model: ${micro_wake_word_model_2}
    - model: ${micro_wake_word_model_3}
    - model: ${micro_wake_word_model_4}
  on_wake_word_detected:
    - lambda: id(global_is_assisting) = true;
    - if:
        condition:
          and:
            - switch.is_off: output_audio
            - switch.is_on: wake_sound
        then:
          - media_player.speaker.play_on_device_media_file:
              media_file: wake_sound_file
              announcement: true
          - wait_until:
              not:
                - media_player.is_announcing:
          - delay: 150ms
        else:
          if:
            condition:
              and:
                - switch.is_on: output_audio
                - switch.is_on: wake_sound
            then:
              - homeassistant.service:
                  service: media_player.play_media
                  data:
                    entity_id: media_player.${external_media_player}
                    media_content_id: '${home_assistant_host}/local/sounds/awake.mp3'
                    media_content_type: music
    - voice_assistant.start:
        wake_word: !lambda return wake_word;

voice_assistant:
  id: va
  microphone: box_mic
  media_player: speaker_media_player
  use_wake_word: true
  noise_suppression_level: 2
  auto_gain: 31dBFS
  volume_multiplier: 4.0
  on_wake_word_detected:
    - lambda: id(global_is_assisting) = true;
    - voice_assistant.stop:
    - lambda: id(va).set_use_wake_word(false);
    - if:
        condition:
          and:
            - switch.is_off: output_audio
            - switch.is_on: wake_sound
        then:
          # - voice_assistant.stop:
          # - delay: 150ms
          # - if:
              # condition:
                # not:
                  # microphone.is_capturing:
              # then:
          - media_player.speaker.play_on_device_media_file:
              media_file: wake_sound_file
              announcement: true
          - wait_until:
              not:
                - media_player.is_announcing:
          - delay: 150ms
          - lambda: id(va).set_use_wake_word(false);
          - display.page.show: listening_page
          - component.update: s3_box_lcd
        else:
          if:
            condition:
              and:
                - switch.is_on: wake_sound
                - switch.is_on: output_audio
            then:
              - homeassistant.service:
                  service: media_player.play_media
                  data:
                    entity_id: media_player.${external_media_player}
                    media_content_id: '${home_assistant_host}/local/sounds/awake.mp3'
                    media_content_type: music
    - voice_assistant.start
  on_start:
    if:
      condition:
        - display.is_displaying_page: listening_page
        - display.is_displaying_page: thinking_page
      then:
        - display.page.show: idle_page
        - component.update: s3_box_lcd
  on_listening:
    - text_sensor.template.publish:
        id: text_request
        state: "..."
    - text_sensor.template.publish:
        id: text_response
        state: "..."
    - script.execute: saver_enabled
    - display.page.show: listening_page
    - component.update: s3_box_lcd
  on_stt_end:
    - text_sensor.template.publish:
        id: text_request
        state: !lambda return x;
  on_stt_vad_end:
    - display.page.show: thinking_page
    - component.update: s3_box_lcd
  on_tts_start:
    - text_sensor.template.publish:
        id: text_response
        state: !lambda return x;
  on_tts_end:
    - if:
        condition:
          and:
            - switch.is_on: mute_response_switch
            - switch.is_off: media_mute
            - switch.is_off: ext_media_mute
        then:
          - switch.turn_on: media_mute
          - switch.turn_on: ext_media_mute
    - display.page.show: replying_page
    - component.update: s3_box_lcd
    - if:
        condition:
          - switch.is_on: output_audio
        then:
          - homeassistant.service:
              service: media_player.play_media
              data:
                entity_id: media_player.${external_media_player}
                media_content_id: !lambda 'return x;'
                media_content_type: music
                announce: "false"
    - delay: 5s
    - display.page.show: idle_page
    - component.update: s3_box_lcd

  on_error:
    - if:
        condition:
          not:
            - voice_assistant.is_running
        then:
          - display.page.show: error_page
          - component.update: s3_box_lcd
          - delay: 4s
          - if:
              condition:
                - display.is_displaying_page: error_page
              then:
                - display.page.show: idle_page
                - component.update: s3_box_lcd
    - lambda: id(global_is_assisting) = false;

  on_idle:
    - display.page.show: idle_page
    - component.update: s3_box_lcd

  on_end:
    - wait_until:
        not:
          voice_assistant.is_running:
    - mixer_speaker.apply_ducking:
        id: media_mixing_input
        decibel_reduction: 0
        duration: 1.0s
    - lambda: id(global_is_assisting) = false;
    - if:
        condition:
          and:
            - switch.is_off: mute_switch
            - lambda: return id(wake_word_engine_location).state == "On device";
        then:
          - voice_assistant.stop
          - micro_wake_word.start

        else:
          if:
            condition:
              - switch.is_off: mute_switch
            then:
              - lambda: id(va).set_use_wake_word(false);
              - voice_assistant.stop:
              - delay: 100ms
              - lambda: id(va).set_use_wake_word(true);
              - delay: 100ms
              - voice_assistant.start
    - if:
        condition:
          and:
            - switch.is_on: mute_response_switch
            - switch.is_on: media_mute
            - switch.is_on: ext_media_mute
        then:
          - switch.turn_off: media_mute
          - switch.turn_off: ext_media_mute

  on_client_connected:
    - if:
        condition:
          and:
            - switch.is_off: mute_switch
            - lambda: return id(wake_word_engine_location).state == "On device";
        then:
          - micro_wake_word.start
        else:
          - if:
              condition:
                - switch.is_off: mute_switch
              then:
                - lambda: id(va).set_use_wake_word(true);
                - voice_assistant.start
  on_timer_started:
    - script.execute: timer_ending
    - component.update: s3_box_lcd
  on_timer_cancelled:
    - lambda: id(time_remaining_0).publish_state ("0:00:00");
    - component.update: s3_box_lcd
  on_timer_updated:
    - component.update: s3_box_lcd
  on_timer_tick:
    - lambda: |-
        int seconds = timers[0].seconds_left;
        int hours = seconds / 3600;
        int minutes = (seconds % 3600) / 60;
        seconds %= 60;
        id(time_remaining_0).publish_state(str_sprintf("%d:%02d:%02d", hours, minutes, seconds));
    - component.update: s3_box_lcd
  on_timer_finished:
    if:
      condition:
        - switch.is_on: output_audio
      then:
        - switch.turn_on: timer_ringing
        - script.execute: timer_started_external
        - display.page.show: timer_finished_page
        - component.update: s3_box_lcd
      else:
        - if:
            condition:
              - switch.is_off: output_audio
            then:
              - switch.turn_on: timer_ringing
              # - script.execute: timer_started
              - display.page.show: timer_finished_page
              - component.update: s3_box_lcd

image:
  - file: "https://github.com/BigBobbas/ESP32-S3-Box3-Custom-ESPHome/raw/main/images/error.png"
    id: error_img
    resize: 320x240
    type: RGB
    transparency: alpha_channel
  - file: "https://github.com/BigBobbas/ESP32-S3-Box3-Custom-ESPHome/raw/main/images/idle.png"
    id: idle_img
    resize: 320x240
    type: RGB
    transparency: alpha_channel
  - file: "https://github.com/BigBobbas/ESP32-S3-Box3-Custom-ESPHome/raw/main/images/listening.png"
    id: listening_img
    resize: 320x240
    type: RGB
    transparency: alpha_channel
  - file: "https://github.com/BigBobbas/ESP32-S3-Box3-Custom-ESPHome/raw/main/images/thinking.png"
    id: thinking_img
    resize: 320x240
    type: RGB
    transparency: alpha_channel
  - file: "https://github.com/BigBobbas/ESP32-S3-Box3-Custom-ESPHome/raw/main/images/replying.png"
    id: replying_img
    resize: 320x240
    type: RGB
    transparency: alpha_channel
  - file: "https://github.com/BigBobbas/ESP32-S3-Box3-Custom-ESPHome/raw/main/images/loading.png"
    id: loading_img
    resize: 320x240
    type: RGB
    transparency: alpha_channel
  - file: "https://github.com/BigBobbas/ESP32-S3-Box3-Custom-ESPHome/raw/main/images/logo.png"
    id: logo_img
    resize: 80x75
    type: RGB
    transparency: alpha_channel
font:
  - file: "https://github.com/BigBobbas/ESP32-S3-Box3-Custom-ESPHome/raw/main/fonts/consola.ttf"
    id: my_font
    size: 14
    glyphs:
      '${font_glyphs}'

  - file: "https://github.com/BigBobbas/ESP32-S3-Box3-Custom-ESPHome/raw/main/fonts/consola.ttf"
    id: my_font16
    size: 16
    glyphs:
      '${font_glyphs}'

  - file: "https://github.com/BigBobbas/ESP32-S3-Box3-Custom-ESPHome/raw/main/fonts/consola.ttf"
    id: my_font2
    size: 72
    glyphs:
      '${font_glyphs}'

  - file: "https://github.com/BigBobbas/ESP32-S3-Box3-Custom-ESPHome/raw/main/fonts/consola.ttf"
    id: my_font3
    size: 28
    glyphs:
      '${font_glyphs}'

  - file: "https://github.com/BigBobbas/ESP32-S3-Box3-Custom-ESPHome/raw/main/fonts/consola.ttf"
    id: my_font4
    size: 40
    glyphs:
      '${font_glyphs}'

  - file: "https://github.com/BigBobbas/ESP32-S3-Box3-Custom-ESPHome/raw/main/fonts/consola.ttf"
    id: my_font18
    size: 18
    glyphs:
      '${font_glyphs}'
  - file: "https://github.com/BigBobbas/ESP32-S3-Box3-Custom-ESPHome/raw/main/fonts/consola.ttf"
    id: my_font5
    size: 22
    glyphs:
      '${font_glyphs}'
  - file: "https://github.com/BigBobbas/ESP32-S3-Box3-Custom-ESPHome/raw/main/fonts/consola.ttf"
    id: my_font6
    size: 50
    glyphs:
      '${font_glyphs}'

  - file: "https://github.com/BigBobbas/ESP32-S3-Box3-Custom-ESPHome/raw/main/fonts/consola.ttf"
    id: my_font82
    size: 82
    glyphs:
      '${font_glyphs}'

  - file: "https://github.com/BigBobbas/ESP32-S3-Box3-Custom-ESPHome/raw/main/fonts/materialdesignicons-webfont.ttf"
    id: icon_font_55
    size: 45
    glyphs: &icon_glyphs
      - "\U000F0079"#battery 100%
      - "\U000F007A"#battery 10%
      - "\U000F007B"#battery 20%
      - "\U000F007C"#battery 30%
      - "\U000F007D"#battery 40%
      - "\U000F007E"#battery 50%
      - "\U000F007F"#battery 60%
      - "\U000F0080"#battery 70%
      - "\U000F0081"#battery 80%
      - "\U000F0082"#battery 90%
      - "\U000F009E"#bell
      - "\U000F0150"#clock
      - "\U000F01AE"#gbp pound symbol
      - "\U000F0210"#fan
      - "\U000F0238"#heating
      - "\U000F024A"#garden/flower
      - "\U000F0335"#light bulb off
      - "\U000F036C"#microphone on
      - "\U000F036D"#microphone off
      - "\U000F036F"#voice settings
      - "\U000F03E4"#pause
      - "\U000F040A"#play
      - "\U000F040E"#play/pause
      - "\U000F0493"#settings cog
      - "\U000F04AD"#next track
      - "\U000F04AE"#previous track
      - "\U000F04B9"#living room
      - "\U000F04C8"#spots
      - "\U000F04DB"#stop
      - "\U000F0502"#screen settings
      - "\U000F050F"#temp sensor
      - "\U000F0521"#toggle on
      - "\U000F0565"#arming
      - "\U000F057E"#speaker on
      - "\U000F0581"#speaker off
      - "\U000F05CB"#voice
      - "\U000F068A"#alarm home
      - "\U000F06E8"#light bulb illuminated
      - "\U000F075A"#music
      - "\U000F075D"#vol plus
      - "\U000F075E"#vol minus
      - "\U000F0769"#ceiling
      - "\U000F07D0"#api connected
      - "\U000F07F4"#tv
      - "\U000F0873"#car miles non
      - "\U000F0874"#car miles full
      - "\U000F0875"#car miles low
      - "\U000F087B"#api disconnected
      - "\U000F08D6"#settings
      - "\U000F099D"#alarm away
      - "\U000F099E"#disarmed
      - "\U000F0A19"#toggle off
      - "\U000F0B26"#down
      - "\U000F0B28"#left
      - "\U000F0B2A"#right
      - "\U000F0B2C"#up
      - "\U000F0B6C"#car battery
      - "\U000F0D90"#screen off
      - "\U000F0EBA"#stats
      - "\U000F0ED4"#voice off
      - "\U000F0FCE"#scene
      - "\U000F1061"#dining
      - "\U000F10CD"#battery warning
      - "\U000F1160"#kitchen
      - "\U000F12A8"#touch button
      - "\U000F12D3"#garage closed
      - "\U000F12D4"#garage open
      - "\U000F1322"#tools
      - "\U000F16BC"#wifidisconnected
      - "\U000F16BD"#wifi connected
      - "\U000F1722"#fire off
      - "\U000F1747"#tall lamp
      - "\U000F1828"#armed night
      - "\U000F192D"#electricity
      - "\U000F1987"#floods
      - "\U000F1A12"#home button
      - "\U000F1A1B"#gas
      - "\U000F1C3B"#battery charging/usb powered
      - "\U000F1C6F"#info
      - "\U000F0599"  # weather-sunny
      - "\U000F0595"  # weather-partly-cloudy
      - "\U000F0590"  # weather-cloudy
      - "\U000F0596"  # weather-pouring
      - "\U000F0593"  # weather-lightning
      - "\U000F0598"  # weather-snowy
      - "\U000F0592"  # weather-hail
      - "\U000F0594"  # weather-night
      - "\U000F0591"  # weather-fog
      - "\U000F059D"  # weather-windy
      - "\U000F0597"  # weather-rainy
      - "\U000F07A6"  # cannabis
      - "\U000F0EC0"  # penguin
      - "\U000F1C4F"  # shape-plus-outline for mid menu
      - "\U000F0B5F"  # bat
      - "\U000F01E5"  # duck
      - "\U000F0208"  # eye on
      - "\U000F0209"  # eye off
      - "\U000F05A0"  # webcam
      - "\U000F13E1"  # umbrella
      - "\U000F03D2"  # owl


  - file: "https://github.com/BigBobbas/ESP32-S3-Box3-Custom-ESPHome/raw/main/fonts/materialdesignicons-webfont.ttf"
    id: icon_font_180
    size: 180
    glyphs: *icon_glyphs


  - file: "https://github.com/BigBobbas/ESP32-S3-Box3-Custom-ESPHome/raw/main/fonts/materialdesignicons-webfont.ttf"
    id: icon_font_80
    size: 75
    glyphs: *icon_glyphs

  - file: "https://github.com/BigBobbas/ESP32-S3-Box3-Custom-ESPHome/raw/main/fonts/materialdesignicons-webfont.ttf"
    id: icon_font_60
    size: 60
    glyphs: *icon_glyphs

color:
  - id: green
    hex: '75D15F'
  - id: red
    hex: 'FF3131'
  - id: blue
    hex: '47B7E9'
  - id: blue_drk
    hex: '085296'
  - id: amber
    hex: 'FBAB35'
  - id: lime
    hex: '20FC30'
  - id: pink
    hex: 'D92BBC'
  - id: yellow
    hex: 'FFC000'
  - id: black
    hex: '000000'
  - id: white
    hex: 'ffffff'
  - id: purple
    hex: '73264D'
  - id: light_blue
    hex: 'CFE2F3'
  - id: bg_blue
    hex: '032341'
  - id: bg_purple
    hex: '301020'
  - id: bg_green
    hex: '05350B'
  - id: bg_red
    hex: '3C0000'
  - id: bg_pink
    hex: '61034D'
  - id: bg_charcoal
    hex: '323232'
  - id: bg_brown
    hex: '41220D'
  - id: bg_grey
    hex: '4F4F4F'
  - id: gold
    hex: 'E1C564'

spi:
  clk_pin: 7
  mosi_pin: 6


display:
  - platform: ili9xxx
    id: s3_box_lcd
    model: S3BOX
    data_rate: 40MHz
    cs_pin: 5
    dc_pin: 4
    reset_pin:
      number: 48
      inverted: true
    update_interval: never
    invert_colors: false
    ##################################################################################################
    ################ The below section defines, what is displayed on the screen,        ##############
    ################ the colours and mdi icons are defined above under font: and Color: ##############
    ################ they are then referenced in the config below.                      ##############
    ##################################################################################################
    pages:
      - id: idle_page ##### home page ######
        lambda: |-
          it.fill(id(black));
          if(id(api_connection) == true) {
          it.printf(15, 5, id(icon_font_55), blue, "\U000F07D0");
          } else {
                  it.printf(15, 5, id(icon_font_55), red, "\U000F087B");
          }
          if(id(wifi_connection) == true) {
                  it.printf(80, 5, id(icon_font_55), lime, "\U000F16BD");
          } else {
                  it.printf(80, 5, id(icon_font_55), red, "\U000F16BC");
          }
          if(id(time_remaining_0).state == "0:00:00"){
          it.printf(135, 5, id(icon_font_55), red, "\U000F0150");
          } else {
          it.printf(135, 5, id(icon_font_55), lime, "\U000F0150");
          }
          if(id(mute_switch).state) {
                 it.printf(190, 5, id(icon_font_55), red, "\U000F036D");
          } else {
                 it.printf(190, 5, id(icon_font_55), lime, "\U000F036C");
          }
          if(id(alarm_status).state == "disarmed") {
          it.printf(250, 5, id(icon_font_55), red, "\U000F099E");
          } else if(id(alarm_status).state == "arming") {
          it.printf(250, 5, id(icon_font_55), amber, "\U000F0565");
          } else if(id(alarm_status).state == "armed_home") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F068A");
          } else if(id(alarm_status).state == "armed_away") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F099D");
          } else if(id(alarm_status).state == "armed_night") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F1828");
          }
          it.printf(20, 75, id(icon_font_80), blue_drk,"\U000F050F"); // temp
          it.printf(40, 120, id(my_font3), white, "%.f", id(s3temp).state); // temperature text
          it.printf(120, 75, id(icon_font_80), pink,"\U000F1C4F" ); // 2nd mid (lights)
          it.printf(220, 75, id(icon_font_80), lime,"\U000F07A6"); // 3rd mid (fans)
          it.printf(20, 155, id(icon_font_80), red,"\U000F075A"); // sound
          it.printf(120, 155, id(icon_font_80), blue,"\U000F0FCE"); // media
          it.printf(220, 155, id(icon_font_80), yellow,"\U000F08D6"); // settings

      - id: template_page ##### template page ##]##
        lambda: |-
          it.fill(id(black));
          if(id(api_connection) == true) {
                  it.printf(15, 5, id(icon_font_55), blue, "\U000F07D0");
          } else {
                  it.printf(15, 5, id(icon_font_55), red, "\U000F087B");
          }
          if(id(wifi_connection) == true) {
                  it.printf(80, 5, id(icon_font_55), lime, "\U000F16BD");
          } else {
                  it.printf(80, 5, id(icon_font_55), red, "\U000F16BC");
          }
          if(id(time_remaining_0).state == "0:00:00"){
          it.printf(135, 5, id(icon_font_55), red, "\U000F0150");
          } else {
          it.printf(135, 5, id(icon_font_55), lime, "\U000F0150");
          }
          if(id(mute_switch).state) {
                 it.printf(190, 5, id(icon_font_55), red, "\U000F036D");
          } else {
                 it.printf(190, 5, id(icon_font_55), lime, "\U000F036C");
          }
          if(id(alarm_status).state == "disarmed") {
          it.printf(250, 5, id(icon_font_55), red, "\U000F099E");
          } else if(id(alarm_status).state == "arming") {
          it.printf(250, 5, id(icon_font_55), amber, "\U000F0565");
          } else if(id(alarm_status).state == "armed_home") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F068A");
          } else if(id(alarm_status).state == "armed_away") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F099D");
          } else if(id(alarm_status).state == "armed_night") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F1828");
          }
          it.printf(20, 75, id(icon_font_80), light_blue,"\U000F06E8");
          it.printf(120, 75, id(icon_font_80), light_blue,"\U000F06E8");
          it.printf(220, 75, id(icon_font_80), light_blue, "\U000F06E8");
          it.printf(20, 155, id(icon_font_80), light_blue,"\U000F06E8");
          it.printf(120, 155, id(icon_font_80), light_blue,"\U000F06E8");
          it.printf(220, 155, id(icon_font_80), light_blue, "\U000F06E8");

      - id: info_page ##### info page #####
        lambda: |-
          it.fill(id(black));
          if(id(api_connection) == true) {
                  it.printf(15, 5, id(icon_font_55), blue, "\U000F07D0");
          } else {
                  it.printf(15, 5, id(icon_font_55), red, "\U000F087B");
          }
          if(id(wifi_connection) == true) {
                  it.printf(80, 5, id(icon_font_55), lime, "\U000F16BD");
          } else {
                  it.printf(80, 5, id(icon_font_55), red, "\U000F16BC");
          }
          if(id(time_remaining_0).state == "0:00:00"){
          it.printf(135, 5, id(icon_font_55), red, "\U000F0150");
          } else {
          it.printf(135, 5, id(icon_font_55), lime, "\U000F0150");
          }
          if(id(mute_switch).state) {
                 it.printf(190, 5, id(icon_font_55), red, "\U000F036D");
          } else {
                 it.printf(190, 5, id(icon_font_55), lime, "\U000F036C");
          }
          if(id(alarm_status).state == "disarmed") {
          it.printf(250, 5, id(icon_font_55), red, "\U000F099E");
          } else if(id(alarm_status).state == "arming") {
          it.printf(250, 5, id(icon_font_55), amber, "\U000F0565");
          } else if(id(alarm_status).state == "armed_home") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F068A");
          } else if(id(alarm_status).state == "armed_away") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F099D");
          } else if(id(alarm_status).state == "armed_night") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F1828");
          }
          it.printf(160, 75, id(my_font5), light_blue, TextAlign::CENTER, "IP Address");
          it.printf(160, 95, id(my_font5), yellow, TextAlign::CENTER, "%s", id(ip_addr).state.c_str());
          it.printf(160, 125, id(my_font5), light_blue, TextAlign::CENTER, "Host Name");
          it.printf(160, 145, id(my_font5), yellow, TextAlign::CENTER, "${name}.local");
          it.printf(160, 175, id(my_font5), light_blue, TextAlign::CENTER, "Device Uptime DDD:H:M:S");
          it.printf(160, 195, id(my_font5), yellow, TextAlign::CENTER, "%s", id(up_sens_text).state.c_str());
          it.printf(40, 210, id(my_font5), light_blue, TextAlign::LEFT, "Battery Level"); // remove for no sensor version
          it.printf(265, 210, id(my_font5), yellow, TextAlign::RIGHT, "%.f%%", id(battery_percent).state); // remove for no sensor version


      - id: ss_set_page ##### screen saver settings page #####
        lambda: |-
          it.fill(id(black));
          it.printf(160, 70, id(icon_font_80), light_blue, TextAlign::CENTER, "\U000F08D6");
          it.printf(160, 20, id(my_font5), light_blue, TextAlign::CENTER, "Screensaver Settings");
          it.printf(250, 115, id(my_font5), light_blue, TextAlign::RIGHT, "Timeout Settings :");
          it.printf(255, 95, id(icon_font_55), lime, "\U000F08D6");
          it.printf(250, 145, id(my_font5), light_blue, TextAlign::RIGHT, "Enable screensaver :");
          if(id(s_saver).state) {
                 it.printf(255, 135, id(icon_font_55), lime, "\U000F0521");
          } else {
                 it.printf(255, 135, id(icon_font_55), blue_drk, "\U000F0A19");
          }
          it.printf(250, 175, id(my_font5), light_blue, TextAlign::RIGHT, "Wake on presence :"); // remove for no sensor version 6 lines
          if(id(s_saver_presc).state) {
                 it.printf(255, 165, id(icon_font_55), lime, "\U000F0521");
          } else {
                 it.printf(255, 165, id(icon_font_55), blue_drk, "\U000F0A19");
          }
          it.printf(250, 205, id(my_font5), light_blue, TextAlign::RIGHT, "Timeout to blank :");
          if(id(s_saver_mode).state) {
                 it.printf(255, 195, id(icon_font_55), lime, "\U000F0521");
          } else {
                 it.printf(255, 195, id(icon_font_55), blue_drk, "\U000F0A19");
          }

      - id: ww_set_page ##### voice settings page #####
        lambda: |-
          it.fill(id(black));
          it.printf(160, 50, id(icon_font_55), light_blue, TextAlign::CENTER, "\U000F08D6");
          it.printf(160, 20, id(my_font5), light_blue, TextAlign::CENTER, "Voice Settings");
          it.printf(155, 85, id(my_font5), light_blue, TextAlign::CENTER, "tap to change");
          it.printf(135, 115, id(my_font5), light_blue, TextAlign::RIGHT, "WakeWord :");
          it.printf(310, 115, id(my_font5), lime, TextAlign::RIGHT, "%s", id(wakeword_location).state.c_str());
          it.printf(250, 145, id(my_font5), light_blue, TextAlign::RIGHT, "Mute responses :");
          if(id(mute_response_switch).state) {
                 it.printf(255, 135, id(icon_font_55), lime, "\U000F0521");
          } else {
                 it.printf(255, 135, id(icon_font_55), blue_drk, "\U000F0A19");
          }
          it.printf(250, 175, id(my_font5), light_blue, TextAlign::RIGHT, "Wake up sound :");
          if(id(wake_sound).state) {
                 it.printf(255, 165, id(icon_font_55), lime, "\U000F0521");
          } else {
                 it.printf(255, 165, id(icon_font_55), blue_drk, "\U000F0A19");
          }
          it.printf(250, 205, id(my_font5), light_blue, TextAlign::RIGHT, "Show Conversation :");
          if(id(display_conversation).state) {
                 it.printf(255, 195, id(icon_font_55), lime, "\U000F0521");
          } else {
                 it.printf(255, 195, id(icon_font_55), blue_drk, "\U000F0A19");
          }

      - id: climate_page ##### climate page #####
        lambda: |-
          it.fill(id(black));
          if(id(api_connection) == true) {
                  it.printf(15, 5, id(icon_font_55), blue, "\U000F07D0");
          } else {
                  it.printf(15, 5, id(icon_font_55), red, "\U000F087B");
          }
          if(id(wifi_connection) == true) {
                  it.printf(80, 5, id(icon_font_55), lime, "\U000F16BD");
          } else {
                  it.printf(80, 5, id(icon_font_55), red, "\U000F16BC");
          }
          if(id(time_remaining_0).state == "0:00:00"){
          it.printf(135, 5, id(icon_font_55), red, "\U000F0150");
          } else {
          it.printf(135, 5, id(icon_font_55), lime, "\U000F0150");
          }
          if(id(mute_switch).state) {
                 it.printf(190, 5, id(icon_font_55), red, "\U000F036D");
          } else {
                 it.printf(190, 5, id(icon_font_55), lime, "\U000F036C");
          }
          if(id(alarm_status).state == "disarmed") {
          it.printf(250, 5, id(icon_font_55), red, "\U000F099E");
          } else if(id(alarm_status).state == "arming") {
          it.printf(250, 5, id(icon_font_55), amber, "\U000F0565");
          } else if(id(alarm_status).state == "armed_home") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F068A");
          } else if(id(alarm_status).state == "armed_away") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F099D");
          } else if(id(alarm_status).state == "armed_night") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F1828");
          }
          it.printf(20, 75, id(icon_font_80), light_blue,"\U000F050F");
          it.printf(120, 75, id(icon_font_80), light_blue,"\U000F050F");
          it.printf(220, 75, id(icon_font_80), light_blue, "\U000F050F");
          it.printf(20, 155, id(icon_font_80), light_blue,"\U000F050F");
          it.printf(120, 155, id(icon_font_80), light_blue,"\U000F050F");
          it.printf(220, 155, id(icon_font_80), light_blue, "\U000F050F");

      - id: lights_page ##### lights page ####
        lambda: |-
          it.fill(id(black));
          if(id(api_connection) == true) {
                  it.printf(15, 5, id(icon_font_55), blue, "\U000F07D0");
          } else {
                  it.printf(15, 5, id(icon_font_55), red, "\U000F087B");
          }
          if(id(wifi_connection) == true) {
                  it.printf(80, 5, id(icon_font_55), lime, "\U000F16BD");
          } else {
                  it.printf(80, 5, id(icon_font_55), red, "\U000F16BC");
          }
          if(id(time_remaining_0).state == "0:00:00"){
          it.printf(135, 5, id(icon_font_55), red, "\U000F0150");
          } else {
          it.printf(135, 5, id(icon_font_55), lime, "\U000F0150");
          }
          if(id(mute_switch).state) {
                 it.printf(190, 5, id(icon_font_55), red, "\U000F036D");
          } else {
                 it.printf(190, 5, id(icon_font_55), lime, "\U000F036C");
          }
          if(id(alarm_status).state == "disarmed") {
          it.printf(250, 5, id(icon_font_55), red, "\U000F099E");
          } else if(id(alarm_status).state == "arming") {
          it.printf(250, 5, id(icon_font_55), amber, "\U000F0565");
          } else if(id(alarm_status).state == "armed_home") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F068A");
          } else if(id(alarm_status).state == "armed_away") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F099D");
          } else if(id(alarm_status).state == "armed_night") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F1828");
          }
          it.printf(20, 75, id(icon_font_80), light_blue,"\U000F0335");
          it.printf(120, 75, id(icon_font_80), light_blue,"\U000F0335");
          it.printf(220, 75, id(icon_font_80), light_blue, "\U000F0335");
          it.printf(20, 155, id(icon_font_80), light_blue,"\U000F0335");
          it.printf(120, 155, id(icon_font_80), light_blue,"\U000F0335");
          it.printf(220, 155, id(icon_font_80), light_blue, "\U000F0335");

      - id: media_page ##### media player page #####
        lambda: |-
          it.fill(id(black));
          if(id(api_connection) == true) {
                  it.printf(15, 5, id(icon_font_55), blue, "\U000F07D0");
          } else {
                  it.printf(15, 5, id(icon_font_55), red, "\U000F087B");
          }
          if(id(wifi_connection) == true) {
                  it.printf(80, 5, id(icon_font_55), lime, "\U000F16BD");
          } else {
                  it.printf(80, 5, id(icon_font_55), red, "\U000F16BC");
          }
          if(id(time_remaining_0).state == "0:00:00"){
          it.printf(135, 5, id(icon_font_55), red, "\U000F0150");
          } else {
          it.printf(135, 5, id(icon_font_55), lime, "\U000F0150");
          }
          if(id(mute_switch).state) {
                 it.printf(190, 5, id(icon_font_55), red, "\U000F036D");
          } else {
                 it.printf(190, 5, id(icon_font_55), lime, "\U000F036C");
          }
          if(id(alarm_status).state == "disarmed") {
          it.printf(250, 5, id(icon_font_55), red, "\U000F099E");
          } else if(id(alarm_status).state == "arming") {
          it.printf(250, 5, id(icon_font_55), amber, "\U000F0565");
          } else if(id(alarm_status).state == "armed_home") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F068A");
          } else if(id(alarm_status).state == "armed_away") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F099D");
          } else if(id(alarm_status).state == "armed_night") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F1828");
          }
          if(id(media_state) == true) {
                 it.printf(160, 80, id(my_font5), lime, TextAlign::CENTER, "Playing");
          } else {
                 it.printf(160, 80, id(my_font5), light_blue, TextAlign::CENTER, "Nothing Playing");
          }
          it.printf(20, 100, id(icon_font_80), blue,"\U000F075E");
          it.printf(120, 100, id(icon_font_80), blue,"\U000F040E");
          it.printf(220, 100, id(icon_font_80), blue,"\U000F075D");
          if(id(media_mute).state) {
                  it.printf(120, 165, id(icon_font_80), red,"\U000F0581");
          } else {
                  it.printf(120, 165, id(icon_font_80), lime,"\U000F057E");
          }
      - id: ext_media_page ##### media player page #####
        lambda: |-
          it.fill(id(black));
          if(id(api_connection) == true) {
                  it.printf(15, 5, id(icon_font_55), blue, "\U000F07D0");
          } else {
                  it.printf(15, 5, id(icon_font_55), red, "\U000F087B");
          }
          if(id(wifi_connection) == true) {
                  it.printf(80, 5, id(icon_font_55), lime, "\U000F16BD");
          } else {
                  it.printf(80, 5, id(icon_font_55), red, "\U000F16BC");
          }
          if(id(time_remaining_0).state == "0:00:00"){
          it.printf(135, 5, id(icon_font_55), red, "\U000F0150");
          } else {
          it.printf(135, 5, id(icon_font_55), lime, "\U000F0150");
          }
          if(id(mute_switch).state) {
                 it.printf(190, 5, id(icon_font_55), red, "\U000F036D");
          } else {
                 it.printf(190, 5, id(icon_font_55), lime, "\U000F036C");
          }
          if(id(alarm_status).state == "disarmed") {
          it.printf(250, 5, id(icon_font_55), red, "\U000F099E");
          } else if(id(alarm_status).state == "arming") {
          it.printf(250, 5, id(icon_font_55), amber, "\U000F0565");
          } else if(id(alarm_status).state == "armed_home") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F068A");
          } else if(id(alarm_status).state == "armed_away") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F099D");
          } else if(id(alarm_status).state == "armed_night") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F1828");
          }
          it.printf(160, 80, id(my_font5), lime, TextAlign::CENTER, id(ha_media_status).state.c_str());
          it.printf(20, 100, id(icon_font_80), blue,"\U000F04AE");
          it.printf(120, 100, id(icon_font_80), blue,"\U000F040E");
          it.printf(220, 100, id(icon_font_80), blue,"\U000F04AD");
          if(id(ext_media_mute).state) {
                  it.printf(120, 165, id(icon_font_80), red,"\U000F0581");
          } else {
                  it.printf(120, 165, id(icon_font_80), lime,"\U000F057E");
          }
          it.printf(20, 165, id(icon_font_80), blue,"\U000F075E");
          it.printf(220, 165, id(icon_font_80), blue,"\U000F075D");

      - id: scenes_page ##### scenes page #####
        lambda: |-
          it.fill(id(black));
          if(id(api_connection) == true) {
                  it.printf(15, 5, id(icon_font_55), blue, "\U000F07D0");
          } else {
                  it.printf(15, 5, id(icon_font_55), red, "\U000F087B");
          }
          if(id(wifi_connection) == true) {
                  it.printf(80, 5, id(icon_font_55), lime, "\U000F16BD");
          } else {
                  it.printf(80, 5, id(icon_font_55), red, "\U000F16BC");
          }
          if(id(time_remaining_0).state == "0:00:00"){
          it.printf(135, 5, id(icon_font_55), red, "\U000F0150");
          } else {
          it.printf(135, 5, id(icon_font_55), lime, "\U000F0150");
          }
          if(id(mute_switch).state) {
                 it.printf(190, 5, id(icon_font_55), red, "\U000F036D");
          } else {
                 it.printf(190, 5, id(icon_font_55), lime, "\U000F036C");
          }
          if(id(alarm_status).state == "disarmed") {
          it.printf(250, 5, id(icon_font_55), red, "\U000F099E");
          } else if(id(alarm_status).state == "arming") {
          it.printf(250, 5, id(icon_font_55), amber, "\U000F0565");
          } else if(id(alarm_status).state == "armed_home") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F068A");
          } else if(id(alarm_status).state == "armed_away") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F099D");
          } else if(id(alarm_status).state == "armed_night") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F1828");
          }
          it.printf(20, 75, id(icon_font_80), light_blue,"\U000F0FCE");
          it.printf(120, 75, id(icon_font_80), light_blue,"\U000F0FCE");
          it.printf(220, 75, id(icon_font_80), light_blue, "\U000F0FCE");
          it.printf(20, 155, id(icon_font_80), light_blue,"\U000F0FCE");
          it.printf(120, 155, id(icon_font_80), light_blue,"\U000F0FCE");
          it.printf(220, 155, id(icon_font_80), light_blue, "\U000F0FCE");


      - id: loading_page ### loading page #####
        lambda: |-
          it.fill(Color::BLACK);
          it.image((it.get_width() / 2), (it.get_height() / 2), id(loading_img), ImageAlign::CENTER);

      - id: listening_page
        lambda: |-
          it.fill(Color::BLACK);
          it.image((it.get_width() / 2), (it.get_height() / 2), id(listening_img), ImageAlign::CENTER);

      - id: thinking_page
        lambda: |-
          it.fill(Color::BLACK);
          it.image((it.get_width() / 2), (it.get_height() / 2), id(thinking_img), ImageAlign::CENTER);
          if (id(display_conversation).state) {
            it.filled_rectangle(0 , 0 , 320 , 30 , Color::WHITE );
            it.printf(10, 10, id(my_font16), Color::BLACK, "%s", id(text_request).state.c_str());
          }
      - id: replying_page
        lambda: |-
          it.fill(Color::BLACK);
          it.image((it.get_width() / 2), (it.get_height() / 2), id(replying_img), ImageAlign::CENTER);
          if (id(display_conversation).state) {
            it.filled_rectangle(0 , 0 , 320 , 30 , Color::WHITE );
            it.filled_rectangle(0 , 210 , 320 , 30 , Color::WHITE );
            it.printf(10, 10, id(my_font16), Color::BLACK, "%s", id(text_request).state.c_str());
            it.printf(10, 220, id(my_font16), Color::BLACK, "%s", id(text_response).state.c_str());
          }
      - id: error_page
        lambda: |-
          it.fill(Color::BLACK);
          it.image((it.get_width() / 2), (it.get_height() / 2), id(error_img), ImageAlign::CENTER);

      - id: timer_finished_page
        lambda: |-
          it.fill(id(black));
          it.printf(160, 20, id(my_font5), light_blue, TextAlign::CENTER, "Timer Finished");
          it.printf(160, 120, id(icon_font_180), light_blue, TextAlign::CENTER, "\U000F009E");
          it.printf(160, 215, id(my_font5), light_blue, TextAlign::CENTER, "tap screen to dismiss");

      - id: muted_page
        lambda: |-
          it.fill(Color::BLACK);
          it.printf(160, 120, id(my_font4), yellow, TextAlign::CENTER, "Mic & Speaker - Muted");

      # MARK: Screen Saver
      - id: saver_page ##### screen saver display page #####
        lambda: |-
          it.fill(id(black));

          const char *days[] {"${sunday}","${monday}","${tuesday}","${wednesday}","${thursday}","${friday}","${saturday}"};
          const char *months[] {"${jan}","${feb}","${mar}","${apr}","${may}","${jun}","${jul}","${aug}","${sept}","${oct}","${nov}","${dec}"};
          it.printf(160, 28, id(my_font5), light_blue, TextAlign::CENTER, "%s %d %s", days[id(ha_time).now().day_of_week - 1], id(ha_time).now().day_of_month, months[id(ha_time).now().month - 1]);
          if(id(time_display_format).state == "24 Hr") {
            it.strftime(160, 88, id(my_font82), TextAlign::CENTER, "%H:%M", id(ha_time).now());
          } else {
            it.strftime(160, 88, id(my_font2), TextAlign::CENTER, "%l:%M%p", id(ha_time).now());
          }
          // Temperature from Home Assistant weather entity
          it.printf(240, 161, id(my_font4), light_blue, TextAlign::CENTER, "%.f°C", id(ha_weather_temp).state);

          // Weather condition (e.g. "partlycloudy", "sunny", etc.)
          std::string condition = id(ha_weather_condition).state;
          if (condition == "sunny") {
            it.printf(240, 210, id(icon_font_55), light_blue, TextAlign::CENTER, "\U000F0668");
          } else if (condition == "partlycloudy") {
            it.printf(240, 210, id(icon_font_55), light_blue, TextAlign::CENTER, "\U000F0595");
          } else if (condition == "cloudy") {
            it.printf(240, 210, id(icon_font_55), light_blue, TextAlign::CENTER, "\U000F0590");
          } else if (condition == "rainy") {
            it.printf(240, 210, id(icon_font_55), light_blue, TextAlign::CENTER, "\U000F0597");
          } else if (condition == "lightning") {
            it.printf(240, 210, id(icon_font_55), light_blue, TextAlign::CENTER, "\U000F0593");
          } else {
            it.printf(240, 210, id(icon_font_55), light_blue, TextAlign::CENTER, "\U000F0594"); // default: cloudy
          }

          // Device
          it.printf(80, 161, id(my_font4), light_blue, TextAlign::CENTER, "%.f°C", id(s3temp).state);
          it.printf(80, 210, id(my_font4), gold, TextAlign::CENTER, "\U000F03D2");

      - id: ota_page ##### firmware uploading page #####
        lambda: |-
          it.fill(Color::BLACK);
          it.printf(160, 60, id(icon_font_80), red, TextAlign::CENTER, "\U000F08D6");
          it.printf((it.get_width() / 2), (it.get_height() / 2), id(my_font3), red, TextAlign::CENTER, "FIRMWARE UPDATING");
          it.printf(160,155, id(my_font5), blue, TextAlign::CENTER, "Once update and restarted");
          it.printf(160,190, id(my_font5), blue, TextAlign::CENTER, "press the reboot button");
          it.printf(160,225, id(my_font5), blue, TextAlign::CENTER, "to enable touch");
      - id: settings_page ##### settings parent page #####
        lambda: |-
          it.fill(id(black));
          if(id(api_connection) == true) {
                  it.printf(15, 5, id(icon_font_55), blue, "\U000F07D0");
          } else {
                  it.printf(15, 5, id(icon_font_55), red, "\U000F087B");
          }
          if(id(wifi_connection) == true) {
                  it.printf(80, 5, id(icon_font_55), lime, "\U000F16BD");
          } else {
                  it.printf(80, 5, id(icon_font_55), red, "\U000F16BC");
          }
          if(id(time_remaining_0).state == "0:00:00"){
          it.printf(135, 5, id(icon_font_55), red, "\U000F0150");
          } else {
          it.printf(135, 5, id(icon_font_55), lime, "\U000F0150");
          }
          if(id(mute_switch).state) {
                 it.printf(190, 5, id(icon_font_55), red, "\U000F036D");
          } else {
                 it.printf(190, 5, id(icon_font_55), lime, "\U000F036C");
          }
          if(id(alarm_status).state == "disarmed") {
          it.printf(250, 5, id(icon_font_55), red, "\U000F099E");
          } else if(id(alarm_status).state == "arming") {
          it.printf(250, 5, id(icon_font_55), amber, "\U000F0565");
          } else if(id(alarm_status).state == "armed_home") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F068A");
          } else if(id(alarm_status).state == "armed_away") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F099D");
          } else if(id(alarm_status).state == "armed_night") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F1828");
          }
          it.printf(160, 65, id(my_font5), light_blue, TextAlign::CENTER, "settings");
          it.printf(20, 80, id(icon_font_55), light_blue,"\U000F036F");
          it.printf(140, 80, id(icon_font_55), light_blue,"\U000F0502");
          it.printf(255, 80, id(icon_font_55), light_blue, "\U000F1C6F");
          it.printf(15, 210, id(my_font5), light_blue,"Device");
          it.printf(245, 130, id(my_font5), light_blue, "Info");
          it.printf(20, 160, id(icon_font_55), light_blue,"\U000F08D6");
          it.printf(255, 160, id(icon_font_55), light_blue, "\U000F05CB");
          it.printf(15, 130, id(my_font5), light_blue,"Voice");
          it.printf(135, 130, id(my_font5), light_blue,"Saver");
          it.printf(245, 210, id(my_font5), light_blue, "Test");
          it.image((it.get_width() / 2), 195, id(logo_img), ImageAlign::CENTER);

      - id: device_set_page ##### Device settings page #####
        lambda: |-
          it.fill(id(black));
          if(id(api_connection) == true) {
                  it.printf(15, 5, id(icon_font_55), blue, "\U000F07D0");
          } else {
                  it.printf(15, 5, id(icon_font_55), red, "\U000F087B");
          }
          if(id(wifi_connection) == true) {
                  it.printf(80, 5, id(icon_font_55), lime, "\U000F16BD");
          } else {
                  it.printf(80, 5, id(icon_font_55), red, "\U000F16BC");
          }
          if(id(time_remaining_0).state == "0:00:00"){
          it.printf(135, 5, id(icon_font_55), red, "\U000F0150");
          } else {
          it.printf(135, 5, id(icon_font_55), lime, "\U000F0150");
          }
          if(id(mute_switch).state) {
                 it.printf(190, 5, id(icon_font_55), red, "\U000F036D");
          } else {
                 it.printf(190, 5, id(icon_font_55), lime, "\U000F036C");
          }
          if(id(alarm_status).state == "disarmed") {
          it.printf(250, 5, id(icon_font_55), red, "\U000F099E");
          } else if(id(alarm_status).state == "arming") {
          it.printf(250, 5, id(icon_font_55), amber, "\U000F0565");
          } else if(id(alarm_status).state == "armed_home") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F068A");
          } else if(id(alarm_status).state == "armed_away") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F099D");
          } else if(id(alarm_status).state == "armed_night") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F1828");
          }
          it.printf(15, 75, id(my_font5), light_blue, "Ext media player");
          if(id(output_audio).state) {
                 it.printf(255, 60, id(icon_font_60), lime, "\U000F0521");
          } else {
                 it.printf(255, 60, id(icon_font_60), blue_drk, "\U000F0A19");
          }
          it.printf(5, 190, id(icon_font_55), light_blue, "\U000F0B28");
          it.printf(15, 135, id(my_font5), light_blue, "Brightness");
          it.printf(238, 148, id(my_font5), light_blue, TextAlign::CENTER, "%.f", id(s_default_brightness).state);
          it.printf(160, 125, id(icon_font_55), lime, TextAlign::LEFT, "\U000F0B2C");
          it.printf(315, 125, id(icon_font_55), lime, TextAlign::RIGHT, "\U000F0B26");
          it.rectangle(215 , 125 , 46 , 40 , light_blue);
          it.printf(65, 180, id(my_font5), light_blue, "Time Format:");
          it.printf(210, 180, id(my_font5), lime, "%s", id(time_display_format).state.c_str());

      - id: timeout_settings_page ##### Timeout Settings page #####
        lambda: |-
          it.fill(id(black));
          //it.printf(160, 50, id(icon_font_55), light_blue, TextAlign::CENTER, "\U000F0150");
          it.printf(160, 20, id(my_font5), light_blue, TextAlign::CENTER, "Screen Settings");
          it.printf(160, 60, id(my_font5), light_blue, TextAlign::CENTER, "Screen Saver");
          it.printf(50, 80, id(my_font), light_blue, "Delay secs");
          it.printf(185, 80, id(my_font), light_blue, "Dim Brightness");
          it.printf(105, 100, id(icon_font_55), lime, TextAlign::LEFT, "\U000F0B2C");
          it.printf(65, 100, id(icon_font_55), lime, TextAlign::RIGHT, "\U000F0B26");
          it.rectangle(65 , 105 , 40 , 40 , lime);
          it.printf(85, 125, id(my_font5), light_blue, TextAlign::CENTER, "%.f", id(s_saver_delay).state);
          it.printf(20, 160, id(my_font), light_blue, "Screen off delay");
          it.printf(105, 180, id(icon_font_55), lime, TextAlign::LEFT, "\U000F0B2C");
          it.printf(65, 180, id(icon_font_55), lime, TextAlign::RIGHT, "\U000F0B26");
          it.rectangle(65 , 180 , 40 , 40 , lime);
          it.printf(85, 200, id(my_font5), light_blue, TextAlign::CENTER, "%.f", id(s_saver_blank_delay).state);
          it.printf(255, 100, id(icon_font_55), pink, TextAlign::LEFT, "\U000F0B2C");
          it.printf(215, 100, id(icon_font_55), pink, TextAlign::RIGHT, "\U000F0B26");
          it.rectangle(215 , 105 , 40 , 40 , pink);
          it.printf(235, 125, id(my_font5), light_blue, TextAlign::CENTER, "%.f", id(s_saver_brightness).state);

      - id: time_remaining_page ##### timer countdown page #####
        lambda: |-
          it.fill(id(black));
          it.printf(160, 20, id(my_font5), light_blue, TextAlign::CENTER, "Active Timers");
          it.printf(160, 70, id(icon_font_80), light_blue, TextAlign::CENTER, "\U000F0150");
          it.printf(160, 155, id(my_font6), light_blue, TextAlign::CENTER, "%s", id(time_remaining_0).state.c_str());

      - id: wifi_page ##### wifi info page #####
        lambda: |-
          it.fill(id(black));
          if(id(api_connection) == true) {
                  it.printf(15, 5, id(icon_font_55), blue, "\U000F07D0");
          } else {
                  it.printf(15, 5, id(icon_font_55), red, "\U000F087B");
          }
          if(id(wifi_connection) == true) {
                  it.printf(80, 5, id(icon_font_55), lime, "\U000F16BD");
          } else {
                  it.printf(80, 5, id(icon_font_55), red, "\U000F16BC");
          }
          if(id(time_remaining_0).state == "0:00:00"){
          it.printf(135, 5, id(icon_font_55), red, "\U000F0150");
          } else {
          it.printf(135, 5, id(icon_font_55), lime, "\U000F0150");
          }
          if(id(mute_switch).state) {
                 it.printf(190, 5, id(icon_font_55), red, "\U000F036D");
          } else {
                 it.printf(190, 5, id(icon_font_55), lime, "\U000F036C");
          }
          if(id(alarm_status).state == "disarmed") {
          it.printf(250, 5, id(icon_font_55), red, "\U000F099E");
          } else if(id(alarm_status).state == "arming") {
          it.printf(250, 5, id(icon_font_55), amber, "\U000F0565");
          } else if(id(alarm_status).state == "armed_home") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F068A");
          } else if(id(alarm_status).state == "armed_away") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F099D");
          } else if(id(alarm_status).state == "armed_night") {
          it.printf(250, 5, id(icon_font_55), green, "\U000F1828");
          }
          it.printf(160, 75, id(my_font5), light_blue, TextAlign::CENTER, "ssid");
          it.printf(160, 95, id(my_font5), yellow, TextAlign::CENTER, "%s", id(connected_ssid).state.c_str());
          it.printf(160, 125, id(my_font5), light_blue, TextAlign::CENTER, "bssid");
          it.printf(160, 145, id(my_font5), yellow, TextAlign::CENTER, "%s", id(connected_bssid).state.c_str());
          it.printf(160, 175, id(my_font5), light_blue, TextAlign::CENTER, "Device MAC");
          it.printf(160, 195, id(my_font5), yellow, TextAlign::CENTER, "%s", id(device_mac).state.c_str());
          it.printf(38, 210, id(my_font5), light_blue, TextAlign::LEFT, "Signal Strength");
          it.printf(283, 210, id(my_font5), yellow, TextAlign::RIGHT, "%4.f%%", id(wifi_percent).state);

      - id: alarm_page   #### alarm page #####
        lambda: |-
          if(id(alarm_status).state == "disarmed") {
          it.printf(10, 10, id(icon_font_180), red, "\U000F099E");
          it.printf(40, 200, id(my_font3), red, "Disarmed");
          } else if(id(alarm_status).state == "arming") {
          it.printf(10, 10, id(icon_font_180), amber, "\U000F0565");
          it.printf(40, 200, id(my_font3), amber, "Arming");
          } else if(id(alarm_status).state == "armed_home") {
          it.printf(10, 10, id(icon_font_180), green, "\U000F068A");
          it.printf(60, 200, id(my_font3), green, "Armed");
          } else if(id(alarm_status).state == "armed_away") {
          it.printf(10, 10, id(icon_font_180), green, "\U000F099D");
          it.printf(60, 200, id(my_font3), green, "Armed");
          } else if(id(alarm_status).state == "armed_night") {
          it.printf(10, 10, id(icon_font_180), green, "\U000F1828");
          it.printf(60, 200, id(my_font3), green, "Armed");
          }
          if(id(alarm_status).state == "armed_home") {
          it.printf(225, 5, id(icon_font_60), green, "\U000F068A");
          it.printf(233, 60, id(my_font18), light_blue, "Home");
          } else {
          it.printf(225, 5, id(icon_font_60), blue_drk, "\U000F068A");
          it.printf(233, 60, id(my_font18), light_blue, "Home");
          }
          if(id(alarm_status).state == "armed_away") {
          it.printf(225, 80, id(icon_font_60), green, "\U000F099D");
          it.printf(233, 135, id(my_font18), light_blue, "Away");
          } else {
          it.printf(225, 80, id(icon_font_60), blue_drk, "\U000F099D");
          it.printf(233, 135, id(my_font18), light_blue, "Away");
          }
          if(id(alarm_status).state == "armed_night") {
          it.printf(225, 155, id(icon_font_60), green, "\U000F1828");
          it.printf(228, 215, id(my_font18), light_blue, "Night");
          } else {
          it.printf(225, 155, id(icon_font_60), blue_drk, "\U000F1828");
          it.printf(228, 215, id(my_font18), light_blue, "Night");
          }
      - id: alarm_home_activate_page ##### alarm  home activation page #####
        lambda: |-
          auto pin_state = id(current_pin).c_str();
          it.print(310, 80, id(my_font3), TextAlign::RIGHT, pin_state);
          // loop for numbers 1 - 9
          for (int i = 0; i < 3; i++) {
          for (int j = 0; j < 3; j++) {
          int number = i * 3 + j + 1;
          int x_position = 15 + j * 56;  // Ajustement de la position en X
          int y_position = 15 + i * 56;  // Ajustement de la position en Y
          it.rectangle(x_position, y_position, 48, 48, light_blue);  // Taille du rectangle ajustée
          char num_str[2];
          snprintf(num_str, sizeof(num_str), "%d", number);
          it.print(x_position + 24, y_position + 24, id(my_font3), TextAlign::CENTER, num_str);  // Centrage du chiffre
          }
           }
          it.rectangle(71, 183, 48, 48, light_blue);  // Position et taille du rectangle ajustées
          it.print(95, 207, id(my_font3), TextAlign::CENTER, "0");  // Centrage du chiffre "0"
          //it.filled_rectangle(198, 110, 108, 50, green);
          if(id(alarm_status).state == "disarmed"){
          it.filled_rectangle(198, 110, 108, 50, red);
          it.print(255, 135, id(my_font3), white, TextAlign::CENTER, "Arm");
          } else if(id(alarm_status).state == "armed_home"){
          it.filled_rectangle(198, 110, 108, 50, green);
          it.print(255, 135, id(my_font3), white, TextAlign::CENTER, "Disarm");
          }
          it.filled_rectangle(198, 170, 108, 50, blue_drk);
          it.print(255, 195, id(my_font3), white, TextAlign::CENTER, "Clear");
          if(id(alarm_status).state == "disarmed") {
          it.printf(255, 30, id(icon_font_55), red, TextAlign::CENTER, "\U000F068A");
          it.printf(255, 70, id(my_font3), red, TextAlign::CENTER, "Disarmed");
          } else if(id(alarm_status).state == "arming") {
          it.printf(255, 30, id(icon_font_55), amber, TextAlign::CENTER, "\U000F0565");
          it.printf(255, 70, id(my_font3), amber, TextAlign::CENTER, "Arming");
          } else if(id(alarm_status).state == "armed_home") {
          it.printf(255, 30, id(icon_font_55), green, TextAlign::CENTER, "\U000F068A");
          it.printf(255, 70, id(my_font3), green, TextAlign::CENTER, "Armed");
          }
      - id: alarm_away_activate_page ##### alarm away activation page #####
        lambda: |-
          auto pin_state = id(current_pin).c_str();
          it.print(310, 80, id(my_font3), TextAlign::RIGHT, pin_state);
          // loop for numbers 1 - 9
          for (int i = 0; i < 3; i++) {
          for (int j = 0; j < 3; j++) {
          int number = i * 3 + j + 1;
          int x_position = 15 + j * 56;  // Ajustement de la position en X
          int y_position = 15 + i * 56;  // Ajustement de la position en Y
          it.rectangle(x_position, y_position, 48, 48, light_blue);  // Taille du rectangle ajustée
          char num_str[2];
          snprintf(num_str, sizeof(num_str), "%d", number);
          it.print(x_position + 24, y_position + 24, id(my_font3), TextAlign::CENTER, num_str);  // Centrage du chiffre
          }
           }
          it.rectangle(71, 183, 48, 48, light_blue);  // Position et taille du rectangle ajustées
          it.print(95, 207, id(my_font3), TextAlign::CENTER, "0");  // Centrage du chiffre "0"
          if(id(alarm_status).state == "disarmed"){
          it.filled_rectangle(198, 110, 108, 50, red);
          it.print(255, 135, id(my_font3), white, TextAlign::CENTER, "Arm");
          } else if(id(alarm_status).state == "armed_away"){
          it.filled_rectangle(198, 110, 108, 50, green);
          it.print(255, 135, id(my_font3), white, TextAlign::CENTER, "Disarm");
          }
          it.filled_rectangle(198, 170, 108, 50, blue_drk);
          it.print(255, 195, id(my_font3), white, TextAlign::CENTER, "Clear");
          if(id(alarm_status).state == "disarmed") {
          it.printf(255, 30, id(icon_font_55), red, TextAlign::CENTER, "\U000F099D");
          it.printf(255, 70, id(my_font3), red, TextAlign::CENTER, "Disarmed");
          } else if(id(alarm_status).state == "arming") {
          it.printf(255, 30, id(icon_font_55), amber, TextAlign::CENTER, "\U000F0565");
          it.printf(255, 70, id(my_font3), amber, TextAlign::CENTER, "Arming");
          } else if(id(alarm_status).state == "armed_away") {
          it.printf(255, 30, id(icon_font_55), green, TextAlign::CENTER, "\U000F099D");
          it.printf(255, 70, id(my_font3), green, TextAlign::CENTER, "Armed");
          }
      - id: alarm_night_activate_page ##### alarm night activation page #####
        lambda: |-
          auto pin_state = id(current_pin).c_str();
          it.print(310, 80, id(my_font3), TextAlign::RIGHT, pin_state);
          // loop for numbers 1 - 9
          for (int i = 0; i < 3; i++) {
          for (int j = 0; j < 3; j++) {
          int number = i * 3 + j + 1;
          int x_position = 15 + j * 56;  // Ajustement de la position en X
          int y_position = 15 + i * 56;  // Ajustement de la position en Y
          it.rectangle(x_position, y_position, 48, 48, light_blue);  // Taille du rectangle ajustée
          char num_str[2];
          snprintf(num_str, sizeof(num_str), "%d", number);
          it.print(x_position + 24, y_position + 24, id(my_font3), TextAlign::CENTER, num_str);  // Centrage du chiffre
          }
           }
          it.rectangle(71, 183, 48, 48, light_blue);  // Position et taille du rectangle ajustées
          it.print(95, 207, id(my_font3), TextAlign::CENTER, "0");  // Centrage du chiffre "0"
          if(id(alarm_status).state == "disarmed"){
          it.filled_rectangle(198, 110, 108, 50, red);
          it.print(255, 135, id(my_font3), white, TextAlign::CENTER, "Arm");
          } else if(id(alarm_status).state == "armed_night"){
          it.filled_rectangle(198, 110, 108, 50, green);
          it.print(255, 135, id(my_font3), white, TextAlign::CENTER, "Disarm");
          }
          it.filled_rectangle(198, 170, 108, 50, blue_drk);
          it.print(255, 195, id(my_font3), white, TextAlign::CENTER, "Clear");
          if(id(alarm_status).state == "disarmed") {
          it.printf(255, 30, id(icon_font_55), red, TextAlign::CENTER, "\U000F1828");
          it.printf(255, 70, id(my_font3), red, TextAlign::CENTER, "Disarmed");
          } else if(id(alarm_status).state == "arming") {
          it.printf(255, 30, id(icon_font_55), amber, TextAlign::CENTER, "\U000F0565");
          it.printf(255, 70, id(my_font3), amber, TextAlign::CENTER, "Arming");
          } else if(id(alarm_status).state == "armed_night") {
          it.printf(255, 30, id(icon_font_55), green, TextAlign::CENTER, "\U000F1828");
          it.printf(255, 70, id(my_font3), green, TextAlign::CENTER, "Armed");
          }
i2c:
  - id: bus_a
    sda: GPIO08
    scl: GPIO18
    scan: true
    sda_pullup_enabled: true
    scl_pullup_enabled: true
    frequency: 100kHz

  - sda: GPIO41
    scl: GPIO40
    scan: true
    sda_pullup_enabled: true
    scl_pullup_enabled: true
    frequency: 50kHz
    id: bus_b


touchscreen:
  - platform: gt911
    i2c_id: bus_a
    address: 0x5D
    id: gt911_touchscreen
    interrupt_pin:
      number: GPIO3
      ignore_strapping_warning: true
    on_touch:
      - lambda: id(led).turn_on().set_brightness(id(s_default_brightness).state /100).perform();
    on_release:
      - script.execute: saver_enabled

binary_sensor:
###### top left hand physical button #######
  - platform: gpio
    id: top_left_button
    pin:
      number: GPIO0
      mode: INPUT_PULLUP
      inverted: true
      ignore_strapping_warning: true
    on_press:
      - if:
          condition:
            - display.is_displaying_page: saver_page
          then:
            - lambda: id(led).turn_on().set_brightness(id(s_default_brightness).state /100).perform();
            - display.page.show: idle_page
            - script.execute: saver_enabled
            - component.update: s3_box_lcd
          else:
            if:
              condition:
                - display.is_displaying_page: idle_page
              then:
                - script.execute: saver_enabled
                - display.page.show: saver_page
                - component.update: s3_box_lcd

# #######     red circle home button   #####################
  - platform: gt911
    id: home_button
    index: 0
    on_press:
      if:
        condition:
          - display.is_displaying_page: idle_page
        then:
          - script.execute: saver_enabled
        else:
          - lambda: id(led).turn_on().set_brightness(id(s_default_brightness).state /100).perform();
          - display.page.show: idle_page
          - component.update: s3_box_lcd

###### radar sensor ########   # remove for no sensor version
  - platform: gpio
    pin:
      number: GPIO21
    name: "Presence detect"
    disabled_by_default: false
    device_class: "occupancy"
    on_state:
      if:
        condition:
          and:
            - switch.is_on: s_saver
            - switch.is_on: s_saver_presc
            - display.is_displaying_page: saver_page
        then:
          - display.page.show: idle_page
          - component.update: s3_box_lcd
          - script.execute: saver_enabled

##### satus bar buttons #####
  - platform: touchscreen
    pages:
      - idle_page
      - info_page
      - lights_page
      - template_page
      - media_page
      - ext_media_page
      - scenes_page
      - settings_page
    id: status_bar_1
    x_min: 5
    x_max: 60
    y_min: 0
    y_max: 55
          #### make sure that the following 4 lines are uncommented by removing the prefixed '#' ###
    # on_click:
      # min_length: 10ms
      # max_length: 500ms
      # then:
      #### add your action here - make sure to uncomment the following  line by removing the prefixed '#' and keep these below your action #####
         # - component.update: s3_box_lcd

  - platform: touchscreen
    pages:
      - idle_page
      - info_page
      - lights_page
      - template_page
      - media_page
      - ext_media_page
      - scenes_page
      - settings_page
    id: status_bar_2
    internal: true
    x_min: 65
    x_max: 125
    y_min: 0
    y_max: 55
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - display.page.show: wifi_page
        - component.update: s3_box_lcd


  - platform: touchscreen
    pages:
      - idle_page
      - info_page
      - lights_page
      - template_page
      - media_page
      - ext_media_page
      - scenes_page
      - settings_page
    id: status_bar_3
    internal: true
    x_min: 130
    x_max: 185
    y_min: 0
    y_max: 55
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        if:
          condition:
            - switch.is_on: timer_ringing
          then:
            - display.page.show: timer_finished_page
            - component.update: s3_box_lcd
          else:
            - display.page.show: time_remaining_page
            - component.update: s3_box_lcd

  - platform: touchscreen
    pages:
      - idle_page
      - info_page
      - lights_page
      - template_page
      - media_page
      - ext_media_page
      - scenes_page
      - settings_page
    id: status_bar_4
    internal: true
    x_min: 190
    x_max: 245
    y_min: 0
    y_max: 55
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - switch.toggle: mute_switch
        - component.update: s3_box_lcd

  - platform: touchscreen
    pages:
      - idle_page
      - info_page
      - lights_page
      - template_page
      - media_page
      - ext_media_page
      - scenes_page
      - settings_page
    name: status_bar_5
    internal: true
    x_min: 250
    x_max: 305
    y_min: 0
    y_max: 55
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - display.page.show: alarm_page
        - component.update: s3_box_lcd

##### settings page ####
  - platform: touchscreen
    page_id: settings_page
    id: voice_set
    internal: true
    x_min: 5
    x_max: 105
    y_min: 100
    y_max: 165
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - display.page.show: ww_set_page
        - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: settings_page
    id: ss_set
    internal: true
    x_min: 110
    x_max: 210
    y_min: 100
    y_max: 165
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - display.page.show: ss_set_page
        - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: settings_page
    id: info_set
    internal: true
    x_min: 215
    x_max: 315
    y_min: 100
    y_max: 165
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - display.page.show: info_page
        - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: settings_page
    id: device_set
    internal: true
    x_min: 5
    x_max: 105
    y_min: 175
    y_max: 240
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - display.page.show: device_set_page
        - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: settings_page
    id: voice_test
    internal: true
    x_min: 215
    x_max: 315
    y_min: 175
    y_max: 240
    on_press:
      then:
        - switch.turn_on: mute_switch
        - lambda: id(va).set_use_wake_word(false);
        - delay: 100ms
        - voice_assistant.start
        - wait_until:
            not:
              - voice_assistant.is_running
        - voice_assistant.stop
    on_release:
      then:
        - switch.turn_off: mute_switch
        - component.update: s3_box_lcd

  - platform: touchscreen
    pages:
      - device_set_page
    id: back_button
    internal: true
    x_min: 5
    x_max: 105
    y_min: 175
    y_max: 240
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - display.page.show: settings_page
        - component.update: s3_box_lcd
#########################################
##### idle / home page ####
  - platform: touchscreen
    page_id: idle_page
    id: control_1
    internal: true
    x_min: 5
    x_max: 105
    y_min: 90
    y_max: 170
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - display.page.show: climate_page
        - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: idle_page
    id: control_2
    internal: true
    x_min: 110
    x_max: 210
    y_min: 90
    y_max: 170
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - display.page.show: lights_page
        - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: idle_page
    id: control_3
    internal: true
    x_min: 215
    x_max: 315
    y_min: 90
    y_max: 170
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - display.page.show: template_page
        - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: idle_page
    id: control_4
    internal: true
    x_min: 5
    x_max: 105
    y_min: 175
    y_max: 240
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        if:
          condition:
            switch.is_off: output_audio
          then:
            - display.page.show: media_page
            - component.update: s3_box_lcd
          else:
            - display.page.show: ext_media_page
            - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: idle_page
    id: control_5
    internal: true
    x_min: 110
    x_max: 210
    y_min: 175
    y_max: 240
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - display.page.show: scenes_page
        - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: idle_page
    id: control_6
    internal: true
    x_min: 215
    x_max: 315
    y_min: 175
    y_max: 240
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - display.page.show: settings_page
        - component.update: s3_box_lcd

#### climate page #####
  - platform: touchscreen
    page_id: climate_page
    id: climate1
    internal: true
    x_min: 5
    x_max: 105
    y_min: 90
    y_max: 170
          #### make sure that the following 4 lines are uncommented by removing the prefixed '#' ###
    # on_click:
      # min_length: 10ms
      # max_length: 500ms
      # then:

      #### add your action here - make sure to uncomment the following  line by removing the prefixed '#' and keep these below your action #####

        # - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: climate_page
    id: climate2
    internal: true
    x_min: 110
    x_max: 210
    y_min: 90
    y_max: 170
          #### make sure that the following 4 lines are uncommented by removing the prefixed '#' ###
    # on_click:
      # min_length: 10ms
      # max_length: 500ms
      # then:
      #### add your action here - make sure to uncomment the following  line by removing the prefixed '#' and keep these below your action #####

        # - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: climate_page
    id: climate3
    internal: true
    x_min: 215
    x_max: 315
    y_min: 90
    y_max: 170
          #### make sure that the following 4 lines are uncommented by removing the prefixed '#' ###
    # on_click:
      # min_length: 10ms
      # max_length: 500ms
      # then:
      #### add your action here - make sure to uncomment the following  line by removing the prefixed '#' and keep these below your action #####

        # - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: climate_page
    id: climate4
    internal: true
    x_min: 5
    x_max: 105
    y_min: 175
    y_max: 240
          #### make sure that the following 4 lines are uncommented by removing the prefixed '#' ###
    # on_click:
      # min_length: 10ms
      # max_length: 500ms
      # then:
      #### add your action here - make sure to uncomment the following  line by removing the prefixed '#' and keep these below your action #####

        # - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: climate_page
    id: climate5
    internal: true
    x_min: 110
    x_max: 210
    y_min: 175
    y_max: 240
          #### make sure that the following 4 lines are uncommented by removing the prefixed '#' ###
    # on_click:
      # min_length: 10ms
      # max_length: 500ms
      # then:
      #### add your action here - make sure to uncomment the following  line by removing the prefixed '#' and keep these below your action #####

        # - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: climate_page
    id: climate6
    internal: true
    x_min: 215
    x_max: 315
    y_min: 175
    y_max: 240
          #### make sure that the following 4 lines are uncommented by removing the prefixed '#' ###
    # on_click:
      # min_length: 10ms
      # max_length: 500ms
      # then:
      #### add your action here - make sure to uncomment the following  line by removing the prefixed '#' and keep these below your action #####

        # - component.update: s3_box_lcd
##### lights page #####
  - platform: touchscreen
    page_id: lights_page
    id: lights1
    internal: true
    x_min: 5
    x_max: 105
    y_min: 90
    y_max: 170
          #### make sure that the following 4 lines are uncommented by removing the prefixed '#' ###
    # on_click:
      # min_length: 10ms
      # max_length: 500ms
      # then:
      #### add your action here - make sure to uncomment the following  line by removing the prefixed '#' and keep these below your action #####

        # - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: lights_page
    id: lights2
    internal: true
    x_min: 110
    x_max: 210
    y_min: 90
    y_max: 170
          #### make sure that the following 4 lines are uncommented by removing the prefixed '#' ###
    # on_click:
      # min_length: 10ms
      # max_length: 500ms
      # then:
      #### add your action here - make sure to uncomment the following  line by removing the prefixed '#' and keep these below your action #####

        # - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: lights_page
    id: lights3
    internal: true
    x_min: 215
    x_max: 315
    y_min: 90
    y_max: 170
          #### make sure that the following 4 lines are uncommented by removing the prefixed '#' ###
    # on_click:
      # min_length: 10ms
      # max_length: 500ms
      # then:
      #### add your action here - make sure to uncomment the following  line by removing the prefixed '#' and keep these below your action #####

        # - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: lights_page
    id: lights4
    internal: true
    x_min: 5
    x_max: 105
    y_min: 175
    y_max: 240
          #### make sure that the following 4 lines are uncommented by removing the prefixed '#' ###
    # on_click:
      # min_length: 10ms
      # max_length: 500ms
      # then:
      #### add your action here - make sure to uncomment the following  line by removing the prefixed '#' and keep these below your action #####

        # - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: lights_page
    id: lights5
    internal: true
    x_min: 110
    x_max: 210
    y_min: 175
    y_max: 240
          #### make sure that the following 4 lines are uncommented by removing the prefixed '#' ###
    # on_click:
      # min_length: 10ms
      # max_length: 500ms
      # then:
      #### add your action here - make sure to uncomment the following  line by removing the prefixed '#' and keep these below your action #####

        # - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: lights_page
    id: lights6
    internal: true
    x_min: 215
    x_max: 315
    y_min: 175
    y_max: 240
          #### make sure that the following 4 lines are uncommented by removing the prefixed '#' ###
    # on_click:
      # min_length: 10ms
      # max_length: 500ms
      # then:
      #### add your action here - make sure to uncomment the following  line by removing the prefixed '#' and keep these below your action #####

        # - component.update: s3_box_lcd

##### media player #####
  - platform: touchscreen
    page_id: media_page
    name: Volume Minus
    internal: true
    x_min: 5
    x_max: 105
    y_min: 90
    y_max: 170
    on_click:
      min_length: 0ms
      max_length: 500ms
      then:
        - logger.log: "Volume Minus pressed"
        - lambda: |-
            if (id(speaker_volume) > 0) {
              id(speaker_volume) -= 1;
            }
        - component.update: s3_box_lcd
        - script.execute: set_volume

  - platform: touchscreen
    page_id: media_page
    name: Volume Plus
    internal: true
    x_min: 215
    x_max: 315
    y_min: 90
    y_max: 170
    on_click:
      min_length: 0ms
      max_length: 500ms
      then:
        - logger.log: "Volume Plus pressed"
        - lambda: |-
            if (id(speaker_volume) < 10) {
              id(speaker_volume) += 1;
            }
        - component.update: s3_box_lcd
        - script.execute: set_volume

  - platform: touchscreen
    page_id: media_page
    name: Play Pause
    internal: true
    x_min: 110
    x_max: 210
    y_min: 90
    y_max: 170
    on_click:
      min_length: 0ms
      max_length: 500ms
      then:
        - if:
            condition:
              media_player.is_idle:
            then:
              - media_player.play
            else:
              - media_player.stop
        - logger.log: "Play Paused pressed"

  - platform: touchscreen
    page_id: media_page
    name: Mute Media
    internal: true
    x_min: 110
    x_max: 210
    y_min: 180
    y_max: 260
    on_click:
      min_length: 0ms
      max_length: 500ms
      then:
        - switch.toggle: media_mute
        - component.update: s3_box_lcd
#### external media ####
  - platform: touchscreen
    page_id: ext_media_page
    id: ext_prev_track
    internal: true
    x_min: 5
    x_max: 105
    y_min: 90
    y_max: 170
    on_click:
      min_length: 0ms
      max_length: 500ms
      then:
        - homeassistant.service:
            service: media_player.media_previous_track
            data:
              entity_id: media_player.${external_media_player}
        - component.update: s3_box_lcd


  - platform: touchscreen
    page_id: ext_media_page
    id: ext_next_track
    internal: true
    x_min: 215
    x_max: 315
    y_min: 90
    y_max: 170
    on_click:
      min_length: 0ms
      max_length: 500ms
      then:
        - homeassistant.service:
            service: media_player.media_next_track
            data:
              entity_id: media_player.${external_media_player}
        - component.update: s3_box_lcd


  - platform: touchscreen
    page_id: ext_media_page
    name: Play Pause
    internal: true
    x_min: 110
    x_max: 210
    y_min: 90
    y_max: 170
    on_click:
      min_length: 0ms
      max_length: 500ms
      then:
        - homeassistant.service:
            service: media_player.media_pause
            data:
              entity_id: media_player.${external_media_player}
        - component.update: s3_box_lcd


  - platform: touchscreen
    page_id: ext_media_page
    name: Mute Media
    internal: true
    x_min: 110
    x_max: 210
    y_min: 180
    y_max: 260
    on_click:
      min_length: 0ms
      max_length: 500ms
      then:
        - switch.toggle: ext_media_mute
        - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: ext_media_page
    id: vol_minus
    internal: true
    x_min: 5
    x_max: 105
    y_min: 180
    y_max: 260
    on_click:
      min_length: 0ms
      max_length: 500ms
      then:
        - homeassistant.service:
            service: media_player.volume_down
            data:
              entity_id: media_player.${external_media_player}
        - component.update: s3_box_lcd
        - script.execute: set_volume

  - platform: touchscreen
    page_id: ext_media_page
    id: vol_plus
    internal: true
    x_min: 215
    x_max: 315
    y_min: 180
    y_max: 260
    on_click:
      min_length: 0ms
      max_length: 500ms
      then:
        - homeassistant.service:
            service: media_player.volume_up
            data:
              entity_id: media_player.${external_media_player}
        - component.update: s3_box_lcd
        - script.execute: set_volume

##### scenes page ####
  - platform: touchscreen
    page_id: scenes_page
    id: scenes1
    internal: true
    x_min: 5
    x_max: 105
    y_min: 90
    y_max: 170
          #### make sure that the following 4 lines are uncommented by removing the prefixed '#' ###
    # on_click:
      # min_length: 10ms
      # max_length: 500ms
      # then:
      #### add your action here - make sure to uncomment the following  line by removing the prefixed '#' and keep these below your action #####

        # - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: scenes_page
    id: scenes2
    internal: true
    x_min: 110
    x_max: 210
    y_min: 90
    y_max: 170
    # on_click:
    #   min_length: 10ms
    #   max_length: 500ms

        #### make sure that the following  line are uncommented and sit at the bottom of this block after your action ###

            # - component.update: s3_box_lcd


  - platform: touchscreen
    page_id: scenes_page
    id: scenes3
    internal: true
    x_min: 215
    x_max: 315
    y_min: 90
    y_max: 170
    # on_click:
    #   min_length: 10ms
    #   max_length: 500ms

        #### make sure that the following  line are uncommented and sit at the bottom of this block after your action ###

            # - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: scenes_page
    id: scenes4
    internal: true
    x_min: 5
    x_max: 105
    y_min: 175
    y_max: 240
    # on_click:
    #   min_length: 10ms
    #   max_length: 500ms

        #### make sure that the following  line are uncommented and sit at the bottom of this block after your action ###

            # - component.update: s3_box_lcd


  - platform: touchscreen
    page_id: scenes_page
    id: scenes5
    internal: true
    x_min: 110
    x_max: 210
    y_min: 175
    y_max: 240
    # on_click:
    #   min_length: 10ms
    #   max_length: 500ms

        #### make sure that the following  line are uncommented and sit at the bottom of this block after your action ###

            # - component.update: s3_box_lcd


  - platform: touchscreen
    page_id: scenes_page
    id: scenes6
    internal: true
    x_min: 215
    x_max: 315
    y_min: 175
    y_max: 240
    # on_click:
    #   min_length: 10ms
    #   max_length: 500ms

        #### make sure that the following  line are uncommented and sit at the bottom of this block after your action ###

            # - component.update: s3_box_lcd

##### Screensaver Settings #####
  - platform: touchscreen
    page_id: ss_set_page
    id: ss_timeout
    internal: true
    x_min: 250
    x_max: 315
    y_min: 115
    y_max: 145
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - display.page.show: timeout_settings_page
        - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: ss_set_page
    id: ss_toggle
    internal: true
    x_min: 250
    x_max: 315
    y_min: 150
    y_max: 175
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - switch.toggle: s_saver
        - component.update: s3_box_lcd

  - platform: touchscreen # remove for no sensor version
    page_id: ss_set_page
    id: ss_wake_presc
    internal: true
    x_min: 250
    x_max: 315
    y_min: 180
    y_max: 205
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - switch.toggle: s_saver_presc
        - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: ss_set_page
    id: ss_toggle_blank
    internal: true
    x_min: 250
    x_max: 315
    y_min: 210
    y_max: 235
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - switch.toggle: s_saver_mode
        - component.update: s3_box_lcd

##### voice settings page #####
  - platform: touchscreen
    page_id: ww_set_page
    id: ww_chang_hass
    internal: true
    x_min: 10
    x_max: 315
    y_min: 100
    y_max: 135
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - select.operation:
            id: wake_word_engine_location
            operation: Next
            cycle: true
        - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: ww_set_page
    id: mute_response
    internal: true
    x_min: 250
    x_max: 315
    y_min: 145
    y_max: 170
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - switch.toggle: mute_response_switch
        - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: ww_set_page
    id: ww_wake_sound
    internal: true
    x_min: 250
    x_max: 315
    y_min: 180
    y_max: 205
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - switch.toggle: wake_sound
        - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: ww_set_page
    id: ww_toggle_conv
    internal: true
    x_min: 250
    x_max: 315
    y_min: 210
    y_max: 235
    on_click:
      - switch.toggle: display_conversation
      - component.update: s3_box_lcd

##### touch to wake screen #####
  - platform: touchscreen
    page_id: saver_page
    id: ss_wake
    internal: true
    x_min: 0
    x_max: 320
    y_min: 0
    y_max: 240
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - display.page.show: idle_page
        - component.update: s3_box_lcd

##### Timer finished page #####
  - platform: touchscreen
    page_id: timer_finished_page
    id: timer_dismiss
    internal: true
    x_min: 0
    x_max: 320
    y_min: 0
    y_max: 240
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - switch.turn_off: timer_ringing
        - display.page.show: idle_page
        - component.update: s3_box_lcd

##### Timeout settings buttons #####
  - id: ss_sleep_down
    page_id: timeout_settings_page
    platform: touchscreen
    internal: true
    x_min: 25
    x_max: 60
    y_min: 105
    y_max: 140
    on_press:
      then:
        - lambda: |-
            int sleep = id(s_saver_delay).state - 5;
            if (sleep < 1) {
              sleep = 1;
            }
            auto call = id(s_saver_delay).make_call();
            call.set_value(sleep);
            call.perform();
        - component.update: s3_box_lcd

  - id: ss_sleep_up
    page_id: timeout_settings_page
    platform: touchscreen
    internal: true
    x_min: 110
    x_max: 145
    y_min: 105
    y_max: 140
    on_press:
      then:
        - lambda: |-
            int sleep = id(s_saver_delay).state + 5;
            auto call = id(s_saver_delay).make_call();
            call.set_value(sleep);
            call.perform();
        - component.update: s3_box_lcd

  - id: ss_blank_down
    page_id: timeout_settings_page
    platform: touchscreen
    internal: true
    x_min: 25
    x_max: 60
    y_min: 180
    y_max: 220
    on_press:
      then:
        - lambda: |-
            int sleep = id(s_saver_blank_delay).state - 5;
            if (sleep < 1) {
              sleep = 1;
            }
            auto call = id(s_saver_blank_delay).make_call();
            call.set_value(sleep);
            call.perform();
        - component.update: s3_box_lcd

  - id: ss_blank_up
    page_id: timeout_settings_page
    platform: touchscreen
    internal: true
    x_min: 110
    x_max: 145
    y_min: 180
    y_max: 220
    on_press:
      then:
        - lambda: |-
            int sleep = id(s_saver_blank_delay).state + 5;
            auto call = id(s_saver_blank_delay).make_call();
            call.set_value(sleep);
            call.perform();
        - component.update: s3_box_lcd

  - id: ss_bright_down
    page_id: timeout_settings_page
    platform: touchscreen
    internal: true
    x_min: 165
    x_max: 195
    y_min: 105
    y_max: 140
    on_press:
      then:
        - lambda: |-
            int bright = id(s_saver_brightness).state - 5;
            if (bright < 1) {
              bright = 1;
            }
            auto call = id(s_saver_brightness).make_call();
            call.set_value(bright);
            call.perform();
        - component.update: s3_box_lcd

  - id: ss_bright_up
    page_id: timeout_settings_page
    platform: touchscreen
    internal: true
    x_min: 260
    x_max: 295
    y_min: 105
    y_max: 140
    on_press:
      then:
        - lambda: |-
            int bright = id(s_saver_brightness).state + 5;
            auto call = id(s_saver_brightness).make_call();
            call.set_value(bright);
            call.perform();
        - component.update: s3_box_lcd
##### device settings page #####
  - id: s_default_bright_down
    page_id: device_set_page
    platform: touchscreen
    internal: true
    x_min: 280
    x_max: 320
    y_min: 125
    y_max: 165
    on_press:
      then:
        - lambda: |-
            int default_bright = id(s_default_brightness).state - 5;
            if (default_bright < 1) {
              default_bright = 1;
            }
            auto call = id(s_default_brightness).make_call();
            call.set_value(default_bright);
            call.perform();
        - component.update: s3_box_lcd

  - id: s_default_bright_up
    page_id: device_set_page
    platform: touchscreen
    internal: true
    x_min: 155
    x_max: 195
    y_min: 125
    y_max: 165
    on_press:
      then:
        - lambda: |-
            int default_bright = id(s_default_brightness).state + 5;
            auto call = id(s_default_brightness).make_call();
            call.set_value(default_bright);
            call.perform();
        - component.update: s3_box_lcd

  - id: ext_media_toggle
    page_id: device_set_page
    platform: touchscreen
    internal: true
    x_min: 280
    x_max: 320
    y_min: 80
    y_max: 120
    on_press:
      then:
        - switch.toggle: output_audio
        - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: device_set_page
    id: chang_display_format
    x_min: 200
    x_max: 260
    y_min: 175
    y_max: 210
    on_click:
      min_length: 10ms
      max_length: 500ms
      then:
        - select.operation:
            id: time_format
            operation: Next
            cycle: true
        - component.update: s3_box_lcd


##### alarm panel buttons #####
  - platform: touchscreen
    pages:
      - alarm_away_activate_page
      - alarm_home_activate_page
      - alarm_night_activate_page
    id: alarm_key_1
    internal: true
    x_min: 15
    x_max: 63
    y_min: 15
    y_max: 63
    on_press:
      - script.execute: increment_digit_1
      - component.update: s3_box_lcd

  - platform: touchscreen
    pages:
      - alarm_away_activate_page
      - alarm_home_activate_page
      - alarm_night_activate_page
    id: alarm_key_2
    internal: true
    x_min: 71
    x_max: 119
    y_min: 15
    y_max: 63
    on_press:
      - script.execute: increment_digit_2
      - component.update: s3_box_lcd

  - platform: touchscreen
    pages:
      - alarm_away_activate_page
      - alarm_home_activate_page
      - alarm_night_activate_page
    id: alarm_key_3
    internal: true
    x_min: 127
    x_max: 175
    y_min: 15
    y_max: 63
    on_press:
      - script.execute: increment_digit_3
      - component.update: s3_box_lcd

  - platform: touchscreen
    pages:
      - alarm_away_activate_page
      - alarm_home_activate_page
      - alarm_night_activate_page
    id: alarm_key_4
    internal: true
    x_min: 15
    x_max: 63
    y_min: 71
    y_max: 119
    on_press:
      - script.execute: increment_digit_4
      - component.update: s3_box_lcd

  - platform: touchscreen
    pages:
      - alarm_away_activate_page
      - alarm_home_activate_page
      - alarm_night_activate_page
    id: alarm_key_5
    internal: true
    x_min: 71
    x_max: 119
    y_min: 71
    y_max: 119
    on_press:
      - script.execute: increment_digit_5
      - component.update: s3_box_lcd

  - platform: touchscreen
    pages:
      - alarm_away_activate_page
      - alarm_home_activate_page
      - alarm_night_activate_page
    id: alarm_key_6
    internal: true
    x_min: 127
    x_max: 175
    y_min: 71
    y_max: 119
    on_press:
      - script.execute: increment_digit_6
      - component.update: s3_box_lcd

  - platform: touchscreen
    pages:
      - alarm_away_activate_page
      - alarm_home_activate_page
      - alarm_night_activate_page
    id: alarm_key_7
    internal: true
    x_min: 15
    x_max: 63
    y_min: 127
    y_max: 175
    on_press:
      - script.execute: increment_digit_7
      - component.update: s3_box_lcd

  - platform: touchscreen
    pages:
      - alarm_away_activate_page
      - alarm_home_activate_page
      - alarm_night_activate_page
    id: alarm_key_8
    internal: true
    x_min: 71
    x_max: 119
    y_min: 127
    y_max: 175
    on_press:
      - script.execute: increment_digit_8
      - component.update: s3_box_lcd

  - platform: touchscreen
    pages:
      - alarm_away_activate_page
      - alarm_home_activate_page
      - alarm_night_activate_page
    id: alarm_key_9
    internal: true
    x_min: 127
    x_max: 175
    y_min: 127
    y_max: 175
    on_press:
      - script.execute: increment_digit_9
      - component.update: s3_box_lcd

  - platform: touchscreen
    pages:
      - alarm_away_activate_page
      - alarm_home_activate_page
      - alarm_night_activate_page
    id: alarm_key_0
    internal: true
    x_min: 71
    x_max: 119
    y_min: 183
    y_max: 231
    on_press:
      - media_player.play_media:
          media_url: '${home_assistant_host}/local/sounds/key.mp3'
      - script.execute: increment_digit_0
      - component.update: s3_box_lcd

  - platform: touchscreen
    pages:
      - alarm_away_activate_page
      - alarm_home_activate_page
      - alarm_night_activate_page
    id: clear_pin
    x_min: 198
    x_max: 306
    y_min: 170
    y_max: 220
    on_press:
      then:
        - lambda: |-
            id(current_pin) = "";
        - component.update: s3_box_lcd

  - platform: touchscreen
    pages:
      - alarm_away_activate_page
      - alarm_home_activate_page
      - alarm_night_activate_page
    id: alarm_ok
    x_min: 198
    x_max: 306
    y_min: 110
    y_max: 160
    on_click:
      min_length: 0ms
      max_length: 500ms
      then:
        - if:
            condition:
              - lambda: |-
                  return (id(alarm_status).state == "arming" || id(alarm_status).state == "armed_away" || id(alarm_status).state == "armed_home" || id(alarm_status).state == "armed_night");
            then:
              - homeassistant.service:
                  service: alarm_control_panel.alarm_disarm
                  data:
                    entity_id: alarm_control_panel.alarmo
                    code: !lambda return id(current_pin).c_str();
              - lambda: |-
                  id(current_pin) = "";
            else:
              - if:
                  condition:
                    and:
                      - lambda: |-
                          return (id(alarm_status).state == "disarmed");
                      - display.is_displaying_page: alarm_home_activate_page
                  then:
                    - homeassistant.service:
                        service: alarm_control_panel.alarm_arm_home
                        data:
                          entity_id: alarm_control_panel.alarmo
                          code: !lambda return id(current_pin).c_str();
                    - lambda: |-
                        id(current_pin) = "";
                  else:
                    - if:
                        condition:
                          and:
                            - lambda: |-
                                return (id(alarm_status).state == "disarmed");

                            - display.is_displaying_page: alarm_away_activate_page
                        then:
                          - homeassistant.service:
                              service: alarm_control_panel.alarm_arm_away
                              data:
                                entity_id: alarm_control_panel.alarmo
                                code: !lambda return id(current_pin).c_str();
                          - lambda: |-
                              id(current_pin) = "";

                        else:
                          - if:
                              condition:
                                and:
                                  - lambda: |-
                                      return (id(alarm_status).state == "disarmed");
                                  - display.is_displaying_page: alarm_night_activate_page
                              then:
                                - homeassistant.service:
                                    service: alarm_control_panel.alarm_arm_night
                                    data:
                                      entity_id: alarm_control_panel.alarmo
                                      code: !lambda return id(current_pin).c_str();
                                - lambda: |-
                                    id(current_pin) = "";
        - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: alarm_page
    id: arm_disarm_home
    x_min: 215
    x_max: 320
    y_min: 5
    y_max: 75
    on_click:
      min_length: 0ms
      max_length: 500ms
      then:
        - display.page.show: alarm_home_activate_page
        - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: alarm_page
    id: arm_disarm_away
    x_min: 215
    x_max: 320
    y_min: 80
    y_max: 150
    on_click:
      min_length: 0ms
      max_length: 500ms
      then:
        - display.page.show: alarm_away_activate_page
        - component.update: s3_box_lcd

  - platform: touchscreen
    page_id: alarm_page
    id: arm_disarm_night
    x_min: 215
    x_max: 320
    y_min: 155
    y_max: 240
    on_click:
      min_length: 0ms
      max_length: 500ms
      then:
        - display.page.show: alarm_night_activate_page
        - component.update: s3_box_lcd
################## config end ############################