Contents |
New programming languages for mobile application development, such Flash Lite and WRT, can't access device native resources such as GPS, Accelerometer, etc. This problem happens because they usually run in a sandbox. An approach that fixes this problem is the development of an access layer which must be between device and mobile application (Flash Lite or WRT). This access layer can be developed in any programming language that has native access to the device.
The figure below shows how this layer works.
We propose the development of a mobile web server written in Python language which the main goal is to allow the retrieval of available native services in a Web Service REST-based approach. The web server was developed in an extensible manner that allows an easy addition of new services, decoupling the parameters handling of the service implementation. Due to that, it's possible to write a service with just the business logic itself.
Figure 2 depicts our architecture solution. There are three main entities associated with the architecture: client, HTTP server and the services.
Figure 2. Architecture of the Mobile Web Server
Figure 3 shows the class diagram of the ServerPython. The Services class is the hotspot of the framework. The developer has to create methods and call the addCallBack method of the MyServer class added in the instance of Services.
Figure 3. Class diagram
In this section, we present some of the main features of our solution.
The code below presents the HTTPServer class which handles the HTTP requests.
class HTTPServer:
def __init__(self, host, port):
"""This class is responsible for parsing the HTTP request and calling the correct method"""
self.host = host;
self.port = port;
self.callbacks={}
def doGet(self, request, response):
"""This method is called when a GET request is sent to the web server. It MUST be overwritten in subclasses and it's called through template method design pattern"""
pass
def doPost(self, request, response):
"""This method is called when a POST request is sent to the web server. It MUST be overwritten in subclasses and it's called through the template method design pattern"""
pass
def __handlerAttributes(self, rawAttributes):
"""This method is called to handler the attributes of the HTTP request"""
rawAttributes=rawAttributes[:len(rawAttributes)-2]
map={}
for i in rawAttributes:
map[i[:i.find(':')]]=i[i.find(':')+2:len(i)-1]
return map
def __handlerRequest(self, connection, rawRequest):
"""This method is called to handler the request. It splits the tokens, call the '__handlerAttributes' method and finaly call the correct request, i.e. GET or POST method"""
self._rawRequest = rawRequest
tokenizedLine=self._rawRequest.split('\n')
requestLine=tokenizedLine[0]
attributes = self.__handlerAttributes(tokenizedLine[1:])
tokenizedLine = requestLine.split()
attributes["request-method"]=tokenizedLine[0]
attributes["requisition"]=tokenizedLine[1]
attributes["http-version"]=tokenizedLine[2]
request_object = attributes["requisition"]
if request_object.startswith('/'):
request_object=request_object[1:]
objects=request_object.split('?')
attributes["object-requested"]=objects[0]
map={}
if len(objects)>1:
objects=objects[1].split('&')
for i in objects:
iObject = i.split('=')
map[iObject[0]]=iObject[1]
attributes["parameters"]=map
request = Request(self._rawRequest, attributes)
response = Response()
if attributes["request-method"]=='GET':
self.doGet(request, response)
elif attributes["request-method"]=='POST':
self.doPost(request, response)
rsp = response.getResponse()
connection.send(rsp)
class MyServer(HTTPServer):
"""This is a subclass of HTTPServer. The implementation of the GET HTTP method is provided. In our case, we call the correct service"""
def __init__(self,host, port):
HTTPServer.__init__(self, host, port)
def doGet(self, request, response):
"""Implementation of the GET method"""
functionName=request.getProperty("object-requested")
attributes=request.getProperty("parameters")
response.println(str(self.callbacks[functionName](attributes))) # Call the service requested and return the result as a string
This is a service example. In this function we retrieve the position of device through GPS
def get_position(attributes):
positioning.select_module(positioning.default_module())
pos=positioning.position()['position']
ret='latitude=' + str(pos['latitude']) + '&longitude=' + str(pos['longitude'])
return ret
This is a piece of code that shows how to start the server and to add a service.
server = MyServer('127.0.0.1',5004)
server.addCallBack("get_position", get_position)
server.startServer()
The developer can easily include new methods into the S60ServerPython, which requires minor knowledges about Python language. Below is described the required steps to make this task.
Implement a method 'method_x' in the Services class. It imposed just one restriction to the new method structure. The method MUST receive a map representing the passed parameters of the URL.
Execute the method 'server.addCallBack('url_to_x', method_x)', where server is an attribute of the type MyServer inside the Services class.
Here you can download the source code and the SIS file of the ServerPython. Note that if you want to use GPS, you have to install the SIS file. Click here to get the zip file with the source and SIS.
As discussed previously, a client (Flash Lite) application has access to S60 internal resources through HTTP requests. In ActionScript 2.0 (which is used in Flash Lite 2.x and 3.x) a HTTP request can be executed using the LoadVars class. The basic use of this class is shown below:
var lv:LoadVars = new LoadVars();
lv.onLoad = function(success:Boolean){
//Actions when data is loaded.
}
lv.sendAndLoad("http://example.com",lv,"GET");
The http://example.com URL has to be changed to http://127.0.0.1:5004/get_position if you want to get the GPS position from the device using the ServerPython.
A complete example on getting GPS position and showing a Google static map can be found here: File:Gps-serverpython.zip example project. More details about this example code are available here: Accessing system resources with PyS60 on S60 3rd Edition devices.
For additional information, go to Web Effort, Flash Lite Effort, WRT Effort and Python S60 Effort