×
Namespaces

Variants
Actions

How to utilize device resources from a WRT widget

From Nokia Developer Wiki
Jump to: navigation, search
Article Metadata
Article
Created: petrosoi (10 Mar 2008)
Last edited: hamishwillee (26 Jul 2012)

The System Info Service API provides access to a limited set of functionality and properties on a compatible S60 device. The current WRT implementation runs in a tight security sandbox and doesn't expose other access to system resources.

While waiting for an updated WRT release, providing access to more system resources, one method to provide some deeper system integration is to run a web server locally on your device and utilize scripting languages (Python, PHP) or native C++ applications to communicate with your WRT widget.

The simplest approach is to use either Mobile Web Server [1] or PAMP Nokia Open Source as your web server to provide an environment suitable for hosting your scripts.

All of the code snippets and examples in this article will assume that you have PAMP successfully installed and running on your WRT widget compatible device, with your htdocs folder residing on the e-drive.

Contents

Python scripts

You may run Python scripts hosted under a PAMP or MWS Apache installation by following the guidelines in the MWS documentation [2].

The S60 Platform Security restrictions make the calls to the location related information unaccessible when a script is invoked under the Apache installation.

PHP scripts

The PHP S60 API documentation Nokia Open Source is still a little shallow in information, but it's a good start for adventurous developers.

Creating a simple SMS sender widget

Create the Python script

The script below sends an SMS message after reading the message recipient number and message contents from the http query string.

I saved my string as test.py. Please keep this in mind when creating your ht.acl file in the next step.

"file test.py" 
 
def handler(req):
from mod_python import apache, util
import messaging
 
req.content_type = 'text/plain'
req.encoding = "UTF-8"
 
request_data = util.FieldStorage(req)
 
try:
 
number = request_data.getfirst("number")
message = request_data.getfirst("message")
 
messaging.sms_send(number, message)
 
req.write( "succeeded" )
 
except KeyError:
number = None
message = None
req.write("failed")
 
return apache.OK

Define the handler information for the mod_python page

Create a ht.acl file with the contents similar to the following:

AddHandler mod_python .py
PythonHandler test
PythonDebug On
Options None
 
Order Deny,Allow
Allow from all
 
<FilesMatch "\.(pyc|psp)$">
Deny from all
</FilesMatch>

Copy the files to your PAMP installation document root

You can copy the .py and .acl files manually to e:\Data\apache\htdocs\PAMPsmsSender\ or e.g. create a sis-package to do the trick.

Create your WRT widget

Please check the Nokia Developer WRT widget documentation [3] for info on how to create a simple WRT widget.

The Javascript stuff needed for communicating with the Python script shown above is simple.

I use the soon to be released WRTKit bundle to add components and command handlers to my widget UI, but you may naturally implement your UI anyway you like.

Define the URL to your Python script

var PY_URL = "http://127.0.0.1/PAMPsmsSender/.py?";

Introduce some constants for the WRTKit UI manager, main view and the necessary UI components.

Build the UI and add a command handler to the Send button.

// Reference to the WRTKit user interface manager and main view.
var uiManager;
var mainView;
 
// Reference to controls in the main view.
var sendButton;
var numberField;
var messageField;
 
 
// Called from the onload event handler to initialize the widget.
function init() {
 
// set tab-navigation mode and show softkeys
// (only if we are in the WRT environment)
 
if (window.widget) {
widget.setNavigationEnabled(false);
menu.showSoftkeys();
}
 
// create UI manager
uiManager = new UIManager();
 
// create main view
mainView = new ListView(null, "Send an SMS");
 
// add a text field to the view
numberField = new TextField(null, "Recipient");
mainView.addControl(numberField);
 
// add a text field to the view
messageField = new TextArea(null, "Message");
mainView.addControl(messageField);
 
// add a button to the view
sendButton = new FormButton(null, "Send");
sendButton.addEventListener("ActionPerformed", sendButtonClicked);
mainView.addControl(sendButton);
 
// display the main view
uiManager.setView(mainView);
}
 
function sendButtonClicked(event){
var number = numberField.getText();
var msg = messageField.getText();
if (number.length == "") {
uiManager.showNotification(2000, "warning", "Enter recipient number!");
}
else if (msg.length == "") {
uiManager.showNotification(2000, "warning", "Enter message text!");
}
else {
sendMsg();
}
}

Add code to issue a request to the Python script and handle the progress of the request

function sendMsg() {
uiManager.showNotification(-1, "wait", "Sending...", -1);
var req = createXMLHttpRequest();
if (req) {
 
var params = "number="+numberField.getText()+"&message="+messageField.getText();
 
var url = PY_URL + params;
 
loadXMLDoc(req, url);
}
}
 
 
// Creates an XMLHttpRequest object
function createXMLHttpRequest() {
var req = null;
try {
req = new XMLHttpRequest();
// Make sure that the browser supports overrideMimeType
if (typeof req.overrideMimeType != "undefined") {
req.overrideMimeType("text/html");
}
} catch (ex) {
req = null;
}
 
return req;
}
 
// Loads target XML document (url) into XMLHttpRequest
function loadXMLDoc(req, url) {
 
// Register a callback function which gets called when the request state changes
req.onreadystatechange = function() {
processStateChange(req);
};
 
req.open("GET", url, true);
// Transmit the request
req.send(null);
}
 
// Processes state changes of XMLHttpRequest
function processStateChange(req) {
// Request states are 0 through 4, where 4 equals complete
 
if (req.readyState == 4) {
 
if (req.status == 200) {
uiManager.hideNotification();
showStatus();
}
}
}
 
 
function showStatus(req) {
uiManager.showNotification(3000, "info", "Message sending "+req.responseText);
}

The beef in all of this is issuing an XMLHttpRequest to the Python script with the correct query string.

Reading the messages from Inbox

The messages from your device inbox may be read with either Python or PHP. The Python script is installed in a similar fashion as in the SMS sender case above.

The PHP script may be copied manually or via sis-file installation to a suitable folder under the Apache htdocs-folder.

The code snippets do a bit of HTML-formatting but you may want to recreate the response contents to suit your needs better.

Python

"file test.py" 
 
def handler(req):
from mod_python import apache
import inbox
from time import ctime
 
 
req.content_type = 'text/html'
req.encoding = "UTF-8"
 
i = inbox.Inbox()
m = i.sms_messages() # all message ID's
 
req.write("<div class=\"messagelist\" id=\"smslistdiv\">")
 
for s in m:
req.write("<p class=\"msgheader\" id=\"header_")
req.write(str(s))
req.write("\">")
req.write(ctime(i.time(s)))
req.write(" - ")
req.write(i.address(s))
req.write("</p>")
 
req.write("<p class=\"msgtext\" id=\"body_")
req.write(str(s))
req.write("\">")
req.write(i.content(s).encode("utf-8"))
req.write("</p>")
 
req.write("</div>")
 
return apache.OK

PHP

<?php
print "<div class=\"messagelist\" id=\"smslistdiv\">";
foreach (s60_inbox_get_messages() as $msg) {
print "<p class=\"msgheader\">";
print 'From: '.$msg->sender()."<br/>\n";
print 'When: '.strftime ("%x %X", $msg->time())."<br/>\n";
print "</p>";
print "<p class=\"msgtext\">";
print 'Content: '.$msg->content()."<br/>\n";
print "</p>";
}
print "</div>";
?>

Widget HTML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link rel="StyleSheet" href="styles/general.css" type="text/css" />
<script type="text/javascript" src="scripts/scripts.js" />
<title>Inbox messages</title>
</head>
<body id="body">
<div id="contents"></div>
</body>
</html>

Widget JavaScript

window.onload = init;
var PY_SCRIPT_URL = "http://127.0.0.1/inboxTest/.py";
var PHP_SCRIPT_URL = "http://127.0.0.1/inboxTest/inboxtest.php";
 
var PY_MENU_ITEM_ID = 993;
var PHP_MENU_ITEM_ID = 994;
 
// Initializes the widget
function init() {
window.menu.showSoftkeys();
window.widget.setNavigationEnabled( false );
createMenu();
}
 
function getMsgs( id ) {
var requrl;
 
switch (id)
{
case PY_MENU_ITEM_ID:
requrl = PY_SCRIPT_URL;
alert("Calling Python script");
break;
case PHP_MENU_ITEM_ID:
alert("Calling PHP script");
requrl = PHP_SCRIPT_URL;
break;
}
 
var req = createXMLHttpRequest();
 
if (req) {
loadXMLDoc(req, requrl);
}
}
 
 
// Creates an XMLHttpRequest object
function createXMLHttpRequest() {
var req = null;
try {
req = new XMLHttpRequest();
if (typeof req.overrideMimeType != "undefined") {
req.overrideMimeType("text/html");
}
} catch (ex) {
req = null;
}
 
return req;
}
 
// Loads target XML document (url) into XMLHttpRequest
function loadXMLDoc(req, url) {
 
// Register a callback function which gets called when the request state changes
req.onreadystatechange = function() {
processStateChange(req);
};
 
req.open("GET", url, true);
// Transmit the request
req.send(null);
}
 
// Processes state changes of XMLHttpRequest
function processStateChange(req) {
// Request states are 0 through 4, where 4 equals complete
if (req.readyState == 4) {
 
if (req.status == 200) {
showList(req);
}
 
}
}
 
 
function showList(req) {
widget.prepareForTransition("fade");
var mybody = document.getElementById("contents");
mybody.innerHTML = req.responseText;
widget.performTransition();
}
 
function createMenu(){
var menu1 = new MenuItem("Fetch using Python", PY_MENU_ITEM_ID);
var menu2 = new MenuItem("Fetch using PHP", PHP_MENU_ITEM_ID);
menu1.onSelect = getMsgs;
menu2.onSelect = getMsgs;
 
window.menu.append(menu1);
window.menu.append(menu2);
}

Known issues, tips, tricks, AOB

PAMP / MWS has to be restarted before executing a different Python script.

This page was last modified on 26 July 2012, at 02:01.
52 page views in the last 30 days.