Live Documentation

Live Documentation describes how lua-scripts can find out what their environment looks like, e.g. which functions there are and how to use them. Lua-scripts have several means of reporting their findings back to you as the script-developer.

You can make them log their results using androids logcat system via debug.log(). If you want to use this feature, you best connect to your Phone via a PC and android-tools. You will have to enable this under `Access` → `Android Debug Bridge`. The adb-tool is provided by google, there are lots of external resources that explain how to get log's via adb. In a pinch you could also download the most recent's logs from the phones Web-UI.

You can also report short strings using system.toast("hello world").

The most immediate way is to have a miniature lua-script running on your phone. You'll send lua-code via http, the scripts executes it and returns the result. Read this for more details.

Lua itself is somewhat auto-discoverable. Though it doesn't have native documentation, you can use it to discover which lua-functions are available by scanning the global table. We've written a script to take a look around. In firmware version 1.6 this script reports the following:

Example output of above script in 1.6:

global-tables: string, package, key, table, bit32, sip, debug, async, system, io, http, dialog, xml, _G, json, bluetooth, time, math, coroutine, phoneInfo, shared, config
global-functions: xpcall, tostring, print, require, pairs, setmetatable, next, assert, rawlen, ipairs, tonumber, rawequal, onKeyUp, collectgarbage, load, getmetatable, rawset, pcall, type, select, rawget, dofile, error, loadfile
global-strings: _VERSION = Luaj 0.0
  string-functions: sub, find, rep, match, gmatch, char, dump, reverse, upper, len, gsub, byte, format, lower
  package-tables: preload, searchers, loaded
  package-functions: loadlib, searchpath
  package-strings: path = /system/vendor/lib/lua/?.lua
    searchers-functions: 1
  key-functions: setInfo, setTitle, setIcon, setLed
  table-functions: remove, pack, concat, sort, insert, unpack
  bit32-functions: band, lrotate, extract, rshift, bor, bnot, arshift, bxor, replace, lshift, btest, rrotate
  sip-tables: calls, identities
  sip-functions: invite, subscribe, unsubscribe
    calls-functions: resume, terminate, accept, listen, get_all, hold, transfer, join, conference, make, dtmf, stop_listen
    identities-functions: is_active, stop_listen, listen
  debug-functions: getDocu, log, getLoadableLibs
  async-functions: async
  system-functions: toast
  io-tables: stderr, stdout
    stderr-functions: read
    stdout-functions: read
  http-functions: post, put, request, get, listen, stop_listen
  dialog-functions: show
  xml-functions: eval, append, appendtext, tostring, find, new
  xml-numbers: TAG = 0
  json-functions: object, eval, insert, array, tostring
  bluetooth-functions: registerRangeCheck, unregisterRangeCheck
  time-functions: sleep, unregister, register, callbackIn
  math-functions: log, exp, acos, atan, ldexp, deg, rad, tan, cos, cosh, random, frexp, randomseed, ceil, tanh, floor, abs, max, sqrt, modf, sinh, asin, min, fmod, pow, atan2, sin
  math-numbers: pi = 3.1415927, huge = inf
  coroutine-functions: running, resume, yield, status, wrap, create
  phoneInfo-functions: getBrand, getMacAddress, getIPs, getModel, getFwVersion
  config-functions: unregister, set, get, register

Here you can see for example that there is a globally available sip-table and it has 3 functions: invite(), subscribe() and unsubscribe()

  sip-functions: invite, subscribe, unsubscribe

With version 1.4 we started to add documentation to our functions. I.e. those funtions that we've written so you can have access to the phone. Standard functions that are available in every lua-environment dont have any such documention, same goes for externally developed plugins like the penlight-library.

You can find a simple script that logs the documentation for sip.invite() here.

We recommend to use curl and our interactive script when you are developing new lua-scripts/-templates.

Example usage for getting the documentation interactivly via curl:

$ curl -k -H "Authorization: tZsvAMV8mhBZh$goWgk},n,USJj;,zEZ" -i "https://192.168.1.101/api/v1/exec/interactive.lua" --data 'return debug.getDocu(sip.invite)'
HTTP/1.1 200 OK
...
Content-Type: text/plain

nil sip.invite( uri:string [, pickup:boolean/default=false] [, line:int] [, hidden:boolean/default=false] )
? sip.invite{ uri=string [pickup=boolean/default=false] [line=int] [hidden=boolean/default=false] [returnHttpResult:boolean/default=false] }

Send an invite, aka makes a call to the specified uri. Uri can be just a telephone-number or a complete sip-uri.
Attemps a pickup if pickup-parameter is true.
line is the number of the identity to use. When not set the default identity (see idle-screen) is used.
With hidden=true -> call will not be shown on the phones display. It won't have audio either.
If you set returnHttpResult to true, the function will return the result of the operation.
 Result consists of multiple values, see http.listen()-callback-description for details.
returns nil unless returnHttpResult==true

Some of our lua-api-functions like sip.calls.get_all() provide dynamic call-objects. These have their own member-functions with documentation but it's a little tricky to inquire lua about them. We've found that the open source library inspect does a nice job of listing the available functions. The phone does not come with the inspect library installed but you can easily add it. After you've installed it you can use curl and our interactive script. Be sure your phone has ongoing calls before you try this:

Example usage for getting the functions of a dynamic call-object:

$ curl -k -i "https://192.168.1.101/api/v1/exec/interactive.lua?AuthToken=..." --data 'return require "inspect"(getmetatable(sip.calls.get_all()[1]))'
HTTP/1.1 200 OK
...
Content-Type: text/plain

{
  __index = {
    accept = <function 1>,
    conference = <function 2>,
    dtmf = <function 3>,
    getDisconnectCause = <function 4>,
    getId = <function 5>,
    getIdentityIndex = <function 6>,
    getRemote = <function 7>,
    getState = <function 8>,
    hold = <function 9>,
    isIncoming = <function 10>,
    isOutgoing = <function 11>,
    join = <function 12>,
    resume = <function 13>,
    terminate = <function 14>,
    transfer = <function 15>
  },
  __tostring = <function 16>
}

This is how you then get the documentation for a single function (note the `.` between call-object and it's function):

$ curl -k -i "https://192.168.1.101/api/v1/exec/interactive.lua?AuthToken=..." --data 'return debug.getDocu(sip.calls.get_all()[1].getState)'
HTTP/1.1 200 OK
...
Content-Type: text/plain

string call:getState()

Get the state of the call.
Returns one of the following Strings:
- calling (outgoing call that was not yet active (i.e. connected))
- ringing (incoming call that was not yet active (i.e. connected))
- active (connected call)
- holding (call was put on hold, i.e. this phone is holding the other party)
- disconnected (call has ended)
- unknown (fallback)

Lastly this is the way to call such a member-function (note the `:` between call-object and it's function):

$ curl -k -i "https://192.168.1.101/api/v1/exec/interactive.lua?AuthToken=..." --data 'return sip.calls.get_all()[1]:getState()'
HTTP/1.1 200 OK
...
Content-Type: text/plain

active

We've also added debug.getLoadableLibs() to list all modules that can be additionally used in your scripts using require. In 1.4 this only lists the modules of the luaLibraries. Since 1.6 it also provides the 'baked-in' libraries we've added into the firmware (currently a subset of the penlight library).

You can see the output in the logs using this script or you send the following two lines to the above mentioned interactive script:

local stringx = require "pl.stringx"
return stringx.join(", ", debug.getLoadableLibs())

Example output:

callforward, pl.List, pl.Map, pl.MultiMap, pl.OrderedMap, pl.Set, pl.class, pl.compat, pl.lexer, pl.pretty, pl.strict, pl.stringx, pl.tablex, pl.types, pl.utils