Tibber - Schedul prices upcoming 24 hours prices!

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!? :slight_smile:

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

GitHub - Danielhiversen/home_assistant_tibber_custom: Display Tibber prices and energy consumption as a graph. Tibber is available in Germany, Norway and Sweden Tibber has helped tens of thousands of new customers each month in Sweden, Norway & Germany to lower their energy bill and consumption. Tibber is using digital technology to make electricity consumption smarter. If you use this link to signup for Tibber, you get 50 euro to buy smart home products in the Tibber store: https://invite.tibber.com/6fd7a447 is a possible option to display future prices

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 :slight_smile: … 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 :slight_smile: ( 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” :slight_smile:
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 ? :slight_smile:

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.

2 Likes

ah ok, cool , thou i need to “read up” in regards to python … im an old-school microsoft-system-admin :slight_smile: , 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 :slight_smile:

I got this graph with the use of apex graphs and node red. I can post my solution if anyone is interested

1 Like

Please do! @philsson

Sorry for the very late reply but here it is.
image

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
2 Likes

Thanks so much @philsson! Much appreciated.

1 Like

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:

  • [YOUR TIBBER ENERGY USAGE SENSOR] - any sensor really showing your consumption
  • [YOUR TIBBER PRICE SENSOR] - regular tibber sensor giving you the price (with mix, max, avg attributes)
6 Likes

Neat solution! And very nice work you’ve done on the graph. I tried doing it your way and ran into two problems.

  • I do not see prices for tomorrow
  • I don’t know what sensor to use for [YOUR TIBBER ENERGY USAGE SENSOR]. Nothing I’ve tried with produces what you’re showing there. Do I need a daily utility meter for the consumption?

…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;
1 Like