OpenWRT Monitor

I had an issue with OpenWRT. The problem ended up being in a strange one-off configuration item I made. But the data collection in the process of debugging it was pretty useful (I think). So I’m going to take a few minutes to share the process. This could be useful for many routers or server monitors.

Firstly, these were my goals:

  • I don’t want HA to have my router password. HA might be more secure than my personal computer, but it feels weird to have the server know the passwords or have ssh keys for other servers.
  • I want to read basic information, like uptime, load, and memory usage from the router.
  • My setup has two OpenWRT routers and I have a Linux machine as my daily driver.

Main Script:

The big idea is to use hass-cli to publish a state value that I get from an automatic ssh command from a Linux machine to the router. This script does these things:

  1. ssh’es into the router
  2. Runs a diagnostic command, like uptime.
  3. Uses python to parse the response from that command to extract the number.
  4. Uses hass-cli to publish that state to an input number value in home assistant.

openwrt-stats.sh:

#!/usr/bin/env bash
export HASS_SERVER=http://X.X.X.X:8123
export HASS_TOKEN=redacted

PATH=/home/jeffeb3/.local/bin:$PATH
UPTIME_TEXT=`ssh [email protected] uptime`
UPTIME=`echo $UPTIME_TEXT | /home/jeffeb3/src/openwrt-hass/uptime_to_minutes.py`
hass-cli service call input_number.set_value --arguments entity_id=input_number.openwrt_downstairs_uptime,value=$UPTIME

This is a bash script. Before you run this, you should be able to do ssh root@router-ip uptime and get a response like: 13:49:27 up 1 day, 5:25, load average: 0.32, 0.28, 0.25. The UPTIME_TEXT is set to that result and passed to the uptime_to_minutes.py script, which returns a number of minutes.

The python script will get that text in stdin and parse it for the uptime and convert it to an integer amount of minutes.

uptime_to_minutes.py:

#!/usr/bin/env python3

import sys

def getMinsFromTime(number, unit):
    if unit == 'min,':
        return int(number)
    else:
        hours, minutes = [int(x.strip(',')) for x in number.split(':')]
        return hours * 60 + minutes

def getMins(words):
    if words[3] == 'day,' or words[3] == 'days,':
        days = int(words[2])
        mins = days * 24 * 60 + getMinsFromTime(words[4], words[5])
    else:
        mins = getMinsFromTime(words[2], words[3])
    return mins

for line in sys.stdin:
    words = line.strip().split()
    if len(sys.argv) == 1:
        print(getMins(words))

Then that returns to the bash script. The hass-cli line pushes that integer number of minutes to home assistant in the state: input_number.openwrt_downstairs_uptime. You have to make that input number first as a helper in the settings.

I would really like some of the stats from the router to be available without root permissions. Ideally, as a public facing json object. Using python requests to grab the stats directly from home assistant without giving home assistant credentials to my router would be awesome. But this worked for the issue I was trying to debug. YMMV.

So… you’re reinventing SNMP? Something that’s been around since 1988, supports Read-Only credentials and is supported by HA and a majority of network equipment?

1 Like

“Reinventing Standards” was my nickname in high school!

Joking aside, I didn’t think SNMP did this. I will have to look into it. Thanks for the tip. (Maybe be less snarky next time though).

Lol, fair enough. :wink: Usually devices/software have a published MIB detailing what stats are available. Some are quite detailed. There are also many utilities for browsing the available data.