DEV Community

Cover image for Home Assistant: How to Fix API Disconnection and False Positive Sensor Readings with ESP8266 Boards
Sebastian
Sebastian

Posted on

Home Assistant: How to Fix API Disconnection and False Positive Sensor Readings with ESP8266 Boards

When using Home Assistant to integrate with ESPHome managed devices, connection timeouts can occur. Normally this means that the device could not be reached temporarily only, and will eventually get connected again. However, a particular behavior creates quite a disturbance: Upon reconnection, all configured sensors are activated immediately. This triggers for example motion sensors, sending a false alert. If you have sophisticated automations running, working with false positives is quite a nuisance. So, how can we prevent this?

This article is a live documentation of my attempts to find the root cause of these problems and to fix them. I will start to investigate the network side first, check that network connectivity is given and that the Docker containers with which both Home Assistant and ESPHome run are properly connected. Then I will consider the ESPHome configuration options to improve WLAN connectivity. Finally, I will research how to configure Home Assistant to prevent the false positives sensor activation when it loses connection to a device.

The technical context of this article is Home Assistant 2024.11 and ESPHome 2024.10, but it should work with newer versions as well.

This article originally appeared at my blog admantium.com.

Home Assistant Timeout Error

What is this timeout error anyway? You can see it in two places. First, in your Home Assistant dashboard, opening a sensor, you can see the message became unavailable, followed by the false positives triggering of the sensor.

Second, you can see disconnect messages inside the log files of your Home Assistant installation. In my case, it’s a Docker container and access the docker logs from this container. But you can also access the logs from the Home Assistant Dashboard.

2024-12-27 10:40:13 WARNING (MainThread) [homeassistant.components.esphome] Can't connect to ESPHome API for None (192.168.3.213): Timeout while waiting for API response!
2024-12-27 10:40:22 WARNING (MainThread) [homeassistant.components.esphome] Error getting initial data for 192.168.3.213: Timeout while waiting for API response!
2024-12-27 10:40:33 WARNING (MainThread) [homeassistant.components.esphome] Can't connect to ESPHome API for None (192.168.3.213): Timeout while waiting for API response!
Enter fullscreen mode Exit fullscreen mode

This message indicates the following error. Home Assistant works with ESPHome controlled devices directly via the API. And when it cannot connect, it assumes the device to be unavailable.

As explained in the introduction, if the connectivity is only disturbed temporarily. But when I look at the history stats of the connected motion sensor, each time the sensor switches back from unavailable, it detects a motion event. An annoying false positive.

cleared (no motion detected)
11:11:58 AM - 3 hours ago
detected motion
11:11:04 AM - 3 hours ago
became unavailable
11:10:56 AM - 3 hours ago
Enter fullscreen mode Exit fullscreen mode

When searching the internet for ESPHome API connection errors from Home Assistant, your will find plenty results! To pinpoint where the error is, I recommend checking things on this order:

  • Network Connectivity
  • WLAN Connectivity
  • ESP Home Configuration
  • Home Assistant Configuration

Let’s start.

Docker Container Connectivity Test

My Home Assistant installation runs as a Docker container. The first thing to check is that the container itself can reach the ESPHome devices IP, e.g. 192.168.3.213. A simple ping is sufficient:

$ ping 192.168.3.213
PING 192.168.3.213 (192.168.3.213) 56(84) bytes of data.
64 bytes from 192.168.3.213: icmp_seq=1 ttl=255 time=2.60 ms
64 bytes from 192.168.3.213: icmp_seq=2 ttl=255 time=2.32 ms
64 bytes from 192.168.3.213: icmp_seq=3 ttl=255 time=6.78 ms
64 bytes from 192.168.3.213: icmp_seq=4 ttl=255 time=2.83 ms
Enter fullscreen mode Exit fullscreen mode

The command works, Home Assistant can reach the devices. To be sure, I also let this command run for several hours: No errors could be seen.

WLAN Connectivity Test

The next test is about checking that the ESP boards are connected properly to the WLAN. Interestingly, ESPHome provides a handy wifi_signal sensor that checks the signal strength in dBm. Just add the following configuration stanza to the ESP device:

sensor:
  - platform: wifi_signal
    name: "WiFi Signal esp8266-02"
    update_interval: 60s
Enter fullscreen mode Exit fullscreen mode

After some time, I saw these results for my three devices

The bottom line shows the board with the motion sensor. It seems connected all the time. But to rule out any measurement error, I put the sensor into a new location, in an unobstructed line-of-sight to the router. And the next day, the chart shows a similar "always connected" state, but with better DBM measurements of course.

Still, the motion sensor log showed the same messages as before.

ESPHome Configuration: Improve Logging Messages

We need more information where the error originates. Each ESPHome device can have different levels of logging output. By setting a very verbose level, you will see detailed information of the boards program. Enabling is simple:

logger:
  level: VERY_VERBOSE
Enter fullscreen mode Exit fullscreen mode

Now log messages provide many more details:

[19:34:02][C][wifi_signal.sensor:009]: WiFi Signal 'WiFi Signal esp8266-01'
[19:34:02][C][wifi_signal.sensor:009]:   Device Class: 'signal_strength'
[19:34:02][C][wifi_signal.sensor:009]:   State Class: 'measurement'
[19:34:02][C][wifi_signal.sensor:009]:   Unit of Measurement: 'dBm'
[19:34:02][C][wifi_signal.sensor:009]:   Accuracy Decimals: 0
[19:34:02][V][wifi_signal.sensor:009]:   Unique ID: '94b97e10625f-wifisignal'
[19:34:09][VV][api.service:327]: on_ping_request: PingRequest {}
....
[19:34:26][V][sensor:070]: 'WiFi Signal esp8266-01': Received new state -50.000000
[19:34:26][D][sensor:120]: 'WiFi Signal esp8266-01': Sending state -50.00000 dBm with 0 decimals of accuracy
[19:34:26][VV][api.service:140]: send_sensor_state_response: SensorStateResponse {
  key: 2237076546
  state: -50
  missing_state: NO
}
Enter fullscreen mode Exit fullscreen mode

With these settings in place, from the ESPHome dashboard, I opened the log from the board. And after some time, I could see these messages:

[10:10:45][VV][api.service:043]: send_ping_response: PingResponse {}
INFO 192.168.3.213: Unexpected error while reading incoming messages: [Errno 104] Connection reset by peer
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/aioesphomeapi/connection.py", line 505, in run_forever
    await self._run_once()
  File "/usr/local/lib/python3.9/dist-packages/aioesphomeapi/connection.py", line 480, in _run_once
    pkt = await self._frame_helper.read_packet()
  File "/usr/local/lib/python3.9/dist-packages/aioesphomeapi/connection.py", line 219, in read_packet
    return await self._read_packet_plaintext()
  File "/usr/local/lib/python3.9/dist-packages/aioesphomeapi/connection.py", line 197, in _read_packet_plaintext
    preamble = await self._reader.readexactly(1)
  File "/usr/lib/python3.9/asyncio/streams.py", line 723, in readexactly
    await self._wait_for_data('readexactly')
  File "/usr/lib/python3.9/asyncio/streams.py", line 517, in _wait_for_data
    await self._waiter
  File "/usr/lib/python3.9/asyncio/selector_events.py", line 856, in _read_ready__data_received
    data = self._sock.recv(self.max_size)
ConnectionResetError: [Errno 104] Connection reset by peer
INFO Disconnected from ESPHome API for 192.168.3.213
WARNING Disconnected from API
INFO Successfully connected to 192.168.3.213
Enter fullscreen mode Exit fullscreen mode

This is very precise: Connection reset by peer. The boards connection was reset. It might by a WIFI problem after all.

ESP Home Configuration: Board and WIFI Settings

Ok, so the ESP board loses its WIFI connection. This problem, and the above mentioned Home Assistant error log message Timeout while waiting for API response! lead to several solution suggestions. For completeness, and for others who have similar problems, I document them all here, but directly indicate what did not help in my case.

Use the most Recent Arduino Framework Version (No Effect)

According to a thread, Arduino libraries could be the source of the error. Unbeknown to me, you can define which version of the PlattformIO espressif8266 framework is used during compilation. See the available tags and add them to your configuration as shown:

esphome:
  name: esp8266-01
  platform: ESP8266
  board: d1_mini
  arduino_version: espressif8266@3.2.0
Enter fullscreen mode Exit fullscreen mode

In an old thread, users were downgrading their ESPHome version because the disconnects just started to appear after an update. I could not see any change whatever version I used.

Add a Delay Function (No Effect)

This comment suggested to add a small delay function that runs continuously in the background. This looks as follows:

esphome:
  name: esp8266-02
  platform: ESP8266
  board: d1_mini
  on_loop:
    then:
      - lambda: delay(15);
Enter fullscreen mode Exit fullscreen mode

Enable Fast Connect, Disable Power Save Mode, Set DNS (No Effect)

There are also two recent and still open GitHub issues: Warning: Disconnected from API and API constantly disconnecting. Following these threads, I saw the change the network settings to include DNS entries and disable power save mode for the WIFI connection. The resulting config is this:

wifi:
  fast_connect: on
  power_save_mode: none
  manual_ip:
    dns1: 192.168.69.11
Enter fullscreen mode Exit fullscreen mode

WLAN Connectivity (Again)

The final thing I investigated is literally back to the beginnings. This thread suggested that disconnects happen when the WIFI router switches channels, and [in this thread](https://community.home-assistant.io/t/esphome-all-devices-periodically-disconnect-see-log-details/222098/ periodically reconnects were observed related to the router changing the WIFI channel.

At my place, its rather noisy with neighboring WIFI’s, so the outer is configured to switch to the best available channel for preventing package collisions. So, I changed the channel to a fixed one. Almost immediately, I could see a familiar error message in the ESP Home logs!

[09:25:45][VV][api.service:043]: send_ping_response: PingResponse {}
[09:26:08][W][wifi_esp8266:466]: Event: Disconnected ssid=[redacted] bssid=[redacted] reason='Beacon Timeout'
INFO 192.168.3.213: Unexpected error while reading incoming messages: 0 bytes read on a total of 1 expected bytes
Enter fullscreen mode Exit fullscreen mode

And furthermore, looking into the Home Assistant History chart, I could see across all ESP boards and sensor this single disconnect event!

I found the culprit! Switching to a fixed channel solved the disconnect problem!

Home Assistant Configuration

With the network connectivity error solved, I only need to find a way of preventing any false positives when the sensor becomes unavailable for other reasons, like an OTA update or when my router is reset.

Essentially, the unavailable event should not trigger the detected motion event as shown in this log:

11:26:22 AM - 3 hours ago
became unavailable
11:26:20 AM - 3 hours ago
detected motion
11:26:02 AM - 3 hours ago
became unavailable
Enter fullscreen mode Exit fullscreen mode

As almost all things in Home Assistant, you can configure this as well. In this Home Assistant community thread, a user suggested to change the behavior of the built-in history stats component so that it immediately resolves the unavailable state. Simply expressed, this means to change the event "entity became unavailable" event to "immediately "ignore this unavailability ".

To achieve this, add this to your configuration.yaml:

# note: add double brackets around the start/end expressions
sensor:
  - platform: history_stats
    name: Ignore
    entity_id: binary_sensor.esp01_motion
    state: "unavailable"
    type: time
    start: "now()"
    end: "now()"
Enter fullscreen mode Exit fullscreen mode

The next day, I was very happy: No more unavailable triggers, only true positives when I moved in front of the sensor. The problem was finally solved.

Conclusion

False positives alarms of sensor are annoying, especially when you have complex automations in places. To find the root source of this error, I systematically investigated four areas: Network connectivity, WIFI connectivity, ESPHome configuration and Home Assistant configuration. From the many potential error sources, and their solutions, here is what worked in my case: First, ensure that all boards are configured with static IP addresses and the WIFI routers 2.4 GHz network is available on a fixed channel. Second, add a custom configuration for Home Assistants History stat component to immediately ignore a motions sensor unavailable state. I hope this article is helpful to you too.

Top comments (0)