Well I’m impatient and haven’t updated to 106. Also @VDRainer’s sensor didn’t work for the USA because theres 9 million state provinces in the us. Anyways, if anyone is interested in a USA sensors…
rest
- platform: rest
resource: "https://services1.arcgis.com/0MSEUqKaxRlEPj5g/arcgis/rest/services/ncov_cases/FeatureServer/1/query?f=json&where=(Confirmed%20%3E%200)%20AND%20(Country_Region%3D%27US%27)&returnGeometry=false&spatialRel=esriSpatialRelIntersects&outFields=*&orderByFields=Confirmed%20desc%2CCountry_Region%20asc%2CProvince_State%20asc&outSR=102100&resultOffset=0&resultRecordCount=250&cacheHint=true"
name: Corona Virus Rest
value_template: "{{ value_json.features | length }}"
json_attributes:
- features
template
- platform: template
sensors:
corona_virus_usa:
friendly_name: Corona Virus USA
value_template: >
{%- set features = state_attr('sensor.corona_virus_rest', 'features') %}
{%- set last_updated = features | map(attribute='attributes.Last_Update') | list | max / 1000 %}
{{ last_updated | timestamp_custom('%Y-%m-%dT%H:%M:%S.%f+00:00') }}
attribute_templates:
confirmed: >
{%- set features = state_attr('sensor.corona_virus_rest', 'features') %}
{{ features | map(attribute='attributes.Confirmed') | list | sum }}
deaths: >
{%- set features = state_attr('sensor.corona_virus_rest', 'features') %}
{{ features | map(attribute='attributes.Deaths') | list | sum }}
recovered: >
{%- set features = state_attr('sensor.corona_virus_rest', 'features') %}
{{ features | map(attribute='attributes.Recovered') | list | sum }}
closest: >
{%- set features = state_attr('sensor.corona_virus_rest', 'features') %}
{%- set features = features | map(attribute='attributes') | list %}
{%- set loc = namespace(dist=[]) %}
{%- for feature in features %}
{%- set loc.dist = loc.dist + [ distance(feature.Lat, feature.Long_, 'zone.home') ] %}
{%- endfor %}
{{ features[loc.dist.index(loc.dist | min)].Province_State }}
miles_away: >
{%- set features = state_attr('sensor.corona_virus_rest', 'features') %}
{%- set features = features | map(attribute='attributes') | list %}
{%- set loc = namespace(dist=[]) %}
{%- for feature in features %}
{%- set loc.dist = loc.dist + [ distance(feature.Lat, feature.Long_, 'zone.home') ] %}
{%- endfor %}
{{ loc.dist | min | round }}
You end up with a sensor that tells you the total deaths, confirmed, recovered, closest province with the virus, and how many miles it is away.
And here’s a custom:button-card configuration.
type: custom:button-card
show_state: false
show_label: true
label: |
[[[
var empty = ' '
if (entity === undefined)
return empty;
function getEntityIcon(text, icon, color){
return `<ha-icon
icon="${icon}"
style="size: 10%; color: ${color};">
</ha-icon><span> ${text}</span>`
}
var attrs = [{
text: entity.attributes.confirmed,
icon: 'mdi:emoticon-neutral-outline',
color: 'var(--paper-item-icon-active-color)'
}, {
text: entity.attributes.recovered,
icon: 'mdi:emoticon-excited-outline',
color: 'rgba(94, 228, 101)'
}, {
text: entity.attributes.deaths,
icon: 'mdi:emoticon-dead-outline',
color: 'rgba(228, 94, 101)'
}]
var i;
var line1 = []
for (i = 0; i < attrs.length; i++){
var attr = attrs[i];
line1.push(getEntityIcon(attr.text, attr.icon, attr.color));
}
var attrs = [{
text: entity.attributes.closest,
icon: 'mdi:map-marker',
color: 'var(--paper-item-icon-active-color)'
}, {
text: entity.attributes.miles_away,
icon: 'mdi:map-marker-distance',
color: 'var(--paper-item-icon-active-color)'
}]
var line2 = []
for (i = 0; i < attrs.length; i++){
var attr = attrs[i];
line2.push(getEntityIcon(attr.text, attr.icon, attr.color));
}
return line1.join(" ") + "<br>" + line2.join(" ");
]]]
aspect_ratio: 4/1
entity: sensor.corona_virus_usa
icon: mdi:biohazard
color: rgb(94, 228, 101)
size: 100%
styles:
card:
- border-radius: 15px
grid:
- grid-template-areas: '"i n" "i l"'
- grid-template-columns: 3fr 14fr
- grid-template-rows: 1fr 2fr
name:
- justify-self: start
- align-self: end
- padding-left: 10px
- font-weight: bold
- font-family: Helvetica
- font-size: 16px
label:
- align-self: start
- padding-left: 10px
- font-size: 12px
- justify-self: start
- color: gray
- text-align: start
custom_fields:
updated:
- position: absolute
- top: 50%
- right: 5%
- transform: translateY(-50%)
- font-size: 13px
- justify-self: start
- text-align: start
custom_fields:
updated: |
[[[
if (entity === undefined)
return 'Invalid Entity';
let now = new Date();
let date = new Date(entity.state);
var tdelta = Math.floor((now - date)/1000);
function plural(descriptor, divisor){
var ret = Math.floor(tdelta/divisor);
return (ret == 1) ? `${ret} ${descriptor} ago` : `${ret} ${descriptor}s ago`;
}
var tstring;
if (tdelta < 60)
tstring = plural('second', 1);
else if (tdelta < 60 * 60)
tstring = plural('minute', 60);
else if (tdelta < 60 * 60 * 24)
tstring = plural('hour', 60 * 60);
else
tstring = plural('day', 60 * 60 * 24);
return tstring;
]]]