Detect API disconnection

Hi,

I am looking to have a kind of failsafe feature on an important plug that is running ESPHOME. This plug is use to manage an heating device for my chicken coop.

Right now it is an outside automation (in nodered) that switch the plug from OFF to ON base on a temp sensor.

My goal is to do something like this :

  • If the esphome API is not reachable (since 5 minutes)
  • Turn ON the plug for 10 minutes
  • Then turn OFF the plug for 10 minutes
  • Loop the process until the API got connected again

any cllue ?
thanks

On thing that may disrupt your plan: If ESPHome can’t detect an API connection for 15 minutes it reboots. You can change this time. See reboot_timeout https://esphome.io/components/api.html#configuration-variables

oh that’s maybe a good way to use for me.
I can, on the “on_boot” event, turn on the switch for an amount of time if the api is not connected.
Do you know if the “reboot process” is recurrent ?
Example :

  • at 8h00 the api or wifi goes disconnected
  • at 8h15 esphome reboot
  • if after the reboot, the api is still disconnected…at 8h30 I will have another reboot ? then 8h45, 9h00, etc. etc. ?

Yes it keeps rebooting every reboot_timeout until reconnected.

However, until wifi is connected nothing else will run. Maybe you could set your on_boot priority below the wifi connection priority? Not sure.

1 Like

Thanks for all your answer tom.
I did some search and I ended out with a “watchdog” like this :

interval:
  - interval: 5 min
    then:
      - if:
          condition:
            not:
              api.connected:
          then:
            - script.execute: heating_device_script
			
script:
- id: heating_device_script
  mode: restart   
  then:
    - switch.turn_on: espawp02
    - delay: 5 min
    - switch.turn_off: espawp02

I didn’t put it online yet but I think it will do the job I need. So each 5 minutes esphome will check if the API is connected and if not, it will call my script that turn on the switch for 5 min.
So with this in place, if my main server that run (HA / NodeRed) crash and it is not accessible, I will be sure that some heating will be done in the coop.

I’m doing something similar to what you’re doing.
I think the problem with your code is that it would execute your script every 5 minutes if it stays disconnected.
The solution to this is to detect only the api.connected state changes.
This is how I’m doing it:

globals:
  - id: api_connection
    type: bool
    restore_value: no
    initial_value: 'false'

interval:
  - interval: 10s
    then:
      - if:
          condition:
            # check last connection state
            - lambda: 'return { (id(api_connection) != true) };'
          then:
            - if:
                condition:
                  api.connected:
                then:
                  # just connected now
                  - lambda: "id(api_connection) = true;"
          else:
            - if:
                condition:
                  not:
                    api.connected:
                then:
                  # just disconnected now
                  - lambda: "id(api_connection) = false;"

This code creates a trigger for both the connected and disconnected state changes.

I hope this helps.

3 Likes

I’ve just written a ‘Router Watcher’ that does exactly this.

It will check every minute for a connection, if not it will add to the global int. Once that global int gets to 5 it performs a reboot and adds to a reboot counter. It has an override switch (for when you’re updating HA) and is easily configured.

Hope this is uselful to someone.

time:
  - platform: homeassistant
    id: hass_time
    on_time: # This will reset the rebootcounter at Midnight Sunday
      - seconds: 0
        minutes: 0
        hours: 0
        days_of_week: 2
        then:
          - number.to_min: rebootcounter

number:
  - platform: template # This will count the number of times your the router has been rebooted
    id: rebootcounter
    name: Reboot Counter
    optimistic: True
    restore_value: True
    mode: box
    min_value: 0
    max_value: 120 # This is the maximum number of reboots it counts to (however, it will still reboot more)
    step: 1
    icon: mdi:restart-alert
    unit_of_measurement: Count

globals:
  - id: counter # This is a counter that increases each time the API is not connected.
    type: int
    restore_value: False
    initial_value: "0"

switch:
  - platform: gpio
    pin: GPIO0
    name: ${upper_devicename} Relay
    id: router
    inverted: True
    restore_mode: ALWAYS_ON
    on_turn_off:
      - delay: 30s
      - switch.turn_on: router 
  - platform: template
    name: ${upper_devicename} Disable
    optimistic: True
    restore_mode: ALWAYS_OFF
    id: disable
    icon: mdi:stop-circle

interval:
  - interval: 1min # Every minute
    then:
      - if:
          condition:
            or:
              - api.connected:
              - lambda: return (id(disable).state != 0); # If the API is not connected
          then:
            - globals.set: # Reset the global 'counter'
                id: counter
                value: "0"
          else:
            - lambda: id(counter) += 1; # Else add 1 to the global 'counter'
      - if:
          condition:
            lambda: return (id(counter) >=5); # If the value of global 'counter' is 5 or above
          then:
            - number.increment: rebootcounter # Add 1 to the number 'rebootcounter'
            - globals.set:
                id: counter
                value: "0" # Reset the global 'counter'
            - switch.turn_off: router # Turn off the router
      - logger.log:
          format: "Disconnect Counter is: %i, Disable State is:  %i"
          args: [ '(int)id(counter)','(int)id(disable).state' ]

And this is what I made, I used an extension cable, cut it in half, through a buck converter and an ESP-01 with a relay module.

2 Likes

Thanks, I used your config
Just to clarify, it only starts the interval once api disconnected, correct?

As for the counter, do I just increase to 3 or 5 counts since it’s 1 by default?

time:
  - platform: homeassistant
    id: hass_time
    on_time: 
      - seconds: 0
        minutes: 0
        hours: 0
        days_of_week: 2 <-- what is this for?
        then:
          - number.to_min: rebootcounter

number:
  - platform: template
    id: rebootcounter
    name: Reboot Counter
    optimistic: True
    restore_value: True
    mode: box
    min_value: 0
    max_value: 120 <-- is the equals to 120 seconds for each counter? do i just reduce the time here (eg 60 seconds)
    step: 1
    icon: mdi:restart-alert
    unit_of_measurement: Count

Every minute it checks if there is a connection to the HA API, if not it will add 1 to the counter, after that counter has reached 5, the switch will turn off the router for 30 seconds and then switch it back on.

The visible counter ‘reboot counter’ shows how many times it has actually gone through all 5 and rebooted the router.

The counter resets at midnight Sunday (That’s what days of the week does)
max_value: is just a maximum number for the counter.

In short, yes, the stuff in the interval will only run if the API is disconnected.

id: rebootcounter is just a counter that add 1 everytime the router is rebooted, it’s not needed, but gives you an indication that there has been a reboot.

The configurable parts are :-

  • How long the interval is (it’s set for 1 minute at the moment)
  • The global counter counts to 5

Therefore 1x5=5mins.

Also edited previous post.

1 Like

Thanks for the explanation, so this should be the line I need to edit for the time & count numbers if i need to reduce or increase them.

image

And it’s not for modify anything, just displays the reboot counter status.

Yes, spot on.

I could have made them number and configurable from HA, but I didn’t think it was needed. Once it’s set up, it’s done :slight_smile:

1 Like

Hey guys, what am I doing wrong, can someone tell me?

...

switch:
  - platform: gpio
    name: "Corridor Ceiling Center"
    pin: GPIO12
    id: relay
    restore_mode: ALWAYS_ON

...

interval:
  - interval: 0.1 min
    then:
      - if:
          condition:
            not:
              api.connected:
          then:
            - switch.turn_on: relay

But switch is still off, when api is disconnected and I rebooting my HA.

HI!
i have same problem - i can fix when my devise connecting HA, but in any case i can’t fix when it disconnecting,
My task is monitor “HA accessible”
when “YES” turn switch on, when “NO” - turn switch off
i tryed to use condition api.connected and triggers on_client_connected: and on_client_disconnected: with same result

Any ideas?