Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Setting up Emporia Vue 2 with ESPHome

Setting up Emporia Vue 2 whole-home power monitor with ESPHome

Changelog
  • 2022-07-02: mention mqtt is now supported
  • 2022-04-30: bump software version number to 2022.4.0
  • 2022-05-04: mention 64-bit ARM issues in FAQ

Setting up Emporia Vue 2 with ESPHome

example of hass setup

What you need

Panel installation, part 1

You'll want to install the clamps & wiring harness into your panel following the instructions at https://www.emporiaenergy.com/installation-guides. At this time, place a label on each wire using masking tape & a pen rather than connecting them to the energy monitor.

Next, we need to figure out which circuits are on which phases, and in the case of multi-pole breakers, the multiplier. There should be a label like the following on your panel: panel phase diagram For each clamp, you want to make a note of the following information:

  • clamp number
  • circuit number
  • phase
  • multiplier, if it is a multi-pole breaker

For the wiring harness, you'll want to make a note of which color cable matches which service main clamp (A, B, C).

Writing configuration

Here's a starting point for a configuration:

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": "<ota password>"}

# Enable logging
logger:

wifi:
  ssid: "<wifi ssid>"
  password: "<wifi password>"

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]
      - 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"
          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"
          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"
          id: phase_b_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:  "Circuit 1 Power", id:  cir1, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_b, input:  "2", power: { name:  "Circuit 2 Power", id:  cir2, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "3", power: { name:  "Circuit 3 Power", id:  cir3, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "4", power: { name:  "Circuit 4 Power", id:  cir4, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "5", power: { name:  "Circuit 5 Power", id:  cir5, filters: [ *moving_avg, *pos, multiply: 2 ] } }
      - { phase_id: phase_a, input:  "6", power: { name:  "Circuit 6 Power", id:  cir6, filters: [ *moving_avg, *pos, multiply: 2 ] } }
      - { phase_id: phase_a, input:  "7", power: { name:  "Circuit 7 Power", id:  cir7, filters: [ *moving_avg, *pos, multiply: 2 ] } }
      - { phase_id: phase_b, input:  "8", power: { name:  "Circuit 8 Power", id:  cir8, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_b, input:  "9", power: { name:  "Circuit 9 Power", id:  cir9, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_b, input: "10", power: { name: "Circuit 10 Power", id: cir10, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "11", power: { name: "Circuit 11 Power", id: cir11, filters: [ *moving_avg, *pos, multiply: 2 ] } }
      - { phase_id: phase_a, input: "12", power: { name: "Circuit 12 Power", id: cir12, filters: [ *moving_avg, *pos, multiply: 2 ] } }
      - { phase_id: phase_a, input: "13", power: { name: "Circuit 13 Power", id: cir13, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "14", power: { name: "Circuit 14 Power", id: cir14, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_b, input: "15", power: { name: "Circuit 15 Power", id: cir15, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "16", power: { name: "Circuit 16 Power", id: cir16, filters: [ *moving_avg, *pos ] } }
  - 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"
  - 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:  "Circuit 1 Daily Energy" }
  - { power_id:  cir2, platform: total_daily_energy, accuracy_decimals: 0, name:  "Circuit 2 Daily Energy" }
  - { power_id:  cir3, platform: total_daily_energy, accuracy_decimals: 0, name:  "Circuit 3 Daily Energy" }
  - { power_id:  cir4, platform: total_daily_energy, accuracy_decimals: 0, name:  "Circuit 4 Daily Energy" }
  - { power_id:  cir5, platform: total_daily_energy, accuracy_decimals: 0, name:  "Circuit 5 Daily Energy" }
  - { power_id:  cir6, platform: total_daily_energy, accuracy_decimals: 0, name:  "Circuit 6 Daily Energy" }
  - { power_id:  cir7, platform: total_daily_energy, accuracy_decimals: 0, name:  "Circuit 7 Daily Energy" }
  - { power_id:  cir8, platform: total_daily_energy, accuracy_decimals: 0, name:  "Circuit 8 Daily Energy" }
  - { power_id:  cir9, platform: total_daily_energy, accuracy_decimals: 0, name:  "Circuit 9 Daily Energy" }
  - { power_id: cir10, platform: total_daily_energy, accuracy_decimals: 0, name: "Circuit 10 Daily Energy" }
  - { power_id: cir11, platform: total_daily_energy, accuracy_decimals: 0, name: "Circuit 11 Daily Energy" }
  - { power_id: cir12, platform: total_daily_energy, accuracy_decimals: 0, name: "Circuit 12 Daily Energy" }
  - { power_id: cir13, platform: total_daily_energy, accuracy_decimals: 0, name: "Circuit 13 Daily Energy" }
  - { power_id: cir14, platform: total_daily_energy, accuracy_decimals: 0, name: "Circuit 14 Daily Energy" }
  - { power_id: cir15, platform: total_daily_energy, accuracy_decimals: 0, name: "Circuit 15 Daily Energy" }
  - { power_id: cir16, platform: total_daily_energy, accuracy_decimals: 0, name: "Circuit 16 Daily Energy" }

You'll want to replace <ota password>, <wifi ssid>, and <wifi password> with a unique password, and your wifi credentials, respectively.

You'll also want to update the sensor section of the configuration using the information you've collected in Panel installation, part 1.

Note the sliding_window_moving_average. This is optional, but since we get a reading every 240ms, it is helpful to average these readings together so that we don't need to store such dense, noisy, data in Home Assistant.

Note the "Total Power", "Total Daily Energy", and "Circuit x Daily Energy". This is needed for the Home Assistant energy system, which requires daily kWh numbers.

Do not use the web_server since it is not compatible with the esp-idf framework, and you will get odd error messages.

It's not too critical to get this right on the first try, because you can update the board over WiFi using the ESPHome Dashboard.

Backing up & flashing the Vue 2

Pry the lever on one of the jumper cables up using a pencil or a needle or some other sharp thing. If your cables don't have a lever, cut one end of the cable & strip it using scissors or a knife. prying the lever on the jumper cableseparated cable You will then need to solder a serial header onto the programming port, so that it looks like this:

closeup of the debug header pinout Plug the USB adapter in. Connect RX to RX, TX to TX, and GND to GND. Do not connect 5V or 3.3V at this time.

Plug in the unmodified end of the cable we modified above into the IO0 pin of the Emporia Vue 2.

Open a console window and test that esptool.py version works.

photo of connected jumpers Hold the modified end of the cable in IO0 to the metal shield on the ESP32. While holding it in place, connect 5V on your UART adapter to the VCC_5V0 pin on the board.

Doing a backup

With your other hand, run the following in the console: esptool.py -b 921600 read_flash 0 0x800000 flash_contents.bin. Successful completion of this step is critical in case something goes wrong later. This file is necessary to restore the device to factory function.

If the above command fails, try again using esptool.py -b 115200 read_flash 0 0x800000 flash_contents.bin.

Flashing new software

With your other hand, run the following in the console: esphome run vue2.yaml. This will take a few minutes, and install the new software on the Vue 2!

You'll see a bunch of errors like Failed to read from sensor due to I2C error 3, but that's fine, since they'll go away when it is installed into into the wall.

Panel installation, part 2

Reassemble to Vue 2, and follow the instructions to plug everything in & started up!

FAQ

How do I use this with MQTT?

There's now support for MQTT with this integration thanks to the hard work of the ESPHome folks! Please reference MQTT Client Component for how to get this set up.

I'm getting negative values

  • You may have put that clamp on the wire backwards
  • You may have selected the wrong phase in the configuration

The readings on one or two of my sensors are crazy

Sometimes the CTs aren't fully plugged into the 3.5mm jacks on the Vue. It's often not an issue with the initial install, but with stuff getting jostled around as you put things back together.

This issue will often manifest as jumps between 0W and some other wattage for no reason.

Open up the panel, and make sure every connector is fully inserted into the Vue. Check if the problem is solved before putting the panel cover back on.

My data readings go up and down

If your readings are within ±1W, then they're within the expected margin of error. The filters are designed to smooth out noise like this, and it's expected as no physical system can be perfect.

If the readings are significant outside of that, there may be a problem.

I'm seeing zeros on certain current clamps

First off, you will want to remove all filters for that sensor. Replace filters: [ *moving_avg, *pos ], etc, with filters: [].

If your data is hovering around 0, then you either don't have any load on that circuit or there's some other issue that hasn't come up before.

If you're seeing negative data, it could be a few things:

  • First off, make sure you've properly installed the clamps according to the instructions. The L side of the clamp should point towards the load. For solar systems or similar, keep in mind that current flows from the solar panel to your electrical panel, not the other way.
  • Make sure you've selected the correct phase in the configuration. You will get negative and nonsense power readings if you select the wrong phase. You can't negate the data through a filter and expect it to be correct.

When you're done troubleshooting, remember to place the filters back.

I'm using a 64-bit Pi & can't compile!

If you're using a 64-bit ARM OS, unfortunately you are unable to build this. It's not a limitation with this project, but a limitation with the upstream PlatformIO toolchains.

You'll see an error like

Could not find the package with 'platformio/toolchain-esp32ulp @ ~1.22851.0' requirements for your system 'linux_aarch64'

You can try using a different computer. 32-bit and 64-bit x86 computers are both compatible (most laptops & desktops).


(c) 2021 Flaviu Tamas

Licensed under CC-BY-4.0

@poblabs
Copy link

poblabs commented Jun 18, 2022

How do I set the timezone correctly? When choosing the homeassistant time platform, I get errors that sntp is required. When I add an addition time reference for homeassistant platform, I get undefined reference errors, and when I try this config below, It doesn't appear to be applying.

time:
  - platform: sntp
    timezone: UTC-5
    id: my_time

Also trying America/New_York doesn't appear to be working either. The logs still show UTC.

I use the following with HomeAssistant

time:
  - platform: homeassistant
    id: homeassistant_time

When I try that, I get this error below:

Compiling .pioenvs/emporiavue2/src/esphome/components/sensor/sensor.o
*** [.pioenvs/emporiavue2/src/esphome/components/sntp/sntp_component.o] Source `src/esphome/components/sntp/sntp_component.cpp' not found, needed by target `.pioenvs/emporiavue2/src/esphome/components/sntp/sntp_component.o'.
========================== [FAILED] Took 8.69 seconds ==========================

@ripvega
Copy link

ripvega commented Jun 19, 2022

I had this issue too, and seem to remember that the compilation framework used doesn't support homeassistant time, only SNTP, whereas the arduino framework does. I think we're stuck with SNTP.

@poblabs
Copy link

poblabs commented Jun 19, 2022

I had this issue too, and seem to remember that the compilation framework used doesn't support homeassistant time, only SNTP, whereas the arduino framework does. I think we're stuck with SNTP.

Were you able to get timezone working?

@ripvega
Copy link

ripvega commented Jun 19, 2022

I didn't play with the timezone as ESPHome automatically picks it from the device running ESPHome. At least, it has for me.

@VivantSenior
Copy link

VivantSenior commented Jun 20, 2022

How do I set the timezone correctly? When choosing the homeassistant time platform, I get errors that sntp is required. When I add an addition time reference for homeassistant platform, I get undefined reference errors, and when I try this config below, It doesn't appear to be applying.

time:
  - platform: sntp
    timezone: UTC-5
    id: my_time

Also trying America/New_York doesn't appear to be working either. The logs still show UTC.

Have you tried to do:

esphome clean emporia.yaml

I found cleaning helpful when was unable to add wifi sensor to the configuration.

BTW I have noticed that sensors are super noisy:
image

Close look:
image

This one is not event connencted to the Emporia yet. I'm thinking about moving to the median to smooth out the output - maybe it will be less sensitive to the measurement outliers.

Do you have the same issue guys?

@poblabs
Copy link

poblabs commented Jun 20, 2022

How do I set the timezone correctly? When choosing the homeassistant time platform, I get errors that sntp is required. When I add an addition time reference for homeassistant platform, I get undefined reference errors, and when I try this config below, It doesn't appear to be applying.

time:
  - platform: sntp
    timezone: UTC-5
    id: my_time

Also trying America/New_York doesn't appear to be working either. The logs still show UTC.

Have you tried to do:

esphome clean emporia.yaml

I found cleaning helpful when was unable to add wifi sensor to the configuration.

BTW I have noticed that sensors are super noisy: image

Close look: image

This one is not event connencted to the Emporia yet. I'm thinking about moving to the median to smooth out the output - maybe it will be less sensitive to the measurement outliers.

Do you have the same issue guys?

I do have 1 sensor that keeps flapping like this. I've moved it to another position but same results so I think that must be a noisy area in the panel? How would you implement the median?

@flaviut
Copy link
Author

flaviut commented Jun 20, 2022

@poblabs @VivantSenior that behavior isn't normal at all--none of my sensors do that.

How about the following? And let me know if it worked and which step solved things.

  • move the problematic sensor to a different port (@poblabs sounds like you've already tried this!)
  • unclamp the problematic clamp, maybe shake it around a bit and use gentle percussive maintenance, and re-clamp it
  • use a different clamp for that sensor

@poblabs
Copy link

poblabs commented Jun 20, 2022

@poblabs @VivantSenior that behavior isn't normal at all--none of my sensors do that.

How about the following? And let me know if it worked and which step solved things.

  • move the problematic sensor to a different port (@poblabs sounds like you've already tried this!)
  • unclamp the problematic clamp, maybe shake it around a bit and use gentle percussive maintenance, and re-clamp it
  • use a different clamp for that sensor

I'll try another clamp to see if that helps.

Any thoughts on the time? I'm trying something like the below, but I'm not seeing anything in the log with my "POB" lines, and the logs time is still in UTC.

I'd like to have the right timezone that way the "Total Daily Energy" is right in my timezone and doesn't reset at UTC

time:
  - platform: homeassistant
    timezone: America/New_York
    id: ha_time
    on_time_sync:
      if:
        condition:
          time.has_time:
        then:
          - logger.log: POB POB POB POB Time has been set and is valid!

@flaviut
Copy link
Author

flaviut commented Jun 20, 2022

@poblabs re. the time, I don't know.

I live in America/New_York too, my config is

time:
  - platform: sntp
    id: my_time

and everything works perfectly:

2022-06-20-102634_375x299_scrot

Only idea I have here is that maybe you have a router firewall blocking outbound UDP connections on port 123. I don't know anything about the homeassistant time platform. You can try asking the esphome community.

@poblabs
Copy link

poblabs commented Jun 20, 2022

@poblabs re. the time, I don't know.

I live in America/New_York too, my config is

time:
  - platform: sntp
    id: my_time

and everything works perfectly:

2022-06-20-102634_375x299_scrot

Only idea I have here is that maybe you have a router firewall blocking outbound UDP connections on port 123. I don't know anything about the homeassistant time platform. You can try asking the esphome community.

Just curious then - are your esphome logs in UTC with sntp set? Also does your daily power reset at 8pm or midnight? Looks like midnight on that chart

@flaviut
Copy link
Author

flaviut commented Jun 20, 2022

@poblabs

Logs are in local time:

[10:50:35][D][sensor:125]: 'Circuit 8 Daily Energy': Sending state 180.83740 Wh with 0 decimals of accuracy
[10:50:35][D][sensor:125]: 'Circuit 9 Power': Sending state 0.25883 W with 0 decimals of accuracy
[10:50:35][D][sensor:125]: 'Circuit 9 Daily Energy': Sending state 4.03635 Wh with 0 decimals of accuracy
[10:50:35][D][sensor:125]: 'Circuit 10 Power': Sending state 12.47641 W with 0 decimals of accuracy

And the daily reset happens at midnight.

@poblabs
Copy link

poblabs commented Jun 20, 2022

@poblabs

Logs are in local time:

[10:50:35][D][sensor:125]: 'Circuit 8 Daily Energy': Sending state 180.83740 Wh with 0 decimals of accuracy
[10:50:35][D][sensor:125]: 'Circuit 9 Power': Sending state 0.25883 W with 0 decimals of accuracy
[10:50:35][D][sensor:125]: 'Circuit 9 Daily Energy': Sending state 4.03635 Wh with 0 decimals of accuracy
[10:50:35][D][sensor:125]: 'Circuit 10 Power': Sending state 12.47641 W with 0 decimals of accuracy

And the daily reset happens at midnight.

Thanks for confirming, and thanks for all your work with this! I'll have to dig in deeper outside of the emporia firmware 😄

@poblabs
Copy link

poblabs commented Jun 20, 2022

EDIT I've figured it out. I'm running esphome in Docker, and I need to pass the timezone through to the container using environment variables.

Thanks to this link for the insight

example:

    volumes:
      - "./data:/config"
      - /etc/localtime:/etc/localtime
      - /etc/timezone:/etc/timezone

@VivantSenior
Copy link

VivantSenior commented Jun 21, 2022

I think I've figured it out also ;-) My issue what that even when sensor wasn't connected to the port the output was like random noise. When I connected the clamp it looks good:
image

Missing data at 16:06 and later it's my Emporia dropping from the wifi.

@flaviut, is there a smart way to do in ESPHome a sensor that will calculate power from the other circuts not measured by Emporia (by phase)? Something like this:

phase_a_other_circuts_power = id(phase_a_power).state - sum(all measured circurs on phase a)

and the same for daily energy.

@flaviut
Copy link
Author

flaviut commented Jun 21, 2022

@VivantSenior glad to hear you figured it out!

Re. doing math on results, copy "Total Power" in the config and try and modify it for your situation.

@cshields
Copy link

cshields commented Jun 22, 2022

First, thanks for this! Truly epic.

Have you heard of an issue where half of the CTs/ports go dead at the same time after working fine for days? I'm pretty sure something went belly up in the hardware but figure I'd ask. At first I thought it must be a fried multiplexer, but the bad ports span both of them.

@flaviut
Copy link
Author

flaviut commented Jun 22, 2022

@cshields all on the same phase? Check the wiring on the 2x2 connector: that all the wire nuts are tight, screws tight, and connector completely inserted.

@Ofloo
Copy link

Ofloo commented Jun 25, 2022

energy monitor keeps disconnecting, ..

INFO energy-monitor.local: Error while reading incoming messages: Error while reading data: 0 bytes read on a total of 1 expected bytes
INFO Disconnected from ESPHome API for energy-monitor.local
WARNING Disconnected from API
INFO energy-monitor.local: Ping Failed: Error while reading data: 0 bytes read on a total of 1 expected bytes
INFO Successfully connected to energy-monitor.local

Configuration:

Config
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
  webserver_username: !secret webserver_username
  webserver_password: !secret webserver_password

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:

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

i2c:
  sda: 21
  scl: 22
  scan: false
  frequency: 200kHz  # recommended range is 50-200kHz
  id: i2c_a
  
time:
  - platform: sntp
    timezone: 'CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00'
    id: my_time
    servers: 
      - 162.159.200.123
      - 195.13.23.5
      - 195.13.1.153
    on_time_sync:
      then:
        - logger.log: "Synchronized system clock"

# 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.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: "Grid 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: "Neutral 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: "PE 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: "Grid Power"
          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: "Neutral Power"
          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: "PE Power"
          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:  "Circuit 1 Power", id:  cir1, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "2", power: { name:  "Circuit 2 Power", id:  cir2, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "3", power: { name:  "Circuit 3 Power", id:  cir3, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "4", power: { name:  "Circuit 4 Power", id:  cir4, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "5", power: { name:  "Circuit 5 Power", id:  cir5, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "6", power: { name:  "Circuit 6 Power", id:  cir6, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "7", power: { name:  "Circuit 7 Power", id:  cir7, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "8", power: { name:  "Circuit 8 Power", id:  cir8, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input:  "9", power: { name:  "Circuit 9 Power", id:  cir9, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "10", power: { name: "Circuit 10 Power", id: cir10, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "11", power: { name: "Circuit 11 Power", id: cir11, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "12", power: { name: "Circuit 12 Power", id: cir12, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "13", power: { name: "Circuit 13 Power", id: cir13, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "14", power: { name: "Circuit 14 Power", id: cir14, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "15", power: { name: "Circuit 15 Power", id: cir15, filters: [ *moving_avg, *pos ] } }
      - { phase_id: phase_a, input: "16", power: { name: "Circuit 16 Power", id: cir16, filters: [ *moving_avg, *pos ] } }
  # phase A L1
  - platform: template
    name: "Total Power Grid"
    lambda: return id(phase_a_power).state;
    update_interval: 1s
    id: total_power_a
    unit_of_measurement: "W"
  - platform: total_daily_energy
    name: "Total Daily Energy Grid"
    power_id: total_power_a
    accuracy_decimals: 0
  # phase B Neutral
  - platform: template
    name: "Total Power Neutral"
    lambda: return id(phase_b_power).state;
    update_interval: 5s
    id: total_power_b
    unit_of_measurement: "W"
  - platform: total_daily_energy
    name: "Total Daily Energy Neutral"
    power_id: total_power_b
    accuracy_decimals: 0
  # phase C to Earth
  - platform: template
    name: "Total Power PE"
    lambda: return id(phase_c_power).state;
    update_interval: 5s
    id: total_power_c
    unit_of_measurement: "W"
  - platform: total_daily_energy
    name: "Total Daily Energy PE"
    power_id: total_power_c
    accuracy_decimals: 0

  - { power_id:  cir1, platform: total_daily_energy, accuracy_decimals: 0, name:  "Circuit 1 Daily Energy" }
  - { power_id:  cir2, platform: total_daily_energy, accuracy_decimals: 0, name:  "Circuit 2 Daily Energy" }
  - { power_id:  cir3, platform: total_daily_energy, accuracy_decimals: 0, name:  "Circuit 3 Daily Energy" }
  - { power_id:  cir4, platform: total_daily_energy, accuracy_decimals: 0, name:  "Circuit 4 Daily Energy" }
  - { power_id:  cir5, platform: total_daily_energy, accuracy_decimals: 0, name:  "Circuit 5 Daily Energy" }
  - { power_id:  cir6, platform: total_daily_energy, accuracy_decimals: 0, name:  "Circuit 6 Daily Energy" }
  - { power_id:  cir7, platform: total_daily_energy, accuracy_decimals: 0, name:  "Circuit 7 Daily Energy" }
  - { power_id:  cir8, platform: total_daily_energy, accuracy_decimals: 0, name:  "Circuit 8 Daily Energy" }
  - { power_id:  cir9, platform: total_daily_energy, accuracy_decimals: 0, name:  "Circuit 9 Daily Energy" }
  - { power_id: cir10, platform: total_daily_energy, accuracy_decimals: 0, name: "Circuit 10 Daily Energy" }
  - { power_id: cir11, platform: total_daily_energy, accuracy_decimals: 0, name: "Circuit 11 Daily Energy" }
  - { power_id: cir12, platform: total_daily_energy, accuracy_decimals: 0, name: "Circuit 12 Daily Energy" }
  - { power_id: cir13, platform: total_daily_energy, accuracy_decimals: 0, name: "Circuit 13 Daily Energy" }
  - { power_id: cir14, platform: total_daily_energy, accuracy_decimals: 0, name: "Circuit 14 Daily Energy" }
  - { power_id: cir15, platform: total_daily_energy, accuracy_decimals: 0, name: "Circuit 15 Daily Energy" }
  - { power_id: cir16, platform: total_daily_energy, accuracy_decimals: 0, name: "Circuit 16 Daily Energy" }

@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

@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

tappyson commented Jun 29, 2022

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

maegibbons commented Jun 29, 2022

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

tappyson commented Jun 29, 2022

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.

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