3895 lines
		
	
	
		
			129 KiB
		
	
	
	
		
			YAML
		
	
	
	
	
	
			
		
		
	
	
			3895 lines
		
	
	
		
			129 KiB
		
	
	
	
		
			YAML
		
	
	
	
	
	
| ## 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: gold
 | ||
|     hex: 'E1C564'
 | ||
|   - 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'
 | ||
| 
 | ||
| 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, 200, id(icon_font_55), yellow, TextAlign::CENTER, "\U000F0599");
 | ||
|           } else if (condition == "partlycloudy") {
 | ||
|             it.printf(240, 200, id(icon_font_55), light_blue, TextAlign::CENTER, "\U000F0595");
 | ||
|           } else if (condition == "cloudy") {
 | ||
|             it.printf(240, 200, id(icon_font_55), light_blue, TextAlign::CENTER, "\U000F0590");
 | ||
|           } else if (condition == "rainy") {
 | ||
|             it.printf(240, 200, id(icon_font_55), light_blue, TextAlign::CENTER, "\U000F0597");
 | ||
|           } else if (condition == "pouring") {
 | ||
|             it.printf(240, 200, id(icon_font_55), light_blue, TextAlign::CENTER, "\U000F0596");
 | ||
|           } else if (condition == "lightning") {
 | ||
|             it.printf(240, 200, id(icon_font_55), light_blue, TextAlign::CENTER, "\U000F0593");
 | ||
|           } else if (condition == "snowy") {
 | ||
|             it.printf(240, 200, id(icon_font_55), light_blue, TextAlign::CENTER, "\U000F0598");
 | ||
|           } else if (condition == "hail") {
 | ||
|             it.printf(240, 200, id(icon_font_55), light_blue, TextAlign::CENTER, "\U000F0592");
 | ||
|           } else if (condition == "fog") {
 | ||
|             it.printf(240, 200, id(icon_font_55), light_blue, TextAlign::CENTER, "\U000F0591");
 | ||
|           } else if (condition == "windy") {
 | ||
|             it.printf(240, 200, id(icon_font_55), light_blue, TextAlign::CENTER, "\U000F059D");
 | ||
|           } else if (condition == "clearnight") {
 | ||
|             it.printf(240, 200, id(icon_font_55), light_blue, TextAlign::CENTER, "\U000F0594");
 | ||
|           } else {
 | ||
|             it.printf(240, 200, id(icon_font_55), green, TextAlign::CENTER, "\U000F07A6"); // default: cannabis
 | ||
|           }
 | ||
| 
 | ||
|           // Device
 | ||
|           it.printf(80, 161, id(my_font4), light_blue, TextAlign::CENTER, "%.f°C", id(s3temp).state);
 | ||
|           it.printf(80, 200, id(icon_font_55), 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 ############################
 |