With the Project Trailblazer database created, populated with test data, and queried, you are ready to move on to developing the Project Trailblazer target and CGI integration scripts.
The collection and storage of temperature data requires two bash scripts:
temperatureReport— The collection script temperatureReport, shown in Listing 12.2, executes continuously on a target board, periodically communicates with an external temperature sensor, and then reports the temperature value via an HTTP connection. The target board's init program or a startup script starts the temperatureReport script.
temperatureRecord— The database storage script temperatureRecord, shown in Listing 12.3, executes as an on-demand CGI script, receives the temperature value, and then sends a formulated database query to the Project Trailblazer database.
#!/bin/bash # temperatureReport v1.0 12/31/01 # www.embeddedlinuxinterfacing.com # # The original location of this code is # http://www.embeddedlinuxinterfacing.com/chapters/12/ # # Copyright (C) 2001 by Craig Hollabaugh # # This program is free software; you can redistribute it and/or modify # it however you want. # # temperatureReport # temperatureReport is a bash script that executes on a target board # with an external temperature sensor and its module loaded. Loading # the module, such as LM70_x86.o from Chapter 10 creates the # /proc/trailblazer/temperature file. This script gets the current # temperature from /proc/trailblazer/temperature, forms an HTTP GET # query using temperatureRecord with the temperature as the # parameter. This query is piped into nc which makes a TCP connection # to tbdev1's apache HTTP server on port 80. nc is configured with # the -w flag which sets a connection timeout. If tbdev1's apache # server doesn't answer, this script will continue to operate. # # Call this from inittab using the respawn option as in # T3:23:respawn:/usr/bin/temperatureReport # If temperatureReport should die, init will start it again # # loop forever while [ 1 ] do # get temp temperature=`cat /proc/trailblazer/temperature` # form the query and pipe to nc echo "GET /cgi-bin/temperatureRecord?$temperature" | nc -w 10 192.168.1.11 80 # print out temperature echo $temperature # pause for 5 minutes sleep 300 done |
TIP
You can configure the Linux init program to start a target board's bash scripts. If you use the respawn option, init restarts the script when it terminates. This is a simple way to ensure that your scripts are always running. Here's an example line from init's configuration file /etc/inittab to respawn a bash script:
T3:23:respawn:/root/temperatureReport
#!/bin/bash # temperatureRecord v1.0 12/31/01 # www.embeddedlinuxinterfacing.com # # The original location of this code is # http://www.embeddedlinuxinterfacing.com/chapters/12/ # # Copyright (C) 2001 by Craig Hollabaugh # # This program is free software; you can redistribute it and/or modify # it however you want. # # temperatureRecord # temperatureRecord is a CGI script. A field target board sends an # HTTP request with the temperature as a parameter. # Apache calls this script setting the $QUERY_STRING variable to the # temperature and $REMOTE_ADDR variable to the sender's IP address. # This script extracts the last octet of the IP address using it # as the location number in an INSERT statement. # # Here's the header/content blank separation line required by Apache echo # Extract the last octet from the sender's IP address, use this # as for the location number. location=`echo $REMOTE_ADDR | cut -f 4 -d '.'` # Get the temperature sent by the target board temperature=$QUERY_STRING # Form the INSERT statement and pipe it to mysql. # You have to login in to mysql as trailblazer with # password tb because apache will execute this script as # user www-data not root. echo "INSERT INTO temperatures (location,temperature) VALUES ($location,$temperature);" | mysql trailblazer --user=trailblazer --pass=tb |
TIP
The Apache HTTP server sets the following bash environment variables before a CGI script is executed: DOCUMENT_ROOT, HTTP_ACCEPT, HTTP_ACCEPT_ENCODING, HTTP_ACCEPT_LANGUAGE, HTTP_CONNECTION, HTTP_HOST, HTTP_REFERRER, HTTP_USER_AGENT, PATH, REMOTE_ADDR, REMOTE_PORT, SCRIPT_FILENAME, SERVER_ADDR, SERVER_ADMIN, SERVER_NAME, SERVER_PORT, SERVER_SIGNATURE, SERVER_SOFTWARE, SERVER_SOFTWARE, SERVER_PROTOCOL, REQUEST_METHOD, QUERY_STRING, REQUEST_URI, and SCRIPT_NAME. To see some sample values for these variables, go to www.embeddedlinuxinterfacing.com/cgi-bin/environment.
Three bash CGI scripts handle the distribution of stored temperature data via an HTTP connection:
temperatureGetLast— This script, shown in Listing 12.4, accepts a location parameter and returns that location's last recorded temperature.
temperatureGetTable— This script, shown in Listing 12.5, accepts a location parameter and returns a table of that location's recorded temperatures.
temperatureGetPlot— This script, shown in Listing 12.6, accepts a location parameter and returns a portable network graphics (PNG) plot of that location's recorded temperatures.
#!/bin/bash # temperatureGetLast v1.0 12/31/01 # www.embeddedlinuxinterfacing.com # # The original location of this code is # http://www.embeddedlinuxinterfacing.com/chapters/12/ # # Copyright (C) 2001 by Craig Hollabaugh # # This program is free software; you can redistribute it and/or modify # it however you want. # # temperatureGetLast # temperatureGetLast is a CGI script. A field target board or web service # sends an HTTP request with a Trailblazer location number # as a parameter. Apache calls this script setting the $QUERY_STRING # variable to the location number. This script forms a SELECT statement # that returns the last recorded temperature for that location. # # Here's the header/content blank separation line required by Apache echo # Set the location location=$QUERY_STRING # Form the SELECT statement and pipe it to mysql. # You have to login in to mysql as trailblazer with # password tb because apache will execute this script as # user www-data not root. echo "SELECT temperature from temperatures where location = $location order by timestamp desc limit 0,1" | mysql trailblazer --user=trailblazer --pass=tb --silent |
#!/bin/bash # temperatureGetTable v1.0 12/31/01 # www.embeddedlinuxinterfacing.com # # The original location of this code is # http://www.embeddedlinuxinterfacing.com/chapters/12/ # # Copyright (C) 2001 by Craig Hollabaugh # # This program is free software; you can redistribute it and/or modify # it however you want. # # temperatureGetTable # temperatureGetTable is a CGI script. A web service sends an HTTP # request with a Trailblazer location number as a parameter. # Apache calls this script setting the $QUERY_STRING # variable to the location number. This script forms a SELECT statement # that returns a temperature table for that location. # # Here's the header/content blank separation line required by Apache echo # Set the location location=$QUERY_STRING # Form the SELECT statement and pipe it to mysql. # You have to login in to mysql as trailblazer with # password tb because apache will execute this script as # user www-data not root. echo "SELECT timestamp, temperature from temperatures where location = $location order by timestamp asc;" | mysql trailblazer --user=trailblazer --pass=tb --silent |
#!/bin/bash # temperatureGetPlot v1.0 12/31/01 # www.embeddedlinuxinterfacing.com # # The original location of this code is # http://www.embeddedlinuxinterfacing.com/chapters/12/ # # Copyright (C) 2001 by Craig Hollabaugh # # This program is free software; you can redistribute it and/or modify # it however you want. # # temperatureGetPlot # temperatureGetPlot is a CGI script. A web service sends an HTTP # request with a Trailblazer location number as a parameter. # Apache calls this script setting the $QUERY_STRING variable # to the location number. This script forms a SELECT statement # that returns a table of record temperatures for the location. The # script then calls gnuplot to plot these temperatures, creating # and outputting a png image. # # Here's the Content-type line to tell the browser that this reply # is a png image. echo Content-type: image/png # Here's the header/content blank separation line required by Apache echo # Set the location location=$QUERY_STRING # Form the SELECT statement and pipe it to mysql. # You have to login in to mysql as trailblazer with # password tb because apache will execute this script as # user www-data not root. Redirect the output to a temp file. echo "SELECT timestamp, temperature from temperatures where location = $location order by timestamp asc;" | mysql trailblazer --user=trailblazer --pass=tb --silent > /tmp/tempdata # Query the database for the location description for use in plot title locationdes=`echo "SELECT description from locations where location = $location;" | mysql trailblazer --user=trailblazer --pass=tb --silent` # Execute gnuplot, send various commands to set up plot, then plot # the temperatures from the temp data file. See http://www.gnuplot.vt.edu/ # for more gnuplot information. /usr/bin/gnuplot << ENDOFINPUT set terminal png color set xdata time set timefmt "%Y%m%d%H%M%S" set format x "%m/%d %H:%M" set nokey set title "$locationdes Temperature" set ylabel "Temperature (F)" set xlabel "Date - Time" set grid set rmargin 5 plot "/tmp/tempdata" using 1:2 with linespoints ENDOFINPUT |
Because the Project Trailblazer database was generated with test data (refer to Listing 12.1), you can test the temperatureGetLast, temperatureGetTable, and temperatureGetPlot scripts. You can use the following commands to download and test these scripts on tbdev1:
root@tbdev1[514]: cd /usr/lib/cgi-bin root@tbdev1[515]: wget http://www.embeddedlinuxinterfacing.com/chapters/12/ temperatureGetLast root@tbdev1[516]: wget http://www.embeddedlinuxinterfacing.com/chapters/12/ temperatureGetTable root@tbdev1[517]: wget http://www.embeddedlinuxinterfacing.com/chapters/12/ temperatureGetPlot root@tbdev1[518]: chmod 755 /usr/lib/cgi-bin/temp* root@tbdev1[519]: echo "GET /cgi-bin/temperatureGetLast?30" | nc 192.168.1.11 80 30 root@tbdev1[520]: echo "GET /cgi-bin/temperatureGetTable?30" | nc 192.168.1.11 80 20011229000000 32 20011229040000 10 20011229080000 15 20011229120000 20 20011229160000 25 20011229200000 27 20011230000000 30
You need to use a browser to test temperatureGetPlot because it returns a PNG plot. Enter this URL in your browser:
http://192.168.1.11/cgi-bin/temperatureGetPlot?30
You should see the plot shown in Figure 12.2. Notice in this figure that when you queried for location 30 (which is Lift 1 Base), the temperatureGetPlot script correctly generated the plot's title, Lift 1 Base Temperature.
The Project Trailblazer requirements call for image collection at the base and top of each lift, as well as at other Silverjack locations, for a total of more than 20 target boards with cameras. The image-grabbing software vgrabbj, which is explained in Chapter 8, “USB Interfacing,” performs a text overlay operation that labels an image with location and timestamp information. The Project Trailblazer engineers wanted to use this overlay functionality, but it would require individual configuration for each camera-equipped target board. For example, the bash script executing on the target board at the top of Lift 1 would contain the text Lift 1 Top as the vgrabbj overlay command-line parameter. Likewise, the script executing at the top of Lift 2 would contain Lift 2 Top.
You could store location information in a configuration file on each target board's root filesystem. A bash script could open this file to determine what location text to use in the overlay. However, using a file still requires a unique location configuration for each image target board. The engineers wanted to stay away from unique configurations on each board because it is time-consuming and potentially leads to problems. Taking a unique configuration approach requires complete and up-to-date project documentation. The Silverjack technicians who maintain field equipment will require additional training. They will need to learn how to configure the target boards properly before field installation. Image collection is more than a convenience; it's a safety system. Configuration mistakes result in system downtime, which could potentially put guests and employees in dangerous situations. The engineers wanted to design an image collection system that required no unique configuration for each target board.
The engineers decided to use the Project Trailblazer database in an innovative way. They developed a target board bash script called imageReport, shown in Listing 12.7. imageReport queries the Silverjack database for the vgrabbj command. The server returns a unique vgrabbj command that the imageReport script then executes. The Apache HTTP server passes the target board's IP address to CGI scripts in the $REMOTE_ADDR variable. A CGI script called imageGetCommand, shown in Listing 12.8, performs a database query, using the target's IP address, to determine the board's location description. The imageGetCommand CGI script then returns to the target board a complete vgrabbj command with the overlay command-line parameter set to the board's location, current time and date, and the output filename parameter set to a unique filename. The imageReport script executes this unique command and creates a unique image file with the appropriate overlay. Through use of the imageGetCommand CGI script, every camera-equipped target board executes the same imageReport script and therefore, the target boards do not require unique configuration.
#!/bin/bash # imageReport v1.0 12/31/01 # www.embeddedlinuxinterfacing.com # # The original location of this code is # http://www.embeddedlinuxinterfacing.com/chapters/12/ # # Copyright (C) 2001 by Craig Hollabaugh # # This program is free software; you can redistribute it and/or modify # it however you want. # # imageReport # imageReport is a bash script that executes on a target board # with an external video camera and its driver loaded. Loading # the driver, connects the camera to the /dev/video file. # # This script queries the tbdev1's apache HTTP server on port 80 # using nc to obtain the image command. It then executes this command. # The command is formatted with all the command line parameters # for the specific target based on based on the target's IP address. # nc is configured with the -w flag which sets a connection timeout. # If tbdev1's apache server doesn't answer, this script will continue # to operate. # # The image command will also contain a sleep statement to pause # the main loop. # # Call this from inittab using the respawn option as in # T3:23:respawn:/usr/bin/imageReport # If imageReport should die, init will start it again # # loop forever while [ 1 ] do # get the command imageCommand=`echo "GET /cgi-bin/imageGetCommand" | nc -w 10 192.168.1.11 80` # execute the command and produce no output eval $imageCommand > /dev/null 2>&1 done |
#!/bin/bash # imageGetCommand v1.0 12/31/01 # www.embeddedlinuxinterfacing.com # # The original location of this code is # http://www.embeddedlinuxinterfacing.com/chapters/12/ # # Copyright (C) 2001 by Craig Hollabaugh # # This program is free software; you can redistribute it and/or modify # it however you want. # # imageGetCommand # imageGetCommand is a CGI script. A field target board # sends an HTTP request to retrieve an complete image capture command. # For Project Trailblazer, we are using the vgrabbj program. This # script performs a query for location description using the target's # IP address contained in the $REMOTE_ADDR variable. The script then # returns a completely formatted bash command that includes a unique # filename for the capture output and an overlay parameter that contains # location, current time and date information. # # The command also contains a sleep statement to pause the script main # loop running on the target. The sleep value could be changed dynamically # based on time of day. Here it is set to 300 seconds or 5 minutes. DELAY=300 # # This script also logs this request in the Trailblazer database image # table. Web queries use these image entries to find the latest image # from a location. # # Here's the header/content blank separation line required by Apache echo # get the last octet of the target's IP address location=`echo $REMOTE_ADDR | cut -f 4 -d '.'` # query the database for the target boards location description locationdes=`echo "SELECT description from locations where location = $location;" | mysql trailblazer --user=trailblazer --pass=tb --silent` # output the image command and the sleep statement filename=`printf "%03d-%s.jpg" $location `date +%Y%m%d%H%M%S`` printf "vgrabbj -e -i vga -f /tmp/$filename" printf " -p "%s - %s" -T 20 -a 5 -m 50; sleep $DELAY " "$locationdes" "`date +%A, %D, %r`" # Here's an example output # vgrabbj -e -i vga -f /tmp/030-20020102000919.jpg -p # "Lift 1 Base - Wednesday, 01/02/02, 12:09:19 AM" -T 20 -a 5 -m 50 # Here are the vgrabbj command line options used #-e Enables the timestamp #-i vga Sets the image size to 640x480 #-f Writes to an output file instead of to stdout #-p Defines the overlay in timestamp format #-T Sets the overlay font size #-a Sets the overlay alignment on the image #-m Sets the overlay blending with the original image # log this query echo "INSERT INTO images (location,filename) VALUES ($location,"$filename");" | mysql trailblazer --user=trailblazer --pass=Trailblazer |
Using the Network File System (NFS), the target boards mount their root filesystems from the server. (See Chapter 5, “Debugging,” for more information about NFS and root filesystem mounting.) When the imageReport script evaluates $imageCommand, vgrabbj writes the image file to the target board's /tmp directory, which is also the server's /tftpboot/i386-rootfs/tmp directory. When the imageGetCommand CGI script is executed, it returns imageCommand with a unique filename and also logs this filename in the Project Trailblazer database images table. Another CGI script, imageGetLast, shown in Listing 12.9, queries the images table for the last recorded image at a specific location. The imageGetLast script returns the appropriate image file contained in the /tftpboot/i386-rootfs/tmp directory.
TIP
If your target board does not mount its root filesystem using NFS, you can use nc, ftp, rcp, scp, or lynx to copy files from the target board to the server. These programs need to be cross-compiled if the target board doesn't use an x86 processor.
#!/bin/bash # imageGetLast v1.0 12/31/01 # www.embeddedlinuxinterfacing.com # # The original location of this code is # http://www.embeddedlinuxinterfacing.com/chapters/12/ # # Copyright (C) 2001 by Craig Hollabaugh # # This program is free software; you can redistribute it and/or modify # it however you want. # # imageGetLast # imageGetLast is a CGI script. A web service sends an HTTP # request with a Trailblazer location number as a parameter. # Apache calls this script setting the $QUERY_STRING variable # to the location number. This script forms a SELECT statement # that returns the filename stored in /tftpboot/i386-rootfs/tmp. # # Here's the Content-type line to tell the browser that this reply # is a jpg image. echo Content-type: image/jpeg # Here's the header/content blank separation line required by Apache echo # Set the location location=$QUERY_STRING # Form the SELECT statement and pipe it to mysql. # You have to login in to mysql as trailblazer with # password tb because apache will execute this script as # user www-data not root. Redirect the output to a temp file. filename=`echo "SELECT filename from images where location = $location order by timestamp desc limit 0,1" | mysql trailblazer --user=trailblazer --pass=tb --silent` # cat the file out to the browser cat /tftpboot/i386-rootfs/tmp/$filename |
You can test the imageGetCommand CGI script by using these commands:
root@tbdev1[509]: imageCommand=`echo "GET /cgi-bin/imageGetCommand" | nc -w 10 192.168.1 .11 80` root@tbdev1[510]: echo $imageCommand vgrabbj -e -i vga -f /tmp/011-20020118142244.jpg -p "tbdev1 - Friday, 01/18/02, 02:22:44 PM" -T 20 -a 5 -m 50; sleep 300
This shows that the imageGetCommand CGI script returned a vgrabbj command with unique location identifier, tbdev1, in the text overlay parameter and a unique filename, /tmp/011-20020118142244.jpg, in the output filename parameter.
You can execute $imageCommand by using this command:
root@tbdev1[508]: eval $imageCommand
Reading image from /dev/video
vgrabbj captures an image and creates the /tmp/011-20020118142244.jpg image file.
The Project Trailblazer lift access point design uses radio frequency identification (RFID) readers from ESPTech. Each guest's daily or season pass contains an RFID tag that emits a unique 20-character identification string that is read when it is near the RFID reader. When the pass is purchased, a unique ID string is generated and the pass's tag is programmed with the ID. This process also creates an entry in the Project Trailblazer database guests table.
A guest who wants to gain lift access presents his or her pass to the lift access point. The pass's tag emits the guest's unique ID string, which the RFID reader reads and passes via an asynchronous serial link to the access point's target board. The bash script accessPointControl, shown in Listing 12.10, that is executing on the target board reads this unique ID and then queries the Trailblazer database for pass validity. If the pass is valid, the accessPointControl script turns on the access point's green light for 5 seconds, permitting guest access to the lift. If the pass is not valid, the script turns on the access point's red light. The accessAllow CGI script, shown in Listing 12.11, not only returns pass validity information but also logs guest lift access.
#!/bin/bash # accessPointControl v1.0 12/31/01 # www.embeddedlinuxinterfacing.com # # The original location of this code is # http://www.embeddedlinuxinterfacing.com/chapters/12/ # # Copyright (C) 2001 by Craig Hollabaugh # # This program is free software; you can redistribute it and/or modify # it however you want. # # accessPointControl # accessPointControl is a bash script that executes on a target board # that controls a lift access point. This script receives the guest # pass ID from the RFID tag reader over serial port 0 (ttyS0). It # queries the database for pass validity and controls the red light # green light circuit connected to ttyS0's DTR signal. # # Call this from inittab using the respawn option as in # T3:23:respawn:/usr/bin/accessPointControl # If accessPointControl should die, init will start it again # # loop forever while [ 1 ] do # Get the passID # The RFID tag reader just outputs the ID when received, no # need to send it a command to get the ID. This command sets the timeout # at 2 seconds. passID=`querySerial /dev/ttyS0 19200 2000 ''` if [ -n "$passID" ] # if passID is not empty. querySerial returned nothing then # query the database. it will return # 1(valid), 0(not valid), or blank (unknown id) valid=`echo "GET /cgi-bin/accessAllow?$passID" | nc -w 10 192.168.1.11 80` if [ -n "$valid" ] # if valid is not blank then if [ "$valid" = "1" ] # we have a valid pass, allow access to lift then # turn green light on for 5 seconds setSerialSignal /dev/ttyS0 1 0 sleep 5 fi # turn red light on setSerialSignal /dev/ttyS0 0 0 fi fi done |
#!/bin/bash # accessAllow v1.0 12/31/01 # www.embeddedlinuxinterfacing.com # # The original location of this code is # http://www.embeddedlinuxinterfacing.com/chapters/12/ # # Copyright (C) 2001 by Craig Hollabaugh # # This program is free software; you can redistribute it and/or modify # it however you want. # # accessAllow # accessAllow is a CGI script. A target board sends an HTTP # request with a pass RFID as a the parameter. # Apache calls this script setting the $QUERY_STRING variable # to the pass RFID. This script forms a SELECT statement # that returns whether the pass is valid or not (1 or 0). This # script also logs the access. # # Here's the header/content blank separation line required by Apache echo # get the location as the last octet of the target board's IP address location=`echo $REMOTE_ADDR | cut -f 4 -d '.'` # get the pass ID passID=$QUERY_STRING # query the database for the pass valid field for this passID echo "SELECT guests.passValid from guests where passID = "$passID";" | mysql trailblazer --user=trailblazer --pass=tb --silent # log the access echo "INSERT INTO accesses (location,passID) VALUES ($location,"$passID");" | mysql trailblazer --user=trailblazer --pass=tb |
You can test the accessPointControl and accessAllow scripts without having an ESPTech RFID reader or tags. In Chapter 6, “Asynchronous Serial Communication Interfacing,” you tested the querySerial program, using minicom, ttyS1, and a null modem cable. That same configuration works here. The Project Trailblazer database contains test data for guests, including pass identification and pass validity information. Of the five guests in the database, four have valid IDs (1000, 1001, 1002, and 1003) and one has an invalid ID (1004). (Refer to Listing 12.1 for more information.)
You can test the accessPointControl and accessAllow scripts by using the following instructions on tbdev1:
3.137.41.205