Getting warned when it's going to freeze

Hi

PLEASE READ ALSO FOSSY777’s post below. This is not working in recent versions of HA

I’m trying to save my outside water tap and some plants from freezing. So I came up with the following idea: Let’s use the weather forecast (in my case Openweathermap) and notify if there are freezing temperatures in the forecast. If that is the case, send me a mail. Openweathermap provides a 3hour/5day forecast and 5 days should be enough as a head warning. A previous solution did not keep state across HA restarts.

So this is how I went a about.

  1. Use a python script to determine if freezing temperatures are in the future
  2. Maintain a template sensor with the lowest temperature in the forecast and the moment the temperature goes below 0°C
  3. Have an automation to notify me when the minimum temperature goes below 0°C or back above 0°C

Here is the code.

The python script:

epoch   = 0
mintemp = 100.0

sensor      = 'sensor.mintemp'
weather     = 'weather.openweathermap'
is_forecast = 'input_select.forecast'

forecast = hass.states.get(weather).attributes['forecast']
current  = float( hass.states.get(sensor).state )

date0 = epoch
for fc3h in forecast:
    temp = fc3h['temperature']
    dt   = int(fc3h['datetime'])
    if temp < mintemp:
        mintemp = temp
    if temp < 0.0 and epoch == date0:
        date0 = dt

date0 = date0 / 1000.0
hass.states.set(sensor, mintemp, {
    "epoch0": date0,
    } )

if mintemp < 0.0:
    result = 'freeze'
else:
    result = 'non-freeze'

hass.states.set(is_forecast, result)

The sensor configuration.yaml definitons

sensor:
- platform: template
  sensors:
    mintemp:
      value_template: 0.0
      unit_of_measurement: "°C"
      attribute_templates:
        epoch0: 0
       
input_select:
  forecast:
    name: forecasting freezing temperatures
    options:
      - non-freeze
      - freeze

weather:
  - platform: openweathermap
    api_key: !secret openweathermap_key

Automation to trigger the python script from

alias: calculate minimum temparature (they don't get simpler)

trigger:
  platform: state
  entity_id: weather.openweathermap

action:
  - service: python_script.mintemp

The automations to detect the freezing forecast (not the end of freezing one as it is very similar. I’m not sure why I added this one as it is very straightforward):

alias: freezing on

trigger:
  platform: state
  entity_id: input_select.forecast
  from: 'non-freeze'
  to: 'freeze'

action:
  - service: notify.mailer
    data_template:
      title: "HA: Vriestemperaturen in het vooruitzicht"
      message: >
        Er wordt een minimum temperatuur verwacht van
        {{states('sensor.mintemp')}}.
        De thermometer gaat onder nul vanaf 
        {{ state_attr( 'sensor.mintemp', 'epoch0' ) | timestamp_custom( '%e %B om %k uur' ) }}

And that’s it. As I don’t have deep knowledge on HA, there may be better solutions to this. If they exist I’m happy to learn about them.

Note that I could do more (if not everything) in the python script, I know. I prefer to do things as much as possible in YAML. But if there are good reasons for that I would like to know those.

Regards, G
EDIT: I changed two things: i no longer need the -3°, so removed that, and introduced the input select so the state survives HA restarts.
EDIT2: Added the configuration for openweathermap.

2 Likes

For my taps and pipes, I use this: https://www.amazon.com/GardenHOME-Valve-Heating-Cable-6Feet/dp/B015JX9332/ref=sr_1_3_sspa?keywords=pipe+heat+tape&qid=1579527703&sr=8-3-spons&psc=1&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUExVThUM01YVkVXOEY1JmVuY3J5cHRlZElkPUEwMTAzNDE0NkNRSDVXR0JHQUVMJmVuY3J5cHRlZEFkSWQ9QTA3MjA1MzMzNUNLU0o4NjZGQk9BJndpZGdldE5hbWU9c3BfYXRmJmFjdGlvbj1jbGlja1JlZGlyZWN0JmRvTm90TG9nQ2xpY2s9dHJ1ZQ==

I have it on a smart plug and when my DarkSky forecast shows 2 or more days of below freezing temps, it turns the outlet on. The tape itself takes care of it’s own temperature as long as it has power. I like your Python approach and I’ll probably change mine to adopt it.

1 Like

Thinking the python script might have been a little excessive - even if functional. Personally, I built a quick car wash sensor that leverages DarkSky weather forecast and the future probability of rain in the next 5 days. Uses a single template sensor which is turned on/off based on some quick probabilities.

    car_wash_test:
      value_template: >
        {% set D0 = states('sensor.darksky_weather_precip_probability') | int %}
        {% set D1 = states('sensor.darksky_weather_precip_probability_1d') | int %}
        {% set D2 = states('sensor.darksky_weather_precip_probability_2d') | int %}
        {% set D3 = states('sensor.darksky_weather_precip_probability_3d') | int %}
        {% set D4 = states('sensor.darksky_weather_precip_probability_4d') | int %}
        {% set D5 = states('sensor.darksky_weather_precip_probability_5d') | int %}

        {% if D0 > 50 %} off
        {% elif D1 > 50 %} off
        {% elif D2 > 60 %} off
        {% elif D3 > 70 %} off
        {% elif D4 > 73 %} off
        {% elif D5 > 76 %} off
        {% elif 'rain' in states('sensor.darksky_weather_icon') %} off
        {% elif states('sensor.darksky_weather_humidity') | int > 89 or states('sensor.front_porch_sensor_relative_humidity_measurement') | int > 89 %} off
        {% elif (D1+D2+D3+D4+D5) > 100 %} off
        {% else %} on
        {% endif %}

    car_wash:
      value_template: >-
        {% if is_state('sensor.car_wash_test','on') %}
          Yes
        {% else %}
          No
        {% endif %}
      entity_picture_template: >-
        {% if is_state('sensor.car_wash_test', 'on') %}
          /local/custom_icons/car-wash-yellow-FDD835.png
        {% else %}
          /local/custom_icons/car-wash-blue-44739E.png
        {% endif %}
      attribute_templates:
        D0: "{{states('sensor.darksky_weather_precip_probability')}}"
        D1: "{{states('sensor.darksky_weather_precip_probability_1d')}}"
        D2: "{{states('sensor.darksky_weather_precip_probability_2d')}}"
        D3: "{{states('sensor.darksky_weather_precip_probability_3d')}}"
        D4: "{{states('sensor.darksky_weather_precip_probability_4d')}}"
        D5: "{{states('sensor.darksky_weather_precip_probability_5d')}}"

Sensor could be used to trigger email / such - but I just have it on my HA dashboard showing me if it’s a good idea to wash the car. Apparently / sadly - it’s going to rain

image

Clicking on it then shows the probabilities in the future. Definitely a little bit of variability / quick switches - but I haven’t cared enough to work to smooth it out…

image

5 Likes

Thanks @Markus99 for the suggestion. I like the idea. Openweathermap provides an array of 40(5d every 3h) forecast data points. The reason for the python script is that this allows me to loop over those 40 points while calculating all the attributes at the same time.
I could write the script in jinja but I would have to rely on the order of execution of the attribute value_templates. And as these are a hash in Yaml, I’m supposing that they are executed in the order they are hashed.
Regards, G.

1 Like

Thanks @code-in-progress. I have a similar device (only 1 foot long) to keep the water for the chickens from freezing. And to your point I can link it directly to this automation. Nice.
Regards, G

1 Like

Thank you, Paul, for this post! I implemented and can confirm it works. The only thing I was facing was that the timestamp_custom parameters you used in your notification did not work on my system. I used then " %d. %B at %H:%M " instead.

Hi Paul,

Just in time before we need it to save our plants, it stopped working. Did you see? Obviously, there was a change either on HA or on OpenWeatherMaps API. The sensor sensor.openweathermap_forecast_temperature_low on which everything relies on is now unknown on my system. On yours, too?

BR, Jo

Hi all,

never mind, it was an issue with changing OpenWeatherMap to integration with 0.115.2 as you can also read here: Smart Sprinkler Automation (skip watering if there is rain in next 48 hours - 2 days)

There was a PR opened and it will get fixed (hopefully) soon

Hello, thank you for this code. I tried it myself but it seems that the forecast only sees in the near future (3 hours). I got a notification this night at 4:30 that the temperature is low at 7:00. Is this code still up to date or can this only view in the really near future?
Regards!

Found my problem. In the integration I needed to choose for “hourly” instead of the “freedaily”. My bad.

Thanks for your feedback, working on HA is a winter activity. I’m still running 0.104.1. I’m upgrading in the next couple of weeks, probably. So thanks @Fossy777 for the heads up.
@belgianrubs, I did not specify the mode in my configuration and added that in my original post. But I may need to change that when I upgrade.

Hi,

on my side, long time ago the script stopped working and I didn´t find the time to debug but now I (finally) did it and figured out why and how to fix:

    dt   = int(fc3h['datetime'])

produced a

Error executing script: invalid literal for int() with base 10: '2021-04-16T18:00:00+00:00'

so I took away the “int(”. Also I hat do comment out or delete the line “date0 = date0 / 1000.0” of course as it is no number then anymore.
I have no idea why this is no longer working, as I have no comparision how it was before, maybe the time format changed?

Anyway, my script looks like this now and it works:

epoch   = 0
mintemp = 100.0

sensor      = 'sensor.mintemp'
weather     = 'weather.openweathermap'
is_forecast = 'input_select.forecast'

forecast = hass.states.get(weather).attributes['forecast']
current  = float( hass.states.get(sensor).state )

date0 = epoch
for fc3h in forecast:
    temp = fc3h['temperature']
    dt   = fc3h['datetime']
    if temp < mintemp:
        mintemp = temp
    if temp < 0.0 and epoch == date0:
        date0 = dt


hass.states.set(sensor, mintemp, {
    "epoch0": date0,
    } )

if mintemp < 0.0:
    result = 'freeze'
else:
    result = 'non-freeze'

hass.states.set(is_forecast, result)

Result is having a weird time stamp in sensor.mintemp.epoch0 like 2021-04-17T03:00:00+00:00, which made my template for the output used in the notifications no longer working so I also had to rework those.

Don´t know if this can be done easier, I find the templating always a pain in the a*, but this is how my working one looks like now:

{{ as_timestamp(strptime(state_attr( 'sensor.mintemp', 'epoch0' ), '%Y-%m-%dT%H:%M:%S'))  |
  timestamp_custom( '%d. %B at %H:%M o´clock.' ) }}

So in the initial example from above, the automation should look like this now (in english as I am not aware of dutch :smiley: ):

alias: freezing on

trigger:
  platform: state
  entity_id: input_select.forecast
  from: 'non-freeze'
  to: 'freeze'

action:
  - service: notify.mailer
    data_template:
      title: "HA: Freezing temperatures ahead"
      message: >
        Caution. A new low temperature is predicted of
        {{states('sensor.mintemp')}}.
        The thermometer will go below zero from
        {{ as_timestamp(strptime(state_attr( 'sensor.mintemp', 'epoch0' ), '%Y-%m-%dT%H:%M:%S'))  | timestamp_custom( '%d. %B at %H:%M .' ) }}

Hope this helps :slight_smile:

Greetings, Jo

1 Like
1 Like

Thanks @HugosDad . I updated it a little bit and this worked for me:

template:
  - trigger:
      - platform: time
        at:
          - '18:00:00'
      # for debug
      # - platform: homeassistant
      #   event: start
    sensor:
      - name: Forecast lowest temperature 5 days
        unit_of_measurement: "°C"
        state: >
          {% set start = now().replace(hour=0,minute=0,second=0, microsecond=0) %}
          {% set end = (start + timedelta(days=5)) %}
          {% set start = start.strftime("%Y-%m-%dT%H:%M:%S+00:00") %}
          {% set end = end.strftime("%Y-%m-%dT%H:%M:%S+00:00") %}
          {{ state_attr('weather.forecast_home', 'forecast') | selectattr('datetime', '>=', start) | selectattr('datetime','<=', end) | map(attribute='templow') | list | min }}

automation:
  alias: Frost Forecast
  description: >-
    Checks the forecast lowest temps for the next 5 days and notify if there are frost risk
  mode: single
  trigger:
    - platform: state
      entity_id: sensor.forecast_lowest_temperature_5_days
  variables:
    min_temp: 2
  condition:
    - "{{ states('sensor.forecast_lowest_temperature_5_days') | int < min_temp }}"
  action:
    - service: notify.all
      data:
        title: Frost is forecast!
        message: |
          Days below {{ min_temp }} °C:
          {%- for day in state_attr('weather.forecast_home', 'forecast') | selectattr('templow', '<', min_temp) %}
          {{ as_datetime(day.datetime).strftime('%m-%d')  }} - Lowest temperature: {{ day.templow }}
          {%- endfor %}
1 Like

Would be great if OpenWeather was working. Seem’s lot of people having issues with it. Needs to be set on oncedaily to allow the sensor not to become unavailable.