Skip to content

Instantly share code, notes, and snippets.

@flaviut
Last active March 12, 2024 00:27
Show Gist options
  • Save flaviut/93a1212c7b165c7674693a45ad52c512 to your computer and use it in GitHub Desktop.
Save flaviut/93a1212c7b165c7674693a45ad52c512 to your computer and use it in GitHub Desktop.
Setting up Emporia Vue 2 with ESPHome
@flaviut
Copy link
Author

flaviut commented Jun 26, 2022

@Ofloo I'm not sure; are you able to get any logs over the serial adapter, ideally while not connected to mains?

If not, I'd suggest reaching out to general ESPHome community and asking them. Please remember to let us know how you solved this!

@Ofloo
Copy link

Ofloo commented Jun 26, 2022 via email

@devWaves
Copy link

devWaves commented Jun 27, 2022

@flaviut just wanted to say thanks for this (also thanks to ESPhome devs). Works awesome. I am now using the MQTT integration at it is exactly what I wanted. So you can update your documentation to say MQTT is working

The main reason I wanted it was to monitor things like the electric stove/oven if it was accidentaly left on while we are away or when everyone is asleep etc. I could only trust a local solution for that

@tappyson
Copy link

Hi. Thank you so much for the brilliant work on this. I managed to flash my Emporia Vue and it seems to be working perfectly. I ran it with the Emporia software and the cloud prior to make sure it all worked fine before I went ahead an flashed it. My issue (Due to lack of templating knowledge) now is that I have a solar system and in order to pull in the right data to home assistant I need to be able to create Current/Total energy exported to the grid (All negative values of the Total Power) and All the Energy imported from the Grid (Positive numbers on total power) I removed the filter so my total power or phase power shows negative and positive depending on if my house is producing more than it uses or not. I've found ways to do this in HA but I'd prefer that it was done locally on the device before being pushed to HA.

@maegibbons
Copy link

Hi. Thank you so much for the brilliant work on this. I managed to flash my Emporia Vue and it seems to be working perfectly. I ran it with the Emporia software and the cloud prior to make sure it all worked fine before I went ahead an flashed it. My issue (Due to lack of templating knowledge) now is that I have a solar system and in order to pull in the right data to home assistant I need to be able to create Current/Total energy exported to the grid (All negative values of the Total Power) and All the Energy imported from the Grid (Positive numbers on total power) I removed the filter so my total power or phase power shows negative and positive depending on if my house is producing more than it uses or not. I've found ways to do this in HA but I'd prefer that it was done locally on the device before being pushed to HA.

Can you share what you have done so far so we can see where you are at?

@tappyson
Copy link

tappyson commented Jun 29, 2022

i2c:
  sda: 21
  scl: 22
  scan: false
  frequency: 200kHz  # recommended range is 50-200kHz
  id: i2c_a
time:
  - platform: sntp
    id: my_time

# these are called references in YAML. They allow you to reuse
# this configuration in each sensor, while only defining it once
.defaultfilters:
  - &moving_avg
    # we capture a new sample every 0.24 seconds, so the time can
    # be calculated from the number of samples as n * 0.24.
    sliding_window_moving_average:
      # we average over the past 2.88 seconds
      window_size: 12
      # we push a new value every 1.44 seconds
      send_every: 6
  - &invert
    # invert and filter out any values below 0.
    lambda: 'return max(-x, 0.0f);'
  - &pos
    # filter out any values below 0.
    lambda: 'return max(x, 0.0f);'
  - &abs
    # take the absolute value of the value
    lambda: 'return abs(x);'

sensor:
  - platform: emporia_vue
    i2c_id: i2c_a
    phases:
      - id: phase_a  # Verify that this specific phase/leg is connected to correct input wire color on device listed below
        input: BLACK  # Vue device wire color
        calibration: 0.022  # 0.022 is used as the default as starting point but may need adjusted to ensure accuracy
        # To calculate new calibration value use the formula <in-use calibration value> * <accurate voltage> / <reporting voltage>
        voltage:
          name: "Phase A Voltage"
          filters: [*moving_avg, *pos]

    ct_clamps:
      - phase_id: phase_a
        input: "C"  # Verify the CT going to this device input also matches the phase/leg
        power:
          name: "Phase A Power"
          id: phase_a_power
          device_class: power
          filters: [*moving_avg]

      # Pay close attention to set the phase_id for each breaker by matching it to the phase/leg it connects to in the panel
      - { phase_id: phase_a, input:  "1", power: { name:  "Lights N9 Power", id:  cir1, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "2", power: { name:  "Lights N8 Power", id:  cir2, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "3", power: { name:  "Plugs N7 Power", id:  cir3, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "4", power: { name:  "Plugs N6 Power", id:  cir4, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "5", power: { name:  "Plugs N5 Power", id:  cir5, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "6", power: { name:  "Solar Power", id:  cir6, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "7", power: { name:  "Aircon N3 Power", id:  cir7, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "8", power: { name:  "Stove N2 Power", id:  cir8, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "9", power: { name:  "Hot Water N1", id:  cir9, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "10", power: { name: "Plugs N4 Power", id: cir10, filters: [ *moving_avg, *pos ] } }


  - platform: template
    name: "Total Power"
    lambda: return id(phase_a_power).state ;
    update_interval: 1s
    id: total_power
    unit_of_measurement: "W"
  - platform: total_daily_energy
    name: "Total Daily Energy"
    power_id: total_power
    accuracy_decimals: 0
  - { power_id:  cir1, platform: total_daily_energy, accuracy_decimals: 0, name:  "Lights N9 Daily Energy", id: total_daily_cir1 }
  - { power_id:  cir2, platform: total_daily_energy, accuracy_decimals: 0, name:  "Lights N8 Daily Energy", id: total_daily_cir2 }
  - { power_id:  cir3, platform: total_daily_energy, accuracy_decimals: 0, name:  "Plugs N7 Daily Energy", id: total_daily_cir3 }
  - { power_id:  cir4, platform: total_daily_energy, accuracy_decimals: 0, name:  "Plugs N6 Daily Energy", id: total_daily_cir4 }
  - { power_id:  cir5, platform: total_daily_energy, accuracy_decimals: 0, name:  "Plugs N5 Daily Energy", id: total_daily_cir5 }
  - { power_id:  cir6, platform: total_daily_energy, accuracy_decimals: 0, name:  "Solar Power Daily Energy", id: total_daily_cir6 }
  - { power_id:  cir7, platform: total_daily_energy, accuracy_decimals: 0, name:  "Aircon N3 Daily Energy", id: total_daily_cir7 }
  - { power_id:  cir8, platform: total_daily_energy, accuracy_decimals: 0, name:  "Stove N2 Daily Energy", id: total_daily_cir8 }
  - { power_id:  cir9, platform: total_daily_energy, accuracy_decimals: 0, name:  "Hot Water N1 Daily Energy", id: total_daily_cir9 }
  - { power_id: cir10, platform: total_daily_energy, accuracy_decimals: 0, name: "Plugs N4 Daily Energy", id: total_daily_cir10 }
  
  
  - platform: template
    name: "Total Usage Power"
    lambda: return id(total_daily_cir1).state + id(total_daily_cir2).state + id(total_daily_cir3).state + id(total_daily_cir4).state + id(total_daily_cir5).state
      + id(total_daily_cir7).state + id(total_daily_cir8).state + id(total_daily_cir9).state + id(total_daily_cir10).state ; 
    update_interval: 1s
    id: total_power_usage
    unit_of_measurement: "W"
    internal: true 

 #Total House Watts Positive
  - platform: template
    name: Total Import
    id: totalconsumed
    lambda: |-
      if (id(total_power).state < 0) {
        return 0;
      } else {
        return id(total_power).state ;
      }
    accuracy_decimals: 1
    unit_of_measurement: "W"
    icon: "mdi:flash-circle"
    update_interval: 1s
    filters: [*moving_avg]
    
#Total House Watts Negative
  - platform: template
    name: Total Export
    id: totalexported
    lambda: |-
      if (id(total_power).state > 0) {
        return 0;
      } else {
        return abs(id(total_power).state) ;
      }
    accuracy_decimals: 1
    unit_of_measurement: "W"
    icon: "mdi:flash-circle"
    update_interval: 1s
    filters: [*moving_avg]

Kinda works but doesn't work in the HA dashboard and the data doesn't look like it's a running total but more like some sort of average?

@tappyson
Copy link

Basically I want two Total Daily's. One that is for all the Grid Import (When the total is positive) and one for Grid Export (When the total is positive) Also please excuse the horrendous editing on the code above. No idea why Github kept editing it that way. I used the insert code tool.

@flaviut
Copy link
Author

flaviut commented Jun 29, 2022

@tappyson you're on the right track. You have the instantaneous power imported and exported. But you need to add that up over time.

Try adding two more sensors like the existing total daily energy:

  - platform: total_daily_energy
    name: "Total Daily Energy"
    power_id: total_power
    accuracy_decimals: 0

Details on how it works: https://esphome.io/components/sensor/total_daily_energy.html

You'll want to replace the thing it's summing over with your totalexported, etc.

PS: I fixed the formatting, here's an explanation of how it works

@Ofloo
Copy link

Ofloo commented Jun 30, 2022

I didn't fix the problem, however I've established how to circumvent it. Seems like the culprit is ESPHome, not sure as to why this specific firmware is having issues with it. Since none of my other clients do but it does.

I've changed my config to mqtt and set all internal to true and now I have no packets going to ESPHome and so no more disconnects and no more packet loss.

Downside I have to configure all my sensors in mqtt: - sensors ..

substitutions:
  devicename: "energy-monitor"
  upper_devicename: "emporiavue2"

  wifi_ssid: !secret iot_wifi_ssid
  wifi_pass: !secret iot_wifi_password
  fallback_pass: !secret fallback_wifi_password
  api_pass: !secret esp_api_password
  ota_pass: !secret esp_ota_password

  # phase a connected to main leat L1 load closet
  name_a_power: "Grid Power"
  name_a_voltage: "Grid Voltage"
  name_total_a_power: "Total Power Grid"
  name_total_a_energy: "Total Daily Energy Grid"
  # phase b connected to main lead N direction load N
  name_b_power: "Neutral Power"
  name_b_voltage: "Neutral Voltage"
  name_total_b_power: "Total Power Neutral"
  name_total_b_energy: "Total Daily Energy Neutral"
  # phase c connected main lead to earth direction load earth
  name_c_power: "PE Power"
  name_c_voltage: "PE Voltage"
  name_total_c_power: "Total Power PE"
  name_total_c_energy: "Total Daily Energy PE"
  # individual circuits
  # individual circuits
  name_circuit01: "Circuit 1"
  name_circuit02: "Circuit 2"
  name_circuit03: "Circuit 3"
  name_circuit04: "Circuit 4"
  name_circuit05: "Circuit 5"
  name_circuit06: "Circuit 6"
  name_circuit07: "Circuit 7"
  name_circuit08: "Circuit 8"
  name_circuit09: "Circuit 9"
  name_circuit10: "Circuit 10"
  name_circuit11: "Circuit 11"
  name_circuit12: "Circuit 12"
  name_circuit13: "Circuit 13"
  name_circuit14: "Circuit 14"
  name_circuit15: "Circuit 15"
  name_circuit16: "Circuit 16"
  name_timezone: 'CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00'


esphome:
  name: $devicename

external_components:
  - source: github://flaviut/esphome@emporia-vue-2022.4.0
    components: [ emporia_vue ]

esp32:
  board: esp32dev
  framework:
    type: esp-idf
    version: recommended

# Enable Home Assistant API
api:
  password: "${api_pass}"

# Enable over the air updates
ota:
  password: "${ota_pass}"

# Enable logging
logger:
  level: error

wifi:
  ssid: "${wifi_ssid}"
  password: "${wifi_pass}"

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "${devicename} Fallback Hotspot"
    password: "${fallback_pass}"

i2c:
  sda: 21
  scl: 22
  scan: false
  frequency: 200kHz  # recommended range is 50-200kHz
  id: i2c_a

# these are called references in YAML. They allow you to reuse
# this configuration in each sensor, while only defining it once
.defaultfilters:
  - &moving_avg
    # we capture a new sample every 0.24 seconds, so the time can
    # be calculated from the number of samples as n * 0.24.
    sliding_window_moving_average:
      # we average over the past 2.88 seconds
      window_size: 12
      # we push a new value every 1.44 seconds
      send_every: 6
  - &invert
    # invert and filter out any values below 0.
    lambda: 'return max(-x, 0.0f);'
  - &pos
    # filter out any values below 0.
    lambda: 'return max(x, 0.0f);'
  - &abs
    # take the absolute value of the value
    lambda: 'return abs(x);'

mqtt:
  broker: !secret mqtt_hostname
  username: !secret mqtt_username
  password: !secret mqtt_password
  client_id: vue2
  port: 1883
  topic_prefix: vue2
  discovery: false
  log_topic: null

sensor:
  - platform: emporia_vue
    i2c_id: i2c_a
    phases:
      - id: phase_a  # Verify that this specific phase/leg is connected to correct input wire color on device listed below
        input: BLACK  # Vue device wire color
        calibration: 0.02260  # 0.022 is used as the default as starting point but may need adjusted to ensure accuracy
        # To calculate new calibration value use the formula <in-use calibration value> * <accurate voltage> / <reporting voltage>
        voltage:
          name: $name_a_voltage
          internal: true
          id: phase_a_voltage
          filters: [*moving_avg, *pos]
      - id: phase_b  # Verify that this specific phase/leg is connected to correct input wire color on device listed below
        input: RED  # Vue device wire color
        calibration: 0.02260  # 0.022 is used as the default as starting point but may need adjusted to ensure accuracy
        # To calculate new calibration value use the formula <in-use calibration value> * <accurate voltage> / <reporting voltage>
        voltage:
          name: $name_b_voltage
          internal: true
          id: phase_b_voltage
          filters: [*moving_avg, *pos]
      - id: phase_c  # Verify that this specific phase/leg is connected to correct input wire color on device listed below
        input: BLUE  # Vue device wire color
        calibration: 0.02260  # 0.022 is used as the default as starting point but may need adjusted to ensure accuracy
        # To calculate new calibration value use the formula <in-use calibration value> * <accurate voltage> / <reporting voltage>
        voltage:
          name: $name_c_voltage
          internal: true
          id: phase_c_voltage
          filters: [*moving_avg, *pos]
    ct_clamps:
      - phase_id: phase_a
        input: "A"  # Verify the CT going to this device input also matches the phase/leg
        power:
          name: $name_a_power
          internal: true
          id: phase_a_power
          device_class: power
          filters: [*moving_avg, *pos]
      - phase_id: phase_b
        input: "B"  # Verify the CT going to this device input also matches the phase/leg
        power:
          name: $name_b_power
          internal: true
          id: phase_b_power
          device_class: power
          filters: [*moving_avg, *pos]
      - phase_id: phase_c
        input: "C"  # Verify the CT going to this device input also matches the phase/leg
        power:
          name: $name_c_power
          internal: true
          id: phase_c_power
          device_class: power
          filters: [*moving_avg, *pos]
      # Pay close attention to set the phase_id for each breaker by matching it to the phase/leg it connects to in the panel
      - { phase_id: phase_a, input:  "1", power: { name: $name_circuit01, internal: true, id: power_cir01, device_class: power, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "2", power: { name: $name_circuit02, internal: true, id: power_cir02, device_class: power, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "3", power: { name: $name_circuit03, internal: true, id: power_cir03, device_class: power, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "4", power: { name: $name_circuit04, internal: true, id: power_cir04, device_class: power, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "5", power: { name: $name_circuit05, internal: true, id: power_cir05, device_class: power, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "6", power: { name: $name_circuit06, internal: true, id: power_cir06, device_class: power, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "7", power: { name: $name_circuit07, internal: true, id: power_cir07, device_class: power, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "8", power: { name: $name_circuit08, internal: true, id: power_cir08, device_class: power, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "9", power: { name: $name_circuit09, internal: true, id: power_cir09, device_class: power, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "10", power: { name: $name_circuit10, internal: true, id: power_cir10, device_class: power, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "11", power: { name: $name_circuit11, internal: true, id: power_cir11, device_class: power, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "12", power: { name: $name_circuit12, internal: true, id: power_cir12, device_class: power, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "13", power: { name: $name_circuit13, internal: true, id: power_cir13, device_class: power, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "14", power: { name: $name_circuit14, internal: true, id: power_cir14, device_class: power, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "15", power: { name: $name_circuit15, internal: true, id: power_cir15, device_class: power, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "16", power: { name: $name_circuit16, internal: true, id: power_cir16, device_class: power, filters: [ *moving_avg, *pos ] } }

  - platform: template
    name: "${name_circuit01} in W"
    lambda: return id(power_cir01).state;
    id: total_cir01
    accuracy_decimals: 0
    unit_of_measurement: "W"
    internal: true
    update_interval: 1s
    icon: mdi:gauge
  - platform: template
    name: "${name_circuit02} in W"
    lambda: return id(power_cir02).state;
    id: total_cir02
    accuracy_decimals: 0
    unit_of_measurement: "W"
    internal: true
    update_interval: 1s
    icon: mdi:gauge
  - platform: template
    name: "${name_circuit03} in W"
    lambda: return id(power_cir03).state;
    id: total_cir03
    accuracy_decimals: 0
    unit_of_measurement: "W"
    internal: true
    update_interval: 1s
    icon: mdi:gauge
  - platform: template
    name: "${name_circuit04} in W"
    lambda: return id(power_cir04).state;
    id: total_cir04
    accuracy_decimals: 0
    unit_of_measurement: "W"
    internal: true
    update_interval: 1s
    icon: mdi:gauge
  - platform: template
    name: "${name_circuit05} in W"
    lambda: return id(power_cir05).state;
    id: total_cir05
    accuracy_decimals: 0
    unit_of_measurement: "W"
    internal: true
    update_interval: 1s
    icon: mdi:gauge
  - platform: template
    name: "${name_circuit06} in W"
    lambda: return id(power_cir06).state;
    id: total_cir06
    accuracy_decimals: 0
    unit_of_measurement: "W"
    internal: true
    update_interval: 1s
    icon: mdi:gauge
  - platform: template
    name: "${name_circuit07} in W"
    lambda: return id(power_cir07).state;
    id: total_cir07
    accuracy_decimals: 0
    unit_of_measurement: "W"
    internal: true
    update_interval: 1s
    icon: mdi:gauge
  - platform: template
    name: "${name_circuit08} in W"
    lambda: return id(power_cir08).state;
    id: total_cir08
    accuracy_decimals: 0
    unit_of_measurement: "W"
    internal: true
    update_interval: 1s
    icon: mdi:gauge
  - platform: template
    name: "${name_circuit09} in W"
    lambda: return id(power_cir09).state;
    id: total_cir09
    accuracy_decimals: 0
    unit_of_measurement: "W"
    internal: true
    update_interval: 1s
    icon: mdi:gauge
  - platform: template
    name: "${name_circuit10} in W"
    lambda: return id(power_cir10).state;
    id: total_cir10
    accuracy_decimals: 0
    unit_of_measurement: "W"
    internal: true
    update_interval: 1s
    icon: mdi:gauge
  - platform: template
    name: "${name_circuit11} in W"
    lambda: return id(power_cir11).state;
    id: total_cir11
    accuracy_decimals: 0
    unit_of_measurement: "W"
    internal: true
    update_interval: 1s
    icon: mdi:gauge
  - platform: template
    name: "${name_circuit12} in W"
    lambda: return id(power_cir12).state;
    id: total_cir12
    accuracy_decimals: 0
    unit_of_measurement: "W"
    internal: true
    update_interval: 1s
    icon: mdi:gauge
  - platform: template
    name: "${name_circuit13} in W"
    lambda: return id(power_cir13).state;
    id: total_cir13
    accuracy_decimals: 0
    unit_of_measurement: "W"
    internal: true
    update_interval: 1s
    icon: mdi:gauge
  - platform: template
    name: "${name_circuit14} in W"
    lambda: return id(power_cir14).state;
    id: total_cir14
    accuracy_decimals: 0
    unit_of_measurement: "W"
    internal: true
    update_interval: 1s
    icon: mdi:gauge
  - platform: template
    name: "${name_circuit15} in W"
    lambda: return id(power_cir15).state;
    id: total_cir15
    accuracy_decimals: 0
    unit_of_measurement: "W"
    internal: true
    update_interval: 1s
    icon: mdi:gauge
  - platform: template
    name: "${name_circuit16} in W"
    lambda: return id(power_cir16).state;
    id: total_cir16
    accuracy_decimals: 0
    unit_of_measurement: "W"
    internal: true
    update_interval: 1s
    icon: mdi:gauge

    # phase A
  - platform: template
    name: $name_total_a_power
    lambda: return id(phase_a_power).state;
    update_interval: 1s
    id: total_power_a
    accuracy_decimals: 0
    unit_of_measurement: "W"
    internal: true
    icon: mdi:gauge
  - platform: total_daily_energy
    name: $name_total_a_energy
    power_id: total_power_a
    id: total_power_a_wh
    accuracy_decimals: 0
    unit_of_measurement: "Wh"
    internal: true
    icon: mdi:gauge
  - platform: total_daily_energy
    name: $name_total_a_energy
    power_id: total_power_a
    id: total_power_a_kwh
    accuracy_decimals: 3
    filters: [multiply: 0.001]
    unit_of_measurement: "kWh"
    internal: true
    icon: mdi:gauge
    # phase B
  - platform: template
    name: $name_total_b_power
    lambda: return id(phase_b_power).state;
    update_interval: 1s
    id: total_power_b
    accuracy_decimals: 0
    unit_of_measurement: "W"
    internal: true
    icon: mdi:gauge
  - platform: total_daily_energy
    name: $name_total_b_energy
    power_id: total_power_b
    id: total_power_b_wh
    accuracy_decimals: 0
    internal: true
    icon: mdi:gauge
  - platform: total_daily_energy
    name: $name_total_b_energy
    power_id: total_power_b
    id: total_power_b_kwh
    accuracy_decimals: 3
    filters: [multiply: 0.001]
    unit_of_measurement: "kWh"
    internal: true
    icon: mdi:gauge
    # phase C
  - platform: template
    name: $name_total_c_power
    lambda: return id(phase_c_power).state;
    update_interval: 1s
    id: total_power_c
    unit_of_measurement: "W"
    internal: true
    icon: mdi:gauge
  - platform: total_daily_energy
    name: $name_total_c_energy
    power_id: total_power_c
    id: total_power_c_wh
    accuracy_decimals: 0
    unit_of_measurement: "Wh"
    internal: true
    icon: mdi:gauge
  - platform: total_daily_energy
    name: $name_total_c_energy
    power_id: total_power_c
    id: total_power_c_kwh
    accuracy_decimals: 3
    filters: [multiply: 0.001]
    unit_of_measurement: "kWh"
    internal: true
    icon: mdi:gauge


  - { power_id: total_cir01, id: total_cir01_wh, platform: total_daily_energy, accuracy_decimals: 1, name: "${name_circuit01} in Wh", unit_of_measurement: "Wh", internal: true, icon: mdi:calendar-clock }
  - { power_id: total_cir02, id: total_cir02_wh, platform: total_daily_energy, accuracy_decimals: 1, name: "${name_circuit02} in Wh", unit_of_measurement: "Wh", internal: true, icon: mdi:calendar-clock }
  - { power_id: total_cir03, id: total_cir03_wh, platform: total_daily_energy, accuracy_decimals: 1, name: "${name_circuit03} in Wh", unit_of_measurement: "Wh", internal: true, icon: mdi:calendar-clock }
  - { power_id: total_cir04, id: total_cir04_wh, platform: total_daily_energy, accuracy_decimals: 1, name: "${name_circuit04} in Wh", unit_of_measurement: "Wh", internal: true, icon: mdi:calendar-clock }
  - { power_id: total_cir05, id: total_cir05_wh, platform: total_daily_energy, accuracy_decimals: 1, name: "${name_circuit05} in Wh", unit_of_measurement: "Wh", internal: true, icon: mdi:calendar-clock }
  - { power_id: total_cir06, id: total_cir06_wh, platform: total_daily_energy, accuracy_decimals: 1, name: "${name_circuit06} in Wh", unit_of_measurement: "Wh", internal: true, icon: mdi:calendar-clock }
  - { power_id: total_cir07, id: total_cir07_wh, platform: total_daily_energy, accuracy_decimals: 1, name: "${name_circuit07} in Wh", unit_of_measurement: "Wh", internal: true, icon: mdi:calendar-clock }
  - { power_id: total_cir08, id: total_cir08_wh, platform: total_daily_energy, accuracy_decimals: 1, name: "${name_circuit08} in Wh", unit_of_measurement: "Wh", internal: true, icon: mdi:calendar-clock }
  - { power_id: total_cir09, id: total_cir09_wh, platform: total_daily_energy, accuracy_decimals: 1, name: "${name_circuit09} in Wh", unit_of_measurement: "Wh", internal: true, icon: mdi:calendar-clock }
  - { power_id: total_cir10, id: total_cir10_wh, platform: total_daily_energy, accuracy_decimals: 1, name: "${name_circuit10} in Wh", unit_of_measurement: "Wh", internal: true, icon: mdi:calendar-clock }
  - { power_id: total_cir11, id: total_cir11_wh, platform: total_daily_energy, accuracy_decimals: 1, name: "${name_circuit11} in Wh", unit_of_measurement: "Wh", internal: true, icon: mdi:calendar-clock }
  - { power_id: total_cir12, id: total_cir12_wh, platform: total_daily_energy, accuracy_decimals: 1, name: "${name_circuit12} in Wh", unit_of_measurement: "Wh", internal: true, icon: mdi:calendar-clock }
  - { power_id: total_cir13, id: total_cir13_wh, platform: total_daily_energy, accuracy_decimals: 1, name: "${name_circuit13} in Wh", unit_of_measurement: "Wh", internal: true, icon: mdi:calendar-clock }
  - { power_id: total_cir14, id: total_cir14_wh, platform: total_daily_energy, accuracy_decimals: 1, name: "${name_circuit14} in Wh", unit_of_measurement: "Wh", internal: true, icon: mdi:calendar-clock }
  - { power_id: total_cir15, id: total_cir15_wh, platform: total_daily_energy, accuracy_decimals: 1, name: "${name_circuit15} in Wh", unit_of_measurement: "Wh", internal: true, icon: mdi:calendar-clock }
  - { power_id: total_cir16, id: total_cir16_wh, platform: total_daily_energy, accuracy_decimals: 1, name: "${name_circuit16} in Wh", unit_of_measurement: "Wh", internal: true, icon: mdi:calendar-clock }

  - { power_id: total_cir01, id: total_cir01_kwh, platform: total_daily_energy, accuracy_decimals: 3, name: "${name_circuit01} in kWh", unit_of_measurement: "kWh", internal: true, filters: [multiply: 0.001], icon: mdi:calendar-clock }
  - { power_id: total_cir02, id: total_cir02_kwh, platform: total_daily_energy, accuracy_decimals: 3, name: "${name_circuit02} in kWh", unit_of_measurement: "kWh", internal: true, filters: [multiply: 0.001], icon: mdi:calendar-clock }
  - { power_id: total_cir03, id: total_cir03_kwh, platform: total_daily_energy, accuracy_decimals: 3, name: "${name_circuit03} in kWh", unit_of_measurement: "kWh", internal: true, filters: [multiply: 0.001], icon: mdi:calendar-clock }
  - { power_id: total_cir04, id: total_cir04_kwh, platform: total_daily_energy, accuracy_decimals: 3, name: "${name_circuit04} in kWh", unit_of_measurement: "kWh", internal: true, filters: [multiply: 0.001], icon: mdi:calendar-clock }
  - { power_id: total_cir05, id: total_cir05_kwh, platform: total_daily_energy, accuracy_decimals: 3, name: "${name_circuit05} in kWh", unit_of_measurement: "kWh", internal: true, filters: [multiply: 0.001], icon: mdi:calendar-clock }
  - { power_id: total_cir06, id: total_cir06_kwh, platform: total_daily_energy, accuracy_decimals: 3, name: "${name_circuit06} in kWh", unit_of_measurement: "kWh", internal: true, filters: [multiply: 0.001], icon: mdi:calendar-clock }
  - { power_id: total_cir07, id: total_cir07_kwh, platform: total_daily_energy, accuracy_decimals: 3, name: "${name_circuit07} in kWh", unit_of_measurement: "kWh", internal: true, filters: [multiply: 0.001], icon: mdi:calendar-clock }
  - { power_id: total_cir08, id: total_cir08_kwh, platform: total_daily_energy, accuracy_decimals: 3, name: "${name_circuit08} in kWh", unit_of_measurement: "kWh", internal: true, filters: [multiply: 0.001], icon: mdi:calendar-clock }
  - { power_id: total_cir09, id: total_cir09_kwh, platform: total_daily_energy, accuracy_decimals: 3, name: "${name_circuit09} in kWh", unit_of_measurement: "kWh", internal: true, filters: [multiply: 0.001], icon: mdi:calendar-clock }
  - { power_id: total_cir10, id: total_cir10_kwh, platform: total_daily_energy, accuracy_decimals: 3, name: "${name_circuit10} in kWh", unit_of_measurement: "kWh", internal: true, filters: [multiply: 0.001], icon: mdi:calendar-clock }
  - { power_id: total_cir11, id: total_cir11_kwh, platform: total_daily_energy, accuracy_decimals: 3, name: "${name_circuit11} in kWh", unit_of_measurement: "kWh", internal: true, filters: [multiply: 0.001], icon: mdi:calendar-clock }
  - { power_id: total_cir12, id: total_cir12_kwh, platform: total_daily_energy, accuracy_decimals: 3, name: "${name_circuit12} in kWh", unit_of_measurement: "kWh", internal: true, filters: [multiply: 0.001], icon: mdi:calendar-clock }
  - { power_id: total_cir13, id: total_cir13_kwh, platform: total_daily_energy, accuracy_decimals: 3, name: "${name_circuit13} in kWh", unit_of_measurement: "kWh", internal: true, filters: [multiply: 0.001], icon: mdi:calendar-clock }
  - { power_id: total_cir14, id: total_cir14_kwh, platform: total_daily_energy, accuracy_decimals: 3, name: "${name_circuit14} in kWh", unit_of_measurement: "kWh", internal: true, filters: [multiply: 0.001], icon: mdi:calendar-clock }
  - { power_id: total_cir15, id: total_cir15_kwh, platform: total_daily_energy, accuracy_decimals: 3, name: "${name_circuit15} in kWh", unit_of_measurement: "kWh", internal: true, filters: [multiply: 0.001], icon: mdi:calendar-clock }
  - { power_id: total_cir16, id: total_cir16_kwh, platform: total_daily_energy, accuracy_decimals: 3, name: "${name_circuit16} in kWh", unit_of_measurement: "kWh", internal: true, filters: [multiply: 0.001], icon: mdi:calendar-clock }



time:
  - platform: sntp
    id: my_time
    timezone: $name_timezone
    servers:
      - 10.13.35.1
    on_time_sync:
      then:
        - logger.log: "Synchronized system clock"

    on_time:
      - seconds: /3
        then:
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/1/watt/state");
              payload: !lambda |-
                return to_string(id(total_cir01).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/2/watt/state");
              payload: !lambda |-
                return to_string(id(total_cir02).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/3/watt/state");
              payload: !lambda |-
                return to_string(id(total_cir03).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/4/watt/state");
              payload: !lambda |-
                return to_string(id(total_cir04).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/5/watt/state");
              payload: !lambda |-
                return to_string(id(total_cir05).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/6/watt/state");
              payload: !lambda |-
                return to_string(id(total_cir06).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/7/watt/state");
              payload: !lambda |-
                return to_string(id(total_cir07).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/8/watt/state");
              payload: !lambda |-
                return to_string(id(total_cir08).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/9/watt/state");
              payload: !lambda |-
                return to_string(id(total_cir09).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/10/watt/state");
              payload: !lambda |-
                return to_string(id(total_cir10).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/11/watt/state");
              payload: !lambda |-
                return to_string(id(total_cir11).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/12/watt/state");
              payload: !lambda |-
                return to_string(id(total_cir12).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/13/watt/state");
              payload: !lambda |-
                return to_string(id(total_cir13).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/14/watt/state");
              payload: !lambda |-
                return to_string(id(total_cir14).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/15/watt/state");
              payload: !lambda |-
                return to_string(id(total_cir15).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/16/watt/state");
              payload: !lambda |-
                return to_string(id(total_cir16).state);
      - seconds: /3
        then:
          - mqtt.publish:
              topic: "vue2/mains/A/watt/state"
              payload: !lambda |-
                return to_string(id(phase_a_power).state);
          - mqtt.publish:
              topic: "vue2/mains/B/watt/state"
              payload: !lambda |-
                return to_string(id(phase_b_power).state);
          - mqtt.publish:
              topic: "vue2/mains/C/watt/state"
              payload: !lambda |-
                return to_string(id(phase_c_power).state);
          - mqtt.publish:
              topic: "vue2/mains/A/voltage/state"
              payload: !lambda |-
                return to_string(id(phase_a_voltage).state);
          - mqtt.publish:
              topic: "vue2/mains/B/voltage/state"
              payload: !lambda |-
                return to_string(id(phase_b_voltage).state);
          - mqtt.publish:
              topic: "vue2/mains/C/voltage/state"
              payload: !lambda |-
                return to_string(id(phase_c_voltage).state);
      - seconds: /5
        then:
          - mqtt.publish:
              topic: "vue2/mains/A/wh/state"
              payload: !lambda |-
                return to_string(id(total_power_a_wh).state);
          - mqtt.publish:
              topic: "vue2/mains/B/wh/state"
              payload: !lambda |-
                return to_string(id(total_power_b_wh).state);
          - mqtt.publish:
              topic: "vue2/mains/C/wh/state"
              payload: !lambda |-
                return to_string(id(total_power_c_wh).state);

          - mqtt.publish:
              topic: "vue2/mains/A/kwh/state"
              payload: !lambda |-
                return to_string(id(total_power_a_kwh).state);
          - mqtt.publish:
              topic: "vue2/mains/B/kwh/state"
              payload: !lambda |-
                return to_string(id(total_power_b_kwh).state);
          - mqtt.publish:
              topic: "vue2/mains/C/kwh/state"
              payload: !lambda |-
                return to_string(id(total_power_c_kwh).state);
      - seconds: /10
        then:
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/1/wh/state");
              payload: !lambda |-
                return to_string(id(total_cir01_wh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/2/wh/state");
              payload: !lambda |-
                return to_string(id(total_cir02_wh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/3/wh/state");
              payload: !lambda |-
                return to_string(id(total_cir03_wh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/4/wh/state");
              payload: !lambda |-
                return to_string(id(total_cir04_wh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/5/wh/state");
              payload: !lambda |-
                return to_string(id(total_cir05_wh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/6/wh/state");
              payload: !lambda |-
                return to_string(id(total_cir06_wh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/7/wh/state");
              payload: !lambda |-
                return to_string(id(total_cir07_wh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/8/wh/state");
              payload: !lambda |-
                return to_string(id(total_cir08_wh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/9/wh/state");
              payload: !lambda |-
                return to_string(id(total_cir09_wh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/10/wh/state");
              payload: !lambda |-
                return to_string(id(total_cir10_wh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/11/wh/state");
              payload: !lambda |-
                return to_string(id(total_cir11_wh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/12/wh/state");
              payload: !lambda |-
                return to_string(id(total_cir12_wh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/13/wh/state");
              payload: !lambda |-
                return to_string(id(total_cir13_wh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/14/wh/state");
              payload: !lambda |-
                return to_string(id(total_cir14_wh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/15/wh/state");
              payload: !lambda |-
                return to_string(id(total_cir15_wh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/16/wh/state");
              payload: !lambda |-
                return to_string(id(total_cir16_wh).state);
      - seconds: /20
        then:
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/1/kwh/state");
              payload: !lambda |-
                return to_string(id(total_cir01_kwh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/2/kwh/state");
              payload: !lambda |-
                return to_string(id(total_cir02_kwh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/3/kwh/state");
              payload: !lambda |-
                return to_string(id(total_cir03_kwh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/4/kwh/state");
              payload: !lambda |-
                return to_string(id(total_cir04_kwh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/5/kwh/state");
              payload: !lambda |-
                return to_string(id(total_cir05_kwh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/6/kwh/state");
              payload: !lambda |-
                return to_string(id(total_cir06_kwh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/7/kwh/state");
              payload: !lambda |-
                return to_string(id(total_cir07_kwh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/8/kwh/state");
              payload: !lambda |-
                return to_string(id(total_cir08_kwh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/9/kwh/state");
              payload: !lambda |-
                return to_string(id(total_cir09_kwh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/10/kwh/state");
              payload: !lambda |-
                return to_string(id(total_cir10_kwh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/11/kwh/state");
              payload: !lambda |-
                return to_string(id(total_cir11_kwh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/12/kwh/state");
              payload: !lambda |-
                return to_string(id(total_cir12_kwh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/13/kwh/state");
              payload: !lambda |-
                return to_string(id(total_cir13_kwh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/14/kwh/state");
              payload: !lambda |-
                return to_string(id(total_cir14_kwh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/15/kwh/state");
              payload: !lambda |-
                return to_string(id(total_cir15_kwh).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/16/kwh/state");
              payload: !lambda |-
                return to_string(id(total_cir16_kwh).state);
      - seconds: 0
        minutes: /5
        then:
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/mains/A/name/state");
              payload: !lambda |-
                return id(phase_a_power).get_name();
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/mains/B/name/state");
              payload: !lambda |-
                return id(phase_b_power).get_name();
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/mains/C/name/state");
              payload: !lambda |-
                return id(phase_c_power).get_name();
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/1/name/state");
              payload: !lambda |-
                return id(power_cir01).get_name();
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/2/name/state");
              payload: !lambda |-
                return id(power_cir02).get_name();
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/3/name/state");
              payload: !lambda |-
                return id(power_cir03).get_name();
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/4/name/state");
              payload: !lambda |-
                return id(power_cir04).get_name();
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/5/name/state");
              payload: !lambda |-
                return id(power_cir05).get_name();
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/6/name/state");
              payload: !lambda |-
                return id(power_cir06).get_name();
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/7/name/state");
              payload: !lambda |-
                return id(power_cir07).get_name();
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/8/name/state");
              payload: !lambda |-
                return id(power_cir08).get_name();
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/9/name/state");
              payload: !lambda |-
                return id(power_cir09).get_name();
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/10/name/state");
              payload: !lambda |-
                return id(power_cir10).get_name();
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/11/name/state");
              payload: !lambda |-
                return id(power_cir11).get_name();
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/12/name/state");
              payload: !lambda |-
                return id(power_cir12).get_name();
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/13/name/state");
              payload: !lambda |-
                return id(power_cir13).get_name();
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/14/name/state");
              payload: !lambda |-
                return id(power_cir14).get_name();
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/15/name/state");
              payload: !lambda |-
                return id(power_cir15).get_name();
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/16/name/state");
              payload: !lambda |-
                return id(power_cir16).get_name();

@tappyson
Copy link

tappyson commented Jul 1, 2022

@tappyson you're on the right track. You have the instantaneous power imported and exported. But you need to add that up over time.

Try adding two more sensors like the existing total daily energy:

  - platform: total_daily_energy
    name: "Total Daily Energy"
    power_id: total_power
    accuracy_decimals: 0

Details on how it works: https://esphome.io/components/sensor/total_daily_energy.html

You'll want to replace the thing it's summing over with your totalexported, etc.

PS: I fixed the formatting, here's an explanation of how it works

Thanks so much. Got to working a treat.

@tappyson
Copy link

tappyson commented Jul 1, 2022

What would good practice be for creating a 1 or 5 min sensor. Create a new sensor with more datapoints using the rolling moving average?

Also does anyone know of a good way to send only say 5min data but then activate a 1s sensor for live viewing with some form of button click?

@flaviut
Copy link
Author

flaviut commented Jul 2, 2022

@tappyson

What would good practice be for creating a 1 or 5 min sensor. Create a new sensor with more datapoints using the rolling moving average?

Yup, exactly. Moving averages are way more complicated than you'd expect, but the sliding_window_moving_average is likely what you're looking for.

Also does anyone know of a good way to send only say 5min data but then activate a 1s sensor for live viewing with some form of button click?

Sorry, I can't help here.


@devWaves Thanks for the reminder! I've updated the guide.

@cosmicosmo4
Copy link

cosmicosmo4 commented Jul 4, 2022

I am having an issue, my total_daily_energy sensors are not resetting at all. I am running esphome and homeassistant in docker containers, with configs nearly identical to the example. I do see the accurate local time in my esphome logs.

In the device's config I have:

time:
  - platform: sntp
    id: my_time

In docker-compose.yaml I have:

    environment:
      ESPHOME_DASHBOARD_USE_PING: 'true'
      TZ: 'America/Chicago'
    volumes:
      - './esphomeconfig/:/config:rw'
      - /etc/localtime:/etc/localtime
      - /etc/timezone:/etc/timezone

(possibly redundant?)

And in the logs I see:

[10:14:17][C][sntp:050]: SNTP Time:
[10:14:17][C][sntp:051]:   Server 1: '0.pool.ntp.org'
[10:14:17][C][sntp:052]:   Server 2: '1.pool.ntp.org'
[10:14:17][C][sntp:053]:   Server 3: '2.pool.ntp.org'
[10:14:17][C][sntp:054]:   Timezone: 'CST6CDT,M3.2.0,M11.1.0'
[10:14:19][D][sensor:125]: 'Total Power': Sending state 236.83893 W with 1 decimals of accuracy
[10:14:19][D][sensor:125]: 'Total Daily Energy': Sending state 283491.21875 Wh with 0 decimals of accuracy

which is the correct local time.

The device is in a VLAN that's firewalled off from the internet, but I opened a rule to allow it to send packets to port 123:

image

But the data just keeps going up:

image

Thanks for any help!

@Ofloo
Copy link

Ofloo commented Jul 4, 2022

you need cycle: daily inside your energy total`

  - platform: total_daily_energy
    name: "Total Daily Energy"
    power_id: total_power
    accuracy_decimals: 0
    cycle: daily

@cosmicosmo4
Copy link

That gives me:
image

@flaviut
Copy link
Author

flaviut commented Jul 4, 2022

I don't see a cycle parameter documented: https://esphome.io/components/sensor/total_daily_energy.html

Anyway @cosmicosmo4, are you sure the time is getting synchronized? You should see a log message: esphome/issues#449 (comment)

@cosmicosmo4
Copy link

I haven't noticed the "Synchronizing..." message. How often is it supposed to synchronize? Also, I do have the correct time in the logs, so it must have synchronized at some point.

@Ofloo
Copy link

Ofloo commented Jul 4, 2022

oh that's inside the emporia config

I have

time:
  - platform: sntp
    id: my_time
    timezone: $name_timezone
    servers:
      - 10.13.35.1
    on_time_sync:
      then:
        - logger.log: "Synchronized system clock"

However keep in mind that I have setup ntp on my gateway don't like my iot clients going to the internet so ...

@stephenjamieson
Copy link

You could try syncing with homeassistant:

time:
  - platform: homeassistant
    id: homeassistant_time
    timezone: America/New_York

@Ofloo
Copy link

Ofloo commented Jul 4, 2022

for name_timezone I have name_timezone: 'CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00'

@flaviut
Copy link
Author

flaviut commented Jul 4, 2022

I'm out of ideas :)

I'd suggest asking the ESPHome community directly. Please let us know what you find out!

@cosmicosmo4
Copy link

cosmicosmo4 commented Jul 11, 2022

Well I solved the problem by specifying the IP addresses of some NTP servers. I have no idea why the emporia was either not finding my pihole or failing DNS lookup for some reason. Everything else on this VLAN works fine.

time:
  - platform: sntp
    id: my_time
    servers:
      - 69.130.244.141
      - 69.164.198.192
      - 185.216.231.116

Unfortunately I imagine this is more likely to break in the future if IP addresses change.

@cdavis289
Copy link

Just wanted to say thanks for all of your work! I set this up yesterday and everything went very smoothly. I wanted to add some additional info for others that install this. I was quite nervous when I did this and this info may help others.

  1. Instead of holding the wire from the IO0 pin to the shield I used a piece of masking tape. I'm not sure if that is risky, but it worked for me.
  2. On os x, if this command failed "esptool.py -b 921600 read_flash 0 0x800000" I had to unplug my USB to serial converter module before trying the other baud rate otherwise I would get "in use" errors.
  3. When I ran the command "esphome run vue2.yaml" I didn't receive any errors.

To do a quick test after the software is flashed, I disconnected the power (VCC) and the IO0 ground, then plugged the VCC pin back in. You can then see if the unit successfully connects to your wifi without having to assemble the entire unit.

@flaviut
Copy link
Author

flaviut commented Jul 13, 2022

  1. Instead of holding the wire from the IO0 pin to the shield I used a piece of masking tape. I'm not sure if that is risky, but it worked for me.

Good idea! I've made a note of that in the instructions

You're right, I've taken so much stuff apart that I don't feel this is at all risky. But people unfamiliar with electronics very likely feel differently.

For future calibration, the only risk here is connecting the positive power and ground backwards, and I think that might be OK too as long as you notice within a few seconds.

To do a quick test after the software is flashed, I disconnected the power (VCC) and the IO0 ground, then plugged the VCC pin back in

Yes, this works, but some adapters don't have enough power to do this, since WiFi draws a lot of power. There's no risk of harm, but it will just keep turning on and off. So rather than answer questions about that, I've omitted it. I've never heard of any trouble connecting to WiFi, so it seems to have worked out!

@PanicRide
Copy link

Instead of holding the wire from the IO0 pin to the shield I used a piece of masking tape.

If your TTL adapter happens to have both the DTR and RTS pins exposed, you can let it automatically reboot the board and put the chip into flash mode when necessary. IO0 connects to DTR, and EN connects to RTS.

Here's an example of an adapter where you can easily solder a PIN to RTS on the side of it. :)

@rjchu
Copy link

rjchu commented Jul 13, 2022

@plopes9000
Thank you for your reply and MQTT code/config example, I appreciate it! I finally had a chance to give this a try and while things compile just fine, when I try and upload I get the output below and all that the Emporia publishes to MQTT is the status as being online or offline - no actual telemetry is published. Any ideas?

I'm on ESPHome 2022.6.22

INFO Uploading /config/.esphome/build/vue-casita-mains/.pioenvs/vue-casita-mains/firmware.bin (881440 bytes)
Uploading: [============================================================] 100% Done...

INFO Waiting for result...
INFO OTA successful
INFO Successfully uploaded program.
Traceback (most recent call last):
File "/usr/local/bin/esphome", line 33, in
sys.exit(load_entry_point('esphome', 'console_scripts', 'esphome')())
File "/esphome/esphome/main.py", line 931, in main
return run_esphome(sys.argv)
File "/esphome/esphome/main.py", line 918, in run_esphome
rc = POST_CONFIG_ACTIONS[args.command](args, config)
File "/esphome/esphome/main.py", line 397, in command_run
return show_logs(config, args, port)
File "/esphome/esphome/main.py", line 292, in show_logs
return mqtt.show_logs(
File "/esphome/esphome/mqtt.py", line 105, in show_logs
topic = config[CONF_MQTT][CONF_LOG_TOPIC][CONF_TOPIC]
TypeError: 'NoneType' object is not subscriptable

@flaviut
Copy link
Author

flaviut commented Jul 16, 2022

@rjchu If you're not using their manual timing of MQTT messages, you'll want to remove the internal: true fields from the config.

As far as the other issue, try clearing the ESPHome caches. I'm not sure how to do that on your particular setup, but it might help out.

@wbarber69
Copy link

not sure what to do. Ive followed the directions. Ive got esphome to install through the terminal on my pc. Ive double checked and my vue just inst coming online on my wifi. my credentials are correct. when i get to the logger portion of installing, nothing shows in the terminal, it just sits as if its waiting for data but nothing comes through. I cannot understand why the device wont join my network. am i supposed to hook it up to mains for wifi to start working? shouldnt the esp module work independantly of the rest of the board? Has something changed that isnt being reflected in the instructions?

@wbarber69
Copy link

okay so I guess its a combination of not having the antenna connected and the usb to serial not delivering enough power for wifi. its on wifi now, but in the logs i get nothing:

INFO Reading configuration /config/esphome/vue2.yaml... INFO Detected timezone 'America/Chicago' INFO Starting log output from 192.168.1.178 using esphome API

@wbarber69
Copy link

And to make matters worse i cannot do ota updates to try to fix anything because i keep getting the error:
Error: Could not find the package with 'platformio/toolchain-esp32ulp @ ~1.22851.0' requirements for your system 'linux_aarch64'

but I have no other way to use esphome. its either pi4 and HAOS or win10 over usb-serial.

@cdavis289
Copy link

And to make matters worse i cannot do ota updates to try to fix anything because i keep getting the error: Error: Could not find the package with 'platformio/toolchain-esp32ulp @ ~1.22851.0' requirements for your system 'linux_aarch64'

but I have no other way to use esphome. its either pi4 and HAOS or win10 over usb-serial.

The error you are getting sounds similar to the error when you try to compile the yaml on the rpi. I had to setup esphome on my Mac to compile and OTA the updated bin files.

Do you have the unit installed with the clamps in your panel and you are not seeing any output?

@wbarber69
Copy link

I know that. I got the device online, and figured id try to install from esphome off HAOS as ive been having so many problems doing it from cmd terminal. Its not that i get no output with or without clamps, the logs timeout over and over again when trying to read logs. they arent empty there is nothing being reported.

@wbarber69
Copy link

okay Im not sure whats going on. Now HAOS is reporting 37 devices and i can see the power consumption. I guess i just had to wait 3 hours... Only issue now is that i left the configuration as is from the instructions intending to go in and change the clamp IDs etc. so now its working, but now am going to have to pull it all the way apart to be able to change settings?

@cdavis289
Copy link

okay Im not sure whats going on. Now HAOS is reporting 37 devices and i can see the power consumption. I guess i just had to wait 3 hours... Only issue now is that i left the configuration as is from the instructions intending to go in and change the clamp IDs etc. so now its working, but now am going to have to pull it all the way apart to be able to change settings?

You don’t need to remove it from the panel or take it apart. You can setup esphome on windows and update the config OTA.

@wbarber69
Copy link

Still no log output though. the esphome integration is showing active details, but no logs are viewable from esphome, just keeps timing out!!! wth?

@wbarber69
Copy link

okay Im not sure whats going on. Now HAOS is reporting 37 devices and i can see the power consumption. I guess i just had to wait 3 hours... Only issue now is that i left the configuration as is from the instructions intending to go in and change the clamp IDs etc. so now its working, but now am going to have to pull it all the way apart to be able to change settings?

You don’t need to remove it from the panel or take it apart. You can setup esphome on windows and update the config OTA.

yeah i wouldnt be complaining if that was an option. it also times out trying to connect.

@flaviut
Copy link
Author

flaviut commented Jul 17, 2022

@wbarber69 is the antenna fully screwed on? Is it fully inserted into the pcb? Is the antenna sticking out a side of the panel box that has the fewest wires (nearby wires interfere)? What happens if you move an access point closer to your panel?

@wbarber69
Copy link

the antenna is fine. the device is relaying information to HAOS but i cannot initiate a log output from ephome. I cannot do an ota update either through haos or esphome on windows, as it simply times out.

@wbarber69
Copy link

nevermind..... it was a stupid typo

@wbarber69
Copy link

well thanks guys, even if it was my stupid mistake. Now onto cracking open and hacking esphome onto all my emporia plugs.....

@stratus-ss
Copy link

Does anyone know how to get Home Assistant's Grid Consumption to recognize total power coming in off the grid. I assume there is something I have to do with the Vue template. Currently total power is set like this (I believe this is from the example)

 - platform: template
    name: "Total Power"
    lambda: return id(phase_a_power).state + id(phase_b_power).state;
    update_interval: 1s
    id: total_power
    unit_of_measurement: "W"

Does this have to be Wh?

@flaviut
Copy link
Author

flaviut commented Jul 26, 2022

Power is in watts, energy is in watt-hours or joules. Take a look at and use total_daily_energy, the next entry down.

I can't remember how I configured homeassistant, but everything you need should be in there--I have the exact same config, with a few numbers and names switched around.

@cdavis289
Copy link

cdavis289 commented Jul 26, 2022

Here is my code. You need to first get total power and then you use the total daily energy platform.

- platform: template
    name: "${friendly_devicename}: Total Power"
    lambda: return id(${devicename_no_dashes}_phase_a_power).state + id(${devicename_no_dashes}_phase_b_power).state;
    update_interval: 1s
    id: "${devicename_no_dashes}_total_power"
    unit_of_measurement: "W"
  
  - platform: total_daily_energy
    name: "${friendly_devicename}: Total Daily Energy"
    power_id: "${devicename_no_dashes}_total_power"
    accuracy_decimals: 0

@stratus-ss
Copy link

thanks @cdavis289 and @flaviut I appreciate what you both do to help this project!

@hiveai
Copy link

hiveai commented Jul 28, 2022

What is the recommended config for an unused input on the emporia vue2? I have some unused inputs that are showing values that are jumping all around (e.g. 0W->8W->24W->0W). How can I configure these Emporia inputs as unused and zero them out?

@flaviut
Copy link
Author

flaviut commented Jul 28, 2022

@hiveai delete their lines in the config and remove the places they're referenced from

@hiveai
Copy link

hiveai commented Jul 29, 2022

@flaviut and other contributors: Thanks for this great project and documentation! I have the vue2 flashed with custom ESPHome code and it working.
Is there a pointer to the recommended way to integrate the data into the energy dashboard in home assistant? I can bring up the device under ESPHome and see the power usage, but I'm not clear on how to configure Home Assistant to use this as a data source for energy monitoring.

@cdavis289
Copy link

Settings -> Dashboards -> Energy -> Electricity Grid (left side) -> Add Consumption or Add device

Select Emporia Vue Circuit Daily Energy Entities or Total Daily Energy.

I like to add each circuit to the consumption. Home assistant will stack the entities in the bar chart so you can get a visual of which circuit uses the most energy. You can also add them to the devices to see a comparison. Just depends on your preference.

@hiveai
Copy link

hiveai commented Jul 29, 2022

@cdavis289 Thanks! That's the info I needed. Looking up in the other comments I see that some folks are using MQTT for integration. Is that in addition to adding devices to the energy dashboard, or instead of the energy dashboard integration. What does MQTT integration of the ESPHome Vue2 get you? I apologize for these basic questions, but looking at the documentation and previous Comments/Q&A it's not clear to me.

@flaviut
Copy link
Author

flaviut commented Jul 29, 2022 via email

@dcorwin8222
Copy link

dcorwin8222 commented Jul 31, 2022 via email

@flaviut
Copy link
Author

flaviut commented Jul 31, 2022

@Jens5395
Copy link

Jens5395 commented Aug 5, 2022

If I upload the bare stub that is generated when a new device is added to ESPHome, should the Emporia connect to wifi? I can't upload the full configuration because it won't compile on the pi4 so I was hoping to maybe do the full configuration over the air once the Emporia is connected to the network. Right now I am dead in the water :(

@flaviut
Copy link
Author

flaviut commented Aug 5, 2022 via email

@Jens5395
Copy link

Jens5395 commented Aug 6, 2022

What's a 'regular computer'? LOL
Anyway, things have progressed substantially from my earlier post. The stub uploads and programs just fine and if you supply enough juice, the emporia does connect to the wifi network. I had to hook up line power to the emporia to make it run.
I tried everything I could think of to upload the required configuration but of course because of the lack of the required tool chain, that got me nowhere :(.
I have now set up an ubuntu laptop with ESPHome and ESPHome dashboard (no Home Assistant) and I got the configuration to compile! now my problem is 'how do I get the magic file that compiled onto the emporia which is wifi connected to the emporia'.. Unfortunately the upload via wifi fails and the ESPHome program will not recognize my serial port to do a wired transfer.
I am also working on some network issues because even though Ubiquity reports the empora to be on line, I can not ping it (although pings might not be allowed in ESPHome.
More research is required!

@flaviut
Copy link
Author

flaviut commented Aug 6, 2022

I'm pretty sure something weird is going on with your wifi, ping works fine for me:

$ ping emporiavue2.lan
PING emporiavue2.lan (192.168.86.144) 56(84) bytes of data.
64 bytes from emporiavue2.lan (192.168.86.144): icmp_seq=1 ttl=255 time=114 ms
64 bytes from emporiavue2.lan (192.168.86.144): icmp_seq=2 ttl=255 time=17.5 ms
64 bytes from emporiavue2.lan (192.168.86.144): icmp_seq=3 ttl=255 time=55.1 ms

anyway, now that you've compiled the file, you can transfer the .bin file over to the Pi, where presumably you had a working serial connection. Something like esptool.py --port /dev/ttyUSB0 write_flash 0x0 emporiavue2.bin should work.

@Jens5395
Copy link

Jens5395 commented Aug 6, 2022

Unfortunately, I am giving up for now.
I am now able to send a configuration from my secondary (non pi4) computer to the emporia but I am now getting a butt load of linking errors during the compile which I do not know how to deal with.
Note that I DO NOT HAVE the full Home Assistant installed on this computer. I only installed ESPHome and ESPHome dashboard. I suspect that some of te stuff that is being complained about relates to the HA not being installed.
Here is a shortened version that shows the beginning of the compile followed by a tiny portion of the linking errors (everything after the line that starts with "linking...." is an error message:

INFO Reading configuration config/emporia-01.yaml...
INFO Detected timezone 'America/Vancouver'
INFO Generating C++ source...
INFO Compiling app...
Processing emporia-01 (board: esp32dev; framework: espidf; platform: platformio/espressif32 @ 3.5.0)

HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash

  • framework-espidf @ 3.40302.0 (4.3.2)
  • tool-cmake @ 3.16.4
  • tool-ninja @ 1.7.1
  • toolchain-riscv32-esp @ 8.4.0+2021r2-patch2
  • toolchain-xtensa-esp32 @ 8.4.0+2021r2-patch2
  • toolchain-xtensa-esp32s2 @ 8.4.0+2021r2-patch2
    Reading CMake configuration...
    LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
    No dependencies
    Linking .pioenvs/emporia-01/firmware.elf
    /home/jens/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pioenvs/emporia-01/src/esphome/components/api/api_connection.o:(.literal._ZN7esphome3api13APIConnection17send_sensor_stateEPNS_6sensor6SensorEf+0xc): undefined reference to esphome::sensor::Sensor::has_state() const' /home/jens/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pioenvs/emporia-01/src/esphome/components/api/api_connection.o:(.literal._ZN7esphome3api13APIConnection16send_sensor_infoEPNS_6sensor6SensorE+0x10): undefined reference to esphome::sensor::Sensor::get_unit_of_measurementabi:cxx11'
    /home/jens/.platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pioenvs/emporia-01/src/esphome/components/api/api_connection.o:(.literal._ZN7esphome3api13APIConnection16send_sensor_infoEPNS_6sensor6SensorE+0x14): undefined reference to `esphome::sensor::Sensor::get_accuracy_decimals()'

@Jens5395
Copy link

Jens5395 commented Aug 7, 2022

Final entry:

For reasons unknown to me, the Emporia configuration compiled, was installed wireless and seems to function. There was a computer reboot involved so that might have fixed whatever was causing the compile errors.
To sum it up, a pi4 64 bit HA server configuration can not compile the Emporia Vue 2 configuration via ESPHome. It can however generate a configuration stub that, once uploaded to the emporia with a wired connection, will allow the emporia to connect to the network via wifi.
Now that the Emporia is on line, the Emporia configuration can be built. This is done, in my case, on a Ubuntu machine that runs an Intel processor and has the required tool chains available.
I installed ESPHome and ESPHome dashboard on my computer (the one wit the Intel processor). Note that there was only ESPHome installed and no Home Assistant files/system. I started up ESPHome, went to the dashboard (btw, you can also do this without the dashboard and I think I read that the dashboard only works on Linux) and generated a new stub for the Emporia. I then copied the configuration as shown in the article here into the stub, over-writing the temporary stub (it was just a place holder). I adjusted the wifi parameters for my setup. There are a couple of gotcha's here. My normal esphome configuration files use !secrets for the ssid and password. This will not work because we are compiling on a computer that does not have these HA options available. The ssid and password must be hard coded into the configuration. I also had to set up static IP parameters in the configuration in order to make this work .... although I can't recall the exact reason. All my esphome devices have static IP's set up in the router so hardcoding a static IP in the configuration might not be required. YMMV.
So, we have an Emporia device that is on the network and we have a configuration file set up on the Intel computer. All that is required now is to install the new configuration to the Emporia.
If all goes as planned (and not like in my case), the configuration will be compiled, uploaded to the Emporia that is on line already and when finished, the Emporia will reboot and spew out all kinds of data which will be captured in the Home Assistant system running on the Pi4.
When you set up the hard coded credentials, please note that the SSIDS field is case sensitive. I new this was so for the password but did not realize that this was the case for the SSID. That error took me WAY too long to find!
I hope that this might help future HA builders to set up an Emporia device without all the crap I went through .....

@Jens5395
Copy link

Jens5395 commented Aug 7, 2022

The instructions for the Emporia indicate that it doesn't matter which of the three 200A circuits you plug into. I am in North America so there are two 200A clamps and it does indeed matter how they are connected to the Emporia. With the configuration script shown in this article, one needs to use inputs A and B.
Yes I know they are called A and B in the configuration but I didn't make the connection ....
While the instructions allude to the fact that you need to keep the legs sorted, I would like to stress that it is important not only for the current clamps but also how you hook up power to the Emporia. If the power leads to the emporia do not not match which 200A clamp is on what leg, readings might be wrong or you might have no readings at all. The black Emporia power wire needs to be on the same power distribution leg that has current clamp A on it. The red power wire needs to be on the same power leg as the clamp that feeds input B.

@Jens5395
Copy link

Jens5395 commented Aug 7, 2022

How does HA know when to reset daily energy numbers? My new install doesn't seem to reset at midnight.

@flaviut
Copy link
Author

flaviut commented Aug 7, 2022 via email

@flaviut
Copy link
Author

flaviut commented Aug 7, 2022 via email

@clowrey
Copy link

clowrey commented Aug 8, 2022

Thanks for all the work getting this working!! I spent about 5 hours thinking there was some way I could get it to compile on a raspberry pi 4 with 4gb ram- including switching to the 32bit version, but it still wont work.. So in the end I relented and am now running home assistant on a 7 year old i3 intel NUC and it works great!! I definitely recommend anyone wanting to use this currently in a standalone installation to just buy a used intel NUC for < $100 on ebay and be done with it... Going to try get it working with three phase inputs some time soon, not sure how hard/easy that will be.

EDIT > looks like it works with three phase just by adding in phase C in the config file! awesome!

@Jens5395
Copy link

Jens5395 commented Aug 8, 2022

I spent way too many hours on this ... but in the end, my method works great and I still have my original Pi4 running HA.

@clowrey
Copy link

clowrey commented Aug 8, 2022

I spent way too many hours on this ... but in the end, my method works great and I still have my original Pi4 running HA.

But can you change the ESPhome settings from the RPI4? that is my main reason, I anticipate needing to re-compile and update, and will have remote systems running this etc..

Edit > I'm not saying one method is better than the other, just saying for me this is overall easier and more maintainable, at least until we can compile it on ARM..

@Jens5395
Copy link

Jens5395 commented Aug 8, 2022

No, I would not be able to change the configuration from the Pi4 .... that would require a recompile which can't be done from the Pi4.
I installed ESPHome and the dashboard on one of my laptops. It just sits there ready for use. If I need to recompile, I just start up ESPHome, go to the dashboard, load te configuration file, tweak it and send it back to the Emporia - no muss, no fuss, I just have to remember to do it via Chrome instead of my normal browser (Thunderbird).
I recompiled a whole bunch of times as I was setting everything up so yes, you absolutely need to be able to recompile and send te result to the Emporia. I am still working out a couple of issues and expect that I am not finished configuring things.
BTW, I did not try generating the .bin file on my laptop, transfer it to the pi and then send it to the Emporia. That should (in theory) work but it's an extra step that is not really required.

@Jens5395
Copy link

Jens5395 commented Aug 9, 2022

Does anybody else have issues with 'daily energy' never resetting at the end of the day?
I did need to set my own sntp server (network doesn't allow traffic to the outside) but that didn't help. Looking at the logs from the Emporia, every message has the correct time in front of it.
Let me clarify this a bit - if I look at the 'energy' dashboard, the daily energy is correct. I have an 'entities' card set up in one of my dashboard views and it shows individual circuits and individual daily power usage (and total daily power usage). It is those totals sensors that do not reset.
Platfom 'Total Daily Energy Sensor' states:

# Enable time component to reset energy at midnight
time:
  - platform: sntp
    id: my_time

From what I can tell, the time platform is working as every single status message from the Emporia has the correct time stamp .... but maybe that time component is different from the time that shows up in the logs - how do I check if id: my_time is correct? my_time is not an entity or a helper so how can I verify it?

@mgulick
Copy link

mgulick commented Aug 9, 2022

Does anybody else have issues with 'daily energy' never resetting at the end of the day?

My daily energy value also did not reset at first. I don't know exactly what I did to fix it. It may have started working on its own at some point after a few days or maybe a week. I do remember that I changed the time platform from sntp to:

time:
  - platform: homeassistant
    id: homeassistant_time

This is working fine for me and is syncing time via home assistant. I have my emporia vue 2 on an isolated VLAN which doesn't have internet access, so sntp probably wasn't working (my DHCP server hands out local ntp server info, but I think most devices ignore that).

@Jens5395
Copy link

Jens5395 commented Aug 9, 2022

Thanks for that mgulick. I tried that this morning but this gives me a compile error which is likely due to me having to compile the Emporia configuration on a computer other than the computer running HA.
It is good to know I am not the only person that has/had daily reset issues.

*** [.pioenvs/emporia-01/src/esphome/components/sntp/sntp_component.o] Source `src/esphome/components/sntp/sntp_component.cpp' not found, needed by target `.pioenvs/emporia-01/src/esphome/components/sntp/sntp_component.o'.

@stephenjamieson
Copy link

Is there another location, discord or an issue somewhere, that these things can be discussed. I'm honestly watching this gist in case there are changes or issues with the integration itself.

@clowrey
Copy link

clowrey commented Aug 9, 2022

You could just watch the Integration source repository that is linked to in the example configuration. Not sure where else to discuss issues as there is no issue tracker?

changes or issues with the integration itself.

@mgulick
Copy link

mgulick commented Aug 9, 2022

@Jens5395, I would frequently have compile errors when rebuilding after making changes to the configuration. Cleaning the build artifacts usually resolved the issue. It looks like this option is called "Clean Build Files" from the ESPHome dashboard (https://esphome.io/guides/getting_started_hassio.html) and esphome clean <config> from the ESPHome CLI (https://esphome.io/guides/cli.html#clean-command).

@Jens5395
Copy link

Jens5395 commented Aug 9, 2022

Ha!!!! That did the trick, it compiled! Now to see if it fixes things at midnight ....
Thanks!

@stephenjamieson
Copy link

@clowrey sure, my point is that these issues are not related to the Emporia Vue.

@flaviut
Copy link
Author

flaviut commented Aug 9, 2022

Please keep all discussion here

Hey y'all, I've had my own gripes with Gist as a discussion platform as well.

Any further comments here will be deleted and recreated in https://github.com/emporia-vue-local/esphome/discussions. This will be the last comment on this gist.

@doronazl
Copy link

@rjchu, Yes mqtt is working quite well - I use FHEM (https://fhem.de/) hence mqtt is my choice of integration in this case.

Btw, unlike the emporia app which only calculates apparent power on the 16 CTs, this implementation is correctly measuring real power - thank you @flaviut !

sudo docker run --rm -v "${PWD}":/config -it esphome/esphome version
Version: 2022.6.0

here is my draft config - still making design decisions but working quite well already. the send times are temporarily set too low, I plan on every 10 secs for instant and every 5 mins for totals, etc

esphome:
  name: emporiavue2

external_components:
  - source: github://flaviut/esphome@emporia-vue-2022.4.0
    components: [ emporia_vue ]

esp32:
  board: esp32dev
  framework:
    type: esp-idf
    version: recommended

# Enable Home Assistant API
#api: {"password": "<ota password>"}
ota: {"password": "<xyz>"}

# Enable logging
logger:
  level: WARN

wifi:
  ssid: "myssid"
  password: "mypassword"

mqtt:
  broker: 1.2.3.4
  client_id: vue2
  username: myuser
  password: mypassword
  port: 1883
  topic_prefix: vue2
  discovery: false
  log_topic: null


i2c:
  sda: 21
  scl: 22
  scan: false
  frequency: 200kHz  # recommended range is 50-200kHz
  id: i2c_a

# these are called references in YAML. They allow you to reuse
# this configuration in each sensor, while only defining it once
.defaultfilters:
  - &moving_avg
    # we capture a new sample every 0.24 seconds, so the time can
    # be calculated from the number of samples as n * 0.24.
    sliding_window_moving_average:
      # we average over the past 2.88 seconds
      window_size: 12
      # we push a new value every 1.44 seconds
      send_every: 6
  - &invert
    # invert and filter out any values below 0.
    lambda: 'return max(-x, 0.0f);'
  - &pos
    # filter out any values below 0.
    lambda: 'return max(x, 0.0f);'
  - &abs
    # take the absolute value of the value
    lambda: 'return abs(x);'

sensor:
  - platform: emporia_vue
    i2c_id: i2c_a
    phases:
      - id: phase_a  # Verify that this specific phase/leg is connected to correct input wire color on device listed below
        input: BLACK  # Vue device wire color
        calibration: 0.0229  # 0.022 is used as the default as starting point but may need adjusted to ensure accuracy
        # To calculate new calibration value use the formula <in-use calibration value> * <accurate voltage> / <reporting voltage>
        voltage:
          name: "Phase A Voltage"
          internal: true
          id: phase_a_voltage
          filters: [*moving_avg, *pos]
      - id: phase_b  # Verify that this specific phase/leg is connected to correct input wire color on device listed below
        input: RED  # Vue device wire color
        calibration: 0.022  # 0.022 is used as the default as starting point but may need adjusted to ensure accuracy
        # To calculate new calibration value use the formula <in-use calibration value> * <accurate voltage> / <reporting voltage>
        voltage:
          name: "Phase B Voltage"
          internal: true
          id: phase_b_voltage
          filters: [*moving_avg, *pos]
      - id: phase_c  # Verify that this specific phase/leg is connected to correct input wire color on device listed below
        input: BLUE  # Vue device wire color
        calibration: 0.022193  # 0.022 is used as the default as starting point but may need adjusted to ensure accuracy
        # To calculate new calibration value use the formula <in-use calibration value> * <accurate voltage> / <reporting voltage>
        voltage:
          internal: true
          name: "Phase C Voltage"
          id: phase_c_voltage
          filters: [*moving_avg, *pos]
    ct_clamps:
      - phase_id: phase_a
        input: "A"  # Verify the CT going to this device input also matches the phase/leg
        power:
          name: "Phase A Power"
          internal: true
          id: phase_a_power
          device_class: power
          filters: [*moving_avg, *pos]
      - phase_id: phase_b
        input: "B"  # Verify the CT going to this device input also matches the phase/leg
        power:
          name: "Phase B Power"
          internal: true
          id: phase_b_power
          device_class: power
          filters: [*moving_avg, *pos]
      - phase_id: phase_c
        input: "C"  # Verify the CT going to this device input also matches the phase/leg
        power:
          name: "Phase C Power"
          internal: true
          id: phase_c_power
          device_class: power
          filters: [*moving_avg, *pos]
      # Pay close attention to set the phase_id for each breaker by matching it to the phase/leg it connects to in the panel
      - { phase_id: phase_b, input:  "1", power: { name: "Front Steps (Camera, Lights)",                            internal: true, id:  cir1, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_b, input:  "2", power: { name: "Kitchen Left (Fridge, Oven, Microwave)",                  internal: true, id:  cir2, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_b, input:  "3", power: { name: "Kitchen Right (Dishwasher, Coffee Machine)",              internal: true, id:  cir3, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_b, input:  "4", power: { name: "4 ??",                                                       internal: true, id:  cir4, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_c, input:  "5", power: { name: "Kitchen Stove",                                           internal: true, id:  cir5, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_b, input:  "6", power: { name: "Downstairs Right (Study, Hall, Bathroom, Guest, Server)", internal: true, id:  cir6, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_c, input:  "7", power: { name: "Downstairs Left (Living, Dining Room)",                   internal: true, id:  cir7, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_b, input:  "8", power: { name: "Upstairs (Master Bedroom)",                               internal: true, id:  cir8, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "9", power: { name: "Upstairs (incl. Attic lights, except Master Bedroom)",    internal: true, id:  cir9, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_c, input: "10", power: { name: "Cellar, Washing Room, Power Room (incl. Freezer)",        internal: true, id: cir10, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "11", power: { name: "Doorbell",                                                internal: true, id: cir11, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "12", power: { name: "Shutters",                                                internal: true, id: cir12, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "13", power: { name: "Cellar (Dryer, Washer)",                                  internal: true, id: cir13, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "14", power: { name: "Cellar Right, Workshop Play Room, Heating Room",          internal: true, id: cir14, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "15", power: { name: "Outdoors Lights",                                         internal: true, id: cir15, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "16", power: { name: "Cellar Left, Washing Room (Plants Lights, Garage)",       internal: true, id: cir16, filters: [ *moving_avg, *pos ] } }





  - platform: template
    internal: true
    name: "Total Circuits Power"
    lambda: return id(cir1).state + id(cir2).state + id(cir3).state + id(cir4).state + id(cir5).state
      + id(cir6).state + id(cir7).state + id(cir8).state + id(cir9).state + id(cir10).state
      + id(cir11).state + id(cir12).state + id(cir13).state + id(cir14).state + id(cir15).state + id(cir16).state;
    update_interval: 1s
    id: total_power_circuits
    unit_of_measurement: "W"
  - platform: template
    internal: true
    name: "Total Power"
    lambda: return id(phase_a_power).state + id(phase_b_power).state + id(phase_c_power).state;
    update_interval: 1s
    id: total_power
    unit_of_measurement: "W"
  - platform: total_daily_energy
    name: "Total Daily Energy"
    internal: true
    power_id: total_power
    id: total_daily_power
    accuracy_decimals: 0
    min_save_interval: 10s
    unit_of_measurement: "W"
  - { power_id:  cir1, platform: total_daily_energy, accuracy_decimals: 0, internal: true, id: total_daily_power_cir1 }
  - { power_id:  cir2, platform: total_daily_energy, accuracy_decimals: 0, internal: true, id: total_daily_power_cir2 }
  - { power_id:  cir3, platform: total_daily_energy, accuracy_decimals: 0, internal: true, id: total_daily_power_cir3 }
  - { power_id:  cir4, platform: total_daily_energy, accuracy_decimals: 0, internal: true, id: total_daily_power_cir4 }
  - { power_id:  cir5, platform: total_daily_energy, accuracy_decimals: 0, internal: true, id: total_daily_power_cir5 }
  - { power_id:  cir6, platform: total_daily_energy, accuracy_decimals: 0, internal: true, id: total_daily_power_cir6 }
  - { power_id:  cir7, platform: total_daily_energy, accuracy_decimals: 0, internal: true, id: total_daily_power_cir7 }
  - { power_id:  cir8, platform: total_daily_energy, accuracy_decimals: 0, internal: true, id: total_daily_power_cir8 }
  - { power_id:  cir9, platform: total_daily_energy, accuracy_decimals: 0, internal: true, id: total_daily_power_cir9 }
  - { power_id: cir10, platform: total_daily_energy, accuracy_decimals: 0, internal: true, id: total_daily_power_cir10 }
  - { power_id: cir11, platform: total_daily_energy, accuracy_decimals: 0, internal: true, id: total_daily_power_cir11 }
  - { power_id: cir12, platform: total_daily_energy, accuracy_decimals: 0, internal: true, id: total_daily_power_cir12 }
  - { power_id: cir13, platform: total_daily_energy, accuracy_decimals: 0, internal: true, id: total_daily_power_cir13 }
  - { power_id: cir14, platform: total_daily_energy, accuracy_decimals: 0, internal: true, id: total_daily_power_cir14 }
  - { power_id: cir15, platform: total_daily_energy, accuracy_decimals: 0, internal: true, id: total_daily_power_cir15 }
  - { power_id: cir16, platform: total_daily_energy, accuracy_decimals: 0, internal: true, id: total_daily_power_cir16 }

time:
  - platform: sntp
    id: my_time
    timezone: Europe/Berlin
    servers: 
      - 192.168.178.99
      - 0.pool.ntp.org
      - 1.pool.ntp.org
    on_time_sync:
      then:
        - logger.log: "Synchronized system clock"
    on_time:
      - seconds: /10
        then:
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir01_power");
              payload: !lambda |-
                return to_string(id(cir1).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir02_power");
              payload: !lambda |-
                return to_string(id(cir2).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir03_power");
              payload: !lambda |-
                return to_string(id(cir3).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir04_power");
              payload: !lambda |-
                return to_string(id(cir4).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir05_power");
              payload: !lambda |-
                return to_string(id(cir5).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir06_power");
              payload: !lambda |-
                return to_string(id(cir6).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir07_power");
              payload: !lambda |-
                return to_string(id(cir7).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir08_power");
              payload: !lambda |-
                return to_string(id(cir8).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir09_power");
              payload: !lambda |-
                return to_string(id(cir9).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir10_power");
              payload: !lambda |-
                return to_string(id(cir10).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir11_power");
              payload: !lambda |-
                return to_string(id(cir11).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir12_power");
              payload: !lambda |-
                return to_string(id(cir12).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir13_power");
              payload: !lambda |-
                return to_string(id(cir13).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir14_power");
              payload: !lambda |-
                return to_string(id(cir14).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir15_power");
              payload: !lambda |-
                return to_string(id(cir15).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir16_power");
              payload: !lambda |-
                return to_string(id(cir16).state);
          - mqtt.publish:
              topic: "vue2/circuits/total_power_circuits"
              payload: !lambda |-
                return to_string(id(total_power_circuits).state);
          - mqtt.publish:
              topic: "vue2/mains/total/total_power"
              payload: !lambda |-
                return to_string(id(total_power).state);

      - seconds: /10
        then:
          - mqtt.publish:
              topic: "vue2/mains/phase_a_voltage"
              payload: !lambda |-
                return to_string(id(phase_a_voltage).state);
          - mqtt.publish:
              topic: "vue2/mains/phase_b_voltage"
              payload: !lambda |-
                return to_string(id(phase_b_voltage).state);
          - mqtt.publish:
              topic: "vue2/mains/phase_c_voltage"
              payload: !lambda |-
                return to_string(id(phase_c_voltage).state);
          - mqtt.publish:
              topic: "vue2/mains/phase_a_power"
              payload: !lambda |-
                return to_string(id(phase_a_power).state);
          - mqtt.publish:
              topic: "vue2/mains/phase_b_power"
              payload: !lambda |-
                return to_string(id(phase_b_power).state);
          - mqtt.publish:
              topic: "vue2/mains/phase_c_power"
              payload: !lambda |-
                return to_string(id(phase_c_power).state);

      - seconds: 0
        minutes: /5
        then:
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir01_total_daily_power");
              payload: !lambda |-
                return to_string(id(total_daily_power_cir1).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir02_total_daily_power");
              payload: !lambda |-
                return to_string(id(total_daily_power_cir2).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir03_total_daily_power");
              payload: !lambda |-
                return to_string(id(total_daily_power_cir3).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir04_total_daily_power");
              payload: !lambda |-
                return to_string(id(total_daily_power_cir4).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir05_total_daily_power");
              payload: !lambda |-
                return to_string(id(total_daily_power_cir5).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir06_total_daily_power");
              payload: !lambda |-
                return to_string(id(total_daily_power_cir6).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir07_total_daily_power");
              payload: !lambda |-
                return to_string(id(total_daily_power_cir7).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir08_total_daily_power");
              payload: !lambda |-
                return to_string(id(total_daily_power_cir8).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir09_total_daily_power");
              payload: !lambda |-
                return to_string(id(total_daily_power_cir9).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir10_total_daily_power");
              payload: !lambda |-
                return to_string(id(total_daily_power_cir10).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir11_total_daily_power");
              payload: !lambda |-
                return to_string(id(total_daily_power_cir11).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir12_total_daily_power");
              payload: !lambda |-
                return to_string(id(total_daily_power_cir12).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir13_total_daily_power");
              payload: !lambda |-
                return to_string(id(total_daily_power_cir13).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir14_total_daily_power");
              payload: !lambda |-
                return to_string(id(total_daily_power_cir14).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir15_total_daily_power");
              payload: !lambda |-
                return to_string(id(total_daily_power_cir15).state);
          - mqtt.publish:
              topic: !lambda |-
                return std::string("vue2/circuits/cir16_total_daily_power");
              payload: !lambda |-
                return to_string(id(total_daily_power_cir16).state);


      - seconds: 0
        minutes: /5
        then:
          - mqtt.publish:
              topic: "vue2/mains/total/total_daily_power"
              payload: !lambda |-
                return to_string(id(total_daily_power).state);

      - seconds: 0
        minutes: /10
        then:
          - mqtt.publish:
              topic: "vue2/circuits/cir01_name"
              payload: !lambda |-
                return id(cir1).get_name();
          - mqtt.publish:
              topic: "vue2/circuits/cir02_name"
              payload: !lambda |-
                return id(cir2).get_name();
          - mqtt.publish:
              topic: "vue2/circuits/cir03_name"
              payload: !lambda |-
                return id(cir3).get_name();
          - mqtt.publish:
              topic: "vue2/circuits/cir04_name"
              payload: !lambda |-
                return id(cir4).get_name();
          - mqtt.publish:
              topic: "vue2/circuits/cir05_name"
              payload: !lambda |-
                return id(cir5).get_name();
          - mqtt.publish:
              topic: "vue2/circuits/cir06_name"
              payload: !lambda |-
                return id(cir6).get_name();
          - mqtt.publish:
              topic: "vue2/circuits/cir07_name"
              payload: !lambda |-
                return id(cir7).get_name();
          - mqtt.publish:
              topic: "vue2/circuits/cir08_name"
              payload: !lambda |-
                return id(cir8).get_name();
          - mqtt.publish:
              topic: "vue2/circuits/cir09_name"
              payload: !lambda |-
                return id(cir9).get_name();
          - mqtt.publish:
              topic: "vue2/circuits/cir10_name"
              payload: !lambda |-
                return id(cir10).get_name();
          - mqtt.publish:
              topic: "vue2/circuits/cir11_name"
              payload: !lambda |-
                return id(cir11).get_name();
          - mqtt.publish:
              topic: "vue2/circuits/cir12_name"
              payload: !lambda |-
                return id(cir12).get_name();
          - mqtt.publish:
              topic: "vue2/circuits/cir13_name"
              payload: !lambda |-
                return id(cir13).get_name();
          - mqtt.publish:
              topic: "vue2/circuits/cir14_name"
              payload: !lambda |-
                return id(cir14).get_name();
          - mqtt.publish:
              topic: "vue2/circuits/cir15_name"
              payload: !lambda |-
                return id(cir15).get_name();
          - mqtt.publish:
              topic: "vue2/circuits/cir16_name"
              payload: !lambda |-
                return id(cir16).get_name();

Hi. How is your setup working with 3 phase?
Just bought a couple of emporia and noticed the yaml is setup for 2 phase, not 3.

@cangaroo82
Copy link

Good morning
VUE 2 modified with ESPHOME.
same as VUE2.yaml. on home assistant virtual machine works well.
on ihost modified Home assistant returns:

`- Configuring incomplete, errors occurred!
See also "/data/build/vue2-1/.pioenvs/vue2-1/CMakeFiles/CMakeOutput.log".
See also "/data/build/vue2-1/.pioenvs/vue2-1/CMakeFiles/CMakeError.log".

fatal: not a git repository (or any parent up to mount point /)
Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).
CMake Error at /data/cache/platformio/packages/tool-cmake/share/cmake-3.16/Modules/CMakeTestCCompiler.cmake:60 (message):
The C compiler

"/data/cache/platformio/packages/toolchain-xtensa-esp32/bin/xtensa-esp32-elf-gcc"

is not able to compile a simple test program.

It fails with the following output:

Change Dir: /data/build/vue2-1/.pioenvs/vue2-1/CMakeFiles/CMakeTmp

Run Build Command(s):/data/cache/platformio/packages/tool-ninja/ninja cmTC_22cff && [1/2] Building C object CMakeFiles/cmTC_22cff.dir/testCCompiler.c.obj
[2/2] Linking C executable cmTC_22cff
FAILED: cmTC_22cff 
: && /data/cache/platformio/packages/toolchain-xtensa-esp32/bin/xtensa-esp32-elf-gcc -mlongcalls -Wno-frame-address   CMakeFiles/cmTC_22cff.dir/testCCompiler.c.obj  -o cmTC_22cff   && :
/data/cache/platformio/packages/toolchain-xtensa-esp32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: /data/cache/platformio/packages/toolchain-xtensa-esp32/bin/../libexec/gcc/xtensa-esp32-elf/8.4.0/liblto_plugin.so: error loading plugin: /data/cache/platformio/packages/toolchain-xtensa-esp32/bin/../libexec/gcc/xtensa-esp32-elf/8.4.0/liblto_plugin.so: cannot open shared object file: No such file or directory
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.

CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
/data/cache/platformio/packages/framework-espidf/tools/cmake/project.cmake:298 (__project)
CMakeLists.txt:3 (project)

========================= [FAILED] Took 26.35 seconds =========================`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment