Vous êtes sur la page 1sur 26

OPEN AT DYNAMIC PROGRAMMING WITH LUA Tutorial

Supprim : F038

confidential WM_PLC_F039 Level001

Page : 1 / 2

This document is the sole and exclusive property of WAVECOM. Not to be distributed or divulged without prior written agreement. Ce document est la proprit exclusive de WAVECOM. Il ne peut tre communiqu ou divulgu des tiers sans son autorisation pralable. Printed document not updated Document imprim non tenu jour

Lua on WMP Tutorial 28th June 2007

Session #1: Setup, Discovering the development environment ... 3

1.1 Setting up Windows for TCP/IP over PPP ................................................3 1.1.1 Configure the serial port ..................................................................3 1.1.2 Add the devkit as a modem ....................... Erreur ! Signet non dfini. 1.1.3 Create the connection ................................ Erreur ! Signet non dfini. 1.2 Other Windows software ........................................................................9 program ..........................................................................................9 FTP download ...............................................................................10 Threads and signals ......................................................................11 Threads and resources ..................................................................12

1.3 First 1.3.1 1.3.2 1.3.3 2 2.1 2.2 2.3 3 3.1 3.2 4 4.1

Session #2 Networking: play with a web server .......................14 My first web page .................................................................................14 Resources .............................................................................................15 Dynamic pages......................................................................................16 Dynamically generated content.................................................17 Beyond dynamism: interactivity ............................................................17 A Quick overview of Lua/C bindings ......................................................19 Session #3 Overview of some sample applications ....................21 Rapid implementation of network protocols ..........................................21

4.2 XML, RSS, AT parsing, in a WEB application.........................................22 4.2.1 Logging and serving hardware-gathered data ...............................24 4.3 4.4 5 6 24 AJAX WebPhone ...................................................................................24 Readings ..................................................................................25 --- Notes --- ...............................................................................26

Supprim : F038 Supprim : 1

confidential WM_PLC_F039 Level002

Page : 2 / 2

This document is the sole and exclusive property of WAVECOM. Not to be distributed or divulged without prior written agreement. Ce document est la proprit exclusive de WAVECOM. Il ne peut tre communiqu ou divulgu des tiers sans son autorisation pralable. Printed document not updated Document imprim non tenu jour

Lua on WMP Tutorial 28th June 2007

1 Session #1: Setup, Discovering the development environment


The devkits have been fitted with an OpenAT application running: Wavecoms porting of Lua interpreter and virtual machine WIP, Wavecoms TCP/IP stack, set up with a PPP server over UART2. By default, the devkit takes address 192.168.1.4, and gives address 192.168.1.5 to the PC. PPP user is wipuser, its password is 123456. A telnet server, serving a Lua interactive shell.

You can find the binary, the samples sources and the library on the USB key. This first sessions goal will be to set up your PC, so that you can start developing and running Lua programs on WMP100.

1.1 Setting up Windows for TCP/IP over PPP


We assume that you have at least one, ideally two serial ports on your development computer. One of them is to be linked to the devkits UART2: it will bear the TCP/IP link. If you have a second serial port, you can hook it to UART1: it will give you an easy way to send AT commands and to survey Lua traces.

We assume you have connected UART1 to your computers COM1.

Start > Parameters > Control Panel > System > Hardware > Device Manager > Ports (COM & LPT) > Communication Port (COM1) > right-click > Properties > Port Settings

p.3

Lua on WMP Tutorial 28th June 2007

Set the bit-rate to 115200.

1.2 Add the devkit as a modem

Start > Parameters > Control Panel > Add Hardware > Next > Yes, I have already connected the hardwatre > Add a New Hardware Device > Install the Hardware that I Manually select from a list (bottom of the scroll-list) > Modems > Dont Detect my Modem > Communication cable between two computers > COM1 > Finish

p.4

Lua on WMP Tutorial 28th June 2007

Check the installation:

Start > Parameters > Control Panel > System > Hardware > Device Manager > Modems > Communication cable between two computers > Right-click > Properties > Modem (2nd tab)
Set maximal speed to 115200:

p.5

Lua on WMP Tutorial 28th June 2007

1.3 Create the connection


Start > Settings > Network Connections > Right-click > Open > Create a new Connection (in the panel on the left) > Setup an advanced Connection > Connect directly to another Computer > Guest This computer is used to access information on the host computer > [give a name to the connection] > Communication cable between two Computers (COM1) > Anyone s use or My use only, at your preference > Finish
Set username: wipuser Set password: 123456 Check the remember checkbox.

Set the connections properties

Properties > Configure (button on the right, below the scroll list) > Set speed to 115200

p.6

Lua on WMP Tutorial 28th June 2007

Network config > Check Internet Protocol (TCP/IP)

Connect:

p.7

Lua on WMP Tutorial 28th June 2007

Thats it; youre connected to your WMP100 through a TCP/IP link. You can check by pingin the module:

p.8

Lua on WMP Tutorial 28th June 2007

Start here if your PC has a properly configured PPP link.


1.4 Other Windows software

To work comfortably, youll need: An FTP server the WMP can download programs straight from your PC. server: Theres one on the USB key if you dont already have one. Configure it to accept anonymous downloads, and set the anonymous FTP root to the ftproot directory. A web browser well play a lot with a web server, and samples have only browser: been tested against Firefox. A telnet client If you dont already have one, PuTTY is available on the USB client. key. A text editor. Youve probably got one, which might or might not offer Lua editor syntax highlight. Weve also provided a Lua syntax aware editor on the key If we have time for low-level network hacking, youll need netcat the netcat, networks Swiss army knife.

WSFTP Setting up WSFTP At first launch, open windows firewall for FTP if its not done already. In Security General, allow anonymous login in Security Users/rights, set anonymous directory to ftproot Optionally, enable logging in Logging Log options

Thats it with the setup.

1.5 First programs


Plug the devkit, connect, open a telnet session (to 192.168.1.4 by default). Save that config, as youll probably connect more than once

You should be greeted with the following prompt:

Lua interactive shell $ _ Now you can type your first programs:

$ print Hello world Hello world $ _

p.9

Lua on WMP Tutorial 28th June 2007 $ for i=1,5 do + print (three times, i, =, 3*i) + end three times 1 = 3 three times 2 = 6 three times 3 = 9 three times 4 = 12 three times 5 = 15 $ _ The language is really simple, basic proficiency shouldnt take more than an hour to someone who has a previous experience with Python, Ruby, Perl, Bash, PHP or JavaScript. Some much more advanced features exist (OO programming, modularization, coroutines, first-class functions, reified environments, error handling ), for those who are willing to invest a day or two in learning them. For this tutorial, youll have to rely on the Short Reference we provided, and the code snippets on the USB key.

1.5.1 FTP download Typing programs on the shell doesnt exactly scale well; setup your FTP server so that it accepts anonymous login from the devkit, and point the root to the ftproot directory (or copy these files to your FTP root). The command to load and execute a program file on the devkit is simply l: a short name because youll type it a lot. Just give it a file name, or a list of file names, and these files will be downloaded, compiled and executed. a parameter-less call l() will just re-download and re-execute the last series of files. Files can be source files, or precompiled files: the latter have the added interest of saving RAM and CPU on the WMP; moreover, you can strip them from their debug info, thus roughly halving their size.

$ l "multable.lua" Loading multable.lua Loaded. Eval... Learn your multiplication tables! 1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20 5 10 15 20 25 6 12 18 24 30 7 14 21 28 35 8 16 24 32 40 9 18 27 36 45 10 20 30 40 50 Done. Lua VM uses 48898 bytes. $ UPTO=5 -- change a value dynamically, $ print_table() 1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20 5 10 15 20 25 $ _

6 12 18 24 30 36 42 48 54 60

7 14 21 28 35 42 49 56 63 70

8 16 24 32 40 48 56 64 72 80

9 18 27 36 45 54 63 72 81 90

10 20 30 40 50 60 70 80 90 100

re-run without reboot!

p.10

Lua on WMP Tutorial 28th June 2007 Lets do something slightly more interesting. There are two ways to access the WMPs hardware: through a C/Lua interface, or through AT commands. The former is much faster and much more powerful, but we dont have time to demonstrate it here. Just trust us: Lua is the easiest dynamic language to interface with C, and integrates perfectly with ADL applications.

$ =at "at+cclk?" -- request the WMPs clock time = { "\r\n+CCLK: \"00/01/04,05:50:38\"", "\r\nOK" } $ =at "at+cclk?"[1] -- first string of the table. = "\r\n+CCLK: \"00/01/04,05:50:48\"", $ =at at+cclk?[1]:match"(.*)" -- capture whats between quotes in string #1 = "00/01/04,05:51:00" _

1.5.2 Threads and signals

Download the application called events.lua: l events.lua. It exploits several important features of Lua: AT commands sending and parsing. Regular expressions: a wonderful tool to parse AT command results as well as network protocols. Collaborative multitasking: function bip_on_foobar() is launched in a background task, which is woken up through signals Signals: a signal consists of an emitter, which can be anything (string, WIP channel, bearer, thread), an event (a string), and optionally some extra parameters. A thread can go to sleep until certain signals are sent (wait()), and some callback can be executed everytime a given signal is emitted (sighook()).

Now you can play with it: every time you send signal (foo,bar), the background thread wakes up and display a message, with the current date and time, gathered from an AT command. If you send signal (foo,bar), the thread terminates itself. This signalling system will be at the core of your Lua programs. Notice that if youve got a second COM port, you get traces of all important signalling events.

function bip_on_foobar() while true do -- infinite loop local ev = wait ("foo", {"bar", "close"}) if ev == "close" then print ("OK, I shut up") return -- Terminate the function, hance the thread else local time = at "at+cclk?" [1] -- Get time from an AT command time = time:match '"(.-)"' -- Extract it with a regexp print ("FOOBAR! at ", time) end end p.11

Lua on WMP Tutorial 28th June 2007 end run (bip_on_foobar) -- Run the function as a background thread function fb() signal ("foo", "bar") end

1.5.3 Threads and resources

A thread alone takes about 770 bytes; together with synchronization data, its about 1.4KB:

all the scheduling and

Lua interactive shell $ =gc() -- full garbage collector, returns used memory after collection = 48711 $ x = coroutine.create (function() end) -- atomic thread, no synchro. $ =gc() = 49485 $ =49485-48711 = 774 $ + + $ = function wait_for_godot () wait ("Godot", "enter") -- This will never happen! end =gc() 51958

$ run (wait_for_godo) -- complete thread with synchro, waiting for Godot $ =gc() = 53342 $ =53342-51958 = 1384 $ _

p.12

Lua on WMP Tutorial 28th June 2007

1.5.4 GPRS, update and commit to flash If you want to get connected on internet through GPRS, you can activate it as an additional bearer. Plug the antenna, put the SIM card, and type: $ =atat+creg? -- should answer something including +CREG: 2,1 { [] } $ wip.bearer_client("GPRS", {apn='orange-mib',login='mportail',password='mib'}) [wait] $ x=wip.tcp_client("www.google.com", 80) -- Test it $ x:write "GET / HTTP/1.0\r\n\r\n" $ =x:read() = "HTTP/1.0 302 Found\r\n []</HTML>\r\n" $ x:close()

If you want to save config across reboot, try: $ GPRS_CONFIG = { apn='orange-mib',login='mportail', password='mib'} $ function gprsup() + print Login into GPRS + wip.bearer_client("GPRS", GPRS_CONFIG) + print GPRS OK (unless you saw error msgs, in which case its KO) + end $ gprsup() -- Testing the function Login into GPRS GPRS OK (unless you saw error msgs, in which case its KO) $ save GPRS_CONFIG -- commit the config and function to flash, since it works $ save gprsup $ _

Now if you reboot, just type gprsup(): the function and config table are saved. Moreover, since the config is saved outside the function, you can alter it separately.

1.5.5 Switching TCP/IP to UART1

Some serial adapters have issues connecting to the cards UART2. The connection program looks for the UART in variable PPP_UART, so in order to make your card serve TCP/IP over UART1, what we do is send it the program: $ PPP_UART=UART1 $ save PPP_UART $ _

p.13

Lua on WMP Tutorial 28th June 2007

Session #2: Networking: play with a web server


For this entire tutorial, well assume that you use Firefox: no effort has been made to ensure cross-browser compatibility. Use other navigators at your own risks.

1.6 My first web page


Most of this session and the following one will focus on a web server, written over WIP TCP sockets. This server, by fitting in about 100 lines of code, demonstrates the power of Lua on WMP: multithreaded, with persistent connections support for mime types support for dynamic page generation caching of compiled pages Access to advanced programming techniques, such as AJAX

However, bear in mind that its a very simplistic and incomplete implementation; a complete, robust web server would be several times bigger.

The source file is in web.lua. To save some RAM, we provided a precompiled version web.luac, stripped from its debug info.

Lua interactive shell $ l "web.luac" Loading web.luac Loaded. Eval... Done. Lua VM uses 57306 bytes. $ web.start() [WEB] Starting the web server $ _ Now, just point your browser to http://192.168.1.4/: you should get the most boring webpage ever.

The site is stored in the table WEBSITE:

$ =WEBSITE = { [""] = "FOO" } $ _

p.14

Lua on WMP Tutorial 28th June 2007 Lets make that page a bit more interesting, on-the-fly:

WEBSITE[""] = [[ + <html> + <head><title>My first page</title></head> + <body> + <h1>Hello, world!</h1> + </body> + </html>]] $ _ Reload the page, enjoy.

1.7 Resources

Theres a magic table, proc, which keeps a lot of relevant information about the Lua VM:

$ =proc = { tasks = { running = [thread 0x180e7888], waiting = { [[channel TCPCLIENT 0x180cf528 ready]] = { peer_close = { { multi = true, hook = [function 0x180c6f68] }, { } }, error = { { multi = true, hook = [function 0x180c6f68] }, { } } } }, ready = { } }, bearers = { [403564040] = [userdata 0x180c4a9c], UART2 = [userdata 0x180c4a9c] }, channels = { [403598344] = [channel TCPSERVER 0x180e6c08 ready], [403601096] = [channel TCPSERVER 0x180e76c8 ready], [403502376] = [channel TCPCLIENT 0x180cf528 ready] } } $ _ Among stuff of interest here, notice the list of all waiting tasks, all active bearers, all open WIP channels. Here we see 3 channels: The telnet server Our current telnet shell (the TCPCLIENT) The web server The HTTP connection here has been closed by the browser, or a second TCPCLIENT would have appeared. If we want to know which server is the web server, lets query their port:

p.15

Lua on WMP Tutorial 28th June 2007 $ =proc.channels[403598344].port = 23 $ _ So, 403598344 is on port 23, its the telnet server. The web server must be 403601096 then. We could have checked it in a smarter way:

$ for n, ch in pairs (proc.channels) do + print("channel:", n, "port:", ch.port) + end channel: 403598344 port: 23 channel: 403601096 port: 80 channel: 403502376 port: 23 $ _ Had we more time, wed study the very powerful debug module, which lets you arbitrarily inspect and mess with live running code. Feel free to do so on your own time!

1.8 Dynamic pages

One of the interests of working with a dynamic language is that we can manipulate code very easily; thats especially handy for web pages generation, and our tiny web server has a powerful compilation-on-demand mechism: all snippets between <%...%> in a web page is supposed to be Lua code, compiled, executed, and everything it passes to function echo() is inserted in the page. It features a couple of extra nice capabilities: Compiled functions are cached, so that they dont need to be compiled twice; Theyre executed in a sandbox, which protects the global environment through a copy-on-write mechanism; This sandbox contains all relevant information on the request: URL, URL parameters, HTTP headers, mime type, serving TCP channel

Lets look at the precompilation in action:

$ l "dynapage.lua" Loading dynapage.lua Loaded. Eval... Done. Lua VM uses 65084 bytes. $ =WEBSITE['dyna.html'] = "<html>\n <head><title>Dynamically generated page</title></head>\n...

p.16

Lua on WMP Tutorial 28th June 2007 Initially, the page is just a string, as we could also have checked from the sources:

WEBSITE['dyna.html'] = [[ <html> <head><title>Dynamically generated page</title></head> <body> <h1>Dynamically generated content</h1> <p> <% for i=1,6 do echo("<font size=", i, ">", i, "&nbsp;</font>\n") end %> </p> </body> </html>]] Now, lets request the page from the browser and look again:

Dynamically generated content


1

3 4

[WEB] Handling request for "dyna.html" [WEB] Connection waiting for another request $ =WEBSITE['dyna.html'] = { "<html>\n <head><title>Dynamically generated page</title></head>\n...", [function 0x180c2770], "\n </p>\n </body>\n</html>" } Now we have three elements under index dyna.html: the part between code markers has been compiled into [function 0x180c2770], and is kept for next requests, so that recompilation wont be necessary. Of course, its much more interesting to serve data gathered from the WMP, through C bindings or AT commands. As an exercice, you can try to serve the time and serial number of the WMP through a web page; correction in dynapage-at.html.

1.9 Beyond dynamism: interactivity


To finish this session, well write an interactive web page. We will create a page which reads arbitrary at commands from a form, sends them through an HTTP PUT request, and displays the result. Since we dont expect you to be already proficient in Lua, we provide you an application which does something similar, for inspiration: this 10 lines program starts a TCP server; whatever is sent to this server is interepreted as an AT command, and the result is returned through the same channel. Since thats Lua, the program is multithreaded, can serve several clients simultaneously without mixing up the responses, and resists failure (channel closing and errors are handled outside of the thread, by a signal hook; if a channel breaks, only its thread dies, and the hook cleans the mess). The program is in at2tcp.lua.

p.17

Lua on WMP Tutorial 28th June 2007

----------------------------------------------------------------------- This function reads a line on the socket, passes it to the AT -- command parser, and writes back the result on the socket. -- The socket is properly closed upon errors and shutdowns. ---------------------------------------------------------------------function read_loop (sock) print "Received an AT connection" -- Callback to clean upon error / shutdow sighook (sock, {"error","peer_close"}, function() sock:close() end) -- Infinite loop (broken by error / shutdown) while true do local line = sock:read "*l" -- Read a line from socket (may block) line=line:match "(.-)[\r\n]*$" -- Get rid of '\r' and '\n' chars print ("Running AT command: "..line) local resp = at (line) -- Execute it, receive response lines sock:write(table.concat(resp),"\n") -- Send result lines concatenated end end ----------------------------------------------------------------------- Launch the server: everytime a connection is established, it's -- handled in a separate thread running read_loop(). ---------------------------------------------------------------------at_socket = wip.tcp_server( 2007, read_loop) The steps to follow will be: Start with a template page: we provided it in at2web.lua Look at whats returned to the phony PUT page Incorporate the relevant code, taken from the program above, into the PUT page, so that it executes tha AT command and gather its response. Make the PUT page return that text, with echo().

The starting point is is the file at2web.lua. It contains an HTML page with a form, whose action is a PUT to at-put.html. The corresponding page simply contains a call to p(params), which will print the parameters table on the shell. If we run it and submit a simple AT command, well get:

$ l at2web.lua [...] [WEB] Starting new connection [WEB] Connection waiting for another request [WEB] Handling request for "/at.html" [WEB] Connection waiting for another request [WEB] Handling request for "/at-put.html?command=AT&send=send" { command = "AT", send = "send" } [WEB] Connection waiting for another request So, when running the page at-put.html, the variable params.command contains the AT command to execute. The rest of the exercise is now straightforward: take the AT command parsing code from at2tcp.lua, and use it inside at-put.html to make the right call, and generate the response page.

p.18

Lua on WMP Tutorial 28th June 2007 Notice that there are two ways to write the at-put.html page: either extending the current function, or replace by with an HTML page with some code embedded into <%...%> markers. In both cases, the way to send text back to the browser is to call echo().

1.10

A Quick overview of Lua/C bindings

As stated, Luas greatest strength with respect to most other dynamic languages is its tight integration with C. This makes a lot of sense in an embedded context, where we often have some realtime tasks to perform, which no dynamic language (or no virtual machine and garbage collection based language, for that matter) can perform properly. Although we wont write and compile actual C/Lua bindings in this session due to lack of time, well take the couple of minutes it takes to understand hoe to call C from Lua, or Lua from C.

1.10.1 Lua calls C All of Lua capabilities are available through a C API, described in Luas reference and users manuals. However, most of the time, youll want to keep all the high level manipulations in Lua, and keep a C functions as simple as possible, exchanging integers, strings and userdata (i.e. raw C data: thats how channels and bearers are represented, for instance). All exchanges between C and Lua happen through a virtual stack. When Lua calls a C function, it pushes all the parameters on the bottom of the stack (indices 1 and following). Conversely, the C function pushes all of its results on the same stack, and returns an integer, indicating the number of meaningful results on the stack. For instance.

Therefore, C wrapper functions have the following form: Take a lua_State as a param (holding the virtual stack), return an int gather arguments from the stack perform the C routine push result(s) back on the stack return the number of results

p.19

Lua on WMP Tutorial 28th June 2007 Example: this function takes a string and two integers I and j; returns the substring between indices I and j, as well as its length: int substring( lua_State *L) { // 1. Gathering arguments // all of the luaL_checkxxx function will cause // in case of invalid or missing argument ascii *str = luaL_checkstring( L, 1); // arg int i = luaL_checknumber( L, 2); // arg int j = luaL_checknumber( L, 3); // arg // 2. Actual computation ascii *result = adl_memGet( j-i+1); strncpy( result, str+i, j-i); result[j-i]=\0; // 3. Pushing back the results lua_pushstring( L, result); adl_memRelease( result); // strings are copied when pushed, we can release it lua_pushnumber( L, j-i); return 2; // 2 results have been returned }

a clean error #1 must be a string #2 must be a number #3 must also be a number

1.10.2 C calls Lua Its sometimes convenient to call Lua from C. This is also done through the virtual stack: Push the call arguments on the virtual stack, with lua_pushxxx(). Push the function, which is typically retrieved from a global var with lua_getglobal(). call lua_call(), with the number of parameters, and the number of results. lua_pcall() does a protexted call, i.e. it will catch any error thrown by the Lua code, instead of propagating it.

p.20

Lua on WMP Tutorial 28th June 2007

2 Session #3: Overview of some sample applications


Depending on how late we ran with other sessions, this one might be substantially shortened. All the samples mentioned here are provided, as source code and potentially pre-compiled, in the ftproot directory.
This last session will be dedicated to overviewing a couple of sample applications provided on the USB key. Most of them still deal with HTTP, because its a fast and easy way to develop applications with an immediate feedback; however, lets stress again that programming the WMP in Lua is in no way limited to web pages generation. Moreover, most of the samples presented here have been developed in a couple of hours: dont expect any sort of robustness from them. More specifically, the web-based samples have only been tested against Firefox, although browser compatibility is well-known as the web developers worth nightmare.

2.1 Rapid implementation of network protocols


See file ftpc.lua
With dynamic multithreading, regular expressions parsing, and complete bindings to WIP, Lua is the perfect tool for rapid implementation of network protocols. This has already been demonstrated with the 100-odd lines web server; lets implement another typical TCP/IP protocol: FTP. Here is the code required to get a file data.txt from an FTP server; this file is here retrieved in active FTP transfer, using only WIP TCP sockets:

x = wip.tcp_client ("192.168.1.5", 21) -- x = control socket y = nil -- y = file transfer socket -- Close z, the TCP server, as soon as a first connection y is established: z = wip.tcp_server (1024, function(client) y=client; z:close() end) z:wait "accept" -- sleep until the FTP server connects to our file socket x:write "USER anonymous\r\n" x:write "PASS lua@wavecom.com\r\n" x:write "PORT 192,168,1,4,4,0\r\n" x:write "RETR data.txt\r\n" data = y:read "*a" -- The whole file is read at once (blocking call) x:write "QUIT\r\n" y:close(); x:close() -- cleanup

p.21

Lua on WMP Tutorial 28th June 2007 Active connections require the client to open a TCP server (here z, spawning a communication as y) where the actual file is received; some providers limit the ability to run a TCP server on the WMP, due to NAT issues; therefore its often safer to use the FTP passive transfer, where the FTP server opens a second TCP server socket, where the file will be served. In this case, the client is slightly more complex to write, as it has to parse the status lines in order to retrieve the passive ports number. However, this is not much more difficult to implement in Lua:

function read_status(x, msg) if msg then x:write(msg) end while true do local status, text = x:read"*l":match"^(%d%d%d) (.*)\r\n" -- regexp parsing if status then return status, text end -- multiple-values return end end x = wip.tcp_client ("192.168.1.5", 21); read_status (x) read_status(x, "USER anonymous\r\n") read_status(x, "PASS lua@wavecom.com\r\n") local status, text = read_status ("PASV\r\n", x) local a,b,c,d,e,f = text:match "(%d+),(%d+),(%d+),(%d+),(%d+),(%d+)" local addr, port = string.format ("%s.%s.%s.%s", a, b, c, d), 256*e + f y = wip.tcp_client (addr, port) -- opening of the passive connection x:write "RETR data.txt\r\n" data = y:read "*a" -- The whole file is read at once (blocking call) x:write "QUIT\r\n" y:close(); x:close() -- cleanup

2.2 XML, RSS, AT parsing, all in a single WEB application


See file websms.lua, and its compiled version websms.luac
Lets come back to web apps. Instead of just serving HTML pages, well implement an RSS feeds generator. This feed will serve the SMS stored on the SIM card; this obviously means that you need a SIM card to run it; think also of setting its pincode: at at+cpin=1234. Since RSS in an XML format, and XML formats are more and more common, well separate the XML generation from the rest of the application, for the sake of reusability. So, we just write a regular Lua table, and get it transformed on-the-fly into an XML node (see the xml() function). RSS is, as its name hints, Really Simple. Just have a look at any RSS feeds in your browser. The SMS are gathered thanks to AT command AT+CMGL, and reformatted into RSS. Moreover, a dynamic page sms-read.html?n=xxx allows to give an URL to each RSS entry, where the SMS content can be read. In addition to reading received SMS, we also allow to send some, with the Lua function sms.send(). Since HTTP PUT method limits the size of parameters, we use the POST method instead, where parameters are passed in the HTTP requests body, rather than in the URL. Access the the requests content is done through the channel environment variable, which contains the TCP socket serving the request.

p.22

Lua on WMP Tutorial 28th June 2007

The main page: a link the the RSS feed on top, and a form to send SMS.

On the left, the RSS feed page; on the right, the RSS feed as a dynamic bookmark.

When clicking on an RSS entry, the SMS content is displayed.

p.23

Lua on WMP Tutorial 28th June 2007

2.3 Logging and serving hardware-gathered data


Another simple web application is available in kbdlog.lua: it keeps count of pressed keys on the devkit, and serves a web page that sums this data up. Its easy to adapt this 20 lines script to log more interesting data (typically gathered from GPIOs, possibly through realtime C code), or to send them through other media, e.g. FTP or SMS. Notice how easy it is to update such an application, even on the field. As an example, you can start counting key releases as well as key presses, with something like:

function onkeypress (emitter, event, arg) local keynum, action = arg:match "(%d+),(%d)" if action==1 then kbdpresslog[keynum] = (kbdpresslog[keynum] or 0) + 1 else kbdreleaselog[keynum] = (kbdreleaselog[keynum] or 0) + 1 end return "again" -- don't remove the hook end

2.4 AJAX WebPhone


See code in webphone.lua, and the compiled version in webphone.luac. AJAX handling library is stored in ajax.lua.
Another GUI through a web page: This one offers a dialer, and an access to the phonebook. Whats interesting with this sample is that it uses AJAX, the technology which allows a web page to dialog with its server without requiring a page reload. Here, clicks on OK and Cancel generate AJAX requests to the WMP (OK requests are accompanied with the phone number dialled in the text input widget).

A User interface which should be familiar to anyone who ever used a cell phone.

p.24

Lua on WMP Tutorial 28th June 2007 AJAX being a feature of very broad interest, its provided in a separate ajax.lua source file. This library is able to wrap Lua functions into javascript ones: when a Lua function name is passed to ajax.bind(), here is what happens, automatically: An homonym javascript wrapping function is inserted in the web page. Whenever that function is called, it wraps its parameters as HTTP params, and sends them to the WMP through an XmlHttpRequest (a.k.a. AJAX request). On the WMP, the corresponding function has been registered in such a way that its triggered by the AJAX request; all parameters passed by javascript to the wrapper are unwrapped, and passed to the wrapped Lua function. As usual, the function can call echo() to generate a response; everything sent through echo() is sent back to the browser, which gives it back to the calling function wrapper. More precisely, since javascript is single-threaded and non-blocking, the javascript wrapper takes an extra argument: a callback function intended to receive the Lua functions response.

To run this sample, youll need to load the web server, the ajax lib, and the webphone application:

$ l web ajax webphone; web.start() Of course, reading the sources requires not to get lost between Lua and javascript code. One should also not confuse Lua code called at page generation time (in this sample, the parsing of the phonebook), and Lua code called in response to an AJAX request (here, ajax_OK() and ajax_cancel()). However, such an application, non-trivial in Lua, would probably be just unimaginable in C.

3 Readings
If youre interested into Lua, you can read these: The most authoritative book on the language: Programming in Lua, 2nd edition a.k.a. the blue PiL. Its first edition is freely available online: http://www.lua.org/pil/. The reference manual: http://www.lua.org/manual/5.1/. Projects which publicized their usage of Lua: http://www.lua.org/uses.html (obviously, there also are plenty of projects which a based on Lua, yet dont brag about it and arent listed here). Kepler, a suite of web services implemented in Lua: http://www.keplerproject.org Another embedded software company publicly using Lua for web services: http://barracudaserver.com. The lessons learned from the implementation of Adobe Photoshop Lightroom in Lua, by the team leader: http://www.lua.org/wshop05/Hamburg.pdf The most useful help resource is the mailing list: http://www.lua.org/lua-l.html The community wiki is also helpful: http://lua-users.org/wiki There also are plenty of forums, but generally of a lower standing than the mailing list A pretty comprehensive, comparative benchmark of languages: http://shootout.alioth.debian.org

p.25

Lua on WMP Tutorial 28th June 2007

4 --- Notes --Possible problems: laptops without a serial port. FIX = gather USB SERIAL converters from IT alternative FIX = get USB to work on the card, but it forces to work with a custom WIP and to mess laptops with shaggy drivers. not enough time. FIX = roughly time the demo, make a hierarchical kill-list of stuff that can be bypassed no laptop: pas de bras, pas de chocolat. Problems with winXP setup : o taken IP address fix in flash o broken COM port ??? SIM / reception config. Demos dont depend on it, just swear that it works outside of a Faraday cage. Crashes due to watchdog or memory: might happen on an alpha. memory shortage to disappear with commercial death of 8Mb mem combos.

Other suggestions: suggest guests to come with a PC preconfigured for IP over PPP over UART (config used by ppp_uart_client.c in all WIP samples)

p.26