Fixing something my ISP couldn't for $10

#home-assistant (1)#esphome (1)
Thumbnail

My modem kept crashing randomly, so I took matters into my own hands.

## Introduction

For context, I have a home cluster consisting of various ARM-based compute modules running k3s and a Synology DS920+ NAS. I try not to run anything user-facing on that cluster, as I cannot guarantee any consistent uptime, but as the only user, I still like having access to my apps most of the time. Unfortunately, I’ve had occasional issues with my ISP-issued modem ever since moving out.

My modem stops working randomly for no apparent reason, causing my router to lose internet connection. I've clicked around its admin panel, which looks like something out of the Stone Age, but I couldn't find any issues. My ISP couldn’t find any problems either. The only solution that seems to work is to power cycle the modem whenever this happens. So, I did something about it.

## The “solution”

When the modem fails, my router loses connection to the internet, but since all my devices are connected to the router and not the modem, they can still communicate. So, suppose I connect the modem to a smart plug that can be controlled through my local network. In that case, I can configure it to automatically power cycle the modem whenever my internet connection is lost for some time. And that’s precisely what I did.

I bought two of these smart plugs from AliExpress (not affiliated), which, funnily enough, appear to be on a fake Black Friday sale at the time of writing this. What I liked about them is that they came pre-flashed with ESPHome, which is convenient as I have a Home Assistant instance on my home server to which I can connect them directly.

The modem plugged into the smart plug
The modem plugged into the smart plug

Setting them up was trivial — all I had to do was plug them in, connect to the Wi-Fi network they created, and input my router’s password in the setup page, after which Home Assistant detected them automatically. As a bonus, these smart plugs also provide me with power consumption information (not that I would be looking at it, but still):

Now, all that’s left is to create an automation that power cycles the smart plug whenever I lose internet, which is surprisingly easy in Home Assistant. First, I need some entity in Home Assistant that monitors my internet connection. Home Assistant has this built-in in the form of the “Ping (ICMP)” integration, which does precisely what the name says.

To create a Ping device, one needs to go to “Settings > Devices & services”, then click “Add integration” and select “Ping (ICMP)”:

Then, you’re prompted to input a host to ping. I personally went with 1.1.1.1 (Cloudflare’s DNS):

When you click “Submit,” you now have a device in Home Assistant that periodically tries to ping the host, updating its state accordingly. You can configure it as any other Home Assistant device. I’ve named mine “Internet” so that I don’t forget why I have it:

As you can see, the grey areas above are periods in which I had no internet, so it appears to be working exactly as advertised. All that’s left is to create an automation using this device’s state as a trigger. Automations are managed from “Settings > Automations & scenes,” and the UI for creating them is pleasant to use, surprisingly. Clicking “Create automation > Create new automation” lands you here:

I created my trigger by clicking “Add trigger > Device” and then selecting the “Internet” device as the device and “Internet disconnected” as the trigger. I put 30 seconds as the duration as a starting point:

I’ll skip the “And if” section, as I do not have any other conditions for the automation to run. Now, I have to define the action. I want the automation to repeatedly power the smart plug off and on with some delay in between until I’ve regained internet access. There are a bit too many clicks and too much vertical screen space needed to show them one by one, so here’s what the final action looks like in YAML:

repeat:
  sequence:
    - type: turn_off
      device_id: 28f696638359548ac56da496e73af839
      entity_id: 9cd05f2529aa5ef2da77062b6c316e17
      domain: switch
    - delay:
        hours: 0
        minutes: 0
        seconds: 10
        milliseconds: 0
    - type: turn_on
      device_id: 28f696638359548ac56da496e73af839
      entity_id: 9cd05f2529aa5ef2da77062b6c316e17
      domain: switch
    - delay:
        hours: 0
        minutes: 5
        seconds: 0
        milliseconds: 0
  until:
    - condition: state
      entity_id: binary_sensor.1_1_1_1
      state: "on" 

All the action does is until I’ve regained internet, it will turn off the modem for 10 seconds, then turn it back on, and recheck after 5 minutes (these modems take a surprisingly long time to boot up). With this automation in place, I no longer need to physically power cycle the modem if this happens again, which is especially convenient for when I’m not home (with my luck, this issue only occurs when I’m not home).