Maybe it is not available by the API but it would be more interesting and useful for automation to know upcoming hours KWh pricing rather than historical, however one doesn’t exclude the other I guess!?
Thanks!
Ricard
Maybe it is not available by the API but it would be more interesting and useful for automation to know upcoming hours KWh pricing rather than historical, however one doesn’t exclude the other I guess!?
Thanks!
Ricard
Hi Boheme61, deleted reply by mistake maybe?
Now I saw your deleted reply, "depending on HA version and/or Tibber integration version.
I am running latest HA 2.2.6, however Tibber plug-in I tried to find a version indicator but failed.
Checking Documentation page for Tibber plug-in do not indicate future price feature?
Thanks!
As you might know, Tibber is no longer a “Custom-Component” , if you read the arguments/discussions up to the decision to include Tibber in the Default HA core, you might understand the reason why “Future statistics” is not included in default Tibber-integration … there are also other ways to get “future prices” but as all, everything comes with a “price” (Usage !) … you could take a look at Nordpool integration ( Also a custom integration !)
The Tibber integration has never been a custom component.
Home Assistant does not support future values very well today, Sensor entity value forcasting / prediction · home-assistant/architecture · Discussion #667 · GitHub
upps , sorry bout that, was just my thought, when i was reading about it, and the argumentation to get it into HA, i just started with HA in October last year, and i fully understand, that HA not currently support future values well, i did however looked into your camera.py “custom-tibber component” and managed to get out a 48 hour view ( for awhile … im not so familiar with .py and the underlying HA core … anyways, “estimated prices” might be a good indicator, but nothing i would entirely depend on , so i would prefer an automation, to heat my tanks ( i.e as i have the option to power on 2KW-5KW-9KW heaters, so if price goes below a certain X, i start with 2, if it goes even further below X i “release” 5, and then 9, if needed, then ofcause there can be exceptions, where you just need to heat up, regardless of price ( if you didnt get enough, during low-price-time …
ok, i haven’t read /667 before, didn’t know that it is “more than” an estimation, here in sweden , so wouldn’t it be possible to “extract” these time/prices into a static “table” (updated frequently) , and then read from this table (cording to “values” decided in checkbox/string automation) … sorry for my “programming language”
well anyway, im still waiting for EON to change “Meter” here, then i guess i just go for Tibber-Pulse, and see how an automate should look like then, thou still “future prices” should probably be dealt with in and additional/separate integration anyway
@Danielhiversen … I guess this is due to the fact that “tomorrows” prices are available after the “bidding’s” ends at 12AM …
so my thought was … if it’s possible using command line sensor
sensor:
- platform: command_line
command: python3 -c "import requests; print(requests.get('http://remote-host/sensor_data.txt').text)"
name: File value
… but the “external” file is actually local “tomorrow’s price” converted to .txt or .csv … i dont know how the "tomorrow’s prices are exposed to HA, but it seems like it’s within the “default tibber” entity, correct me if im wrong, so instead of showing(storing this) due to usage or other issues/limitations in HA, one could “extract” this to a file(static table, that gets “updated/overwritten” when a new “tomorrow’s price” is available ) and then read from there, when creating an automation … am im out of my mind, or just wishful ?
The prices are already in memory of Home Assistant (if you use the Tibber integration).
Today they are not available for automation.
Here is how you can find the prices:
I do all my automations in Python the same way.
ah ok, cool , thou i need to “read up” in regards to python … im an old-school microsoft-system-admin , thou i can analyze various scripts, but im no programmer, in dept :), and yes i use Tibber integration, Thanks alot for this … i will look more into this, and see what i can figure out, thx … i did see some others creating .json files from external data, but if/when it already in HA memory, might be easyer
Upps, just saw that my met.no have changed ?, hmm … missing the 2 secondary_info_attributes in 1st, and showing state_header in 2nd … must have been tired, or just ordinary messed up in my head, last time i was playing around there
I got this graph with the use of apex graphs and node red. I can post my solution if anyone is interested
Sorry for the very late reply but here it is.
I use the tibber API in Node-Red and publish on topic on mqtt
This is the overview of my flow in Node-Red. A bit messy and could be cleaned up
Here is code for the function nodes starting with “Set Home ID”
flow.set("tibberHome", msg.payload[0].id)
msg.payload = msg.payload[0].id;
return msg;
Get Home ID
msg.payload = { "homeId": flow.get("tibberHome")};
return msg;
Generate array (today)
var priceArray = [];
for (let i = 0; i < 24; i++) {
priceArray[i] = msg.payload[i]["total"];
}
flow.set("pArray", priceArray);
msg.payload = { "day_price": priceArray };
return msg;
Generate array (tomorrow)
var priceArray = [];
for (let i = 0; i < 24; i++) {
try
{
priceArray[i] = msg.payload[i]["total"];
}
catch
{
priceArray[i] = 0.0;
}
}
flow.set("pTomorrowArray", priceArray);
msg.payload = { "tomorrow_price": priceArray };
return msg;
Get next hour price SEK (all prices ink tomorrow)
var priceArray = [];
var priceTomorrowArray = [];
priceArray = flow.get("pArray");
priceTomorrowArray = flow.get("pTomorrowArray");
const today = new Date();
let todayHour = today.getHours();
let todayDate = ("0" + today.getDate()).slice(-2)
let todayMonth = ("0" + (today.getMonth() + 1)).slice(-2);
let todayYear = today.getFullYear();
const tomorrow = new Date();
tomorrow.setDate(today.getDate() + 1);
let tomorrowDate = ("0" + tomorrow.getDate()).slice(-2)
let tomorrowMonth = ("0" + (tomorrow.getMonth() + 1)).slice(-2);
let tomorrowYear = tomorrow.getFullYear();
node.log(priceArray);
var day_ahead_price = priceArray[todayHour];
msg.payload = {
"day_ahead_price": priceArray[todayHour],
"records": [
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T00:00:00",
"Price": priceArray[0]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T01:00:00",
"Price": priceArray[1]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T02:00:00",
"Price": priceArray[2]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T03:00:00",
"Price": priceArray[3]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T04:00:00",
"Price": priceArray[4]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T05:00:00",
"Price": priceArray[5]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T06:00:00",
"Price": priceArray[6]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T07:00:00",
"Price": priceArray[7]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T08:00:00",
"Price": priceArray[8]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T09:00:00",
"Price": priceArray[9]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T10:00:00",
"Price": priceArray[10]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T11:00:00",
"Price": priceArray[11]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T12:00:00",
"Price": priceArray[12]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T13:00:00",
"Price": priceArray[13]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T14:00:00",
"Price": priceArray[14]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T15:00:00",
"Price": priceArray[15]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T16:00:00",
"Price": priceArray[16]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T17:00:00",
"Price": priceArray[17]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T18:00:00",
"Price": priceArray[18]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T19:00:00",
"Price": priceArray[19]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T20:00:00",
"Price": priceArray[20]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T21:00:00",
"Price": priceArray[21]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T22:00:00",
"Price": priceArray[22]
},
{
"Time": todayYear + "-" + todayMonth + "-" + todayDate + "T23:00:00",
"Price": priceArray[23]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T00:00:00",
"Price": priceTomorrowArray[0]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T01:00:00",
"Price": priceTomorrowArray[1]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T02:00:00",
"Price": priceTomorrowArray[2]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T03:00:00",
"Price": priceTomorrowArray[3]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T04:00:00",
"Price": priceTomorrowArray[4]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T05:00:00",
"Price": priceTomorrowArray[5]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T06:00:00",
"Price": priceTomorrowArray[6]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T07:00:00",
"Price": priceTomorrowArray[7]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T08:00:00",
"Price": priceTomorrowArray[8]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T09:00:00",
"Price": priceTomorrowArray[9]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T10:00:00",
"Price": priceTomorrowArray[10]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T11:00:00",
"Price": priceTomorrowArray[11]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T12:00:00",
"Price": priceTomorrowArray[12]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T13:00:00",
"Price": priceTomorrowArray[13]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T14:00:00",
"Price": priceTomorrowArray[14]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T15:00:00",
"Price": priceTomorrowArray[15]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T16:00:00",
"Price": priceTomorrowArray[16]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T17:00:00",
"Price": priceTomorrowArray[17]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T18:00:00",
"Price": priceTomorrowArray[18]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T19:00:00",
"Price": priceTomorrowArray[19]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T20:00:00",
"Price": priceTomorrowArray[20]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T21:00:00",
"Price": priceTomorrowArray[21]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T22:00:00",
"Price": priceTomorrowArray[22]
},
{
"Time": tomorrowYear + "-" + tomorrowMonth + "-" + tomorrowDate + "T23:00:00",
"Price": priceTomorrowArray[23]
}
]
};
return msg;
The mqtt sensor in home assistant
- name: 'Day Ahead Price'
unit_of_measurement: "SEK"
state_topic: enstoe/day-ahead
value_template: '{{ value_json.day_ahead_price }}'
json_attributes_topic: enstoe/day-ahead
This is the code for the graph
type: custom:apexcharts-card
experimental:
color_threshold: true
graph_span: 48h
span:
start: day
now:
show: true
label: Now
header:
standard_format: false
show: true
show_states: true
title: Electricity Price (SEK/KWh)
colorize_states: true
series:
- entity: sensor.day_ahead_price
stroke_width: 2
type: area
opacity: 0.3
data_generator: |
return entity.attributes.records.map((record, index) => {
return [record.Time, record.Price];
});
color_threshold:
- value: 0.5
color: green
- value: 1
color: orange
- value: 2
color: red
show:
extremas: true
in_header: false
- entity: sensor.day_ahead_price
show:
in_chart: false
Is there any chance you could post the whole flow as JSON? You can get it by going to Hamburger Menu → Export
Thanks in advance.
Here you go. I’ve tried to remove sensitive information like my mqtt broker and api keys but besides names and addresses there did not seem to be anything exposed there.
[
{
"id": "a8c760080311f38b",
"type": "inject",
"z": "12d4ba9f6048efc0",
"name": "00:00",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "00 00 * * *",
"once": true,
"onceDelay": "0.1",
"topic": "",
"payload": "",
"payloadType": "date",
"x": 105.66667175292969,
"y": 146,
"wires": [
[
"5bc2f6ca187ea894"
]
]
},
{
"id": "26a8bd5dd6074036",
"type": "debug",
"z": "12d4ba9f6048efc0",
"name": "debug home id",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 669.666690826416,
"y": 145.0000057220459,
"wires": []
},
{
"id": "5bc2f6ca187ea894",
"type": "tibber-data",
"z": "12d4ba9f6048efc0",
"name": "getHomes",
"active": true,
"apiEndpointRef": "5864d476a88382a7",
"queryName": "getHomes",
"homeId": "",
"energyResolution": "DAILY",
"lastCount": 10,
"x": 282.00000381469727,
"y": 146.00000190734863,
"wires": [
[
"ad839c46b2258ca2"
]
]
},
{
"id": "ad839c46b2258ca2",
"type": "function",
"z": "12d4ba9f6048efc0",
"name": "Set Home ID",
"func": "/*\nvar priceArray = [];\nfor (let i = 0; i < 24; i++) {\n priceArray[i] = msg.payload.Publication_MarketDocument.TimeSeries[0].Period[0].Point[i][\"price.amount\"][0];\n}\nflow.set(\"pArray\", priceArray);\nmsg.payload = { \"day_ahead_price\": priceArray };\nreturn msg;\n*/\n\nflow.set(\"tibberHome\", msg.payload[0].id)\n\nmsg.payload = msg.payload[0].id;\n\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 478.00000381469727,
"y": 146.00000190734863,
"wires": [
[
"26a8bd5dd6074036"
]
]
},
{
"id": "dffaa38aa1dfe09d",
"type": "tibber-data",
"z": "12d4ba9f6048efc0",
"name": "getTodaysEnergyPrices",
"active": true,
"apiEndpointRef": "5864d476a88382a7",
"queryName": "getTodaysEnergyPrices",
"homeId": "",
"energyResolution": "DAILY",
"lastCount": 10,
"x": 496.0000915527344,
"y": 332.00000953674316,
"wires": [
[
"20416e46564932e7",
"b101179a02ff89a9"
]
]
},
{
"id": "40e7cb98e3f82e19",
"type": "inject",
"z": "12d4ba9f6048efc0",
"name": "00:01",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "01 00 * * *",
"once": true,
"onceDelay": "1",
"topic": "",
"payload": "",
"payloadType": "date",
"x": 109,
"y": 332.00000953674316,
"wires": [
[
"d16962d1c1a3fe75"
]
]
},
{
"id": "d16962d1c1a3fe75",
"type": "function",
"z": "12d4ba9f6048efc0",
"name": "Get Home ID",
"func": "msg.payload = { \"homeId\": flow.get(\"tibberHome\")};\n\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 275.00000762939453,
"y": 332.00000953674316,
"wires": [
[
"dffaa38aa1dfe09d",
"20416e46564932e7",
"8aa8f7ba7008b5b4"
]
]
},
{
"id": "b101179a02ff89a9",
"type": "function",
"z": "12d4ba9f6048efc0",
"name": "Generate Array",
"func": "var priceArray = [];\nfor (let i = 0; i < 24; i++) {\n priceArray[i] = msg.payload[i][\"total\"];\n}\nflow.set(\"pArray\", priceArray);\nmsg.payload = { \"day_price\": priceArray };\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 747.0000190734863,
"y": 332.00000953674316,
"wires": [
[
"20416e46564932e7"
]
]
},
{
"id": "4ec634cf620861a1",
"type": "tibber-data",
"z": "12d4ba9f6048efc0",
"name": "getTomorrowsEnergyPrices",
"active": true,
"apiEndpointRef": "5864d476a88382a7",
"queryName": "getTomorrowsEnergyPrices",
"homeId": "",
"energyResolution": "DAILY",
"lastCount": 10,
"x": 509.0001335144043,
"y": 461.00002670288086,
"wires": [
[
"9c3849a9607b434c",
"a92cf4c196d82fd9"
]
]
},
{
"id": "a92cf4c196d82fd9",
"type": "function",
"z": "12d4ba9f6048efc0",
"name": "Generate Array",
"func": "var priceArray = [];\nfor (let i = 0; i < 24; i++) {\n try\n {\n priceArray[i] = msg.payload[i][\"total\"];\n }\n catch\n {\n priceArray[i] = 0.0;\n }\n}\nflow.set(\"pTomorrowArray\", priceArray);\nmsg.payload = { \"tomorrow_price\": priceArray };\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 750.0000610351562,
"y": 461.00002670288086,
"wires": [
[
"9c3849a9607b434c",
"e9e23fd396c22b9b"
]
]
},
{
"id": "7baba3034fcff343",
"type": "inject",
"z": "12d4ba9f6048efc0",
"name": "Every hour",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "0 0-23 * * *",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 120,
"y": 645.0000247955322,
"wires": [
[
"dcbd466f11be4ddc"
]
]
},
{
"id": "721de519ee826a48",
"type": "mqttdb out",
"z": "12d4ba9f6048efc0",
"name": "day_ahead_price",
"topic": "enstoe/day-ahead",
"qos": "2",
"retain": "true",
"broker": "80171daa.0027b",
"x": 830.0000228881836,
"y": 597.0000152587891,
"wires": []
},
{
"id": "dcbd466f11be4ddc",
"type": "function",
"z": "12d4ba9f6048efc0",
"name": "Get next hour price SEK (all prices ink tomorrow)",
"func": "var priceArray = [];\nvar priceTomorrowArray = [];\npriceArray = flow.get(\"pArray\");\npriceTomorrowArray = flow.get(\"pTomorrowArray\");\n\nconst today = new Date();\nlet todayHour = today.getHours();\nlet todayDate = (\"0\" + today.getDate()).slice(-2)\nlet todayMonth = (\"0\" + (today.getMonth() + 1)).slice(-2);\nlet todayYear = today.getFullYear();\n\nconst tomorrow = new Date();\ntomorrow.setDate(today.getDate() + 1);\nlet tomorrowDate = (\"0\" + tomorrow.getDate()).slice(-2)\nlet tomorrowMonth = (\"0\" + (tomorrow.getMonth() + 1)).slice(-2);\nlet tomorrowYear = tomorrow.getFullYear();\n\nnode.log(priceArray);\nvar day_ahead_price = priceArray[todayHour];\n\n\nmsg.payload = {\n \"day_ahead_price\": priceArray[todayHour],\n \"records\": [\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T00:00:00\",\n \"Price\": priceArray[0]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T01:00:00\",\n \"Price\": priceArray[1]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T02:00:00\",\n \"Price\": priceArray[2]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T03:00:00\",\n \"Price\": priceArray[3]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T04:00:00\",\n \"Price\": priceArray[4]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T05:00:00\",\n \"Price\": priceArray[5]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T06:00:00\",\n \"Price\": priceArray[6]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T07:00:00\",\n \"Price\": priceArray[7]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T08:00:00\",\n \"Price\": priceArray[8]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T09:00:00\",\n \"Price\": priceArray[9]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T10:00:00\",\n \"Price\": priceArray[10]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T11:00:00\",\n \"Price\": priceArray[11]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T12:00:00\",\n \"Price\": priceArray[12]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T13:00:00\",\n \"Price\": priceArray[13]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T14:00:00\",\n \"Price\": priceArray[14]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T15:00:00\",\n \"Price\": priceArray[15]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T16:00:00\",\n \"Price\": priceArray[16]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T17:00:00\",\n \"Price\": priceArray[17]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T18:00:00\",\n \"Price\": priceArray[18]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T19:00:00\",\n \"Price\": priceArray[19]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T20:00:00\",\n \"Price\": priceArray[20]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T21:00:00\",\n \"Price\": priceArray[21]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T22:00:00\",\n \"Price\": priceArray[22]\n },\n {\n \"Time\": todayYear + \"-\" + todayMonth + \"-\" + todayDate + \"T23:00:00\",\n \"Price\": priceArray[23]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T00:00:00\",\n \"Price\": priceTomorrowArray[0]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T01:00:00\",\n \"Price\": priceTomorrowArray[1]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T02:00:00\",\n \"Price\": priceTomorrowArray[2]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T03:00:00\",\n \"Price\": priceTomorrowArray[3]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T04:00:00\",\n \"Price\": priceTomorrowArray[4]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T05:00:00\",\n \"Price\": priceTomorrowArray[5]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T06:00:00\",\n \"Price\": priceTomorrowArray[6]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T07:00:00\",\n \"Price\": priceTomorrowArray[7]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T08:00:00\",\n \"Price\": priceTomorrowArray[8]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T09:00:00\",\n \"Price\": priceTomorrowArray[9]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T10:00:00\",\n \"Price\": priceTomorrowArray[10]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T11:00:00\",\n \"Price\": priceTomorrowArray[11]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T12:00:00\",\n \"Price\": priceTomorrowArray[12]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T13:00:00\",\n \"Price\": priceTomorrowArray[13]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T14:00:00\",\n \"Price\": priceTomorrowArray[14]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T15:00:00\",\n \"Price\": priceTomorrowArray[15]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T16:00:00\",\n \"Price\": priceTomorrowArray[16]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T17:00:00\",\n \"Price\": priceTomorrowArray[17]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T18:00:00\",\n \"Price\": priceTomorrowArray[18]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T19:00:00\",\n \"Price\": priceTomorrowArray[19]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T20:00:00\",\n \"Price\": priceTomorrowArray[20]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T21:00:00\",\n \"Price\": priceTomorrowArray[21]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T22:00:00\",\n \"Price\": priceTomorrowArray[22]\n },\n {\n \"Time\": tomorrowYear + \"-\" + tomorrowMonth + \"-\" + tomorrowDate + \"T23:00:00\",\n \"Price\": priceTomorrowArray[23]\n }\n ]\n};\n\n//msg.payload = day_ahead_price;\n//msg.payload = priceArray;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 404.66668701171875,
"y": 645.0000495910645,
"wires": [
[
"ef4c837cb008fc3b",
"721de519ee826a48"
]
]
},
{
"id": "038220987cb0c091",
"type": "inject",
"z": "12d4ba9f6048efc0",
"name": "12:01",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "01 12 * * *",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 109,
"y": 375,
"wires": [
[
"d16962d1c1a3fe75"
]
]
},
{
"id": "49b83a4356262b65",
"type": "inject",
"z": "12d4ba9f6048efc0",
"name": "13:01",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "01 13 * * *",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 108,
"y": 418,
"wires": [
[
"d16962d1c1a3fe75"
]
]
},
{
"id": "e9e23fd396c22b9b",
"type": "delay",
"z": "12d4ba9f6048efc0",
"name": "500ms",
"pauseType": "delay",
"timeout": "500",
"timeoutUnits": "milliseconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 452.6666259765625,
"y": 567.9999694824219,
"wires": [
[
"dcbd466f11be4ddc"
]
]
},
{
"id": "8aa8f7ba7008b5b4",
"type": "delay",
"z": "12d4ba9f6048efc0",
"name": "500ms",
"pauseType": "delay",
"timeout": "500",
"timeoutUnits": "milliseconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 368.33331298828125,
"y": 397.3333435058594,
"wires": [
[
"4ec634cf620861a1"
]
]
},
{
"id": "5864d476a88382a7",
"type": "tibber-api-endpoint",
"feedUrl": "wss://api.tibber.com/v1-beta/gql/subscriptions",
"queryUrl": "https://api.tibber.com/v1-beta/gql",
"feedTimeout": "60",
"name": ""
},
{
"id": "80171daa.0027b",
"type": "",
"name": "",
"broker": "",
"port": "",
"clientid": "",
"usetls": false,
"compatmode": true,
"keepalive": "60",
"cleansession": true,
"willTopic": "",
"willQos": "0",
"willPayload": "",
"birthTopic": "",
"birthQos": "0",
"birthPayload": "",
"persistout": true,
"persistin": false,
"compactinterval": "30"
}
]
Thank you very much. After looking at it, and playing around, I decided to stay away from NodeRed and implement native HA solition with REST sensor + Apex Charts:
REST Sensor:
You need to replace [YOUR AUTH CODE FROM TIBBER DEVELOPER PROFILE] with your access token from tibber dev profile
- platform: rest
name: Tibber prices
resource: https://api.tibber.com/v1-beta/gql
method: POST
scan_interval: 60
payload: '{ "query": "{ viewer { homes { currentSubscription { priceInfo { today { total startsAt } tomorrow { total startsAt }}}}}}" }'
json_attributes_path: "$.data.viewer.homes[0].currentSubscription.priceInfo"
json_attributes:
- today
- tomorrow
value_template: Ok
headers:
Authorization: "**[YOUR AUTH CODE FROM TIBBER DEVELOPER PROFILE]**"
Content-Type: application/json
User-Agent: REST
Apex charts YAML
type: custom:apexcharts-card
apex_config:
chart:
height: 500px
header:
show: true
title: Energy stats
show_states: true
colorize_states: true
now:
show: true
color: white
label: NOW
hours_12: false
graph_span: 36h
span:
start: day
yaxis:
- id: kWh
decimals: 0
opposite: true
max: 500
apex_config:
tickAmount: 4
- id: EUR
series:
- entity: sensor.**[YOUR TIBBER ENERGY USAGE SENSOR]**
type: column
show:
extremas: true
name: Usage
stroke_width: 2
color: '#64511c'
opacity: 0.3
yaxis_id: kWh
group_by:
func: avg
duration: 15min
- entity: sensor.tibber_prices
stroke_width: 2
color: blue
curve: smooth
show:
legend_value: false
extremas: true
in_header: false
extend_to: now
yaxis_id: EUR
name: Predicted all
data_generator: |
return entity.attributes.today.map((entry) => {
return [new Date(entry.startsAt), entry.total];
});
return entity.attributes.tomorrow.map((entry) => {
return [new Date(entry.startsAt), entry.total];
});
- entity: sensor.**[YOUR TIBBER PRICE SENSOR]**
extend_to: now
show:
extremas: true
color: pink
stroke_width: 5
yaxis_id: EUR
name: price
- entity: sensor.**[YOUR TIBBER PRICE SENSOR]**
stroke_width: 2
show:
legend_value: false
extremas: true
curve: smooth
attribute: min_price
name: MIN
color: green
yaxis_id: EUR
type: line
group_by:
duration: 24hours
func: min
- entity: sensor.**[YOUR TIBBER PRICE SENSOR]**
stroke_width: 2
yaxis_id: EUR
name: AVG
attribute: avg_price
color: violet
curve: smooth
type: line
show:
legend_value: false
extremas: true
group_by:
duration: 24hours
func: avg
- entity: sensor.**[YOUR TIBBER PRICE SENSOR]**
attribute: max_price
stroke_width: 2
curve: smooth
show:
legend_value: false
extremas: true
name: MAX
color: red
yaxis_id: EUR
type: line
group_by:
duration: 24hours
func: max
You need to replace following sensors above:
Neat solution! And very nice work you’ve done on the graph. I tried doing it your way and ran into two problems.
…and if anybody wants to get upcoming prices extracted into let’s say entities,
then this is the secret sauce in my “Price in x hours” functions:
const data = msg.payload;
const now = new Date();
now.setHours(now.getHours() + 1); //Price in x hours
const findTimestamp = now.setMinutes(0, 0, 0);
msg.payload = data.find(e => {
return (new Date(e.startsAt)).valueOf() == findTimestamp;
});
return msg;