Monthly Archives: August 2017

Use Environment Canada Weather forecast atom feed to decide whether to irrigate

By   August 20, 2017

I have more or less switched to using Home Assistant to automate things at the cabin.  One of the things I’ve had to do is integrate the Etherrain/8 from QuickSmart into HomeAssistant by creating a new component and switch module.  This is currently (as of this writing) on a branch waiting for release integration.

Now the next thing was to automate the irrigation.  HomeAssistant’s automation scripts take a bit of getting used to.. It’s certainly not very intuitive but it is what it is.

First the automation, to water the front beds at 7 AM on Mon/Wed/Fri if the chance of rain is <60%:

    - id: water_front_beds_on
      alias: Start Watering Front Beds mon/wed/fri at 7AM
      initial_state: on
      trigger:
        platform: time
        hours: 7
        minutes: 0
        seconds: 0
      condition:
        condition: and
        conditions:
          - condition: state
            entity_id: binary_sensor.rain_unlikely
            state: 'on'
          - condition: time
            weekday:
              - mon
              - wed
              - fri
      action:
        service: switch.turn_on
        entity_id: switch.front_beds

So the next question is likely “where does rain_unlikely come from”?  It’s here:

    binary_sensor:
      - platform: threshold
        name: rain_unlikely
        threshold: 59
        type: lower
        entity_id: sensor.environment_canada_pop
    
      - platform: mqtt
        state_topic: environment_canada/pop
        name: environment_canada_pop

Essentially, an MQTT message with a percentage that is the “probability of precipitation”.  But who generates this MQTT message?  In fact, nobody really.  This is just a placeholder sensor that holds the POP.  But something must populate this. Well, here’s an Appdaemon script written in Python:

    import appdaemon.appapi as appapi
    import feedparser
    import sys
    import time
    import datetime

    class EnvCanada(appapi.AppDaemon):

      def initialize(self):
        if "locator" in self.args:
          loc = self.args["locator"]
        else:
          loc = "ab-52"  # Default to Calgary
        if "hr" in self.args:
          hr = int(self.args["hr"])
        else:
          hr = 4
        if "ahead" in self.args:
          add=int(self.args["ahead"])
        else:
          add = 0

        myargs={}
        myargs["loc"] = loc
        myargs["add"] = add
        myargs["module"] = self.args["module"]
        # First run immediately
        h = self.run_in(self.get_pop, 1, **myargs)
        # Then schedule a runtime for the specified hour.
        runtime = datetime.time(hr, 0, 0)
        h = self.run_once(self.get_pop, runtime, **myargs)

      def get_pop(self, args):
        loc = args["loc"]
        add = args["add"]
        d=feedparser.parse('http://weather.gc.ca/rss/city/{0}_e.xml'.format(loc))
        weekdays=["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"]
        today = (weekdays[time.localtime().tm_wday+add])
        pop = 0
        for entry in iter(d.entries):
          if today in entry.title:
            if "howers" in entry.title:
              pop = 100
            if "POP" in entry.title:
              next=0
              for word in iter(entry.title.split(" ")):
                if next:
                  pop = int(word.rstrip("%"))
                if word == "POP":
                  next=1
        print("{0}: Got POP {1}".format(args["module"], pop))
        self.set_state("sensor.environment_canada_pop", state = pop)

      def terminate(self):
        self.log("Terminating!", "INFO")

This essentially grabs the Atom feed from Environment Canada, looks for the word “Showers” or “showers” or “POP” and generates that percentage.  It then reaches under the skirt of Home Assistant and populates the above mentioned ‘MQTT sensor’.. I really wish I could think of a better way to do that.

Just for the sake of completion; here is the AppDaemon configuration to get it all started:

  EnvCanada:
  module: environment_canada
  class: EnvCanada
  hr: 5
  ahead: 0
  locator: ab-53

The ‘ahead’ attribute is “how many days ahead to determine the POP.  Ie: at 0, it returns todays probability of precipitation.  At 1, it will return tomorrow’s.   the ‘hr’ attribute is when AppDaemon should run this script.  In this case, at 05:00AM.  The ‘locator’ is the portion of the URL that specifies which Environment Canada weather location to use.  ‘ab-53’ is Sundre Alberta.

 

Hope that helps someone.