Shell Scripting a Camera Server
Exposing functionality always is an issue in embedded development—how much effort should be put into easy customization? In this case, much effort has gone into it—no two surveillance installations are alike.
The browser-based interface is easy to use, feature-full and meant for human consumption. It is often not especially well suited for machine automation.
The HTTP API is a simple request-response API, made for automation, offering most options available in the browser-based interface. It generally returns just a status code or the bare requested object, like a snapshot or video stream. This lends itself well to remote control, and several third-party vendors sell software that uses this API for controlling tens to hundreds of cameras from one or a few central nodes.
The PHP3 lite dialect is the easiest option for adding custom dynamic pages to the browser-based interface, and it can also be used for general-purpose internal scripting.
Shell scripting, via the provided sh-compatible shell and attendant utilities, is flexible and quick when some local intelligence is needed—for example, reacting to the push of a doorbell by snapping a picture, then opening a gate via a relay.
And if some advanced local smarts is needed, the GCC SDK for the platform is available.
As previously mentioned, we chose shell scripting for the issue at hand. In the relevant firmware revision, we had quite a few programs worth using:
BusyBox: including sash shell as /bin/sh.
mish: minix sh-compatible shell.
utask: task scheduler, not cron-compatible.
bufferd: image capture/buffering.
sftpclient: simple FTP client.
shttpclient: simple HTTP client.
smtpclient: simple mailer.
Of special note is the unobtrusive shttpclient. This allows us to use the HTTP API from internal shell scripts, which we needed for PTZ control. It also could be used in many other ways, of course—signalling events to another Webserver or video server, uploading pictures via HTTP, and other things not needing more than basic authentication. It is a simple HTTP client, after all, not wget or cURL.
Problems we encountered when pushing this into production use mostly turned out to have nothing to do with the scripting. We had some intermittent failures to upload images—these turned out to be caused by a climbing vine colonizing one of the antennas for the wireless bridge.
All good things end. I'll leave you now, but first, the final script we cobbled together is shown in Listing 1. Not particularly elegant, granted, but small and not that hard to write, thanks to the consideration of the original embedded developers. That's a fair lesson to take away from this, isn't it?
Listing 1. Final Script
#!/bin/mish PATH=/bin:/sbin:/usr/bin:/usr/sbin # stop button pressed? skip the rest. stopp=`ls /tmp/stopp` ; if [ "x$stopp" = "x" ]; then # clear working directory bufferd -reset -buffername BILDE ; # read configured positions, '~' signifies a unset # position grep -v '~' /etc/sysconfig/presetpos.conf \ >/tmp/presets ; # pos 1-10 reserved for non-public views num=11; while [ $num -lt 21 ]; do # another stop button check - break the loop stopp=`ls /tmp/stopp` ; if [ "x$stopp" = "x" ]; then grep Pos$num /tmp/presets >/tmp/canptz ; canptz=`cat /tmp/canptz` ; if [ "x$canptz" != "x" ]; then # go to position shttpclient "http://127.0.0.1/axis-cgi/\ com/ptz.cgi?camera=1&gotoserverpresetno=$num"; # wait for picture to settle sleep 6 ; # save picture to /tmp/BILDE/ bufferd -start -buffername BILDE -snapshot\ -pre 1 -format snapshot_pos$num.jpg -uri\ 'ftp://127.0.0.1/jpg/1/704x576.jpg' ; bufferd -stop -buffername BILDE ; tmpwait=20 ; while [ $tmpwait -gt 0 ]; do sleep 2; expr $tmpwait - 2 >/tmp/tmpwait ; tmpwait=`cat /tmp/tmpwait` ; if [ $tmpwait -eq 0 ]; then # timeout creating jpeg, kill process and # settle for potentially incomplete picture logger "timeout waiting for bufferd -stop,\ killing image_buffer and continuing." # ps is only available as a builtin # command in /bin/sh /bin/sh -c ps >/tmp/kverk ; grep image_buffer /tmp/kverk >/tmp/kverk2 ; imbuf_pid=`cut -b 0-5 /tmp/kverk2` ; rm /tmp/kverk; rm /tmp/kverk2; kill $imbuf_pid ; fi; if [ -f /tmp/BILDE/status ]; then # status file appeared - picture complete rm /tmp/BILDE/status ; tmpwait=0; fi; done; rm /tmp/tmpwait ; fi; fi; expr $num + 1 >/tmp/A ; num=`cat /tmp/A` ; rm /tmp/A; done; rm /tmp/presets ; rm /tmp/canptz ; # batch ftp all the pictures from this round sftpclient -L -m 10.0.0.1 -k /tmp/BILDE -c \ /var/www/pictures/c2 -u web -w P2SsW1Rd -t \ /var/www/pictures/c2/temp_c2.jpg ; fi;
Resources for this article: /article/8695.
Erik Inge Bolso is a UNIX consultant and epee fencer who lives in Molde, Norway, and has been running Linux since 1996. Another of his hobbies can be found via a Google search for “balrog genealogy”, and he can be reached at email@example.com.
|Where's That Pesky Hidden Word?||Aug 28, 2015|
|A Project to Guarantee Better Security for Open-Source Projects||Aug 27, 2015|
|Concerning Containers' Connections: on Docker Networking||Aug 26, 2015|
|My Network Go-Bag||Aug 24, 2015|
|Doing Astronomy with Python||Aug 19, 2015|
|Build a “Virtual SuperComputer” with Process Virtualization||Aug 18, 2015|
- Problems with Ubuntu's Software Center and How Canonical Plans to Fix Them
- Concerning Containers' Connections: on Docker Networking
- A Project to Guarantee Better Security for Open-Source Projects
- Where's That Pesky Hidden Word?
- Firefox Security Exploit Targets Linux Users and Web Developers
- My Network Go-Bag
- Doing Astronomy with Python
- Build a “Virtual SuperComputer” with Process Virtualization
- Three More Lessons
- diff -u: What's New in Kernel Development