Open at Dynamic Programming With Lua Tutorial

26
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 propriété exclusive de WAVECOM. Il ne peut être communiqué ou divulgué à des tiers sans son autorisation préalable. Printed document not updated – Document imprimé non tenu à jour OPEN AT ® DYNAMIC PROGRAMMING WITH LUA Tutorial Supprimé : F038

Transcript of Open at Dynamic Programming With Lua Tutorial

Page 1: Open at Dynamic Programming With Lua Tutorial

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 propriété exclusive de WAVECOM. Il ne peut être communiqué ou divulgué à des tiers sans son autorisation préalable.

Printed document not updated – Document imprimé non tenu à jour

OPEN AT® DYNAMIC PROGRAMMING

WITH LUA

Tutorial

Supprimé : F038

Page 2: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

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 propriété exclusive de WAVECOM. Il ne peut être communiqué ou divulgué à des tiers sans son autorisation préalable.

Printed document not updated – Document imprimé non tenu à jour

1 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 .......................ErreurErreurErreurErreur ! Signet non défini.! Signet non défini.! Signet non défini.! Signet non défini. 1.1.3 Create the connection................................ErreurErreurErreurErreur ! Signet non défini.! Signet non défini.! Signet non défini.! Signet non défini.

1.2 Other Windows software ........................................................................9

1.3 First program ..........................................................................................9 1.3.1 FTP download ...............................................................................10 1.3.2 Threads and signals ......................................................................11 1.3.3 Threads and resources ..................................................................12

2 Session #2 Networking: play with a web server .......................14

2.1 My first web page .................................................................................14

2.2 Resources .............................................................................................15

2.3 Dynamic pages......................................................................................16

3 Dynamically generated content.................................................17

3.1 Beyond dynamism: interactivity ............................................................17

3.2 A Quick overview of Lua/C bindings ......................................................19

4 Session #3 Overview of some sample applications....................21

4.1 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 24

4.4 AJAX WebPhone...................................................................................24

5 Readings ..................................................................................25

6 --- Notes ---...............................................................................26

Supprimé : F038

Supprimé : 1

Page 3: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.3

1 Session #1: Setup, Discovering the development environment

The devkits have been fitted with an OpenAT application running:

• Wavecom’s porting of Lua interpreter and virtual machine

• WIP, Wavecom’s 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 sample’s sources and the library on the USB key.

This first session’s 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 devkit’s 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 computer’s COM1.

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

Page 4: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.4

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 > “Don’t Detect my Modem” > Communication cable between two computers > COM1 > Finish

Page 5: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.5

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:

Page 6: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.6

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 connection’s properties

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

Page 7: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.7

Network config > Check “Internet Protocol (TCP/IP)”

Connect:

Page 8: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.8

That’s it; you’re connected to your WMP100 through a TCP/IP link. You can check by pingin the module:

Page 9: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.9

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

1.4 Other Windows software

To work comfortably, you’ll need:

• An FTP serverFTP serverFTP serverFTP server: the WMP can download programs straight from your PC. There’s one on the USB key if you don’t already have one. Configure it to accept anonymous downloads, and set the anonymous FTP root to the ftproot directory.

• A web browserweb browserweb browserweb browser: we’ll play a lot with a web server, and samples have only been tested against Firefox.

• A telnet clienttelnet clienttelnet clienttelnet client. If you don’t already have one, PuTTY is available on the USB key.

• A text editortext editortext editortext editor. You’ve probably got one, which might or might not offer Lua syntax highlight. We’ve also provided a Lua syntax aware editor on the key

• If we have time for low-level network hacking, you’ll need netcatnetcatnetcatnetcat, the network’s Swiss army knife.

Setting up WSetting up WSetting up WSetting up WSFTPSFTPSFTPSFTP

At first launch, open windows firewall for FTP if it’s 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…

That’s it with the setup.That’s it with the setup.That’s it with the setup.That’s 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 you’ll 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 $ _

Page 10: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.10

$ 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 shouldn’t 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, you’ll 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 doesn’t 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 you’ll 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 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30 4 8 12 16 20 24 28 32 36 40 5 10 15 20 25 30 35 40 45 50 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 Done. Lua VM uses 48898 bytes. $ UPTO=5 -- change a value dynamically, re-run without reboot! $ 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 $ _

Page 11: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.11

Let’s do something slightly more interesting. There are two ways to access the WMP’s hardware: through a C/Lua interface, or through AT commands. The former is much faster and much more powerful, but we don’t 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 WMP’s 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 what’s 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 you’ve 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

Page 12: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.12

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 all the scheduling and synchronization data, it’s about 1.4KB:

Lua interactive shell $ =gc() -- full garbage collector, returns used memory afte r 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 $ _

Page 13: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.13

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:

$ =at”at+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 w hich case it’s KO)” + end $ gprsup() -- Testing the function Login into GPRS… GPRS OK (unless you saw error msgs, in which case i t’s KO) $ save ‘GPRS_CONFIG’ -- commit the config and function to flash, since i t 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 card’s 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’ $ _

Page 14: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.14

Session #2: Networking: play with a web server

For this entire tutorial, we’ll 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 it’s 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" } $ _

Page 15: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.15

Let’s 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

There’s a magic table, proc , which keeps a lot of relevant information about the Lua

VM:

$ =proc = { tasks = { running = [thread 0x180e7888], waiting = { [[channel TCPCLIENT 0x180cf528 read y]] = { 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 rea dy], [403601096] = [channel TCPSERVER 0x180e76c8 rea dy], [403502376] = [channel TCPCLIENT 0x180cf528 rea dy] } } $ _

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, let’s query their port:

Page 16: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.16

$ =proc.channels[403598344].port = 23 $ _

So, 403598344 is on port 23, it’s 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, we’d 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; that’s 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 don’t need to be compiled twice;

• They’re 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…

Let’s 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 pag e</title></head>\n...

Page 17: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.17

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, let’s request the page from the browser and look again:

Dynamically generated content

1 2 3 4 5 6

[WEB] Handling request for "dyna.html" [WEB] Connection waiting for another request $ =WEBSITE['dyna.html'] = { "<html>\n <head><title>Dynamically generated pag e</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 won’t be necessary.

Of course, it’s 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, we’ll 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 don’t 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 that’s 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 .

Page 18: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.18

--------------------------------------------------- ------------------- -- This function reads a line on the socket, passes it to the AT -- command parser, and writes back the result on th e socket. -- The socket is properly closed upon errors and sh utdowns. --------------------------------------------------- ------------------- 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 est ablished, 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 what’s 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, we’ll 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.

Page 19: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.19

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, Lua’s 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 won’t write and compile actual C/Lua bindings in this session due to lack of time, we’ll 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 Lua’s reference and user’s manuals. However, most of the time, you’ll 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: that’s 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

Page 20: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.20

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 a clean error // in case of invalid or missing argument ascii *str = luaL_checkstring( L, 1); // arg #1 must be a string int i = luaL_checknumber( L, 2); // arg #2 must be a number int j = luaL_checknumber( L, 3); // arg #3 must also be a number // 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 i t lua_pushnumber( L, j-i); return 2; // 2 results have been returned }

1.10.2 C calls Lua

It’s 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.

Page 21: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.21

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 it’s a fast and easy way to develop applications with an immediate feedback; however, let’s 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: don’t 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 developer’s 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; let’s 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 conn ection 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 [email protected]\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

Page 22: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.22

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 it’s 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 port’s 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 [email protected]\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

Let’s come back to web apps. Instead of just serving HTML pages, we’ll 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, we’ll 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 request’s body, rather than in the URL. Access the the request’s content is done through the channel environment variable, which contains the TCP socket serving the request.

Page 23: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.23

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.

Page 24: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.24

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. It’s 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] = (kbdpr esslog[keynum] or 0) + 1 else kbdreleaselog[keynum] = (kbdreleaselog[keyn um] 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. What’s 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.

Page 25: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.25

AJAX being a feature of very broad interest, it’s 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 it’s 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 function’s response.

To run this sample, you’ll 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 you’re 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 don’t brag about it and aren’t 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

Page 26: Open at Dynamic Programming With Lua Tutorial

Lua on WMP – Tutorial 28th June 2007

p.26

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 don’t 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)

_