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:
- Create a marklogic database with an assigned triggers database
- Turn on fast reverse query for the database
- Create a new HTTP app server, pointing it’s modules to the xquery code in the following Source code
- from qconsole, with the dropdown set to the primary db (not the trigger db) run the installAlert.xqy script
Creating some geofences:
- Using the “My Places” feature of Google Maps, create a new map
- draw some polygons on the map and give each a different color
- 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.
- 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)