Restore_mode stopped working when upgrading from 2023.6.1 to 2023.8.1

I’ve used an automatic water shutoff valve for quite a while with ESPHome (since 2020 apparently) and I’ve been very happy with the results. It’s on the main incoming water line for my house in the event of a detected leak. So when it turns the water off, it’s pretty obvious.

I’ve upgraded the firmware on it probably a dozen times since migrating from Tasmota to ESPHome in 2020. However, in August 2023, I noticed that when I flashed the latest version of ESPHome (then it was 2023.8.1) the flash operation caused the water valve to shut off the water!! I thought: “maybe this is a fluke” since I hadn’t changed anything in the config YAML and it had previously worked fine when rebooting after a flash.

I flashed it again in September 2023 to ESPHome version 2023.9.1 and again it shut the valve off on reboot. I have the restore_mode set to RESTORE_DEFAULT_ON which used to work. The YAML is laid out like this (flattened but not changed):

substitutions:
  node_name: watervalve
  friendly_name: Water Main Valve
  board: esp01_1m
  restore_from_flash: 'True'
  log_level: NONE

packages:
  wifi: !include common/wifi.yaml
  device_base: !include common/device_base_esp8266.yaml

# these esphome and esp8266 statements are in the esp8266 package YAML file above
esphome:
  name: ${node_name}

esp8266:
  board: ${board}
  restore_from_flash: ${restore_from_flash}
# end package YAML file statements

api:
  encryption:
    key: [REDACTED]

binary_sensor:
  - platform: gpio
    pin:
      number: GPIO13
      mode: INPUT_PULLUP
      inverted: True
    id: my_button
    internal: True
    on_press:
      - switch.toggle: relay_template

status_led:
  id: blue_led
  pin:
    number: GPIO4

switch:
  - platform: gpio
    pin: GPIO12
    id: relay
    restore_mode: RESTORE_DEFAULT_ON
  - platform: template
    name: ${friendly_name}
    id: relay_template
    icon: 'mdi:pipe'
    lambda: |-
      if (id(relay).state) {
        return true;
      } else {
        return false;
      }
    turn_on_action:
      - switch.turn_on: relay
      - light.turn_on: valve_status_light
    turn_off_action:
      - switch.turn_off: relay
      - light.turn_off: valve_status_light

output:
  - platform: gpio
    id: red_led
    pin:
      number: GPIO5
      inverted: True

light:
  - platform: binary
    name: ${friendly_name} Status Light
    id: valve_status_light
    output: red_led
    #internal: True

I looked through the ESPHome change history for anything with “restore” in it and found one entry released in 2023.7.0 but it doesn’t appear to have to do with the restore_mode that I’m using in gpio switch.

I read a bit in the gpio switch help page for anything that might help me understand what is going on here and I found a note at the bottom that says:

Warning

These are software interlocks. As such, a software bug (which can always happen) can still activate both switches at the same time. Similarly, at reset time (before any of ESPHome’s code runs) the relay GPIO pins may have pull-ups active, so the relay may be active before ESPHome can manually deactivate them.

So it is highly recommended to use hardware interlocks (like SPDT-type relays) that ensure that two GPIOs are never active at the same time.

it was the “Similarly, at reset time…” that caught my eye. I wonder if the pin used for the relay is pulled up. My hardware hasn’t changed but I don’t remember this note… I did some research on this but it appears GPIO12 is recommended as an input and an output with no specific messages citing pull ups nor downs on it.

I’m at a loss now. Aside from trying just ALWAYS OFF which I’d rather avoid, I’m not sure if there are any other options. Anyone know how to troubleshoot the restore from flash memory? There isn’t any USB plug on this thing so I’ll probably have to disassemble it a bit and use a FTDI serial thing to watch the logs but I think that might be my next move… :frowning:

I am not sure, but one thing to try is replacing 'True' by true (so no apostrophes and no capital letter).
And another option could be to add an on_boot automation to ensure the valve to be on at boot.

I tried this and the editor doesn’t like it:

Apparently, for substitutions you have to use the quotes.

I just realized something bad about this YAML. When I reboot the device gracefully with:

button:
  - platform: restart
    name: ${friendly_name} Restart

The valve starts to turn off!! Then when it’s booting and the handle is half-way closed, it reverses direction and starts opening again. I wonder if the template switch is causing issues here, is there a way to disable it from interacting at startup/shutdown?

I spent a few hours today looking deeper at this. I took the device off the water main valve and brought it to my PC so I could run a bunch of tests. I think the original way I implemented this was poor – maybe some of the ESPHome features I’m using didn’t exist yet :wink: . Anyway, I re-wrote it and took advantage of the automations (like on_press, on_turn_on, etc.) to handle the linkages between the lights, the button, and the relay.

I think the original template switch and linkages were causing big problems on reboots and updates. Still weird that it happened on a transition from version to version but I’m glad I’ve been able to tighten up the code! :smiley:

This new YAML is much simpler:

substitutions:
  node_name: watervalve
  friendly_name: Water Main Valve
  board: esp01_1m
  restore_from_flash: 'True'
  log_level: NONE
  
packages:
  wifi: !include common/wifi.yaml
  device_base: !include common/device_base_esp8266.yaml

api:
  encryption:
    key: [REDACTED]

binary_sensor:
  - platform: gpio
    pin:
      number: GPIO13
      mode: INPUT_PULLUP
      inverted: True
    name: ${friendly_name} Button
    id: ${node_name}_button
    on_press:
      - switch.toggle: ${node_name}

switch:
  - platform: gpio
    pin: GPIO12
    name: ${friendly_name}
    id: ${node_name}
    icon: mdi:pipe-valve
    restore_mode: RESTORE_DEFAULT_ON
    on_turn_on:
      - light.turn_off: ${node_name}_red_led
    on_turn_off:
      - light.turn_on: ${node_name}_red_led

output:
  - platform: gpio
    id: red_led_output
    pin:
      number: GPIO5

light:
  - platform: status_led
    name: ${friendly_name} Blue LED
    id: ${node_name}_blue_led
    pin:
      number: GPIO4
  - platform: binary
    name: ${friendly_name} Red LED
    id: ${node_name}_red_led
    output: red_led_output

and best of all it works in all conditions:

  • whatever state the valve is set to remains on reboot and updates
  • blue LED is warning status - blinks slow for warn/notice, fast for error, and turns off after good boot
  • red LED is valve status - it turns on if the water valve is turned off (and vice versa)
  • button can be pressed to toggle state
  • switch in Home Assistant represents the state of the relay (on means water can flow)

I noticed some other YAMLs that people posted for their water valves with GPIO13 and GPIO12 swapped from my config. I verified all the pins on mine when messing with it to be sure – it must be a manufacturer difference or something.

3 Likes

Thanks for this feedback.
It is strange, isn’t it?
According to the ESPHome ESP8266 Platform docs the restore_from_flash config variable has to be a boolean, so true or false, and for instance the board config variable has to be a string.
But apparently when you put those config variables in a substitutions: section the restore_from_flash config variable has to be a string between single quotes and the board config variable has to be a string but not between single quotes…
This at least is confusing, but could this be a “bug”?

Thanks Spikey! I replaced the Tuya chip with an ESP-12F in my SM-AW713 and it worked straight away with the core of your code. I thought I was going to have to try every permutation of GPIO ports to get it working.

Cheers

1 Like