OzPoll - Australian Pollen Forecast (Integration)

Dropping back from version 5 to 4 appears to bring back the thunderstorm asthma forecast.
I’ll update the main solution in a sec.
If poeple could keep an eye on it vs the webpage and let me know if they spot any issues that would be tops.

Use:
https://api.pollenforecast.com.au/app/json/app_data.php?app=1&version=4
Not:
https://api.pollenforecast.com.au/app/json/app_data.php?app=1&version=5

image

This also validates against the app. So all good.
image

I think the code for the dashboard tiles is wrong in your master solution post. Icons weren’t working.

Here’s my code and the icons seem to be ok. Using V4 API.

type: horizontal-stack
show_name: true
show_icon: true
show_state: true
title: Pollen Count and Forecast
cards:
  - type: custom:button-card
    entity: sensor.melbourne_pollen_forecast_api
    state_display: >
      [[[return
      (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[0].pollen_level);]]]
    label: |
      [[[return 'Pollen Today';]]]
    icon: |
      [[[
        if ((states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[0].pollen_level == 'LOW') || (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[0].pollen_level == 'Low'))
          return "mdi:emoticon-happy";
        if ((states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[0].pollen_level == 'MODERATE') || (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[0].pollen_level == 'Moderate'))
          return "mdi:emoticon-neutral";
        if ((states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[0].pollen_level == 'HIGH') || (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[0].pollen_level == 'High'))
          return "mdi:emoticon-sad";
        if ((states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[0].pollen_level == 'EXTREME') || (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[0].pollen_level == 'Extreme'))
          return "mdi:emoticon-angry";
        else
          return "mdi:help-circle";
      ]]]
    show_label: true
    show_state: true
    show_name: false
    size: 70%
    aspect_ratio: 2/1
    layout: icon_state
    styles:
      name:
        - font-weight: bold
        - font-size: 0.5vw
        - color: grey
      icon:
        - color: |
            [[[
              if ((states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[0].pollen_level == 'LOW') || (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[0].pollen_level == 'Low'))
                return 'lime';
              if ((states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[0].pollen_level == 'MODERATE') || (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[0].pollen_level == 'Moderate'))
                return 'yellow';
              if ((states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[0].pollen_level == 'HIGH') || (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[0].pollen_level == 'High'))
                return 'orange';
              if ((states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[0].pollen_level == 'EXTREME') || (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[0].pollen_level == 'Extreme'))
                return 'red';
              else
                return 'grey';
            ]]]
      label:
        - font-weight: bold
        - font-size: 0.8vw
        - color: white
  - type: custom:button-card
    entity: sensor.melbourne_pollen_forecast_api
    state_display: >
      [[[return
      (states['sensor.melbourne_pollen_forecast_api'].attributes.my_district_asthma_forecast_today[0]);]]]
    label: |
      [[[return 'Thunderstorm Asthma Today';]]]
    icon: |
      [[[
        if ((states['sensor.melbourne_pollen_forecast_api'].attributes.my_district_asthma_forecast_today[0] == 'low') || (states['sensor.melbourne_pollen_forecast_api'].attributes.my_district_asthma_forecast_today[0] == 'LOW'))
          return "mdi:emoticon-happy";
        if ((states['sensor.melbourne_pollen_forecast_api'].attributes.my_district_asthma_forecast_today[0] == 'moderate') || (states['sensor.melbourne_pollen_forecast_api'].attributes.my_district_asthma_forecast_today[0] == 'MODERATE'))
          return "mdi:emoticon-neutral";
        if ((states['sensor.melbourne_pollen_forecast_api'].attributes.my_district_asthma_forecast_today[0] == 'high') || (states['sensor.melbourne_pollen_forecast_api'].attributes.my_district_asthma_forecast_today[0] == 'HIGH'))
          return "mdi:emoticon-sad";
        if ((states['sensor.melbourne_pollen_forecast_api'].attributes.my_district_asthma_forecast_today[0] == 'extreme') || (states['sensor.melbourne_pollen_forecast_api'].attributes.my_district_asthma_forecast_today[0] == 'EXTREME'))
          return "mdi:emoticon-angry";
        else
          return "mdi:help-circle";
      ]]]
    show_label: true
    show_state: true
    show_name: false
    size: 70%
    aspect_ratio: 2/1
    layout: icon_state
    styles:
      name:
        - font-weight: bold
        - font-size: 0.5vw
        - color: grey
      icon:
        - color: |
            [[[
              if ((states['sensor.melbourne_pollen_forecast_api'].attributes.my_district_asthma_forecast_today[0] == 'low') || (states['sensor.melbourne_pollen_forecast_api'].attributes.my_district_asthma_forecast_today[0] == 'LOW'))
                return 'lime';
              if ((states['sensor.melbourne_pollen_forecast_api'].attributes.my_district_asthma_forecast_today[0] == 'moderate') || (states['sensor.melbourne_pollen_forecast_api'].attributes.my_district_asthma_forecast_today[0] == 'MODERATE'))
                return 'yellow';
              if ((states['sensor.melbourne_pollen_forecast_api'].attributes.my_district_asthma_forecast_today[0] == 'high') || (states['sensor.melbourne_pollen_forecast_api'].attributes.my_district_asthma_forecast_today[0] == 'HIGH'))
                return 'orange';
              if ((states['sensor.melbourne_pollen_forecast_api'].attributes.my_district_asthma_forecast_today[0] == 'extreme') || (states['sensor.melbourne_pollen_forecast_api'].attributes.my_district_asthma_forecast_today[0] == 'EXTREME'))
                return 'red';
              else
                return 'grey';
            ]]]
      label:
        - font-weight: bold
        - font-size: 0.8vw
        - color: white
      state:
        - text-transform: uppercase

Mine are working fine. Perhaps I made changes and forgot to update the post, but I don’t think so.

Thanks for reporting. I’ll take a closer look soonish and try to clarify what’s happening.

This week if looking a bit grim.

I prob should optimize the text size for mobile too.

I’ve dropped in a fresh copy of my working lovelace config and added an update note to that solution post about whats going on (in summary, no clue, quite possibly my bad version management when i do slap-dash fixes.).

Thanks for letting me know. Hopefully it’s ok now for other users…

Just found this topic - what a great idea - have been struggling with pollen and storm asthma for a couple of weeks now, so will be interesting to see if I can correlate the forecasting with how I’m feeling - awesome bit of coding!

1 Like

It’s really ramping up this week!

Yep definitely an annoying few days of extreme pollen conditions. Running my purifiers all day along with the split system with plasma filter. Helping to a degree. Maybe I should automate it based on the forecasts

1 Like

Mine does exactly that. Air purifiers go on and my windows automatically close too;)

Bedroom purifier on in sleep mode at night if today/tomorrow moderate or above.

Announcements when I rise/go to bed.

that’s a little bit un-wife friendly in my house - we don’t have anything IOT in the bedroom aside from phones charging…

I’ve noticed that the REST call doesn’t always work reliably - aside from restarting HA, any other suggestions? Or is it that the service is exceeding number of polls maybe?

Getting an Error -3 from the call

Error fetching data: https://api.pollenforecast.com.au/app/json/app_data.php?app=1&version=4 failed with [Errno -3] Try again

1 Like

Yeah not sure what’s up there.

How often often are you hitting it?

I just used your example and dropped it into my config, so every 600 seconds

1 Like

I quickly checked my logs and I seem to get the same too sometimes.

Are you able to share how you did the automations? I’m not sure how I trigger something from the API data as it’s not stored in discrete sensors. Unfortunately beyond my knowledge but keen to learn.

Here’s some automation examples.

I ran out of characters in the main solution post so I’ll maintain these here.
These are excerpts from my more complex config so let me know if they don’t work) :slight_smile:


Make some binary sensors in your config. You can use these as triggers in your automations.

binary_sensor:
 #Create some binary sensors from the forecasts
  - platform: template
    sensors:
      climate_alert_pollen_hayfever:
        friendly_name: Pollen Alert Today
        device_class: "problem"
        icon_template: mdi:flower-pollen
        #Adjust to set your own tolerances/thresholds
        value_template: >-
          {{
          states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[0].pollen_level == 'Moderate'
            or
          states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[0].pollen_level == 'High'
            or
          states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[0].pollen_level == 'Extreme'
          }}
      climate_alert_pollen_hayfever_tommorrow:
        friendly_name: Pollen Alert Tomorrow
        device_class: "problem"
        icon_template: mdi:flower-pollen
        value_template: >-
          {{
          states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[1].pollen_level == 'Moderate'
            or
          states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[1].pollen_level == 'High'
            or
          states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[1].pollen_level == 'Extreme'
          }}

A script which triggers an announcment on my Google homes and posts to my homes Telegram thread. You can use something simlar with TTS etc.

pollen_report:
  sequence:
  #Announce Pollen today
  - service: rest_command.assistant_broadcast 
    data:
      command: "The pollen forecast today is {{states.sensor.melbourne_pollen_forecast_api.attributes.melbourne_6day_pollen_forecast.days[0].pollen_level}}"
  #Pollen 6 day outlook
  - service: rest_command.assistant_broadcast
    data:
      command: >-
        {{states.sensor.melbourne_pollen_forecast_api_6day_summary_stats.attributes.six_day_outlook_description}}
  - service: notify.mothershiptelegramannouncements
    data:
        title: "*Pollen Outlook*"
        message: {{states.sensor.melbourne_pollen_forecast_api_6day_summary_stats.attributes.six_day_outlook_description}}

In my bedtime/arrive home scripts, turn on purifiers if pollen is alerting.

sleepmode_routines:
  alias: Sleep Mode Routines
  sequence:
##Pollen: Turn on Bedroom air purifier if pollen is alerting
  - if:
      or:
        - "{{states.binary_sensor.climate_alert_pollen_hayfever.state == 'on'}}"
        - "{{states.binary_sensor.climate_alert_pollen_hayfever_tommorrow.state == 'on'}}" 
    then:
      - service: switch.turn_on
        entity_id: switch.kogan_air_purifier_sleep_mode_2
      - service: rest_command.assistant_broadcast 
        data:
          command: "Turning on the bedroom air purifier for pollen"

day_time_routines:
  alias: Activate Daytime Routines
  sequence:
#Pollen
  - if:
     - "{{states.binary_sensor.climate_alert_pollen_hayfever.state == 'on'}}"           
    then:
      - service: fan.set_percentage
        target:
          entity_id: fan.mi_air_purifier_3_3h
        data:
          percentage: 33
      - service: rest_command.assistant_broadcast 
        data:
          command: "Turning on the air purifier for pollen"
  

In an automation, set purifier fan speed depending on pollen level

- id: '121124152535'
  alias: Turn on purifier for pollen
  trigger:
  - platform: state
    entity_id: sensor.melbourne_pollen_forecast_api_6day_summary_stats
  - platform: state
    entity_id: input_select.operating_mode
  condition:
    condition: template
    value_template: '{{not is_state("input_select.operating_mode", "Away")}}'
  action:
  - choose:
      - conditions: '{{is_state("input_select.operating_mode", "Sleep")}}'
        sequence:
          - service: fan.set_percentage
            target:
              entity_id: fan.mi_air_purifier_3_3h
            data_template:
              percentage: >
                {%- if is_state("sensor.melbourne_pollen_forecast_today", "Extreme") -%} 66
                {% elif is_state("sensor.melbourne_pollen_forecast_today", "Low") %} 0
                {%- else -%}
                33
                {%- endif -%}
    default:
      - service: fan.set_percentage
        target:
          entity_id: fan.mi_air_purifier_3_3h
        data_template:
          percentage: >
            {% if is_state("sensor.melbourne_pollen_forecast_today", "Moderate") %} 33
            {% elif is_state("sensor.melbourne_pollen_forecast_today", "High") %} 66
            {% elif is_state("sensor.melbourne_pollen_forecast_today", "Low") %} 0
            {% elif is_state("sensor.melbourne_pollen_forecast_today", "Extreme") %} 100
            {% endif %}
2 Likes

Added to post above;)

1 Like

Awesome thanks for sharing

New fix for API change (for Asthma forecast) implemented in main solution post:

  1. 2022-11-27 Asthma forecast randomly changed from div7 to div8, breaking the sensor. So that was adjusted in 2 places.

I tried setting this up today but noticed the values returned from the API were inconsistent with those on the direct webpage (melbournepollen.com.au). That’s a little troubling, maybe their API is unreliable? I assume the main webpage data is correct and their undocumented API is acting weird.

Using Home Assistant’s native scrape integration, I was able to fetch the default grass pollen value for “VIC: Melbourne” from the top of the main webpage, and also the first thunderstorm asthma entry (which corresponds with “Central”).

I’m sure this will break if they change their website design, and it doesn’t provide the 6-day forecast or support different regions in Victoria. But for anyone in Melbourne looking for some simple sensors to perform automations from (eg. turn on air purifiers, open/close windows and so on), this might do the trick as an interim solution until they sort out their API.

sensor:
  - platform: scrape
    name: "Pollen Forecast"
    resource: https://www.melbournepollen.com.au/
    scan_interval: 3600
    select: "#inseason .pollen-level" # Primary grass pollen value, assumes "VIC: Melbourne" is the default selection
    #select: "#district-pollen-div .forecast-value:first-child" # First regional pollen value, assumes "Central" is first entry
  - platform: scrape
    name: "Thunderstorm Asthma Forecast"
    resource: https://www.melbournepollen.com.au/
    scan_interval: 3600
    select: "#tae-div .forecast-value:first-child" # First regional thunderstorm asthma value, assumes "Central" is first entry

(The above is in the old config yaml format as I’m running an older HA install.)

The original solution in the OP scraped the webpage like you’re doing.

They used to offer a 5 day forecast on their webpage but they removed it when they started monetising via the app.

I’ve validated the API against the paid app and it seems consistent.

So I believe it’s the webpage which is inaccurate/lacking maintenance now and not the API. Therefore I don’t recommend your solution.