Modem Power Level Graphing

I wanted to monitor the downstream and upstream power levels on my Scientific-Atlantic modem (provided by my ISP). My intended goal was to keep logs of the power levels and if my modem “froze” then I could go back to the logs and look for any abnormal power levels.

At first, I just logged the power levels to a simple text file. This worked, but the aggressive logging I was doing generated a lot of data. I thought it’d be nice to see how the power levels changed throughout the day.

The following emerged:

Logging Script (python)

#!/usr/bin/env python2

import urllib2
from BeautifulSoup import BeautifulSoup
from lxml import etree
from StringIO import StringIO
import sys
import datetime

URL = 'http://192.168.100.1/system.asp'

def timestamp():
    now=datetime.datetime.now()
    return now.strftime("%b %d %H:%M:%S")

def error():
    print "Error"
    return

try:
    page = urllib2.urlopen(URL, timeout=10)
except:
    print timestamp() + ": # dBmV (rx), # dBmV (tx)"
    sys.exit()

soup = BeautifulSoup(page)

# Remove   markups, because they break the XML parser.
f = StringIO(str(soup.findAll('tbody')[0]).replace(' ', ''))

dom = etree.parse(f)
nodes = dom.xpath('//font')
# We take every value we can get, but do not use them, yet
modemvalues = []
for i in xrange(0, len(nodes), 2):
    modemvalues.append((nodes[i].text, nodes[i+1].text.strip()))

rpl = float(modemvalues[5][1].split(' ')[0]) # dBmV
tpl = float(modemvalues[6][1].split(' ')[0]) # dBmV

print timestamp() + ": " + str(rpl) + " dBmV (rx), " + str(tpl) +" dBmV (tx)"

Usage: ./getModemPl.py >> logFile (cron job)

Output:

Nov 06 22:30:41: 0.7 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:31:41: 0.8 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:32:41: 0.9 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:33:41: 0.5 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:34:41: 0.5 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:35:41: 0.5 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:36:41: 0.6 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:37:41: 0.7 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:38:41: 0.7 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:39:41: 0.7 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:40:41: 0.7 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:41:41: 0.6 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:42:41: 0.7 dBmV (rx), 35.4 dBmV (tx)

Graph Generator (takes every 5th log entry)

#!/bin/bash

if [[ ! $1 ]]; then
    echo "No File to Parse"
    exit
fi

startRange=$2
endRange=$3

tmpDir="/tmp"
currentDir="$PWD"
logFile="$1"
data="/tmp/modempowerdata"

# Takes every sample from log File
#cat $logFile | sed 's/.dBmV.(rx),//' | sed 's/.dBmV.(tx)//' | sed 's/: / /'  | perl -pe 's/(.*?)\s(.*?)\s(.*)/$1-$2-$3/;' > $data

# Takes every 5th sample (we log every minute)
cat $logFile | sed 's/.dBmV.(rx),//' | sed 's/.dBmV.(tx)//' | sed 's/: / /'  | sed -n 'p;n;n;n;n;' | perl -pe 's/(.*?)\s(.*?)\s(.*)/$1-$2-$3/;' > $data

date=$(head -1 $logFile | cut -d' ' -f1,2)
date2=$(echo $date | sed 's/ /-/')

png="$currentDir/$date2.png"
svg="$currentDir/$date2.svg"

#rm "$data"

plot=""

cat << EOF | gnuplot
#
# --- gnuplot ---
#
# PNG output
#set terminal png enhanced size 1400,900
set terminal pngcairo size 1200,600 enhanced font 'Verdana,10'
set output "$png"

# SVG Output
#set terminal svg enhanced size 1440,900

# Adds White Background to SVG
set object 1 rect from screen 0, 0, 0 to screen 1, 1, 0 behind
set object 1 rect fc  rgb "white"  fillstyle solid 1.0
#set output "$svg"

# Line Sytes
set style line 1 lc rgb "#8b1a0e" pt 1 ps 1 lt 1 lw 2
set style line 2 lc rgb "#5e9c36" pt 6 ps 1 lt 1 lw 2
set style line 12 lc rgb '#808080' lt 0 lw 1

set timefmt "%b-%d-%H:%M:%S"
set grid
#set grid back ls 12
set key left box
set title "$date - Power Levels"

# X Label
set xdata time
set format x "%H:%M"
#set xlabel "Time"

# Y Data
set ylabel "dBmV (rx)"
#set yrange [-2:2]
#set ytics 0.2
set yrange [-1.6:4.4]
set ytics 0.2

# Y2 Data
set y2range [31:37]
set y2label "dBmV (tx)"
set y2tics 0.2

plot "$data" u 1:2 ls 1 axis x1y1 ti "rx" with lines, "$data" u 1:3 ls 2 axis x1y2 t "tx" with lines

EOF

Notes:

  • Usage: ./graphModemPower.bash /path/to/logfile
  • Modify yrange and y2range to scale to appropriate power levels for you

Graph:

 

Feel free to use the scripts,  they work for me, and hopefully they work for you. As always, use at your own risk.