Luup Lua extensions

From MiOS
(Difference between revisions)
Jump to: navigation, search
Line 199: Line 199:
 
== Module: luup.chdev ==
 
== Module: luup.chdev ==
  
Contains functions for a parent to synchronize its child devices.  Whenever a device has multiple end-points, the devices are represented in a parent/child fashion where the parent device is responsible for reporting what child devices it has and giving each one a unique id.  For example in the sample [[Luup_Somfy_Walkthrough]] there is a parent device, which is the interface module that controls up to 16 blinds, and up to 16 child devices, one for each blind.  As shown in that sample, the parent calls start, then enumerates each child device with append, and finally calls sync.
+
Contains functions for a parent to synchronize its child devices.  Whenever a device has multiple end-points, the devices are represented in a parent/child fashion where the parent device is responsible for reporting what child devices it has and giving each one a unique id.  For example in the sample [[Luup_Somfy_Walkthrough]] there is a parent device, which is the interface module that controls up to 16 blinds, and up to 16 child devices, one for each blind.  As shown in that sample, the parent calls start, then enumerates each child device with append, and finally calls sync.  You will need to pass the same value for device to append and sync that you passed to start.
  
 
=== function: start ===
 
=== function: start ===
Line 208: Line 208:
  
 
Tells Luup you will start enumerating the children of device.  If device is a string it is interpreted as a udn, if it's a number, as a device id.  The return value is a binary object which you cannot do anything with in Lua, but you do pass it to the append and sync functions.
 
Tells Luup you will start enumerating the children of device.  If device is a string it is interpreted as a udn, if it's a number, as a device id.  The return value is a binary object which you cannot do anything with in Lua, but you do pass it to the append and sync functions.
 
  
 
=== function: append ===
 
=== function: append ===
Line 216: Line 215:
 
returns: nothing
 
returns: nothing
  
Enumerates one child of device.  If device is a string it is interpreted as a udn, if it's a number, as a device id.  Pass in the ptr which you received from the start function.  Give each child a unique id so you can keep track of which is which.  You can optionally provide a description which the user sees in the user interface.  device_type is the UPnP device type, such as urn:schemas-upnp-org:device:BinaryLight:1.  If device_filename is specified, that is the name of the xml file with the UPnP device specification.  The deviceType from the filename will override any device_type you set manually.  If the device_file contains the implementation file for this child device you do not need to specify it in implementation_filename.  Otherwise, if there is a Luup implementation for this child device and it's not being handled by the parent device, you can specify it in implementation_filename.   
+
Enumerates one child of device.  If device is a string it is interpreted as a udn, if it's a number, as a device id.  Pass in the ptr which you received from the start function.  Give each child a unique id so you can keep track of which is which.  You can optionally provide a description which the user sees in the user interface.  device_type is the UPnP device type, such as urn:schemas-upnp-org:device:BinaryLight:1.  If device_filename is specified, that is the name of the xml file with the UPnP device specification.  The deviceType from the filename will override any device_type you set manually.  If the device_file contains the implementation file for this child device you do not need to specify it in implementation_filename.  Otherwise, if there is a Luup implementation for this child device and it's not being handled by the parent device, you can specify it in implementation_filename.  If embedded is true, the 'embedded' flag is set for the device which generally means that the parent and all the children will be displayed as one compound device, or group, rather than as separate devices which you can put in their own rooms.
  
 +
The parameters are upnp service+variables you want set when the device is created.  You can specify multiple variables by separating them with a line feed (\n) and use a , and = to separate service, variable and value, like this: service,variable=value \n service... 
  
**fix parameters**
+
=== function: sync ===
  
 +
parameters: device (string or number), ptr (binary object),
  
= editing: =
+
returns: nothing
 
+
lu_wget(URL,Timeout,Username,Password)
+
 
+
This reads the URL and returns 2 variables: The first is a numeric error code which is 0 if successful, and the second is a string containing the contents of the page. If Timeout is specified, the function will timeout after that many seconds. If Username and Password are specified, they will be used for HTTP authentication.
+
 
+
=== Reporting child devices ===
+
 
+
These functions are for reporting to the Luup engine the child devices you have. First call lu_chdev_start with the id of the parent device and store the return value in a variable. The return value is a Lua type "userdata", meaning it's a binary object that you can't do anything with in Lua, other than pass it back to the Luup engine. Next call lu_chdev_append for each child device, passing in the device id of th parent, the binary object, a string with an internal ID you use to reference the child, a string with a description of the child, the UPNP device type, the UPNP device filename, the UPNP Luup Implementation filename, any variables you want to set (ie parameters), and a boolean true/false which, if true, means the child is "embedded" within the parent, and will appear in the UI as part of the parent device, rather than a separate device you can put in it's own room. Lastly call lu_chdev_sync passing in the device number of the parent and that same binary object. When you pass in the variables, or parameters, use the syntax:  
+
 
+
Service,Variable=value\n
+
 
+
and pass in as many variables as you want, separated with a line feed. There is a sample in the [[Luup Somfy Walkthrough]]
+
  
lu_chdev_append(int iDevice|string sUDN, Child_Device *pChildDevice,string sID,string sDescription,string sDeviceType,string sUpnpDevFilename,string sUpnpImplFilename,string sParameters,bool bEmbedded)
+
If device is a string it is interpreted as a udn, if it's a number, as a device id.  Pass in the ptr which you received from the start function.  Tells the Luup engine you have finished enumerating the child devices.  If the child devices have changed in anyway, the new device tree will be written to the configuration file and the Luup engine is reset.
  
lu_chdev_start(int iDevice|string sUDN)
+
== module: io ==
  
lu_chdev_sync(int iDevice|string sUDN, Child_Device *pChildDevice)
+
=== function: open ===
  
 
=== I/O data ===
 
=== I/O data ===

Revision as of 23:05, 8 August 2009

In addition to the [Lua] commands described in the [Lua reference manual], you can also reference in your Lua code variables and functions from modules which the Luup engine provides as follows:

Contents

Module: luup

These are general purpose functions and variables. Call them by using the luup. module, such as:

luup.log('Now running version: ' .. luup.version)

variable: version

Contains the version of the luup engine, such as "1.0.843", as a string.

variable: longitude

Contains the longitude as a number, as found on the location tab in the setup UI.

variable: latitude

Contains the latitude as a number, as found on the location tab in the setup UI.

variable: timezone

Contains the timezone as a number, as found on the location tab in the setup UI.

variable: city

Contains the city as a string, as found on the location tab in the setup UI.

variable: devices

Contains all the devices in the system as a table indexed by the device number. The members are: room_num (number), device_type (string), category_num (number), device_num_parent (number), ip (string), mac (string), id (string), description (string), udn (string). See also: Lua Device Structure. Example to log device #5's IP addess and it's internal ID:

 luup.log('Device #5 ip: ' .. luup.devices[5].ip .. ' id: ' .. luup.devices[5].id)

room_num: This is the number of the room the device is in.

device_type: This is a number representing the type of device. See: Luup Device Types Categories for a list.

category_num: This is a category for the device. See: Luup Device Types Categories

device_num_parent: This is the number of the parent device. See: Lua Device Structure for details.

ip: If this device is IP based, this is the IP address.

mac: If this device is IP based, this is the MAC address.

id: If this device has an internal ID that is specific to the device, it is contained here. For example, for Z-Wave devices this is the Node ID, and for Insteon device it is the Insteon ID.

description: This is the text description for the device as supplied by the user in the web ui.

udn: This is the UDN for the UPnP device.

This code will log all the attributes from all the devices:

 for k,v in pairs(lug_device) do
   for k2,v2 in v
     lu_log("Device #" .. k .. ":" .. k2 .. "=" .. "v2")
   end
 end

variable: rooms

Contains all the rooms as a table of strings indexed by the room number. Example:

 luup.log('Room #1 is called: ' .. luup.rooms[1])

variable: scenes

Contains all the scenes in the system as a table indexed by the device number. The members are: room_num (number), description(string)

variable: remotes

Contains all the remotes in the system as a table indexed by the remote id. The members are: remote_file (string), room_num (number), description(string)

function: log

parameters: what_to_log (string), log_level (optional, number)

return: nothing

Writes what_to_log to the log, /var/log/cmh/LuaUPnP.log, with the given log_level, which is 50 by default. See: Luup_Loglevels

function: call_delay

parameters: function_name (string), seconds (number), data (string)

returns: result (number)

The function 'function_name', which must be passed as a string, will be called in 'seconds' seconds, and will be past the string 'data'. The function returns 0 if successful. See: Luup_Declarations#timed_function_callback for the names and syntax of the parameters that will be passed to function_name. function_name will only be called once and you must call call_delay again if you want it called again, or use call_timer instead.

function: call_timer

parameters: function_name (string), type (number), time (string), days (string), data (string)

returns: result (number)

The function 'function_name', which must be passed as a string, will be called when the timer is triggered, and will be past the string 'data'. The function returns 0 if successful. See: Luup_Declarations#timed_function_callback for the names and syntax of the parameters that will be passed to function_name.

Type is 1=Interval timer, 2=Day of week timer, 3=Day of month timer, 4=Absolute timer. For an interval timer, days is not used, and Time should be a number of seconds, minutes, or hours using an optional 'h' or 'm' suffix. Example: 30=call in 30 seconds, 5m=call in 5 minutes, 2h=call in 2 hours. For a day of week timer, Days is a comma separated list with the days of the week where 1=Monday and 7=Sunday. Time is the time of day in hh:mm:ss format. Time can also include an 'r' at the end for Sunrise or a 't' for Sunset and the time is relative to sunrise/sunset. For example: Days="3,5" Time="20:30:00" means your function will be called on the next Wed or Fri at 8:30pm. Days="1,7" Time="-3:00:00r" means your function will be called on the next Monday or Sunday 3 hours before sunrise. Day of month works the same way except Days is a comma separated list of days of the month, such as "15,20,30". For an absolute timer, Days is not used, and Time should be in the format: "yyyy-mm-dd hh:mm:ss"

Data can be a string passed back to the function. The function should be declared so it takes a single argument, which is this data.

function refreshCache(stuff)
    ....
end

function startup()
    --
    -- Setup an interval-based timer to call refreshCache after 30 minutes.
    -- Note that if you want it to "recur" then you need to call this function again
    -- at the end of the refreshCache() implementation.
    --
    lu_CallFunctionTimer("refreshCache", 1, "30m", "", "SomeStuff")
end

call_action

parameters: service (string), action (string), arguments (table), device (string or number)

returns: error (number), error_msg (string), job (number), arguments (table)

Invokes the UPnP service + action, passing in the arguments (table of string->string pairs) to the device, which, if it's a string, is interpreted as a udn, and if it's a number, is the device number. If the invocation could not be made, only error will be returned with a value of -1. Otherwise, all 4 values are returned. error is 0 if the UPnP device reported the action was successful. arguments is a table of string->string pairs with the return arguments from the action. If the action is handled asynchronously by a Luup job, then the job number will be returned as a positive integer.

Example to dim device #5 to 50%:

 local lul_arguments = {}
 lul_arguments["newLoadlevelTarget"]=50
 lul_resultcode,lul_resultstring,lul_job,lul_returnarguments = luup.call_action("urn:upnp-org:serviceId:Dimming1","SetLoadLevelTarget",lul_arguments,5)

function: variable_set

parameters: service (string), variable (string), value (string), device (string or number)

returns: nothing

The UPnP service+variable will be set to value for device, which if it's a string, is interpreted as a udn, and if it's a number, as a device id. If there are events or notifications tied to the variable they will be fired.

function: variable_get

parameters: service (string), variable (string), device (string or number)

returns: value (string), time (number)

If the service+variable or device does not exist, it returns nothing. Otherwise it returns the value of the UPnP service+variable and the time when the variable was last modified, as a unix time stamp (number of seconds since 1/1/1970). You can assign just the value to a variable, as follows:

 local value = luup.variable_get("urn:upnp-org:serviceId:Dimming1","LoadLevelTarget",5)
 luup.log("Dim level for device #5 is: " .. value)

function: register_handler

parameters: function_name (string), request_name (string)

returns: nothing

When a certain URL is requested from a web browser or other HTTP get, function_name will be called and whatever string it returns will be returned.

See the WAP mobile phone plugin as an example:

 luup.register_handler("lug_WapRequest","wap")
 function lug_WapRequest(lul_request,lul_parameters,lul_outputformat)

local lul_html = "<head>\n" .. "<title>Main</title>\n" .. "</head>\n" .. "<body>\n" .. "Choose a room:
\n"

 end

The request is made with the URL: data_request?id=lr_[the registered name] on port 49451. So: http://192.168.1.1:49451/data_request?id=lr_wap will return the web page defined in the function lug_WapRequest in the example above.

function: variable_watch

parameters: function_name (string), service (string), variable (string or nill), device (string or number)

returns: nothing

Whenever the UPnP variable is changed for the specified device, which if a string is interpreted as a udn and if a number as a device id, function_name will be called. See Luup_Declarations#watch_callback for the values that will be passed to function_name. If variable is nill, function_name will be called whenever any variable in the service is changed.


function: devices_by_service

parameters:

returns:

function: device_supports_service

parameters:

returns:

function: set_failure

parameters: value (boolean), device (string or number)

returns:

Luup maintains a 'failure' flag for every device to indicate if it is not functioning. You can set the flag to true if the device is failing. If device is a string it is interpreted as a udn, if it's a number, as a device id.

Module: luup.chdev

Contains functions for a parent to synchronize its child devices. Whenever a device has multiple end-points, the devices are represented in a parent/child fashion where the parent device is responsible for reporting what child devices it has and giving each one a unique id. For example in the sample Luup_Somfy_Walkthrough there is a parent device, which is the interface module that controls up to 16 blinds, and up to 16 child devices, one for each blind. As shown in that sample, the parent calls start, then enumerates each child device with append, and finally calls sync. You will need to pass the same value for device to append and sync that you passed to start.

function: start

parameters: device (string or number)

returns: ptr (binary object)

Tells Luup you will start enumerating the children of device. If device is a string it is interpreted as a udn, if it's a number, as a device id. The return value is a binary object which you cannot do anything with in Lua, but you do pass it to the append and sync functions.

function: append

parameters: device (string or number), ptr (binary object), id (string), description (string), device_type (string), device_filename (string), implementation_filename (string), parameters (string), embedded (boolean)

returns: nothing

Enumerates one child of device. If device is a string it is interpreted as a udn, if it's a number, as a device id. Pass in the ptr which you received from the start function. Give each child a unique id so you can keep track of which is which. You can optionally provide a description which the user sees in the user interface. device_type is the UPnP device type, such as urn:schemas-upnp-org:device:BinaryLight:1. If device_filename is specified, that is the name of the xml file with the UPnP device specification. The deviceType from the filename will override any device_type you set manually. If the device_file contains the implementation file for this child device you do not need to specify it in implementation_filename. Otherwise, if there is a Luup implementation for this child device and it's not being handled by the parent device, you can specify it in implementation_filename. If embedded is true, the 'embedded' flag is set for the device which generally means that the parent and all the children will be displayed as one compound device, or group, rather than as separate devices which you can put in their own rooms.

The parameters are upnp service+variables you want set when the device is created. You can specify multiple variables by separating them with a line feed (\n) and use a , and = to separate service, variable and value, like this: service,variable=value \n service...

function: sync

parameters: device (string or number), ptr (binary object),

returns: nothing

If device is a string it is interpreted as a udn, if it's a number, as a device id. Pass in the ptr which you received from the start function. Tells the Luup engine you have finished enumerating the child devices. If the child devices have changed in anyway, the new device tree will be written to the configuration file and the Luup engine is reset.

module: io

function: open

I/O data

lu_iop_intercept_incoming

lu_iop_open

lu_iop_recv_block

lu_iop_send

Job Handling

lu_job_set

lu_job_get

Personal tools