Skip to content

Instantly share code, notes, and snippets.

@thimslugga
Forked from bradsjm/emporia-vue-v3.yaml
Created November 11, 2024 12:54
Show Gist options
  • Save thimslugga/b9682c9f78a95238c564ec6795962f58 to your computer and use it in GitHub Desktop.
Save thimslugga/b9682c9f78a95238c564ec6795962f58 to your computer and use it in GitHub Desktop.
Emporia VUE V3 ESPHome Configuration
substitutions:
name: emporia-vue-v3
friendly_name: Emporia Vue V3
area: "Garage"
# Circuit Labels used for publishing to Home Assistant
circuit_1: "Dryer" #"Circuit 1"
circuit_2: "AC Blower/Heat" #"Circuit 2"
circuit_3: "AC Condenser" #"Circuit 3"
circuit_4: "Water Heater" #"Circuit 4"
circuit_5: "Master Bedroom Lights" #"Circuit 5"
circuit_6: "Master Bedroom Outlets" #"Circuit 6"
circuit_7: "Guest Room/Office" #"Circuit 7"
circuit_8: "Garage Rear" #"Circuit 8"
circuit_9: "Circuit 9"
circuit_10: "Circuit 10"
circuit_11: "Circuit 11"
circuit_12: "Circuit 12"
circuit_13: "Circuit 13"
circuit_14: "Circuit 14"
circuit_15: "Circuit 15"
circuit_16: "Circuit 16"
# Icons for Home Assistant
icon_circuit: "mdi:power-plug"
icon_current: "mdi:current-ac"
icon_meter: "mdi:meter-electric"
icon_phase: "mdi:angle-acute"
icon_power: "mdi:transmission-tower-import"
icon_voltage: "mdi:transmission-tower"
# Use Ethernet or WiFi on the Emporia Vue V3 (you can only include one)
wifi:
ap: # Enable access point mode for the captive portal
ssid: !secret wifi_ssid
password: !secret wifi_password
on_connect:
- light.turn_on: wifi_led
on_disconnect:
- light.turn_off: wifi_led
# ethernet:
# type: RTL8201
# mdc_pin: GPIO32
# mdio_pin: GPIO33
# clk_mode: GPIO0_IN
# on_connect:
# - light.turn_on: ethernet_led
# on_disconnect:
# - light.turn_off: ethernet_led
# Define filters to be used in circuit sensors.
.defaultfilters:
- &throttle_avg # Average all raw readings together over a 5 second span before publishing
throttle_average: 5s
- &throttle_time # Only send the most recent measurement every 60 seconds
throttle: 60s
- &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);"
- &zero # Use for disconnected circuits to return 0
lambda: "return 0.0f;"
- &double # Use to double the measurement for 240V breakers
multiply: 2
# Define the sensors to be exposed to Home Assistant.
sensor:
- platform: emporia_vue
i2c_id: i2c_a
# Configure the Emporia Vue wire harness phases.
phases:
# Verify that this specific phase/leg is connected to the matching input wire color on device listed below
- id: phase_a
# Vue device wire color (BLACK or RED for split phase)
input: BLACK
# To calculate new calibration value use the formula <in-use calibration value> * <accurate voltage> / <reporting voltage>
# 0.0194 is used as the default as starting point for Vue 3 but may need adjusted to ensure accuracy
calibration: 0.0194
voltage: { id: phase_a_voltage, name: "Phase A Voltage", icon: $icon_voltage, accuracy_decimals: 0, filters: [ *throttle_avg, *pos ] }
frequency: { id: phase_a_freqency, name: "Phase A Frequency", accuracy_decimals: 0, filters: [ *throttle_avg, *pos ] }
# Verify that this specific phase/leg is connected to the matching input wire color on device listed below
- id: phase_b
# Vue device wire color (BLACK or RED for split phase)
input: RED
# To calculate new calibration value use the formula <in-use calibration value> * <accurate voltage> / <reporting voltage>
# 0.0194 is used as the default as starting point for Vue 3 but may need adjusted to ensure accuracy
calibration: 0.0194
voltage: { id: phase_b_voltage, name: "Phase B Voltage", icon: $icon_voltage, accuracy_decimals: 0, filters: [ *throttle_avg, *pos ] }
phase_angle: { id: phase_b_angle, name: "Phase B Phase Angle", icon: $icon_phase, accuracy_decimals: 0, filters: [ *throttle_avg, *pos ] }
# Verify that this specific phase/leg is connected to the matching input wire color on device listed below
# - id: phase_c
# # Vue device wire color (BLUE for three phase)
# input: BLUE
# # To calculate new calibration value use the formula <in-use calibration value> * <accurate voltage> / <reporting voltage>
# # 0.0194 is used as the default as starting point for Vue 3 but may need adjusted to ensure accuracy
# calibration: 0.0194
# voltage: { id: phase_c_voltage, name: "Phase C Voltage", icon: $icon_voltage, accuracy_decimals: 0, filters: [ *throttle_avg, *pos ] }
# phase_angle: { id: phase_c_angle, name: "Phase C Phase Angle", icon: $icon_phase, accuracy_decimals: 0, filters: [ *throttle_avg, *pos ] }
# Configure the Emporia Vue CT clamps.
ct_clamps:
# Do not specify a name for any of the power sensors here, only an id. This leaves the power sensors internal to ESPHome.
# These non-throttled power sensors are used for accurately calculating energy.
# Copy sensors defined later will filter and then send power measurements to Home Assistant.
# Main Service CT Clamps (up to 3)
# Verify the correct input on the device is connected to the CT clamp phase defined (Vue 3 inputs are inverted)
- { input: "A", phase_id: phase_a, power: { id: phase_a_power, filters: *invert } }
- { input: "B", phase_id: phase_b, power: { id: phase_b_power, filters: *invert } }
# - { input: "C", phase_id: phase_c, power: { id: phase_c_power, filters: *invert } }
# Circuit CT Clamps (up to 16)
# Pay close attention to set the phase_id for each breaker by matching it to the phase/leg it connects to in the panel
# Use *abs filter to always take the positive absolute value
# Use *invert filter for inverted positive values (Vue 3 inputs are inverted) or *zero for un-used inputs
# Use *double filter for double (240v) breakers (this will assume power is evenly divided between the two legs)
- { input: "1", phase_id: phase_a, power: { id: c1_pwr, filters: [ *abs, *double ] }, current: { id: c1_cur, filters: [ *double ] } }
- { input: "2", phase_id: phase_a, power: { id: c2_pwr, filters: [ *abs, *double ] }, current: { id: c2_cur, filters: [ *double ] } }
- { input: "3", phase_id: phase_a, power: { id: c3_pwr, filters: [ *abs, *double ] }, current: { id: c3_cur, filters: [ *double ] } }
- { input: "4", phase_id: phase_a, power: { id: c4_pwr, filters: [ *abs, *double ] }, current: { id: c4_cur, filters: [ *double ] } }
- { input: "5", phase_id: phase_b, power: { id: c5_pwr, filters: [ *abs ] }, current: { id: c5_cur } }
- { input: "6", phase_id: phase_a, power: { id: c6_pwr, filters: [ *abs ] }, current: { id: c6_cur } }
- { input: "7", phase_id: phase_b, power: { id: c7_pwr, filters: [ *abs ] }, current: { id: c7_cur } }
- { input: "8", phase_id: phase_b, power: { id: c8_pwr, filters: [ *abs ] }, current: { id: c8_cur } }
# Unused CT clamp inputs are explicitly set to zero (*zero filter) to avoid phantom readings
- { input: "9", phase_id: phase_a, power: { id: c9_pwr, filters: [ *zero ] }, current: { id: c9_cur, filters: [ *zero ] } }
- { input: "10", phase_id: phase_a, power: { id: c10_pwr, filters: [ *zero ] }, current: { id: c10_cur, filters: [ *zero ] } }
- { input: "11", phase_id: phase_a, power: { id: c11_pwr, filters: [ *zero ] }, current: { id: c11_cur, filters: [ *zero ] } }
- { input: "12", phase_id: phase_a, power: { id: c12_pwr, filters: [ *zero ] }, current: { id: c12_cur, filters: [ *zero ] } }
- { input: "13", phase_id: phase_a, power: { id: c13_pwr, filters: [ *zero ] }, current: { id: c13_cur, filters: [ *zero ] } }
- { input: "14", phase_id: phase_a, power: { id: c14_pwr, filters: [ *zero ] }, current: { id: c14_cur, filters: [ *zero ] } }
- { input: "15", phase_id: phase_a, power: { id: c15_pwr, filters: [ *zero ] }, current: { id: c15_cur, filters: [ *zero ] } }
- { input: "16", phase_id: phase_a, power: { id: c16_pwr, filters: [ *zero ] }, current: { id: c16_cur, filters: [ *zero ] } }
# Update total power and balance power readings at the same time.
on_update:
then:
- component.update: total_power
- component.update: balance_power
# The total power sensor will be updated after all power sensors update via on_update trigger.
- platform: template
id: total_power
update_interval: never
device_class: power
state_class: measurement
unit_of_measurement: "W"
lambda: return id(phase_a_power).state + id(phase_b_power).state;
#lambda: return id(phase_a_power).state + id(phase_b_power).state + id(phase_c_power).state;
# The balance power sensor will be updated after all power sensors update via on_update trigger.
- platform: template
id: balance_power
update_interval: never
device_class: power
state_class: measurement
unit_of_measurement: "W"
lambda: !lambda |-
return max(0.0f, id(total_power).state
- id( c1_pwr).state
- id( c2_pwr).state
- id( c3_pwr).state
- id( c4_pwr).state
- id( c5_pwr).state
- id( c6_pwr).state
- id( c7_pwr).state
- id( c8_pwr).state
- id( c9_pwr).state
- id(c10_pwr).state
- id(c11_pwr).state
- id(c12_pwr).state
- id(c13_pwr).state
- id(c14_pwr).state
- id(c15_pwr).state
- id(c16_pwr).state
);
- platform: wifi_signal
name: "RSSI"
update_interval: 60s
disabled_by_default: true
# The copy sensors publish the each power state to Home Assistant.
- { platform: copy, name: "Phase A Power", source_id: phase_a_power, filters: *throttle_avg, accuracy_decimals: 0, icon: $icon_power }
- { platform: copy, name: "Phase B Power", source_id: phase_b_power, filters: *throttle_avg, accuracy_decimals: 0, icon: $icon_power }
- { platform: copy, name: "Total Power", source_id: total_power, filters: *throttle_avg, accuracy_decimals: 0, icon: $icon_power }
- { platform: copy, name: "Balance Power", source_id: balance_power, filters: *throttle_avg, accuracy_decimals: 0, icon: $icon_power }
- { platform: copy, name: "${circuit_1} Power", source_id: c1_pwr, filters: *throttle_avg, accuracy_decimals: 0, icon: $icon_circuit }
- { platform: copy, name: "${circuit_2} Power", source_id: c2_pwr, filters: *throttle_avg, accuracy_decimals: 0, icon: $icon_circuit }
- { platform: copy, name: "${circuit_3} Power", source_id: c3_pwr, filters: *throttle_avg, accuracy_decimals: 0, icon: $icon_circuit }
- { platform: copy, name: "${circuit_4} Power", source_id: c4_pwr, filters: *throttle_avg, accuracy_decimals: 0, icon: $icon_circuit }
- { platform: copy, name: "${circuit_5} Power", source_id: c5_pwr, filters: *throttle_avg, accuracy_decimals: 0, icon: $icon_circuit }
- { platform: copy, name: "${circuit_6} Power", source_id: c6_pwr, filters: *throttle_avg, accuracy_decimals: 0, icon: $icon_circuit }
- { platform: copy, name: "${circuit_7} Power", source_id: c7_pwr, filters: *throttle_avg, accuracy_decimals: 0, icon: $icon_circuit }
- { platform: copy, name: "${circuit_8} Power", source_id: c8_pwr, filters: *throttle_avg, accuracy_decimals: 0, icon: $icon_circuit }
# - { platform: copy, name: "${circuit_9} Power", source_id: cir9_pwr, filters: *throttle_avg, accuracy_decimals: 0, icon: $icon_circuit }
# - { platform: copy, name: "${circuit_10} Power", source_id: cir10_pwr, filters: *throttle_avg, accuracy_decimals: 0, icon: $icon_circuit }
# - { platform: copy, name: "${circuit_11} Power", source_id: cir11_pwr, filters: *throttle_avg, accuracy_decimals: 0, icon: $icon_circuit }
# - { platform: copy, name: "${circuit_12} Power", source_id: cir12_pwr, filters: *throttle_avg, accuracy_decimals: 0, icon: $icon_circuit }
# - { platform: copy, name: "${circuit_13} Power", source_id: cir13_pwr, filters: *throttle_avg, accuracy_decimals: 0, icon: $icon_circuit }
# - { platform: copy, name: "${circuit_14} Power", source_id: cir14_pwr, filters: *throttle_avg, accuracy_decimals: 0, icon: $icon_circuit }
# - { platform: copy, name: "${circuit_15} Power", source_id: cir15_pwr, filters: *throttle_avg, accuracy_decimals: 0, icon: $icon_circuit }
# - { platform: copy, name: "${circuit_16} Power", source_id: cir16_pwr, filters: *throttle_avg, accuracy_decimals: 0, icon: $icon_circuit }
- { platform: copy, name: "${circuit_1} Current", source_id: c1_cur, filters: *throttle_avg, accuracy_decimals: 1, icon: $icon_current }
- { platform: copy, name: "${circuit_2} Current", source_id: c2_cur, filters: *throttle_avg, accuracy_decimals: 1, icon: $icon_current }
- { platform: copy, name: "${circuit_3} Current", source_id: c3_cur, filters: *throttle_avg, accuracy_decimals: 1, icon: $icon_current }
- { platform: copy, name: "${circuit_4} Current", source_id: c4_cur, filters: *throttle_avg, accuracy_decimals: 1, icon: $icon_current }
- { platform: copy, name: "${circuit_5} Current", source_id: c5_cur, filters: *throttle_avg, accuracy_decimals: 1, icon: $icon_current }
- { platform: copy, name: "${circuit_6} Current", source_id: c6_cur, filters: *throttle_avg, accuracy_decimals: 1, icon: $icon_current }
- { platform: copy, name: "${circuit_7} Current", source_id: c7_cur, filters: *throttle_avg, accuracy_decimals: 1, icon: $icon_current }
- { platform: copy, name: "${circuit_8} Current", source_id: c8_cur, filters: *throttle_avg, accuracy_decimals: 1, icon: $icon_current }
# - { platform: copy, name: "${circuit_9} Current", source_id: c9_cur, filters: *throttle_avg, accuracy_decimals: 1, icon: $icon_current }
# - { platform: copy, name: "${circuit_10} Current", source_id: c10_cur, filters: *throttle_avg, accuracy_decimals: 1, icon: $icon_current }
# - { platform: copy, name: "${circuit_11} Current", source_id: c11_cur, filters: *throttle_avg, accuracy_decimals: 1, icon: $icon_current }
# - { platform: copy, name: "${circuit_12} Current", source_id: c12_cur, filters: *throttle_avg, accuracy_decimals: 1, icon: $icon_current }
# - { platform: copy, name: "${circuit_13} Current", source_id: c13_cur, filters: *throttle_avg, accuracy_decimals: 1, icon: $icon_current }
# - { platform: copy, name: "${circuit_14} Current", source_id: c14_cur, filters: *throttle_avg, accuracy_decimals: 1, icon: $icon_current }
# - { platform: copy, name: "${circuit_15} Current", source_id: c15_cur, filters: *throttle_avg, accuracy_decimals: 1, icon: $icon_current }
# - { platform: copy, name: "${circuit_16} Current", source_id: c16_cur, filters: *throttle_avg, accuracy_decimals: 1, icon: $icon_current }
# The total daily energy sensors to be published to Home Assistant
- { platform: total_daily_energy, name: "Total Daily Energy", power_id: total_power, filters: *throttle_time, accuracy_decimals: 0, restore: false, icon: $icon_meter }
- { platform: total_daily_energy, name: "Balance Daily Energy", power_id: balance_power, filters: *throttle_time, accuracy_decimals: 0, restore: false, icon: $icon_meter }
- { platform: total_daily_energy, name: "${circuit_1} Daily Energy", power_id: c1_pwr, filters: *throttle_time, accuracy_decimals: 0, restore: false, icon: $icon_meter }
- { platform: total_daily_energy, name: "${circuit_2} Daily Energy", power_id: c2_pwr, filters: *throttle_time, accuracy_decimals: 0, restore: false, icon: $icon_meter }
- { platform: total_daily_energy, name: "${circuit_3} Daily Energy", power_id: c3_pwr, filters: *throttle_time, accuracy_decimals: 0, restore: false, icon: $icon_meter }
- { platform: total_daily_energy, name: "${circuit_4} Daily Energy", power_id: c4_pwr, filters: *throttle_time, accuracy_decimals: 0, restore: false, icon: $icon_meter }
- { platform: total_daily_energy, name: "${circuit_5} Daily Energy", power_id: c5_pwr, filters: *throttle_time, accuracy_decimals: 0, restore: false, icon: $icon_meter }
- { platform: total_daily_energy, name: "${circuit_6} Daily Energy", power_id: c6_pwr, filters: *throttle_time, accuracy_decimals: 0, restore: false, icon: $icon_meter }
- { platform: total_daily_energy, name: "${circuit_7} Daily Energy", power_id: c7_pwr, filters: *throttle_time, accuracy_decimals: 0, restore: false, icon: $icon_meter }
- { platform: total_daily_energy, name: "${circuit_8} Daily Energy", power_id: c8_pwr, filters: *throttle_time, accuracy_decimals: 0, restore: false, icon: $icon_meter }
# - { platform: total_daily_energy, name: "${circuit_9} Daily Energy", power_id: c9_pwr, filters: *throttle_time, accuracy_decimals: 0, restore: false, icon: $icon_meter }
# - { platform: total_daily_energy, name: "${circuit_10} Daily Energy", power_id: c10_pwr, filters: *throttle_time, accuracy_decimals: 0, restore: false, icon: $icon_meter }
# - { platform: total_daily_energy, name: "${circuit_11} Daily Energy", power_id: c11_pwr, filters: *throttle_time, accuracy_decimals: 0, restore: false, icon: $icon_meter }
# - { platform: total_daily_energy, name: "${circuit_12} Daily Energy", power_id: c12_pwr, filters: *throttle_time, accuracy_decimals: 0, restore: false, icon: $icon_meter }
# - { platform: total_daily_energy, name: "${circuit_13} Daily Energy", power_id: c13_pwr, filters: *throttle_time, accuracy_decimals: 0, restore: false, icon: $icon_meter }
# - { platform: total_daily_energy, name: "${circuit_14} Daily Energy", power_id: c14_pwr, filters: *throttle_time, accuracy_decimals: 0, restore: false, icon: $icon_meter }
# - { platform: total_daily_energy, name: "${circuit_15} Daily Energy", power_id: c15_pwr, filters: *throttle_time, accuracy_decimals: 0, restore: false, icon: $icon_meter }
# - { platform: total_daily_energy, name: "${circuit_16} Daily Energy", power_id: c16_pwr, filters: *throttle_time, accuracy_decimals: 0, restore: false, icon: $icon_meter }
# Core ESPHome Node Configuration.
esphome:
name: ${name}
area: ${area}
friendly_name: ${friendly_name}
name_add_mac_suffix: false
# Import the emporia-vue-local v3 community component.
external_components:
- source: github://emporia-vue-local/esphome@vue3
components:
- emporia_vue
# Set ESPHome preferences.
preferences:
flash_write_interval: "48h" # The default of 1min is too short (flash chip is rated for approx 100k writes)
# The logger component automatically logs all log messages
logger:
baud_rate: 0 # Disable the hardware UART logging
level: INFO # Minimum log level
logs:
component: ERROR # Silence warnings about execution/blocking time
# Sets up the I²C bus used to communicate with the Emporia Vue hardware.
i2c:
id: i2c_a
sda:
number: 5
ignore_strapping_warning: true
scl: 18
frequency: 200kHz
scan: false
# The Emporia Vue V3 uses an ESP32 board.
esp32:
board: esp32dev
framework:
type: esp-idf
version: recommended
# Configure the two status LEDs on the Emporia Vue v3 case.
light:
- platform: status_led
id: wifi_led
pin:
number: 2
ignore_strapping_warning: true
restore_mode: ALWAYS_OFF
- platform: status_led
id: ethernet_led
pin: 4
restore_mode: ALWAYS_OFF
# The restart button platform allows you to restart your node remotely through Home Assistant.
button:
- platform: restart
name: Restart
id: restart_button
icon: mdi:restart
- platform: safe_mode
name: Restart (Safe Mode)
id: safe_mode_button
icon: mdi:restart-alert
# The preferred way to get time in ESPHome is using Home Assistant. This is used for the daily energy use calculation.
time:
- platform: homeassistant
# The ESPHome native API is used to communicate with Home Assistant directly.
api:
# The OTA (Over The Air) enables uploading firmware binaries to your node without having to use a USB cable for uploads.
ota:
platform: esphome
on_error:
then:
- button.press: safe_mode_button
# The web_server component creates a simple web server on the node that can be accessed through any browser and a simple REST API.
# This is not required for Home Assistant and can be commented out to reduce memory and processor utilization.
web_server:
# The captive portal component in ESPHome is a fallback mechanism used when connecting to WiFi fails.
captive_portal:
# Provide diagnostic information about the platform.
text_sensor:
- platform: wifi_info
ip_address:
name: "IP Address"
ssid:
name: "Connected SSID"
disabled_by_default: true
mac_address:
name: "MAC Address"
disabled_by_default: true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment