This ist only apex Charts with minimalist Theme. Can you Show me a picture of your Card?
How i can show tibber prices from last day(s)?
Here my APEX-Code
type: custom:apexcharts-card
header:
show: true
title: Preis & Batterie
show_states: true
colorize_states: true
now:
show: true
label: ""
graph_span: 48h
span:
end: day
offset: "-24"
apex_config:
dataLabels:
enabled: true
distributed: true
yaxis:
- id: Tibber
opposite: false
decimalsInFloat: 0
max: 50
min: 0
tickAmount: 5
- id: Batterie
opposite: true
decimalsInFloat: 0
max: 100
min: 0
tickAmount: 5
- id: kWh
opposite: true
decimalsInFloat: 0
max: 1000
min: 1
tickAmount: 1
series:
- entity: sensor.tibber_prices
name: Tibber
yaxis_id: Tibber
show:
in_header: before_now
name_in_header: false
legend_value: false
in_chart: true
in_brush: true
color_threshold:
- value: 0
color: 4DD0E1
- value: 10
color: 26A69A
- value: 15
color: 4CAF50
- value: 20
color: 7CB342
- value: 25
color: FBC02D
- value: 30
color: EF6C00
- value: 40
color: B71C1C
type: line
curve: stepline
extend_to: false
stroke_width: 1
float_precision: 2
data_generator: |
const noon = new Date()
noon.setHours(0, 0, 0, 0)
const prices = entity.attributes.today.concat(entity.attributes.tomorrow);
const data = [];
for(let i = 0 ; i < prices.length; i++) {
data.push([noon.getTime() + i * 1000 * 3600, prices[i].total * 100])
}
return data;
- entity: sensor.delta_2_max_battery_level
name: Batterie
yaxis_id: Batterie
stroke_width: 1
float_precision: 0
extend_to: false
show:
legend_value: false
in_header: true
group_by:
duration: 15m
func: avg
- entity: sensor.tasmota_bkw_bat_in_energy_power
name: Laden
yaxis_id: kWh
type: area
stroke_width: 1
float_precision: 0
extend_to: false
show:
legend_value: false
in_header: false
group_by:
duration: 1m
func: avg
- entity: sensor.tasmota_bkw_mwr_out_energy_power
name: Einspeisung
yaxis_id: kWh
type: area
stroke_width: 1
float_precision: 0
extend_to: false
show:
legend_value: false
in_header: false
group_by:
duration: 15m
func: avg
- entity: sensor.solarproduktion_gesamt_akt
name: Solar
yaxis_id: kWh
type: area
stroke_width: 1
float_precision: 0
extend_to: false
show:
legend_value: false
in_header: false
group_by:
duration: 15m
func: avg
Hello Ingo, these sensors are missing
or where do I get them?
- sensor.electricity_generation_stand
- sensor.electricity_generation_previously
- sensor.tibber_stand_zahler_einspeisung
- sensor.einspeisegeuhr_im_current_jahr
- sensor.tibber_stand_payer_reference
- sensor.power consumption_kwh_previously
- sensor.template_tibber_consumption_year
- sensor.template_tibber_cost_year
- sensor.template_tibber_consumption_per_month
- sensor.template_tibber_kosten_je_kwh_jahr_ohne_grundgebuhr
- sensor.template_tibber_kosten_je_kwh_jahr
- sensor.tibber_monthly_consumption
- sensor.tibber_api_kosten_aktueller_monat
Greetings Alex
Does nobody have an idea where one can display the prices from the past (a few days ago) and those of the future in a curve?
With a bit of fiddling and trail and error, I was able to realise the suggestion presented here for myself and would like to start by thanking you for it. Strangely, however, I can’t get any historical values for my Tibber price. Does anyone have any ideas?
Hi Ingo,
first thank you much sharing your awesome Tibber Card with Storage charging evaluation. Exactly what i need!
Could you please please update your first post from 01.2024 to the actual code changes? Also for me as a beginner it woud be great to get some more information at which path in homeassistant the Code fragments must be added.
Thanks a lot in advance!
Hi,
I wanted to take up the two topics again because I can’t find any solutions online and my attempts are also coming to nothing…
-
Always display two decimal places (example: 23.00)
-
Show the prices from the previous day and the future ones in a curve…
I hope for your ideas / support
Hi, I really appreciate the path you set here and good explanations. Can you help me out with the “binary_sensor.akku_aus_dem_netz_laden”? What the YAML for this one? I like that it shows the charging period and not just how the battery state increases.
Thanks
Hi. Sorry for the late answer. The YAML-Code for that one is:
{% set min_price = state_attr("sensor.electricity_price_wester_esch_26b","min_price") | float(default=0) %}
{% set max_price = state_attr("sensor.electricity_price_wester_esch_26b","max_price") | float(default=0) %}
{% set price = states("sensor.electricity_price_wester_esch_26b") | float(default=0) %}
{% set price_range = max_price - min_price %}
{% set price_above_min = price - min_price %}
{% set price_below_max = max_price - price %}
{% set price_level = (price_above_min / price_range) * 100 %}
{% set price_difference_to_max = (price_below_max / price_range) * 100 %}
{% set price_min_tomorrow = states("sensor.template_tibber_price_min_tomorrow") | float(default=0) + 0.05 %}
{% set house_power = states("sensor.senec_house_power") | int(default=0) %}
{% set solar_power = states("sensor.senec_solar_generated_power") | int(default=0) %}
{% set solar_energy_expected = states("sensor.solar_restproduktion_heute") | float(default=0) %}
{% set charge_from_grid_below_expected_energy = states("input_number.laden_bei_restproduktion_unter") | float(default=0) %}
{% set battery_state = states("sensor.senec_system_state") %}
{% set max_price = state_attr('sensor.electricity_price_wester_esch_26b','max_price') | float %}
{% set current_price = states('sensor.electricity_price_wester_esch_26b') | float %}
{% set price_difference = max_price - current_price %}
{% set storage_capacity = 7.5 %} # Kapazität deines Speichers in kWh
{% set charging_efficiency = 0.90 %} # Ladeeffizienz
{% set economic_threshold = 0.10 %} # Dein wirtschaftlicher Schwellenwert in €/kWh
{% if solar_power < house_power and price_difference_to_max > 50 and solar_energy_expected < charge_from_grid_below_expected_energy and price <= (min_price + 0.02) and price < price_min_tomorrow and battery_state != "AKKU VOLL" and price_difference >= economic_threshold %}
true
{% else %}
false
{% endif %}
But i decided to start over new on my approach to charge from grid. Here is my new solution:
Needed Entities:
1.) a template-binary_sensor to display if there is more solar-power coming in then my house needs. It is TRUE if there is NOT enough solar-power to feed energy into my battery.
{% set house_power = states("sensor.senec_house_power") | int(default=0) %}
{% set solar_power = states("sensor.senec_solar_generated_power") | int(default=0) %}
{{solar_power < house_power}}
2.) a template-binary_sensor to display if my battery is full or not. It is TRUE if my battery is NOT fully charged. This is based on an battery-state-sensor from my home-battery-integration.
{% set battery_state = states("sensor.senec_system_state") %}
{{battery_state != "AKKU VOLL"}}
3.) a template-binary_sensor to display if there is not much solar-energy expected for the rest of the day. It is TRUE if there ist NOT much energy expected. It is based on an input_number and the sensor for the expected energy from the Forecast.Solar-Integration
{% set solar_energy_expected = states("sensor.solar_restproduktion_heute") | float(default=0) %}
{% set charge_from_grid_below_expected_energy = states("input_number.laden_bei_restproduktion_unter") | float(default=0) %}
{{solar_energy_expected < charge_from_grid_below_expected_energy}}
4.) a trigger-binary_sensor that catches the prices for a specific amount of hours and decides if and when there is a good time to charge from grid. The decission is based on:
- the price-difference between the cheapest and the most expensive price in the time-span
- if the price-difference is above a specific value (input_number → for me 0.1 = 10 Cents)
template:
- trigger:
- platform: time_pattern
hours: "/1"
- platform: homeassistant
event: start
action:
- service: tibber.get_prices
data:
start: "{{ (now()).strftime('%Y-%m-%d %H:') + '00:00' }}"
end: "{{ (now() + timedelta(hours=states('input_number.tibber_cheap_energy_prices_hours') | int(default=24))).strftime('%Y-%m-%d %H:%M:%S') }}"
response_variable: action_response
binary_sensor:
- unique_id: tibber_next_good_grid_charging_time
name: tibber_next_good_grid_charging_time
# replace "Zuhause" with the name of your "home" in the tibber-integration
state: >
{% set min_price = action_response["prices"]["Zuhause"] |map(attribute='price') | list | min | float(default=0) %}
{% set max_price = action_response["prices"]["Zuhause"] |map(attribute='price') | list | max | float(default=0) %}
{% set lowest_price_entry = action_response["prices"]["Zuhause"] | min(attribute='price') %}
{% set start_time_lowest_price = lowest_price_entry["start_time"] %}
{% set end_time_lowest_price = as_datetime(start_time_lowest_price) + timedelta(hours=1) %}
{{as_datetime(now()) > as_datetime(start_time_lowest_price) and as_datetime(now()) < as_datetime(end_time_lowest_price) and (max_price - min_price) > states('input_number.tibber_cheap_energy_min_price_difference') | float(default=0) }}
attributes:
min_price: >
{% set min_price = action_response["prices"]["Zuhause"] |map(attribute='price') | list | min | float(default=0) %}
{{min_price}}
max_price: >
{% set max_price = action_response["prices"]["Zuhause"] |map(attribute='price') | list | max | float(default=0) %}
{{max_price}}
price_range: >
{% set min_price = action_response["prices"]["Zuhause"] |map(attribute='price') | list | min | float(default=0) %}
{% set max_price = action_response["prices"]["Zuhause"] |map(attribute='price') | list | max | float(default=0) %}
{{max_price - min_price}}
start_time: >
{% set min_price = action_response["prices"]["Zuhause"] |map(attribute='price') | list | min | float(default=0) %}
{% set max_price = action_response["prices"]["Zuhause"] |map(attribute='price') | list | max | float(default=0) %}
{% set lowest_price_entry = action_response["prices"]["Zuhause"] | min(attribute='price') %}
{% set start_time_lowest_price = lowest_price_entry["start_time"] %}
{% set end_time_lowest_price = as_datetime(start_time_lowest_price) + timedelta(hours=1) %}
{{start_time_lowest_price}}
end_time: >
{% set min_price = action_response["prices"]["Zuhause"] |map(attribute='price') | list | min | float(default=0) %}
{% set max_price = action_response["prices"]["Zuhause"] |map(attribute='price') | list | max | float(default=0) %}
{% set lowest_price_entry = action_response["prices"]["Zuhause"] | min(attribute='price') %}
{% set start_time_lowest_price = lowest_price_entry["start_time"] %}
{% set end_time_lowest_price = as_datetime(start_time_lowest_price) + timedelta(hours=1) %}
{{end_time_lowest_price}}
prices: >
{{action_response["prices"]["Zuhause"] | list}}
That binary_sensor has a few attributes that i need for my dashboard:
- min_price => the minimum price in the fetched time-span (in €, so 0,32 means 32 Cents)
- max_price => the maximum price in the fetched time-span (in €, so 0,40 means 40 Cents)
- price_range => the difference between the min_price and the max_price (in €, so 0,08 means 8 Cents)
- start_time => the start-time of the cheapest energy-hour
- end_time => the end-time of the cheapest energy-hour
- prices => just for information: the start_times, prices and price_levels in the time-span
- a group-helper for binary_sensors that is ON when ALL of the above binary_sensors are on and OFF if at least one of the above binary_sensors is OFF. I set this up via UI like this:
It is important to toggle “all entities” on for the disrciped behavior
Charging from grid automation:
With alle the above information i made an automation the switches on the “load from grid”-switch from my home-battery-integration if the group_helper-binary_sensor is ON.
alias: Tibber - Speicher günstig laden
description: ""
triggers:
- trigger: state
entity_id:
- binary_sensor.tibber_netzladen_schalter
to: "on"
for:
hours: 0
minutes: 1
seconds: 0
id: Netzladen an
- trigger: state
entity_id:
- binary_sensor.tibber_netzladen_schalter
to: "off"
for:
hours: 0
minutes: 1
seconds: 0
id: Netzladen aus
conditions: []
actions:
- choose:
- conditions:
- condition: trigger
id:
- Netzladen an
- condition: state
entity_id: switch.senec_safe_charge
state: "off"
sequence:
- action: switch.turn_on
metadata: {}
data: {}
target:
entity_id: switch.senec_safe_charge
- conditions:
- condition: trigger
id:
- Netzladen aus
- condition: state
entity_id: switch.senec_safe_charge
state: "on"
sequence:
- action: switch.turn_off
metadata: {}
data: {}
target:
entity_id: switch.senec_safe_charge
mode: single
And for my dashboard i made an mushroom-template-card that shows my if and when the charge from grid will happen:
type: custom:mushroom-template-card
primary: >-
{% if states(entity) == 'on' and
states('binary_sensor.tibber_netzladen_schalter') == 'on' %}
Speicher wird aus dem Netz geladen
{% elif states(entity) == 'on' and
states('binary_sensor.tibber_netzladen_schalter') == 'off' and
state_attr(entity,'price_range') | float(default=0) >
states('input_number.tibber_cheap_energy_min_price_difference') %}
Speicher wird nicht aus dem Netz geladen
{% elif state_attr(entity,'price_range') | float(default=0) <
states('input_number.tibber_cheap_energy_min_price_difference') |
float(default=0) %}
Keine Netzladung in den nächsten {{states('input_number.tibber_cheap_energy_prices_hours') | int(default=0)}} Stunden
{% else %}
Geplante Speicherladung ab {{as_datetime(state_attr(entity,'start_time')).strftime('%-H:%M')}} Uhr
{% endif %}
secondary: >-
{% if states(entity) == 'on' and
states('binary_sensor.tibber_netzladen_schalter') == 'on' %}
Der Speicher wird gerade aus dem Netz geladen, weil der aktuelle Preis von {{(state_attr(entity,'min_price') | float(default=0) * 100) | round(1)}} Cent um {{(state_attr(entity,'price_range') | float(default=0) * 100) | round(1)}} Cent unter dem Maximalpreis liegt.
{% elif states(entity) == 'on' and
states('binary_sensor.tibber_netzladen_schalter') == 'off' and
state_attr(entity,'price_range') | float(default=0) >
states('input_number.tibber_cheap_energy_min_price_difference') %}
Der Speicher wird nicht aus dem Netz geladen obwohl die Konditionen günstig sind, weil Überschüsse aus der Photovoltaikanlage vorliegen oder erwartet werden.
{% elif state_attr(entity,'price_range') | float(default=0) <
states('input_number.tibber_cheap_energy_min_price_difference') |
float(default=0) %}
Die Preisdifferenz zwischen dem niedrigsten und höchsten Preis beträgt nur {{(state_attr(entity,'price_range') | float(default=0) * 100) | round(1)}} Cent. Aus dem Netz geladen wird erst ab {{(states('input_number.tibber_cheap_energy_min_price_difference') | float(default=0) * 100) | round(1)}} Cent.
{% else %}
Der Speicher wird von {{as_datetime(state_attr(entity,'start_time')).strftime('%-H:%M')}} bis {{as_datetime(state_attr(entity,'end_time')).strftime('%-H:%M')}} Uhr zu einem Preis von {{(state_attr(entity,'min_price') | float(default=0) * 100) | round(1)}} Cent aus dem Netz geladen. Die Preisdifferenz zum Maximalpreis beträgt {{(state_attr(entity,'price_range') | float(default=0) * 100) | round(1)}} Cent.
{% endif %}
icon: mdi:home-battery
entity: binary_sensor.tibber_next_good_grid_charging_time
grid_options:
columns: full
multiline_secondary: true
badge_icon: mdi:transmission-tower
badge_color: >-
{% if states(entity) == 'on' and
states('binary_sensor.tibber_netzladen_schalter') == 'on' %}
red
{% elif states(entity) == 'on' and
states('binary_sensor.tibber_netzladen_schalter') == 'off' and
state_attr(entity,'price_range') | float(default=0) >
states('input_number.tibber_cheap_energy_min_price_difference') %}
grey
{% elif state_attr(entity,'price_range') | float(default=0) <
states('input_number.tibber_cheap_energy_min_price_difference') |
float(default=0) %}
grey
{% else %}
orange
{% endif %}
icon_color: >-
{% if states(entity) == 'on' and
states('binary_sensor.tibber_netzladen_schalter') == 'on' %}
red
{% elif states(entity) == 'on' and
states('binary_sensor.tibber_netzladen_schalter') == 'off' and
state_attr(entity,'price_range') | float(default=0) >
states('input_number.tibber_cheap_energy_min_price_difference') %}
grey
{% elif state_attr(entity,'price_range') | float(default=0) <
states('input_number.tibber_cheap_energy_min_price_difference') |
float(default=0) %}
grey
{% else %}
orange
{% endif %}
Very nice thread with awesome ideas. Thanks!
My issue is that the colors in the charts in summer (mostly green) are different than in winter (mostly orange/red).
What i’d like to see is the apexchart for todays electricity price being colored based on this:
Now, apexchart only accepts hardcoded integers as treshold value so the above values need a template to return this integer.
This is where my knowledge falls short. Has someone else achieved this?
I also found this topic where something similar is achieved.
Edit Decided to take the approach as mentioned in the linked topic.
Cheers.
Is there a problem with the Tibber integration?
I have the same issue since update to 2024.11 today… but i read the prices directly via rest-api also, there is everything ok…
Hi, can someone tell me where or how I have to put this sensor on?
template:
- trigger:
- platform: time_pattern
hours: "/1"
- platform: homeassistant
event: start
action:
- service: tibber.get_prices
data:
start: "{{ (now()).strftime('%Y-%m-%d %H:') + '00:00' }}"
end: "{{ (now() + timedelta(hours=states('input_number.tibber_cheap_energy_prices_hours') | int(default=24))).strftime('%Y-%m-%d %H:%M:%S') }}"
response_variable: action_response
binary_sensor:
- unique_id: tibber_next_good_grid_charging_time
name: tibber_next_good_grid_charging_time
# replace "Zuhause" with the name of your "home" in the tibber-integration
state: >
{% set min_price = action_response["prices"]["Zuhause"] |map(attribute='price') | list | min | float(default=0) %}
{% set max_price = action_response["prices"]["Zuhause"] |map(attribute='price') | list | max | float(default=0) %}
{% set lowest_price_entry = action_response["prices"]["Zuhause"] | min(attribute='price') %}
{% set start_time_lowest_price = lowest_price_entry["start_time"] %}
{% set end_time_lowest_price = as_datetime(start_time_lowest_price) + timedelta(hours=1) %}
{{as_datetime(now()) > as_datetime(start_time_lowest_price) and as_datetime(now()) < as_datetime(end_time_lowest_price) and (max_price - min_price) > states('input_number.tibber_cheap_energy_min_price_difference') | float(default=0) }}
attributes:
min_price: >
{% set min_price = action_response["prices"]["Zuhause"] |map(attribute='price') | list | min | float(default=0) %}
{{min_price}}
max_price: >
{% set max_price = action_response["prices"]["Zuhause"] |map(attribute='price') | list | max | float(default=0) %}
{{max_price}}
price_range: >
{% set min_price = action_response["prices"]["Zuhause"] |map(attribute='price') | list | min | float(default=0) %}
{% set max_price = action_response["prices"]["Zuhause"] |map(attribute='price') | list | max | float(default=0) %}
{{max_price - min_price}}
start_time: >
{% set min_price = action_response["prices"]["Zuhause"] |map(attribute='price') | list | min | float(default=0) %}
{% set max_price = action_response["prices"]["Zuhause"] |map(attribute='price') | list | max | float(default=0) %}
{% set lowest_price_entry = action_response["prices"]["Zuhause"] | min(attribute='price') %}
{% set start_time_lowest_price = lowest_price_entry["start_time"] %}
{% set end_time_lowest_price = as_datetime(start_time_lowest_price) + timedelta(hours=1) %}
{{start_time_lowest_price}}
end_time: >
{% set min_price = action_response["prices"]["Zuhause"] |map(attribute='price') | list | min | float(default=0) %}
{% set max_price = action_response["prices"]["Zuhause"] |map(attribute='price') | list | max | float(default=0) %}
{% set lowest_price_entry = action_response["prices"]["Zuhause"] | min(attribute='price') %}
{% set start_time_lowest_price = lowest_price_entry["start_time"] %}
{% set end_time_lowest_price = as_datetime(start_time_lowest_price) + timedelta(hours=1) %}
{{end_time_lowest_price}}
prices: >
{{action_response["prices"]["Zuhause"] | list}}
i think this from another source
I got the same issue with the max price, which is an issue for my loading from grid automation.
Any thoughts on how to fix this, more than welcome!
Same Problem here. Configure code in configuration.yaml,
but no values on: tibber_next_good_grid_charging_time
Think trigger don´t work, need to put code in automations.yaml ?
Reload the integration