Shelly 2.5: Flash ESPHome Over The Air!

It's no secret that I'm a fan of Shelly products to automate various devices in my house. They're well built, tiny and rock solid, and best of all: compatible with ESPHome.

I flashed ESPHome onto all my Shelly 1's, but for some reason, I have issues with my Shelly 2.5 devices... Here's how I flashed ESPHome onto them over-the-air. No wires!

My problems with the Shelly 2.5

Shelly devices usually have exposed programming pins that you can use to attach a USB-to-UART adapter (through the TX and RX pins). That's how I flashed my Shelly 1 units. However, the Shelly 2.5 is problematic.

First up: the pins are smaller than regular Dupont pins (the ones you find on practically every micro-controller board). That means you have to use special adapter (which is outrageously expensive) or a stripped ethernet cable or female-to-female jumper wires.

These options are ugly and impractical. I tried using needles, which fit the holes, but I couldn't get the Shelly into download mode.

I gave up on it and used the default firmware instead. Then, weeks later, I found a workaround to flash them over-the-air. No need for me to take my Shelly's out the wall again. Cool!


Here's what we'll do:

Let's get going!

Creating an ESPHome configuration

I'll start by creating an ESPHome configuration for the Shelly 2.5. As usual, there's already one available on I'm using the second one which includes protection against drawing too much current & over-temperature.

Here's my configuration (slightly adapted to expose 2 lights to Home Assistant):

  devicename: shelly_25_bathroom
  # Name for the relays
  channel_1: Light 1
  channel_2: Light 2
  max_power: "2000.0" # watt
  max_temp: "80.0" # °C

  name: ${devicename}
  platform: ESP8266
  board: esp01_1m

  ssid: !secret wifi_iot_ssid
  password: !secret wifi_iot_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
    ssid: ${friendly_name} AP
    password: !secret esphome_fallback_ap_password


# Enable logging

# Enable Home Assistant API
  password: !secret esphome_api_password

  password: !secret esphome_api_password

  sda: GPIO12
  scl: GPIO14

  - platform: ade7953
      name: ${devicename} voltage
      name: ${channel_2} current
      internal: true
      name: ${channel_1} current
      internal: true
      name: ${channel_2} power
      id: power_channel_2
        - multiply: 1
        - above: ${max_power}
            - switch.turn_off: shelly_relay_2
            - homeassistant.service:
                service: persistent_notification.create
                  title: Message from ${devicename}
                  message: Switch turned off because power exceeded ${max_power}W
      name: ${channel_1} power
      id: power_channel_1
        - multiply: -1
        - above: ${max_power}
            - switch.turn_off: shelly_relay_1
            - homeassistant.service:
                service: persistent_notification.create
                  title: Message from ${devicename}
                  message: Switch turned off because power exceeded ${max_power}W
    update_interval: 30s

  # NTC Temperature
  - platform: ntc
    sensor: temp_resistance_reading
    name: ${devicename} temperature
    unit_of_measurement: "°C"
    accuracy_decimals: 1
    icon: "mdi:thermometer"
      b_constant: 3350
      reference_resistance: 10kOhm
      reference_temperature: 298.15K
      - above: ${max_temp}
          - switch.turn_off: shelly_relay_1
          - switch.turn_off: shelly_relay_2
          - homeassistant.service:
              service: persistent_notification.create
                title: Message from ${devicename}
                message: Switch turned off because temperature exceeded ${max_temp}°C
  - platform: resistance
    id: temp_resistance_reading
    sensor: temp_analog_reading
    configuration: DOWNSTREAM
    resistor: 32kOhm
  - platform: adc
    id: temp_analog_reading
    pin: A0

    number: GPIO0
    inverted: yes

  - platform: gpio
    pin: GPIO4
    id: shelly_25_relay_1
  - platform: gpio
    pin: GPIO15
    id: shelly_25_relay_2

  - platform: binary
    name: "${channel_1}"
    output: shelly_25_relay_1
    id: lightid1
  - platform: binary
    name: "${channel_2}"
    output: shelly_25_relay_2
    id: lightid2

  - platform: gpio
      number: GPIO13
    name: "${channel_1} input"
    internal: true
        - light.toggle: lightid1
  - platform: gpio
      number: GPIO5
    name: "${channel_2} input"
    internal: true
        - light.toggle: lightid2

  # Prevent short circuit with "floating" pin!
  - platform: gpio
    pin: GPIO16
    name: "ade7953 IRQ pin"
    internal: true

I found that the maximum temperature of 70°C is a bit low. My units reach that temperature quickly with a relatively small load (about 30-50W), so I increased the limit to 80°C.

I'm using the ESPHome add-on for Home Assistant. To compile the firmware, head over to your configuration, click the 3 dots and click "Compile".

After compilation, click "Download binary" to get the .bin file:

Flash intermediate firmware

Next up: flashing Tasmota onto the Shelly over-the-air.

I'm using an open-source tool called mg2x which converts the Shelly from running Mongoose OS to Tasmota. It supports the following models:

Start by finding the IP address of your Shelly device. I did this through my router, but you can also use the Shelly's native firmware.

Once you have that, navigate to this URL:


Pay attention: the URL depends on your Shelly device. The above is valid for the Shelly 2.5. Check the mg2x README for a list of alternative URLs for other Shelly devices.

You should see the following JSON document as response:

  "status": "updating",
  "has_update": false,
  "new_version": "20200812-091015/v1.8.0@8acf41b0",
  "old_version": "20200601-122849/v1.7.0@d7961837"

The Shelly will now download the intermediate firmware, which in turn will download and flash Tasmota. This took about 2 minutes.

Configure Tasmota

Next up, we have to configure Tasmota. Make sure your computer is physically near the Shelly and scan for WiFi networks. There should be a tasmota-XXXXX network. Connect to it.

In my case, macOS showed a popup with Tasmota's captive portal. If this doesn't happen on your computer, navigate to the Shelly 2.5 directly:

Fill in your WiFi network name (SSID) and password. Then, scroll down and click "Save".

The Shelly will now attempt to connect to your WiFi network. Make sure you do the same on your computer.

Browse to the IP address of your Shelly and you should see the default Tasmota page. No point in configuring the module. We're going to ESPHome!

Before we can upload ESPHome, we have to disable Tasmota's firmware check. By default, it only allows you to flash other Tasmota builds (that's a safety feature).

To do that, go to "Console" and type in this command, followed by return:

SetOption78 1

Tasmota will confirm the change:

Now we can flash our ESPHome firmware.

Go back to the main screen and click on "Firmware Upgrade". Upload your ESPHome firmware and click "Start upgrade".

ESPHome is now being flashed. This process takes about a minute.

After a short wait, head over to your Home Assistant installation and check your notifications. My device was automatically discovered:

Click "Configure" and follow the onboarding process of Home Assistant. Easy!

All the necessary entities should now have been created in Home Assistant. Here are my living room lights as an example:

Problem: no energy monitoring

As you can see from the screenshot above, the energy monitoring doesn't work, even though the ADE7953 power sensor, is correctly configured.

In the logs I could see that ESPHome detected no i2c devices, and even threw NACK errors when trying to talk to the sensor:

[15:35:58][C][i2c:028]: I2C Bus:
[15:35:58][C][i2c:029]:   SDA Pin: GPIO12
[15:35:58][C][i2c:030]:   SCL Pin: GPIO14
[15:35:58][C][i2c:031]:   Frequency: 50000 Hz
[15:35:58][I][i2c:033]: Scanning i2c bus for active devices...
[15:35:58][I][i2c:049]: Found no i2c devices!

[15:40:39][W][i2c:070]: Received NACK on transmit of address 0x38
[15:40:39][W][i2c:070]: Received NACK on transmit of address 0x38
[15:40:39][W][i2c:070]: Received NACK on transmit of address 0x38
[15:40:39][W][i2c:070]: Received NACK on transmit of address 0x38
[15:40:39][W][i2c:070]: Received NACK on transmit of address 0x38

I tried power-cycling the Shelly with the Restart Switch in ESPHome, to no avail. I then submitted a bug report on GitHub.

It seems like the power sensor is going in a sleep mode and can't be woken up.

Ultimately, someone suggested to properly power-cycle the Shelly. I installed mine behind a light switch and I didn't want to open that up again. So instead, I toggled my circuit breaker off and on:

Sure enough, the Shelly now reports the correct power stats for each relay, along with the voltage it receives.

I hope you found this tutorial helpful. Let me know in the comments if you run into issues or you have suggestions.

Problem: potential short-circuit & fire hazard

You might have noticed that I create a "useless" binary sensor in the configuration file:

  - platform: gpio
    pin: GPIO16
    name: "ade7953 IRQ pin"
    internal: true

This is very important. Please do not remove it! It configures the IRQ pin of the energy monitoring chip in the Shelly. Without it, your device will heat up significantly!

Thanks to GuestGregor for pointing this out!

Posted on

You May Also Enjoy

Subscribe to my newsletter

Monthly newsletter with cool stuff I found on the internet (related to science, technology, biology, and other nerdy things)! Check out past editions.