Below I am sharing the current version of the YAML I am using for the S31 outlets. It has not changed too much from the original posted above but has been adjusted to work with the latest changed in ESPHome.
@nosar7 - I modified the code to add the regular energy sensor and a couple others that I had missed or maybe were added after I finished working on the YAML. Either way you should now have what you seek.
If you want to adjust it in any way, here are a couple pages that might help:
@MatthewCMason - Unfortunately I do not know of any way to add the restore state configuration to the UI. If anyone does, please let me know!
One of the sensor I added, based on the cse7766 page referenced above is the Power Factor which prior I was calculating with a lambda. They both gave the same number so I just removed my template in favor of the baked in support… anyhow now I see an error in the logs:
[09:00:33][D][cse7766:186]: Impossible power factor: 1.0110 not in interval [0, 1]
Not a big deal but I wonder why…
Also, another minor issue is that the switch entity will show in the UI without a name. This is due to how I set up the YAML to force the naming of the entities (both internal and UI facing) to I want them to be. In other words, if the device is called “Office Equipment Outlet”, I want the switch entity to have the same name and I want the internal entity to also reflect that as in switch.office_equipment_outlet. Without my workaround it would end up being something like switch.office_equipment_outlet_office_equipment_outlet. Without the workaround the fix is just to rename the entity id, and with the workaround, it is simply to copy the device name and paste it into the entity name. This issue started once friendly_name was introduced eliminating the need to prepend it to each entity. Hopefully this makes sense…
Device specific YAML:
office-equipment-outlet.yaml
substitutions:
devicename: "office-equipment-outlet"
friendly_devicename: "Office Equipment Outlet"
device_description: "Office Equipment Outlet - s31-outlet-1"
voltage_cal: "0.5"
restore_mode_setting: ALWAYS_ON
#restore_mode: Control how the relay attempts to restore state on bootup.
#RESTORE_DEFAULT_OFF - Attempt to restore state and default to OFF if not possible to restore.
#RESTORE_DEFAULT_ON - Attempt to restore state and default to ON if not possible to restore.
#RESTORE_INVERTED_DEFAULT_OFF - Attempt to restore state inverted from the previous state and default to OFF.
#RESTORE_INVERTED_DEFAULT_ON - Attempt to restore state inverted from the previous state and default to ON.
#ALWAYS_OFF - Always initialize the pin as OFF on bootup.
#ALWAYS_ON - Always initialize the pin as ON on bootup.
# Interval of how often the wifi info is updated
update_interval_wifi: "120s"
cse7766_throttle_interval: "60s"
wifi:
ssid: !secret iot_wifi_ssid
password: !secret iot_wifi_password
# Default 15min, 0s will disable. Disabling because w/HA down the relays cycle on/off every 15 minutes.
reboot_timeout: 0s
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "${devicename}"
password: !secret iot_wifi_password
#Faster than DHCP. Also use if can't reach because of name change
manual_ip:
static_ip: 10.1.3.170
gateway: 10.1.2.1
subnet: 255.255.254.0
dns1: 10.1.0.50
dns2: 10.1.0.51
#Manually override what address to use to connect to the ESP.
#Defaults to auto-generated value. Example, if you have changed your
#static IP and want to flash OTA to the previously configured IP address.
use_address: 10.1.3.170
<<: !include template-s31-outlet.yaml
Template YAML common to all S31 outlets you have:
template-s31-outlet.yaml
esphome:
name: ${devicename}
comment: ${device_description}
friendly_name: ${friendly_devicename}
esp8266:
board: esp01_1m
early_pin_init: false #This prevents the on-off-on of the relay upon firmware upload
logger:
baud_rate: 0 # (UART logging interferes with cse7766)
# Remove this line if you're not using Home Assistsant or your switch will restart every now and again
api:
ota:
- platform: esphome
#password: !secret ota_password
web_server:
port: 80
include_internal: true
# Sync time with Home Assistant
# Used to calculate total daily energy
time:
- platform: homeassistant
id: ha_time
uart:
rx_pin: RX
baud_rate: 4800
text_sensor:
- platform: wifi_info
ip_address:
name: "IP"
id: device_ip
icon: "mdi:ip-outline"
update_interval: ${update_interval_wifi}
dns_address:
name: "DNS"
id: device_dns
icon: "mdi:dns-outline"
update_interval: ${update_interval_wifi}
ssid:
name: "SSID"
icon: "mdi:wifi-settings"
update_interval: ${update_interval_wifi}
bssid:
name: "BSSID"
icon: "mdi:wifi-settings"
update_interval: ${update_interval_wifi}
mac_address:
name: "MAC"
icon: "mdi:network-outline"
scan_results:
name: "Wifi Scan"
icon: "mdi:wifi-refresh"
update_interval: ${update_interval_wifi}
disabled_by_default: true
binary_sensor:
#Status Binary Sensor exposes the node state (if it’s connected to via MQTT/native API) for Home Assistant.
- platform: status
name: "Connection Status"
id: connection_status
entity_category: diagnostic
- platform: gpio
id: outlet_button
name: "Button"
pin:
number: GPIO0
mode: INPUT_PULLUP
inverted: True
entity_category: ''
on_press:
then:
- if:
condition: # only toggle relay if button is enabled
lambda: 'return (id(select_button).state == "Enabled");'
then:
switch.toggle: relay
- platform: template
id: threshold_status
name: "Above Threshold"
sensor:
- platform: wifi_signal
name: "WiFi Signal"
update_interval: ${update_interval_wifi}
#https://esphome.io/components/sensor/cse7766.html
- platform: cse7766
current:
name: "Current"
id: current
state_class: measurement
device_class: current
unit_of_measurement: A
accuracy_decimals: 1
filters:
- throttle_average: ${cse7766_throttle_interval}
voltage:
name: "Voltage"
id: voltage
state_class: measurement
device_class: voltage
unit_of_measurement: V
accuracy_decimals: 1
filters:
- throttle_average: ${cse7766_throttle_interval}
- offset: ${voltage_cal}
power:
name: "Power"
id: power
state_class: measurement
device_class: power
unit_of_measurement: W
accuracy_decimals: 1
filters:
- throttle_average: ${cse7766_throttle_interval}
on_value: # set or clear threshold_status template binary sensor depending on whether power usage is over threshold
- if:
condition:
lambda: 'return (x >= id(power_threshold).state);'
then:
- binary_sensor.template.publish:
id: threshold_status
state: ON
- if: # set or clear threshold_status template binary sensor depending on whether power usage is above threshold
condition:
lambda: 'return (id(select_led).state == "Threshold");'
then:
- switch.turn_on: blue_led
else:
- binary_sensor.template.publish:
id: threshold_status
state: OFF
- if: # set or clear threshold_status template binary sensor depending on whether power usage is above threshold
condition:
lambda: 'return (id(select_led).state == "Threshold");'
then:
- switch.turn_off: blue_led
energy:
name: "Energy"
accuracy_decimals: 1
filters:
- throttle: ${cse7766_throttle_interval}
apparent_power:
name: "Apparent Power"
accuracy_decimals: 1
filters:
- throttle_average: ${cse7766_throttle_interval}
power_factor:
name: "Power Factor"
accuracy_decimals: 1
filters:
- throttle_average: ${cse7766_throttle_interval}
- platform: total_daily_energy
name: "Daily Energy"
power_id: power
filters:
# Multiplication factor from W to kW is 0.001
- multiply: 0.001
unit_of_measurement: kWh
state_class: total_increasing
device_class: energy
# 3 shows each W consumed, 2 every 10W, 1 every 100W
accuracy_decimals: 1
number: # used as a threshold for whether the plugged-in devices is running.
- platform: template
name: "Power Threshold"
min_value: 1
max_value: 1800
step: 1
initial_value: 3
id: power_threshold
entity_category: config
optimistic: true # required for changing value from home assistant
restore_value: true
unit_of_measurement: W
mode: box
on_value:
- if:
condition:
lambda: 'return (id(power).state >= x);'
then:
- binary_sensor.template.publish:
id: threshold_status
state: ON
- if:
condition:
lambda: 'return (id(select_led).state == "Threshold");'
then:
- switch.turn_on: blue_led
else:
- binary_sensor.template.publish:
id: threshold_status
state: OFF
- if:
condition:
lambda: 'return (id(select_led).state == "Threshold");'
then:
- switch.turn_off: blue_led
switch:
# blue LED follows relay power state
- platform: gpio
id: blue_led
pin:
number: GPIO13
inverted: true
# relay output
- platform: gpio
id: relay
name: ' '
icon: "mdi:power-socket-us"
pin: GPIO12
entity_category: ''
restore_mode: ${restore_mode_setting}
# automatically make blue led equal relay state if set to "Relay"
on_turn_on:
- if:
condition: # only if blue LED set to "Relay"
lambda: 'return (id(select_led).state == "Relay");'
then:
switch.turn_on: blue_led
on_turn_off:
- if:
condition: # only if blue LED set to "Relay"
lambda: 'return (id(select_led).state == "Relay");'
then:
switch.turn_off: blue_led
#Do not enable otherwise Blue led can't be configured
#status_led:
# pin:
# number: GPIO13
button:
- platform: restart
id: restart_button
name: "Restart"
entity_category: diagnostic
select:
# option to disable button
- platform: template
name: "Button"
id: select_button
optimistic: true
options:
- Enabled
- Disabled
initial_option: Enabled
restore_value: true
icon: mdi:circle-double
entity_category: config
# option to disable blue LED
- platform: template
name: Blue LED
id: select_led
optimistic: true
entity_category: config
options:
- Relay
- Threshold
- Disabled
initial_option: Relay
restore_value: true
icon: mdi:led-on
on_value:
then:
- if:
condition:
lambda: 'return ( (id(select_led).state == "Relay") && id(relay).state );'
then:
switch.turn_on: blue_led
else:
switch.turn_off: blue_led