I have learned a great deal from other tinkerers who were kind enough to put their detailed notes on the web, so here are mine.
About the time when we started thinking about staging a second Empire State Building Flash-A-Thon, I had been doing some reading on the Wireless Web, AKA Wireless Area Protocol, or WAP. I got a lot of good notes from the WAP Forum, and from Phone.com. By registering as a developer at the latter (it's free), you get all kinds of good notes.
My plan was to operate a video camera remotely, using a cell phone connected to the wireless web. The camera would be attached to a server via a serial cable, and the server would have a CGI program on it that would send directions to the camera, get responses from the camera, and serve those responses back to the cell phone client.
WAP works a lot like the worldwide web, with a few additions. Basically, your cell phone has a mini browser on it, and through that, connects to a server at your cell service company. That server then sends any http request you make out to the rest of the internet, brings back the results, and serves them to your phone's browser. Other servers have to be configured for the WAP MIME types, and have to have content formatted as WML pages (Wireless Markup Language, WAP's analog to HTML). That's the basics of it.
I had been doing some work with Applescript at the time, and knew that it could be used to write CGI applications for a Mac server. I also knew that there were Applescript extensions for addressing the Mac's serial port. So I decided to set the whole system up using a Mac as a server (using the Personal Web Sharing extensions for System 8 and beyond), and Applescript to do all the talking. For a camera, I had access to a Sony TRV-8 digital video camera, which is enabled with Sony's Control-L serial control protocol.
To test all my WML programming, I used the UP.Phone browser emulator from Phone.com. It's part of the UP SDK on their developer's site. It's a program that emulates the mini-browser on your phone on the desktop of a PC. Invaluable for quicker testing, and for saving minutes on a real cell phone during development. Do check your pages at each stage of development on a real phone, however, as you'll be amazed at the interesting errors that come up.
I had already set up a WML site on a Linux server, and found it was a piece of cake. All I had to do was add a few MIME types to my .htaccess file, write some WML pages, and all was beautiful. The MIME types involved are as follows (paste these directly into your .htaccess file if you want):
AddType text/x-hdml hdml AddType text/vnd.wap.wml wml AddType image/bmp bmp
On the Mac, it wasn't so simple. I could add the MIME types using the Personal Web Sharing control panel's preferences, but still the cell phones kept getting formatting errors. I finally decided to try a different server program, and went to the old MacHTTP 2.2.2. It serves static WML pages seamlessly, all I had to do (again) was add the MIME types to the MacHTTP.config file.
CGI programs were a little more difficult to get going. (Aside: Felipe's Applescript CGI Examples were invaluable to me. Also useful was Apple's Applescript site and related links) First, the MacHTTP.config file had to be modified, because it kept serving all CGI results out as text/html. When I modified it to serve all CGI requests as text/vnd.wap.wml, things worked better. I still had to have the CGI application write its own header, however, including:
HTTP/1.0 200 OK MIME-Version: 1.0 Server: MacHTTP/2.2.2 Date: (fill in date here) Content-type: text/vnd.wap.wml Content-length: (fill in length of the file served out here)
In the end, the Applescript CGI looked a bit like this:
on handle CGI request path_args Â searching for http_search_args from address client_address from user username using password |password| -- make a date string in a form like MacHTTP formats it: set date_slug to create_GMT_date(the currentDate) -- get the user's choice from the argument passed to the CGI: set userChoice to http_search_args as integer -- make a carriage return character: set cr to (ASCII character 10) -- give the file path to a text file with the WML template for the reply: set whatPage to "Macintosh HD:webdocs:reply.wml" try -- serial stuff: write_to_serial(userChoice) set stampResponse to read_from_serial() -- read the reply template file into a string: set wmltext to read_this_file(whatPage) -- fill in the serial port response where <guts> appears in the template: set the wmltext to replace_chars(wmltext, "
<guts>", stampResponse) -- get the length of the response: set contentLength to the number of characters of wmltext -- create the header info: set headertext to Â "HTTP/1.0 200 OK" & cr & return & Â "MIME-Version: 1.0" & cr & return & Â "Server: MacHTTP/2.2.2" & cr & return & Â "Date: " & date_slug & cr & return & Â "Content-type: text/vnd.wap.wml" & cr & return & Â "Content-length: " & (contentLength as text) & return & cr & cr quit return headertext & wmltext on error errormsg -- create a page of WML text to return; I never did this. Bad Tom, no cookie. quit return errormsg end try end handle CGI request
The subroutines for writing and reading the serial info, creating the date string, etc. are omitted here for brevity.
Originally, I was saving my CGI programs as Asynchronous CGI's (ACGI's), but I found there was a problem with getting them to quit properly, and they weren't serving the results correctly, so I went back to making them normal CGI's. I had to adjust the timeout length in the MacHTTP.config file to be shorter than the default 60 seconds to about 35-40 seconds. Once that was all done, I was able to read from and write to the serial port from my cell phone.
Talking to the camera turned out to be a greater challenge. Sony's Control-L and Control-S protocols are documented on many websites, including the ever-useful Sony S-Link Resource Center. Also useful were here and here. In the end, the most useful tool I found was the Video Toolkit, originally by Mark Abbate, now a product of Videonics. This link is to version 3.0 for Windows, though I was using Version 2.0 for Mac. What I learned was that while I could control the camera perfectly in VTR mode, I couldn't control it in camera mode.
By this time, I had a day to go until the day of the shoot, so I chose the expedient route. I made a servomotor controller for the camera's remote control using the ever-popular BASIC Stamp to talk to the serial port of the Mac.
As this detail shows, the servo's arm pressed down on the record button of the stamp in response to a command from the serial port:
It ain't pretty, but it works.
The BASIC Stamp servo program was a little troublesome, because of the timing issues between the SERIN command and the servo control. In order to keep the servo in place, you have to continually PULSOUT to it, and in order to keep the stamp listening to the Mac, you have to continually SERIN. I juggled the two:
n9600 con 16624 ' baud mode for serial port (9600 8-N-1 for Stamp 2SX) byteVar var byte ' serial data angle var word ' servo position goto push ' do an initial button push on power up main: serin 9, n9600, [byteVar] ' get data from mac if byteVar = 1 or byteVar = 2 then push goto main push: serout 10, n9600, [byteVar] ' send back the data to the Mac for angle = 1000 to 850 step 5 ' push the button pulsout 8, angle pause 10 next pulsout 8, 1000 ' raise the arm again goto main
The system worked fine as long as I had good cell coverage. In a strong cell, it took only about three seconds for the command to go from my keypress to completion at the camera to notification on my phone again. Not bad for a net transaction of any sort. However, with spotty cell coverage, the lag tome was significantly longer. When I called from the 86th floor observation deck of the Empire State Building, the return trip (completion to notification) took over a minute and a half as the phone searched for a string signal. While we were able to record a successful test from the Empire State, we did not use the system for starting and stopping during the actual event, so as not to keep 40 people waiting for a network transaction.
I was using Sprint PCS basic service for these tests. At the Empire State, we found that the basic service was not adequate, and a second Sprint-connected phone made a voice connection for the event, albeit by roaming outside the local network! I can only assume it was picking up a cell in New Jersey, perhaps? A Bell Atlantic Mobile phone was tested too, and could not pick up service at all.