Using KML to define Geofences

Feb 14, 2013    

I’ve written about geospatial alerting in previous posts.  Here’s a fun example where we drive Philips Hue lighting changes based on geofence definitions driven by a mobile device’s GPS.

Demo Overview:

  • MarkLogic will be configured to accept KML with colored polygons as a description of geofences
  • Each supplied geofence will be used to create an alerting rule
  • An HTML5 mobile app will poll the GPS device of my phone to send “ping” messages to MarkLogic
  • MarkLogic will insert a “ping” document containing the lat/lon of the phone
  • MarkLogic will detect whether the ping document exists within a saved geofence using reverse queries and the alerting framework.
  • If we have a hit, the demo will change the lights in my living-room to the color of the KML polygon which defined the geofence.

Results:

App Install:

  1. Create a marklogic database with an assigned triggers database
  2. Turn on fast reverse query for the database
  3. Create a new HTTP app server, pointing it’s modules to the xquery code in the following Source code
  4. from qconsole, with the dropdown set to the primary db (not the trigger db) run the installAlert.xqy script

Creating some geofences:

kml

  1. Using the “My Places” feature of Google Maps, create a new map
  2. draw some polygons on the map and give each a different color
  3. I placed a red polygon on the right side of my front lawn, and a blue polygon on the left side of my front lawn so that as I cross the walkway to my apartment, I move from one region to another.
  4. Copy and paste the “sharing” link to the map.  By adding “&output=kml” to the end of the URL, google will provide a KML view of the map.

Now we inert this record into MarkLogic as a geo fence from qconsole.  This code will download the KML, parse it into polygons, and create alerts:

xquery version "1.0-ml";
import module namespace mkf = "http://derickson/kmlalert/model/m-kf" at "/model/m-kmlfence.xqy";
import module namespace lk = "http://derickson/kmlalert/lib/kml" at "/lib/l-kml.xqy";

declare namespace kml ="http://www.opengis.net/kml/2.2";
declare namespace gx ="http://www.google.com/kml/ext/2.2";

mkf:insert-fence(
lk:get-google-map("https://maps.google.com/maps/ms?msid=2041XXXXXX Your URL GOES HERE")
)

A quick test of the alert by manually inserting a ping:

xquery version "1.0-ml";
import module namespace mp = "http://derickson/kmlalert/model/m-ping" at "/model/m-ping.xqy";


mp:store( mp:gen-ping( cts:point(38.XXXX,-77.XXX) ) )

For the video above, I’m driving the geo alert from my phone with a quick Ember.js + HTML5 geo alerting + JQuery.ajax application.  The main code to look at is the Geo.js file (which I stripped from something else I’m working on, so pardon the strange variable names)