lozzd / octopus-energy-rates-card

This lovelace card for Home Assistant displays the Octopus Energy rate prices per each 30 minute slot
MIT License
60 stars 22 forks source link

Graph of the rates #13

Open plandregan opened 1 year ago

plandregan commented 1 year ago

Is there a chance we can have the rates as a graph option. Say a config option, list or graph. WOuld be awesome

viking2010 commented 11 months ago

I too would love to be able to see this feature included. Either that, or a means to use the data in an Apex Chart.

lozzd commented 11 months ago

Well Dave's integration is providing a sensor which means there is history and thus you can use the history card to get the graph.

Screenshot_20230715-170305

Oh, unless you mean the future prices too?

BobC76 commented 11 months ago

Hi, I've just switched to Octopus Agile and so finding my way with both the data from Octopus and the HA Octopus integrations. While searching for such a graph myself I couldn't see anyone has posted the code so I came up with this in case its what you are looking for: image

Uses apex charts card within a card-templater card to work around https://github.com/RomRider/apexcharts-card/issues/482 and set the span dynamically based on whether 1d or 2d rates are available:

type: custom:card-templater
card:
  type: custom:apexcharts-card
  experimental:
    color_threshold: true
  now:
    show: true
  graph_span_template: >
    "{{ 1 if (now().day ==
    state_attr('sensor.octopus_energy_electricity_XXXX_current_rate',
    'rates').pop().from.day) else 2 }}d"
  span:
    start: day
  header:
    show: true
    title_template: >-
      Octopus Agile Rates (Current: {{
      ((states('sensor.octopus_energy_electricity_XXXX_current_rate')
      | float ) * 100.0) | round | int }}p/kWh)    
  series:
    - entity: sensor.octopus_energy_electricity_XXXX_current_rate
      type: column
      color_threshold:
        - value: -10
          color: blue
        - value: 0
          color: green
        - value: 10
          color: yellow
        - value: 15
          color: orange
        - value: 25
          color: red
      data_generator: |
        return entity.attributes.rates.map((entry) => {
          return [new Date(entry.from), entry.rate]
        });
entities:
  - sensor.octopus_energy_electricity_XXXX_current_rate
lozzd commented 11 months ago

Oh that's really great, thanks for sharing. I think I prefer that to the card 😆 Do you want to PR the README to add that as an example? Or I can if you like.

BobC76 commented 11 months ago

Do you want to PR the README to add that as an example? Or I can if you like.

Happy to or for you to, either way. I might get round to spending a bit more time to handle the presence/absence of tomorrows rates more neatly. And see if I could fix the "state" to be the current value, not the final value.

[edit] Fixed the example above to address these two.

plandregan commented 11 months ago

Very nice.

I've moved to Intelligent Octopus now.

But still use this integration

On Mon, 17 Jul 2023, 14:23 BobC76, @.***> wrote:

Hi, I've just switched to Octopus Agile and so finding my way with both the data from Octopus and the HA Octopus integrations. While searching for such a graph myself I couldn't see anyone has posted the code so I came up with this in case its what you are looking for: [image: image] https://user-images.githubusercontent.com/32709143/253953144-678d14de-2d84-4ceb-8c53-356e5245b9c5.png

Uses apex charts card:

type: custom:apexcharts-card experimental: color_threshold: true graph_span: 1d span: start: day header: show: true title: ApexCharts-Card show_states: true colorize_states: true series:

  • entity: sensor.octopus_energyelectricity[XXX]_current_rate type: column color_threshold:
    • value: -10 color: blue
    • value: 0 color: green
    • value: 10 color: yellow
    • value: 15 color: orange
    • value: 25 color: red data_generator: | return entity.attributes.rates.map((entry) => { return [new Date(entry.from), entry.rate] });

As of right now (2pm) I've not got future prices for tomorrow, but I assume they'll pop up when they're published? (and then would need to change graph_span to 2d)

— Reply to this email directly, view it on GitHub https://github.com/lozzd/octopus-energy-rates-card/issues/13#issuecomment-1638136012, or unsubscribe https://github.com/notifications/unsubscribe-auth/A2FHAFQDIV3N3EQKQUDIBNLXQU4E7ANCNFSM6AAAAAAXJXVFAA . You are receiving this because you authored the thread.Message ID: @.***>

jamesgreeley commented 10 months ago

Hi @BobC76 really nice work!

any idea why I get the following error?

Screenshot 2023-08-16 at 16 11 15

I've replaced the sensor.octopus_energy_electricity_XXXX_current_rate with my own in all instances.

BobC76 commented 10 months ago

Hi, the apex charts card is wrapped inside this https://github.com/gadgetchnnel/lovelace-card-templater to dynamically alter the graph span based on whether octopus agile rates for tomorrow have been provided (usually after about 4pm). I get that error when I edit the graph and for a brief second as the page loads. Otherwise it would happen if there's a flaw in that logic - which there is: pop() isn't the right thing to do, plus I noticed in a recent update the attributes in the sensors got slight name changes so that's probably where my original code is not finding the right property.

FWIW I have since needed to know when tomorrows rates were published anyway for other automations I was building so created a binary sensor for that, so the code became:

  graph_span_template: >-
    {{ 2 if
    is_state('binary_sensor.track_octopus_energy_rates_for_tomorrow_published',
    'on') else 1}}d

which I suspect is slightly more fault tolerant. Obviously then you have to create a binary sensor that tracks this info, which I did in two parts because the code was cleaner and sensors are cheap right?

- sensor:
  - name: track_octopus_energy_rates_to_day
    state: >-
      {% if has_value('sensor.octopus_energy_electricity_[MPAN]_current_rate') and state_attr('sensor.octopus_energy_electricity_[MPAN]_current_rate', 'all_rates') != None and state_attr('sensor.octopus_energy_electricity_[MPAN]_current_rate', 'all_rates')[-1] != None %}
      {{ state_attr('sensor.octopus_energy_electricity_[MPAN]_current_rate', 'all_rates') != None and state_attr('sensor.octopus_energy_electricity_[MPAN]_current_rate', 'all_rates')[-1].valid_to.day }}
      {% else %}
      None
      {% endif %}

- binary_sensor:
  - name: track_octopus_energy_rates_for_tomorrow_published
    state: >-
      {% if has_value('sensor.track_octopus_energy_rates_to_day') %}
      {{ states( 'sensor.track_octopus_energy_rates_to_day') | int > now().day }}
      {% else %}
      False
      {% endif %}

Someone better familiar with jinja/ha extensions might be able to simplify all my error case checking down, I don't think its especially elegant.

BobC76 commented 10 months ago

Oh and for completeness the data_generator needs to change:

      data_generator: |
        return entity.attributes.all_rates.map((entry) => {
           return [new Date(entry.valid_from), entry.value_inc_vat]
        });

Also as RomRider pointed out after I linked to the issue, there's already a fix for the header data:

      show:
        in_header: before_now
Texelo commented 6 months ago

Hi, for anyone here after recent homeassistant-octopusenergy changes...

type: custom:config-template-card
variables:
  NEXT_DAY_RATES: >-
    states['event.octopus_energy_electricity_XXXX_next_day_rates'].attributes.rates
  CURRENT_RATE: >-
    Number(states['sensor.octopus_energy_electricity_XXXX_current_rate'].state)
    * 100
entities:
  - event.octopus_energy_electricity_XXXX_current_day_rates
  - event.octopus_energy_electricity_XXXX_next_day_rates
card:
  type: custom:apexcharts-card
  apex_config:
    legend:
      show: false
    tooltip:
      enabled: false
    xaxis:
      tickAmount: 12
      labels:
        formatter: |
          EVAL:function(value) {
            var time = new Date(value)
            return time.getHours().toString().padStart(2,'0') + ":" + time.getMinutes().toString().padStart(2,'0');
          }
  experimental:
    color_threshold: true
  now:
    show: true
  graph_span: '${(NEXT_DAY_RATES.length > 0 ? 2 : 1) + ''d''}'
  span:
    start: day
  update_interval: 30min
  header:
    show: true
    title: '${''Octopus Agile Rates (Current: '' + CURRENT_RATE.toFixed(1) + ''p/kWh)''}'
  series:
    - entity: >-
        event.octopus_energy_electricity_XXXX_current_day_rates
      type: column
      unit: p/kwh
      color_threshold:
        - value: -100
          color: blue
        - value: 0
          color: green
        - value: 10
          color: yellow
        - value: 20
          color: orange
        - value: 30
          color: red
      data_generator: |
        return entity.attributes.rates.map((entry) => {
          return [new Date(entry.start), entry.value_inc_vat * 100]
        });
    - entity: event.octopus_energy_electricity_XXXX_next_day_rates
      type: column
      unit: p/kwh
      color_threshold:
        - value: -100
          color: blue
        - value: 0
          color: green
        - value: 10
          color: yellow
        - value: 20
          color: orange
        - value: 30
          color: red
      data_generator: |
        return entity.attributes.rates.map((entry) => {
          return [new Date(entry.start), entry.value_inc_vat * 100]
        });