New Update
Update 2024-11-26 (date written in ISO 8601 standard)
I wanted to use Header and Footer, but I did not find any way to do it. It does not mean that there is no way.
My way is to use partial update, virtual switch and “If state”
Template switch named “Winter Mode”
if (id(winter_mode).state) in Display lambda
New Code:
substitutions:
friendly_name: Inkplate Hallway
devicename: inkplate_hallway
update_slow: 600s # WiFi, Uptime,
update_fast: 30s # Screen, update
update_full: '360' # '360'
esphome:
name: ${devicename}
friendly_name: $friendly_name
esp32:
board: esp-wrover-kit
framework:
type: arduino
logger:
level: DEBUG
logs:
component: ERROR
api:
encryption:
key: !secret inkplate_api_key
ota:
- platform: esphome
password: !secret inkplate_ota_password
wifi:
ssid: !secret wifi_iot_ssid
password: !secret wifi_iot_password
power_save_mode: none
ap:
ssid: $friendly_name Hotspot
password: !secret fallback_ap_password
captive_portal:
web_server:
port: 80
auth:
username: !secret admin_user
password: !secret fallback_ap_password
mdns:
disabled: false
packages:
switch: !include include/switch_reboot.yaml
sensor: !include include/sensor_wifi_uptime.yaml
text_sensor: !include include/text_sensor_wifi_uptime.yaml
binary_sensor: !include include/binary_sensor_status.yaml
time:
- platform: sntp
id: esptime
on_time:
- seconds: 0
minutes: /1
then:
- component.update: ${devicename}_display
i2c:
mcp23017:
- id: mcp23017_hub
address: 0x20
globals:
- id: winter_bool
type: bool
restore_value: true
initial_value: 'true'
binary_sensor:
- platform: gpio
name: "Garage 1 Door Button"
pin:
number: GPIO12 # WARNING GPIO12 is a strapping PIN and should only be used for I/O with care.
mode: INPUT_PULLUP
inverted: true
internal: true
on_click:
- min_length: 2ms
max_length: 2500ms
then:
- homeassistant.service:
service: cover.open_cover
data:
entity_id: cover.garage_1_uni_door
- min_length: 3000ms
max_length: 15000ms
then:
- homeassistant.service:
service: lock.lock
data:
entity_id: lock.backdoor
- platform: gpio
name: "Garage 2 Door Button"
pin:
number: GPIO13
mode: INPUT_PULLUP
inverted: true
internal: true
on_click:
- min_length: 2ms
max_length: 2500ms
then:
- homeassistant.service:
service: cover.open_cover
data:
entity_id: cover.garage_2_uni_door
- min_length: 3000ms
max_length: 15000ms
then:
- homeassistant.service:
service: lock.lock
data:
entity_id: lock.frontdoor
switch:
# Virtual switch based on a global variable.
- platform: template
name: "Winter Mode"
icon: mdi:snowflake
id: winter_mode
restore_mode: RESTORE_DEFAULT_ON
turn_on_action:
- globals.set:
id: winter_bool
value: 'true'
- component.update: ${devicename}_display
turn_off_action:
- globals.set:
id: winter_bool
value: 'false'
- component.update: ${devicename}_display
lambda: |-
return id(winter_bool);
- platform: shutdown
name: "Shutdown"
id: powerdown
text_sensor:
- platform: homeassistant
id: garage_1_state
name: "Garage 1 State"
entity_id: sensor.garage_1_cover_state
internal: true
on_value:
then:
- component.update: ${devicename}_display
- platform: homeassistant
id: garage_2_state
name: "Garage 2 State"
entity_id: sensor.garage_2_cover_state
internal: true
on_value:
then:
- component.update: ${devicename}_display
- platform: homeassistant
id: lock_frontdoor
name: "Frontdoor"
entity_id: lock.frontdoor
internal: true
on_value:
then:
- component.update: ${devicename}_display
- platform: homeassistant
id: lock_backdoor
name: "Backdoor"
entity_id: lock.backdoor
internal: true
on_value:
then:
- component.update: ${devicename}_display
- platform: homeassistant
id: lock_garage_back
name: "Garage Back"
entity_id: lock.garage_back
internal: true
on_value:
then:
- component.update: ${devicename}_display
- platform: homeassistant
id: current_weather
entity_id: sensor.current_weather
on_value:
then:
- component.update: ${devicename}_display
sensor:
- platform: homeassistant
id: porch_temp
name: "Porch Temperature"
entity_id: sensor.motion_porch_temperature
on_value:
then:
- component.update: ${devicename}_display
- platform: homeassistant
id: indoor_temp
name: "Smoke Detector Hallway: Air temperature"
entity_id: sensor.smoke_detector_hallway_air_temperature
on_value:
then:
- component.update: ${devicename}_display
- platform: homeassistant
id: sauna_temp
name: "Sauna Temperature"
entity_id: sensor.sauna_temperature
on_value:
then:
- component.update: ${devicename}_display
- platform: homeassistant
id: greenhouse_temp
name: "Greenhouse Temperature"
entity_id: sensor.weather_greenhouse_temperature
on_value:
then:
- component.update: ${devicename}_display
- platform: homeassistant
id: greenhouse_hum
name: "Greenhouse Humidity"
entity_id: sensor.weather_greenhouse_humidity
on_value:
then:
- component.update: ${devicename}_display
- platform: homeassistant
id: garage1_temperature
name: "Garage 1 Temperature"
entity_id: sensor.garage_1_uni_temperature
on_value:
then:
- component.update: ${devicename}_display
- platform: homeassistant
id: garage2_temperature
name: "Garage 2 Temperature"
entity_id: sensor.garage_2_uni_temperature
on_value:
then:
- component.update: ${devicename}_display
font:
- file: "0_fonts/Helvetica.ttf"
id: helvetica_96
size: 96
- file: "0_fonts/Helvetica.ttf"
id: helvetica_85
size: 85
- file: "0_fonts/Helvetica.ttf"
id: helvetica_48
size: 48
- file: "0_fonts/Helvetica.ttf"
id: helvetica_36
size: 36
- file: "0_fonts/Helvetica.ttf"
id: helvetica_25
size: 25
image:
- file: "images/00-indoor.png"
id: indoor
type: BINARY
- file: "images/00-outdoor.png"
id: outdoor
type: BINARY
- file: "images/00-garage1.png"
id: garage1_img
type: BINARY
- file: "images/00-garage2.png"
id: garage2_img
type: BINARY
- file: "images/00-garage_closed.png"
id: garage_closed_img
type: BINARY
- file: "images/00-garage_down.png"
id: garage_down_img
type: BINARY
- file: "images/00-garage_up.png"
id: garage_up_img
type: BINARY
- file: "images/00-garage_half.png"
id: garage_half_img
type: BINARY
- file: "images/00-garage_arrow.png"
id: garage_arrow_img
type: BINARY
- file: "images/00-garage_loading.png"
id: garage_loading_img
type: BINARY
- file: "images/00-garage_error.png"
id: garage_error_img
type: BINARY
- file: "images/00-greenhouse.png"
id: greenhouse
type: BINARY
- file: "images/00-sauna.png"
id: sauna
type: BINARY
- file: "images/00-lock.png"
id: lock
type: BINARY
# Weather icons
- file: "images/0-default.png"
id: wpng_default
type: BINARY
- file: "images/1-clear-night.png"
id: wpng_clear_night
type: BINARY
- file: "images/2-cloudy.png"
id: wpng_cloudy
type: BINARY
- file: "images/3-fog.png"
id: wpng_fog
type: BINARY
- file: "images/4-hail.png"
id: wpng_hail
type: BINARY
- file: "images/5-lightning.png"
id: wpng_lightning
type: BINARY
- file: "images/7-partlycloudy.png"
id: wpng_partlycloudy
type: BINARY
- file: "images/8-pouring.png"
id: wpng_pouring
type: BINARY
- file: "images/9-rainy.png"
id: wpng_rainy
type: BINARY
- file: "images/10-snowy.png"
id: wpng_snowy
type: BINARY
- file: "images/11-snowy-rainy.png"
id: wpng_snowy_rainy
type: BINARY
- file: "images/12-sunny.png"
id: wpng_sunny
type: BINARY
- file: "images/13-windy.png"
id: wpng_windy
type: BINARY
- file: "images/14-windy-variant.png"
id: wpng_windy_variant
type: BINARY
- file: "images/15-exceptional.png"
id: wpng_exceptional
type: BINARY
display:
# Resolution 800 (x) x 600 (y)
- platform: inkplate6
id: ${devicename}_display
greyscale: false
partial_updating: true
update_interval: $update_fast
full_update_every: $update_full # When partial updating is enabled, forces a full screen update after chosen number of updates
model: inkplate_6
ckv_pin: 32
sph_pin: 33
gmod_pin:
mcp23xxx: mcp23017_hub
number: 1
gpio0_enable_pin:
mcp23xxx: mcp23017_hub
number: 8
oe_pin:
mcp23xxx: mcp23017_hub
number: 0 # Inkplate config pin , but results WARNING GPIO0 is a strapping PIN and should only be used for I/O with care.
spv_pin:
mcp23xxx: mcp23017_hub
number: 2 # Inkplate config pin , but results WARNING GPIO2 is a strapping PIN and should only be used for I/O with care.
powerup_pin:
mcp23xxx: mcp23017_hub
number: 4
wakeup_pin:
mcp23xxx: mcp23017_hub
number: 3
vcom_pin:
mcp23xxx: mcp23017_hub
number: 5 # Inkplate config pin , but results WARNING GPIO5 is a strapping PIN and should only be used for I/O with care.
lambda: |-
it.fill(COLOR_ON);
// -- Header --\\
it.strftime(150, 45, id(helvetica_48), COLOR_OFF, TextAlign::CENTER, "%A", id(esptime).now());
if (id(porch_temp).has_state()) {
it.printf(230, 120, id(helvetica_96), COLOR_OFF, TextAlign::CENTER_RIGHT, "%.1f", id(porch_temp).state);
it.printf(230, 95, id(helvetica_36), COLOR_OFF, TextAlign::CENTER_LEFT, "°C", id(porch_temp).state);
}
it.strftime(650, 45, id(helvetica_48), COLOR_OFF, TextAlign::CENTER, "%Y-%m-%d", id(esptime).now());
it.strftime(650, 120, id(helvetica_96), COLOR_OFF, TextAlign::CENTER, "%H:%M", id(esptime).now());
// Weather
if (id(current_weather).state == "clear-night") {
it.image(336, 25, id(wpng_clear_night));
} else if (id(current_weather).state == "cloudy") {
it.image(336, 25, id(wpng_cloudy));
} else if (id(current_weather).state == "fog") {
it.image(336, 25, id(wpng_fog));
} else if (id(current_weather).state == "hail") {
it.image(336, 25, id(wpng_hail));
} else if (id(current_weather).state == "lightning") {
it.image(336, 25, id(wpng_lightning));
} else if (id(current_weather).state == "lightning-rainy") {
it.image(336, 25, id(wpng_lightning));
} else if (id(current_weather).state == "partlycloudy") {
it.image(336, 25, id(wpng_partlycloudy));
} else if (id(current_weather).state == "pouring") {
it.image(336, 25, id(wpng_pouring));
} else if (id(current_weather).state == "rainy") {
it.image(336, 25, id(wpng_rainy));
} else if (id(current_weather).state == "snowy") {
it.image(336, 25, id(wpng_snowy));
} else if (id(current_weather).state == "snowy-rainy'") {
it.image(336, 25, id(wpng_snowy_rainy));
} else if (id(current_weather).state == "sunny") {
it.image(336, 25, id(wpng_sunny));
} else if (id(current_weather).state == "windy") {
it.image(336, 25, id(wpng_windy));
} else if (id(current_weather).state == "windy-variant") {
it.image(336, 25, id(wpng_windy_variant));
} else if (id(current_weather).state == "exceptional") {
it.image(336, 25, id(wpng_exceptional));
} else {
it.image(336, 25, id(wpng_default));
}
// Line x=10, y=180 to x=590, y=180
it.line(10, 180, 790, 180, COLOR_OFF);
// Temperature
if (id(indoor_temp).has_state()) {
it.image(30, 200, id(indoor));
it.printf(350, 240, id(helvetica_85), COLOR_OFF, TextAlign::TOP_RIGHT, "%.1f", id(indoor_temp).state);
it.printf(350, 240, id(helvetica_36), COLOR_OFF, TextAlign::TOP_LEFT, "°C", id(indoor_temp).state);
}
if (id(sauna_temp).has_state()) {
it.image(410, 200, id(sauna));
it.printf(730, 240, id(helvetica_85), COLOR_OFF, TextAlign::TOP_RIGHT, "%.1f", id(sauna_temp).state);
it.printf(730, 240, id(helvetica_36), COLOR_OFF, TextAlign::TOP_LEFT, "°C", id(sauna_temp).state);
}
// -- Footer --\\
// Status
if (id(system_status).state) {
it.print(780, 550, id(helvetica_36), COLOR_ON, TextAlign::TOP_RIGHT, "Offline");
} else {
it.print(780, 550, id(helvetica_36), COLOR_OFF, TextAlign::TOP_RIGHT, "Offline");
}
// Door Locks
if (id(lock_backdoor).state == "unlocked") {
it.image(40, 480, id(lock));
}
if (id(lock_garage_back).state == "unlocked") {
it.image(336, 480, id(lock));
}
if (id(lock_frontdoor).state == "unlocked") {
it.image(632, 480, id(lock));
}
// -- Footer end --\\
if (id(winter_mode).state) {
// -- Winter -- \\
if (id(garage_1_state).state == "Fully Closed") {
it.printf(25, 520, id(helvetica_25), COLOR_ON, TextAlign::TOP_LEFT, "Garage 1");
it.image(30, 350, id(garage_closed_img));
} else if (id(garage_1_state).state == "Fully Open"){
it.image(30, 350, id(garage1_img));
it.image(185, 480, id(garage_arrow_img));
} else if (id(garage_1_state).state == "Partially Open") {
it.image(30, 350, id(garage_half_img));
} else if (id(garage_1_state).state == "Door is Closing") {
it.image(30, 350, id(garage_down_img));
} else if (id(garage_1_state).state == "Door is Opening") {
it.image(30, 350, id(garage_up_img));
} else if (id(garage_1_state).state == "Loading") {
it.image(410, 350, id(garage_loading_img));
} else {
it.image(185, 480, id(garage_error_img));
}
if (id(garage1_temperature).has_state()) {
it.printf(350, 390, id(helvetica_85), COLOR_OFF, TextAlign::TOP_RIGHT, "%.1f", id(garage1_temperature).state);
it.printf(350, 390, id(helvetica_36), COLOR_OFF, TextAlign::TOP_LEFT, "°C", id(garage1_temperature).state);
}
if (id(garage_2_state).state == "Fully Closed") {
it.printf(25, 550, id(helvetica_25), COLOR_ON, TextAlign::TOP_LEFT, "Garage 1");
it.image(410, 350, id(garage_closed_img));
} else if (id(garage_2_state).state == "Fully Open"){
it.image(410, 350, id(garage2_img));
it.image(485, 480, id(garage_arrow_img));
} else if (id(garage_2_state).state == "Partially Open"){
it.image(410, 350, id(garage_half_img));
} else if (id(garage_2_state).state == "Door is Closing"){
it.image(410, 350, id(garage_down_img));
} else if (id(garage_2_state).state == "Door is Opening"){
it.image(410, 350, id(garage_up_img));
} else if (id(garage_2_state).state == "Loading"){
it.image(410, 350, id(garage_loading_img));
} else {
it.image(185, 480, id(garage_error_img));
}
if (id(garage2_temperature).has_state()) {
it.printf(730, 390, id(helvetica_85), COLOR_OFF, TextAlign::TOP_RIGHT, "%.1f", id(garage2_temperature).state);
it.printf(730, 390, id(helvetica_36), COLOR_OFF, TextAlign::TOP_LEFT, "°C", id(garage2_temperature).state);
}
// -- Winter end -- \\
} else {
// -- Summer -- \\
if (id(greenhouse_temp).has_state()) {
it.image(30, 350, id(greenhouse));
it.printf(350, 390, id(helvetica_85), COLOR_OFF, TextAlign::TOP_RIGHT, "%.1f", id(greenhouse_temp).state);
it.printf(350, 390, id(helvetica_36), COLOR_OFF, TextAlign::TOP_LEFT, "°C", id(greenhouse_temp).state);
it.printf(600, 380, id(helvetica_48), COLOR_OFF, TextAlign::TOP_RIGHT, "%.1f%%", id(greenhouse_hum).state);
// it.printf(600, 430, id(helvetica_48), COLOR_OFF, TextAlign::TOP_RIGHT, "%.1f%%", id(greenhouse_hum).state);
}
// Garage 1
if (id(garage_1_state).state == "Fully Closed") {
it.printf(25, 520, id(helvetica_25), COLOR_ON, TextAlign::TOP_LEFT, "Garage 1");
} else if (id(garage_1_state).state == "Fully Open"){
it.image(185, 480, id(garage1_img));
} else if (id(garage_1_state).state == "Partially Open") {
it.image(185, 480, id(garage_half_img));
} else if (id(garage_1_state).state == "Door is Closing") {
it.image(185, 480, id(garage_down_img));
} else if (id(garage_1_state).state == "Door is Opening") {
it.image(185, 480, id(garage_up_img));
} else if (id(garage_1_state).state == "Loading") {
it.image(185, 480, id(garage_loading_img));
} else {
it.image(185, 480, id(garage_error_img));
}
// Garage 2
if (id(garage_2_state).state == "Fully Closed") {
it.printf(25, 550, id(helvetica_25), COLOR_ON, TextAlign::TOP_LEFT, "Garage 2");
} else if (id(garage_2_state).state == "Fully Open"){
it.image(485, 480, id(garage2_img));
} else if (id(garage_2_state).state == "Partially Open") {
it.image(485, 480, id(garage_half_img));
} else if (id(garage_2_state).state == "Door is Closing") {
it.image(485, 480, id(garage_down_img));
} else if (id(garage_2_state).state == "Door is Opening") {
it.image(485, 480, id(garage_up_img));
} else if (id(garage_2_state).state == "Loading") {
it.image(485, 480, id(garage_loading_img));
} else {
it.image(485, 480, id(garage_error_img));
}
// -- Summer end -- \\
}