esp_apps/larry/larry.yaml

3964 lines
131 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 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
dns1: 192.168.50.1
dns2: 8.8.8.8
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:
http_request:
useragent: esphome/device
timeout: 10s
verify_ssl: false # if you're using HTTP or self-signed HTTPS
online_image:
- id: ewie_live_feed_image
format: JPEG
type: RGB565
url: '${home_assistant_host}/static/icons/ohf.svg'
resize: "320x240"
on_download_finished:
- component.update: s3_box_lcd
on_error:
- logger.log: "❌ Failed to load camera snapshot"
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;"
- interval: 3s
id: ewie_feed_refresh_interval
then:
- if:
condition:
# - lambda: 'return id(s3_box_lcd).get_active_page() == id(video_feed_page);'
- lambda: 'return id(global_ewie_streaming);'
then:
- script.execute: update_ewie_feed_image
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:
and:
- switch.is_on: s_saver
- lambda: 'return !id(global_ewie_streaming);'
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());
- id: update_ewie_feed_image
mode: restart
then:
- lambda: |-
std::string host = "${home_assistant_host}";
std::string path = id(ewie_image_path).state;
std::string full_url = host + path;
ESP_LOGD("video_feed_page", "Current url: %s", full_url);
id(ewie_live_feed_image).set_url(full_url);
- component.update: ewie_live_feed_image
- component.update: s3_box_lcd
- script.execute: saver_enabled
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
- id: global_ewie_streaming
type: bool
initial_value: "false"
restore_value: no
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
- platform: homeassistant
id: ewie_image_path
entity_id: camera.ewie_live_ansicht
attribute: entity_picture
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 == "clear-night") {
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");
}
- id: video_feed_page ### load picture
lambda: |-
it.fill(id(purple));
it.image(0, 0, id(ewie_live_feed_image));
on_page_change:
- to: video_feed_page
then:
- lambda: |-
ESP_LOGD("ewie", "starting to stream");
id(global_ewie_streaming) = true;
- from: video_feed_page
then:
- lambda: |-
ESP_LOGD("ewie", "stopping to stream");
id(global_ewie_streaming) = false;
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 '#' ###
# MARK: ewie button
on_click:
min_length: 10ms
max_length: 500ms
then:
- display.page.show: video_feed_page
- script.execute: update_ewie_feed_image
- 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 ############################