To finish this little series, I wanted to describe the little setup I built and how it was done. Nothing spectacular, more an example of how you can create a software cocktail / mashup to get a one-off short-lived project like this going fast.
First the basic task at hand: allow kids to register their FanBot and print out a “passport” with a picture of their creation and some information about when and how to get their FanBot back after the RoboCup 2013 event. At the same time, it would be nice to have a monitor display the current count and show images of the last few FanBot pictures taken.
I decided to use 3 Raspberry Pi’s as “slave”, each with a webcam, an LCD screen (thanks David, for the laser-cut frame!), and Ethernet + power. The code running on them is on github. It would be nice if each slave could continue to accept registrations even with the network connection temporarily down, so I went for the following approach:
- collect registrations locally, using
rsyncto push new ones to the master
- everything is based on a few simple shell scripts for quick adjustment
- two C/C++ programs were needed: to read the FanBot data and to drive the LCD
- do a
git pullon power-up and re-compile as needed before starting operation
- periodic webcam readout and periodic rsync, using loops and
For the master, I thought about using the Odroid/U2, but decided against it as there would be too much setup involved in the last minute. Next idea was to use an Acer Inspire One Linux netbook, but it turned out to be way too slow. For some reason, Node.js was consuming 100% CPU (I suspect a bad
nodemon disk change polling error on the slow SSD). No time to figure that out, so I ended up using my second Mac laptop instead.
The master logic started out as follows:
- an rsync server was set up to collect files from all the slaves in one spot
- the display is presented via a browser in full-screen mode and Node.js
- the original plan was to also allow outside access, but we never got to that
- for live updating, I decided to use SocketStream (same as in HouseMon)
- a PDF was generated for each image by
convert, which is part of ImageMagick
- an AppleScript then prints each PDF to the USB-attached laser-printer
These choices turned out to be very convenient: by having the rsync folder inside the Node.js application area, and using nodemon, refresh became automatic (nodemon + socketstream will force a refresh on each client whenever a file system change is detected). So all I had to do was write a static Node.js app to display the count and the latest images.
So far so good. A couple of glitches, such as an erratic printer (new firmware fixed it), an overheating RPi (fixed by clocking at 700 MHz again), and all the slave rsyncs fighting when the same registration was present on more than one (fixed by adding the “-u” flag).
During installation, we found out that there was no wired ethernet w/ DHCP, as I had assumed. Oops. So the Mac laptop was turned into a WiFi -> wired bridge, since WiFi was available most of the time. Whoops: “most” is not good enough, the RPi’s have no clock, they really need an NTP server – especially since the whole system was based on rsync and file modification times! We hacked a fixed DNS – but internet still has to be there.
And then the fun started – various little wishes came up after the fact:
- can we get images + passports off-site during the event? sure: rsync them to Dropbox
- could we have a page with all images? sure: on my server at JeeLabs, I made an rsync loop from one Dropbox area to another, and made a little photo-album using Dropbox
- could we show a live count, even though the monitor website was not accessible? sure: I simply added another shell loop on my server again, to generate an image with the count in it, and made it show up as first one in the photo album.
Here is the shell script for that last feature:
cd ~/Dropbox/FanBots while : do N=$(echo `ls *.jpg | wc -l`) if [ "$N" != "$P" ] then echo $N - `date` convert -background black -fill red -size 480x640 \ -gravity center "label:$N\n\nFanBots" 0-teller.png P=$N fi sleep 10 done
This can run anywhere, since Dropbox is taking care of all updates in both directions!
The point of all this is not which languages I used (your choice will definitely be superior), nor what hardware was selected for this (it changed several times). The point is that:
- it all got done in a very limited amount of time
- the basic rsync approach made things resilient and self-recovering
- github pulls made it possible to apply last-minute tweaks
- some nice changes were possible very late in the game
- dropbox integration made it possible to add features remotely
Happy ending: all the kids are having a good time … including me :)
PS. Tomorrow (Sunday) is the RoboCup 2013 finals. See you there?