Why are my ESPs API-rebooting every 15 minutes even if they are accessible from Hass?

I have nothing else in the system that could trigger reboots, and still the ESPs in my boat reboot every 15 minutes like clockwork. I can only conclude that the reason has to be the api part. Does anybody have any idea why that happens? Here’s the code in the simplest one (fewest relays and only one ina219 voltage sensor…), as an example. I can of course block it by setting the reboot timeout to 0s, but it would be nice not to have to, in case they actually should loose the connection. Mad Max is the name of the boat, it’s a rugged looking hobby fishing boat, so I think it fits.

esphome:
  name: madmaxbaug
  platform: ESP32
  board: esp32doit-devkit-v1

wifi:
  ssid: "MadMax"
  password: "censored"
  manual_ip:
    static_ip: 192.168.3.101
    gateway: 192.168.3.1
    subnet: 255.255.255.0

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "madmaxbaugfallback"
    password: "censored"

captive_portal:

# Enable logging
#logger:

ota:

api:


mqtt:
  broker: 192.168.3.1
  topic_prefix: madmax/madmaxbaug
  reboot_timeout: 5min
  birth_message:
    topic: madmax/oppstart
    payload: "Mad Max baug har startet"
    retain: False
  on_message:
   - topic: madmax/ask
     then:
       - if:
           condition:
             lambda: 'return x == "ask";'
           then:
             - mqtt.publish:
                 topic: madmax/driftssjekk
                 payload: "Mad Max baug er i drift"

   - topic: madmax/madmaxbaug/on
     payload: "1"
     then:
       - if:
           condition:
             switch.is_on: baugrele1
           then:
             - mqtt.publish:
                 topic: madmax/releer/madmaxbaug
                 payload: "Mad Max baug relé 1 er allerede på"
           else:
             - mqtt.publish:
                 topic: madmax/releer/madmaxbaug
                 payload: "Mad Max baug relé 1 er av, slår på nå"
             - mqtt.publish:
                 topic: madmax/madmaxbaug/switch/rele1/state
                 payload: "ON"
             - delay: 0.5s
             - switch.turn_on: baugrele1

   - topic: madmax/madmaxbaug/off
     payload: "1"
     then:
       - if:
           condition:
             switch.is_on: baugrele1
           then:
             - mqtt.publish:
                 topic: madmax/releer/madmaxbaug
                 payload: "Mad Max baug relé 1 er på, slår av nå"
             - mqtt.publish:
                 topic: madmax/madmaxbaug/switch/rele1/state
                 payload: "OFF"
             - delay: 0.5s
             - switch.turn_off: baugrele1
           else:
             - mqtt.publish:
                 topic: madmax/releer/madmaxbaug
                 payload: "Mad Max baug relé 1 er allerede slått av"

   - topic: madmax/madmaxbaug/on
     payload: "2"
     then:
       - if:
           condition:
             switch.is_on: baugrele2
           then:
             - mqtt.publish:
                 topic: madmax/releer/madmaxbaug
                 payload: "Mad Max baug relé 2 er allerede på"
           else:
             - mqtt.publish:
                 topic: madmax/releer/madmaxbaug
                 payload: "Mad Max baug relé 2 er av, slår på nå"
             - mqtt.publish:
                 topic: madmax/madmaxbaug/switch/rele2/state
                 payload: "ON"
             - delay: 0.5s
             - switch.turn_on: baugrele2

   - topic: madmax/madmaxbaug/off
     payload: "2"
     then:
       - if:
           condition:
             switch.is_on: baugrele2
           then:
             - mqtt.publish:
                 topic: madmax/releer/madmaxbaug
                 payload: "Mad Max baug relé 2 er på, slår av nå"
             - mqtt.publish:
                 topic: madmax/madmaxbaug/switch/rele2/state
                 payload: "OFF"
             - delay: 0.5s
             - switch.turn_off: baugrele2
           else:
             - mqtt.publish:
                 topic: madmax/releer/madmaxbaug
                 payload: "Mad Max baug relé 2 er allerede slått av"

   - topic: madmax/madmaxbaug/on
     payload: "3"
     then:
       - if:
           condition:
             switch.is_on: baugrele3
           then:
             - mqtt.publish:
                 topic: madmax/releer/madmaxbaug
                 payload: "Mad Max baug relé 3 er allerede på"
           else:
             - mqtt.publish:
                 topic: madmax/releer/madmaxbaug
                 payload: "Mad Max baug relé 3 er av, slår på nå"
             - mqtt.publish:
                 topic: madmax/madmaxbaug/switch/rele3/state
                 payload: "ON"
             - delay: 0.5s
             - switch.turn_on: baugrele3

   - topic: madmax/madmaxbaug/off
     payload: "3"
     then:
       - if:
           condition:
             switch.is_on: baugrele3
           then:
             - mqtt.publish:
                 topic: madmax/releer/madmaxbaug
                 payload: "Mad Max baug relé 3 er på, slår av nå"
             - mqtt.publish:
                 topic: madmax/madmaxbaug/switch/rele3/state
                 payload: "OFF"
             - delay: 0.5s
             - switch.turn_off: baugrele3
           else:
             - mqtt.publish:
                 topic: madmax/releer/madmaxbaug
                 payload: "Mad Max baug relé 3 er allerede slått av"

   - topic: madmax/madmaxbaug/on
     payload: "4"
     then:
       - if:
           condition:
             switch.is_on: baugrele4
           then:
             - mqtt.publish:
                 topic: madmax/releer/madmaxbaug
                 payload: "Mad Max baug relé 4 er allerede på"
           else:
             - mqtt.publish:
                 topic: madmax/releer/madmaxbaug
                 payload: "Mad Max baug relé 4 er av, slår på nå"
             - mqtt.publish:
                 topic: madmax/madmaxbaug/switch/rele4/state
                 payload: "ON"
             - delay: 0.5s
             - switch.turn_on: baugrele4

   - topic: madmax/madmaxbaug/off
     payload: "4"
     then:
       - if:
           condition:
             switch.is_on: baugrele4
           then:
             - mqtt.publish:
                 topic: madmax/releer/madmaxbaug
                 payload: "Mad Max baug relé 4 er på, slår av nå"
             - mqtt.publish:
                 topic: madmax/madmaxbaug/switch/rele4/state
                 payload: "OFF"
             - delay: 0.5s
             - switch.turn_off: baugrele4
           else:
             - mqtt.publish:
                 topic: madmax/releer/madmaxbaug
                 payload: "Mad Max baug relé 4 er allerede slått av"
   - topic: madmax/madmaxbaug/omstart
     then:
       - mqtt.publish:
           topic: madmax/releer/madmaxbaug
           payload: "Tar omstart av Mad Max baug"
       - switch.turn_on: baugomstart

   - topic: madmax/madmaxbaug/omstart
     then:
       - mqtt.publish:
           topic: madmax/omstart
           payload: "Tar omstart av Mad Max baug"
       - switch.turn_on: baugomstart

switch:
  - platform: gpio
    name: "baugrele1"
    retain: False
    id: baugrele1
    pin:
      number: 19
      inverted: True
    restore_mode: ALWAYS_OFF

  - platform: gpio
    name: "baugrele2"
    retain: False
    id: baugrele2
    pin:
      number: 18
      inverted: True
    restore_mode: ALWAYS_OFF

  - platform: gpio
    name: "baugrele3"
    retain: False
    id: baugrele3
    pin:
      number: 5
      inverted: True
    restore_mode: ALWAYS_OFF

  - platform: gpio
    name: "baugrele4"
    retain: False
    id: baugrele4
    pin:
      number: 17
      inverted: True
    restore_mode: ALWAYS_OFF

  - platform: restart
    name: "baugomstart"
    retain: False
    id: baugomstart

i2c:
  - id: bus_a
    sda: 21
    scl: 22
    scan: True
  - id: bus_b
    sda: 14
    scl: 15
    scan: True
   
sensor:
  - platform: ina219
    i2c_id: bus_a
    address: 0x40
    shunt_resistance: 0.1 ohm
    bus_voltage:
      name: "Batterispenning baug"
    max_voltage: 32.0V
    max_current: 3.2A
    update_interval: 60s

As you have api and mqtt in your config I guess you just use one of them (actively) and the other is causing the automatic reboot like written in the docs… :point_down:

In anyway the logs will also tell you the reason for the reboot…

Thanks for answering! No, I use them both. I have the switches controllable both from Node-RED (not the Hass integration, the solo Node-RED) and from the GUI in Hass. MQTT is never lost, and I have a heartbeat going over MQTT every minute that will restart Hass if that locks up, restart Node-RED if that locks up and reboot the Pi if the MQTT or anything else in the system stops working.

I also see in real time that the voltmeter’s value changes in both NR and Hass. Here’s the Hass graph:

Edit: Logs where? if you mean the logs in Hass, that doesn’t show anything for this. It doesn’t have an entry since 13.06 yesterday, and that was an error connecting to the main system in the cabin because I was out pulling my lobster pots.

Edit 2: The low points of the graph is not dropouts, they are the C-TEK charger testing the voltage for a short periode to adjust the charging.

I also had problem with both MQTT and the HA API at the same time. My solution was to just use one or the other. (At this point I don’t think I have any MQTT on my ESPHome nodes). All of my MQTT is handled in Node Red.

I am assuming that it isn’t a power issue.

Thanks! Then I guess I’ll just have to turn off the API reboot on them, the rest works and I need both in my system.

And no, I’d be very surprised if my boat went under 11 V (which I believe is the limit for Hobbywing 3A power supplies) like clockwork every 15 minutes while charging at the dock. Also they are on two different batteries, so that makes it even less plausible.

The second paragraph of the MQTT component answers your question, in a big red box:

Warning

If you enable MQTT and you do not use the “native API” for Home Assistant, you must remove the api: line from your ESPHome configuration, otherwise the ESP will reboot every 15 minutes because no client connected to the native API.

3 Likes

@zoogara Do you mean that the native API is something else than what comes up in Hass when it discovers the ESPs over MQTT? I always thought that was the same. This is the devices page for my boat:

When ESPHome talks about the native API, it is talking about a communication protocol that can be used instead of MQTT to talk to Home Assistant.

The 2 protocols are mutually exclusive - because if you enable MQTT then that will get used instead of the API. Because no traffic is being sent over the API link, the restart timer kicks in and reboots.

Aha, I see! Then I was mistaken about that. I’ll dump it from all of my 20+ ESPs in the house, cabin, car and boat. Thanks!

Some differences between the native API and MQTT are mentioned in the esphome docs :page_facing_up: :

Advantages over MQTT

The ESPHome native API has many advantages over using MQTT for communication with Home Automation software (currently only Home Assistant). But MQTT is a great protocol and will never be removed. Features of native API (vs. MQTT):

  • Much more efficient: ESPHome encodes all messages in a highly optimized format with protocol buffers - for example binary sensor state messages are about 1/10 of the size.
  • One-click configuration: ESPHome just needs one click to set up in Home Assistant - no more messing around with retained MQTT discovery messages and alike.
  • One less single point of failure: In the ESPHome native API each ESP is its own server. With MQTT, when the broker shuts off nothing can communicate anymore.
  • Stability: Since ESPHome has far more control over the protocol than with MQTT, it’s really easy for us to roll out stability improvements.
  • Low Latency: The native API is optimized for very low latency, usually this is only a couple of milliseconds and far less than can be noticed by the eye.

That looks very good, and preferable. But as I understood the last mesages I can’t have both MQTT active and the API at the same time, so when I need Node-RED to have access to the ESPs with MQTT and MQTT then will be active, that will take presedence over the API in Hass as well. Or is there a way around that, like blocking discovery in MQTT? I need MQTT to be active in Hass because that sends command to Node-RED and receives NMEA 0183 navigational data (like position, water depth and so on) from SignalK over MQTT.

I found somebody else who had done it, so I think it should work with blocking discovery. Worth a shot!

Edit: Seems to work so far. The weird thing is that the relays on the devices got the same names as they had under MQTT, I only had to rename the device itself (like madmaxbaug to Baug (in the bow of the boat)).

1 Like

Using the Api: home assistant will mark entities from “ESPHome” integration.

Yep, it did. I haven’t changed them all yet, they are not all in the boat at the moment. I’m doing a bit of a refit of the electrical system, with some new stuff, like NMEA 2000 integration.

A bit of a word salad there… But what do you mean that Node Red needs access to the ESP? Show an example. As I said, all of my MQTT is handled by Node Red, and Node Red installed as a Home Assistant add-on has API nodes.

I had misunderstood, I thought it was impossible to have both MQTT and API from the ESP’s, but it’s no problem, as long as they are set to discovery: false in the ESP Home YAML that’s programmed into them.

I need to use an older version of Node-RED for my systems because I still use the Tellstick Duo’s, which I have a bunch of, for temp sensors. In the boat that’s both water and air temperature sensors. The latest version of Node-RED does not support Tellstick Duo (neither does Bullseye, btw). so I must block all upgrades. That’s easier to do with a stand-alone Node-RED, at least it was when I started using it.

And why I need access from Node-RED is mostly a preference thing. I use Hass as a front end, while the more advanced stuff I prefer to do in Node-RED. For instance: I’m almost done with a flow in Node-RED that will do this:

  1. Take an MQTT message from a button on the Hass GUI.

  2. Turn on the ignition with a relay to check if the outboard motor is up or down, from the NMEA 2000 Suzuki Interface.

  3. Tilt it down if it’s up, then lower the jack plate to standard setting for driving the boat (a jack plate is a setup with an actuator that can lower and raise the motor, so it can come completely out of the water when docked, and it is very useful in high waves, like we often have in October in Norway, when I fish lobster).

  4. Start the motor with other relays, so it has a running temperature when I go out. The Suzukis like to be warm when they ned to go fast from forward, throttle all the way down, and over in reverse, or they can sometimes stall. That’s a problem when I’m three meters from the rocks, pulling a lobster pot.

I am also going to do one that stops the motor, raises the jack plate up to where the hall sensor confirms that it’s in the highest position and then tilts it up. If it’s tilted up before the jack plate is in the highest position, it will damage the steering because that will hit the boat.

So complex stuff like that I prefer to do in Node-RED. I am fully aware that I can do it in automations in Hass, I just prefer to do flows, it’s easier for me than YAML. I wish Hass automations could be done in LUA or Python, those are my languages, especially LUA. But design choices are up to the designers, not me.

On the other hand it’s nice to have the individual relays available in the GUI for stuff I don’t need a long “if-then-else” flow for, like when the boat is docked and I’m not at the cabin, and ther’s a storm after dark. Then I can use the relay for the deck lights to turn them on and see that it’s still docked and does not pull too much in the mooring, through the camera in the cabin window.