Melbourne Pollen Forecast Scrape Sensor and Lovelace "Card"

Hi - great work maintaining this - I find the pollen card very helpful.

I would love to scrape the thunderstorm asthma warning from the same page as well - I’ve tried (and failed) using the css selector in chrome to replicate what you’ve done but I’m out of my depth.

I had a quick go but failed too. I think I’d failed previously too which is why I didn’t put it up.
I feel like this is right but it’s not working for me.

      - unique_id: melbourne_thunderstorm_asthma_today
        name: Thunderstorm Asthma Forecast Today
        select: '#tae-div > div > div > div > div > div > div.uk-grid-match.uk-child-width-1-2\@s.uk-text-center.uk-grid-collapse.uk-grid > div.uk-first-column > div:nth-child(1) > div:nth-child(2) > div'
        value_template: '{{ value| trim}}'
        attributes:
          - name: Website Last Updated
            select: '#district-pollen-div > div > div > div > div > div > div.uk-grid-match.uk-child-width-1-2\@s.uk-text-center.uk-grid-collapse.uk-grid > div:nth-child(1) > div.ta-notice'
            value_template: "{{ value| replace('Last updated:', '')}}"
        icon: >-
          {% if value == 'Low' %}
            mdi:emoticon-happy
          {% elif value == 'Moderate' %}
            mdi:emoticon-neutral
          {% elif value == 'High' %}
            mdi:emoticon-sad
          {% elif value == 'Extreme' %}
            mdi:emoticon-angry
          {% else %}
            mdi:help-circle
          {% endif %}

thanks for trying. that looks similar to what I was doing

1 Like

Maybe try this link.

http://api.pollenforecast.com.au/app/json/app_data.php?app=1&version=2

1 Like

Oh wow. What’s the deal? :slight_smile:

No deal. Just an unofficial api that can easily be found if you know how to :wink:

Legend. I actually had a dig around for it too but couldn’t figure it out.

thanks, this is super helpful!

I’m chipping away at it and making some progress. Don’t really know what I’m doing though.

I’ve been trying to hack something together this morning to use the asthma forecast.

The HTML nested within the JSON makes it hard to work with.

my solution at the moment is this:
I’m using a shell command to extract just the asthma forecast HTML from the API (this is div 5)
asthma_refresh: 'curl "https://api.pollenforecast.com.au/app/json/app_data.php?app=1&version=2" | jq .div5 >/config/www/asthma.html'

I’m running this as a service every 30 mins.

I’m then running multiscrape over the output:

  - resource: http://[IP address]/local/asthma.html
    scan_interval: 3600 #3600 sec = hr
    name: Asthma forecast
    sensor:
      - unique_id: asthma_forecast_scrape
        name: Asthma forecast 
        select: '#\\\"ta-forecast-table\\\" > tbody > tr:nth-child(1) > td.\\\"center\\\" > p'
        attributes:
          - name: Website Last Updated
            select: 'body > div > div > div:nth-child(8) > p'

This is not a neat way to do it, but it does give me a sensor in homeassistant.

Nice progress. Better than my attempts. Yeah I had the same struggles with the html nested in the json.

I managed to get the forecast html in as text using the rest sensor, then I was tinkering with some very gross parsing of the HTML as text, despite finding some hilarious warnings.

Edit: Added detail

Like If you have this:

rest:
  - authentication: basic
    scan_interval: 600
    resource: https://api.pollenforecast.com.au/app/json/app_data.php?app=1&version=2
    headers:
       Accept: application/json
       Content-Type: application/xml
    sensor:
      - name: "Melbourne Pollen test"
        value_template: "OK"
        json_attributes:
          - "forecastpage"
          - "div5"
          - "share"

Then you get a sensor with the requested attributes that have the massive html text as attributes (I was hoping HA might recognise it and parse it)

Then I was going to try to somehow parse the html from each of the above json_attributes it into some simplified json that could be stored nested and then queried. I dunno if that makes sense.

In template developer tools

{% set myxml = states.sensor.melbourne_pollen_test.attributes.div5 %}
{{ 
myxml 
|replace('\n', '*+*+')
|striptags
|replace(' *+*+ *+*+ *+*+ ', '\n')
|replace('*+*+ *+*+ *+*+ ', '')
|replace('*+*+ *+*+ ', ': ')
|replace('*+*+', '')
}}

Output of above template starting to look a bit like json pairs.

Thunderstorm Asthma Forecast :  
  
 District  Risk of thunderstorm asthma
: Central : low
East Gippsland : low
Mallee : low
North Central : low
North East : low
Northern Country : low
South West : low
West and South Gippsland : low
Wimmera : low

 Note: The above epidemic thunderstorm asthma forecast information was provided by the Victorian Department of Health and Human Services and the Bureau of Meteorology. For more information pertaining to these forecasts visit this website.  Last updated: 2021-11-22 14:00:00; Current date: 2021-11-22

Update #2: On my “steaming pile of poo solution”
With the same rest sensor above, you can then create a template sensor like this to do some dogy parsing of the html into json

sensor:
  - platform: template
    sensors:
      melbourne_pollen_forecast_api_dev:
        friendly_name: Melbourne Pollen Forecast API Dev
        value_template: 'Ok' 
        attribute_templates:
          pollen_forecast: >-
            {% set myxml = states.sensor.melbourne_pollen_test.attributes.forecastpage %}
            {{ 
            '{\n' +
            myxml 
            |replace('Melbourne Pollen Forecast', '"data": [')
            |replace('<H2 ', '*NL*{*NL*"day_name":"<H1 ')
            |replace('</h2>', '</H2>",*NL* ')
            |replace('<P', '"date":"<P')
            |replace('P>', '<\/P>",*NL* ')
            |replace('<div class="pollen-forecast-level', '"pollen_level":"<<div class="pollen-forecast-level')
            |replace('</span>', '"</span>*NL*},*NL* ')
            |striptags
            |replace('*NL*', '\n') + ']\n}'
            }}

Which will look like this:

{
  "data": [
    {
      "day_name": "Monday",
      "date": "22 November 2021",
      "pollen_level": "HIGH"
    },
    {
      "day_name": "Tuesday",
      "date": "23 November 2021",
      "pollen_level": "HIGH"
    },
    {
      "day_name": "Wednesday",
      "date": "24 November 2021",
      "pollen_level": "MODERATE"
    },
    {
      "day_name": "Thursday",
      "date": "25 November 2021",
      "pollen_level": "LOW"
    },
    {
      "day_name": "Friday",
      "date": "26 November 2021",
      "pollen_level": "MODERATE"
    },
    {
      "day_name": "Saturday",
      "date": "27 November 2021",
      "pollen_level": "MODERATE"
    }
  ]
}

Then you can access values like this:

{{states.sensor.melbourne_pollen_forecast_api_dev.attributes.pollen_forecast.data[1].pollen_level}}

Returns "HIGH" in template Developer tool

if it works, it works! you’ve made great progress

1 Like

This is the main post which I will try to keep up to date with a working solution.

The solution has been breaking periodically due to changes in the unofficial API and the pretty fragile nature of my solution. I’m no coding guru I just slapped together something pretty hacky.

But don’t worry I’m pretty invested in keeping it working if possible (self-interest;).

I’ve added change notes at the bottom of this post, so hopefully you can check if you are up to date with changes before flagging an issue.


The main outputs are a bunch sensors and a “card”

image

You need a rest sensor in your config which pulls in chucks of the massive html which is nested in json attributes.

rest:
  - authentication: basic
    scan_interval: 600
    resource: https://api.pollenforecast.com.au/app/json/app_data.php?app=1&version=4
    sensor:
      - name: "Melbourne Pollen API HTML"
        value_template: "OK"
        json_attributes:
          - "forecastpage"
          - "div8"
          # - "div7"

Then two template sensors in your config parses the html with regex (probably fragile and a bad idea).

  1. The ‘melbourne_pollen_forecast_api’ sensor covers the basics and feeds the card.
  2. The ‘melbourne_pollen_forecast_api_6day_summary_stats’ sensor has some summary stats about the 6 days ahead, which you can use to build up alerts and announcments. For example I have this announced when rising in the morning and at bedtime. It helps me plan ahead. It’s still not quite right.

six_day_outlook_description: The 6 day pollen outlook level is Low. There are 1 moderate days, 0 high days and 0 extreme days. Tommorrow is Low, Saturday is Low, and Sunday is Low.

  - platform: template
    sensors:
      melbourne_pollen_forecast_api:
        friendly_name: Melbourne Pollen Forecast via API
        value_template: ''
        attribute_templates:
          melbourne_6day_pollen_forecast: >-
            {% set forecastpageHTML = states.sensor.melbourne_pollen_api_html.attributes.forecastpage %}
            {% set LowerForecastpageHTML = forecastpageHTML|lower  %}
            {{ 
            '{\n' +
            LowerForecastpageHTML
            |replace('monday', 'Mon')
            |replace('tuesday', 'Tue')
            |replace('wednesday', 'Wed')
            |replace('thursday', 'Thu')
            |replace('friday', 'Fri')
            |replace('saturday', 'Sat')
            |replace('sunday', 'Sun')
            |replace('melbourne pollen forecast', '"days": [')
            |replace('<h2 ', '*nl*{*nl*"day_short_name":"<h1 ')
            |replace('</h2>', '</h2>",*nl* ')
            |replace('<p', '"date":"<p')
            |replace('p>', '<\/p>",*nl* ')
            |replace('<div class="pollen-forecast-level', '"pollen_level":"<<div class="pollen-forecast-level')
            |replace('low', 'Low"},')
            |replace('moderate', 'Moderate"},')
            |replace('high', 'High"},')
            |replace('extreme', 'Extreme"},')
            |striptags
            |replace('*nl*', '\n') + ']\n}'
            }}    
            
          my_district_asthma_forecast_today: >-
            {% set myDistrict =  'Central' %}
            {% set asthmaForecastHTML = states.sensor.melbourne_pollen_api_html.attributes.div8  %}
            {% set myDistrictasthmaForecast = asthmaForecastHTML
            |replace('\r\n','')
            |replace('>' + myDistrict  + '</td>', '>x' + myDistrict + 'x<')
            | regex_findall(find='>x' + myDistrict + 'x<'+'([\\s\\S]*?)</p>', ignorecase=False)
            |striptags
            |replace(' ','')
            %}
            {{myDistrictasthmaForecast}}
            #Change myDistrict value above to one of: 
            # Central
            # East Gippsland
            # Mallee
            # North Central
            # North East
            # Northern Country
            # South West
            # West and South Gippsland
            # Wimmera
      melbourne_pollen_forecast_api_6day_summary_stats:
        friendly_name: Melbourne Pollen Forecast 6 Day Summary Stats
        #Todo: Comment code properly
        value_template: >-
          {% set count_low = namespace(count = 0) %}
          {% for days in states.sensor.melbourne_pollen_forecast_api.attributes.melbourne_6day_pollen_forecast.days %}
              {%- if days.pollen_level == "Low" -%}
                 {% set count_low.count = count_low.count+1 %}
              {%- endif -%}
          {% endfor %}
          {% set count_moderate = namespace(count = 0) %}
          {% for days in states.sensor.melbourne_pollen_forecast_api.attributes.melbourne_6day_pollen_forecast.days %}
              {%- if days.pollen_level == "Moderate" -%}
                 {% set count_moderate.count = count_moderate.count+1 %}
              {%- endif -%}
          {% endfor %}
          {% set count_high = namespace(count = 0) %}
          {% for days in states.sensor.melbourne_pollen_forecast_api.attributes.melbourne_6day_pollen_forecast.days %}
              {%- if days.pollen_level == "High" -%}
                 {% set count_high.count = count_high.count+1 %}
              {%- endif -%}
          {% endfor %}
          {% set count_extreme = namespace(count = 0) %}
          {% for days in states.sensor.melbourne_pollen_forecast_api.attributes.melbourne_6day_pollen_forecast.days %}
              {%- if days.pollen_level == "Extreme" -%}
                 {% set count_extreme.count = count_extreme.count+1 %}
              {%- endif -%}
          {% endfor %}
          {% set overall_pollen_rating =  (count_low.count*1 + count_moderate.count*2 + count_high.count*3 + count_extreme.count*4)/6 %}
          {%- if overall_pollen_rating <= 1 -%}
                {% set overall_pollen_level =  'Low' %}
          {%- elif overall_pollen_rating <= 2 -%}
                {% set overall_pollen_level =  'Moderate' %}
          {%- elif overall_pollen_rating <= 3 -%}
                {% set overall_pollen_level =  'High' %}
          {%- elif overall_pollen_rating <= 4 -%}
                {% set overall_pollen_level =  'Extreme' %}
              {%- endif -%}
           {{overall_pollen_level}}
        attribute_templates:
          count_of_low_days: >-
              {% set count_low = namespace(count = 0) %}
                {% for days in states.sensor.melbourne_pollen_forecast_api.attributes.melbourne_6day_pollen_forecast.days %}
                    {%- if days.pollen_level == "Low" -%}
                      {% set count_low.count = count_low.count+1 %}
                    {%- endif -%}
                {% endfor %}
              {{count_low.count}}
          count_of_moderate_days: >-
              {% set count_moderate = namespace(count = 0) %}
              {% for days in states.sensor.melbourne_pollen_forecast_api.attributes.melbourne_6day_pollen_forecast.days %}
                  {%- if days.pollen_level == "Moderate" -%}
                     {% set count_moderate.count = count_moderate.count+1 %}
                  {%- endif -%}
              {% endfor %}
              {{count_moderate.count}}
          count_of_high_days: >-
              {% set count_high = namespace(count = 0) %}
              {% for days in states.sensor.melbourne_pollen_forecast_api.attributes.melbourne_6day_pollen_forecast.days %}
                  {%- if days.pollen_level == "High" -%}
                     {% set count_high.count = count_high.count+1 %}
                  {%- endif -%}
              {% endfor %}
              {{count_high.count}}
          count_of_extreme_days: >-
            {% set count_extreme = namespace(count = 0) %}
            {% for days in states.sensor.melbourne_pollen_forecast_api.attributes.melbourne_6day_pollen_forecast.days %}
                {%- if days.pollen_level == "Extreme" -%}
                   {% set count_extreme.count = count_extreme.count+1 %}
                {%- endif -%}
            {% endfor %}
            {{count_extreme.count}}
            
          six_day_outlook_description: >-
            The 6 day pollen outlook level is {{states.sensor.melbourne_pollen_forecast_api_6day_summary_stats.state}}. 
            There are {{states.sensor.melbourne_pollen_forecast_api_6day_summary_stats.attributes.count_of_moderate_days}} moderate days, 
            {{states.sensor.melbourne_pollen_forecast_api_6day_summary_stats.attributes.count_of_high_days}} high days and 
            {{states.sensor.melbourne_pollen_forecast_api_6day_summary_stats.attributes.count_of_extreme_days}} extreme days.
            Tommorrow is {{states.sensor.melbourne_pollen_forecast_api.attributes.melbourne_6day_pollen_forecast.days[1].pollen_level}},
            Saturday is 
            {% for days in states.sensor.melbourne_pollen_forecast_api.attributes.melbourne_6day_pollen_forecast.days %}
                {%- if days.day_short_name == "Sat" -%}
                   {{days.pollen_level}}
                {%- endif -%}
            {% endfor %}, and
            Sunday is 
            {% for days in states.sensor.melbourne_pollen_forecast_api.attributes.melbourne_6day_pollen_forecast.days %}
                {%- if days.day_short_name == "Sun" -%}
                   {{days.pollen_level}}
                {%- endif -%}
            {% endfor %}.

Then lots of jiggery-pokery in lovelace using the custom button-card (via HACS):

    # #### Melbourne Pollen Card ##############################################################################################################
          - type: vertical-stack
            cards:
              - type: horizontal-stack
                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')
                          return "mdi:emoticon-happy";
                        if (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')
                          return "mdi:emoticon-sad";
                        if (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.5/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')
                              return 'lime';
                            if (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')
                              return 'orange';
                            if (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')
                          return "mdi:emoticon-happy";
                        if (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')
                          return "mdi:emoticon-sad";
                        if (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.5/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')
                              return 'lime';
                            if (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')
                              return 'orange';
                            if (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
              - type: horizontal-stack
                cards:
                  - type: "custom:button-card"
                    entity: sensor.melbourne_pollen_forecast_api
                    label: >
                      [[[return (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[1].pollen_level);]]]
                    state_display: >
                      [[[return (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[1].day_short_name);]]]
                    icon: >
                      [[[
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[1].pollen_level == 'Low')
                          return "mdi:emoticon-happy";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[1].pollen_level == 'Moderate')
                          return "mdi:emoticon-neutral";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[1].pollen_level == 'High')
                          return "mdi:emoticon-sad";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[1].pollen_level == 'Extreme')
                          return "mdi:emoticon-angry";
                        else
                          return "mdi:help-circle";
                      ]]]
                    show_label: true
                    show_state: true
                    show_name: false                
                    size: 50%
                    aspect_ratio: 1.8/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[1].pollen_level == 'Low')
                              return 'lime';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[1].pollen_level == 'Moderate')
                              return 'yellow';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[1].pollen_level == 'High')
                              return 'orange';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[1].pollen_level == 'Extreme')
                              return 'red';
                            else
                              return 'grey';
                          ]]]
                      label:
                        - font-weight: bold
                        - font-size: 0.6vw
                        - color: white
                  - type: "custom:button-card"
                    entity: sensor.melbourne_pollen_forecast_api
                    label: >
                      [[[return (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[2].pollen_level);]]]
                    state_display: >
                      [[[return (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[2].day_short_name);]]]
                    icon: >
                      [[[
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[2].pollen_level == 'Low')
                          return "mdi:emoticon-happy";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[2].pollen_level == 'Moderate')
                          return "mdi:emoticon-neutral";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[2].pollen_level == 'High')
                          return "mdi:emoticon-sad";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[2].pollen_level == 'Extreme')
                          return "mdi:emoticon-angry";
                        else
                          return "mdi:help-circle";
                      ]]]
                    show_label: true
                    show_state: true
                    show_name: false                
                    size: 50%
                    aspect_ratio: 1.8/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[2].pollen_level == 'Low')
                              return 'lime';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[2].pollen_level == 'Moderate')
                              return 'yellow';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[2].pollen_level == 'High')
                              return 'orange';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[2].pollen_level == 'Extreme')
                              return 'red';
                            else
                              return 'grey';
                          ]]]
                      label:
                        - font-weight: bold
                        - font-size: 0.6vw
                        - color: white
                  - type: "custom:button-card"
                    entity: sensor.melbourne_pollen_forecast_api
                    label: >
                      [[[return (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[3].pollen_level);]]]
                    state_display: >
                      [[[return (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[3].day_short_name);]]]
                    icon: >
                      [[[
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[3].pollen_level == 'Low')
                          return "mdi:emoticon-happy";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[3].pollen_level == 'Moderate')
                          return "mdi:emoticon-neutral";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[3].pollen_level == 'High')
                          return "mdi:emoticon-sad";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[3].pollen_level == 'Extreme')
                          return "mdi:emoticon-angry";
                        else
                          return "mdi:help-circle";
                      ]]]
                    show_label: true
                    show_state: true
                    show_name: false                
                    size: 50%
                    aspect_ratio: 1.8/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[3].pollen_level == 'Low')
                              return 'lime';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[3].pollen_level == 'Moderate')
                              return 'yellow';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[3].pollen_level == 'High')
                              return 'orange';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[3].pollen_level == 'Extreme')
                              return 'red';
                            else
                              return 'grey';
                          ]]]
                      label:
                        - font-weight: bold
                        - font-size: 0.6vw
                        - color: white
                  - type: "custom:button-card"
                    entity: sensor.melbourne_pollen_forecast_api
                    label: >
                      [[[return (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[4].pollen_level);]]]
                    state_display: >
                      [[[return (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[4].day_short_name);]]]
                    icon: >
                      [[[
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[4].pollen_level == 'Low')
                          return "mdi:emoticon-happy";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[4].pollen_level == 'Moderate')
                          return "mdi:emoticon-neutral";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[4].pollen_level == 'High')
                          return "mdi:emoticon-sad";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[4].pollen_level == 'Extreme')
                          return "mdi:emoticon-angry";
                        else
                          return "mdi:help-circle";
                      ]]]
                    show_label: true
                    show_state: true
                    show_name: false                
                    size: 50%
                    aspect_ratio: 1.8/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[4].pollen_level == 'Low')
                              return 'lime';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[4].pollen_level == 'Moderate')
                              return 'yellow';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[4].pollen_level == 'High')
                              return 'orange';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[4].pollen_level == 'Extreme')
                              return 'red';
                            else
                              return 'grey';
                          ]]]
                      label:
                        - font-weight: bold
                        - font-size: 0.6vw
                        - color: white
                  - type: "custom:button-card"
                    entity: sensor.melbourne_pollen_forecast_api
                    label: >
                      [[[
                        return (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[5].pollen_level);
                      ]]]
                      
                      
                    state_display: >
                      [[[return (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[5].day_short_name);]]]
                    icon: >
                      [[[
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[5].pollen_level == 'Low')
                          return "mdi:emoticon-happy";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[5].pollen_level == 'Moderate')
                          return "mdi:emoticon-neutral";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[5].pollen_level == 'High')
                          return "mdi:emoticon-sad";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[5].pollen_level == 'Extreme')
                          return "mdi:emoticon-angry";
                        else
                          return "mdi:help-circle";
                      ]]]
                    show_label: true
                    show_state: true
                    show_name: false                
                    size: 50%
                    aspect_ratio: 1.8/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[5].pollen_level == 'Low')
                              return 'lime';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[5].pollen_level == 'Moderate')
                              return 'yellow';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[5].pollen_level == 'High')
                              return 'orange';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[5].pollen_level == 'Extreme')
                              return 'red';
                            else
                              return 'grey';
                          ]]]
                      label:
                        - font-weight: bold
                        - font-size: 0.6vw
                        - color: white

And there’s some automation examples here:

Change Notes:

  1. 2022-09-22: Updated for 2022.
  2. 2022-10-06: Fixed breaking change due to pollen forecast in API changing from title case to upper case (Low > LOW etc.)
  3. 2022-10-08: Reversed #2 above as it changed back! lol…
  4. It reversed yet again! So I built an initial handle for either case…
  5. 2022-10-22: Changed API version from 5 to 4 as 5 had asthma forecasts as “unavailable” whereas 4 appears to have them.
  6. Pasted in a fresh copy of the lovelace config.
  7. 2022-11-10: Added some automation examples on request
  8. 2022-11-27 Asthma forecast randomly changed from div7 to div8, breaking the sensor. So that was adjusted in 2 places.
  9. 2023-10-14: It’s broken again with no fix in sight ATM for the 6 day forecast. The API doesn’t seem to contain updated data.
3 Likes

Hey guys, Multiscrape is now also supporting json: Scrape sensor improved - scraping multiple values - #188 by danieldotnl

It might help you to merge your rest and template sensors into one.

1 Like

Appreciate the heads up @danieldotnl .

The thing with the api we are using is it actually has html nested within the JSON.

So we kind of need to be able to first do some JSON type selects and then do some HTML based selects on the results.

Any thoughts on if we can tackle this query chain with just Multi-scrape and the new features?

It would be great if so as our current solutions are clunky.

Thank you.

Thank you so much for this!!

For anyone playing in 2022 this still works :slight_smile:

1 Like

No prob. I’ll be revisiting it closer to spring, as I definitely would like it working.

They seem to change what data they offer almost annually.

I use it to plan my week, alert me about the day, close my windows, turn on my air purifier etc. Basically manage my exposure.

I’ve told the boss I’ll be trying to work from home on Extreme days etc.

Just doing some testing on this. Seems a few minor changes are required for this year.

  1. Change api version from version 2 to version 5.
  2. Add div7. I think you can remove div5. Looks like Thunderstorm asthma moved from div5 to div7.
rest:
  - authentication: basic
    scan_interval: 600
    resource: https://api.pollenforecast.com.au/app/json/app_data.php?app=1&version=5
    sensor:
      - name: "Melbourne Pollen API HTML"
        value_template: "OK"
        json_attributes:
          - "forecastpage"
          - "div5"
          - "div7"
          - "share"

Make the change in this section too:

          my_district_asthma_forecast_today: >-
            {% set myDistrict =  'Central' %}
            {% set asthmaForecastHTML = states.sensor.melbourne_pollen_api_html.attributes.div7  %}
            {% set myDistrictasthmaForecast = asthmaForecastHTML

Then we seem to be running again.
image

Not sure if the Asthma info will becoem availabe as we get into the season.

HI

I have manged to get both the API and HtML working.
But for some reason when I try and add it to Lovelave, the code fails

ButtonCardJSTemplateError: TypeError: Cannot read properties of undefined (reading '0') in 'return (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.d...'

I pretty much copied the lovelace card, so not sure what exactly, i am doing wrong

Thanks as always

Could you provide a few more details please and I can help take a look?

A few basic first checks…

Does the sensor.melbourne_pollen_forecast_api look like this?

Can you get a basic custom:button-card working with another unrelated sensor? And are you on the latest version?

Also give this a try in case I debugged something and forgot to update earlier configs. Also try smaller parts of it…

    # #### Melbourne Pollen Card ##############################################################################################################
          - type: vertical-stack
            cards:
              - type: horizontal-stack
                cards:
                   #mother Mode
                  - 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')
                          return "mdi:emoticon-happy";
                        if (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')
                          return "mdi:emoticon-sad";
                        if (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.5/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')
                              return 'lime';
                            if (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')
                              return 'orange';
                            if (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
                   #mother Mode
                  - 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')
                          return "mdi:emoticon-happy";
                        if (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')
                          return "mdi:emoticon-sad";
                        if (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.5/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')
                              return 'lime';
                            if (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')
                              return 'orange';
                            if (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
              - type: horizontal-stack
                cards:
                  - type: "custom:button-card"
                    entity: sensor.melbourne_pollen_forecast_api
                    label: >
                      [[[return (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[1].pollen_level);]]]
                    state_display: >
                      [[[return (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[1].day_short_name);]]]
                    icon: >
                      [[[
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[1].pollen_level == 'Low')
                          return "mdi:emoticon-happy";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[1].pollen_level == 'Moderate')
                          return "mdi:emoticon-neutral";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[1].pollen_level == 'High')
                          return "mdi:emoticon-sad";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[1].pollen_level == 'Extreme')
                          return "mdi:emoticon-angry";
                        else
                          return "mdi:help-circle";
                      ]]]
                    show_label: true
                    show_state: true
                    show_name: false                
                    size: 50%
                    aspect_ratio: 1.8/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[1].pollen_level == 'Low')
                              return 'lime';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[1].pollen_level == 'Moderate')
                              return 'yellow';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[1].pollen_level == 'High')
                              return 'orange';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[1].pollen_level == 'Extreme')
                              return 'red';
                            else
                              return 'grey';
                          ]]]
                      label:
                        - font-weight: bold
                        - font-size: 0.6vw
                        - color: white
                  - type: "custom:button-card"
                    entity: sensor.melbourne_pollen_forecast_api
                    label: >
                      [[[return (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[2].pollen_level);]]]
                    state_display: >
                      [[[return (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[2].day_short_name);]]]
                    icon: >
                      [[[
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[2].pollen_level == 'Low')
                          return "mdi:emoticon-happy";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[2].pollen_level == 'Moderate')
                          return "mdi:emoticon-neutral";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[2].pollen_level == 'High')
                          return "mdi:emoticon-sad";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[2].pollen_level == 'Extreme')
                          return "mdi:emoticon-angry";
                        else
                          return "mdi:help-circle";
                      ]]]
                    show_label: true
                    show_state: true
                    show_name: false                
                    size: 50%
                    aspect_ratio: 1.8/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[2].pollen_level == 'Low')
                              return 'lime';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[2].pollen_level == 'Moderate')
                              return 'yellow';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[2].pollen_level == 'High')
                              return 'orange';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[2].pollen_level == 'Extreme')
                              return 'red';
                            else
                              return 'grey';
                          ]]]
                      label:
                        - font-weight: bold
                        - font-size: 0.6vw
                        - color: white
                  - type: "custom:button-card"
                    entity: sensor.melbourne_pollen_forecast_api
                    label: >
                      [[[return (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[3].pollen_level);]]]
                    state_display: >
                      [[[return (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[3].day_short_name);]]]
                    icon: >
                      [[[
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[3].pollen_level == 'Low')
                          return "mdi:emoticon-happy";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[3].pollen_level == 'Moderate')
                          return "mdi:emoticon-neutral";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[3].pollen_level == 'High')
                          return "mdi:emoticon-sad";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[3].pollen_level == 'Extreme')
                          return "mdi:emoticon-angry";
                        else
                          return "mdi:help-circle";
                      ]]]
                    show_label: true
                    show_state: true
                    show_name: false                
                    size: 50%
                    aspect_ratio: 1.8/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[3].pollen_level == 'Low')
                              return 'lime';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[3].pollen_level == 'Moderate')
                              return 'yellow';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[3].pollen_level == 'High')
                              return 'orange';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[3].pollen_level == 'Extreme')
                              return 'red';
                            else
                              return 'grey';
                          ]]]
                      label:
                        - font-weight: bold
                        - font-size: 0.6vw
                        - color: white
                  - type: "custom:button-card"
                    entity: sensor.melbourne_pollen_forecast_api
                    label: >
                      [[[return (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[4].pollen_level);]]]
                    state_display: >
                      [[[return (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[4].day_short_name);]]]
                    icon: >
                      [[[
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[4].pollen_level == 'Low')
                          return "mdi:emoticon-happy";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[4].pollen_level == 'Moderate')
                          return "mdi:emoticon-neutral";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[4].pollen_level == 'High')
                          return "mdi:emoticon-sad";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[4].pollen_level == 'Extreme')
                          return "mdi:emoticon-angry";
                        else
                          return "mdi:help-circle";
                      ]]]
                    show_label: true
                    show_state: true
                    show_name: false                
                    size: 50%
                    aspect_ratio: 1.8/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[4].pollen_level == 'Low')
                              return 'lime';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[4].pollen_level == 'Moderate')
                              return 'yellow';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[4].pollen_level == 'High')
                              return 'orange';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[4].pollen_level == 'Extreme')
                              return 'red';
                            else
                              return 'grey';
                          ]]]
                      label:
                        - font-weight: bold
                        - font-size: 0.6vw
                        - color: white
                  - type: "custom:button-card"
                    entity: sensor.melbourne_pollen_forecast_api
                    label: >
                      [[[return (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[5].pollen_level);]]]
                    state_display: >
                      [[[return (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[5].day_short_name);]]]
                    icon: >
                      [[[
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[5].pollen_level == 'Low')
                          return "mdi:emoticon-happy";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[5].pollen_level == 'Moderate')
                          return "mdi:emoticon-neutral";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[5].pollen_level == 'High')
                          return "mdi:emoticon-sad";
                        if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[5].pollen_level == 'Extreme')
                          return "mdi:emoticon-angry";
                        else
                          return "mdi:help-circle";
                      ]]]
                    show_label: true
                    show_state: true
                    show_name: false                
                    size: 50%
                    aspect_ratio: 1.8/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[5].pollen_level == 'Low')
                              return 'lime';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[5].pollen_level == 'Moderate')
                              return 'yellow';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[5].pollen_level == 'High')
                              return 'orange';
                            if (states['sensor.melbourne_pollen_forecast_api'].attributes.melbourne_6day_pollen_forecast.days[5].pollen_level == 'Extreme')
                              return 'red';
                            else
                              return 'grey';
                          ]]]
                      label:
                        - font-weight: bold
                        - font-size: 0.6vw
                        - color: white