Categories
Connected Farm

Weather Forecast Based Automation and Notifications with Home Assistant.

Having recently changed electricity plan to one of the new smart meter plans with variable electricity unit price rates, I moved my immersion timer to night time to take advantage of the cheapest rate. This created a slight issue because I also have solar panels for hot water and I’m now heating water at night using electricity. Previously the immersion came on in the evening only if the solar panels had not produced enough hot water during the day.

My solution to this problem was to create an automation which can read the forecast and decide whether or not the immersion should switch on at all, based on the cloud forecast for the daytime hours of the following day. Unfortunately none of the weather integrations as far as I could see had an hourly cloud forecast. However Home Assistant has a sensor platform called Rest which can read in Json formatted data and https://openweathermap.org/api can provide forecast data in Json form.

In order to use the API you need to register with https://openweathermap.org/api. Then using the following yaml config, replacing {my_latitude}={my_longitude}={MY_API_KEY} with your latitude, longitude and API key the forecast data will be read every hour.

sensor:
  - platform: rest
    name: openweather_report
    json_attributes:
      - current
      - daily
      - hourly
    value_template: "{{ value_json['current']['dt'] | timestamp_custom('%Y-%m-%d %H:%M', true) }}"
    resource: https://api.openweathermap.org/data/2.5/onecall?lat=<strong>{my_latitude}</strong>=<strong>{my_longitude}</strong>=<strong>{MY_API_KEY}</strong>&units=metric&lang=en
    scan_interval: 3600
Code language: HTML, XML (xml)

Next the data needs to be extracted and individual sensors created. In the code examples below I’ve created 24 hourly cloud forecast sensors, ‘hourly‘)[0].clouds is the current hour ‘hourly‘)[0].clouds is the forecast for 1 hours time and so on.

  - platform: template
    sensors:
      openweather_cloud_cover_now:
        friendly_name: "Current Cloud Cover"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[0].clouds</strong> }}"
      openweather_cloud_cover_1:
        friendly_name: "Cloud Cover in 1 Hour"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[1].clouds</strong> }}"
      openweather_cloud_cover_2:
        friendly_name: "Cloud Cover in 2 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[2].clouds</strong> }}"
      openweather_cloud_cover_3:
        friendly_name: "Cloud Cover in 3 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[3].clouds</strong> }}"
      openweather_cloud_cover_4:
        friendly_name: "Cloud Cover in 4 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[4].clouds</strong> }}"
      openweather_cloud_cover_5:
        friendly_name: "Cloud Cover in 5 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[5].clouds</strong> }}"
      openweather_cloud_cover_6:
        friendly_name: "Cloud Cover in 6 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[6].clouds</strong> }}"
      openweather_cloud_cover_7:
        friendly_name: "Cloud Cover in 7 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[7].clouds</strong> }}"
      openweather_cloud_cover_8:
        friendly_name: "Cloud Cover in 8 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[8].clouds</strong> }}"
      openweather_cloud_cover_9:
        friendly_name: "Cloud Cover in 9 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[9].clouds</strong> }}"
      openweather_cloud_cover_10:
        friendly_name: "Cloud Cover in 10 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[10].clouds </strong>}}"
      openweather_cloud_cover_11:
        friendly_name: "Cloud Cover in 11 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[11].clouds</strong> }}"
      openweather_cloud_cover_12:
        friendly_name: "Cloud Cover in 12 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[12].clouds</strong> }}"
      openweather_cloud_cover_13:
        friendly_name: "Cloud Cover in 13 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[13].clouds</strong> }}"
      openweather_cloud_cover_14:
        friendly_name: "Cloud Cover in 14 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[14].clouds</strong> }}"
      openweather_cloud_cover_15:
        friendly_name: "Cloud Cover in 15 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[15].clouds</strong> }}"
      openweather_cloud_cover_16:
        friendly_name: "Cloud Cover in 16 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[16].clouds</strong> }}"
      openweather_cloud_cover_17:
        friendly_name: "Cloud Cover in 17 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[17].clouds</strong> }}"
      openweather_cloud_cover_18:
        friendly_name: "Cloud Cover in 18 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[18].clouds</strong> }}"
      openweather_cloud_cover_19:
        friendly_name: "Cloud Cover in 19 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[19].clouds</strong> }}"
      openweather_cloud_cover_20:
        friendly_name: "Cloud Cover in 20 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[20].clouds</strong> }}"
      openweather_cloud_cover_21:
        friendly_name: "Cloud Cover in 21 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[21].clouds</strong> }}"
      openweather_cloud_cover_22:
        friendly_name: "Cloud Cover in 22 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[22].clouds</strong> }}"
      openweather_cloud_cover_23:
        friendly_name: "Cloud Cover in 23 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>hourly</strong>')<strong>[23].clouds</strong> }}"

        Code language: HTML, XML (xml)

Other sensors can be created in the same way. ‘daily‘)[0].wind_speed is todays wind speed forecast and ‘daily‘)[1].wind_speed is tomorrows.

      openweather_wind_today:
        friendly_name: "Wind Speed Today"
        unit_of_measurement: 'mps'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>daily</strong>')<strong>[0].wind_speed</strong> }}"
      openweather_wind_tomorrow:
        friendly_name: "Wind Speed Tomorrow"
        unit_of_measurement: 'mps'
        value_template: "{{ state_attr('sensor.openweather_report', '<strong>daily</strong>')<strong>[1].wind_speed</strong> }}"Code language: HTML, XML (xml)

A full list of paths and potential weather forecast sensors can be worked out by parsing the Json output from the OpenWeatherMap API using a path finder like https://jsonpathfinder.com/.

I also needed to create one more template sensor to work out the average cloud cover for the day, the automation to decide whether or not the immersion should switch on will run at midnight and takes an average of the cloud cover forecast of the hours +9 to +16 which will be day time. This is the simple version I’m using for testing purposes but I think in future it will be modified to allow for longer days in summer and shorter days in winter.

template:
  - sensor:
      - name: "Cloud forecast Average"
        unit_of_measurement: "%"
        state: >
          
          {% set plus9h = states('sensor.openweather_cloud_cover_9') | float %}
          {% set plus10h = states('sensor.openweather_cloud_cover_10') | float %}
          {% set plus11h = states('sensor.openweather_cloud_cover_11') | float %}
          {% set plus12h = states('sensor.openweather_cloud_cover_12') | float %}
          {% set plus13h = states('sensor.openweather_cloud_cover_13') | float %}
          {% set plus14h = states('sensor.openweather_cloud_cover_14') | float %}
          {% set plus15h = states('sensor.openweather_cloud_cover_15') | float %}
          {% set plus16h = states('sensor.openweather_cloud_cover_16') | float %}
          
          {{ ((plus9h + plus10h + plus11h + plus12h + plus13h + plus14h + plus15h + plus16h ) / 8) | round(0, default=0) }}Code language: JavaScript (javascript)

The following yaml was added to my automations config to complete the immersion automation, it disables and enables the immersion automation based on average cloud cover percentage.

- id: 'weather based immersion'
  alias: Smart Weather Based Immersion On
  description: ''
  trigger:
  - platform: time
    at: 00:10:00
  condition: []
  action:
  - service: > 
      {% if states('sensor.cloud_forecast_average') | int < states('input_number.cloud_forecast') |int %}  
        homeassistant.turn_off
      {% else %}
        homeassistant.turn_on
      {% endif %}
    entity_id: automation.immersion_on_time
  mode: singleCode language: PHP (php)

The following is the raw yaml output from LoveLace and provides a GUI to provide monitoring and inputs to adjust all of the variables.

- icon: mdi:water-pump
    title: Hot Water
    badges:
      - entity: sensor.time
    cards:
      - cards:
          - entities:
              - entity: input_boolean.switch_immersion_timer
                name: Boost HW Immersion
              - entity: input_number.immersion_timer
                name: Immersion Minutes
              - entity: input_boolean.switch_hw_timer
                name: Boost HW Boiler
              - entity: input_number.hw_timer
                name: HW Boiler Minutes
              - entity: input_number.immersion_temp
                icon: mdi:thermometer
                name: Hot Water °C
            show_header_toggle: false
            type: entities
          - entity: sensor.temperature_sensor_32_0
            max: 100
            min: 0
            name: HW @ Taps
            severity:
              green: 40
              red: 50
              yellow: 45
            type: gauge
          - entity: sensor.temperature_sensor_31_0
            max: 100
            min: 0
            name: HW @ Boiler
            severity:
              green: 35
              red: 55
              yellow: 45
            theme: default
            type: gauge
          - entities:
              - entity: switch.immersion_heater
                icon: mdi:hot-tub
                name: Immersion
              - entity: switch.boiler
                name: Boiler
                icon: mdi:fire
              - entity: climate.hw_zone_thermostat
                icon: mdi:water-pump
                name: HW Zone
              - entity: sensor.temperature_sensor_30_0
                icon: mdi:weather-sunny
                name: HW @ Solar
            type: glance
        type: vertical-stack
      - entities:
          - entity: sensor.temperature_sensor_30_0
            name: Solar Temperature
          - entity: sensor.temperature_sensor_31_0
            name: Boiler Temperature
          - entity: sensor.temperature_sensor_32_0
            name: Taps Temperature
        hours_to_show: 24
        refresh_interval: 0
        title: Hot Water
        type: history-graph
      - entities:
          - entity: sensor.temperature_sensor_30_0
            name: Solar
        hours_to_show: 168
        refresh_interval: 0
        title: Solar HW Last 7 Days
        type: history-graph
      - type: entities
        entities:
          - entity: automation.smart_weather_based_immersion_on
            name: Smart Immersion Power Saver
          - entity: input_number.cloud_forecast
          - entity: automation.immersion_on_time
            name: Immersion Auto On.
          - entity: input_datetime.immersion_auto_on
            icon: mdi:clock-outline
            name: Immersion On time
          - entity: automation.hw_on_time
            name: HW Boiler Auto on
          - entity: input_datetime.hw_auto_on
            icon: mdi:clock-outline
            name: HW Boiler On timeCode language: CSS (css)

I thought this was a farming blog!

From the beginning my automation project started off as a project to sort out my disjointed and inefficient heating system controls and expanded out as a whole home/farm automation project. This new weather forecasting addition is no different and I can see potential for farming related projects, like weather notifications and automations for frost protection or closing doors and shutters when high winds are forecast.

An example of a notification for a weather event is in the following automations yaml. It will send a frost warning to my phone app if there is to be low temperatures.

#Frost Warning
- id: 'farm notifications 3'
  alias: Frost Warning
  description: ''
  trigger:
  - platform: numeric_state
    entity_id: sensor.openweather_temp_night_today
    below: '0'
  condition: []
  action:
  - device_id: !secret eds_phone
    domain: mobile_app
    type: notify
    title: ''
    message: Warning! Frost Tonight
  mode: singleCode language: PHP (php)

I’ve also added weather maps to my Farm Dashboard. Infrared and rain radar maps are taken from https://en.sat24.com/en/freeimages and can be added to Home Assistant as camera entities by adding the following to the configuration.yaml

#--------------------------Weather maps-----------------------------------------------
camera:
  - platform: generic
    still_image_url: https://api.sat24.com/animated/GB/rainTMC/3/GMT%20Standard%20Time/441208
    name: Rain Radar
    
  - platform: generic
    still_image_url: https://api.sat24.com/animated/GB/infraPolair/3/GMT%20Standard%20Time/4239410
    name: Infrared RadarCode language: PHP (php)

And the LovelLace yaml, which also includes an embedded iframe for https://www.ventusky.com/

  - title: Weather
    path: weather
    badges: []
    cards:
      - type: weather-forecast
        entity: weather.home_2
      - type: picture-glance
        title: Rain Map
        image: https://demo.home-assistant.io/stub_config/kitchen.png
        entities: []
        camera_image: camera.rain_radar
      - type: picture-glance
        title: Infrared
        image: https://demo.home-assistant.io/stub_config/kitchen.png
        entities: []
        camera_image: camera.infrared_radar
      - type: entities
        entities:
          - entity: sensor.date_time
          - entity: sensor.outside_temperature
            name: Current Temperature
          - entity: sensor.openweather_temp_day_today
          - entity: sensor.openweather_temp_night_today
          - entity: sensor.openweather_cloud_cover_now
            icon: mdi:weather-cloudy
          - entity: sensor.openweather_wind_today
            icon: mdi:windsock
          - entity: sensor.openweather_wind_tomorrow
            icon: mdi:windsock
      - type: iframe
        url: https://www.ventusky.com/?l=wind-10m#settings-main
        aspect_ratio: 200%Code language: JavaScript (javascript)
I recently setup a GitHub account and will be adding all code including Home Assistant yaml and Arduino Sketches used in my Farm and home automation projects.
Home-Assistant-Heating-Schedule
Home-Assistant-Weather-Based-Automations
Home-Assistant-based-Farm-Automation-and-Monitoring

Facebook Comments