Open 6thGuest opened 1 year ago
Now I wonder if it is possible to create a line or bar chart with the different colors for it. E.g. cheap=green, normal=yellow and expensive=red
I don't have control on the colors on that screen where you are, but we probably can have a card on your dashboard with the right colors.
or a sensor which states the times with the cheapest prices maybe like this: "Cheapest today: 01:00:00 - 02:00:00 15:00:00 - 16:00:00" "Cheapest tomorrow: 07:00:00 - 08:00:00" Do you think it is possible to create something like this?
This is pretty easy. I already have a "min" attribute a other sensor giving the lowest value available (which includes today and tomorrow) and another one called "future_min", which is kind of the same, but excluding the past hours of today. I will work on this later and share this sensor with you. How are you planning to display this info?
I don't have control on the colors on that screen where you are, but we probably can have a card on your dashboard with the right colors.
Well I was thinking about a seperate card (maybe Apexcharts) with only the colored bars for the prices. Something like this - but green, yellow, red for cheap, normal, expensive.
How are you planning to display this info?
Maybe on a "text-card" like "Cheapest periods today: 09:00-10:00 ; 15:00-17:00" "Cheapest periods tomorrow: xxxxxxxxxxxx"
Sorry, @6thGuest, I've been quite busy those days and couldn't work at this chart yet, but I was playing a bit with a table card that might help you in the meantime:
This is the card I've used for this: https://github.com/edwardtfn/HomeAssistant-Config/blob/main/lovelace/library/cards/card_electricity_price_table.yaml
Hey Edward, that looks great - THANKS!!! I adapted that to German language > works well :-) Can you tell me, how to start the table at the current hour (or maybe 1 hour back)?
This card is using the attribute all_prices
from that template sensor. The same sensor have another attribute called future
which is the same, but without past data.
So, if you are using that same sensor, you can replace in the card all instances of all_prices
by future
and it should work.
Perfect.
future_prices
works perfectly.
Hey Edward, I managed to get some more information from tibber (energy-price and taxes) - not only the sum of it. In the flex-table-card you have defined the variables to change the background-color corresponding to the price-level.
Now I tried to define a variable which changes the text-color (of only the energy-price cell) corresponding to the energy-price. Means: If energy-price is <=0 then color... and if it is >0 then color...
But now I fail to define the comparison to "0".
Can you help once more?
Could you please share the yaml of your card as it is now?
If energy-price is <=0 then color... and if it is >0 then color.
Try this:
( energy-price <= 0 ? 'red' : 'green')
This is like it is now:
type: custom:flex-table-card
title: Strompreis-Level
entities:
include: sensor.electricity_price
sort:
- future_prices+
columns:
- name: Sorting columns
data: future_prices
modify: x.startsAt
hidden: true
- name: beginnt
data: future_prices
modify: |
{
var colors = [
{ level: "VERY_EXPENSIVE", color: "red" },
{ level: "EXPENSIVE", color: "goldenrod" },
{ level: "NORMAL", color: "green" },
{ level: "CHEAP", color: "limegreen" },
{ level: "VERY_CHEAP", color: "lightgreen" } ]
var startsAt = new Date(x.startsAt)
var d = new Date()
var sday = ""
if (startsAt.getDay() == d.getDay())
sday = "heute"
else
sday = "morgen";
'<div style="color: black; background-color: ' + colors.find(c => c.level === x.level).color + '">'
+ sday + " ab " + startsAt.getHours().toLocaleString('en-US', {minimumIntegerDigits: 1}) + " Uhr" +
'</div>'
}
align: center
- name: Level
data: future_prices
modify: |
{
var colors = [
{ level: "VERY_EXPENSIVE", color: "red" },
{ level: "EXPENSIVE", color: "goldenrod" },
{ level: "NORMAL", color: "green" },
{ level: "CHEAP", color: "limegreen" },
{ level: "VERY_CHEAP", color: "lightgreen" } ]
'<div style="color: black; background-color: ' + colors.find(c => c.level === x.level).color + '">'
+ x.level.replace('CHEAP', 'günstig').replace('NORMAL', 'normal').replace('EXPENSIVE', 'teuer').replace('VERY_', 'sehr ') +
'</div>'
}
align: center
- name: Strompreis
data: future_prices
modify: |
{
var colors = [
{ level: "VERY_EXPENSIVE", color: "red" },
{ level: "EXPENSIVE", color: "goldenrod" },
{ level: "NORMAL", color: "green" },
{ level: "CHEAP", color: "limegreen" },
{ level: "VERY_CHEAP", color: "lightgreen" } ]
'<div style="color: black; background-color: ' + colors.find(c => c.level === x.level).color + '">'
+ (x.energy * 100).toFixed(2) +
' Ct/kWh</div>'
}
align: center
- name: Steuer/Gebühr
data: future_prices
modify: |
{
var colors = [
{ level: "VERY_EXPENSIVE", color: "red" },
{ level: "EXPENSIVE", color: "goldenrod" },
{ level: "NORMAL", color: "green" },
{ level: "CHEAP", color: "limegreen" },
{ level: "VERY_CHEAP", color: "lightgreen" } ]
'<div style="color: black; background-color: ' + colors.find(c => c.level === x.level).color + '">'
+ (x.tax * 100).toFixed(2) +
' Ct/kWh</div>'
}
align: center
- name: Gesamtpreis
data: future_prices
modify: |
{
var colors = [
{ level: "VERY_EXPENSIVE", color: "red" },
{ level: "EXPENSIVE", color: "goldenrod" },
{ level: "NORMAL", color: "green" },
{ level: "CHEAP", color: "limegreen" },
{ level: "VERY_CHEAP", color: "lightgreen" } ]
'<div style="color: black; background-color: ' + colors.find(c => c.level === x.level).color + '">'
+ (x.total * 100).toFixed(2) +
' Ct/kWh</div>'
}
align: center
I only want to change the textcolor in the "Strompreis" tab (energy).
Try this:
type: custom:flex-table-card
title: Strompreis-Level
entities:
include: sensor.electricity_price
sort:
- future_prices+
columns:
- name: Sorting columns
data: future_prices
modify: x.startsAt
hidden: true
- name: beginnt
data: future_prices
modify: |
{
var colors = [
{ level: "VERY_EXPENSIVE", color: "red" },
{ level: "EXPENSIVE", color: "goldenrod" },
{ level: "NORMAL", color: "green" },
{ level: "CHEAP", color: "limegreen" },
{ level: "VERY_CHEAP", color: "lightgreen" } ]
var startsAt = new Date(x.startsAt)
var d = new Date()
var sday = ""
if (startsAt.getDay() == d.getDay())
sday = "heute"
else
sday = "morgen";
'<div style="color: black; background-color: ' + colors.find(c => c.level === x.level).color + '">'
+ sday + " ab " + startsAt.getHours().toLocaleString('en-US', {minimumIntegerDigits: 1}) + " Uhr" +
'</div>'
}
align: center
- name: Level
data: future_prices
modify: |
{
var colors = [
{ level: "VERY_EXPENSIVE", color: "red" },
{ level: "EXPENSIVE", color: "goldenrod" },
{ level: "NORMAL", color: "green" },
{ level: "CHEAP", color: "limegreen" },
{ level: "VERY_CHEAP", color: "lightgreen" } ]
'<div style="color: black; background-color: ' + colors.find(c => c.level === x.level).color + '">'
+ x.level.replace('CHEAP', 'günstig').replace('NORMAL', 'normal').replace('EXPENSIVE', 'teuer').replace('VERY_', 'sehr ') +
'</div>'
}
align: center
- name: Strompreis
data: future_prices
modify: |
{
'<div style="color: black; background-color: ' + ( x.energy <= 0 ? 'green' : 'red') + '">'
+ (x.energy * 100).toFixed(2) +
' Ct/kWh</div>'
}
align: center
- name: Steuer/Gebühr
data: future_prices
modify: |
{
var colors = [
{ level: "VERY_EXPENSIVE", color: "red" },
{ level: "EXPENSIVE", color: "goldenrod" },
{ level: "NORMAL", color: "green" },
{ level: "CHEAP", color: "limegreen" },
{ level: "VERY_CHEAP", color: "lightgreen" } ]
'<div style="color: black; background-color: ' + colors.find(c => c.level === x.level).color + '">'
+ (x.tax * 100).toFixed(2) +
' Ct/kWh</div>'
}
align: center
- name: Gesamtpreis
data: future_prices
modify: |
{
var colors = [
{ level: "VERY_EXPENSIVE", color: "red" },
{ level: "EXPENSIVE", color: "goldenrod" },
{ level: "NORMAL", color: "green" },
{ level: "CHEAP", color: "limegreen" },
{ level: "VERY_CHEAP", color: "lightgreen" } ]
'<div style="color: black; background-color: ' + colors.find(c => c.level === x.level).color + '">'
+ (x.total * 100).toFixed(2) +
' Ct/kWh</div>'
}
align: center
Yeah - thanks again I changed it a little bit to only change the textcolor...
'<div style="color: ' + ( x.energy <= 0 ? 'white' : 'black') + '; background-color: ' + colors.find(c => c.level === x.level).color + '">'
+ (x.energy * 100).toFixed(2) +
' Ct/kWh</div>'
Great. By the way, I saw you using replace to translate the strings on the column "Level". It will work fine as you did, but if in the future you have a bigger list or more complex strings, you could try adding the translations to the table. Something like this:
- name: Level
data: future_prices
modify: |
{
var table = [
{ level: "VERY_EXPENSIVE", color: "red", translation: "Sehr teuer" },
{ level: "EXPENSIVE", color: "goldenrod", translation: "Teuer" },
{ level: "NORMAL", color: "green", translation: "Normal" },
{ level: "CHEAP", color: "limegreen", translation: "Günstig" },
{ level: "VERY_CHEAP", color: "lightgreen" }, translation: "Sehr günstig" ]
'<div style="color: black; background-color: ' + table.find(c => c.level === x.level).color + '">'
+ table.find(c => c.level === x.level).translation +
'</div>'
}
align: center
Okay - I'll try this. But unfortunately I don't get along with the syntax of all this. Just if you leave out a "space" something might not work as expected. I also tried to figure out c.level x.level and so on - no chance. Now I tried to sort the "today-prices" (total) in ascending order and thought that this couldn't be a big problem - only change the "sort_by" and that's it. But I failed again. The table is only sorted by the "startsAt" column but not by the price. My intention was to have a table with maybe 3 to 5 rows showing the cheapest prices and the "startsAt" column.
This is my try:
type: custom:flex-table-card
sort_by:
- total+
title: Tibber - Test
entities:
include: sensor.electricity_price
columns:
- name: beginnt
data: today
modify: |
{
var colors = [
{ level: "VERY_EXPENSIVE", color: "red" },
{ level: "EXPENSIVE", color: "goldenrod" },
{ level: "NORMAL", color: "green" },
{ level: "CHEAP", color: "limegreen" },
{ level: "VERY_CHEAP", color: "lightgreen" } ]
var startsAt = new Date(x.startsAt)
var d = new Date()
var sday = ""
if (startsAt.getDay() == d.getDay())
sday = "heute"
else
sday = "morgen";
'<div style="color: black; background-color: ' + colors.find(c => c.level === x.level).color + '">'
+ sday + " ab " + startsAt.getHours().toLocaleString('en-US', {minimumIntegerDigits: 1}) + " Uhr" +
'</div>'
}
align: center
- name: Gesamtpreis
data: today
modify: |
{
var colors = [
{ level: "VERY_EXPENSIVE", color: "red" },
{ level: "EXPENSIVE", color: "goldenrod" },
{ level: "NORMAL", color: "green" },
{ level: "CHEAP", color: "limegreen" },
{ level: "VERY_CHEAP", color: "lightgreen" } ]
'<div style="color: black; background-color: ' + colors.find(c => c.level === x.level).color + '">'
+ (x.total * 100).toFixed(2) +
' Ct/kWh</div>'
}
align: center
This drives me maaaaaaaad :-(
Now I tried to sort the "today-prices" (total) in ascending order and thought that this couldn't be a big problem - only change the "sort_by" and that's it. But I failed again. The table is only sorted by the "startsAt" column but not by the price. My intention was to have a table with maybe 3 to 5 rows showing the cheapest prices and the "startsAt" column.
The problem is on the data format. This card is not prepared to handle fields inside an attribute, so all your columns are showing the same attribute (today
) and, when sorting by that it will always sort by the first column with that attribute.
So, a work around is to have a hidden column first with the data you want to sort.
Something like this:
type: custom:flex-table-card
sort_by:
- today+
title: Tibber - Test
entities:
include: sensor.electricity_price
columns:
- name: Sorting column
data: today
modify: x.total
hidden: true
- name: beginnt
data: today
modify: |
{
var colors = [
{ level: "VERY_EXPENSIVE", color: "red" },
{ level: "EXPENSIVE", color: "goldenrod" },
{ level: "NORMAL", color: "green" },
{ level: "CHEAP", color: "limegreen" },
{ level: "VERY_CHEAP", color: "lightgreen" } ]
var startsAt = new Date(x.startsAt)
var d = new Date()
var sday = ""
if (startsAt.getDay() == d.getDay())
sday = "heute"
else
sday = "morgen";
'<div style="color: black; background-color: ' + colors.find(c => c.level === x.level).color + '">'
+ sday + " ab " + startsAt.getHours().toLocaleString('en-US', {minimumIntegerDigits: 1}) + " Uhr" +
'</div>'
}
align: center
- name: Gesamtpreis
data: today
modify: |
{
var colors = [
{ level: "VERY_EXPENSIVE", color: "red" },
{ level: "EXPENSIVE", color: "goldenrod" },
{ level: "NORMAL", color: "green" },
{ level: "CHEAP", color: "limegreen" },
{ level: "VERY_CHEAP", color: "lightgreen" } ]
'<div style="color: black; background-color: ' + colors.find(c => c.level === x.level).color + '">'
+ (x.total * 100).toFixed(2) +
' Ct/kWh</div>'
}
align: center
But unfortunately I don't get along with the syntax of all this.
It is a YAML using Javascript to create a HTML with CSS... This makes me crazy also... 😜
Slowly but surely I seem to get in...
I added an additional attribute to the sensor (for the future prices of only today)...
future_prices_today: >-
{% if (this.attributes.today | default('unknown')) in ['unknown','unavailable','none'] %}
unknown
{% else %}
{{ (this.attributes.today | default([])) | selectattr('startsAt', 'gt', (now() - timedelta(hours=1)) | string | replace(' ','T')) | list }}
{% endif %}
And now I can sort the prices of only today in ascending order:
type: custom:flex-table-card
sort_by:
- future_prices_today+
max_rows: 10
title: günstigste Strompreise heut
entities:
include: sensor.electricity_price
columns:
- name: Sorting column
data: future_prices_today
modify: x.total
hidden: true
- name: beginnt
data: future_prices_today
modify: |
{
var colors = [
{ level: "VERY_EXPENSIVE", color: "red" },
{ level: "EXPENSIVE", color: "goldenrod" },
{ level: "NORMAL", color: "green" },
{ level: "CHEAP", color: "limegreen" },
{ level: "VERY_CHEAP", color: "lightgreen" } ]
var startsAt = new Date(x.startsAt)
'<div style="color: black; background-color: ' + colors.find(c => c.level === x.level).color + '">'
+ " ab " + startsAt.getHours().toLocaleString('en-US', {minimumIntegerDigits: 1}) + " Uhr" +
'</div>'
}
align: center
- name: Gesamtpreis
data: future_prices_today
modify: |
{
var colors = [
{ level: "VERY_EXPENSIVE", color: "red" },
{ level: "EXPENSIVE", color: "goldenrod" },
{ level: "NORMAL", color: "green" },
{ level: "CHEAP", color: "limegreen" },
{ level: "VERY_CHEAP", color: "lightgreen" } ]
'<div style="color: black; background-color: ' + colors.find(c => c.level === x.level).color + '">'
+ (x.total * 100).toFixed(2) +
' Ct/kWh</div>'
}
align: center
Short feedback... The total-price-sorted table works well. But the WAF (woman acceptance factor) is very low... - "too confusing" :-( "Can you remove this and make a table with the 3 or 4 cheapest hours for today and tomorrow?!?!?!" - That was the only reaction to this. And my answer: "NOOOO I CAN'T!" But this helped me a bit to get a little bit more into the syntax of this YAML-thing. Cheers
Hey Edward, since I am totally unexperienced in programming I had to use "copy-paste" and "try-and-error" for integrating the tibber price graphs into HA. I only used your rest-sensor:
It also states "Cheap, normal and expensive".
Now I wonder if it is possible to create a line or bar chart with the different colors for it. E.g. cheap=green, normal=yellow and expensive=red and/or a sensor which states the times with the cheapest prices maybe like this: "Cheapest today: 01:00:00 - 02:00:00 15:00:00 - 16:00:00" "Cheapest tomorrow: 07:00:00 - 08:00:00"
Do you think it is possible to create something like this?
THANKS so far!