Paul-Vincent Roll 9 months ago
commit 7bfb4ba075

@ -31,6 +31,25 @@ This is part of the ecosystem for [my Home Assistant configuration](https://gith
5. Once booted, flash `weatherman.yaml` the ESP32 board using ESPHome. 5. Once booted, flash `weatherman.yaml` the ESP32 board using ESPHome.
6. Enjoy! 6. Enjoy!
## Features
## Intelligent Screen Refreshing
To reduce the frequency of screen refreshes and to prolong the life of the e-ink screen, the screen will now only refresh when motion (or any template criteria) sensor `binary_sensor.weatherman_motion_detected` is on. I have it set up so that it wakes up when there are any motions from my sensors in the living room.
## Last Refreshed Timestamp
The last update timestamp can be displayed on the screen itself. No more wondering when the screen was last refreshed!
## Remote Control and Monitoring
The screen can now be controlled and monitored remotely. The screen can be either refreshed manually, restarted, or safely shut down through buttons in your HA. The number of screen refreshes in its lifetime as well as its last update timestamp and wifi signal strength can also be monitored.
![List of available sensors and buttons](https://user-images.githubusercontent.com/4341881/210636590-40ec6a53-2bae-40db-afe2-6246cfc785a4.png)
![Refresh Screen Count example](https://user-images.githubusercontent.com/4341881/210636618-c59e18d6-d31a-4ddd-98a9-2b5a1094be67.png)
Other changes:
* Negative temperatures can now be displayed. Perfect for winter.
* A nice loading screen is shown before any data is received.
* Titles are now in text rather than bitmaps. Much easier to change it to anything you like.
## Data Sources ## Data Sources
- Metno Hourly Weather Forecast HA integration - Metno Hourly Weather Forecast HA integration

@ -84,7 +84,7 @@ template:
{% set next_setting = as_timestamp(state_attr('sun.sun', 'next_setting')) %} {% set next_setting = as_timestamp(state_attr('sun.sun', 'next_setting')) %}
{% set next_rising = as_timestamp(state_attr('sun.sun', 'next_rising')) %} {% set next_rising = as_timestamp(state_attr('sun.sun', 'next_rising')) %}
{% set cond0_time = as_timestamp(state_attr('weather.valhalla_hourly', 'forecast')[0].datetime) %} {% set cond0_time = as_timestamp(state_attr('weather.valhalla_hourly', 'forecast')[0].datetime) %}
{% if cond0_time > next_setting and cond0_time < next_rising %} {% if cond0_time < next_rising and next_rising < next_setting %}
{% if cond0 == 'sunny' %} night {% elif cond0 == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond0 }} {% endif %} {% if cond0 == 'sunny' %} night {% elif cond0 == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond0 }} {% endif %}
{% else %} {% else %}
{{ cond0 }} {{ cond0 }}
@ -99,7 +99,7 @@ template:
{% set next_setting = as_timestamp(state_attr('sun.sun', 'next_setting')) %} {% set next_setting = as_timestamp(state_attr('sun.sun', 'next_setting')) %}
{% set next_rising = as_timestamp(state_attr('sun.sun', 'next_rising')) %} {% set next_rising = as_timestamp(state_attr('sun.sun', 'next_rising')) %}
{% set cond1_time = as_timestamp(state_attr('weather.valhalla_hourly', 'forecast')[1].datetime) %} {% set cond1_time = as_timestamp(state_attr('weather.valhalla_hourly', 'forecast')[1].datetime) %}
{% if cond1_time > next_setting and cond1_time < next_rising %} {% if cond1_time < next_rising and next_rising < next_setting %}
{% if cond1 == 'sunny' %} night {% elif cond1 == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond1 }} {% endif %} {% if cond1 == 'sunny' %} night {% elif cond1 == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond1 }} {% endif %}
{% else %} {% else %}
{{ cond1 }} {{ cond1 }}
@ -114,7 +114,7 @@ template:
{% set next_setting = as_timestamp(state_attr('sun.sun', 'next_setting')) %} {% set next_setting = as_timestamp(state_attr('sun.sun', 'next_setting')) %}
{% set next_rising = as_timestamp(state_attr('sun.sun', 'next_rising')) %} {% set next_rising = as_timestamp(state_attr('sun.sun', 'next_rising')) %}
{% set cond2_time = as_timestamp(state_attr('weather.valhalla_hourly', 'forecast')[2].datetime) %} {% set cond2_time = as_timestamp(state_attr('weather.valhalla_hourly', 'forecast')[2].datetime) %}
{% if cond2_time > next_setting and cond2_time < next_rising %} {% if cond2_time < next_rising and next_rising < next_setting %}
{% if cond2 == 'sunny' %} night {% elif cond2 == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond2 }} {% endif %} {% if cond2 == 'sunny' %} night {% elif cond2 == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond2 }} {% endif %}
{% else %} {% else %}
{{ cond2 }} {{ cond2 }}
@ -129,7 +129,7 @@ template:
{% set next_setting = as_timestamp(state_attr('sun.sun', 'next_setting')) %} {% set next_setting = as_timestamp(state_attr('sun.sun', 'next_setting')) %}
{% set next_rising = as_timestamp(state_attr('sun.sun', 'next_rising')) %} {% set next_rising = as_timestamp(state_attr('sun.sun', 'next_rising')) %}
{% set cond3_time = as_timestamp(state_attr('weather.valhalla_hourly', 'forecast')[3].datetime) %} {% set cond3_time = as_timestamp(state_attr('weather.valhalla_hourly', 'forecast')[3].datetime) %}
{% if cond3_time > next_setting and cond3_time < next_rising %} {% if cond3_time < next_rising and next_rising < next_setting %}
{% if cond3 == 'sunny' %} night {% elif cond3 == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond3 }} {% endif %} {% if cond3 == 'sunny' %} night {% elif cond3 == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond3 }} {% endif %}
{% else %} {% else %}
{{ cond3 }} {{ cond3 }}

@ -23,6 +23,7 @@ esp32:
framework: framework:
type: arduino type: arduino
# Enable logging # Enable logging
logger: logger:
@ -34,11 +35,11 @@ ota:
button: button:
- platform: shutdown - platform: shutdown
name: "weatherman: Shutdown" name: "Weatherman - Shutdown"
- platform: restart - platform: restart
name: "weatherman: Restart" name: "Weatherman - Restart"
- platform: template - platform: template
name: "weatherman: Refresh Screen" name: "Weatherman - Refresh Screen"
entity_category: config entity_category: config
on_press: on_press:
- script.execute: update_screen - script.execute: update_screen
@ -71,7 +72,7 @@ globals:
initial_value: '0' initial_value: '0'
# Script for updating screen - Refresh display and publish refresh count and time. (Thanks @paviro!)
script: script:
- id: update_screen - id: update_screen
then: then:
@ -113,8 +114,8 @@ wifi:
# Enable fallback hotspot (captive portal) in case wifi connection fails # Enable fallback hotspot (captive portal) in case wifi connection fails
ap: ap:
ssid: "Esphome-Web-901078" ssid: !secret weatherman_ap_ssid
password: "2JOrpBYEHQsV" password: !secret weatherman_ap_password
# Include custom fonts # Include custom fonts
@ -125,7 +126,7 @@ font:
- file: 'fonts/GothamRnd-Bold.ttf' - file: 'fonts/GothamRnd-Bold.ttf'
id: font_large_bold id: font_large_bold
size: 108 size: 108
glyphs: [' ', '°', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'C'] glyphs: [' ', '-', '°', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'C']
- file: 'fonts/GothamRnd-Bold.ttf' - file: 'fonts/GothamRnd-Bold.ttf'
id: font_title id: font_title
size: 54 size: 54
@ -137,7 +138,7 @@ font:
- file: 'fonts/GothamRnd-Bold.ttf' - file: 'fonts/GothamRnd-Bold.ttf'
id: font_small_bold id: font_small_bold
size: 18 size: 18
# glyphs: ['°', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'C', 'M', 'I', 'N'] # glyphs: [' ', '-', '°', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'C', 'M', 'I', 'N']
# Include Material Design Icons font # Include Material Design Icons font
@ -199,31 +200,43 @@ binary_sensor:
id: motion_detected id: motion_detected
sensor: sensor:
# Create sensors for monitoring Weatherman remotely.
- platform: template - platform: template
name: "weatherman: Display Last Update" name: "Weatherman - Display Last Update"
device_class: timestamp device_class: timestamp
entity_category: "diagnostic"
id: display_last_update id: display_last_update
- platform: template - platform: template
name: "weatherman: Recorded Display Refresh" name: "Weatherman - Recorded Display Refresh"
accuracy_decimals: 0
unit_of_measurement: "Refreshes"
state_class: "total_increasing"
entity_category: "diagnostic"
lambda: 'return id(recorded_display_refresh);' lambda: 'return id(recorded_display_refresh);'
- platform: wifi_signal
name: "Weatherman - WiFi Signal Strength"
id: wifisignal
unit_of_measurement: "dBm"
entity_category: "diagnostic"
update_interval: 60s
# Call Subway and Weather sensors from HA. # Call Subway and Weather sensors from HA.
- platform: homeassistant - platform: homeassistant
entity_id: sensor.gtfs_mta_subway_manhattan entity_id: sensor.gtfs_mta_subway_manhattan
id: train_manhattan_due_in id: train_manhattan_due_in
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.gtfs_mta_subway_canarsie entity_id: sensor.gtfs_mta_subway_canarsie
id: train_canarsie_due_in id: train_canarsie_due_in
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.gtfs_mta_subway_manhattan entity_id: sensor.gtfs_mta_subway_manhattan
@ -231,7 +244,7 @@ sensor:
id: train_manhattan_next_train_due_in id: train_manhattan_next_train_due_in
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.gtfs_mta_subway_canarsie entity_id: sensor.gtfs_mta_subway_canarsie
@ -239,7 +252,7 @@ sensor:
id: train_canarsie_next_train_due_in id: train_canarsie_next_train_due_in
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: weather.hourly entity_id: weather.hourly
@ -247,7 +260,7 @@ sensor:
id: weather_temperature id: weather_temperature
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.weatherman_data entity_id: sensor.weatherman_data
@ -255,7 +268,7 @@ sensor:
id: weather_temperature_0 id: weather_temperature_0
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.weatherman_data entity_id: sensor.weatherman_data
@ -263,7 +276,7 @@ sensor:
id: weather_temperature_1 id: weather_temperature_1
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.weatherman_data entity_id: sensor.weatherman_data
@ -271,7 +284,7 @@ sensor:
id: weather_temperature_2 id: weather_temperature_2
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.weatherman_data entity_id: sensor.weatherman_data
@ -279,12 +292,7 @@ sensor:
id: weather_temperature_3 id: weather_temperature_3
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: wifi_signal
name: "WiFi Signal Sensor"
id: wifisignal
update_interval: 60s
text_sensor: text_sensor:
@ -294,7 +302,7 @@ text_sensor:
id: train_manhattan_due_at id: train_manhattan_due_at
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.gtfs_mta_subway_canarsie entity_id: sensor.gtfs_mta_subway_canarsie
@ -302,7 +310,7 @@ text_sensor:
id: train_canarsie_due_at id: train_canarsie_due_at
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.gtfs_mta_subway_manhattan entity_id: sensor.gtfs_mta_subway_manhattan
@ -310,7 +318,7 @@ text_sensor:
id: train_manhattan_next_train_due_at id: train_manhattan_next_train_due_at
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.gtfs_mta_subway_canarsie entity_id: sensor.gtfs_mta_subway_canarsie
@ -318,14 +326,14 @@ text_sensor:
id: train_canarsie_next_train_due_at id: train_canarsie_next_train_due_at
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: weather.valhalla_hourly entity_id: weather.valhalla_hourly
id: weather_state id: weather_state
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.weatherman_data entity_id: sensor.weatherman_data
@ -333,63 +341,63 @@ text_sensor:
id: weather_condition_now id: weather_condition_now
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.weatherman_data entity_id: sensor.weatherman_data
attribute: weather_condition_0 attribute: weather_condition_0
id: weather_condition_0 id: weather_condition_0
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.weatherman_data entity_id: sensor.weatherman_data
attribute: weather_timestamp_0 attribute: weather_timestamp_0
id: weather_timestamp_0 id: weather_timestamp_0
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.weatherman_data entity_id: sensor.weatherman_data
attribute: weather_condition_1 attribute: weather_condition_1
id: weather_condition_1 id: weather_condition_1
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.weatherman_data entity_id: sensor.weatherman_data
attribute: weather_timestamp_1 attribute: weather_timestamp_1
id: weather_timestamp_1 id: weather_timestamp_1
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.weatherman_data entity_id: sensor.weatherman_data
attribute: weather_condition_2 attribute: weather_condition_2
id: weather_condition_2 id: weather_condition_2
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.weatherman_data entity_id: sensor.weatherman_data
attribute: weather_timestamp_2 attribute: weather_timestamp_2
id: weather_timestamp_2 id: weather_timestamp_2
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.weatherman_data entity_id: sensor.weatherman_data
attribute: weather_condition_3 attribute: weather_condition_3
id: weather_condition_3 id: weather_condition_3
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.weatherman_data entity_id: sensor.weatherman_data
attribute: weather_timestamp_3 attribute: weather_timestamp_3
id: weather_timestamp_3 id: weather_timestamp_3
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.weatherman_data entity_id: sensor.weatherman_data
@ -397,21 +405,21 @@ text_sensor:
id: train_status id: train_status
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.weatherman_data entity_id: sensor.weatherman_data
attribute: train_status_manhattan attribute: train_status_manhattan
id: train_status_manhattan id: train_status_manhattan
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
- platform: homeassistant - platform: homeassistant
entity_id: sensor.weatherman_data entity_id: sensor.weatherman_data
attribute: train_status_canarsie attribute: train_status_canarsie
id: train_status_canarsie id: train_status_canarsie
on_value: on_value:
then: then:
- lambda: 'id(data_updated) = true;' - lambda: 'id(data_updated) = true;'
# Pins for Waveshare ePaper ESP Board # Pins for Waveshare ePaper ESP Board
spi: spi:
@ -534,6 +542,13 @@ display:
it.printf(330, 652, id(font_medium_bold), color_text, TextAlign::TOP_CENTER, "%2.0f MIN", id(train_canarsie_next_train_due_in).state); it.printf(330, 652, id(font_medium_bold), color_text, TextAlign::TOP_CENTER, "%2.0f MIN", id(train_canarsie_next_train_due_in).state);
it.printf(150, 684, id(font_small_book), color_text, TextAlign::TOP_CENTER, "%s", id(train_manhattan_next_train_due_at).state.c_str()); it.printf(150, 684, id(font_small_book), color_text, TextAlign::TOP_CENTER, "%s", id(train_manhattan_next_train_due_at).state.c_str());
it.printf(330, 684, id(font_small_book), color_text, TextAlign::TOP_CENTER, "%s", id(train_canarsie_next_train_due_at).state.c_str()); it.printf(330, 684, id(font_small_book), color_text, TextAlign::TOP_CENTER, "%s", id(train_canarsie_next_train_due_at).state.c_str());
// Refresh Timestamp
// Code by EnsconcE from https://community.home-assistant.io/t/esphome-show-time/348903
char str[17];
time_t currTime = id(homeassistant_time).now().timestamp;
strftime(str, sizeof(str), "%H:%M", localtime(&currTime));
it.printf(240, 710, id(font_small_book), color_text, TextAlign::TOP_CENTER, "REFRESHED AT %s", str);
} }
captive_portal: captive_portal:

Loading…
Cancel
Save