Luup Plugins
If you didn't already come from the Luup_Intro page, start there to see what Luup Plugins are intended for.
Contents |
Introduction to UPnP
UPnP (Universal plug and play) is the industry-standard way to communicate with devices. In UPnP the device that is doing the controlling (ie the remote control) is called a UPnP Control Point. The device which can be controlled is the UPnP Device. You describe the capabilities of a UPnP Device and tell the UPnP Control Points what the device can do by creating 2 types of XML files: 1) a single device specification file which has basic information on your device such as the manufacturer and model, and 2) one or more service specification files which describe a service. In UPnP a "service" is a list of variables and actions. Variables describe the current state of the device and actions describe what you can do with the device.
For example, a common service is "SwitchPower". This service describes the ability to turn something on and off. The main variable in the service is called "Status", and it has a value of 0 if the device is currently off or 1 if it's currently on. The main action in the service is called "SetTarget" which is how you turn the power on or off. The "SetTarget" action has an argument called "newTargetValue" which can be either 0 or 1 to indicate if the device should be turned on or off. Variables, then, are outgoing data from the UPnP Device to the UPnP Control Point, and actions are incoming data from the UPnP Control Point to the UPnP Device. Let's say your UPnP device is a light switch. The UPnP Control Point is perhaps a touch-screen web pad, and it will display an icon of a light switch to let the user control your UPnP light switch. The Control Point will first ask the UPnP light switch for the current value of the "Status" variable. If the variable is currently 1, the Control Point will display the light switch in the 'on' position. Now, if the user hits the 'off' button on the UPnP control point it sends the UPnP light switch a "SetTarget" action with the argument "newTargetValue" equals 0. After the light switch successfully turns off, the variable "Status" will change to 0 so anytime a UPnP control point that wants to know if the light is on or off can ask the light switch for the current value of the "Status" variable.
In the UPnP device's device description xml file there is a list of the services that the device implements with a cross reference to the service file. Whenever possible a service should be as small and re-usable as possible so other devices can use the same service file without creating the service's again from scratch. For example, there are both dimmable light switches, and simple on/off switches. Both kinds of switches support the ability to turn on and off, dimmable ones just add the ability to dim also. So, the most efficient thing to do is have a service called "SwitchPower" which describes the action to turn the switch on and off, and to have a separate service called "Dimming" which describes the action to dim the light. The on/off switch will support only the "SwitchPower" service, and the dimmable switch will support both the "SwitchPower" and the "Dimming" service. This is better than creating a "Dimming" service which does both on/off and dimming because if you did that, the maker of a UPnP control point would need to implement 2 different actions for the basic on/off. You do not want to make an individual service do more than one thing.
The UPnP forum is an industry consortium that approves specifications for UPnP devices. They have already approved standards for SwitchPower, Dimming, and so on. We will not want to modify these device or service specifications. We use them as they were ratified by the committee because that is what UPnP Control Points will be expecting. However there are lots of devices which the UPnP forum has not yet come up with a standard for. In this case each vendor can come up with his own solution. However, if there is an existing device+service specification that is already in use, particularly by a large company in the industry, we should use their device+service specifications (ie XML files) whenever possible since there are probably already UPnP Control Points out there that know how to talk to them.
Introduction to Luup plugins
The UPnP specifications define what the XML files look like and how a UPnP Control Point talks to a UPnP Device to get the current Variables and to send the device Actions. But that's where UPnP ends; it does not define the implementation, which is to say, how the device will implement the action. Normally UPnP devices write programming code to handle the implementation. Luup instead lets you store the implementation in a 3rd type of XML file we call the implementation file. In the implementation file you tell Luup what to do when it receives an action from a UPnP Control Point. The implementation file can contain infrared codes which Loop will send when the action comes in, binary data which Luup will send out a serial port, or some Lua code that Luup will run. The Lua code can set the current value of the variables for the device.
Luup handles all the complexities of the UPnP protocol. And the web-based Luup plugin generator handles all the complexities of XML (coming soon). So all you do is fill in the form which has basic information about your device, like the manufacturer and model, and the generator creates the UPnP Device specification for you. You can then check off which services your device implements, such as "SwitchPower" if it's something that can be turned on and off. If your device has new capabilities that aren't already in an existing service, the generator let's you create a new service by describing the actions your device implements, like "Brightness Up", or "Sensor Arm", etc. Lastly, the web generator let's you specify what to do when the action comes in. This is saved in the implementation file.
There is not necessarily a 1:1 relationship between an implementation file and either device or specification files. For example, you may create a device which has some of the Lua code in one implementation file, and some other Lua code in another implementation file. The same implementation file can contain both infrared codes, serial data, and Lua code.
Luup also supports the concept of parent-child, or embedded, devices. For example, the Global Cache gc-100 is an ethernet device that contains a couple serial ports, some relay switches, some infrared transmit ports, and some on/off input sensors. Each relay/sensor/ir/serial port is logically a separate device, since each one can do something distinct. One relay could be connected to a doorbell, the other to a siren. So, in Luup there is one parent device called the "gc100", which actually doesn't have any UPnP services at all, but it has child devices for each of the sensors/relays/ports. The relays are logically like on/off switches, so rather than creating our own service, we use the standard UPnP device for a binary switch with the standard UPnP service "SwitchPower". This way any UPnP control point will see the relays and, without any custom work for the gc100, the control point can show them to the user as an on/off switch. There are other device+service files for the inputs and ports. In Luup you have the concept of a parent device being able to be responsible for the child devices. So, the way we implemented the gc100 is that the parent device has no UPnP services, but it does have a single implementation file "I_GC100.xml", which tells Luup how to implement all the actions from all the services that it's child devices may have. So in this case, there is one implementation file for many devices and services. We could have broken this into separate implemenation files, for example one for each service. However since the implementation is specific to the gc100 and not likely to be re-usable with another device, we just put all the gc100 implementation in a single file. You may want to add support for some other type of on/off switch and you could do that by using the same standard UPnP device+specification files, but instead you would create your own implementation file. The UPnP Control Point will never know the difference; it just sees a standard a UPnP light switch device and sends the 'on/off' actions the same way.
Description of the XML files
Because the web generator is not yet operational you need to create the XML files by hand. The easiest way to do this is to start with an existing device as a template that you modify to suit your needs. In Vera's Setup Web UI, choose Devices, Luup plug-ins. There is a list of all the XML files which came with Vera by default. Files that start with D_ are UPnP device specifications. Files that start with S_ are UPnP service specifications. And files that start with I_ are Luup implementation files. Click a file to view it's contents.
When you open a device specification file the xml tag deviceType defines what kind of device it is. This is how a UPnP Control Point knows what this device is. If the device type starts with urn:schemas-upnp-org, that means it's a UPnP defined standard, and the list of services the device must support are defined by the UPnP forum. If you're creating your own device type you can substitute the schemas-upnp-org with your own web domain name and change the other parts of the name. But stick to the same convention and use only a-z, 0-9 and hypens (-) and colons (:). Remember though that if you use your own device type chances are UPnP Control Points won't know what to do with it unless the author of the control point makes a custom addition for you.
The device file references the service files (S_) and gives each service a serviceType and a serviceId. The serviceType what defines the standard UPnP service. But since it's possible to have multiple instances of a given service, each needs a unique serviceId. For example, there is a standard UPnP service to set the setpoint on a thermostat called: urn:schemas-upnp-org:service:TemperatureSetpoint:1. But many thermostats have multiple setpoints, such as heat and cool. So in the standard for a UPnP thermostat device (D_HVAC_ZoneThermostat1.xml), there are 2 instances of the serviceType "urn:schemas-upnp-org:service:TemperatureSetpoint:1", one has the id "urn:upnp-org:serviceId:TemperatureSetpoint1_Cool" and the other "urn:upnp-org:serviceId:TemperatureSetpoint1_Heat". They both use the same service specification, S_TemperatureSetpoint1.xml, which is in the XML tag SCPDURL.
The controlURL and eventSubURL are set by the Luup engine and the values in the device specification file are ignored.
The UPnP specification allows that we can add our own custom xml tags. So we add the xml tags "implemenationList" to the device specification which references the implementation files that device will use.
The Luup XML implementation file
The top-level XML tag (ie root node) is called "implementation". It contains
Therefore you do not need
A Luup plugin is a UPnP Device that can be controlled by any UPnP Control Point.
In the meantime, you will need to create a Luup plugin by hand as explained here: Luup_Plugins_ByHand.