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:
- ssh’es into the router
- Runs a diagnostic command, like
uptime
. - Uses python to parse the response from that command to extract the number.
- 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.