Support for thirdparty grid carbon footprint

As the new energy feature has been added it’d be nice if energy providers could hook into the Grid carbon footprint option as so far I only see hardcoded support for CO2 Signal.

For example my energy provider Amber energy ensures we offset our entire CO2 footprint so it’d be nice if we could set that.

Giving this a bump and a vote! I’ve recently discovered our regional power network (Western Power Distribution in the UK) has an API that gives a substation-level mix of the energy being supplied and carbon intensity.

Right now, my local energy mix from the grid is 99.7% solar and has a carbon intensity of just 0.32g/kWh vs the 169g/kWh being reported by electricityMap for the whole of Great Britain.

It would be great if the Energy dashboard was able to support sensors, other than the co2signal integration, where it could take the intensity and fossil fuel percentage values - whether fixed or set - from other sources.

1 Like

Hi,

I think there are two aspects being requested here.

(a) Offsetting and (b) other “CO2Equiv intensity measures” being added in.

I’ve just coded up some changes to the energy pages that will allow tracking of emissions, offsets and avoided emissions. See this other thread:

The offset aspect is relatively simple configuration change. I just added a percentage offset configuration for a “grid interface” import or export. That will cover the Amber “Greenpower” offsetting use case I believe.

The use of other sensors in addition to CO2 Signal would also be relatively straight-forward. The sensor is essentially just a carbon intensity measure (gCO2Eq / kWh) and a “percent non-fossil”. As long as the sampling looked like a CO2 Signal then that is easy to integrate as an alternative. If someone can point me to another intensity sensor I can make the changes to select it as an alternative to CO2 Sensor.

I also think that it might be good to try and get the ElectricityMap CO2 Signal feed to do better localisation of its feed. For example I can get an Australian total or a better breakdown for my state AU-NSW (coming from OpenNEM here in Australia). It might be possible to convince someone at WesternPower to share that localised information back in to CO2Signal. Someone already dod the Orkney islands separately. See Electricity Maps | Live 24/7 CO₂ emissions of electricity consumption.

I am going to keep refining my solution for augmenting the energy dashboards with emissions for the next few weeks and then open a PR and see how we can get it merged back to main.

I’d love any feedback.

Cheers,
Brody

1 Like

Did you mange to get any further with that pull request and merging this into main?

It seems a logical progression for Ha where APIs are becoming more available for countries or smaller regions.

I have been looking at working around this issue and am stumped by the lack of manipulation of the total_increasing state for CO2 eq weight.

Do you think potentially a addon may be better for integration if the PR to main is denied?

I paused this. I ended up tracking my emissions externally to HA for the main part.

HA just isn’t great as an accounting/entry tool.

I do real time scope 1/2 emissions from my grid use (and “public grid” for highway DC chargers) in HA.

Looks like this:

We use our battery to charge from our rooftop PV or if that won’t fill it to pull green/clean energy from the grid in the middle of the day. We then displace dirty grid energy in the evening. That is tracked in near real time based on import/export and CO2 intensity.

We then keep those numbers for daily tracking and lifetime of the house.

Those are then inputs to an external spreadsheet where we can track our scope 3 emissions from our other purchases.

I think an add-on that would help on the scope 3 emissions tracking (and calculations) would be good to then resurrect my effort here and try and pull this back in to the main dashboards (my gut is it should be a separate dashboard to energy - but related called emissions or environmental impact).

Curious to know how you create the graph you show above - I ended up doing horrible things with automations and helper numbers to calculate emissions from the grid using the Electricity Map numbers.

1 Like

Here is the real-time “intensity” chart that I can track how much CO2eq we are displacing for the day (using the awesome apexcharts), then there are a few related sensors (calulated and utility meters) based on powerwall grid import/export and co2signal.

type: custom:apexcharts-card
header:
  show: true
  title: Emissions
  show_states: true
  colorize_states: true
apex_config:
  legend:
    show: false
  stroke:
    show: true
    lineCap: round
    dashArray:
      - 4
      - 4
graph_span: 24h
span:
  start: day
  offset: +1s
now:
  show: true
yaxis:
  - id: gCO2EqPerHour
    decimals: 0
    opposite: true
    apex_config:
      forceNiceScale: true
      title:
        text: gCO2Eq/h
  - id: gCO2Eq
    decimals: 0
    apex_config:
      forceNiceScale: true
      title:
        text: gCO2Eq
  - id: header_only
    show: false
series:
  - entity: sensor.emissions_avoided
    yaxis_id: gCO2Eq
    invert: true
    stroke_width: 1
    opacity: 0.5
    color: green
    float_precision: 0
    extend_to: now
    show:
      legend_value: false
      in_header: false
  - entity: sensor.emissions_created
    yaxis_id: gCO2Eq
    stroke_width: 1
    opacity: 0.5
    color: grey
    float_precision: 0
    extend_to: now
    show:
      legend_value: false
      in_header: false
  - entity: sensor.emissions_created_daily
    yaxis_id: gCO2Eq
    stroke_width: 1.2
    opacity: 0.8
    color: grey
    float_precision: 0
    extend_to: now
  - entity: sensor.emissions_avoided_daily
    yaxis_id: gCO2Eq
    invert: true
    stroke_width: 1
    opacity: 0.7
    color: green
    float_precision: 0
    extend_to: now
  - entity: sensor.emissions_net_daily
    yaxis_id: gCO2Eq
    stroke_width: 1.25
    opacity: 0.7
    color: teal
    float_precision: 0
    extend_to: now
  - entity: sensor.co2_intensity_site_import_daily
    yaxis_id: header_only
    color: grey
    float_precision: 0
    name: Intensity Import
    show:
      legend_value: false
      in_header: true
      in_chart: false
  - entity: sensor.co2_intensity_site_export_daily
    yaxis_id: header_only
    color: green
    float_precision: 0
    name: Intensity Export
    show:
      legend_value: false
      in_header: true
      in_chart: false

Then from configuration.yaml…

sensor.emissions_avoided and sensor.emissions_created

template:
  - sensor:
      # Emissions in gCO2eq/h - so if we went for an hour that is how much would be created/avoided 
      - name: Emissions Avoided
        unique_id: "emissions_avoided"
        state_class: measurement
        unit_of_measurement: gCO2eq/h
        icon: mdi:co2
        state: >
          {% set site_export_power_kW = -(min(0,states('sensor.powerwall_site_now') | float)) | float %}
          {% set intensity_gCO2eq_per_kWh = states('sensor.co2_intensity') | float %}
          {% set emissions_avoided_gCO2eq_per_hour = (site_export_power_kW * intensity_gCO2eq_per_kWh) %}
          {{ emissions_avoided_gCO2eq_per_hour | round(2) }}
      - name: Emissions Created
        unique_id: "emissions_created"
        state_class: measurement
        unit_of_measurement: gCO2eq/h
        icon: mdi:co2
        state: >
          {% set site_import_power_kW = (max(0,states('sensor.powerwall_site_now') | float)) | float %}
          {% set intensity_gCO2eq_per_kWh = states('sensor.co2_intensity') | float %}
          {% set emissions_created_gCO2eq_per_hour = (site_import_power_kW * intensity_gCO2eq_per_kWh) %}
          {{ emissions_created_gCO2eq_per_hour | round(2) }}

sensor.emissions_created_daily and sensor.emissions_avoided_daily


utility_meter:
  #Daily emissions
  emissions_created_daily:
    source: sensor.emissions_created_cumulative
    name: Emissions Created Daily
    unique_id: "emissions_created_daily"
    net_consumption: true
    cycle: daily
  emissions_avoided_daily:
    source: sensor.emissions_avoided_cumulative
    name: Emissions Avoided Daily
    unique_id: "emissions_avoided_daily"
    net_consumption: true
    cycle: daily

sensor.emissions_net_daily

  - sensor:
        #Emissions net calculations (avoided/created are the base)
      - name: "emissions_net_daily"
        unique_id: "emissions_net_daily"
        state_class: measurement
        unit_of_measurement: gCO2eq
        state: "{{ ((states('sensor.emissions_created_daily') | float(0)) ) - ((states('sensor.emissions_avoided_daily') | float(0)) ) }}"

sensor.co2_intensity_site_import_daily and sensor.co2_intensity_site_export_daily

      - name: "CO2 Intensity Site Export Daily"
        unique_id: "co2_intensity_site_export_daily"
        state_class: measurement
        unit_of_measurement: gCO2eq/kWh
        state: >
          {% set emissions = (states('sensor.emissions_avoided_daily') | float(0)) %}
          {% set energy = (states('sensor.energy_site_export_daily') | float(0)) %}
          {% set intensity = (emissions/energy) %}
          {{ intensity | round(0) }}
      - name: "CO2 Intensity Site Import Daily"
        unique_id: "co2_intensity_site_import_daily"
        state_class: measurement
        unit_of_measurement: gCO2eq/kWh
        state: >
          {% set emissions = (states('sensor.emissions_created_daily') | float(0)) %}
          {% set energy = (states('sensor.energy_site_import_daily') | float(0)) %}
          {% set intensity = (emissions/energy) %}
          {{ intensity | round(0) }}

Hopefully I didn’t miss anything in there.

2 Likes

The history is a pretty simple chart also, but the calculations/sensors under it are a little complicated and only applicable to our house (they have a variety of assumptions and various components for emissions prior to our full electrification and to calculate emissions when we are charging our EV from DC chargers on the road or at other locations).

type: custom:apexcharts-card
apex_config:
  legend:
    show: false
graph_span: 30d
span:
  end: day
stacked: true
header:
  title: Emissions - Daily History (Today's Numbers)
  show: true
  show_states: true
  colorize_states: true
yaxis:
  - id: gCO2eq
    decimals: 0
    apex_config:
      forceNiceScale: true
      title:
        text: kgCO2eq
series:
  - entity: sensor.emissions_created_cumulative
    name: Created
    type: column
    color: grey
    float_precision: 1
    transform: return x/1000;
    unit: kgCO2eq
    opacity: 0.5
    statistics:
      type: sum
      period: day
    group_by:
      duration: 1d
      start_with_last: true
      func: diff
  - entity: sensor.emissions_avoided_cumulative
    name: Displaced
    type: column
    color: green
    float_precision: 1
    transform: return x/1000;
    unit: kgCO2eq
    invert: true
    opacity: 0.5
    statistics:
      type: sum
      period: day
    group_by:
      duration: 1d
      start_with_last: true
      func: diff
  - entity: sensor.emissions_net_cumulative
    name: Net
    type: line
    color: teal
    float_precision: 1
    transform: return x/1000;
    unit: kgCO2eq
    statistics:
      type: min
      period: day
    show:
      datalabels: true
    group_by:
      duration: 1d
      start_with_last: true
      func: diff

sensor.emissions_created_cumulative and sensor.emissions_avoided_cumulative

  #Emissions Avoided/Created
  - platform: integration
    source: sensor.emissions_created
    name: emissions_created_cumulative
  - platform: integration
    source: sensor.emissions_avoided
    name: emissions_avoided_cumulative

sensor.emissions_net_cumulative

      - name: "emissions_net_cumulative"
        unique_id: "emissions_net_cumulative"
        state_class: measurement
        unit_of_measurement: gCO2eq
        state: "{{ ((states('sensor.emissions_created_cumulative') | float(0)) ) - ((states('sensor.emissions_avoided_cumulative') | float(0)) ) }}"

oh, the sensors call it avoiding co2eq but the charts label it as displaced.

Hopefully that can get you to somewhere of less a horrible place (or if your setup is less horrible than mine then please share back).

1 Like