The Yaml as requested. Posted the last comment too soon sorry.
Same warning as you really
clunky, with room for improvement. They all have been working fine for ages though.
🌨️ Whether warnings as calendars 🌨️
As I said before this could really do with having a way to update events, as currently if a weather warning changes then it will duplicate it. I'm not sure what timescale Met office posts the warnings in, maybe it's just a simple case as looking at future events and re-writing those.
Edit: TIL there is no delete calendar event… so scratch that for now
###############################################################
###### RSS Feedparser sensor for my region
###############################################################
sensor:
- platform: feedparser
name: "Weather Alerts"
feed_url: 'https://www.metoffice.gov.uk/public/data/PWSCache/WarningsRSS/Region/yh'
date_format: '%a, %b %d %I:%M %p'
inclusions:
- summary
- link
###############################################################
###### Template Sensor to check for my location
###############################################################
template:
- sensor:
- name: "Weather Alerts Yorkshire & Humber"
state: >
{{ state_attr('sensor.weather_alerts','entries')
| map(attribute='summary')
| select('search', 'North Yorkshire')
| list
| count
}}
###############################################################
###### Automation to monitor the state of yorkshire and humber and create a calendar event
###############################################################
alias: Create Calendar Event - Weather Alerts
description: ""
triggers:
- trigger: state
entity_id:
- sensor.weather_alerts_yorkshire_humber
from: null
to: null
conditions: []
actions:
- variables:
alerts: >-
{% set year = now().year %} {% set ns = namespace(alerts=[]) %} {% if
state_attr('sensor.weather_alerts','entries') != 0 %}
{% for item in state_attr('sensor.weather_alerts','entries') %}
{% for type, icon in [('rain', '🌧️'), ('thunderstorms', '⛈️'),
('wind', '🌪️'), ('snow', '❄️'), ('snow, ice', '❄️ 🧊'),
('lightning', '🌩️'), ('ice', '🧊'),
('fog', '🌫️'), ('extreme heat', '🥵'), ('thunderstorm', '⛈️')] if type == item.summary | regex_findall_index('.*warning of (.*) affecting.*', ignorecase=True) %}
{% set color = item.summary.split(' ')[0] %}
{% set summary = item.summary | regex_findall_index('(.*) affecting Yorkshire & Humber: (.*) valid from (.*) to (.*)', ignorecase=True) %}
{% set time_from = as_timestamp(strptime(summary[2], "%H%M %a %d %b")) | timestamp_custom('%m-%d %H:%M:%S') %}
{% set time_to = as_timestamp(strptime(summary[3], "%H%M %a %d %b")) | timestamp_custom('%m-%d %H:%M:%S') %}
{% set ns.alerts = ns.alerts + [{ "title": icon+" "+summary[0], "message": summary[1], "from": year~"-"~time_from, "to": year~"-"~time_to }] %}
{% endfor %}
{% endfor %}
{% endif %}
{{ ns.alerts }}
- repeat:
for_each: "{{ alerts|list }}"
sequence:
- if:
- condition: template
value_template: "{{ \"North Yorkshire\" in repeat.item.message }}"
then:
- action: script.create_a_calendar_event
metadata: {}
data:
all_day: false
title: "{{ repeat.item.title }}"
description: "{{ repeat.item.message }}"
calendar: calendar.weather_alerts
start_date: "{{ repeat.item.from }}"
end_date: "{{ repeat.item.to }}"
mode: single
###############################################################
###### Script I created to make sure a calendar event isn't duplicated, used in automation above
###############################################################
sequence:
- action: calendar.get_events
metadata: {}
data:
duration:
hours: 120
minutes: 0
seconds: 0
start_date_time: "{{ (now() - timedelta(days=1) ).strftime('%Y-%m-%dT%H:%M:%S') }}"
response_variable: events
target:
entity_id: calendar.weather_alerts
- variables:
does_event_exist: >-
{% set event_list = events[calendar].events %} {% set ns =
namespace(name=false, start=false, end=false) %} {% for event in
event_list %}
{% if(event.summary == title) %}
{% set ns.name = true %}
{% endif %}
{% if(strptime(event.start[:18], '%Y-%m-%dT%H:%M:%S') == strptime(start_date, '%Y-%m-%d %H:%M:%S') ) %}
{% set ns.start = true %}
{% endif %}
{% if(strptime(event.end[:18], '%Y-%m-%dT%H:%M:%S') == strptime(end_date, '%Y-%m-%d %H:%M:%S') ) %}
{% set ns.end = true %}
{% endif %}
{% endfor %}
{{ ns.name and ns.start and ns.end }}
- if:
- condition: template
value_template: "{{ not does_event_exist }}"
then:
- action: calendar.create_event
metadata: {}
data:
summary: "{{ title }}"
description: "{{ description }}"
start_date_time: "{{ start_date }}"
end_date_time: "{{ end_date }}"
target:
entity_id: "{{ calendar }}"
alias: If event doesn't exist
fields:
title:
selector:
text: null
name: Title
required: true
description: "The title of the event "
description:
selector:
text: null
name: Description
required: true
description: "The description of the event. "
calendar:
selector:
entity:
filter:
domain: calendar
name: Calendar
required: true
description: "Which calendar to add the event too. "
start_date:
selector:
datetime: {}
name: Start Date
required: false
description: "The date and time the event begins. "
end_date:
selector:
datetime: {}
name: End Date
required: false
description: "The date and time the event ends. Must be after the start date. "
all_day:
selector:
boolean: {}
default: false
name: All Day Event
required: true
description: "Whether the event is all day or not. Default: Off"
alias: Create a Calendar Event If One Doesn't Exist
description: Creates a calendar event
👚 Thin/Thick clothing dry time 👚
This was working "okay" in summer, in winter it's not worked as well not that I get chance to dry the clothes outside much at the minute.
The original script is from this thread: To Line Dry or Not
I use the illuminance integration as I don’t have an outdoor light sensor, so I calculate the sunshine_percent from that which is probably why it fails quite often. Either way it’s been an ok indication of whether I should put the clothes on the line. I also use my rain sensors below too to make a better decision.
I also haven’t gotten around to updating this to make it show hours, currently the calculation comes out in seconds.
###############################################################
###### To line dry or not template sensor.
###############################################################
template:
- trigger:
- platform: time_pattern
minutes: /6
- platform: homeassistant
event: start
action:
- service: weather.get_forecasts
data:
type: hourly
target:
entity_id: weather.###
response_variable: hourly
unique_id: weather_forcast
sensor:
## Line Drying
- trigger:
- platform: time_pattern
id: "update"
minutes: "/6" # repeat every 15 minutes
sensor:
- name: Time to line dry a towel
unique_id: time_to_line_dry_a_towel
unit_of_measurement: "min"
device_class: duration
state_class: "measurement"
state: >
{% set clothing_value = 0.25 %}
{% set illuminance = states('sensor.outdoor_illuminance')|int(0) %}
{% set sunshine_percent = (illuminance / 150000) * 100 %}
{% set current_temp = states('sensor.average_outdoor_temperature')|float(0) or states('sensor.###_temperature')|float(0) %}
{% set current_humidity = states('sensor.average_outdoor_humidity')|float(0) or states('sensor.###_humidity')|float(0) %}
{% set temp = current_temp|round(2) + 273.15 %}
{% set wind = states('sensor.###_wind_speed')|float(0)|round(2) * 0.2777777778 %}
{% set humidity = current_humidity|round(2) / 100 %}
{% set pressure = states('sensor.###_pressure')|float(0) / 10 %}
{% set rn = 9.4*(sunshine_percent / 100) %}
{% set delta=((5336/temp)**(21.07-(5336/temp))) %}
{% set lamda=2.501-0.002361*(temp-273) %}
{% set y=(0.0016286*pressure)/lamda %}
{% set ea=1**(21.07-(5336/temp)) %}
{% set d=(1-humidity)*ea %}
{% set e=(delta*rn+y*(6.43*(1+0.536*wind)*d))/(lamda*(delta+y)) %}
{{ ((clothing_value/(e))*1440)|round(2) }}
- name: Time to line dry a t-shirt
unique_id: time_to_line_dry_a_t_shirt
unit_of_measurement: "min"
device_class: duration
state_class: "measurement"
state: >
{% set clothing_value = 0.075 %}
{% set illuminance = states('sensor.outdoor_illuminance')|int(0) %}
{% set sunshine_percent = (illuminance / 150000) * 100 %}
{% set current_temp = states('sensor.average_outdoor_temperature')|float(0) or states('sensor.###_temperature')|float(0) %}
{% set current_humidity = states('sensor.average_outdoor_humidity')|float(0) or states('sensor.###_humidity')|float(0) %}
{% set temp = current_temp|round(2) + 273.15 %}
{% set wind = states('sensor.###_wind_speed')|float(0)|round(2) * 0.2777777778 %}
{% set humidity = current_humidity|round(2) / 100 %}
{% set pressure = states('sensor.###_pressure')|float(0) / 10 %}
{% set rn = 9.4*(sunshine_percent / 100) %}
{% set delta=((5336/temp)**(21.07-(5336/temp))) %}
{% set lamda=2.501-0.002361*(temp-273) %}
{% set y=(0.0016286*pressure)/lamda %}
{% set ea=1**(21.07-(5336/temp)) %}
{% set d=(1-humidity)*ea %}
{% set e=(delta*rn+y*(6.43*(1+0.536*wind)*d))/(lamda*(delta+y)) %}
{{ ((clothing_value/(e))*1440)|round(2) }}
🌧️ Rain and Temperature Average Forecasts 🌡️
These I quite like to give an average of the future conditions rather than having to look at the forecast. I use them on my home page to tell me weather rain is more than likely continuing or stopping in the next 6/12 hours and similar for temperature, I can check whether it's going to get warmer/cooler.
###############################################################
###### Rain and Temperature Sensor Average Forecasts
###############################################################
template:
- trigger:
- platform: time_pattern
minutes: /6
- platform: homeassistant
event: start
action:
- service: weather.get_forecasts
data:
type: hourly
target:
entity_id: ###
response_variable: hourly
unique_id: weather_forcast
sensor:
- name: Next 6 Hours Chance of Rain
unique_id: next_6_hours_rain
unit_of_measurement: "%"
state_class: "measurement"
state: >-
{% set forecast = hourly['###'].forecast %}
{{
((
forecast[5].precipitation_probability | float +
forecast[4].precipitation_probability | float +
forecast[3].precipitation_probability | float +
forecast[2].precipitation_probability | float +
forecast[1].precipitation_probability | float +
forecast[0].precipitation_probability | float) / 6
)|round(2)
}}
- name: Next 12 Hours Chance of Rain
unique_id: next_12_hours_rain
unit_of_measurement: "%"
state_class: "measurement"
state: >-
{% set forecast = hourly['###'].forecast %}
{{
((
forecast[11].precipitation_probability | float +
forecast[10].precipitation_probability | float +
forecast[9].precipitation_probability | float +
forecast[8].precipitation_probability | float +
forecast[7].precipitation_probability | float +
forecast[6].precipitation_probability | float) / 6
)|round(2)
}}
- name: Next 6 Hours Average Temperature Forecast
unique_id: next_6_hours_temperature
unit_of_measurement: "°C"
state_class: "measurement"
state: >-
{% set forecast = hourly['###'].forecast %}
{{
((
forecast[5].temperature | float +
forecast[4].temperature | float +
forecast[3].temperature | float +
forecast[2].temperature | float +
forecast[1].temperature | float +
forecast[0].temperature | float) / 6
)|round(2)
}}
- name: Next 12 Hours Average Temperature Forecast
unique_id: next_12_hours_temperature
unit_of_measurement: "°C"
state_class: "measurement"
state: >-
{% set forecast = hourly['###'].forecast %}
{{
((
forecast[11].temperature | float +
forecast[10].temperature | float +
forecast[9].temperature | float +
forecast[8].temperature | float +
forecast[7].temperature | float +
forecast[6].temperature | float) / 6
)|round(2)
}}
###############################################################
###### Mushroom Badge to display the temperatures from the template
###### Limits visibility to really cold, or overly hot.
###############################################################
type: custom:mushroom-template-badge
content: |-
{% set six = states(entity)|float(0) %}
{% set twelve = states(entity.replace("6","12"))|float(0) %}
{% if(six > 18) %}
{{ six|int(0) }}°C {% if six > twelve %}- Cooling{% else %}- Warming{% endif %}
{% elif(twelve > 18) %}
{{ twelve|int(0) }}°C
{% elif(six < 5) %}
{{ twelve|int(0) }}°C
{% elif(twelve < 5) %}
{{ six|int(0) }}°C {% if six > twelve %}- Cooling{% else %}- Warming{% endif %}
{% else %}
Cold
{% endif %}
icon: mdi:thermometer
color: |-
{% set six = states(entity)|float(0) %}
{% set twelve = states(entity.replace("6","12"))|float(0) %}
{% if(six > 18) %}
orange
{% elif(twelve > 18) %}
red
{% elif(six < 5) %}
cyan
{% elif(twelve < 5) %}
blue
{% else %}
black
{% endif %}
label: |-
{% set six = states(entity)|float(0) %}
{% set twelve = states(entity.replace("6","12"))|float(0) %}
{% if(six > 18) %}
6 Hour Temp
{% elif(twelve > 18) %}
12 Hour Temp
{% elif(six < 5) %}
6 Hour Temp
{% elif(twelve < 5) %}
12 Hour Temp
{% else %}
Cold
{% endif %}
tap_action:
action: navigate
navigation_path: /lovelace/weather
entity: sensor.next_6_hours_average_temperature_forecast
visibility:
- condition: or
conditions:
- condition: numeric_state
entity: sensor.next_6_hours_average_temperature_forecast
above: 18
- condition: numeric_state
entity: sensor.next_12_hours_average_temperature_forecast
above: 18
- condition: numeric_state
entity: sensor.next_6_hours_average_temperature_forecast
below: 5
- condition: numeric_state
entity: sensor.next_12_hours_average_temperature_forecast
below: 5
###############################################################
###### Mushroom Card Template Badges to display the chance of Rain
###### Limits visibility to percentages I've settled at when Rain occured from what pirate weather said.
###############################################################
type: custom:mushroom-template-badge
content: |-
{% set six = states(entity)|float(0) %}
{% set twelve = states(entity.replace("6","12"))|float(0) %}
{% if(six > 20) %}
{{ six|int(0) }}% {% if six > twelve %}- Passing{% else %}- Continuing{% endif %}
{% elif(twelve > 20) %}
{{ twelve|int(0) }}%
{% else %}
No Rain
{% endif %}
icon: mdi:weather-rainy
color: |-
{% set six = states(entity)|float(0) %}
{% set twelve = states(entity.replace("6","12"))|float(0) %}
{% if(six > 20) %}
cyan
{% elif(twelve > 20) %}
lightblue
{% else %}
black
{% endif %}
label: |-
{% set six = states(entity)|float(0) %}
{% set twelve = states(entity.replace("6","12"))|float(0) %}
{% if(six > 20) %}
Rain in 6 hours
{% elif(twelve > 20) %}
Rain in 12 hours
{% else %}
No Rain
{% endif %}
tap_action:
action: navigate
navigation_path: /lovelace/rain
entity: sensor.next_6_hours_chance_of_rain
visibility:
- condition: or
conditions:
- condition: numeric_state
entity: sensor.next_6_hours_chance_of_rain
above: 20
- condition: numeric_state
entity: sensor.next_12_hours_chance_of_rain
above: 20
🕰️ Daylights Savings Sensor 🕰️
Original Thread: [Daylight Savings Time](https://community.home-assistant.io/t/daylight-savings-time-dst-template-and-automation/351889)
template:
- trigger:
- platform: time
at: "00:00:00"
- platform: homeassistant
event: start
- platform: event
event_type: call_service
event_data:
domain: template
service: reload
sensor:
- unique_id: dst_next
name: "Daylight Savings Next"
device_class: timestamp
state: >
{%- macro hms(t) %}
{%- set dststr = t.dst() | string if t.dst() is not none else "00:00:00" %}
{%- set h, m, s = dststr.split(':') | map('int') %}
{{- h * 60 * 60 + m * 60 + s }}
{%- endmacro %}
{%- macro is_dst(t) %}
{{- hms(t) | int != 0 }}
{%- endmacro %}
{%- macro finddst(t, kwarg, rng) %}
{%- set ns = namespace(previous=is_dst(t), found=none) %}
{%- for i in range(rng) %}
{%- set ts = t + timedelta(**{kwarg:i}) %}
{%- if ns.previous != is_dst(ts) and ns.found is none %}
{%- set ns.found = i %}
{%- endif %}
{%- endfor %}
{{- ns.found }}
{%- endmacro %}
{%- set t = now().replace(hour=0, minute=0, second=0, microsecond=0) %}
{%- set d = finddst(t, 'days', 366) | int - 1 %}
{%- set h = finddst(t + timedelta(days=d), 'hours', 25) | int - 1 %}
{%- set m = finddst(t + timedelta(days=d, hours=h), 'minutes', 61) | int %}
{{ (t + timedelta(days=d, hours=h, minutes=m)) }}
- unique_id: dst_phrase
name: "Daylight Savings Phrase"
state: >
{%- macro hms(t) %}
{%- set dststr = t.dst() | string if t.dst() is not none else "00:00:00" %}
{%- set h, m, s = dststr.split(':') | map('int') %}
{{- h * 60 * 60 + m * 60 + s }}
{%- endmacro %}
{%- macro phrase(seconds, name, divisor, mod=None) %}
{%- set value = ((seconds | abs // divisor) % (mod if mod else divisor)) | int %}
{%- set end = 's' if value > 1 else '' %}
{{- '{} {}{}'.format(value, name, end) if value > 0 else '' }}
{%- endmacro %}
{%- macro total(seconds) %}
{%- set values = [
phrase(seconds, 'hour', 60*60, 60*60*24),
phrase(seconds, 'minute', 60, 60),
] | select('!=','') | list %}
{{- values[:-1] | join(', ') ~ ' and ' ~ values[-1] if values | length > 1 else values | first | default}}
{%- endmacro %}
{%- macro finddelta(t, kwarg, rng) %}
{%- set ns = namespace(previous=hms(t), found=none) %}
{%- for i in range(rng) %}
{%- set ts = t + timedelta(**{kwarg:i}) %}
{%- if ns.previous != hms(ts) and ns.found is none %}
{%- set before = hms(ts - timedelta(days=1)) | int %}
{%- set after = hms(ts) | int %}
{%- set ns.found = after - before %}
{%- endif %}
{%- endfor %}
{{ ns.found }}
{%- endmacro %}
{%- set t = now().replace(hour=0, minute=0, second=0, microsecond=0) %}
{%- set delta = finddelta(t, 'days', 365) | int %}
{% if delta > 0 %}
lose {{ total(delta | abs) }}
{% else %}
gain {{ total(delta | abs) }}
{% endif %}
- sensor:
- unique_id: dst_days
name: "Daylight Savings Days Until"
unit_of_measurement: days
state: >
{% set next = states('sensor.daylight_savings_next') | as_datetime %}
{% set today = now().replace(hour=0, minute=0, second=0, microsecond=0) %}
{{ (next - today).days if next is not none else 0 }}
availability: >
{{ states('sensor.daylight_savings_next') not in ['unknown', 'unavailable'] }}
Don’t think I’ve missed any. The lightning sensor is just blitzortung integration and the custom card “blitzortung-lightning-card”. The “Outside Rain %” is just something I’m messing around with currently. I’ve got 2 soil moisture sensors sat outside open to the air and when they get wet that percent rises. It was working ok until it decided to get frosty and dewy on a morning
. If you need help with anything let me know. I’ll update if I change how I do the calendar as events, as I think I might clear any future events from the day the event changes and then re-create the new ones. Thinking that might solve the duplicate issue and allow me to keep a history.