Last active
March 26, 2025 14:35
-
-
Save patrick3399/23297c6ca4b37dfc87ca8593183a9a17 to your computer and use it in GitHub Desktop.
S31-Ultimate
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 |
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
excellent code