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:

  • Create an ESPHome configuration for the Shelly 2.5 and compile a firmware
  • Use a special firmware to update the Shelly to Tasmota over-the-air
  • Use Tasmota to flash the ESPHome firmware

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:

  • Shelly 1
  • Shelly 1PM
  • Shelly Plug S
  • Shelly 2
  • Shelly 2.5
  • Shelly RGBW2
  • Shelly EM

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

💌 Subscribe to my newsletter

No more than once a month.
No spam, only highlights about my work.