Raspberry Pi and PiGlow Network Monitor (rPiGNeMo)

We’ve had a Raspberry Pi for a couple of years, and I’ve struggled to figure out something to do with it. The most popular projects involve turning it into a media streaming device of some sort, but I’ve already got four devices in my family room with that kind of functionality (Blu-ray player, Apple TV, the TV, and the XBox 360). So the Pi sat in its starter kit box, waiting for a purpose. I kept it close by, hoping to have a fun idea to throw at it.

We are a family that makes heavy usage of our internet connection, from typical e-mail, browsing, and shopping, to Netflix, Pandora, videos and online gaming. It became almost comically frequent that my son would come into the den and ask “Dad, are you downloading something?” or “Dad, are you uploading photos?” because he was not getting the responsiveness he so desired to feed his data addiction. If I knew that I was the cause of the bottle neck, I would tell him so. But sometimes I had to pull up the traffic monitor page on our router to show him that our family connection was largely idle, and that the problem was with his distant game server, and not our local connection.trafficmonitor

I really like the graph that my router provides of our usage, and started to wonder–how could I present that information to my son without giving him the keys to the kingdom (i.e. the router admin password). A few hours of tinkering and hacking later, I was able to extract the raw data from my router with a simple web request.

Hrm, maybe I should put that script on the Rasberry Pi, thought me, and figure out how to display the results compactly. My first inclination was to wire up some sort of LED bank–more lights lit would mean more activity on the router. I started looking into what it would take to make that a reality, and though it was within reach of my skills, it was likely going to look messy when I was done.

So I looked for ready-made LED solutions designed for the Raspberry Pi, and eventually stumbled on the Piglow. The Piglow’s triple spiral-arm of LEDs was enticing, even though I didn’t immediately know how I would represent the data from my router.  I ordered one, and started learning Python.

Python is a relatively straight-forward programming language, but I’ve never had need to dive into it in the past. It is really popular for working with the Raspberry Pi, and comes with the default installation. I won’t go through my slightly tedious learning curve, but I’ll just present to you here the chunks of the code that I used to turn my Raspberry Pi into a network bandwidth monitor. Don’t judge my coding in Python–its my first every Python project.

import urllib2
import re
import time
from piglow import PiGlow
from time import sleep
from time import time

In the first several lines of code, I set up the necessary modules. urllib2 is for the HTTP requests to get data from my router. re is for regular expression evaluations so that I can parse the data from the router response. time is required to keep track of time while doing the calculations. And PiGlow is a module that simplifies how I interface with the PiGlow.

piglow = PiGlow()
download_leds = [6,5,4,3,2,1]
upload_leds = [12,11,10,9,8,7]
timer_leds = [18,17,16,15,14,13]

Above I set up a bunch of variables to get started. I create a piglow object, then define arrays for the LEDs. I decided to make each arm have a different function–one arm for upload, one for download, and then another one to indicate it was waiting between queries. The LED numbers correspond to how they are numbered on the PiGlow, and are in reverse order because I always light them up from the center (high number) to the outside (low number). Next I store the current time, and set my transmission variables. I have 30Mbps internet access, so that corresponds to a theoretical max of 3,750,000 bytes per second download, and 3Mbps upload, or 375,000 bytes. Finally, I have to set up the authentication scheme for my router, specifying the realm, url, username and password. My router happens to be an Asus RT-N16. The code it uses is heavily based on Tomato. Your router just might too!

def light_up(leds,show):
    for x in leds:
    if show > 0:
        for x in range(show):
            if x<= len(leds)-1:

Next up is a function to light up an arm of the PiGlow. It takes two input parameters: an array of the leds to be lit up, and the number of them to be lit. The first step is to go through the list of all the leds in the passed-in array, and set their value to 0 (i.e. off), then sleep for a tenth of a second. Then we go through and light up the LEDs one by one, in order, with a tenth of a second delay. Unfortunately, what I found in testing was that on occasion I would get more bandwidth for a short time than my ‘max’, and as a result, I would pass in a number greater than ‘6’ for the show parameter. So I had to add a bit of logic to handle it in the else clause above. If I end up trying to light up an led beyond what I had in the list (e.g. trying to light led number 7), then I would just blink the 6th led in the arm. The more we exceeded our bandwidth max, the more it would blink. Very cool (sez me).

def countdown():
 for x in range(len(timer_leds)):

One more function before we get to the main loop. Above is my simple countdown timer. I turn off all the leds in arm 3, then turn them on slowly. I just wanted a little bit of code so that I could look at the Pi and know that it was working even if we weren’t consuming much bandwidth.

        while 1:
                if tx_rx != None:
                    if rx_prev!=0 : 
except KeyboardInterrupt:

This is the main loop. It is wrapped in a try statement so that while I was debugging, I could terminate it and turn all the leds off.

First I grab the raw data from my router and store it in rawout. Immediately after grabbing rawout, I send a logout command to the router. I’ve got to do this, otherwise I can’t login to the admin page on the router while the Raspberry Pi is one.

The next several lines of code deal with the contents of rawout, and trying to get something usable from it. The output looks like this.

netdev = {

The usage numbers are put in four categories, and then further broken down into rx (receive) and tx (transmit). For my purposes, I really only care about the Internet numbers, so I pull out the hex numbers after rx: and tx: on the Internet line, and covert them to decimal. That decimal number is the number of bytes processed since I-don’t-know-when. When it was 0 doesn’t really matter to me since all I care about is the delta. Then I do a time check, and calculate how much data has been received/transmitted since the previous check. The result of the bit of math is that, theoretically at least, my rx_diff and tx_diff contain an integer from 0 to 6, giving me an indication of how much bandwidth has been consumed in the previous interval. And with those numbers, I then call the light_up function to light the appropriate number of LEDs on the corresponding arm of the PiGlow. Then I store the current byte counts so that I can use them in the next loop.

Now there is an else clause where I turn on the red LEDs. This will happen if I wasn’t able to find ‘INTERNET’ followed by rx and tx in rawout. This will happen if I’m logged into the web page of the router, or if the router happens to be down. I turn on the red LEDs so that I know something is amiss, but the script will keep on running, and will try again on the next interval. The last step is to perform the count_down function, taking its time before hitting the router again. The whole cycle takes 6-7 seconds, and is just about right for knowing if something is really hammering the network for long periods. But it isn’t so manic that I’m constantly watching just how intense the traffic is.

The last two steps to get this thing fully operational are configuring the wifi (I’ll leave that up to you), and getting the script to run on boot. I followed these instructions to a T. No problems.

Below is a video showing the end result. The RaspberryPiGlowNetworkMonitor (rPiGNeMo for short) runs like a champ and has been rock solid for the last few weeks since I finally deployed it.