TomTom One, Macstumbler and NMEA data
In my last post I wrote about how I attached my TomTom One to my Mac via bluetooth to extract the GPS data. I hooked this all up to Mac stumbler and took a drive around Aberystwyth to see what wireless access points were advertsing themsleves. I used no special aerials, nor did I try and look for access points that were not advertising themselves – if a beacon frame made it to my Mac sitting on the passenger seat, it was counted – otherwise the access point was ignored.
The results of my drive are displayed in this Google map of some Aberystwyth Wireless Access Points. I haven’t put all captured fields of data into this map, because it is just for demonstration purposes. It is also not a complete map of Aberystwyth access points for the same reason. The third disclaimer is that the markers show the locations where I first saw a beacon frame and not the position of the strongest signal from the access point.
But the question is: how do we get the data from Mac stumbler to Google maps?
Mac stumbler saves its data in a “plist” XML format. This is a slightly odd format that looks like this:
<plist version="1.0">
<array>
<dict>
<key>channel</key>
<integer>1</integer>
<key>comments</key>
<string></string>
<key>date</key>
<date>2006-11-08T17:26:57Z</date>
<key>latitude</key>
<string>W 5224.795410</string>
<key>longitude</key>
<string>N 404.561493</string>
<key>mac</key>
<string>00:12:17:DD:99:0E</string>
…
</dict></array></plist>
and so on.
What would make more sense would be:
<node> <channel>1</channel> <comments /> <date>2006-11-10T17:57:11Z</date> <latitude>W 5224.771484</latitude> <longitude>N 404.355896</longitude> <mac>00:12:17:DD:99:0E</mac> … </node>
So I wrote an XSL style sheet which would do this translation, and ran the plist file through xalan to apply the stylesheet. The stylesheet is here:Â
<?xml version="1.0" ?>
<xsl :stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
</xsl><xsl :template match="array">
<nodelist>
<xsl :apply-templates select="dict"/>
</nodelist>
</xsl>
<xsl :template match="dict">
<node>
<xsl :apply-templates select="key"/>
</node>
</xsl>
<xsl :template match="key">
</xsl><xsl :element name="{translate(text(), ' ', '_')}">
<xsl :value-of select="following-sibling::*"/>
</xsl>
</xsl:template>
</xsl:stylesheet>
At this point, I could have just written a google maps page to read my data, but there is a complication. NMEA format presents data in degrees and minutes, whereas google maps and many other applications want to use decimal degrees. I wrote another stylesheet that translates the NMEA data to decimal degrees and then throws out the results in someting that I could copy and paste into an existing google maps page. This is not pretty (and the XML code is not as neat as I would like), but I wanted something running quickly, so here is the code I used:
< ?xml version="1.0" ?> <xsl :stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl&:output method="html" omit-xml-declaration="no" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" /> </xsl><xsl :template match="node"> </xsl><xsl :variable name="lat1"> <xsl :value-of select="substring(latitude,3) div 100" /> </xsl> <xsl :variable name="lon1"> <xsl :value-of select="substring(longitude,3) div 100" /> </xsl> <xsl :variable name="lat2"> <xsl :value-of select="floor($lat1)" /> </xsl> <xsl :variable name="lon2"> <xsl :value-of select="floor($lon1)" /> </xsl> <xsl :variable name="lat"> <xsl :value-of select="(($lat1 - $lat2) div 0.6) + $lat2" /> </xsl> <xsl :variable name="lon"> <xsl :value-of select="(($lon1 - $lon2) div 0.6) + $lon2" /> </xsl> var marker = createMarker(new GPoint(-<xsl :value-of select="$lon" />, <xsl :value-of select=”$lat” />), 0<xsl :if test=”wep=’Yes’” >1</xsl>,”<xsl :value-of select=”ssid” /><xsl :value-of select=”mac” />“); map.addOverlay(marker); </xsl:template> </xsl:stylesheet>
Having run the plist through xalan again, I coped and pasted the results into the web page example above.