Pachube Bandwidth Monitor

I recently discovered Pachube. Pachube is basically the YouTube of the graphing world. You create the data, and then send it up to Pachube to be plotted.

I use both DDWRT and OpenWrt firmwares on my routers around the house. They both are Linux based, running the 2.6 Kernel. I wanted to log the bandwidth use in the the house on an hourly basis, but neither firmware provides an easy way to measure it. I wrote this script to parse /proc/net/dev for the data for the appropriate interface and send this to Pachube. This script averages the difference between two interval across the whole interval. I may rewrite this using environmental variables so that it can be used with cron, but at the moment it works for me and I'm happy with it. I'm also aware this could be done more efficiently in Perl, but I kept it in BASH because these devices only have 4MB of ROM, and do not have space for the Perl binaries.

Setup Instructions:

  • Create a new Pachube feed with two parameters; ID 0 being upload and ID 1 being Download.
  • Personalise the script below and upload to your router as bandwidth.sh
  • Grant the script permission to execute:
    chmod +x bandwidth.sh
  • Run the script in the background:
    sh bandwidth.sh &
#!/bin/bash

# variables

#sleeptime in seconds
#dont set too low or you may exceed the pachube api rate limit
sleep=60

#wan interface varies from device from device
#ifconfig should show you
net_iface=vlan2

#pachube details
pachube_api_key="API_KEY"
pachube_feed="0000"

eval `cat /proc/net/dev | grep $net_iface | cut -d ':' -f 2 | awk '{print "rx_old="$1";tx_old="$9}'`

while [ 1 ]
do
        sleep $sleep
        eval `cat /proc/net/dev | grep $net_iface | cut -d ':' -f 2 | awk '{print "rx="$1";tx="$9}'`
        let tx_diff=$(((((($tx-$tx_old))/1024))/$sleep))
        let rx_diff=$(((((($rx-$rx_old))/1024))/$sleep))
        curl --request PUT --header "X-PachubeApiKey: "$pachube_api_key --data $tx_diff,$rx_diff "http://www.pachube.com/api/"$pachube_feed".csv"
        tx_old=$tx
        rx_old=$rx
done

Live graphs from my router at home:

6 thoughts on “Pachube Bandwidth Monitor

  1. Could I use the above code to run on my router to output data to pachube from /dev/tts/1 at the moment I see data only by cat < /dev/tts/1 router (WRT54GL) is running Firmware: DD-WRT v24-sp2 (07/22/09) mini has following space left

    Total Available
    80%
    13028 kB / 16384 kB
    Free
    20%
    2544 kB / 13028 kB
    Used
    80%
    10484 kB / 13028 kB
    Buffers
    13%
    1368 kB / 10484 kB
    Cached
    41%
    4272 kB / 10484 kB
    Active
    38%
    3976 kB / 10484 kB
    Inactive
    16%
    1684 kB / 10484 kB

    Space Usage
    JFFS2
    896.00 KB / 196.00 KB

    any help welcome !

    Jean

    • Hi Jean,

      I assume you are trying to read something like the output from a CC128 and upload it to Pachube?

      I wrote this a good while ago, and haven't used it since, but it might be what you need.

      The script essentially runs as a daemon listening for input from the CC128.
      The CC128 spits out data far too frequently, so it saves the values to a file, and ever so often, it averages these values and uploads to Pachube.

      Have a play around with it yourself.

      head is used to read the input, sed is used to filter and extract the XML.
      awk is used to average the values, and curl used to send the data to Pachube.
      catting /dev/null is just to empty the file.

      #!/bin/bash
      
      # variables
      pachube_api_key="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
      pachube_feed="12345"
      
      stty -F /dev/ttyS0 57600
      touch /tmp/cc128
      while [ 1 ]
      do
      	head /dev/ttyS0 -n150 | sed -n 's/.*([^<]*).*/1/p' >> /tmp/cc128
      	eval `awk '{total+=$0;n++}END{print "export WATTS="total/n}' /tmp/cc128`
      	curl --request PUT --header "X-PachubeApiKey: "$pachube_api_key --data $WATTS "http://www.pachube.com/api/"$pachube_feed".csv"
      	cat /dev/null > /tmp/cc128
      done
      

      EDIT: bits seem to have got clipped, so I've posted on gist instead. :)

      Regards,
      Jon

  2. my output controlled by what i print from the arduino to dev/tts/1 at the moment it looks like this 20.0,20.0,20.0,20.0,15.6,1 so 6 feeds each with a value I can pass the whole string at once as data. but how ? cat < /dev/tts/1
    then what ?

  3. Thanks for the great start.

    This is expanded a bit and uses wget.

    D-Link DIR-825 rev. B1
    OpenWrt Backfire 10.03.1 / LuCI 0.10.0 Release (0.10.0)

    See: https://pachube.com/feeds/48835

    Uses the following bash script. Name it /usr/sbin/pachube.sh & put this in the the Local Startup box under System/Startup.
    "sh /usr/sbin/pachube.sh &" (without the quotes)

    Don't forget to add it to the "Configuration" box under "System"/"Backup/Flash Firmware"

    #!/bin/bash
    #based on work from http://dereenigne.org/computers/openwrt-ddwrt/pachube-bandwidth-monitor

    #N.B. Your must install wget or wget-nossl. The busybox version doesn't work. CURL is easier but very big.

    # variables

    #sleeptime in seconds
    #dont set too low or you may exceed the pachube api rate limit
    sleep=30

    #wan interface varies from device from device
    #ifconfig should show you
    net_iface=wan

    #pachube details
    pachube_api_key=""
    pachube_feed=""

    eval `cat /proc/net/dev | grep $net_iface | cut -d ':' -f 2 | awk '{print "rx_old="$1";tx_old="$9}'`

    while [ 1 ]
    do
    sleep $sleep
    eval `cat /proc/net/dev | grep $net_iface | cut -d ':' -f 2 | awk '{print "rx_now="$1";tx_now="$9}'`
    let tx_rate=$((((($tx_now-$tx_old)*8))/$sleep))
    let rx_rate=$((((($rx_now-$rx_old)*8))/$sleep))
    let rx_megs=$(($rx_now/1048576))
    let tx_megs=$(($tx_now/1048576))
    let rx_tx_ratio=$(($rx_now/$tx_now))
    echo -e "RateTx,"$tx_rate"\nRateRx,"$rx_rate"\nTotalTx,"$tx_megs"\nTotalRx,"$rx_megs"\nRatioRxTx,"$rx_tx_ratio > /tmp/dtxdrx.txt
    wget --quiet \
    --header="X-PachubeApiKey: $pachube_api_key"\
    --header="X-Http-Method-Override:put" \
    --post-file /tmp/dtxdrx.txt http://api.pachube.com/v2/feeds/$pachube_feed.csv \
    --timeout=10 \
    --output-document=/tmp/wget_output
    tx_old=$tx_now
    rx_old=$rx_now
    done

    • Hi GoldEye,

      Thanks for posting a new version!
      I have actually moved away from this script and now monitor my bandwidth on the router from another machine using muninlite and vnstat.

      Regards,
      Jon

Leave a Reply