Tibber - Schedul prices upcoming 24 hours prices!

Same problem with no price for tomorrow. ENERGY USEAGE SENSOR is a Tibber entity that displays monthly usage.

Mind exporting your flow and share?

I don’t see that I have that sensor. Maybe it comes with their HAN port reader? I am using my own ESPHome based.

The reason the graph does not show tomorrow I think must be because the script returns today’s price immediately and that the second return is just dead code. I’m guessing the arrays new to be combined before returning.

oh, sorry I didn’t notice, it’s not a tibber sensor, I get this from discovergy integration.

I see that tibber is reporting consumption for me in this sensor:

- platform: rest
  name: Tibber consumption
  resource: https://api.tibber.com/v1-beta/gql
  method: POST
  scan_interval: 60
  payload: '{ "query": "{viewer{homes{consumption(resolution: HOURLY, last: 24) { nodes {from cost consumption}}}}}" }'
  json_attributes_path: "$.data.viewer.homes[0].consumption"
  json_attributes:
    - nodes
  value_template: Ok
  headers:
    Authorization: "**[APIKEY]**"
    Content-Type: application/json
    User-Agent: REST

and apex config:

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: 24h
span:
  start: day
yaxis:
  - id: kWh
    decimals: 2
    opposite: true
    apex_config:
      tickAmount: 4
  - id: EUR
    decimals: 2
series:
  - entity: sensor.tibber_consumption
    type: column
    show:
      extremas: true
    name: Usage
    float_precision: 2
    stroke_width: 2
    color: '#64511c'
    opacity: 0.3
    yaxis_id: kWh
    group_by:
      func: avg
      duration: 15min
    data_generator: |
      var a = entity.attributes.nodes.map((entry) => {
        return [new Date(entry.from), entry.consumption];
      }); 
      return a;

if that works for you too, you could put the 2 things together

No probs :slight_smile: It can easily be made by e.g. an utility meter. What kind of data does it provide? Is it hourly, daily or monthly accumulated consumption in kwh? I wonder as when I added one of the sensors I do have (total kwh on the meter from like forever) it did not seem to divide this data into hourly sections but rather just present the value at each hour.

You can choose the period reporting kWh, here I used last 24 hours for each hour.

(resolution: HOURLY, last: 24)

If you go to Tibber Developer you can query your stuff directly. by putting this query for example:

{viewer{homes{consumption(resolution: HOURLY, last: 24) { nodes {from cost consumption}}}}}

or use samples they provide.

And for those not getting pricing data for tomorrow, I see it’s only giving the Today node, not sure why the tomorrow is empty. Today node returns next 24 hours for me starting at midnight today.

Sweet tool there! So did you create a sensor like this for the graph? Or could info already in HA be used instead to avoid polling the API too much?`I’ve heard the tibber API does not allow for that many queries a day. Also local data will update faster than the tibber database as it is read more often. I believe data to tibber is sent in my case through 4G connection (mobile).

EDIT: I created this sensor that works great. Now I just have to figure out how to add it to the chart :slight_smile:
Although using available data in HA from my p1 (HAN) port reader would update the most current data quicker.

- platform: rest
  name: Tibber 24h Hourly Consumption
  resource: https://api.tibber.com/v1-beta/gql
  method: POST
  scan_interval: 60
  payload: '{ "query": "{ viewer { homes { consumption(resolution: HOURLY, last: 24) { nodes {from cost consumption }}}}}" }'
  json_attributes_path: "$.data.viewer.homes[0].consumption"
  json_attributes:
    - nodes
  value_template: Ok
  headers:
    Authorization: !secret tibber_api_token
    Content-Type: application/json
    User-Agent: REST

Yes, below code plots the graph on apexcharts:
You can set scan_interval of the sensor to increase/decrease frequency of polling. They have limit 100 requests in 5 minutes per IP address, so the limit is quite low.

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: 24h
span:
  start: day
yaxis:
  - id: kWh
    decimals: 2
    opposite: true
    apex_config:
      tickAmount: 4
  - id: EUR
    decimals: 2
series:
  - entity: sensor.Tibber_24h_Hourly_Consumption
    type: column
    show:
      extremas: true
    name: Usage
    float_precision: 2
    stroke_width: 2
    color: '#64511c'
    opacity: 0.3
    yaxis_id: kWh
    group_by:
      func: avg
      duration: 60min
    data_generator: |
      var a = entity.attributes.nodes.map((entry) => {
        return [new Date(entry.from), entry.consumption];
      }); 
      return a;

Thanks a lot for the code. It seems unfortunately tibber does not update so fast. Missing all data from today (and its now 20:44)

{
  "data": {
    "viewer": {
      "homes": [
        {
          "consumption": {
            "nodes": [
              {
                "from": "2022-09-17T20:00:00.000+02:00",
                "cost": 0.8351015625,
                "consumption": 0.555
              },
              {
                "from": "2022-09-17T21:00:00.000+02:00",
                "cost": 0.9424128,
                "consumption": 0.896
              },
              {
                "from": "2022-09-17T22:00:00.000+02:00",
                "cost": 1.7347201875,
                "consumption": 1.737
              },
              {
                "from": "2022-09-17T23:00:00.000+02:00",
                "cost": 0.442479375,
                "consumption": 0.675
              },
              {
                "from": "2022-09-18T00:00:00.000+02:00",
                "cost": 0.1590415,
                "consumption": 0.358
              },
              {
                "from": "2022-09-18T01:00:00.000+02:00",
                "cost": null,
                "consumption": null
              },
              {
                "from": "2022-09-18T02:00:00.000+02:00",
                "cost": null,
                "consumption": null
              },
              {
                "from": "2022-09-18T03:00:00.000+02:00",
                "cost": null,
                "consumption": null
              },
              {
                "from": "2022-09-18T04:00:00.000+02:00",
                "cost": null,
                "consumption": null
              },
              {
                "from": "2022-09-18T05:00:00.000+02:00",
                "cost": null,
                "consumption": null
              },
              {
                "from": "2022-09-18T06:00:00.000+02:00",
                "cost": null,
                "consumption": null
              },
              {
                "from": "2022-09-18T07:00:00.000+02:00",
                "cost": null,
                "consumption": null
              },
              {
                "from": "2022-09-18T08:00:00.000+02:00",
                "cost": null,
                "consumption": null
              },
              {
                "from": "2022-09-18T09:00:00.000+02:00",
                "cost": null,
                "consumption": null
              },
              {
                "from": "2022-09-18T10:00:00.000+02:00",
                "cost": null,
                "consumption": null
              },
              {
                "from": "2022-09-18T11:00:00.000+02:00",
                "cost": null,
                "consumption": null
              },
              {
                "from": "2022-09-18T12:00:00.000+02:00",
                "cost": null,
                "consumption": null
              },
              {
                "from": "2022-09-18T13:00:00.000+02:00",
                "cost": null,
                "consumption": null
              },
              {
                "from": "2022-09-18T14:00:00.000+02:00",
                "cost": null,
                "consumption": null
              },
              {
                "from": "2022-09-18T15:00:00.000+02:00",
                "cost": null,
                "consumption": null
              },
              {
                "from": "2022-09-18T16:00:00.000+02:00",
                "cost": null,
                "consumption": null
              },
              {
                "from": "2022-09-18T17:00:00.000+02:00",
                "cost": null,
                "consumption": null
              },
              {
                "from": "2022-09-18T18:00:00.000+02:00",
                "cost": null,
                "consumption": null
              },
              {
                "from": "2022-09-18T19:00:00.000+02:00",
                "cost": null,
                "consumption": null
              }
            ]
          }

EDIT:
This worked instead with my existing sensor


  - entity: sensor.cumulative_active_import
    type: column
    show:
      extremas: true
    name: Usage P1
    float_precision: 2
    color: a4ddc6
    opacity: 0.2
    yaxis_id: kWh
    group_by:
      func: diff
      duration: 60min
      start_with_last: true
    stroke_width: 4

Thanks for the ideas @p1ranha! I got it quite good. I get the usage from a local sensor (P1/HAN port on the meter, not connected to Tibber).

The red and purple lines are not straight… And the current energy consumption are not shown, because I use a cumulative-sensor. I have a momentary sensor: sensor.electricity_meter_momentary_active_import where I get currently measured kW. Can I include it in some way?

And, I still don’t get the tomorrow prices. I checked the sensor sensor.tibber_prices and both today and tomorrow are present!

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
    apex_config:
      tickAmount: 4
  - id: SEK
series:
  - entity: sensor.electricity_meter_cumulative_active_import
    type: column
    show:
      extremas: true
    name: Usage
    stroke_width: 2
    color: '#64511c'
    opacity: 0.3
    yaxis_id: kWh
    group_by:
      func: diff
      duration: 60min
      start_with_last: true
  - 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: SEK
    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.electricity_price_home
    extend_to: now
    show:
      extremas: true
    color: pink
    stroke_width: 5
    yaxis_id: SEK
    name: price
  - entity: sensor.electricity_price_home
    stroke_width: 2
    show:
      legend_value: false
      extremas: true
    curve: smooth
    attribute: min_price
    name: MIN
    color: green
    yaxis_id: SEK
    type: line
    group_by:
      duration: 24hours
      func: min
  - entity: sensor.electricity_price_home
    stroke_width: 2
    yaxis_id: SEK
    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.electricity_price_home
    attribute: max_price
    stroke_width: 2
    curve: smooth
    show:
      legend_value: false
      extremas: true
    name: MAX
    color: red
    yaxis_id: SEK
    type: line
    group_by:
      duration: 24hours
      func: max

I did this to get mine working

    data_generator: |
      var today = entity.attributes.today.map((record, index) => {
              return [record.startsAt, record.total];
            });
      var tomorrow = entity.attributes.tomorrow.map((record, index) => {
              return [record.startsAt, record.total];
            });

      return today.concat(tomorrow);
1 Like

Holy shit. I totally missed this. Sorry.

But I reworked it a little so there’s only one function node to manage everything.
You have to fix the correct API endpoint in the Tibber nodes.

You have to create these helper entities.

input_number.elpris_gransvarde_low
input_number.elpris_gransvarde_hog
input_number.elpris_granspris_lag
input_number.elpris_granspris_hog

This is the Node-RED code.

[{"id":"1896f74a3f62ef44","type":"tibber-data","z":"ce6c5295294be6b3","name":"Get Todays Prices","active":true,"apiEndpointRef":"70b33fa87d346e0c","queryName":"getTodaysEnergyPrices","homeId":"","energyResolution":"HOURLY","lastCount":10,"x":950,"y":540,"wires":[["b290b2d2ee300d33"]]},{"id":"2ea2b8506beee228","type":"tibber-data","z":"ce6c5295294be6b3","name":"Get Tomorrows Prices","active":true,"apiEndpointRef":"70b33fa87d346e0c","queryName":"getTomorrowsEnergyPrices","homeId":"","energyResolution":"HOURLY","lastCount":10,"x":960,"y":600,"wires":[["099fc427156bf2d1"]]},{"id":"0f8b7329bdb2bcc6","type":"inject","z":"ce6c5295294be6b3","name":"Every hour","props":[],"repeat":"","crontab":"0 0-23 * * *","once":true,"onceDelay":"0.1","topic":"","x":110,"y":360,"wires":[["8b372d2c150e7d33","fe70b9021c349192"]]},{"id":"5a111d474a21d572","type":"time-range-switch","z":"ce6c5295294be6b3","name":"","lat":"","lon":"","startTime":"00:00","endTime":"12:59","startOffset":0,"endOffset":0,"x":690,"y":600,"wires":[[],["2ea2b8506beee228"]]},{"id":"384c206d221964a6","type":"inject","z":"ce6c5295294be6b3","name":"00:00","props":[],"repeat":"","crontab":"00 00 * * *","once":true,"onceDelay":"1","topic":"","x":100,"y":80,"wires":[["5c262db773ec0f5e"]]},{"id":"5c262db773ec0f5e","type":"tibber-data","z":"ce6c5295294be6b3","name":"getHomes","active":true,"apiEndpointRef":"70b33fa87d346e0c","queryName":"getHomes","homeId":"{ payload.[0] }","energyResolution":"DAILY","lastCount":10,"x":330,"y":80,"wires":[["60835a8a05d9df00"]]},{"id":"6adc76948391f8f2","type":"debug","z":"ce6c5295294be6b3","name":"HomeID","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":760,"y":80,"wires":[]},{"id":"60835a8a05d9df00","type":"function","z":"ce6c5295294be6b3","name":"set Home ID","func":"flow.set(\"tibberHome\", msg.payload[0].id)\n\nmsg.payload = msg.payload[0].id;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":550,"y":80,"wires":[["6adc76948391f8f2"]]},{"id":"71e52704cbeaf3d2","type":"function","z":"ce6c5295294be6b3","name":"get Home ID","func":"msg.payload = { \"homeId\": flow.get(\"tibberHome\") };\n\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":690,"y":540,"wires":[["1896f74a3f62ef44","5a111d474a21d572"]]},{"id":"eb5dceff17e2034a","type":"catch","z":"ce6c5295294be6b3","name":"","scope":null,"uncaught":false,"x":1200,"y":80,"wires":[["534fac41780628d8"]]},{"id":"534fac41780628d8","type":"debug","z":"ce6c5295294be6b3","name":"Errors","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1390,"y":80,"wires":[]},{"id":"9f4b345dd3f5ce67","type":"function","z":"ce6c5295294be6b3","name":"Set Price Thresholds","func":"const ha = global.get('homeassistant').homeAssistant.states;\nconst priceThresholdLow = ha[\"input_number.elpris_gransvarde_low\"].state;\nconst priceThresholdHigh = ha[\"input_number.elpris_gransvarde_hog\"].state;\nconst priceLow = ha[\"input_number.elpris_granspris_lag\"].state;\nconst priceHigh = ha[\"input_number.elpris_granspris_hog\"].state;\n\nflow.set(\"priceThresholdLow\", priceThresholdLow);\nflow.set(\"priceThresholdHigh\", priceThresholdHigh);\nflow.set(\"priceLow\", priceLow);\nflow.set(\"priceHigh\", priceHigh);\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":580,"y":200,"wires":[[]]},{"id":"fe70b9021c349192","type":"delay","z":"ce6c5295294be6b3","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":340,"y":360,"wires":[["9f4b345dd3f5ce67"]]},{"id":"8d212665da1bf70e","type":"comment","z":"ce6c5295294be6b3","name":"Hämta och sätt Home ID från Tibber i flow-variabel varje dag klockan 00:00.","info":"Home ID hämtas från Tibber \nvid start av Home Assistant\noch klockan 00:00 varje dygn","x":300,"y":40,"wires":[]},{"id":"411ce4dc63667929","type":"comment","z":"ce6c5295294be6b3","name":"Uppdatera priser, vid ändring av gränsvärde. Processa nya värden för drift.","info":"","x":260,"y":160,"wires":[]},{"id":"0585b5d20bee526d","type":"comment","z":"ce6c5295294be6b3","name":"Hämta priser varje timme och uppdatera drift (under gränsvärde = drift, ovan gränsvärde = stopp).","info":"","x":630,"y":500,"wires":[]},{"id":"f8eab22e0b97916a","type":"comment","z":"ce6c5295294be6b3","name":"Tjonga fast en massa states i olika noder som nyttjas av HA.","info":"","x":1940,"y":500,"wires":[]},{"id":"9c05e6a076cfc05f","type":"comment","z":"ce6c5295294be6b3","name":"Fånga märkliga errors.","info":"","x":1240,"y":40,"wires":[]},{"id":"48d9c102110176cb","type":"comment","z":"ce6c5295294be6b3","name":"Node Red ska först koppla upp sig till HA","info":"","x":440,"y":320,"wires":[]},{"id":"6c9aa1bc149d09bf","type":"comment","z":"ce6c5295294be6b3","name":"I denna funktion sprakar magi.","info":"","x":1560,"y":500,"wires":[]},{"id":"8b372d2c150e7d33","type":"delay","z":"ce6c5295294be6b3","name":"","pauseType":"queue","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"20","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":false,"outputs":1,"x":400,"y":540,"wires":[["71e52704cbeaf3d2"]]},{"id":"27213fa4bc540a8b","type":"ha-button","z":"ce6c5295294be6b3","name":"Update Prices","version":0,"debugenabled":false,"outputs":1,"entityConfig":"0a9777e75cdf4f2e","outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"x":110,"y":200,"wires":[["9f4b345dd3f5ce67","8b372d2c150e7d33"]]},{"id":"1852ad800b07db13","type":"comment","z":"ce6c5295294be6b3","name":"Kör en gång i timmen.","info":"","x":140,"y":320,"wires":[]},{"id":"24fff71dd1ed6384","type":"debug","z":"ce6c5295294be6b3","name":"Process Data","active":true,"tosidebar":true,"console":true,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1800,"y":1380,"wires":[]},{"id":"b290b2d2ee300d33","type":"change","z":"ce6c5295294be6b3","name":"Change payload to today","rules":[{"t":"move","p":"payload","pt":"msg","to":"today","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1230,"y":540,"wires":[["3f60206f132695f8"]]},{"id":"099fc427156bf2d1","type":"change","z":"ce6c5295294be6b3","name":"Change payload to tomorrow","rules":[{"t":"move","p":"payload","pt":"msg","to":"tomorrow","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1240,"y":600,"wires":[["3f60206f132695f8"]]},{"id":"3f60206f132695f8","type":"function","z":"ce6c5295294be6b3","name":"Process Data","func":"// FUNCTION NODE FOR FETCHING PRICES NOW AND TOMORROW.\n// CALCULATING MIN, MAX, THRESHOLDS.\n// SETTING RUNAPPLIANCE LOW AND HIGH ACCORDINGLY.\n\n// TODAY\n\nif (msg.today != null) {\n\n    //Variables\n    const data = msg.today;\n\n    const now = new Date();\n\n    const onehour = new Date();\n    onehour.setHours(onehour.getHours() + 1);\n\n    const twohour = new Date();\n    twohour.setHours(twohour.getHours() + 2);\n\n    const threehour = new Date();\n    threehour.setHours(threehour.getHours() + 3);\n\n    const fourhour = new Date();\n    fourhour.setHours(fourhour.getHours() + 4);\n\n    const fivehour = new Date();\n    fivehour.setHours(fivehour.getHours() + 5);\n\n    const sixhour = new Date();\n    sixhour.setHours(sixhour.getHours() + 6);\n\n    const findTimestampnow = now.setMinutes(0, 0, 0);\n    const findTimestamponehour = onehour.setMinutes(0, 0, 0);\n    const findTimestamptwohour = twohour.setMinutes(0, 0, 0);\n    const findTimestampthreehour = threehour.setMinutes(0, 0, 0);\n    const findTimestampfourhour = fourhour.setMinutes(0, 0, 0);\n    const findTimestampfivehour = fivehour.setMinutes(0, 0, 0);\n    const findTimestampsixhour = sixhour.setMinutes(0, 0, 0);\n\n    //find price now\n    let priceNow = data.find(e => {\n        return (new Date(e.startsAt)).valueOf() == findTimestampnow;\n    });\n\n    //find price in one hour\n    let price1hour = data.find(e => {\n        return (new Date(e.startsAt)).valueOf() == findTimestamponehour;\n    });\n\n    //find price in two hours\n    let price2hour = data.find(e => {\n        return (new Date(e.startsAt)).valueOf() == findTimestamptwohour;\n    });\n\n    //find price in three hours\n    let price3hour = data.find(e => {\n        return (new Date(e.startsAt)).valueOf() == findTimestampthreehour;\n    });\n\n    //find price in four hours\n    let price4hour = data.find(e => {\n        return (new Date(e.startsAt)).valueOf() == findTimestampfourhour;\n    });\n\n    //find price in five hours\n    let price5hour = data.find(e => {\n        return (new Date(e.startsAt)).valueOf() == findTimestampfivehour;\n    });\n\n    //find price in six hours\n    let price6hour = data.find(e => {\n        return (new Date(e.startsAt)).valueOf() == findTimestampsixhour;\n    });\n\n    //Now lets parse the days min and max prices\n    let prices = msg.today\n    let minTotal = prices[0].total\n    let maxTotal = prices[0].total\n\n    prices.forEach(el => {\n        if (el.total < minTotal) minTotal = el.total\n    })\n\n    prices.forEach(el => {\n        if (el.total > maxTotal) maxTotal = el.total\n    })\n\n    //Price threshold, are we ok to run whatever needs to be run?\n    let runApplianceLow = false;\n    let runApplianceHigh = false;    \n    let thresholdLow = minTotal + ((maxTotal - minTotal) * (flow.get(\"priceThresholdLow\") / 100))    \n    let thresholdHigh = minTotal + ((maxTotal - minTotal) * (flow.get(\"priceThresholdHigh\") / 100))\n\n    //Run appliance? Either from threshold or set price levels\n    if (priceNow.total <= thresholdLow) {\n        runApplianceLow = true;\n    } else if (priceNow.total <= flow.get(\"priceLow\")) {\n        runApplianceLow = true;\n    }\n\n    if (priceNow.total <= thresholdHigh) {\n        runApplianceHigh = true;\n    } else if (priceNow.total <= flow.get(\"priceHigh\")) {\n        runApplianceHigh = true;\n    }\n    \n    //Null old payloads\n    msg.payload = null;\n    msg.today = null;\n\n    //Build our payload\n    msg.payload = {\n        priceNow,\n        minTotal,\n        maxTotal,\n        runApplianceLow,\n        runApplianceHigh,\n        thresholdLow,\n        thresholdHigh\n    }\n\n    if (typeof price1hour != \"undefined\") {\n        msg.payload[\"price1hour\"] = price1hour;\n    }\n\n    if (typeof price2hour != \"undefined\") {\n        msg.payload[\"price2hour\"] = price2hour;\n    }\n\n    if (typeof price3hour != \"undefined\") {\n        msg.payload[\"price3hour\"] = price3hour;\n    }\n\n    if (typeof price4hour != \"undefined\") {\n        msg.payload[\"price4hour\"] = price4hour;\n    }\n\n    if (typeof price5hour != \"undefined\") {\n        msg.payload[\"price5hour\"] = price5hour;\n    }\n\n    if (typeof price6hour != \"undefined\") {\n        msg.payload[\"price6hour\"] = price6hour;\n    } \n\n    //Jalla let go\n    return msg;\n}\n\n//TOMORROW\n\nif (msg.tomorrow != null) {\n\n    //Variables\n    const data = msg.tomorrow;\n\n    const tom = new Date();\n    tom.setHours(tom.getHours() + 24);\n\n    const onehour = new Date();\n    onehour.setHours(onehour.getHours() + 1);\n\n    const twohour = new Date();\n    twohour.setHours(twohour.getHours() + 2);\n\n    const threehour = new Date();\n    threehour.setHours(threehour.getHours() + 3);\n\n    const fourhour = new Date();\n    fourhour.setHours(fourhour.getHours() + 4);\n\n    const fivehour = new Date();\n    fivehour.setHours(fivehour.getHours() + 5);\n\n    const sixhour = new Date();\n    sixhour.setHours(sixhour.getHours() + 6);    \n\n    const findTimestamptom = tom.setMinutes(0, 0, 0);\n    const findTimestamponehour = onehour.setMinutes(0, 0, 0);\n    const findTimestamptwohour = twohour.setMinutes(0, 0, 0);\n    const findTimestampthreehour = threehour.setMinutes(0, 0, 0);\n    const findTimestampfourhour = fourhour.setMinutes(0, 0, 0);\n    const findTimestampfivehour = fivehour.setMinutes(0, 0, 0);\n    const findTimestampsixhour = sixhour.setMinutes(0, 0, 0);\n\n    //find price tomorrow\n    let priceTomorrow = data.find(e => {\n        return (new Date(e.startsAt)).valueOf() == findTimestamptom;\n    });\n\n    //find price in one hour\n    let price1hour = data.find(e => {\n        return (new Date(e.startsAt)).valueOf() == findTimestamponehour;\n    });\n\n    //find price in two hours\n    let price2hour = data.find(e => {\n        return (new Date(e.startsAt)).valueOf() == findTimestamptwohour;\n    });\n\n    //find price in three hours\n    let price3hour = data.find(e => {\n        return (new Date(e.startsAt)).valueOf() == findTimestampthreehour;\n    });\n\n    //find price in four hours\n    let price4hour = data.find(e => {\n        return (new Date(e.startsAt)).valueOf() == findTimestampfourhour;\n    });\n\n    //find price in five hours\n    let price5hour = data.find(e => {\n        return (new Date(e.startsAt)).valueOf() == findTimestampfivehour;\n    });\n\n    //find price in six hours\n    let price6hour = data.find(e => {\n        return (new Date(e.startsAt)).valueOf() == findTimestampsixhour;\n    });\n\n    //Min max prices tomorrow\n    let prices = msg.tomorrow\n    let minTotalTom = prices[0].total\n    let maxTotalTom = prices[0].total\n\n    prices.forEach(el => {\n        if (el.total < minTotalTom) minTotalTom = el.total\n    })\n\n    prices.forEach(el => {\n        if (el.total > maxTotalTom) maxTotalTom = el.total\n    })\n\n    //Thresholds tomorrow\n    let thresholdLowTom = minTotalTom + ((maxTotalTom - minTotalTom) * (flow.get(\"priceThresholdLow\") / 100))\n    let thresholdHighTom = minTotalTom + ((maxTotalTom - minTotalTom) * (flow.get(\"priceThresholdHigh\") / 100))\n\n    //Null the old payloads\n    msg.payload = null;\n    msg.tomorrow = null;\n\n    //Build our payload\n    if (typeof priceTomorrow != \"undefined\") {\n        msg.payload = {\n            priceTomorrow,\n            minTotalTom,\n            maxTotalTom,\n            thresholdLowTom,\n            thresholdHighTom\n        }\n    }\n\n    if (typeof price1hour != \"undefined\") {\n        msg.payload[\"price1hour\"] = price1hour;\n    }\n\n    if (typeof price2hour != \"undefined\") {\n        msg.payload[\"price2hour\"] = price2hour;\n    }\n\n    if (typeof price3hour != \"undefined\") {\n        msg.payload[\"price3hour\"] = price3hour;\n    }\n\n    if (typeof price4hour != \"undefined\") {\n        msg.payload[\"price4hour\"] = price4hour;\n    }\n\n    if (typeof price5hour != \"undefined\") {\n        msg.payload[\"price5hour\"] = price5hour;\n    }\n\n    if (typeof price6hour != \"undefined\") {\n        msg.payload[\"price6hour\"] = price6hour;\n    }    \n\n    //Jalla let go\n    return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1520,"y":540,"wires":[["24fff71dd1ed6384","d21bf43301a97314","1ac7b8b302c16ca4","d466832b2120c5b0","2b9e6563bb1d5dab","cc5856cc6cc7f1a7","df0bab559e91b51d","1bf278cc13af329a","e5463d982916c28e","b03b5120dff8cca0","b8c28a61f66732f1","26ed89da0bdfb31e","c00365d6c09f6ffd","3fe5772dda3c2605","00d1ffcc148e9b9d"]]},{"id":"d21bf43301a97314","type":"ha-sensor","z":"ce6c5295294be6b3","name":"Price now","entityConfig":"8930b7772c84df5f","version":0,"state":"payload.priceNow.total","stateType":"msg","attributes":[{"property":"Mintotal","value":"payload.minTotal","valueType":"msg"},{"property":"Maxtotal","value":"payload.maxTotal","valueType":"msg"},{"property":"level","value":"payload.level","valueType":"str"}],"inputOverride":"allow","outputProperties":[],"x":1790,"y":540,"wires":[[]]},{"id":"1ac7b8b302c16ca4","type":"ha-sensor","z":"ce6c5295294be6b3","name":"Price in 1 hour","entityConfig":"887f061916c54562","version":0,"state":"payload.price1hour.total","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1800,"y":660,"wires":[[]]},{"id":"d466832b2120c5b0","type":"ha-sensor","z":"ce6c5295294be6b3","name":"Price in 2 hours","entityConfig":"375aa345a1202971","version":0,"state":"payload.price2hour.total","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1800,"y":720,"wires":[[]]},{"id":"2b9e6563bb1d5dab","type":"ha-sensor","z":"ce6c5295294be6b3","name":"Price in 3 hours","entityConfig":"eb0d4cb5d9d5e7bd","version":0,"state":"payload.price3hour.total","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1800,"y":780,"wires":[[]]},{"id":"cc5856cc6cc7f1a7","type":"ha-sensor","z":"ce6c5295294be6b3","name":"Price in 4 hours","entityConfig":"e1956e8443b7732b","version":0,"state":"payload.price4hour.total","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1800,"y":840,"wires":[[]]},{"id":"df0bab559e91b51d","type":"ha-sensor","z":"ce6c5295294be6b3","name":"Price in 5 hours","entityConfig":"cb2721b09234eda7","version":0,"state":"payload.price5hour.total","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1800,"y":900,"wires":[[]]},{"id":"1bf278cc13af329a","type":"ha-sensor","z":"ce6c5295294be6b3","name":"Price in 6 hours","entityConfig":"10d5cb062d73c8b2","version":0,"state":"payload.price6hour.total","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1800,"y":960,"wires":[[]]},{"id":"e5463d982916c28e","type":"ha-binary-sensor","z":"ce6c5295294be6b3","name":"runApplianceLow","entityConfig":"d789d71f44158785","version":0,"state":"payload.runApplianceLow","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1810,"y":1260,"wires":[[]]},{"id":"b03b5120dff8cca0","type":"ha-binary-sensor","z":"ce6c5295294be6b3","name":"runApplianceHigh","entityConfig":"8f4fb67ec1f422eb","version":0,"state":"payload.runApplianceHigh","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1810,"y":1320,"wires":[[]]},{"id":"b8c28a61f66732f1","type":"ha-sensor","z":"ce6c5295294be6b3","name":"Threshold Low","entityConfig":"3b106120266b6db9","version":0,"state":"payload.thresholdLow","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1800,"y":1020,"wires":[[]]},{"id":"26ed89da0bdfb31e","type":"ha-sensor","z":"ce6c5295294be6b3","name":"Threshold High","entityConfig":"c10f0321b04d4245","version":0,"state":"payload.thresholdHigh","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1800,"y":1080,"wires":[[]]},{"id":"c00365d6c09f6ffd","type":"ha-sensor","z":"ce6c5295294be6b3","name":"Threshold Low Tomorrow","entityConfig":"264e4dee52fefabe","version":0,"state":"payload.thresholdLowTom","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1830,"y":1140,"wires":[[]]},{"id":"3fe5772dda3c2605","type":"ha-sensor","z":"ce6c5295294be6b3","name":"Threshold High Tomorrow","entityConfig":"dd2e464f7101f4e2","version":0,"state":"payload.thresholdHighTom","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1830,"y":1200,"wires":[[]]},{"id":"00d1ffcc148e9b9d","type":"ha-sensor","z":"ce6c5295294be6b3","name":"Price tomorrow","entityConfig":"1d4fcf6095bc6e5b","version":0,"state":"payload.priceTomorrow.total","stateType":"msg","attributes":[{"property":"Mintotal","value":"payload.minTotalTom","valueType":"msg"},{"property":"Maxtotal","value":"payload.maxTotalTom","valueType":"msg"},{"property":"level","value":"payload.priceTomorrow.level","valueType":"msg"}],"inputOverride":"allow","outputProperties":[],"x":1800,"y":600,"wires":[[]]},{"id":"70b33fa87d346e0c","type":"tibber-api-endpoint","feedUrl":"wss://api.tibber.com/v1-beta/gql/subscriptions","queryUrl":"https://api.tibber.com/v1-beta/gql","feedTimeout":"60","name":"Tibber Baby"},{"id":"0a9777e75cdf4f2e","type":"ha-entity-config","server":"1101e9cb.075866","name":"Update Prices","version":6,"entityType":"button","haConfig":[{"property":"name","value":""},{"property":"icon","value":""},{"property":"device_class","value":""}]},{"id":"8930b7772c84df5f","type":"ha-entity-config","server":"1101e9cb.075866","deviceConfig":"","name":"sensor config for Price now","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"Price now"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:currency-usd"},{"property":"unit_of_measurement","value":"SEK/kWh"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"resend":true},{"id":"887f061916c54562","type":"ha-entity-config","server":"1101e9cb.075866","deviceConfig":"","name":"sensor config for Price in 1 hour","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"Price +1 hour"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:currency-usd"},{"property":"unit_of_measurement","value":"SEK/kWh"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"resend":true},{"id":"375aa345a1202971","type":"ha-entity-config","server":"1101e9cb.075866","deviceConfig":"","name":"sensor config for Price in 2 hours","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"Price +2 hours"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:currency-usd"},{"property":"unit_of_measurement","value":"SEK/kWh"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"resend":true},{"id":"eb0d4cb5d9d5e7bd","type":"ha-entity-config","server":"1101e9cb.075866","deviceConfig":"","name":"sensor config for Price in 3 hours","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"Price +3 hours"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:currency-usd"},{"property":"unit_of_measurement","value":"SEK/kWh"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"resend":true},{"id":"e1956e8443b7732b","type":"ha-entity-config","server":"1101e9cb.075866","deviceConfig":"","name":"sensor config for Price in 4 hours","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"Price +4 hours"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:currency-usd"},{"property":"unit_of_measurement","value":"SEK/kWh"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"resend":true},{"id":"cb2721b09234eda7","type":"ha-entity-config","server":"1101e9cb.075866","deviceConfig":"","name":"sensor config for Price in 5 hours","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"Price +5 hours"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:currency-usd"},{"property":"unit_of_measurement","value":"SEK/kWh"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"resend":true},{"id":"10d5cb062d73c8b2","type":"ha-entity-config","server":"1101e9cb.075866","deviceConfig":"","name":"sensor config for Price in 6 hours","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"Price +6 hours"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:currency-usd"},{"property":"unit_of_measurement","value":"SEK/kWh"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"resend":true},{"id":"d789d71f44158785","type":"ha-entity-config","server":"1101e9cb.075866","deviceConfig":"","name":"binary sensor config for runApplianceLow","version":6,"entityType":"binary_sensor","haConfig":[{"property":"name","value":"runApplianceLow"},{"property":"device_class","value":""},{"property":"icon","value":""},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"resend":true},{"id":"8f4fb67ec1f422eb","type":"ha-entity-config","server":"1101e9cb.075866","deviceConfig":"","name":"binary sensor config for runApplianceHigh","version":6,"entityType":"binary_sensor","haConfig":[{"property":"name","value":"runApplianceHigh"},{"property":"device_class","value":""},{"property":"icon","value":""},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"resend":true},{"id":"3b106120266b6db9","type":"ha-entity-config","server":"1101e9cb.075866","deviceConfig":"","name":"sensor config for Threshold Low","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"Threshold Low SEK"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:currency-usd"},{"property":"unit_of_measurement","value":"SEK/kWh"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"resend":true},{"id":"c10f0321b04d4245","type":"ha-entity-config","server":"1101e9cb.075866","deviceConfig":"","name":"sensor config for Threshold High","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"Threshold High SEK"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:currency-usd"},{"property":"unit_of_measurement","value":"SEK/kWh"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"resend":true},{"id":"264e4dee52fefabe","type":"ha-entity-config","server":"1101e9cb.075866","deviceConfig":"","name":"sensor config for Threshold Low Tomorrow","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"Threshold Low Tomorrow SEK "},{"property":"device_class","value":""},{"property":"icon","value":"mdi:currency-usd"},{"property":"unit_of_measurement","value":"SEK/kWh"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"resend":true},{"id":"dd2e464f7101f4e2","type":"ha-entity-config","server":"1101e9cb.075866","deviceConfig":"","name":"sensor config for Threshold High Tomorrow","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"Threshold High Tomorrow SEK"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:currency-usd"},{"property":"unit_of_measurement","value":"SEK/kWh"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"resend":true},{"id":"1d4fcf6095bc6e5b","type":"ha-entity-config","server":"1101e9cb.075866","deviceConfig":"","name":"sensor config for Price tomorrow","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"Price +24 hours"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:currency-usd"},{"property":"unit_of_measurement","value":"SEK/kWh"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"resend":true},{"id":"1101e9cb.075866","type":"server","name":"Home Assistant","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30,"areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true}]

And this is my lovelace-panel for controlling it. There’s a bunch of entities that derives from my Tibber Pulse. It uses stack-in-card (from HACS) and vertical-stack.

views:
  - title: Home
    cards:
      - type: custom:stack-in-card
        cards:
          - type: vertical-stack
            cards:
              - type: entities
                title: Inställningar
                entities:
                  - entity: input_boolean.visa_elpris_installningar
                    name: Visa
          - type: vertical-stack
            cards:
              - type: conditional
                conditions:
                  - entity: input_boolean.visa_elpris_installningar
                    state: 'on'
                card:
                  type: entities
                  title: Gränsvärden
                  entities:
                    - entity: button.nodered_0a9777e75cdf4f2e
                      name: Uppdatera Priser
                    - entity: input_number.elpris_gransvarde_low
                      secondary_info: last-changed
                      name: Gränsvärde låg
                    - entity: input_number.elpris_gransvarde_hog
                      secondary_info: last-changed
                      name: Gränsvärde hög
                    - entity: input_number.elpris_granspris_lag
                      name: Gränspris låg
                      secondary_info: last-changed
                    - entity: input_number.elpris_granspris_hog
                      name: Gränspris hög
                      secondary_info: last-changed
          - type: vertical-stack
            cards:
              - type: conditional
                conditions:
                  - entity: input_boolean.visa_elpris_installningar
                    state: 'on'
                card:
                  type: entities
                  title: Info
                  entities:
                    - entity: sensor.thresholdprices
                      secondary_info: last-changed
                      name: GV idag låg
                    - entity: sensor.threshold_high_sek
                      secondary_info: last-changed
                      name: GV idag hög
                    - entity: sensor.threshold_low_tomorrow_sek
                      secondary_info: last-changed
                      name: GV imorgon låg
                    - entity: sensor.threshold_high_tomorrow_sek
                      secondary_info: last-changed
                      name: GV imorgon hög
                    - entity: binary_sensor.nodered_d789d71f44158785
                      secondary_info: last-changed
                      name: Lågdrift
                    - entity: binary_sensor.runappliancehigh
                      secondary_info: last-changed
                      name: Högdrift
      - type: custom:stack-in-card
        cards:
          - type: vertical-stack
            cards:
              - type: entities
                title: Drift
                entities:
                  - entity: input_boolean.visa_drift
                    name: Visa
          - type: vertical-stack
            cards:
              - type: conditional
                conditions:
                  - entity: input_boolean.visa_drift
                    state: 'on'
                card:
                  type: entities
                  title: Låg
                  entities:
                    - entity: switch.shelly_elpanna_1
                      name: Elpanna
                      secondary_info: last-updated
          - type: vertical-stack
            cards:
              - type: conditional
                conditions:
                  - entity: input_boolean.visa_drift
                    state: 'on'
                card:
                  type: entities
                  title: Hög
                  entities:
                    - entity: switch.shp1
                      secondary_info: last-updated
                      name: Luftavfuktare
                    - entity: sensor.shp1_power
                      name: Effekt
                    - entity: sensor.shp1_energy
                      name: Förbrukning
      - type: custom:stack-in-card
        cards:
          - type: vertical-stack
            cards:
              - type: entities
                title: Mätare
                entities:
                  - entity: input_boolean.visa_matare
                    name: Visa
          - type: vertical-stack
            cards:
              - type: conditional
                conditions:
                  - entity: input_boolean.visa_matare
                    state: 'on'
                card:
                  type: entities
                  entities:
                    - entity: sensor.power_morarpsvagen_14
                      name: Effektuttag nu
                    - entity: sensor.average_power_morarpsvagen_14
                      name: Genomsnittligt effektuttag
                    - entity: sensor.accumulated_cost_morarpsvagen_14
                      name: Kostnad idag
                    - entity: sensor.monthly_cost_morarpsvagen_14
                      name: Kostnad denna månad
                    - entity: sensor.monthly_net_consumption_morarpsvagen_14
                      name: Förbrukning denna månad
                    - entity: sensor.monthly_peak_hour_consumption_morarpsvagen_14
                      name: Högsta effektuttag denna månad
                    - entity: sensor.last_meter_consumption_morarpsvagen_14
                      name: Mätarställning
                    - entity: sensor.current_l1_morarpsvagen_14
                      name: Ström L1
                    - entity: sensor.current_l2_morarpsvagen_14
                      name: Ström L2
                    - entity: sensor.current_l3_morarpsvagen_14
                      name: Ström L3
      - type: custom:stack-in-card
        cards:
          - type: vertical-stack
            cards:
              - type: entities
                title: Priser
                entities:
                  - entity: input_boolean.visa_priser
                    name: Visa
          - type: vertical-stack
            cards:
              - type: conditional
                conditions:
                  - entity: input_boolean.visa_priser
                    state: 'on'
                card:
                  type: entities
                  title: Idag
                  entities:
                    - entity: sensor.nodered_8930b7772c84df5f
                      secondary_info: last-changed
                      name: Pris just nu
                    - type: attribute
                      entity: sensor.electricity_price_morarpsvagen_14
                      attribute: price_level
                      secondary_info: last-changed
                      name: Tibber prisnivå
                    - type: attribute
                      entity: sensor.nodered_8930b7772c84df5f
                      attribute: mintotal
                      suffix: SEK/kWh
                      name: Lägsta
                    - type: attribute
                      entity: sensor.nodered_8930b7772c84df5f
                      attribute: maxtotal
                      suffix: SEK/kWh
                      name: Högsta
                    - entity: sensor.thresholdprices
                      secondary_info: last-changed
                      name: Gränsvärde lågdrift
                    - entity: sensor.threshold_high_sek
                      secondary_info: last-changed
                      name: Gränsvärde högdrift
          - type: vertical-stack
            cards:
              - type: conditional
                conditions:
                  - entity: binary_sensor.tibber_morgondagens_priser
                    state: 'on'
                  - entity: input_boolean.visa_priser
                    state: 'on'
                card:
                  type: entities
                  title: Imorgon
                  entities:
                    - entity: sensor.price_24_hours
                      name: Pris om 24h
                      secondary_info: none
                    - type: attribute
                      entity: sensor.price_24_hours
                      attribute: level
                      secondary_info: last-changed
                      name: Tibber prisnivå
                    - type: attribute
                      entity: sensor.price_24_hours
                      attribute: mintotal
                      suffix: SEK/kWh
                      name: Lägsta
                    - type: attribute
                      entity: sensor.price_24_hours
                      attribute: maxtotal
                      suffix: SEK/kWh
                      name: Högsta
                    - entity: sensor.threshold_low_tomorrow_sek
                      secondary_info: last-changed
                      name: Gränsvärde lågdrift
                    - entity: sensor.threshold_high_tomorrow_sek
                      secondary_info: last-changed
                      name: Gränsvärde högdrift
          - type: vertical-stack
            cards:
              - type: conditional
                conditions:
                  - entity: input_boolean.visa_priser
                    state: 'on'
                card:
                  type: entities
                  title: Kommande timmar
                  entities:
                    - entity: sensor.nodered_887f061916c54562
                      name: +1 timme
                    - entity: sensor.nodered_375aa345a1202971
                      name: +2 timmar
                    - entity: sensor.nodered_eb0d4cb5d9d5e7bd
                      name: +3 timmar
                    - entity: sensor.nodered_e1956e8443b7732b
                      name: +4 timmar
                    - entity: sensor.nodered_cb2721b09234eda7
                      name: +5 timmar
                    - entity: sensor.nodered_10d5cb062d73c8b2
                      name: +6 timmar
      - chart_type: line
        period: 5minute
        days_to_show: 0.5
        type: statistics-graph
        entities:
          - entity: sensor.power_morarpsvagen_14
            name: Effekt
        stat_types:
          - mean
          - sum
          - max
          - min
title: Elpris

Might have missed something, just ask.

Hi, I have created the sensor but it only shows “ok”.
What have I done wrong?
/Niklas

Nothing wrong, it’s by design:

value_template: Ok

The data it fetches (prices) is in the attributes of the sensor Tibber prices.

So if I want the forecast for price, is this the right kind of sensor?
I’m trying to keep up in the discussion… :see_no_evil:

Yes it is. I believe the state is just hardcoded to OK since state is limited to 255 characters or something like that. The data is kept in the attributes instead.
This is what mine looks like:

Then you can create other template sensors based on those attributes (today, tomorrow), with min, max, average etc. depending on your use case.
Or create a price chart for future prices with apex charts. That is what the data generator does, takes the data from the attributes of Tibber Prices and generates a chart from it.

So I guess there is something wrong with my sensor then…

Is there something wrong with this:

  • 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: “[XXXXX]
      Content-Type: application/json
      User-Agent: REST

It seems so yes, not sure if it a formatting issue when pasting in the forum or if your actual yaml has the same. Here is how mine look:

value_template and headers should not have indentation as in your example.

    json_attributes:
      - today
      - tomorrow
    value_template: 'OK'
    headers:
      Authorization: "Bearer *****************************************"
      User-Agent: Home Assistant
      Content-Type: application/json

Now the sensor works great.
Now I just want to have the predicted price in a simple apex chart but can’t get it to show properly.
This only show todays historical prizes: (copy/paste so maybe code seems wrong but it works, not just showing tomorrow’s prize)

type: custom:apexcharts-card
header:
show: true
title: ApexCharts-Card
show_states: true
colorize_states: true
series:

  • entity: sensor.tibber_prices
    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];
    });