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
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”
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).
- The ‘melbourne_pollen_forecast_api’ sensor covers the basics and feeds the card.
- 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:
- 2022-09-22: Updated for 2022.
- 2022-10-06: Fixed breaking change due to pollen forecast in API changing from title case to upper case (Low > LOW etc.)
- 2022-10-08: Reversed #2 above as it changed back! lol…
- It reversed yet again! So I built an initial handle for either case…
- 2022-10-22: Changed API version from 5 to 4 as 5 had asthma forecasts as “unavailable” whereas 4 appears to have them.
- Pasted in a fresh copy of the lovelace config.
- 2022-11-10: Added some automation examples on request
- 2022-11-27 Asthma forecast randomly changed from div7 to div8, breaking the sensor. So that was adjusted in 2 places.
- 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.
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.
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
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.
- Change api version from version 2 to version 5.
- 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.
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
Thanks for getting back to me
Here is a screenshot of the api sensor
It seems to have a slightly different formatting, which I think might be why the lovelace doesn’t like it.
Here is the code I used for the rest and template sensor
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"
sensor:
- 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 %}
{{
'{\n' +
forecastpageHTML
|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('</span>', '"</span>*NL*},*NL* ')
|striptags
|replace('*NL*', '\n') + ']\n}'
}}
my_district_asthma_forecast_today: >-
{% set myDistrict = 'Central' %}
{% set asthmaForecastHTML = states.sensor.melbourne_pollen_api_html.attributes.div7 %}
{% 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
So not sure if I have misconfigured something.
I think I made more changes but didn’t publish/change them.
Try this, then if it works, I’ll update my earlier post…
- 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 %}
{{
'{\n' +
forecastpageHTML
|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.div7 %}
{% 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
Thanks you, that appears to have worked. Thanks…
I’ve been playing with some 6day forecast summary stats while I’m active on this.
This template sensor counts the number of low, moderate, high, and extreme days in the next 6 days.
It also assigns a weighting of 1,2,3,4 for each of the levels then calculates an overall rating based on a simple average.
This can be used to trigger alerts and help plan your week. For example I might plan to work-from-home rather than cycle in, and let the boss know that ahead of time etc…
Might be a more concise way to do it, but it works (I think)…
- platform: template
sensors:
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 %}.
Great work @Mahko_Mahko. I set it up a couple of days ago and it was working fine until today when I ran into the same issue with rendering cards as @obrien.craig.
Haven’t changed anything and my sensor.melbourne_pollen_forecast_api looks like this:
friendly_name: Melbourne Pollen Forecast via API
melbourne_6day_pollen_forecast: {
"days": [
{
"day_short_name":"Wed",
"date":"05 October 2022",
"pollen_level":"LOW
{
"day_short_name":"Thu",
"date":"06 October 2022",
"pollen_level":"MODERATE
{
"day_short_name":"Fri",
"date":"07 October 2022",
"pollen_level":"LOW
{
"day_short_name":"Sat",
"date":"08 October 2022",
"pollen_level":"LOW
{
"day_short_name":"Sun",
"date":"09 October 2022",
"pollen_level":"LOW
{
"day_short_name":"Mon",
"date":"10 October 2022",
"pollen_level":"LOW]
}
my_district_asthma_forecast_today: not-available
My card config:
- 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
color_type: card
styles:
name:
- font-weight: bold
- font-size: 0.6vw
- color: black
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: black
- 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
color_type: card
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: black
state:
- text-transform: capitalize
- 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
color_type: card
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: 1.0vw
- color: black
- 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
color_type: card
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: 1.0vw
- color: black
- 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
color_type: card
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: 1.0vw
- color: black
- 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
color_type: card
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: 1.0vw
- color: black
- 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
color_type: card
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: 1.0vw
- color: black
Mine appears to have broken too. Stay tuned. Seems to just be the card.
I can confirm there was a breaking change due to the API changing from reporting the pollen forecasts in title case to upper case (e.g “Low” is now “LOW”) in the api.
I’ve made the required changes/fixes and it should be ok again. I’ve updated the main solution post with neccessary changes.
The changes are in this section, but it probably wouldn’t hurt to be using my whole config line-for-line, as that may make debugging easier if you need a bit of help from me.
|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}'
}}
Not sure what’s up with the Thunderstorm Asthma forecast for this season.
Also at time of publishing one day of forecast seemed to be missing (from the API).
Will monitor that.