Layar POI service using Google App Engine
Layar is a cool handheld augmented reality application that allows to overlay "Layers" on the image seen by a handheld device's camera. One can think of these layers as content that is seen based on your current location. This allows to overlay digital data over actual live imagery.
The Layar API depends that the source of data (Points Of Interest) is a RESTful web service, that sends an HTTP GET request, and expects back a JSON object. The details of the GET parameters, and the required JSON object could be found here in the layar API documentation.
To create a layer, one needs to provide such a service that provides the Points Of Interest (POI). Such a service could easily be written and provided by google app engine. This article will discuss how to do so using the google app engine python SDK, and is highly depends on the getting started guide for google app engine through python. Sections 1-4,6 are sufficient for understanding of the coming content.
Handling Requests
Since requests from layar to the POI web service come in the form of GET requests, the parameters can simply be accessed in the request handling method through:
[sourcecode language="python"]
self.request.get(parameter_name)
[/sourcecode]
POI Response
The POI response that layar expects is a json object. The API place many restrictions on the response. The first comes in the content type of the HTTP response. Thus, it has to be set as follows:
[sourcecode language="python"]
self.response.headers['Content-type'] = 'text/javascript; charset=utf-8'
[/sourcecode]
Another restriction is in JSON object returned as a response, where almost all the fields are required by layar. To make things simpler, the object is to be represented as a python object. This could be later converted to a JSON object. The JSON object responded with could be represented as follows (as a minumum):
[sourcecode lanaguage="javascript"]
{'layer':'layer name', 'hotspots':list_of_POI, 'errorCode':0, 'errorString':'ok'}
[/sourcecode]
Where hotspots is a list of POI object. These object could be represented as:
[sourcecode language="python"]
class POI:
def __init__(self,poi_id,title,lat,lang):
self.actions = []
self.id = poi_id
self.imageURL = None
self.lat = lat
self.lon = lang
self.distance = None
self.title = title
self.line2 = None
self.line3 = None
self.line4 = None
self.attribution = ""
self.type = 0
self.dimenion = 1
self.transform = {'rel':True, 'angle':0, 'scale':1.0}
self.object = {'baseURL': ""}
[/sourcecode]
From python to JSON
As python follows a batteries all included strategy, there are libraries that convert python dictionaries to JSON objects. Even though google app engine uses python, the "json" module is not available. Thankfully, an equivalent one is found through "from django.utils import simplejson". It could be used to convert a python dictionary (that looks frightfully like a JSON object) to a JSON object string as follows:
[sourcecode language="python"]
simplejson.dumps({'layer':'guc', 'hotspots':poi_list, 'errorCode':0, 'errorString':'ok'})
[/sourcecode]
The problem with simplejson is that it only takes dictionaries or lists. Thus, this poses a problem when using the POI class mentioned earlier. Again, python comes with a rescue, where a dictionary representing the object could be obtained as follows:
[sourcecode language="python"]
poi = POI('C1','C1',29986707,31438864)
poiDictionary = poi1.__dict__
[/sourcecode]
Putting the code together
Now that we have the POI object, and the conversion mechanism, we are ready to have a request handler for layar requests. An example of static POIs is as follows:
[sourcecode language="python"]
from django.utils import simplejson
from poi import POI
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
class POIHandler(webapp.RequestHandler):
def get(self):
self.response.headers['Content-type'] = 'text/javascript; charset=utf-8'
#latitude and longitude is an integer will be divided by 10^6
# so take care of accuracy after the division
poi1 = POI('C1','C1',29986707,31438864).__dict__
poi2 = POI('C2','C2',29986744,31439272).__dict__
poi3 = POI('C3','C3',29986995,31438923).__dict__
poi4 = POI('C4','C4',29987153,31439245).__dict__
poi5 = POI('C5','C5',29986326,31438810).__dict__
poi6 = POI('C6','C6',29986688,31438569).__dict__
poi7 = POI('C7','C7',29986442,31438370).__dict__
pois = [poi1,poi2,poi3,poi4,poi5,poi6,poi7]
# final getPOI response dictionary
d = {'layer':'guc', 'hotspots':pois, 'errorCode':0, 'errorString':'ok'}
self.response.out.write(simplejson.dumps(d))
application = webapp.WSGIApplication(
[('/',POIHandler),
('/getPOI',POIHandler)],
debug=True)
def main():
run_wsgi_app(application)
if __name__=='__main__':
main()
[/sourcecode]
Updates
With the new layar 4 api coming soon, and the new features being in beta2, un update of how to add one of my favorite new features is needed. This is having different actions on the entire layar. It can be easily done by adding an action attribute to the final getPOI response dictionary (see code above). An example of the addition is as follows:
[sourcecode language="python"]
d['actions'] = [{'uri':'http://google.com','label':'action on the entire layar'}]
[/sourcecode]