the78mole
(Daniel Glaser)
December 12, 2024, 12:34am
1
Hi Guys,
since I was searching quite some time and could not find a solution, how to pipe in the data from a service (in my case the tibber price “forecast”) into the apex charts card, here is my solution, that took me around three hours to digg through (it’s what moles do) the ApexChartsCard integration and trying almost thousands of variants of JavaScript code in the browser console:
type: custom:apexcharts-card
graph_span: 48h
update_interval: 15s
apex_config:
chart:
height: 500px
legend:
position: top
horizontalAlign: right
float_precision: 2
show:
last_updated: true
span:
start: day
header:
show: true
title: Strompreise
show_states: false
colorize_states: true
yaxis:
- id: price
min: ~10
decimals: 0
- id: soc
opposite: true
min: ~0
max: 100
decimals: 0
now:
show: true
color: red
label: Jetzt
series:
- entity: sensor.zuhause_strompreis
yaxis_id: price
show:
extremas: true
offset_in_name: false
legend_value: false
type: area
curve: stepline
stroke_width: 2
unit: ct/kWh
data_generator: |
var result = await hass.connection.sendMessagePromise({
type: 'call_service',
domain: 'tibber',
service: 'get_prices',
return_response: true
}).then((result) => {
var data = Object.values(result.response.prices)[0];
return data.map((p) => { return [p.start_time, p.price * 100]; });
}).catch((error) => {
console.error('Error calling service:', error);
});
return result;
- entity: sensor.zuhause_strompreis
name: Aktueller Preis
yaxis_id: price
show:
extremas: true
offset_in_name: false
legend_value: true
stroke_width: 5
float_precision: 2
type: line
unit: ct/kWh
extend_to: false
group_by:
fill: "null"
data_generator: |
var now = new Date();
return [
[ now.getTime(), entity.state * 100.0],
[] // This avoids a strange s-curve...
];
- entity: input_number.batterie_ladepreis
yaxis_id: price
name: Ladepreis
color: red
stroke_width: 1
float_precision: 2
show:
extremas: false
datalabels: true
offset_in_name: false
data_generator: |
var startOfDay = new Date();
startOfDay.setHours(0);
startOfDay.setMinutes(0);
startOfDay.setSeconds(0);
return [[startOfDay.getTime(), entity.state]];
return [[startOfDay.getTime(), entity.state]];
- entity: sensor.victron_battery_soc
name: Akku SoC
yaxis_id: soc
color: green
type: line
stroke_width: 2
extend_to: now
view_layout:
position: main
I also added the state of charge from the home battery storage and the current value of the charging threshold (if price drops below, battery will be charged).
Here is, how it looks like:
Sorry for the German labels, but this is the Smart Home of my father not speaking english at all
The snapshot is one of the rare days, the price jumps into sky and it was the real reason to implement this for my fathers convenience…
Hope it helps others to avoid using node-red (as I still do in my SmartHome) or searching for wired solutions
Have
2 Likes
the78mole
(Daniel Glaser)
December 14, 2024, 4:00pm
2
OK, here is an update to get the full two days of forecast (it was retrieving only the first day)…
type: custom:apexcharts-card
graph_span: 48h
update_interval: 5s
apex_config:
chart:
height: 500px
width: 100%
legend:
position: top
horizontalAlign: right
float_precision: 2
show:
last_updated: true
span:
start: day
header:
show: true
title: Strompreise
show_states: false
colorize_states: true
yaxis:
- id: price
min: ~10
decimals: 0
- id: soc
opposite: true
min: ~0
max: 100
decimals: 0
now:
show: true
color: red
label: Jetzt
series:
- entity: sensor.zuhause_strompreis
yaxis_id: price
show:
extremas: true
offset_in_name: false
legend_value: false
type: area
float_precision: 2
curve: stepline
stroke_width: 2
unit: ct/kWh
data_generator: |
var xnow = moment().startOf("day").add("days", 2);
var strtwoday = xnow.format("YYYY-MM-DD HH:mm:ssZ");
console.log(strtwoday);
var result = await hass.connection.sendMessagePromise({
type: 'call_service',
domain: 'tibber',
service: 'get_prices',
return_response: true,
service_data: { end: strtwoday }
}).then((result) => {
var data = Object.values(result.response.prices)[0];
return data.map((p) => { return [p.start_time, p.price * 100]; });
}).catch((error) => {
console.error('Error calling service:', error);
});
return result;
- entity: sensor.zuhause_strompreis
name: Aktueller Preis
yaxis_id: price
show:
extremas: true
offset_in_name: false
legend_value: true
stroke_width: 5
float_precision: 2
type: line
unit: ct/kWh
extend_to: false
group_by:
fill: "null"
data_generator: |
var now = new Date();
return [
[ now.getTime(), entity.state * 100.0],
[] // This avoids a strange s-curve...
];
- entity: input_number.batterie_ladepreis
yaxis_id: price
name: Ladepreis
color: red
stroke_width: 1
float_precision: 2
show:
extremas: false
datalabels: true
offset_in_name: false
data_generator: |
var startOfDay = new Date();
startOfDay.setHours(0);
startOfDay.setMinutes(0);
startOfDay.setSeconds(0);
return [[startOfDay.getTime(), entity.state]];
return [[startOfDay.getTime(), entity.state]];
- entity: input_number.mindest_soc_entladen
yaxis_id: soc
name: Ladeschluss SOC
color: blue
opacity: 0.5
stroke_width: 1
float_precision: 2
show:
extremas: false
datalabels: true
offset_in_name: false
data_generator: |
var startOfDay = new Date();
startOfDay.setHours(0);
startOfDay.setMinutes(0);
startOfDay.setSeconds(0);
return [[startOfDay.getTime(), entity.state]];
return [[startOfDay.getTime(), entity.state]];
- entity: input_number.mindest_soc_laden
yaxis_id: soc
name: Entladeschluss SOC
color: green
opacity: 0.5
stroke_width: 1
float_precision: 2
show:
extremas: false
datalabels: true
offset_in_name: false
data_generator: |
var startOfDay = new Date();
startOfDay.setHours(0);
startOfDay.setMinutes(0);
startOfDay.setSeconds(0);
return [[startOfDay.getTime(), entity.state]];
return [[startOfDay.getTime(), entity.state]];
- entity: sensor.victron_battery_soc
name: Akku SoC
yaxis_id: soc
color: green
type: line
stroke_width: 2
extend_to: now
view_layout:
position: main
1 Like
Thanks for this! Could you tell me where you’re getting this sensor from:
the78mole
(Daniel Glaser)
January 8, 2025, 6:23pm
4
This is just a placeholder for the tibber price sensor, that is named differently on every installation e.g., sensor.electricity_price_examplestreet_123. But this should be the similar for every dynamically priced electricity provider that has some API to get the prices from.
Since the Tibber integration sensor is in €/kWh, it is useful to convert it to ct/kWh with a template or a template helper sensor.
Hope that helps
NCO3
(Nco3)
January 26, 2025, 8:25am
6
Perfect - thank you.
I finally have added the charging threshold for my EV!
1 Like