I spent all weekend fine tuning my OpenWeatherMap integration, just so I can get an accurate, by the minute chance of precipitation notification prior to walking my dogs at lunch. Since I appear to have succeeded, I wanted to share my final outcome, and how I implemented it in HA. Disclaimer: I am very new to Home Assistant, so please bear with me if my code isn’t that great, but it does appear to work!
I had figured out precipitation probability and went over that in another post, but noticed a discrepancy between the chance of rain, and actual rain in the next hour. For example, OWM will say 80% chance of rain, but on the map, “no rain expected in the next hour.” I figured that rain expectation might be based on radar maps of actual precipitation, and would be a much better way to judge whether to venture out into the woods with our dogs.
These are my resulting dashboard widgets, and I have a notification that let’s me know if there’s going to be rain or not using the sensors.
First, I created a text helper called “Precipitation Forecast JSON” with a maximum of 255 characters.
I then built an automation that uses the OWM API to get the minute forecast, then formats the precipitation amounts for the next hour in a condensed version to send to the text helper:
alias: Update Precipitation Forecast JSON
description: ""
triggers:
- minutes: /5
trigger: time_pattern
- event: start
trigger: homeassistant
actions:
- target:
entity_id: weather.openweathermap
response_variable: minute_forecast_data
action: openweathermap.get_minute_forecast
data: {}
- target:
entity_id: input_text.minute_forecast_json
data:
value: >-
{% set rain_data =
minute_forecast_data['weather.openweathermap'].forecast %} {% if
rain_data is defined and rain_data is not none %}
{{ (rain_data[:60] | map(attribute='precipitation') | map('float') | map('int') | list | to_json | replace(' ', ''))[:255] }}
{% else %}
"[]"
{% endif %}
action: input_text.set_value
mode: single
Now that I had an updated text helper with the information formatted in a compressed layout that fit the character limitation, I created a sensor, using moisture dry/wet to use for the notification for my walk. This one was verrrry difficult to figure out, but I finally got this sensor to work:
sensor:
- platform: template
sensors:
rainy_minute_summary:
friendly_name: "Rainy Minute Summary"
value_template: >
{% set data_string = states('input_text.minute_forecast_json') %}
{% set final_display_state = 'No rain expected' %}
{% if data_string is string and data_string not in ['unknown', 'unavailable', ''] %}
{% set values = data_string | from_json | map('float') | list %}
{% set ns = namespace(rainy_minutes=[]) %}
{% for i in range(values | length) %}
{% if values[i] > 0 %}
{% set ns.rainy_minutes = ns.rainy_minutes + [i] %}
{% endif %}
{% endfor %}
{% if ns.rainy_minutes | length > 0 %}
{% set final_display_state = 'Rain expected at minutes: ' + (ns.rainy_minutes | join(', ')) %}
{% endif %}
{% endif %}
{{ final_display_state }}
attribute_templates:
source: "{{ states('input_text.minute_forecast_json') }}"
parsed_values: >
{% set data_string = states('input_text.minute_forecast_json') %}
{% if data_string is string and data_string not in ['unknown', 'unavailable', ''] %}
{{ data_string | from_json | map('float') | list }}
{% else %}
[]
{% endif %}
rainy_minutes: >
{% set data_string = states('input_text.minute_forecast_json') %}
{% set ns = namespace(rainy_minutes=[]) %}
{% if data_string is string and data_string not in ['unknown', 'unavailable', ''] %}
{% set values = data_string | from_json | map('float') | list %}
{% for i in range(values | length) %}
{% if values[i] > 0 %}
{% set ns.rainy_minutes = ns.rainy_minutes + [i] %}
{% endif %}
{% endfor %}
{% endif %}
{{ ns.rainy_minutes }}
This lets me know yes/no it will be raining at some point in the next hour, and I could have stopped there, but I was on a roll. This sensor lists the minutes that will be rainy over the next hour:
binary_sensor:
- platform: template
sensors:
precipitation_expected_next_hour:
friendly_name: "Precipitation Expected Next Hour"
unique_id: openweathermap_precipitation_expected_next_hour
device_class: moisture
icon_template: >
{% if is_state('binary_sensor.precipitation_expected_next_hour', 'on') %}
mdi:weather-pouring
{% else %}
mdi:water-off
{% endif %}
value_template: >
{% set data_string = states('input_text.minute_forecast_json') %}
{% set final_state = 'unavailable' %}
{% if data_string is string and data_string not in ['unknown', 'unavailable', ''] %}
{% set values = data_string | from_json %}
{% if values is iterable and values is not string and values is not none %}
{% set total_precipitation = values | sum %}
{% set precipitation_detected = total_precipitation > 0 %}
{% set final_state = 'on' if precipitation_detected else 'off' %}
{% endif %}
{% endif %}
{{ final_state }}