Sonoff S26 OTA not working

I’ve just received some Sonoff S26 power plugs and I flashed the ESPHome firmware using UART. Everything works fine besides the OTA update. The OTA update always fails after transfering about 30% of the firmware.

I’m using the esphome Docker image to compile and transfer the firmware and the esphomeflasher for the UART update. Here is the yaml configuration of my device:

esphome:
  name: sonoff01
  platform: ESP8266
  board: esp01_1m

wifi:
  domain: .mydomain
  networks:
    - ssid: "MYWIFI"
      bssid: "XX:XX:XX:XX:XX:XX"
      password: !secret MYWIFIPASSWORD

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Sonoff01 Fallback Hotspot"
    password: !secret CAPTIVE_PORTAL_PASSWORD

mqtt:
  broker: 172.17.2.21
  client_id: sonoff01
  discovery: True
  birth_message:
    topic: sonoff01/availability
    payload: online
  will_message:
    topic: sonoff01/availability
    payload: offline

api:

logger:

ota:
  password: !secret OTA_PASSWORD

binary_sensor:
- platform: gpio
  pin:
    number: GPIO0
    mode: INPUT_PULLUP
    inverted: True
  name: "Sonoff S20 Button"
  on_press:
    - switch.toggle: relay
- platform: status
  name: "Sonoff S20 Status"

switch:
- platform: gpio
  name: "Sonoff S20 Relay"
  pin: GPIO12
  id: relay

output:
- platform: esp8266_pwm
  id: s20_green_led
  pin: GPIO13
  inverted: True

light:
- platform: monochromatic
  name: "Sonoff S20 Green LED"
  output: s20_green_led

This is the output of esphome during OTA update:

INFO Uploading /config/sonoff01/.pioenvs/sonoff01/firmware.bin (424416 bytes)
Uploading: [============================================================] 100% Done...

INFO Waiting for result...
ERROR Error receiving acknowledge receive OK: timed out

And here is the output from the device log during an OTA update:

[12:53:02][D][ota:072]: Starting OTA Update from 172.17.128.204...
[12:53:02][D][ota:243]: OTA in progress: 0.2%
[12:53:03][D][ota:243]: OTA in progress: 5.0%
[12:53:04][D][ota:243]: OTA in progress: 9.9%
[12:53:06][D][ota:243]: OTA in progress: 14.7%
[12:53:07][D][ota:243]: OTA in progress: 19.5%
WARNING Disconnected from API: Timeout while waiting for message response!

I’ve already tried setting a static ip and I also tried the “dev” Docker image, but the OTA update still fails. I’ve also tried setting board: esp8285 and arduino_version: 2.4.2, but that does also not work.

The strange thing is that during the update the whole transfer seems to happen in under one second, but the “OTA in progress” logs are coming in very slowly. My best guess would be that the esphome OTA update timeout is set to low and breaks the connection while the device is still under 50% of the update.

Does anyone else have this problem and is there a way to fix this?

I’ve had that occasionally with my D1 Minis. Try a power cycle: no idea why that works but it solved it for me. To avoid that in future, put a restart switch in your config and you can reboot it from HA.

The timeout is when there’s been no communication for a few seconds. If it’s slow but consistent it should still work.

@Troon I’ve already tried this several times, but that does not change anything. I did just take a quick look at the esphome Python files and I found a socket timeout in the /usr/src/app/esphome/espota2.py file that was set to 20 seconds. I’ve now just increased this timeout to 120 seconds in my docker container and now the OTA update works fine.

Is this a known problem or should I report this on GitHub?

Glad you’ve fixed it. Report it if you like as it’s clearly an issue for you. That 20s timeout has been in place for a while, looking at the Github source.

Ok I will report this on GitHub. In the meantime this Dockerfile can be used as a workarround:

FROM esphome/esphome
RUN   sed -i "s|sock.settimeout(20.0)|sock.settimeout(120.0)|g" /usr/src/app/esphome/espota2.py
RUN   sed -i "s|sock.settimeout(10.0)|sock.settimeout(120.0)|g" /usr/src/app/esphome/espota2.py

Just put this text into an empty Dockerfile and create a new image with docker build -t esphome_sonoff --pull .
After that just use esphome_sonoff as image name to start the container instead of esphome/esphome and the upload should work.

I’ve just created an Issue on GitHub regarding this problem: https://github.com/esphome/issues/issues/1951