Energy Dashboard, Tariffs, Daily & Monthly Cost

I setup the CircuitSetup 6-channel monitor with only two channels in use and added it via the esphome integration. No problem there; everything looking good. However, things start to get dicey when using the Utility helper and setting up the Energy Dashboard.

I’m an Ameren Missouri customer on the “Smart Savers” plan and that effectively means I’ve got 6 tariff options (Rate Options - Ameren Missouri). Is there a better to set them than this?

utility_meter:
  monthly_energy:
    source: sensor.6c_total_kwh
    name: Monthly Energy
    cycle: monthly
    offset: 27
    tariffs:
      - summer_midpeak
      - summer_offpeak
      - summer_onpeak
      - winter_midpeak
      - winter_offpeak
      - winter_onpeak
  daily_energy:
    source: sensor.6c_total_kwh
    name: Daily Energy
    cycle: daily
    tariffs:
      - summer_midpeak
      - summer_offpeak
      - summer_onpeak
      - winter_midpeak
      - winter_offpeak
      - winter_onpeak

Then onto the Energy Dashboard. Is the best way to configure that using the 6 daily energy sensors created due to my tariff structure? Seems like there could be a better way. Perhaps just using the total_kwh sensor but then it doesn’t show cost information. What if I want to see monthly cost? Using the monthly sensors doesn’t seem to show any cost on the dashboard.

I do have an automation to select the tariff. Throwing it below for posterity and possibly to help someone else out.

  alias: "Set correct electricity costs"
  trigger:
    - platform: template
      variables:
        tariff: "winter_offpeak"
      value_template: >-
        {{
          (now().month >= 10 or now().month <= 5) and
          (
            (now().hour >= 0 and now().hour <= 5) or
            (now().hour >= 22 and now().hour <= 23)
          ) and
          (now().minute == 0)
        }}
    - platform: template
      variables:
        tariff: "winter_midpeak"
      value_template: >-
        {{
          (now().month >= 10 or now().month <= 5) and
          (
            (
              is_state("binary_sensor.workday_sensor", "on") and
              (
                (now().hour >= 6 and now().hour <= 7) or
                (now().hour >= 20 and now().hour <= 21)
              )
            ) or (
              is_state("binary_sensor.workday_sensor", "off") and
              (now().hour >= 6 and now().hour <= 21)
            )
          ) and
          (now().minute == 0)
        }}
    - platform: template
      variables:
        tariff: "winter_onpeak"
      value_template: >-
        {{
           (now().month >= 10 or now().month <= 5) and
           (
             is_state("binary_sensor.workday_sensor", "on") and
             (
               (now().hour >= 6 and now().hour <= 7) or
               (now().hour >= 18 and now().hour <= 19)
             )
           ) and
           (now().minute == 0)
        }}
    - platform: template
      variables:
        tariff: "summer_offpeak"
      value_template: >-
        {{
          (now().month >= 6) and
          (now().month <= 9) and
          (
            (now().hour >= 0 and now().hour <= 5) or
            (now().hour >= 22 and now().hour <= 23)
          ) and
          (now().minute == 0)
        }}
    - platform: template
      variables:
        tariff: "summer_midpeak"
      value_template: >-
        {{
          (now().month >= 6 and now().month <= 9) and
          (
            (
              is_state("binary_sensor.workday_sensor", "on") and
              (
                (now().hour >= 6 and now().hour <= 14) or
                (now().hour >= 19 and now().hour <= 21)
              )
            ) or (
              is_state("binary_sensor.workday_sensor", "off") and
              (now().hour >= 6 and now().hour <= 21)
            )
          ) and
          (now().minute == 0)
        }}
    - platform: template
      variables:
        tariff: "summer_onpeak"
      value_template: >-
        {{
           (now().month >= 6 and now().month <= 9) and
           (now().hour >= 15) and
           (now().hour <= 18) and
           (now().minute == 0) and
           is_state("binary_sensor.workday_sensor", "on")
        }}
  action:
    - service: select.select_option
      target:
        entity_id: select.daily_energy
      data:
        option: "{{ tariff }}"
    - service: select.select_option
      target:
        entity_id: select.monthly_energy
      data:
        option: "{{ tariff }}"

Here’s the ESPHome config, also for posterity.

# Example config for when jp8-jp11 are all bridged - this connects all the voltage channels and allows for power to be calculated by the meter directly.
# Boards >= v1.4 jp8-jp11 are removed and have all voltage channels connected

substitutions:
# Change the disp_name to something you want
  disp_name: 6C
# Interval of how often the power is updated
  update_time: 10s
# Current Transformers:
#  20A/25mA SCT-006: 11143
#  30A/1V SCT-013-030: 8650
#  50A/1V SCT-013-050: 15420
#  50A/16.6mA SCT-010: 41334
#  80A/26.6mA SCT-010: 41660
#  100A/50ma SCT-013-000: 27518
#  120A/40mA: SCT-016: 41787
#  200A/100mA SCT-024: 27518
#  200A/50mA SCT-024: 55036
  current_cal_1: '3516'
  current_cal_2: '3516'
# Jameco 9VAC Transformer:
#  For meter versions:
#  >= v1.3: 7305
  voltage_cal: '7427'

esphome:
  name: 6chan-energy-meter
  platform: ESP32
  board: nodemcu-32s

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "REMOVED"

ota:
  safe_mode: false
  password: "REMOVED"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Test Fallback Hotspot"
    password: "REMOVED"

web_server:
  port: 80

spi:
  clk_pin: 18
  miso_pin: 19
  mosi_pin: 23

sensor:
  - platform: wifi_signal
    name: ${disp_name} WiFi
    update_interval: 60s
#IC1
  - platform: atm90e32
    cs_pin: 5
    phase_a:
      voltage:
        name: ${disp_name} Volts A
        id: ic1Volts
        accuracy_decimals: 1
      current:
        name: ${disp_name} CT1 Amps
        id: ct1Amps
# The max value for current that the meter can output is 65.535. If you expect to measure current over 65A,
# divide the gain_ct by 2 (120A CT) or 4 (200A CT) and multiply the current and power values by 2 or 4 by uncommenting the filter below
        filters:
          - multiply: 4
      power:
        name: ${disp_name} CT1 Watts
        id: ct1Watts
        filters:
          - multiply: 4
      gain_voltage: ${voltage_cal}
      gain_ct: ${current_cal_1}
      forward_active_energy:
        name: ${disp_name} CT1 WattHours
        id: ct1FAWattHours
    phase_b:
      current:
        name: ${disp_name} CT2 Amps
        id: ct2Amps
        filters:
          - multiply: 4
      power:
        name: ${disp_name} CT2 Watts
        id: ct2Watts
        filters:
          - multiply: 4
      gain_voltage: ${voltage_cal}
      gain_ct: ${current_cal_2}
      forward_active_energy:
        name: ${disp_name} CT2 WattHours
        id: ct2FAWattHours
    frequency:
      name: ${disp_name} Freq A
    line_frequency: 60Hz
    gain_pga: 4X
    update_interval: ${update_time}
#Total Amps
  - platform: template
    name: ${disp_name} Total Amps
    id: totalAmps
    lambda: return id(ct1Amps).state + id(ct2Amps).state;
    accuracy_decimals: 2
    unit_of_measurement: A
    device_class: current
    update_interval: ${update_time}
#Total Watts
  - platform: template
    name: ${disp_name} Total Watts
    id: totalWatts
    lambda: return id(ct1Watts).state + id(ct2Watts).state;
    accuracy_decimals: 1
    unit_of_measurement: W
    device_class: energy
    update_interval: ${update_time}
#kWh
  - platform: total_daily_energy
    name: ${disp_name} Total kWh
    power_id: totalWatts
    filters:
      - multiply: 0.001
    unit_of_measurement: kWh
    device_class: energy
    state_class: total_increasing
switch:
  - platform: restart
    name: ${disp_name} Restart
time:
  - platform: sntp
    id: sntp_time

@allrightname I also am a Ameren Missouri customer. Would you mind sharing details of how you are getting your information from the utility? Thank you!

Here’s what I’ve donefor Ameren MO. It won’t be 100% accurate in winter due to the 750kWh tier, depending on when they do their meter reading. You can drop this in your config file. You’ll need to adjust the rates to match your plan, and the consumption meter to match your sensor name though. This will output the current electric rate that you’re paying, you can then use this as an “entity that tracks current price” on the energy dashboard.

  - sensor:
    - name: "Current Electric Rate"
      unit_of_measurement: "USD/kWh"
      state: >
          {% set winter_months = [ 10, 11, 12, 1, 2, 3, 4, 5] %}
          {% set summer_months = [ 6, 7, 8, 9] %}
          {% set on_peak_start_hour = 9 %}
          {% set on_peak_end_hour = 21 %}
          {% set current_hour = now().hour %}
          {% set current_month = now().month %}
          {% set monthly_energy = states('sensor.monthly_energy') %}
          {% if current_month in winter_months %}
            {% if states('sensor.monthly_energy') | int <= 750 %}
              {% if current_hour >= on_peak_start_hour and current_hour < on_peak_end_hour %}
                {% set rate = 0.0918 %}
              {% else %}
                {% set rate = 0.0943 %}
              {% endif %}
            {% else %}
              {% if current_hour >= on_peak_start_hour and current_hour < on_peak_end_hour %}
                {% set rate = 0.0615 %}
              {% else %}
                {% set rate = 0.0640 %}
              {% endif %}
            {% endif %}
          {% else %}
            {% if current_hour >= on_peak_start_hour and current_hour < on_peak_end_hour %}
              {% set rate = 0.1392 %}
            {% else %}
              {% set rate = 0.1342 %}
            {% endif %}
          {% endif %}
          {{ rate }}



          
utility_meter:
  monthly_energy:
    source: sensor.esphome_web_dd4dc8_power_consumption
    name: Monthly Energy
    cycle: monthly
    offset:
      days: 22