Code 19/06/24
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
#########################
# use_address: 192.168.2.53
#########################
manual_ip:
static_ip: !secret ip_m5stack_dial
gateway: !secret wifi_gtw
subnet: !secret wifi_sub
ap:
ssid: "m5stack-dial-fallback"
password: !secret wifi_ap_password
ota:
password: !secret ota_password
logger:
# level: DEBUG
api:
encryption:
key: !secret api_encryption_key
esp32:
board: esp32-s3-devkitc-1
framework:
type: arduino
esphome:
name: ${name}
friendly_name: ${friendly_name}
on_boot:
then:
- pcf8563.read_time: rtc_time
- delay: 13s
- light.turn_on: backlight
- display.page.show: page_01
external_components:
- source: github://dgaust/esphome@gc9a01
components: [ gc9a01, ft3267 ]
refresh: 0s
<<: !include m5dial_files/colors_and_fonts.yaml
<<: !include m5dial_files/images_and_icons.yaml
spi: #required by display.ili9xxx
mosi_pin: GPIO5
clk_pin: GPIO6
i2c:
- id: bus_internal #required by touchscreen.ft3267
sda: GPIO11
scl: GPIO12
scan: false
touchscreen:
platform: ft3267
on_touch:
then:
- logger.log:
format: 'Touch ID: %d at _____________________ (%d, %d)'
args: [touch.id, touch.x, touch.y]
rc522_i2c: # RFiD
i2c_id: bus_internal
address: 0x28
on_tag:
then:
- rtttl.play: 'two_short:d=4,o=5,b=100:16e6,16e6'
- homeassistant.tag_scanned: !lambda 'return x;'
rtttl: # buzzer
output: rtttl_out
id: my_rtttl
time:
- platform: pcf8563
id: rtc_time
address: 0x38
update_interval: never
- platform: homeassistant
on_time_sync:
then:
- pcf8563.write_time: rtc_time
- logger.log: "time synced"
output:
- id: lcdbacklight # screen backlight
platform: ledc
pin: GPIO9
min_power: 0
max_power: 1
- platform: ledc # buzzer
pin: GPIO3
id: rtttl_out
substitutions:
name: tab-m5stack-dial
friendly_name: M5Stack Dial
wifi_ssid: !secret wifi_ssid
wifi_password: !secret wifi_password
alarm_panel_id: alarm_control_panel.alarme_maison
climate_id: climate.heatpump_sdgs_ebusd
door_bell_id: input_boolean.test
garage_sensor_id: binary_sensor.io_frient_garage_09c6_input_1
garage_door_sensor_id: binary_sensor.magnet_aqara_garage_door_contact
gate_sensor_id: binary_sensor.tplt_gate_open_too_long
lux_sensor_id: sensor.ip030_mmw_aqara_living_luminance
window_group_id: binary_sensor.windows_upstairs
light_01_id: light.shelly_one_cour
window_01_id: binary_sensor.magnet_aqara_bedroom_north_contact
window_02_id: binary_sensor.magnet_aqara_kitchen_contact
window_03_id: binary_sensor.magnet_aqara_attic_contact
window_04_id: binary_sensor.magnet_aqara_bedroom_south_contact
window_05_id: binary_sensor.magnet_aqara_bay_contact
# ======================================================================================
# ======================================================================================
# ========================================================================== text sensor
text_sensor:
- platform: homeassistant
id: alarm_text # armed_away / armed_home / pending etc....
entity_id: $alarm_panel_id
on_value:
then:
- display.page.show: !lambda |-
auto selector = id(page_selector).state;
if (selector == "page_off" or selector == "page_01") {
return id(page_a1);
} else {
return nullptr;
}
- component.update: screen
- platform: homeassistant
id: gate_text # closed / open / alert
entity_id: $gate_sensor_id
attribute: esphome_text_sensor
<<: &gate_value
on_value:
then:
- display.page.show: !lambda |-
auto selector = id(page_selector).state;
auto gate = id(gate_text).state;
if (selector == "page_off" or selector == "page_01") {
if (gate == "open" or gate == "alert") {
return id(page_b1);
} else {
return nullptr;
}
} else {
return nullptr;
}
- component.update: screen
- platform: homeassistant
id: garage_text # off / on
entity_id: $garage_sensor_id
on_value:
then:
- display.page.show: !lambda |-
auto selector = id(page_selector).state;
if (selector == "page_off" or selector == "page_01") {
if (id(garage_text).state == "on") {
return id(page_b2);
} else {
return nullptr;
}
} else {
return nullptr;
}
- component.update: screen
- platform: homeassistant
id: garage_door_text # off / on
entity_id: $garage_door_sensor_id
on_value:
then:
- display.page.show: !lambda |-
auto selector = id(page_selector).state;
if (selector == "page_off" or selector == "page_01") {
if (id(garage_door_text).state == "on") {
return id(page_b2);
} else {
return nullptr;
}
} else {
return nullptr;
}
- component.update: screen
- platform: homeassistant
id: climate_mode_text # auto / heat / off
entity_id: $climate_id
- platform: homeassistant
id: door_bell_text # off / on
entity_id: $door_bell_id
<<: *gate_value
- platform: homeassistant
id: light_01_text # off / on
entity_id: $light_01_id
- platform: homeassistant
id: window_group_text # off / on
entity_id: $window_group_id
- platform: homeassistant
id: window_01_text # off / on
entity_id: $window_01_id
- platform: homeassistant
id: window_02_text # off / on
entity_id: $window_02_id
- platform: homeassistant
id: window_03_text # off / on
entity_id: $window_03_id
- platform: homeassistant
id: window_04_text # off / on
entity_id: $window_04_id
- platform: homeassistant
id: window_05_text # off / on
entity_id: $window_05_id
# ======================================================================================
# ======================================================================================
# ================================================================================ light
light:
- platform: monochromatic
id: backlight
name: "Backlight"
output: lcdbacklight
default_transition_length: 500ms
# ======================================================================================
# ======================================================================================
# =============================================================================== select
select:
- platform: template
name: Page Selector
icon: "mdi:book-open-page-variant-outline"
id: page_selector
options:
- "page_off"
- "page_01"
- "page_02"
- "page_a1"
- "page_b1"
- "page_b2"
- "page_c1"
- "page_d1"
initial_option: "page_01"
optimistic: true
on_value:
- if:
condition:
- lambda: 'return id(page_selector).state == "page_off";'
then:
- display.page.show: page_off
- lambda: 'id(lcdbacklight).set_level(0.1);'
- delay: 8s
- light.turn_off: backlight
else:
- if:
condition:
- light.is_off: backlight
then:
- light.turn_on: backlight
- display.page.show: !lambda |-
auto selector = id(page_selector).state;
if (selector == "page_01") {
return id(page_01);
} else if (selector == "page_02") {
return id(page_02);
} else if (selector == "page_a1") {
return id(page_a1);
} else if (selector == "page_b1") {
return id(page_b1);
} else if (selector == "page_b2") {
return id(page_b2);
} else if (selector == "page_c1") {
return id(page_c1);
} else if (selector == "page_d1") {
return id(page_d1);
} else {
return nullptr;
}
- component.update: screen
# ======================================================================================
# ======================================================================================
# ====================================================================== display + pages
display:
- platform: ili9xxx
model: gc9a01a
reset_pin: GPIO8
id: screen
cs_pin: GPIO7
dc_pin: GPIO4
dimensions:
height: 240
width: 240
on_page_change:
- to: page_off
then:
- select.set:
id: page_selector
option: page_off
- component.update: screen
- to: page_01
then:
- select.set:
id: page_selector
option: page_01
- component.update: screen
- to: page_02
then:
- select.set:
id: page_selector
option: page_02
- component.update: screen
- to: page_a1
then:
- select.set:
id: page_selector
option: page_a1
- component.update: screen
- to: page_b1
then:
- select.set:
id: page_selector
option: page_b1
- component.update: screen
- to: page_b2
then:
- select.set:
id: page_selector
option: page_b2
- component.update: screen
- to: page_c1
then:
- select.set:
id: page_selector
option: page_c1
- component.update: screen
- to: page_d1
then:
- select.set:
id: page_selector
option: page_d1
- component.update: screen
pages:
# ------------------------------------------------------------ qrcode page
- id: page_off
lambda: |-
// variables =========================================================
float screenwidth = it.get_width();
float screenheight = it.get_height();
float halfscreenwidth = screenwidth /2;
float halfscreenheight = screenheight / 2;
// background draws ==================================================
it.filled_rectangle(0, 0, screenwidth, screenheight, COLOR_ON);
// content ===========================================================
it.print(halfscreenwidth, 15, id(roboto_20_bold), blue_color, TextAlign::CENTER, "SSID:");
it.printf(halfscreenwidth, 35, id(roboto_20_bold), blue_color, TextAlign::CENTER, "${wifi_ssid}");
it.image(halfscreenwidth, halfscreenheight + 10, img_off, ImageAlign::CENTER);
# ----------------------------------------------------------- welcome page
- id: page_01
lambda: |-
// variables =========================================================
float screenheight = it.get_height();
float screenwidth = it.get_width();
float halfscreenheight = screenheight / 2;
float halfscreenwidth = screenwidth /2;
auto gate = id(gate_text).state;
auto garage = id(garage_text).state;
auto garage_door = id(garage_door_text).state;
auto mode = id(climate_mode_text).state;
auto current = id(climate_current_temperature).state;
auto target = id(climate_target_temperature).state;
// background draws ==================================================
it.filled_rectangle(0, 0, screenwidth, screenheight, pri_color);
it.line(0, halfscreenheight, screenwidth, halfscreenheight, off_color);
it.line(halfscreenwidth, 0, halfscreenwidth, screenheight, off_color);
// icons =============================================================
// alarm icon --------------------------------------------------------
if (id(alarm_text).state == "armed_away") {
it.image(65, 75, icon_shield_lock, ImageAlign::CENTER, nova_color);
} else if (id(alarm_text).state == "armed_night") {
it.image(65, 75, icon_shield_moon, ImageAlign::CENTER, nova_color);
} else if (id(alarm_text).state == "armed_home") {
it.image(65, 75, icon_shield_account, ImageAlign::CENTER, blue_color);
} else if (id(alarm_text).state == "arming") {
it.image(65, 75, icon_shield_sync, ImageAlign::CENTER, text_color);
} else if (id(alarm_text).state == "pending") {
it.image(65, 75, icon_shield_lock_open, ImageAlign::CENTER, yellow_color);
} else if (id(alarm_text).state == "triggered") {
it.image(65, 75, icon_shield_alert, ImageAlign::CENTER, red_color);
} else {
it.image(65, 75, icon_shield_off, ImageAlign::CENTER, off_color);
}
// openings icon -----------------------------------------------------
if (gate == "alert") {
it.image(175, 75, icon_gate_alert, ImageAlign::CENTER, red_color);
} else if (garage == "on" or garage_door == "on") {
it.image(175, 75, icon_garage_open, ImageAlign::CENTER, yellow_color);
} else if (gate == "open") {
it.image(175, 75, icon_gate_open, ImageAlign::CENTER, blue_color);
} else {
it.image(175, 75, icon_gate_closed, ImageAlign::CENTER, text_color);
}
// thermostat icon ---------------------------------------------------
if (mode == "auto") {
it.image(65, 165, icon_temperature_auto, ImageAlign::CENTER, green_color);
} else if (mode == "heat") {
if (current < target) {
it.image(65, 165, icon_temperature_heat, ImageAlign::CENTER, red_color);
} else {
it.image(65, 165, icon_temperature_cool, ImageAlign::CENTER, blue_color);
}
} else {
it.image(65, 165, icon_temperature_off, ImageAlign::CENTER, text_color);
}
// light icon --------------------------------------------------------
it.image(175, 165, icon_light_on, ImageAlign::CENTER, text_color);
// foreground draws ==================================================
it.filled_regular_polygon(halfscreenwidth, halfscreenheight -220, 144, EDGES_OCTAGON, VARIATION_FLAT_TOP, sec_color);
it.filled_regular_polygon(halfscreenwidth, halfscreenheight +220, 144, EDGES_OCTAGON, VARIATION_FLAT_TOP, sec_color);
it.regular_polygon(halfscreenwidth, halfscreenheight -220, 145, EDGES_OCTAGON, VARIATION_FLAT_TOP, off_color);
it.regular_polygon(halfscreenwidth, halfscreenheight +220, 145, EDGES_OCTAGON, VARIATION_FLAT_TOP, off_color);
// top text ==========================================================
it.strftime(halfscreenwidth, 20, id(roboto_16_bold), orange_color, TextAlign::CENTER, "%d/%m %X", id(rtc_time).now());
// bottom text =======================================================
it.print(halfscreenwidth, screenheight -20, id(roboto_16_bold), orange_color, TextAlign::CENTER, "\U000F0046 QRCODE");
# ----------------------------------------------------------- windows page
- id: page_02
lambda: |-
// variables =========================================================
float screenwidth = it.get_width();
float screenheight = it.get_height();
float halfscreenwidth = screenwidth /2;
float halfscreenheight = screenheight / 2;
// background draws ==================================================
it.filled_rectangle(0, 0, screenwidth, screenheight, pri_color);
// icons =============================================================
if (id(window_01_text).state == "off") {
it.image(60, 70, icon_bedroom_north_closed, ImageAlign::CENTER, text_color);
} else {
it.image(60, 70, icon_bedroom_north_open, ImageAlign::CENTER, blue_color);
}
if (id(window_02_text).state == "off") {
it.image(180, 70, icon_kitchen_closed, ImageAlign::CENTER, text_color);
} else {
it.image(180, 70, icon_kitchen_open, ImageAlign::CENTER, blue_color);
}
if (id(window_03_text).state == "off") {
it.image(halfscreenwidth, halfscreenheight, icon_velux, ImageAlign::CENTER, text_color);
} else {
it.image(halfscreenwidth, halfscreenheight, icon_velux, ImageAlign::CENTER, blue_color);
}
if (id(window_04_text).state == "off") {
it.image(60, 170, icon_bedroom_south_closed, ImageAlign::CENTER, text_color);
} else {
it.image(60, 170, icon_bedroom_south_open, ImageAlign::CENTER, blue_color);
}
if (id(window_05_text).state == "off") {
it.image(180, 170, icon_dining_closed, ImageAlign::CENTER, text_color);
} else {
it.image(180, 170, icon_dining_open, ImageAlign::CENTER, blue_color);
}
// foreground draws ==================================================
it.filled_regular_polygon(halfscreenwidth, halfscreenheight -220, 144, EDGES_OCTAGON, VARIATION_FLAT_TOP, sec_color);
it.filled_regular_polygon(halfscreenwidth, halfscreenheight +220, 144, EDGES_OCTAGON, VARIATION_FLAT_TOP, sec_color);
it.regular_polygon(halfscreenwidth, halfscreenheight -220, 145, EDGES_OCTAGON, VARIATION_FLAT_TOP, off_color);
it.regular_polygon(halfscreenwidth, halfscreenheight +220, 145, EDGES_OCTAGON, VARIATION_FLAT_TOP, off_color);
// top text ==========================================================
it.print(halfscreenwidth, 20, id(roboto_16_bold), orange_color, TextAlign::CENTER, "FENETRES");
// bottom text =======================================================
it.print(halfscreenwidth, screenheight -20, id(roboto_16_bold), orange_color, TextAlign::CENTER, "\U000F0046 RETOUR");
# ------------------------------------------------------------- alarm page
- id: page_a1
lambda: |-
// variables =========================================================
float screenheight = it.get_height();
float screenwidth = it.get_width();
float halfscreenheight = screenheight / 2;
float halfscreenwidth = screenwidth /2;
auto alarm = id(alarm_text).state;
// background draws ==================================================
it.filled_rectangle(0, 0, screenwidth, screenheight, pri_color);
// main icons ========================================================
if (alarm == "armed_home") {
it.image(60, 85, big_icon_shield_account, ImageAlign::CENTER, blue_color);
it.image(halfscreenwidth, 85, icon_arrow_left, ImageAlign::CENTER, text_color);
} else if (alarm == "armed_night") {
it.image(60, 85, big_icon_shield_moon, ImageAlign::CENTER, nova_color);
it.image(halfscreenwidth, 85, icon_arrow_left, ImageAlign::CENTER, text_color);
} else if (alarm == "disarmed") {
it.image(60, 85, big_icon_shield_off, ImageAlign::CENTER, off_color);
it.image(halfscreenwidth, 85, icon_arrow_left, ImageAlign::CENTER, text_color);
} else {
if (alarm == "armed_away") {
it.image(halfscreenwidth, 85, big_icon_shield_lock, ImageAlign::CENTER, nova_color);
} else if (alarm == "arming") {
it.image(halfscreenwidth, 85, big_icon_shield_sync, ImageAlign::CENTER, text_color);
} else if (alarm == "pending") {
it.image(halfscreenwidth, 85, big_icon_shield_lock_open, ImageAlign::CENTER, yellow_color);
} else if (alarm == "triggered") {
it.image(halfscreenwidth, 85, big_icon_shield_alert, ImageAlign::CENTER, red_color);
}
}
if (alarm == "armed_home") {
it.image(180, 85, big_icon_shield_moon, ImageAlign::CENTER, text_color);
} else if (alarm == "armed_night" or alarm == "disarmed") {
it.image(180, 85, big_icon_shield_account, ImageAlign::CENTER, text_color);
}
// main text =========================================================
if (alarm == "armed_home") {
it.print(halfscreenwidth, 140, id(roboto_24_regular), text_color, TextAlign::CENTER, "Armer mode nuit");
it.print(halfscreenwidth, 180, id(roboto_20_bold), blue_color, TextAlign::CENTER, "\U000F0741 CONFIRMER");
} else if (alarm == "armed_night" or alarm == "disarmed") {
it.print(halfscreenwidth, 140, id(roboto_24_regular), text_color, TextAlign::CENTER, "Armer mode presence");
it.print(halfscreenwidth, 180, id(roboto_20_bold), blue_color, TextAlign::CENTER, "\U000F0741 CONFIRMER");
} else {
it.print(halfscreenwidth, 140, id(roboto_24_regular), text_color, TextAlign::CENTER, "Etat actuel:");
if (alarm == "armed_away") {
it.print(halfscreenwidth, 180, id(roboto_20_bold), nova_color, TextAlign::CENTER, "ABSENTS");
} else if (alarm == "arming") {
it.print(halfscreenwidth, 180, id(roboto_20_bold), text_color, TextAlign::CENTER, "ARMEMENT");
} else if (alarm == "pending") {
it.print(halfscreenwidth, 180, id(roboto_20_bold), yellow_color, TextAlign::CENTER, "EN SUSPENS");
} else if (alarm == "triggered") {
it.print(halfscreenwidth, 180, id(roboto_20_bold), red_color, TextAlign::CENTER, "DECLENCHEE");
}
}
// foreground draws ==================================================
it.filled_regular_polygon(halfscreenwidth, halfscreenheight -220, 144, EDGES_OCTAGON, VARIATION_FLAT_TOP, sec_color);
it.filled_regular_polygon(halfscreenwidth, halfscreenheight +220, 144, EDGES_OCTAGON, VARIATION_FLAT_TOP, sec_color);
it.regular_polygon(halfscreenwidth, halfscreenheight -220, 145, EDGES_OCTAGON, VARIATION_FLAT_TOP, off_color);
it.regular_polygon(halfscreenwidth, halfscreenheight +220, 145, EDGES_OCTAGON, VARIATION_FLAT_TOP, off_color);
// top text ==========================================================
it.print(halfscreenwidth, 20, id(roboto_16_bold), orange_color, TextAlign::CENTER, "ALARME");
// bottom text =======================================================
if (alarm == "armed_home" or alarm == "armed_night" or alarm == "disarmed") {
it.print(halfscreenwidth, screenheight -20, id(roboto_16_bold), orange_color, TextAlign::CENTER, "\U000F0046 ANNULER");
} else {
it.print(halfscreenwidth, screenheight -20, id(roboto_16_bold), orange_color, TextAlign::CENTER, "\U000F0046 RETOUR");
}
# ---------------------------------------------------------- openings page
# ____________________________________________________ gate
- id: page_b1
lambda: |-
// variables =========================================================
float screenheight = it.get_height();
float screenwidth = it.get_width();
float halfscreenheight = screenheight / 2;
float halfscreenwidth = screenwidth /2;
auto gate = id(gate_text).state;
// background draws ==================================================
it.filled_rectangle(0, 0, screenwidth, screenheight, pri_color);
// main icons ========================================================
if (gate == "closed") {
it.image(60, 85, big_icon_gate_closed, ImageAlign::CENTER, text_color);
it.image(halfscreenwidth, 85, icon_arrow_left, ImageAlign::CENTER, text_color);
it.image(180, 85, big_icon_gate_open, ImageAlign::CENTER, yellow_color);
} else if (gate == "open") {
it.image(halfscreenwidth, 85, big_icon_gate_open, ImageAlign::CENTER, yellow_color);
} else {
it.image(halfscreenwidth, 85, big_icon_gate_alert, ImageAlign::CENTER, red_color);
}
// main text =========================================================
if (gate == "closed") {
it.print(halfscreenwidth, 140, id(roboto_24_regular), text_color, TextAlign::CENTER, "Ouvrir le portail?");
} else if (gate == "open") {
it.print(halfscreenwidth, 140, id(roboto_24_regular), text_color, TextAlign::CENTER, "Portail ouvert");
} else {
it.print(halfscreenwidth, 140, id(roboto_24_regular), text_color, TextAlign::CENTER, "Portail a controler!");
}
// + tap text --------------------------------------------------------
if (gate == "closed") {
it.print(halfscreenwidth, 180, id(roboto_20_bold), blue_color, TextAlign::CENTER, "\U000F0741 CONFIRMER");
}
// foreground draws ==================================================
it.filled_regular_polygon(halfscreenwidth, halfscreenheight -220, 144, EDGES_OCTAGON, VARIATION_FLAT_TOP, sec_color);
it.filled_regular_polygon(halfscreenwidth, halfscreenheight +220, 144, EDGES_OCTAGON, VARIATION_FLAT_TOP, sec_color);
it.regular_polygon(halfscreenwidth, halfscreenheight -220, 145, EDGES_OCTAGON, VARIATION_FLAT_TOP, off_color);
it.regular_polygon(halfscreenwidth, halfscreenheight +220, 145, EDGES_OCTAGON, VARIATION_FLAT_TOP, off_color);
// top text ==========================================================
it.print(halfscreenwidth, 20, id(roboto_16_bold), orange_color, TextAlign::CENTER, "\U000F1999 CHOIX");
// bottom text =======================================================
if (gate == "closed") {
it.print(halfscreenwidth, screenheight -20, id(roboto_16_bold), orange_color, TextAlign::CENTER, "\U000F0046 ANNULER");
} else {
it.print(halfscreenwidth, screenheight -20, id(roboto_16_bold), orange_color, TextAlign::CENTER, "\U000F0046 RETOUR");
}
# ____________________________________________________ garage
- id: page_b2
lambda: |-
// variables =========================================================
float screenheight = it.get_height();
float screenwidth = it.get_width();
float halfscreenheight = screenheight / 2;
float halfscreenwidth = screenwidth /2;
auto garage = id(garage_text).state;
auto garage_door = id(garage_door_text).state;
// background draws ==================================================
it.filled_rectangle(0, 0, screenwidth, screenheight, pri_color);
// main icons ========================================================
if (garage == "off") {
if (garage_door == "on") {
it.image(halfscreenwidth, 85, big_icon_door_open, ImageAlign::CENTER, yellow_color);
} else {
it.image(60, 85, big_icon_garage_closed, ImageAlign::CENTER, text_color);
it.image(halfscreenwidth, 85, icon_arrow_left, ImageAlign::CENTER, text_color);
it.image(180, 85, big_icon_garage_open, ImageAlign::CENTER, yellow_color);
}
} else {
it.image(60, 85, big_icon_garage_open, ImageAlign::CENTER, yellow_color);
it.image(halfscreenwidth, 85, icon_arrow_left, ImageAlign::CENTER, text_color);
it.image(180, 85, big_icon_garage_closed, ImageAlign::CENTER, text_color);
}
// main text =========================================================
if (garage == "off") {
if (garage_door == "on") {
it.print(halfscreenwidth, 140, id(roboto_24_regular), text_color, TextAlign::CENTER, "Garage ouvert!");
} else {
it.print(halfscreenwidth, 140, id(roboto_24_regular), text_color, TextAlign::CENTER, "Ouvrir le garage?");
}
} else {
it.print(halfscreenwidth, 140, id(roboto_24_regular), text_color, TextAlign::CENTER, "Fermer le garage?");
}
// + tap text --------------------------------------------------------
it.print(halfscreenwidth, 180, id(roboto_20_bold), blue_color, TextAlign::CENTER, "\U000F0741 CONFIRMER");
// foreground draws ==================================================
it.filled_regular_polygon(halfscreenwidth, halfscreenheight -220, 144, EDGES_OCTAGON, VARIATION_FLAT_TOP, sec_color);
it.filled_regular_polygon(halfscreenwidth, halfscreenheight +220, 144, EDGES_OCTAGON, VARIATION_FLAT_TOP, sec_color);
it.regular_polygon(halfscreenwidth, halfscreenheight -220, 145, EDGES_OCTAGON, VARIATION_FLAT_TOP, off_color);
it.regular_polygon(halfscreenwidth, halfscreenheight +220, 145, EDGES_OCTAGON, VARIATION_FLAT_TOP, off_color);
// top text ==========================================================
it.print(halfscreenwidth, 20, id(roboto_16_bold), orange_color, TextAlign::CENTER, "\U000F1999 CHOIX");
// bottom text =======================================================
if (garage == "off") {
it.print(halfscreenwidth, screenheight -20, id(roboto_16_bold), orange_color, TextAlign::CENTER, "\U000F0046 ANNULER");
} else {
it.print(halfscreenwidth, screenheight -20, id(roboto_16_bold), orange_color, TextAlign::CENTER, "\U000F0046 RETOUR");
}
# ------------------------------------------------------- temperature page
- id: page_c1
lambda: |-
// variables =========================================================
float screenheight = it.get_height();
float screenwidth = it.get_width();
float halfscreenheight = screenheight / 2;
float halfscreenwidth = screenwidth /2;
auto mode = id(climate_mode_text).state;
auto current = id(climate_current_temperature).state;
auto target = id(new_target_temperature).state;
// background draws ==================================================
it.filled_rectangle(0, 0, screenwidth, screenheight, pri_color);
// foreground draws ==================================================
it.filled_regular_polygon(halfscreenwidth, halfscreenheight -220, 144, EDGES_OCTAGON, VARIATION_FLAT_TOP, sec_color);
it.filled_regular_polygon(halfscreenwidth, halfscreenheight +220, 144, EDGES_OCTAGON, VARIATION_FLAT_TOP, sec_color);
it.regular_polygon(halfscreenwidth, halfscreenheight -220, 145, EDGES_OCTAGON, VARIATION_FLAT_TOP, off_color);
it.regular_polygon(halfscreenwidth, halfscreenheight +220, 145, EDGES_OCTAGON, VARIATION_FLAT_TOP, off_color);
// top text ==========================================================
if (mode == "auto") {
it.print(halfscreenwidth, 20, id(roboto_16_bold), orange_color, TextAlign::CENTER, "THERMOSTAT");
} else {
it.print(halfscreenwidth, 20, id(roboto_16_bold), orange_color, TextAlign::CENTER, "\U000F1999 CONSIGNE");
}
// main icon =========================================================
if (mode == "auto") {
it.image(75, 85, big_icon_temperature_auto, ImageAlign::CENTER, green_color);
} else if (mode == "heat") {
if (current < target) {
it.image(75, 85, big_icon_temperature_heat, ImageAlign::CENTER, red_color);
} else {
it.image(75, 85, big_icon_temperature_cool, ImageAlign::CENTER, blue_color);
}
} else {
it.image(75, 85, big_icon_temperature_off, ImageAlign::CENTER, off_color);
}
it.print(165, 85, id(roboto_20_regular), orange_color, TextAlign::CENTER, "\U000F0741 MODE");
// main text =========================================================
if (mode == "auto") {
it.printf(halfscreenwidth, 140, id(roboto_24_regular), text_color, TextAlign::CENTER, "Consigne: %2.1f°C", target);
} else if (mode == "heat") {
it.printf(halfscreenwidth, 140, id(roboto_24_regular), text_color, TextAlign::CENTER, "Consigne: %2.1f°C", target);
} else {
it.printf(halfscreenwidth, 140, id(roboto_24_regular), text_color, TextAlign::CENTER, "Consigne: %2.1f°C", target);
}
it.printf(halfscreenwidth, 180, id(roboto_20_bold), blue_color, TextAlign::CENTER, "Sonde: %2.1f°C", current);
// bottom text =======================================================
it.print(halfscreenwidth, screenheight -20, id(roboto_16_bold), orange_color, TextAlign::CENTER, "\U000F0046 RETOUR");
# ------------------------------------------------------------ lights page
- id: page_d1
lambda: |-
// variables =========================================================
float screenheight = it.get_height();
float screenwidth = it.get_width();
float halfscreenheight = screenheight / 2;
float halfscreenwidth = screenwidth /2;
auto cour = id(light_01_text).state;
// background draws ==================================================
it.filled_rectangle(0, 0, screenwidth, screenheight, pri_color);
// main icons ========================================================
if (cour == "on") {
it.image(60, 85, big_icon_light_on, ImageAlign::CENTER, yellow_color);
it.image(halfscreenwidth, 85, icon_arrow_left, ImageAlign::CENTER, text_color);
it.image(180, 85, big_icon_light_off, ImageAlign::CENTER, text_color);
} else {
it.image(60, 85, big_icon_light_off, ImageAlign::CENTER, text_color);
it.image(halfscreenwidth, 85, icon_arrow_left, ImageAlign::CENTER, text_color);
it.image(180, 85, big_icon_light_on, ImageAlign::CENTER, yellow_color);
}
// main text =========================================================
if (cour == "on") {
it.print(halfscreenwidth, 140, id(roboto_24_regular), text_color, TextAlign::CENTER, "Eteindre la cour?");
} else {
it.print(halfscreenwidth, 140, id(roboto_24_regular), text_color, TextAlign::CENTER, "Allumer la cour?");
}
// + tap text --------------------------------------------------------
it.print(halfscreenwidth, 180, id(roboto_20_bold), blue_color, TextAlign::CENTER, "\U000F0741 CONFIRMER");
// foreground draws ==================================================
it.filled_regular_polygon(halfscreenwidth, halfscreenheight -220, 144, EDGES_OCTAGON, VARIATION_FLAT_TOP, sec_color);
it.filled_regular_polygon(halfscreenwidth, halfscreenheight +220, 144, EDGES_OCTAGON, VARIATION_FLAT_TOP, sec_color);
it.regular_polygon(halfscreenwidth, halfscreenheight -220, 145, EDGES_OCTAGON, VARIATION_FLAT_TOP, off_color);
it.regular_polygon(halfscreenwidth, halfscreenheight +220, 145, EDGES_OCTAGON, VARIATION_FLAT_TOP, off_color);
// top text ==========================================================
it.print(halfscreenwidth, 20, id(roboto_16_bold), orange_color, TextAlign::CENTER, "\U000F1999 CHOIX");
// bottom text =======================================================
it.print(halfscreenwidth, screenheight -20, id(roboto_16_bold), orange_color, TextAlign::CENTER, "\U000F0046 RETOUR");
# ======================================================================================
# ======================================================================================
# ============================================================================== sensors
sensor:
# -------------------------------------------------------------------- climate
- platform: homeassistant
id: climate_target_temperature
entity_id: $climate_id
attribute: temperature
on_value:
- lambda: |-
id(new_target_temperature).publish_state(x);
- logger.log: "nouvelle valeur : TEST new target temperature"
- platform: homeassistant
id: climate_current_temperature
entity_id: $climate_id
attribute: current_temperature
- platform: template
id: new_target_temperature
name: Target Temperature
icon: mdi:thermometer-lines
# ----------------------------------------------------------------- lux sensor
- platform: homeassistant
entity_id: $lux_sensor_id
name: "Lux Sensor"
id: sensor_lux
accuracy_decimals: 0
on_value:
- logger.log:
format: "$lux_sensor_id: %.0f"
args: [ 'id(sensor_lux).state' ]
- if:
condition:
- light.is_on: backlight
then:
- lambda: |-
float lux = id(sensor_lux).state;
if (lux < 10) {
id(lcdbacklight).set_level(0.1);
}
else if (lux < 40) {
id(lcdbacklight).set_level(0.3);
}
else if (lux < 80) {
id(lcdbacklight).set_level(0.5);
}
else {
id(lcdbacklight).set_level(0.7);
}
# ------------------------------------------------------------- rotary encoder
- platform: rotary_encoder
name: Rotary Encoder
id: rotaryencoder
resolution: 1
pin_a:
number: GPIO40
mode:
input: true
pullup: true
pin_b:
number: GPIO41
mode:
input: true
pullup: true
accuracy_decimals: 0
# accuracy_decimals: 1
on_clockwise:
- logger.log: "rotary_encoder : _____________________ turned_clockwise"
- if:
<<: &select_off
condition:
- lambda: 'return id(page_selector).state == "page_off";'
then:
- select.set:
id: page_selector
option: page_01
- component.update: screen
else:
# ____________________________________________ 0 pages
- if:
<<: &01_02
condition:
- lambda: 'return id(page_selector).state == "page_01";'
then:
- select.set:
id: page_selector
option: page_02
- component.update: screen
else:
- if:
<<: &02_01
condition:
- lambda: 'return id(page_selector).state == "page_02";'
then:
- select.set:
id: page_selector
option: page_01
- component.update: screen
# ____________________________________________ B pages
- if:
<<: &b1_b2
condition:
- lambda: 'return id(page_selector).state == "page_b1";'
then:
- select.set:
id: page_selector
option: page_b2
- component.update: screen
else:
- if:
<<: &b2_b1
condition:
- lambda: 'return id(page_selector).state == "page_b2";'
then:
- select.set:
id: page_selector
option: page_b1
- component.update: screen
# ____________________________________________ c pages
- if:
condition:
- lambda: 'return id(page_selector).state == "page_c1";'
then:
- lambda: |-
return id(new_target_temperature).publish_state(id(new_target_temperature).state + 0.5);
on_anticlockwise:
- logger.log: "rotary_encoder : _____________________ turned_ANTIclockwise"
- if:
<<: *select_off
else:
# ____________________________________________ 0 pages
- if:
<<: *01_02
else:
- if:
<<: *02_01
else:
# ____________________________________________ B pages
- if:
<<: *b1_b2
else:
- if:
<<: *b2_b1
else:
# ____________________________________________ c pages
- if:
condition:
- lambda: 'return id(page_selector).state == "page_c1";'
then:
- lambda: |-
return id(new_target_temperature).publish_state(id(new_target_temperature).state - 0.5);
# id(new_target_temperature).publish_state(id(climate_target_temperature).state - 0.5);
# ======================================================================================
# ======================================================================================
# ======================================================================= binary sensors
binary_sensor:
# --------------------------------------------------------------------- button
- platform: gpio
pin:
number: GPIO42
inverted: true
name: M5 Button
on_press:
- logger.log: "button_pushed _____________________ button_pushed"
- if:
condition:
- lambda: 'return id(page_selector).state == "page_01";'
then:
- select.set:
id: page_selector
option: page_off
else:
- select.set:
id: page_selector
option: page_01
- component.update: screen
# ================================================================= touch inputs
# -------------------------------------------------------------- welcome
- platform: touchscreen
id: touch_01_tl
internal: true
x_min: 0
x_max: 118
y_min: 0
y_max: 118
page_id: page_01
on_release:
- logger.log: "touch_input OVER page_01 : _____________________ top_left"
- if:
condition:
- light.is_on: backlight
then:
- display.page.show: page_a1
- component.update: screen
- platform: touchscreen
id: touch_01_tr
internal: true
x_min: 122
x_max: 240
y_min: 0
y_max: 118
page_id: page_01
on_release:
- logger.log: "touch_input OVER page_01 : _____________________ top_right"
- if:
condition:
- light.is_on: backlight
then:
- lambda: |-
// function ====================================================
auto call = id(page_selector).make_call();
// conditions ==================================================
if (id(garage_text).state == "on") {
call.set_option("page_b2");
} else {
call.set_option("page_b1");
}
// function call ===============================================
call.perform();
- component.update: screen
- platform: touchscreen
id: touch_01_bl
internal: true
x_min: 0
x_max: 118
y_min: 122
y_max: 240
page_id: page_01
on_release:
- logger.log: "touch_input OVER page_01 : _____________________ bottom_left"
- if:
condition:
- light.is_on: backlight
then:
- display.page.show: page_c1
- component.update: screen
- platform: touchscreen
id: touch_01_br
internal: true
x_min: 122
x_max: 240
y_min: 122
y_max: 240
page_id: page_01
on_release:
- logger.log: "touch_input OVER page_01 : _____________________ bottom_right"
- if:
condition:
- light.is_on: backlight
then:
- display.page.show: page_d1
- component.update: screen
# -------------------------------------------------------------- A pages
- platform: touchscreen
id: touch_a1
page_id: page_a1
<<: &touch_full
internal: true
x_min: 0
x_max: 240
y_min: 0
y_max: 240
on_press:
- if:
condition:
- light.is_on: backlight
then:
- if:
condition:
or:
- lambda: 'return id(alarm_text).state == "disarmed";'
then:
- <<: &bip
rtttl.play: 'one_short:d=32,o=4,b=900:a'
- homeassistant.service:
service: input_button.press
data_template:
entity_id: input_button.alarm_arm_home
- if:
condition:
- lambda: 'return id(alarm_text).state == "armed_home";'
then:
- <<: *bip
- homeassistant.service:
service: input_button.press
data_template:
entity_id: input_button.alarm_arm_night
- if:
condition:
or:
- lambda: 'return id(alarm_text).state == "disarmed";'
- lambda: 'return id(alarm_text).state == "armed_night";'
then:
- <<: *bip
# TEST #############################################################
- homeassistant.service:
service: input_boolean.toggle
data_template:
entity_id: input_boolean.test
# TEST #############################################################
# -------------------------------------------------------------- B pages
- platform: touchscreen
id: touch_b1
page_id: page_b1
<<: *touch_full
on_press:
- if:
condition:
- light.is_on: backlight
then:
- <<: *bip
- homeassistant.service:
service: lock.unlock
data_template:
entity_id: lock.gate
- platform: touchscreen
id: touch_b2
page_id: page_b2
<<: *touch_full
on_press:
- if:
condition:
- light.is_on: backlight
then:
- <<: *bip
# TEST #############################################################
- homeassistant.service:
service: input_boolean.toggle
data_template:
entity_id: input_boolean.test
# TEST #############################################################
# -------------------------------------------------------------- C pages
- platform: touchscreen
id: touch_c1
page_id: page_c1
<<: *touch_full
on_press:
- if:
condition:
- light.is_on: backlight
then:
- if:
condition:
- lambda: 'return id(climate_mode_text).state == "off";'
then:
- <<: *bip
- homeassistant.service:
service: climate.set_hvac_mode
data_template:
entity_id: climate.heatpump_sdgs_ebusd
hvac_mode: heat
- if:
condition:
or:
- lambda: 'return id(climate_mode_text).state == "heat";'
then:
- <<: *bip
- homeassistant.service:
service: climate.set_hvac_mode
data_template:
entity_id: climate.heatpump_sdgs_ebusd
hvac_mode: auto
- if:
condition:
or:
- lambda: 'return id(climate_mode_text).state == "auto";'
then:
- <<: *bip
- homeassistant.service:
service: climate.set_hvac_mode
data_template:
entity_id: climate.heatpump_sdgs_ebusd
hvac_mode: "off"
# -------------------------------------------------------------- D pages
- platform: touchscreen
id: touch_d1
page_id: page_d1
<<: *touch_full
on_press:
- if:
condition:
- light.is_on: backlight
then:
- <<: *bip
- homeassistant.service:
service: light.toggle
data_template:
entity_id: light.shelly_one_cour