devices.esphome.io
Shelly Plus Plug S
Shelly Plus Plug S
Device Type: plugElectrical Standard: euBoard: esp32
GPIO Pinout
Pin | Function |
---|---|
GPIO25 | LED 1 & 2 |
GPIO26 | LED 3 & 4 |
GPIO9 | Button |
GPIO4 | Relay |
GPIO33 | Internal Temperature |
GPIO19 | HLW8012 (power measurement) |
GPIO10 | CF Pin |
GPIO22 | CF1 Pin |
Configuration as relay with overpower and overtemperature protection
When integration with home assistant exists, it will appear as a switch, 3 sensors (power, total energy, temperature) and two RGB lights that can be configured as the color for the ring when on or off.
When the max_power
is exceeded, the relay will be switched off and a persistent notification will be created in home-assistant
When the max_temp
is exceeded, the relay will be switched off and a persistent notification will be created in home-assistant
Thanks to all contributors in this topic.
Config tested by bobkersten
substitutions: device_name: shelly-plus-plug-s-3 friendly_name: shelly-plus-plug-s-3 channel_1: Relay max_power: "1500" # 2000 max_temp: "65.0" # 70.0 # Higher value gives lower watt readout. current_res: "0.001" # Lower value gives lower voltage readout. voltage_div: "1830"
esphome: name: ${device_name} friendly_name: ${friendly_name} on_boot: - delay: 10s - lambda: !lambda |- id(rgb_ready) = true; - script.execute: set_rgb
esp32: board: esp32doit-devkit-v1 framework: type: esp-idf
# Enable logginglogger:
# Enable Home Assistant APIapi:
ota:
wifi: ssid: !secret wifi_ssid password: !secret wifi_password
# Enable fallback hotspot in case wifi connection fails ap: ssid: ${device_name}
time: - platform: homeassistant id: my_time
globals: - id: rgb_ready type: bool restore_value: false initial_value: 'false' - id: total_energy type: float restore_value: true initial_value: '0.0'
#### only needed for RGB LED to set up a while after boot #####
script: - id: set_rgb mode: queued then: - if: condition: lambda: 'return id(rgb_ready);' then: - if: condition: lambda: 'return id(relay).state;' then: - if: condition: lambda: 'return id(ring_on).remote_values.is_on();' then: - light.turn_on: id: rgb_light1 brightness: !lambda |- return id(ring_on).remote_values.get_brightness(); red: !lambda |- return id(ring_on).remote_values.get_red(); green: !lambda |- return id(ring_on).remote_values.get_green(); blue: !lambda |- return id(ring_on).remote_values.get_blue(); - light.turn_on: id: rgb_light2 brightness: !lambda |- return id(ring_on).remote_values.get_brightness(); red: !lambda |- return id(ring_on).remote_values.get_red(); green: !lambda |- return id(ring_on).remote_values.get_green(); blue: !lambda |- return id(ring_on).remote_values.get_blue(); else: - light.turn_off: rgb_light1 - light.turn_off: rgb_light2 else: - if: condition: lambda: 'return id(ring_off).remote_values.is_on();' then: - light.turn_on: id: rgb_light1 brightness: !lambda |- return id(ring_off).remote_values.get_brightness(); red: !lambda |- return id(ring_off).remote_values.get_red(); green: !lambda |- return id(ring_off).remote_values.get_green(); blue: !lambda |- return id(ring_off).remote_values.get_blue(); - light.turn_on: id: rgb_light2 brightness: !lambda |- return id(ring_off).remote_values.get_brightness(); red: !lambda |- return id(ring_off).remote_values.get_red(); green: !lambda |- return id(ring_off).remote_values.get_green(); blue: !lambda |- return id(ring_off).remote_values.get_blue(); else: - light.turn_off: rgb_light1 - light.turn_off: rgb_light2
output: - platform: template id: r_out_on type: float write_action: - lambda: |- - platform: template id: g_out_on type: float write_action: - lambda: |- - platform: template id: b_out_on type: float write_action: - lambda: |- - platform: template id: r_out_off type: float write_action: - lambda: |- - platform: template id: g_out_off type: float write_action: - lambda: |- - platform: template id: b_out_off type: float write_action: - lambda: |-
light: - platform: rgb id: ring_on name: "${channel_1} Ring when On" icon: "mdi:circle-outline" default_transition_length: 0s red: r_out_on green: g_out_on blue: b_out_on restore_mode: RESTORE_DEFAULT_OFF entity_category: config on_state: - delay: 50ms - script.execute: set_rgb - platform: rgb id: ring_off name: "${channel_1} Ring when Off" icon: "mdi:circle-outline" default_transition_length: 0s red: r_out_off green: g_out_off blue: b_out_off restore_mode: RESTORE_DEFAULT_OFF entity_category: config on_state: - delay: 50ms - script.execute: set_rgb
- platform: esp32_rmt_led_strip rgb_order: GRB rmt_channel: 0 chipset: ws2812 pin: GPIO25 num_leds: 2 id: rgb_light1 internal: true default_transition_length: 700ms restore_mode: ALWAYS_OFF - platform: esp32_rmt_led_strip rgb_order: GRB rmt_channel: 1 chipset: ws2812 pin: GPIO26 num_leds: 2 id: rgb_light2 internal: true default_transition_length: 700ms restore_mode: ALWAYS_OFF
binary_sensor: - platform: gpio id: "push_button" internal: true pin: number: GPIO9 inverted: yes mode: input: true pullup: true on_click: then: - if: condition: switch.is_off: button_lock then: - switch.toggle: relay filters: - delayed_on_off: 5ms
switch: - platform: gpio pin: GPIO4 id: relay name: "${channel_1}" restore_mode: RESTORE_DEFAULT_OFF on_turn_on: - script.execute: set_rgb on_turn_off: - script.execute: set_rgb - platform: template entity_category: 'config' name: "Button lock" id: button_lock optimistic: true restore_mode: ALWAYS_OFF
sensor: - platform: ntc sensor: temp_resistance_reading name: "${device_name} Temperature" unit_of_measurement: "°C" accuracy_decimals: 1 icon: "mdi:thermometer" entity_category: 'diagnostic' calibration: b_constant: 3350 reference_resistance: 10kOhm reference_temperature: 298.15K on_value_range: - above: ${max_temp} then: - switch.turn_off: "relay" - homeassistant.service: service: persistent_notification.create data: title: Message from ${device_name} data_template: message: Switch turned off because temperature exceeded ${max_temp} °C - platform: resistance id: temp_resistance_reading sensor: temp_analog_reading configuration: DOWNSTREAM resistor: 10kOhm - platform: adc id: temp_analog_reading pin: GPIO33 attenuation: 12db update_interval: 10s
- platform: hlw8012 model: BL0937 sel_pin: number: GPIO19 inverted: true cf_pin: GPIO10 cf1_pin: GPIO22 current_resistor: ${current_res} voltage_divider: ${voltage_div} change_mode_every: 1 update_interval: 5s current: id: current unit_of_measurement: A accuracy_decimals: 3 internal: true name: "${channel_1} current" voltage: id: voltage unit_of_measurement: V accuracy_decimals: 1 internal: false name: "${channel_1} voltage" power: name: "${channel_1} power" unit_of_measurement: W id: power icon: mdi:flash-outline force_update: true on_value_range: - above: ${max_power} then: - switch.turn_off: relay - homeassistant.service: service: persistent_notification.create data: title: Message from ${device_name} data_template: message: Switch turned off because power exceeded ${max_power}W
- platform: total_daily_energy name: "${channel_1} energy" power_id: power state_class: total_increasing unit_of_measurement: kWh filters: # Multiplication factor from W to kW is 0.001 - multiply: 0.001 - lambda: !lambda |- static auto last_state = x; if (x < last_state) { // x was reset id(total_energy) += last_state; ESP_LOGI("main", "Energy channel 1 was reset: %f", id(total_energy)); } last_state = x; return id(total_energy) + x;