That should be fine… works with apex; date/time is stored as UTC an HA will automatically show the applied time zone; same should be for template sensors.
I would need to check manual. But take below sensor. It compares with now().date(); Are you sure it then automatically takes 1 hour from the previous day and not just the 23 hours it can find for today?
- platform: template
sensors:
avg_energy_price:
friendly_name: Average current energy price
value_template: >
{% set ns = namespace(sum = 0, count = 0) %}
{% for item in state_attr('sensor.zonneplan_current_electricity_tariff', 'forcast') -%}
{% if as_datetime(item.datetime).date() == now().date() %}
{% set ns.sum = ns.sum + item.price %}
{% set ns.count = ns.count + 1 %}
{% endif %}
{%- endfor %}
{{ (ns.sum/ns.count/100000) }}
If you change the data generator to below you can also get extremas in the graph:
return entity.attributes.forcast.map((entry) => {
return [new Date(entry.datetime).getTime(), entry.price /100000] ;
});
For the colors in the graph: Instead of a static value to set the color threshold you can also adjust based on (in my case) average.
Example below
- type: custom:config-template-card
variables:
MOVINGAVERAGE: states['sensor.avg_energy_price_cnt']
entities:
- ${MOVINGAVERAGE.entity_id}
card:
type: custom:apexcharts-card
apex_config:
chart:
height: 200px
fontFamily: Raleway,sans-serif
xaxis:
labels:
format: HH
legend:
show: false
stroke:
width: 2
plotOptions:
bar:
columnWidth: 100%
grid:
show: true
borderColor: '#00000030'
strokeDashArray: 4
position: back
dataLabels:
offsetY: -8
background:
opacity: 0.01
enabled: true
foreColor: '#CF7524'
padding: 2
borderRadius: 4
borderWidth: 0
style:
fontSize: 9px
color: rgb(200,200,200)
experimental:
color_threshold: true
graph_span: 30h
span:
start: day
offset: +4h
update_interval: +1h
header:
title: Zonneplan Forecast
show: false
now:
show: true
label: NOW
series:
- entity: sensor.zonneplan_current_electricity_tariff
color_threshold:
- value: ${MOVINGAVERAGE.state * .75}
color: '#228B22'
- value: ${MOVINGAVERAGE.state * 1}
color: '#d35400'
- value: ${MOVINGAVERAGE.state * 1.25}
color: '#c0392b'
show:
extremas: true
type: column
float_precision: 2
data_generator: |
return entity.attributes.forcast.map((entry) => {
return [new Date(entry.datetime).getTime(), entry.price /100000] ;
});
yaxis:
- id: '1'
decimals: 1
min: 0.1
apex_config:
tickAmount: 4
This one has an attribute with the last date_time of update:
- platform: template
sensors:
zonneplan_gas_prijs:
friendly_name: "Zonneplan Gasprijs"
unit_of_measurement: €/m³
device_class: monetary
value_template: >-
{% for i in states.sensor.enever_gasprijs.attributes.data %}
{{ i.prijsZP }}
{% endfor %}
attribute_templates:
datum: >-
{% for i in states.sensor.enever_gasprijs.attributes.data %}
{{ i.datum }}
{% endfor %}
@Tyfoon Cool graph. I have it working.
How did you make the circles with the pricing and the prediction of the cheapest?
The sensors on top are using ‘mushroom’ custom lovelace templates. Below is the full code.
The sensors are template sensors. Most of that code can be found in this post
type: custom:stack-in-card
cards:
- type: horizontal-stack
cards:
- type: custom:mushroom-template-card
entity: sensor.avg_energy_price
secondary: >
{{ states('sensor.lowest_price') | round(1) }}/{{
states('sensor.highest_price') | round(1) }}
primary: |
{{ states('sensor.avg_energy_price_CNT') | round(2) }} €
icon: mdi:power-plug
icon_color: orange
tap_action:
action: more-info
- type: custom:mushroom-template-card
entity: sensor.hours_low_coming
secondary: |
{{ states('sensor.hours_low_coming_short') | round(0) }} urgent
primary: >
{{ states('sensor.hours_low_coming') | round(0) }}/{{
states('sensor.hours_low_coming_far') | round(0) }} H
icon: mdi:clock-check
icon_color: orange
tap_action:
action: more-info
- type: custom:mushroom-template-card
entity: sensor.zonneplan_current_gas_tarriff_fixed
secondary: |
Gas
primary: >
{{ states('sensor.zonneplan_current_gas_tarriff_fixed') | round(2) }}
€
icon: mdi:gas-burner
icon_color: orange
tap_action:
action: more-info
- type: custom:config-template-card
variables:
MOVINGAVERAGE: states['sensor.avg_energy_price_cnt']
entities:
- ${MOVINGAVERAGE.entity_id}
card:
type: custom:apexcharts-card
apex_config:
chart:
height: 200px
fontFamily: Raleway,sans-serif
xaxis:
labels:
format: HH
legend:
show: false
stroke:
width: 2
plotOptions:
bar:
columnWidth: 100%
grid:
show: true
borderColor: '#00000030'
strokeDashArray: 4
position: back
dataLabels:
offsetY: -8
background:
opacity: 0.01
enabled: true
foreColor: '#CF7524'
padding: 2
borderRadius: 4
borderWidth: 0
style:
fontSize: 9px
color: rgb(200,200,200)
experimental:
color_threshold: true
graph_span: 30h
span:
start: day
offset: +4h
update_interval: +1h
header:
title: Zonneplan Forecast
show: false
now:
show: true
label: NOW
series:
- entity: sensor.zonneplan_current_electricity_tariff
color_threshold:
- value: ${MOVINGAVERAGE.state * .75}
color: '#228B22'
- value: ${MOVINGAVERAGE.state * 1}
color: '#d35400'
- value: ${MOVINGAVERAGE.state * 1.25}
color: '#c0392b'
show:
extremas: true
type: column
float_precision: 2
data_generator: |
return entity.attributes.forcast.map((entry) => {
return [new Date(entry.datetime).getTime(), entry.price /100000] ;
});
yaxis:
- id: '1'
decimals: 1
min: 10
apex_config:
tickAmount: 4
I cant seem to get this working.
The state of sensor.avg_energy_price = ‘Unavailable’ and i think due to this option i cant get the card to work!
Any clue what I need to fix / change?
Do you have sensor.lowest_price
and sensor.highest_price
created?
like @Hmmbob suggests; Did you create the sensors? Below is what I use. Also please note that the dev of this integration recently changed something. There was a spelling mistake in the sensor attributes and it was changed from “forcast” to “forecast”.
The yaml for the 2 sensors I use below:
- platform: template
sensors:
avg_energy_price_cnt:
friendly_name: Average current energy price cent
unique_id: avg_energy_price_cnt
value_template: >
{% set ns = namespace(sum = 0, count = 0) %}
{% for item in state_attr('sensor.zonneplan_current_electricity_tariff', 'forecast') -%}
{% if as_datetime(item.datetime).date() == now().date() %}
{% set ns.sum = ns.sum + item.price %}
{% set ns.count = ns.count + 1 %}
{% endif %}
{%- endfor %}
{{ (ns.sum/ns.count/100000) }}
- platform: template
sensors:
avg_energy_price:
friendly_name: Average current energy price
unique_id: avg_energy_price
device_class: monetary
value_template: >
{% set ns = namespace(sum = 0, count = 0) %}
{% for item in state_attr('sensor.zonneplan_current_electricity_tariff', 'forecast') -%}
{% if as_datetime(item.datetime).date() == now().date() %}
{% set ns.sum = ns.sum + item.price %}
{% set ns.count = ns.count + 1 %}
{% endif %}
{%- endfor %}
{{ (ns.sum/ns.count/10000000) }}
Thank you! The issue was ‘Forcast’ instead of Forecast…
I didn’t know this was changed, thanks!
After the latest zonneplan.one update, this code is not working anymore.
template:
- sensor:
- name: zonneplan_cheapest_hour
state: >
{% set cheapest_hour_next_ten_hours = state_attr('sensor.zonneplan_current_electricity_tariff', 'forcast')
| selectattr('datetime', '>', utcnow().isoformat())
| selectattr('datetime', '<', (utcnow() + timedelta(hours = 13)).isoformat())
| sort(attribute='price')
| first %}
{{ (cheapest_hour_next_ten_hours.price /10000000)|round(2) }}
{{ as_local(as_datetime(cheapest_hour_next_ten_hours.datetime)).strftime('%d-%m - %H:%M') }}
change forcast
to forecast
Thanks man! This is great! Well done.
Hi All,
Has somebody a solution for the montly costs, based on the zonneplan tariff as sensor data? I would like to show them on my dashboard.
Thanks
Use the energy dashboard and set cost to variable/using sensor. If you use the zonneplan price sensor then the energy dashboard will calculate it for you and store the values in long term statistics.
Hi Ronald,
Thanks for your reply. I have the data in the energy dashboard and also to total cost and now I want to display these on the lovelace. I have no clue how, coming from homey where I first pushed these values using mqtt to the lovelace. But my homey died so going all the way into HA
Thanks, John
Hi John, you can use the statics card:
type: statistic
entity: sensor.gas_consumption_cost
period:
calendar:
period: month
stat_type: change
That picks up the cost change from the LT statistics database. You may need to change the sensor as this is mine. Hope this is helpful.
Ronald
And with the statistics card you can make a Graph as well:
chart_type: bar
period: month
days_to_show: 1000
type: statistics-graph
entities:
- sensor.gas_consumption_cost
stat_types:
- change
Yeah, found it, using the ‘dev tools’ and then the tab ‘statics’ for the correct entities and displaying it with your yaml.
Thanks a lot!
Created a new zonneplan chart using plotly-graph from HACS. Uses same colors as in the zonneplan app, and shows all from forecast scrollable over time. Time window and pricing shown on mouse over. Reset button to reset to default setting after scrolling. See image and cde attached.
Edit: updated the api change of may 10 (see below)
type: custom:plotly-graph
title: Zonneplan electricity forecast
hours_to_show: 18
time_offset: 14h
fn: |
$fn ({ hass, vars }) => {
vars.x = []; vars.y = []; vars.color = []; vars.hover = []
vars.min = {p: 999,t: null}; vars.max = {p:-999,t:null}
vars.ymin = 999; vars.ymax = -999
vars.unit_of_measurement = hass.states['sensor.zonneplan_current_electricity_tariff'].attributes.unit_of_measurement
hass.states['sensor.zonneplan_current_electricity_tariff']?.attributes?.forecast?.map(e => {
var t = new Date(e.datetime).getTime()+1800000
var p = e.electricity_price/10000000
var c = e.tariff_group.replace("low", "#00a964").replace("normal", "#365651").replace("high","#ed5e18")
if (t>=Date.now()-1800000) {
if (p<vars.min.p) vars.min = {p,t,c}
if (p>vars.max.p) vars.max = {p,t,c}
}
if (p<vars.ymin) vars.ymin = p
if (p>vars.ymax) vars.ymax = p
vars.x.push(t)
vars.y.push(p)
vars.color.push(c)
vars.hover.push(String(new Date(t).getHours()).padStart(2,"0") + "-" +
String(new Date((new Date(t).getTime()+3600000)).getHours()).padStart(2,"0") + ": <b>" +
p.toFixed(3) + "</b> " + vars.unit_of_measurement)
})
}
layout:
yaxis:
fixedrange: true
tickformat: .2f
range: $fn ({vars}) => [ vars.ymin-0.02, vars.ymax+0.02 ]
xaxis:
tickformat: '%H:%M'
config:
displayModeBar: false
entities:
- entity: ''
unit_of_measurement: $ex vars.unit_of_measurement
name: Tariff
showlegend: false
x: $ex vars.x
'y': $ex vars.y
marker:
color: $ex vars.color
type: bar
hovertemplate: $ex vars.hover
- entity: ''
mode: markers
textposition: top
showlegend: true
name: >-
$fn ({vars}) => vars.min.p.toFixed(3) + " " + vars.unit_of_measurement + "
@ " + new Date(vars.min.t).getHours() + ":00"
yaxis: y0
marker:
symbol: diamond
color: $ex vars.min.c
opacity: 0.7
x:
- $ex vars.min.t
'y':
- $ex vars.min.p
- entity: ''
mode: markers
textposition: top
showlegend: true
name: >-
$fn ({vars}) => vars.max.p.toFixed(3) + " " + vars.unit_of_measurement + "
@ " + new Date(vars.max.t).getHours() + ":00"
yaxis: y0
marker:
symbol: diamond
color: $ex vars.max.c
opacity: 0.7
x:
- $ex vars.max.t
'y':
- $ex vars.max.p
- entity: ''
name: Now
yaxis: y9
showlegend: false
line:
width: 1
dash: dot
color: deepskyblue
x: $ex [Date.now(), Date.now()]
'y':
- 0
- 1