Skip to content

Instantly share code, notes, and snippets.

@patrick3399
Last active March 26, 2025 14:35
Show Gist options
  • Save patrick3399/23297c6ca4b37dfc87ca8593183a9a17 to your computer and use it in GitHub Desktop.
Save patrick3399/23297c6ca4b37dfc87ca8593183a9a17 to your computer and use it in GitHub Desktop.
S31-Ultimate
#Feature:
#Adjustable Overload Protect, Custom Current and Timing.
#Auto Overload Recovery, Adjustable Timing
#All Time 16A Safety Overload Protect
#Changeable Relay Initial State
#Overload Warning With LED Effect
#Detachment Relay Mode Support
#Press the Buttom more then 10s to Return the Factory Setting (AP Mode)
#Web and OTA, mDNS Available
#Github https://gist.github.com/patrick3399/23297c6ca4b37dfc87ca8593183a9a17
substitutions:
devicename: s31-ultimate
upper_devicename: S31U
comment: S31-ULTIMATE
update_current: 5000ms #Current Publish Interval
update_other: 30s #Other Publish Interval
esphome:
name: $devicename
comment: $comment
platformio_options:
build_flags: -D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
board_build.ldscript: eagle.flash.4m.ld
name_add_mac_suffix: True
on_boot:
priority: 300
then:
- if:
condition:
lambda: 'return id(default_relay_state).state == "OFF";'
then:
- switch.turn_off: relay
- if:
condition:
lambda: 'return id(default_relay_state).state == "ON";'
then:
- switch.turn_on: relay
project:
name: "patrick3399.S31Ultimate"
version: "2.0"
min_version: "2025.3.0"
preferences:
flash_write_interval: 30s
esp8266:
board: esp12e
framework:
version: latest
restore_from_flash: True
logger:
baud_rate: 0
level: WARN
api:
reboot_timeout: 0s
ota:
- platform: esphome
password: ""
wifi:
ap:
ssid: "S31-Ultimate Fallback Hotspot"
password: "S31ULTIMATE" # This is AP Password <<<
channel: 6
ap_timeout: 20min
power_save_mode: HIGH
reboot_timeout: 1h
captive_portal:
mdns:
disabled: False
web_server:
port: 80
uart:
rx_pin: RX
baud_rate: 4800
binary_sensor:
- platform: status
name: ${upper_devicename} API Connection Status
- platform: gpio
pin:
number: GPIO0
mode: INPUT_PULLUP
inverted: True
name: ${upper_devicename} Button
filters:
- delayed_on: 10ms
on_press:
then:
- if:
condition:
or:
- script.is_running: s31overloadrecovery
- script.is_running: s31overload_ems
- lambda: 'return id(detachment_relay).state == "ON";'
# When overload, there is a restart sequence, so manual switch the relay will be disable when sequence enable.
then:
else:
- switch.toggle: relay
on_click:
min_length: 8s
max_length: 30s
then:
- button.press: reset_to_factory
globals:
- id: clear_energy
type: float
restore_value: no
initial_value: "0"
- id: past_overload_led_stat
type: bool
restore_value: false
initial_value: 'false'
script:
- id: s31overloadtimer
mode: single
then:
- delay: !lambda 'return id(overload_trigger_timing).state * 1000;'
- switch.turn_off: relay
- if:
condition:
lambda: 'return id(overload_protect_recovery).state == "ON";'
then:
- script.execute: s31overloadrecovery
- if:
condition:
light.is_on: blueled_mono
then:
- lambda: 'id(past_overload_led_stat) = true;'
else:
- lambda: 'id(past_overload_led_stat) = false;'
- light.turn_on:
id: blueled_mono
effect: "Normal Overload Indicator"
- script.execute: s31overload_led
- id: s31overloadrecovery
mode: single
then:
- delay: !lambda 'return id(overload_recovery_timing).state * 1000;'
- switch.turn_on: relay
- id: s31overload_led
mode: restart
then:
- if:
condition:
- lambda: 'return id(overload_protect_recovery).state == "ON";'
then:
- delay: !lambda 'return id(overload_recovery_timing).state * 1000;'
else:
- delay: 30s
- light.turn_on:
id: blueled_mono
effect: none
- if:
condition:
- lambda: 'return id(past_overload_led_stat) == false;'
then:
- light.turn_off:
id: blueled_mono
- id: s31overload_ems
mode: single
then:
- light.turn_on:
id: blueled_mono
effect: "Emergency Overload Indicator"
- delay: 60s
- light.turn_on:
id: blueled_mono
effect: none
- if:
condition:
- lambda: 'return id(past_overload_led_stat) == false;'
then:
- light.turn_off:
id: blueled_mono
else:
sensor:
- platform: wifi_signal
name: ${upper_devicename} WiFi Signal
update_interval: 60s
- platform: cse7766
current:
name: ${upper_devicename} Current
accuracy_decimals: 1
id: s31current
filters:
- or:
- skip_initial: 1
- throttle_average: ${update_current} # Home Assistant Data ivterval
- delta: 30%
on_raw_value:
then:
- if:
condition:
sensor.in_range:
id: s31current
above: 16.0 # Emergency Shutdown Current
then:
- switch.turn_off: relay
- if:
condition:
light.is_on: blueled_mono
then:
- lambda: 'id(past_overload_led_stat) = true;'
else:
- lambda: 'id(past_overload_led_stat) = false;'
- script.execute: s31overload_ems
- if:
condition:
and:
- lambda: |-
return id(s31current).raw_state > id(overload_current).state;
- lambda: 'return id(overload_protect).state == "ON";'
- not:
script.is_running: s31overloadtimer
then:
- script.execute: s31overloadtimer
- if:
condition:
and:
- lambda: |-
return id(s31current).raw_state < id(overload_current).state;
- script.is_running: s31overloadtimer
then:
- script.stop: s31overloadtimer
voltage:
name: ${upper_devicename} Voltage
accuracy_decimals: 1
filters:
- skip_initial: 2
- throttle_average: ${update_other} # Home Assistant Data ivterval
power:
name: ${upper_devicename} Power
accuracy_decimals: 1
id: s31_power
filters:
- or:
- skip_initial: 1
- throttle_average: ${update_other} # Home Assistant Data ivterval
- delta: 30%
energy:
id: s31_origin_energy
filters:
- throttle_average: ${update_other} # Home Assistant Data ivterval
- multiply: 0.001
unit_of_measurement: kWh
accuracy_decimals: 4
on_value:
then:
- sensor.template.publish:
id: s31_energy
state: !lambda 'return x - id(clear_energy);'
- platform: template
name: ${upper_devicename} Energy Total
id: s31_energy
unit_of_measurement: kWh
accuracy_decimals: 3
icon: "mdi:lightning-bolt-circle"
device_class: energy
- platform: total_daily_energy
name: ${upper_devicename} Energy Daily
accuracy_decimals: 3
power_id: s31_power
restore: false
filters:
- multiply: 0.001
unit_of_measurement: kWh
- platform: uptime
name: ${upper_devicename} Uptime
name: ${upper_devicename} Uptime
text_sensor:
- platform: version
name: "${upper_devicename} ESPHome Version"
hide_timestamp: True
- platform: wifi_info
ip_address:
name: ${upper_devicename} IP Address
ssid:
name: ${upper_devicename} SSID
bssid:
name: ${upper_devicename} BSSID
mac_address:
name: ${upper_devicename} Mac Address
button:
- platform: template
name: ${upper_devicename} Reset Energy Total
icon: "mdi:power-settings"
on_press:
then:
lambda: !lambda |-
id(clear_energy) = id(s31_origin_energy).state;
id(s31_energy).publish_state(id(s31_origin_energy).state - id(clear_energy));
id(s31_energy).update();
- platform: factory_reset
name: ${upper_devicename} Factory Reset
id: reset_to_factory
switch:
- platform: gpio
name: ${upper_devicename} Relay
pin: GPIO12
id: relay
restore_mode: RESTORE_DEFAULT_ON
select:
- platform: template
name: "${upper_devicename} Default Relay State"
id: default_relay_state
optimistic: True
restore_value: True
options:
- "ON"
- "OFF"
- "RESTORE"
initial_option: "ON"
- platform: template
name: "${upper_devicename} Overload Protect"
id: overload_protect
optimistic: True
restore_value: True
options:
- "ON"
- "OFF"
initial_option: "ON"
- platform: template
name: "${upper_devicename} Overload Protect Auto Recovery"
id: overload_protect_recovery
optimistic: True
restore_value: True
options:
- "ON"
- "OFF"
initial_option: "ON"
- platform: template
name: "${upper_devicename} Detachment Relay_Button Link"
id: detachment_relay
optimistic: True
restore_value: True
options:
- "OFF"
- "ON"
initial_option: "OFF"
number:
- platform: template
name: "${upper_devicename} Overload Current Setting"
id: overload_current
optimistic: true
min_value: 0.5
max_value: 15
step: 0.5
initial_value: 15
restore_value: True
- platform: template
name: "${upper_devicename} Overload Trigger Timing Setting"
id: overload_trigger_timing
optimistic: true
min_value: 1
max_value: 15
step: 1
initial_value: 5
restore_value: True
- platform: template
name: "${upper_devicename} Overload Recovery Timing Setting"
id: overload_recovery_timing
optimistic: true
min_value: 15
max_value: 60
step: 5
initial_value: 30
restore_value: True
time:
- platform: homeassistant
output:
- platform: esp8266_pwm
pin:
number: GPIO13
inverted: True
mode: output
frequency: 1000 Hz
id: blueled_pwm
light:
- platform: status_led
id: blueled_status
output: blueled_pwm
internal: true
- platform: monochromatic
output: blueled_pwm
name: "${upper_devicename} Blue LED"
id: blueled_mono
effects:
- pulse:
name: Emergency Overload Indicator
update_interval: 0.4s
transition_length: 0s
- pulse:
name: Normal Overload Indicator
update_interval: 2s
transition_length: 0s
@Billtou
Copy link

Billtou commented Oct 15, 2023

excellent code

@Ares4570
Copy link

This doesn't seem compatible with the changes made in 2024.2 to the cse7766 component. Building in ESPhome gives an error:

[update_interval] is an invalid option for [sensor.cse7766]. Please check the indentation.

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