I have several of the Version 1 units (with WB2S chip, plus a batch of the “version 2” units that were actually version 1). The current “Version 3” units use a different chip again, which has been patched to prevent being cloudcut over the air … so I’m hoping another reasonably priced device comes on the market before I need to replace these ones. Expect PC191HA to fail sometime after 18 months.
I know I have given my yaml for these plugs in discussions previously, so do a search here for “PC191HA”.
From memory, they return a value for Power every time, but alternate between Voltage or Current - and it is not possible to use one value for voltage_divider that gives accurate results for both Voltage and Current I chose to optimise for Voltage and use “voltage_divider: 770” and to calculate Current as Power / Voltage
I will also mention that I have found that these plugs rarely start using new firmware immediately - you have to physically unplug them for a minute or so, and when powered up again they should pause (loading the new firmware) before the LED starts blinking (starting to connect to wi-fi). I guess that internally they do a warm restart which isn’t enough to trigger the firmware update
This can be detected from the ESPHome addon by selecting the [Logs] button then looking at the heading from the device - the first (green) line tells you the ESPHome version and the compile date/time.
And finally, when adding code into a furum post, use the [</>] button (or three backticks(`) to keep the indentation correct.
FYI, my yaml code is currently one header for each plug:
#
# I have a number of Arlec PC191HA smart plugs with Power Monitoring,
#
# This contains the parameters specific to this individual device.
### This unit is labelled as "series 2" but is v1 internally ###
# device-specific values moved out of common files
substitutions:
deviceIP: "111" # last octet of the IP Address used in the device name
wifi_ssid: !secret upstairs_ssid ### which wi-fi to connect to
wifi_password: !secret upstairs_password
# This unit is labelled as "series 2" but is v1 internally
pc191ha_version: "v1" # versions 1 and 2 use different chips with different pinouts
update_interval_network: "10 min" # How often to report network quality values
update_interval_energy: "10 min" # How often to measure and report energy values
update_interval_sensor: "2 min" # How often to measure and report other values
packages:
common_wifi: !include _common_wifi.yaml
device_base: !include _common_pc191ha-v1.yaml # version 1
Almost all the code is common to all of this model of plug, so is in an include file - which I have kept adding to as I find new things, so there’s a fair bit you can ignore. Honestly I’m impressed that so much functionality can be fitted into such a small device.
_common_pc191ha-v1.yaml is:
# I have a number of Arlec PC191HA v1 smart plugs with Power Monitoring,
# so this file contains logic common to all, to save updating multiple files.
#
# Version 1 uses WB2S chip, but version 2 uses CB2S chip with different pin numbers
# ... so easier to have separate v1 and v2 common files.
# Except that my units labelled "Version 2" are in fact the same as version 1.
# ESPHome guide says to use "name_add_mac_suffix: true" to automatically add the
# MAC address to the device name, so you can use a single firmware for all devices.
# Since I already use static IP addresses, I use last octet of the device IP Address.
#
# Many sections include name: and id: which are given the same values.
# In fact the id: is used only within the yaml configuration, whereas the external
# HA entity is named with friendly_name: and underline and name:
# So, the code:
# binary_sensor: # button (bt1_pin: 11)
# - platform: gpio
# pin: P11
# name: button
# device_class: window
# will generate HA entity named "pc191ha-111 button" with entity ID of "binary_sensor.pc191ha-111-button"
#
# Beware using friendly_name as this inconsistently adds a second device name prefix
# friendly_name: pc191ha-${deviceIP} # friendly_name is automatically prefixed to entities where necessary,
# # often resulting in entity ID of "binary_sensor.pc191ha-111-pc191ha-111-button"
substitutions:
devicename: pc191ha-${deviceIP}
# the parameters used below (for ease of adjusting)
restore_mode: RESTORE_DEFAULT_ON # mode for when power is turned on
esphome:
name: pc191ha-${deviceIP}
### friendly_name: pc191ha-${deviceIP} # friendly_name is automatically prefixed to entities where necessary.
bk72xx:
board: wb2s # version 1 uses WB2S chip
framework:
version: dev
# Enable logging
logger:
###########################################################
#
# PC191HA basic switch operation - button, relay and LED
#
###########################################################
#
# button is a binary.sensor. With the invert filter, the button is "ON" only while the button is being pressed.
# switch is the relay which turns the power on/off
# light is the LED in the switch, so should have same on/off state as the relay
# so no point exposing these to HA - use internal: true option
# there is also a wifi_LED, but it is not seen from outside the case
# I have added a virtual Reset button, pressed via control panel or long press of the button
#
binary_sensor: # button (bt1_pin: 11)
- platform: gpio
pin: P11
name: $devicename button
device_class: window
# by default the button is ON, and momentarily OFF while it is being pressed
# invert this, so ON means button is being pressed
filters:
- invert:
# when button is pressed, toggle the switch on/off
# add long (4second) press to reset
on_multi_click:
- timing:
- ON for at least 4s
- OFF for at least 1s
then:
- logger.log: "Button Long press to reset"
- button.press: reboot # long press to reset
- timing:
- ON for at most 1s
- OFF for at least 1s
then:
- logger.log: "Button Single Short Clicked"
- switch.toggle: relay # toggle the relay / switch
internal: true # button is momentary-on, HA is concerned with relay
switch: # relay (rl1_pin: 6)
- platform: gpio
pin: P6
name: $devicename Relay
id: relay
restore_mode: $restore_mode # default when power is turned on
# synchronise the LED with the relay
on_turn_on:
then:
- light.turn_on: led
on_turn_off:
then:
- light.turn_off: led
light: # Blue LED in the button (led1_pin: 26)
- platform: status_led
#name: $devicename LED state
id: led
pin: P26
restore_mode: $restore_mode # default when power is turned on
internal: true # don't need to see/change state of the LED separate from the relay
button:
- platform: restart
name: $devicename Reboot
id: reboot
###########################################################
#
# PC191HA sensors - power monitoring
#
###########################################################
globals:
- id: total_energy
type: float
restore_value: yes
initial_value: '0.0'
sensor:
# PC191HA includes a BL0937 chip for measuring power consumption
# and BL0937 is a variation of hlw8012, but using inverted SEL pin functionality
# Note that the first value reported should be ignored as inaccurate
- platform: hlw8012
model: BL0937 # note that the model must be specified to use special calculation parameters
sel_pin: # I believe that cf_pin reports either Voltage or Current depending on this select pin
inverted: true # determine whether true reports Voltage
number: P24
cf_pin: # current or voltage (ele_pin: 7)
inverted: true # the logic of BL0937 is opposite from HLW8012
number: P7
cf1_pin: # Power (vi_pin: 8)
inverted: true # the logic of BL0937 is opposite from HLW8012
number: P8
update_interval: ${update_interval_sensor} # How often to measure and report raw values
### Decided that I want Power and Voltage reported each time (not swapping with Current).
# I can choose not to keep swapping SEL pin, instead setting change_mode_every to a
# sufficiently high value that it will take 4000 years to change.
# This means I will have to calculate the value for current (as a template) from power / voltage
initial_mode: "VOLTAGE" # reports VOLTAGE or CURRENT
change_mode_every: 4294967295 # how many times to report before swapping
# Adjust according to the actual resistor values on board to calibrate the specific unit
voltage_divider: 770 # LOWER VALUE GIVES LOWER VOLTAGE
current_resistor: 0.001 # HIGHER VALUE GIVES LOWER WATTAGE
# how the power monitoring values are returned to ESPHome
voltage:
name: $devicename Voltage
id: voltage
unit_of_measurement: V
accuracy_decimals: 2
filters:
- skip_initial: 1
power:
name: $devicename Power
id: power_sensor
unit_of_measurement: W
accuracy_decimals: 3
filters:
- skip_initial: 1
- multiply: 0.97
- lambda: if (x < 0.01) {return 0;} else {return x;}
energy:
name: $devicename Energy
id: energy
unit_of_measurement: kWh
accuracy_decimals: 3
filters:
- skip_initial: 1
- multiply: 0.001 # Multiplication factor from W to kW is 0.001
on_value:
then:
- lambda: |-
static float previous_energy_value = 0.0;
float current_energy_value = id(energy).state;
id(total_energy) += current_energy_value - previous_energy_value;
previous_energy_value = current_energy_value;
- platform: template
name: $devicename Current
id: current
unit_of_measurement: A
accuracy_decimals: 3
update_interval: ${update_interval_energy}
lambda: |-
return ( id(power_sensor).state / id(voltage).state );
filters:
- skip_initial: 2 # give time for data to settle to avoid NaN
- platform: template
name: $devicename Total Energy
unit_of_measurement: kWh
device_class: "energy"
state_class: "total_increasing"
icon: "mdi:lightning-bolt"
accuracy_decimals: 1
lambda: |-
return id(total_energy);
- platform: total_daily_energy
name: $devicename Daily Energy
restore: true
power_id: power_sensor
unit_of_measurement: kWh
accuracy_decimals: 1
filters:
- multiply: 0.001
and _common_wifi.yaml contains the wi-fi parameters (including sensors) common to all my devices:
###########################################################
#
# Start with the Wi-fi connection
#
###########################################################
wifi:
ssid: $wifi_ssid
password: $wifi_password
manual_ip:
static_ip: 192.168.1.${deviceIP}
gateway: 192.168.1.1
subnet: 255.255.255.0
fast_connect: True
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "$devicename Fallback Hotspot"
password: !secret wifi_ap_password
ota:
platform: esphome
password: !secret esphome_ota_password
captive_portal:
# this displays the device's status at http:IP_Address
web_server:
port: 80
# Enable Home Assistant API
api:
encryption:
key: !secret esphome_api_encryption
sensor:
- platform: wifi_signal
name: $devicename Wifi signal
update_interval: ${update_interval_network} # how often to report wifi signal strength
# human readable uptime sensor output to the text sensor
- platform: uptime
name: $devicename Uptime
id: uptime_sensor
update_interval: ${update_interval_network} # how often to report
on_raw_value:
then:
- text_sensor.template.publish:
id: uptime_human
state: !lambda |-
int seconds = round(id(uptime_sensor).raw_state);
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
return (
(days ? String(days) + "d " : "") +
(hours ? String(hours) + "h " : "") +
(minutes ? String(minutes) + "m " : "") +
(String(seconds) + "s")
).c_str();
text_sensor:
- platform: version
name: $devicename ESPHome Version
hide_timestamp: False
- platform: wifi_info
ip_address:
name: $devicename Wifi IP Address
ssid:
name: $devicename Wifi connected to SSID
mac_address:
name: $devicename Wifi MAC Address
- platform: template
name: $devicename Uptime Human Readable
id: uptime_human
icon: mdi:clock-start
time:
- platform: sntp
id: sntp_time
update_interval: "120h" # I guess this is to poll the SNTP server ?