Octopus Energy Integration: Display graph of usage?

Is it possible to display Gas and Electricity usage on statistics graph? Like a bar chart showing how much was used of each every hour over a 24 hour period?

I’m using the very good HomeAssistant-OctopusEnergy integration. It provides usage data for the past 24 hours via the Smart Metre / Octopus’ API. It’d be handy to see what the busy times of usage are for Gas and Electricity in my house.

The integration provides an array showing how much of each resource was used in a 30 min period. There’s a lot of data, but I’m not sure how to turn this into a way that can be displayed as a bar chart in a UI?

Example array in one of the Integration>Sensor>Attributes.
e.g. sensor.octopus_energy_gas_XXXXXX_previous_accumulative_cost → Arrtibutes → Charges

[{'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 0, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 0, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 0, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 1, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 1, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 1, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 1, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 2, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 2, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 2, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 2, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 3, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 3, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 3, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 3, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 4, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 4, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 4, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 4, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 5, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 5, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 5, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 5, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 6, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 6, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 6, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 6, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 7, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '4.522 kWh',
  'cost': '£0.4',
  'from': datetime.datetime(2022, 11, 4, 7, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 7, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '2.738 kWh',
  'cost': '£0.24',
  'from': datetime.datetime(2022, 11, 4, 7, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 8, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '1.295 kWh',
  'cost': '£0.11',
  'from': datetime.datetime(2022, 11, 4, 8, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 8, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 8, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 9, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 9, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 9, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.148 kWh',
  'cost': '£0.01',
  'from': datetime.datetime(2022, 11, 4, 9, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 10, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 10, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 10, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 10, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 11, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.182 kWh',
  'cost': '£0.02',
  'from': datetime.datetime(2022, 11, 4, 11, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 11, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.102 kWh',
  'cost': '£0.01',
  'from': datetime.datetime(2022, 11, 4, 11, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 12, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 12, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 12, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 12, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 13, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.25 kWh',
  'cost': '£0.02',
  'from': datetime.datetime(2022, 11, 4, 13, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 13, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.068 kWh',
  'cost': '£0.01',
  'from': datetime.datetime(2022, 11, 4, 13, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 14, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 14, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 14, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.057 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 14, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 15, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 15, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 15, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 15, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 16, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 16, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 16, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 16, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 17, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 17, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 17, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.045 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 17, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 18, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.636 kWh',
  'cost': '£0.06',
  'from': datetime.datetime(2022, 11, 4, 18, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 18, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '1.068 kWh',
  'cost': '£0.09',
  'from': datetime.datetime(2022, 11, 4, 18, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 19, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.091 kWh',
  'cost': '£0.01',
  'from': datetime.datetime(2022, 11, 4, 19, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 19, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 19, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 20, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '5.659 kWh',
  'cost': '£0.5',
  'from': datetime.datetime(2022, 11, 4, 20, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 20, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '3.443 kWh',
  'cost': '£0.3',
  'from': datetime.datetime(2022, 11, 4, 20, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 21, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '1.716 kWh',
  'cost': '£0.15',
  'from': datetime.datetime(2022, 11, 4, 21, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 21, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '3.045 kWh',
  'cost': '£0.27',
  'from': datetime.datetime(2022, 11, 4, 21, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 22, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '2.977 kWh',
  'cost': '£0.26',
  'from': datetime.datetime(2022, 11, 4, 22, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 22, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.148 kWh',
  'cost': '£0.01',
  'from': datetime.datetime(2022, 11, 4, 22, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 23, 0, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 23, 0, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 4, 23, 30, tzinfo=datetime.timezone.utc)},
 {'consumption': '0.0 kWh',
  'cost': '£0.0',
  'from': datetime.datetime(2022, 11, 4, 23, 30, tzinfo=datetime.timezone.utc),
  'rate': '8.7675p',
  'to': datetime.datetime(2022, 11, 5, 0, 0, tzinfo=datetime.timezone.utc)}]

I use the HA Octopus Energy integration too. Easy to set up, it provides the smart-meter figures for yesterday including tariff and cost.

I have moved on to making my own Octopus API calls (using Node-RED) to get monthly summary data, but your post encouraged me to set up a graph for my electricity import. Useful at the moment as I am trying to set myself up to be ready for the National Grid (Octopus Saver Sessions) ‘paid for not using electricity’ sessions.

I assume you would like something like…?

Octopus daily chart

The best way to get a bespoke graph in HA is by using ApexCharts. This is an extra ‘custom’ dashboard card, and you can find all the details including installation instructions at
https://github.com/RomRider/apexcharts-card

Once the custom card is set up correctly, add a new card to the HA dashboard and select the custom:ApexCharts Card from the bottom of the card list. You will need to post the card yaml configuration directly into the UI card configuration.

This card is designed to plot sensor data directly from history. In our case we are using sensor attribute data, so we have to use the special ‘data generator’ option, which must provide an array of time/value pairs. In this case, the generator uses the JS map function to go through the attribute ‘charges’ array, and create a millisecond timestamp (from the ‘from’ time) and the corresponding value from the consumption figure.

One of the drawbacks of the ApexChart is that everything has to be correct before anything gets plotted, otherwise we end up with nothing or just ‘loading’. The data generator is relatively straightforward. The secret here, since the data we are plotting is for yesterday, is to set the graph span for 24 hours, starting yesterday. The graph plots from ‘now’ by default unless you specify otherwise.

Here is the HA card configuration required. You can experiment with all the various options!
NOTE since the sensor name has my meter ID and MPAN number, I have removed these and you will need to select the correct entity and adjust the configuration accordingly.

type: custom:apexcharts-card
header:
  show: true
  title: Octopus Electricity Import - Yesterday
show:
  last_updated: true
graph_span: 24h
span:
  start: day
  offset: '-1d'
series:
  - entity: >-
      sensor.octopus_energy_electricity_*METER*_*MPAN*_previous_accumulative_consumption
    data_generator: |
      return entity.attributes.charges.map((reading) => {
        return [new Date(reading.from).getTime(), reading.consumption];
      });
    type: column
    color: Purple

Having just put this together, I have yet to see what happens tonight/tomorrow when the integration pulls ‘null’ until the next set of readings arrives after 9:00. Probably more work is required, but hopefully this is a good start!

And, if anyone from Octopus is reading this, I am still waiting for my ‘Octopus’ toy, ordered when I ‘joined’ Octopus last year when my old supplier went to the wall.

PS.
The gas graph equivalent is much the same, just adjust the series to change the sensor for the gas consumption, change the generator to use the ‘consumption_kwh’ figure, and add ‘unit: kWh’ to the end. The default gas sensor unit is m3 (not kWh) and this shows when hovering over the graph, so the unit setting can be used to override this.

series:
  - entity: >-
      sensor.octopus_energy_gas_*METER*_*NUMBER*_previous_accumulative_consumption
    data_generator: |
      return entity.attributes.charges.map((reading) => {
        return [new Date(reading.from).getTime(), reading.consumption_kwh];
      });
    type: column
    color: Green
    unit: kWh

3 Likes

Some further tinkering…

I finally managed to work out how the data generator code works, and have changed the code to sum each pair of half hour periods into one hour - this makes the graph a little simpler and gives energy use in kWh per hour for each full hour.

The graph is set to display ‘yesterday’. The Octopus electricity readings are updated in the early morning, usually by 9:00. After midnight and before the update the graph will be blank, but will show the previous day readings following the update. The gas readings take much longer to update, and often do not appear until 16:00. This results in a blank graph for most of the day, so I have modified the code to check if the attribute values are for the day before yesterday, and if so, to add one day to the timestamp. This brings the readings for the day before yesterday into the graph period, so that something will be displayed. Then, at the update for yesterday, the new readings for yesterday will be displayed. However, this results in the day before yesterday pretending to be yesterday, and as I have not found a way of showing this in the header, I have coded this to set the gas consumption at 00:00 to -1 as a way of visually showing that the displayed readings are one day older than as displayed.

Also extra settings to set the y-axis limits.

New graphs… Note the gas shows -1 kWh at 00:00 to indicate that it is, in fact, readings for the day before yesterday and not yesterday.

Configuration code for Gas (again update the entity sensor to the correct one)

type: custom:apexcharts-card
header:
  show: true
  title: Octopus Gas kWh - Previous
show:
  last_updated: true
graph_span: 24h
span:
  start: day
  offset: '-1d'
series:
  - entity: >-
      sensor.octopus_energy_gas_xxxxxx_xxxxx_previous_accumulative_consumption
    data_generator: |
      let array = entity.attributes.charges;
      let delta = Date.now() - (new Date(array[array.length-1].to).getTime());
      if (delta >86400000) {delta=86400000} else {delta=0};
      let final = [];
      let i=0;
      let j=0;
      for (i=0; i<array.length-1; i=i+2){
        final[j] = [(new Date(array[i].from).getTime())+delta, array[i].consumption_kwh + array[i+1].consumption_kwh];
        j++;
      };
      if (delta>0) {final[0][1]=-1}
      return final;
    type: column
    color: green
    unit: kWh
yaxis:
  - min: -1
    max: '|+0.5|'

Electricity…

type: custom:apexcharts-card
header:
  show: true
  title: Octopus Electricity Import - Yesterday
show:
  last_updated: true
graph_span: 24h
span:
  start: day
  offset: '-1d'
series:
  - entity: >-
      sensor.octopus_energy_electricity_*METER*_*MPAN*_previous_accumulative_consumption
    data_generator: |
      let array = entity.attributes.charges;
      let final = [];
      let i=0;
      let j=0;
      for (i=0; i<array.length-1; i=i+2){
        final[j] = [new Date(array[i].from).getTime(), array[i].consumption + array[i+1].consumption];
        j++;
      };
      return final;
    type: column
    color: purple
yaxis:
  - min: 0
    max: '|+0.5|'

The data generator for ApexCharts has been bothering me for a long time. At long last I finally understand what is going on, and how to write new generator code. Thank you for asking your question and encouraging me to learn!

6 Likes

Wow, it’s people like you working through edge cases that make the HomeAssistant community so great. Thank you. This is exactly what I was trying to achieve. The data is all there I just didn’t know how to manipulate it into something useful.

Your updated code snippets work perfectly. Thank you.

I don’t really understand the JS side of things due to lack of experience. How would you use Apexcharts to show £cost breakdown charges? I’ve had a play with the data generator but not having any luck getting a chart to appear. The cost of energy in our household for gas and electricity makes more meaningful sense. Especially as we don’t have an In Home Display, only a smart metre.

E.g.

{{ state_attr('sensor.octopus_energy_gas_XXXXXXXX_previous_accumulative_cost', 'charges')|map(attribute='cost')|list }}

[
  "£0.0",
  "£0.0",
  "£0.0",
  "£0.0",
  "£0.0",
  "£0.0",
  "£0.0",
  "£0.0",
  "£0.0",
  "£0.0",
  "£0.0",
  "£0.0",
  "£0.0",
  "£0.0",
  "£0.4",
  "£0.24",
  "£0.11",
  "£0.0",
  "£0.0",
  "£0.01",
  "£0.0",
  "£0.0",
  "£0.02",
  "£0.01",
  "£0.0",
  "£0.0",
  "£0.02",
  "£0.01",
  "£0.0",
  "£0.0",
  "£0.0",
  "£0.0",
  "£0.0",
  "£0.0",
  "£0.0",
  "£0.0",
  "£0.06",
  "£0.09",
  "£0.01",
  "£0.0",
  "£0.5",
  "£0.3",
  "£0.15",
  "£0.27",
  "£0.26",
  "£0.01",
  "£0.0",
  "£0.0"
]

I’m in the same boat as you. Trying to see how and when our energy is being consumed so that we can anticipate the upcoming National Grid (Octopus Saver Sessions).

I like to pick one or two questions and treat them as a learning challenge - I usually get as much out of it myself as the recipient of the answer.

ApexCharts is a very powerful charting tool, but a bit complicated at first. The chart either takes a sensor entity, and plots history from the HA recorder database, or you have to provide an array of data, which is where the data-generator comes in to play. What the chart wants is an array of pairs of timestamps (in milliseconds) and values (as numbers) for example [[timestamp1, value1], [timestamp2, value2]].

What I have found with ApexCharts is that, unless everything is correct, nothing much appears. Editing the data generator code in the configuration UI is also dynamic - the chart continually tries to run the code to show a preview, and making changes and any mistake can lock up the page. I had to edit my for-loops very carefully.

If you look at the integration ‘cost’ sensor

sensor.octopus_energy_electricity_xxx_xxx_previous_accumulative_cost

you will see that this also has a ‘charges’ array in attributes, with not only the ‘consumption’, but also ‘rate’ and ‘cost’. It is a simple matter of changing the code and entity names. Replace ‘consumption’ with ‘cost’ in both the entity and in the data-generator code.

The problem you have found is that the cost is a string being £1.23, and the ‘£’ at the front stops the charts from working. To address this we need a bit of extra code to take just the number part.

.substring(1) does the trick (note the ‘.’) - this takes the given string and returns a substring, starting at 1 (index starts at position 0) and, with no other parameters, goes to the end of the string. This thus removes the £ and returns just the number part.

series:
  - entity: >-
      sensor.octopus_energy_electricity_xxxx_xxxx_previous_accumulative_cost
    data_generator: |
      let array = entity.attributes.charges;
      let final = [];
      let i=0;
      let j=0;
      for (i=0; i<array.length-1; i=i+2){
        final[j] = [new Date(array[i].from).getTime(), array[i].cost.substring(1) + array[i+1].cost.substring(1)];
        j++;
      };
      return final;
    type: column
    color: purple;

I have just pasted the important bit of the config. This seems to work - and since the entity has units of GBP, the graph units should also be correct.

3 Likes

Thank you. And I really appreciate you explaining it in a succinct and helpful way.

Mind sharing your Node-Red setup for making calls to the Octopus API?

OK. So the easy part is making the API call.

The hard part is processing the return JSON into something useful, but as you asked for the code to make the call, here it is.

Octopus API call in Node-RED

This is why I really like Node-RED. Simple and not a bit of code in sight.

[{"id":"96d7391878e82aea","type":"http request","z":"2dd6b0b4a5f86125","name":"GET","method":"GET","ret":"obj","paytoqs":"query","url":"","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"credentials":{},"x":430,"y":2160,"wires":[[]]},{"id":"c32b351424d19047","type":"template","z":"2dd6b0b4a5f86125","name":"URL","field":"url","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"https://{{apikey}}:@api.octopus.energy/v1/electricity-meter-points/{{mpan}}/meters/{{meter}}/consumption","output":"str","x":310,"y":2160,"wires":[["96d7391878e82aea"]]},{"id":"7e246b56908e9e73","type":"change","z":"2dd6b0b4a5f86125","name":"Parms","rules":[{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"mpan","pt":"msg","to":"put your mpan number (as string) here","tot":"str"},{"t":"set","p":"meter","pt":"msg","to":"put your meter number here","tot":"str"},{"t":"set","p":"apikey","pt":"msg","to":"put your private (keep secret) apikey here","tot":"str"},{"t":"set","p":"payload.page_size","pt":"msg","to":"1010","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":190,"y":2160,"wires":[["c32b351424d19047"]]}]

To make this work, you will need

  • an API key from Octopus (do not disclose this to ANYONE)
  • your meter details

All the documentation for the API calls can be found at
https://developer.octopus.energy/docs/api/

Note.
You get your personal API key from your Octopus dashboard (as a customer).
You select the API call you need - my example above is for requesting electricity meter consumption. There is a different API call for gas consumption, and different ones for tariffs etc.
If you have Octopus electricity export, you will have one mpan and two meter numbers - one meter number will be for your import, and the other for your export.
You can add parameters to the call, for example group_by or page_size. In my example the return will be limited to 1010 individual records, each record is for the consumption over 30 minutes, hence this is the data 21 days + 2 records. The data you get back is in reverse chronological order, and there is an odd 1 hour offset, so 1010 records ensure that I get the last 21 days worth of electricity import meter readings. I recommend using the group_by option too!

After that, I recommend JSONata for processing the data into something useful.

2 Likes

This is great work…! I have installed the Octopus integration and already have apex charts up and running for other things. I have created the charts, but just get ‘loading’ and the Octopus usage entities are currently showing as 0. The rate detail ones are correct. Can I assume that the usage based ones will update over night? Or should the initial installation of the integration have pulled in previous readings for past days?

Edit… I’ve got this running on the electric side by expanding the graph to 48 hrs - it seems my data availability is even worse! I still dont get anything for gas, but will keep playing.
I will have a play around and see how I can pull the Total out to display on the chart too

In the UK, smart meters hold half-hourly readings for up to 13 months in the meter memory. The electricity meter updates (to the ‘in home display’) regularly - the gas meter being battery powered, updates to the electricity meter less frequently to conserve the battery.
The meter readings are collected to the backbone data network overnight. Octopus then have to pull this data and assign it to customer accounts, which happens during the following day. At some point in the day therefore, a customer meter reading history will suddenly have an extra 48 records (yesterday) appended.

The HA Octopus integration seems to regularly (every 30 minutes?) call for meter readings throughout the day. The integration appears to call for 48 readings covering just 00:00 to 23:30 but only for yesterday’s readings. The values held by the integration entities are for the latest 48 readings, and these seem to be replaced only when the most recent 48 are for a new day. I find from experience that, for me, the new electricity readings for yesterday usually appear around 7:30 in the morning but that the gas readings will not arrive until much later, often around 16:30 but sometimes early evening or even not at all.

The Apex chart card will display for any time period you wish, but clearly asking the graph to show 00:00 to 23:59 yesterday will not show anything if there are no data values covering that period. Since the gas meter readings are often late, I have set the data-generator code to move the currently held integration values into the ‘today’ window for the graph, even if they are still for the day before yesterday. This gives a graph of the ‘previous’ gas meter readings if they are for yesterday, or if still the day before. It won’t show anything if the integration held readings are older than that.

Using the HA settings integration / entities view it is easy to check the Octopus Gas Prev Acc Used entity - the history chart will show a step-change at the time when the integration has updated the entity state (the total figure), and the attributes section will show the readings held in the ‘charges’ array.

Apex charts is very powerful and can do a great deal, but the data here is generated using Javascript code. I assume that this has to run using the browser JS execution engine, and there are times when the browser cache can show the page but without regenerating the necessary data. In this case you will see ‘loading’ and not much else - refreshing the page often helps.

1 Like

Just set everything up and its working perfectly! For the life in me I can’t figure out how to resize these charts… do i have to add like height: somewhere? For some reason they’re defaulting to some hugeee value

yes, at at bottom of the YAML add:

apex_config:
  chart:
    height: 200

Hi

Since the latest Octopus integration update my apex chart showing the previous days consumption by attribute no longer works / loads data . The entity is correct . But the chart does not load any data
Regards
NS

Sorry to drag up a year old post, but I have been using your yaml code for about six months with no problems, and recently the octopus integration update to V9 has broken the graphs.

I am no coding expert, but have established the portion which no longer plots is the data_generator, as when I comment it out I get the accumulative plot of the usage - just not broken down into 30min chunks.

Given I am a code newbie, would you mind helping me out?

Well, where did the year go to?

BottlecapDave has been very busy updating the Octopus integration, and alerted by your post I can see that V9 came out a few days ago (great new features too…). I update everything manually, and I usually wait until I have time and space in case of issues.

In this update I read that there is a long list of breaking changes, and I expect that almost anything using the integration entities will need some modification.

I need to be home on my PC to look at this properly, and I already have a backlog of recent breaking changes in Samba share and Node-RED to deal with, so this is just a suggestion for you to try and fix it yourself.

In the breaking changes the following is the reason why the data generator is no longer working with the timestamps.

Any previous references to valid_from/valid_to,
interval_start/interval_end or from/to have now been changed to
start/end. This change may take a little while to propagate while old
data is replaced. Any reliances on these attribute names will need to be
updated.

My JS for the data generator uses ‘from’, and this is now ‘start

You should be able to make the changes and test. Everything else looks good still, so try this and see.

The pricing cost has also changed from a £ string to a number, so this will need looking at, and various names have changed, so plenty to look at!

3 Likes

Thank you very much the help! I have managed to get the electricity import charts up and running once more. So that is a great start. Thanks again, really appreciate it.

I can’t get mine to work - I just get the error message 'apexcharts-card
Entity not available: sensor.octopus_energy_electricity_xxxxxxxxxxx_xxxxxxxxxxxxx_previous_accumulative_consumption [the x’s are my meter number followed by my mpan number]

I’ve checked, and the entity is there, but it’s shown as ‘not loaded’ - any ideas how I can get it to load? Do I have to be an Octopus Agile customer? (I’ve got Octopus EV Go tarrif, but I’m interested to watch the difference in price)

Thanks

did you replace from with start as mentioned a couple of posts above?

This graph display shows past period consumption using the Octopus Energy integration.

The sensor.octopus_energy_electricity_xxx_xxx_previous_accumulative_consumption is created by the integration, and will be updated once a day (with details of the previous day values).

If you have the entity showing in HA, then you probably have the integration working. This requires an Octopus Energy account, it does not matter what your tariff is. Worth checking that you have other entities being updated to check that you have indeed correctly setup the integration configuration.

If the entity is ‘not loaded’, then it is probably not loaded. There are two likely reasons for this

1 the entity is disabled. Many of the integration entities are disabled by default, and you need to go to the settings entity page, find the entity you want, and use the setting option to enable it. Then wait for it to become available (and also wait for it to be populated).

2 you have just created the integration. The integration will only call the Octopus API roughly once per day for this particular entity (there is no point in updating it every five minutes, and Octopus don’t want to be flooded by pointless API calls). In simple terms, the entity gets updated during the day with the consumption value(s) of the previous day. Electricity prior consumption update usually happens around 10:00 in the morning, but can be as late as 18:00, so you may have to wait.

This entity and graph example only shows the prior consumption. It is nothing to do with the rate/price.

Thanks for your suggestions. I’ve checked and the entity isn’t disabled. I didn’t realise that it was created by the integration. Yes, I want to see past 24hrs consumption (as well as the agile price graph - sorry I got confused!). The octopus entities that I had already installed from the Octopus integration seem to generally be working (though not all of them), so maybe I have to wait until tomorrow morning to see if it comes through. I thought the ‘not loaded’ message meant that it wasn’t functioning, as opposed to what you’re saying - that it simply hasn’t been updated by Octopus yet. Thankyou - I’ll be patient and see if it starts working tomorrow!

I’ve also changed the ‘from’ in the code to ‘start’…when I worked out where to find it!