XML ‘parsing’ using only Bash

I’m working on setting up my wireless router (running OpenWRT) as an ethernet-to-xBee gateway:
xBee router
The basic plan is just to connect an xBee module to one of the serial ports (which run at 3.3v anyway), and write a smaller daemon to pass things back and forth. As a test, I hooked up my Terrorism Threat Alert system, but I didn’t want to install Python on the poor router just to run one little program. Instead, I just wrote a script to grab the latest threat level using wget and pull out the current level. Once it has the right level, it outputs the appropriate command to the serial port that the xBee is attached to (/dev/ttyS1), and the rest is magic. One missing feature from the current script is a way to set the serial port communication settings. For that, I need stty, which does not appear to be part of the OpenWRT distro for now. As a work around, I run minicom once after booting the router, use that to set everything up, and then close it without resetting the port.

To automate the script, I set up a cron job to run it every half hour. All together, I get nearly the same functionality as my Python version in only a few lines of code and a much lower overhead. Cool, I think, but I ended up feeling kind of dirty for using shell scripts to do such things. Source code follows.

Here is the script (I named it tta.sh, and put it in /usr/local.bin):

#!/bin/sh
# Determine the current U.S. Terrorist Threat Advisory level, and output it to
# a serial device
#
# Written by Matt Mets in 2008
# This code is released into the public domain, attribution is appreciated

#### Configuration Options ##############################################

# Location of the threat alert level XML document
SRC_URL="http://www.dhs.gov/dhspublic/getAdvisoryCondition"

# Serial device to output the result to
TTY_DEV="/dev/ttyS1"

#########################################################################

# Retrieve the current threat level
# We are expecting something like:
# <?xml version="1.0" encoding="UTF-8" ?>
# <THREAT_ADVISORY CONDITION="ELEVATED" />
ALERT_DOC=`wget ${SRC_URL} -q -O -`

# Do some rudimentary parsing using regular expressions to isolate the current
# threat level
# TODO: can this be done in one pass?
TMP=${ALERT_DOC#*CONDITION\=\"}
ALERT_LEVEL=${TMP%\" *}

# Convert the output into a serial command
# (The current system expects just a number 1-5)
case ${ALERT_LEVEL} in
    SEVERE)     COMMAND=5 ;;
    HIGH)       COMMAND=4 ;;
    ELEVATED)   COMMAND=3 ;;
    GUARDED)    COMMAND=2 ;;
    LOW)        COMMAND=1 ;;
esac

# If a threat level was retrieved, output it to the device
if [ -n ${COMMAND} ]
then
    # Send the command to the serial port (-n supresses the newline character)
    echo -n ${COMMAND} > ${TTY_DEV}
    exit 0
else
    exit 1
fi

And the cron entry:

0,30 * * * * /usr/local/bin/tta.sh
This entry was posted in tech. Bookmark the permalink.

One Response to XML ‘parsing’ using only Bash

  1. Pingback: 10 minute project: Traffic counter for router | C i b o M a h t o . c o m

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>