Developing a DCE Device

From LinuxMCE
Jump to: navigation, search

Document Relevance:

  • LinuxMCE 810
  • LinuxMCE 1004

Introduction

DCE (Data, Commands and Events) is a lightweight network protocol allowing any device to access its configuration (ie data) from a central database, send + receive commands, and fire + respond to events.

A DCE device is a piece of software that implements the DCE protocol, as a means to interface with hardware or other pieces of software.

See Developers Guide for more info on DCE and other parts of LinuxMCE architecture.

For the purposes of this demonstration, we will be using the instructions below to create a c++ project that will result in a working DCE implementation of a fictional smart light bulb socket.

Preparation

Developing for any part of the system requires a specific environment setup, including an up to date source code tree and some required programs to be installed. It is assumed that this guide will be followed on an existing LinuxMCE Core installation. All commands following a # sign are to be run as a privileged user, either by prepending 'sudo' or after obtaining a root shell ("sudo -s", "sudo -r", or "sudo su" are all acceptable means of doing this).

Required Packages

Install pluto-dcegen, pluto-sql2cpp, and a few other build dependencies

# apt-get install pluto-dcegen pluto-sql2cpp subversion build-essential libmysqld-dev
  • In my case on 810 replace libmysqld-dev with libmysqlclient15-dev -L3mce

Source Tree

Check out the LinuxMCE source tree

# svn co http://svn.linuxmce.org/svn/branches/LinuxMCE-1004/src .

Environment Preparation

Copy the system libs into the source tree

# cp /usr/pluto/lib/* src/lib

Developing the Device

Device Template

Every DCE device, starts with a template.

A template merely specifies what the device is, what it's capable of, how it relates to the other devices in the system, what it needs to install (the package entry), any data it might need to carry around (device data), any events the device may want to EMIT, any related devices that need to exist for this device to function, and any orbiter screens this thing might need, as well as plug and play data so the system can detect it if it's hardware.
In short, as the name implies, it is a template that the system can use as a basis to create a unique device for each piece of hardware or software attached to the system (even multiples of each).

Before any code can be written, a device template is needed. This is created in the Web Admin, under Advanced -> Configuration -> Device Templates.
There is a button for "Add device template", but a manufacturer and a device category must be selected first. In this case, the manufacturer will be "Pluto" and the device category will be "Lighting Device < Environment". New manufacturers and device categories can be added if none are suitable for the device being controlled.
Select the manufacturer and device category, then click the "Add device template" button.
On the window that pops up, select the second option (to make it a c++ device) and fill in a name (this guide will use "Intelligent Light Switch") and click "Add".
At this point the device template is complete and a functioning device could be made from it, however there are some important options that need to be set to make the device actually be useful. These are listed below organized by the section they appear in on the device template configuration screen.

Device Template #xxxx

This is the main section. Remember the number after the pound sign; this is the unique identifier for this device template and will be required for some steps later. For demonstration purposes, this guide will use the number 2181. There are some important options that must be set here. For details on items which are not covered here, see Edit Device Template.
Implements DCE device - this should always be checked for DCE devices, for obvious reasons.
This device is controlled via and This device is controlled via category - devices are usually attached to other devices or controlled via other devices; these options provide a way of specifying that relationship. This mythical intelligent light can be controlled by any Media Director (which includes the Media Director portion of a Core/Hybrid) so click the "Add a new controlled via category device" and choose "Media Director".
Inherits MAC from PC and Is IP Based - the light is network-attached, so select these options.

Device Data

Device Data is simply a way of describing pieces of information, so that the device and the rest of the system know how to talk to each other. Events and Commands make use of Device Data to pass information around. This section tells this device what kind of information it will send or receive.
The intelligent light will be able to provide information on how much electricity it is consuming, or we can manually configure it with this information, so open the drop-down next to "Add a new parameter" and select "Energy Consumption". There are several options available for each Device Data:
Comments - as it says, a comment describing what this piece of information is for. Device Data are fairly generic in nature, so this allows a more descriptive entry. This is required, so fill it in with something.
Default Value - the value to use by default in any device created by this template. It is not required, but fill in a 0 for now.
Required - device data can be optional. If this is checked then a default value must be provided or the user must enter a value. Leave it unchecked.
Allowed to Modify - as it implies, this controls whether the user can modify the value in the web admin. Enable this.
Use Master Device List Defaults - this means that the default value above will always be used by any created devices, and any time the device template default is changed all created devices will be automatically updated. Leave it unchecked.
Set by Device - this means that the DCE device itself sets the value. Normally a device like the intelligent light switch would set its energy usage, but since this is just a demonstration this will be left unchecked.

Commands

Commands are how the system tells this device to perform an action. As can be seen, several command groups have already been made available, chosen based on what device category this device template is. None are actually enabled, however, so some will need to be selected. The intelligent light switch is able to turn on and off, as well as dim to partially on states, so select the check boxes for "Dimming" and "On/Off Light Switch". You can click on the "Edit Commands" button to see what commands make up each group.

Events

Events are how the device lets the system know that something with this device has happened. Other parts of the system can register to listen for these events and perform an action of their own when the event is fired. The intelligent light switch also has manual controls, so it needs to let the system know when someone operates one of these controls.
Usually events will mirror commands, so use the dropdown to add events for "Device On/Off" and "State Changed" and use the textbox to add an appropriate comment for each.

Plug & Play

This is used to help the system identify when a device becomes available and know that this is the device template to use when creating a device for it. This section is not used in this guide.

Device Template Related

This is used to let the system know about devices that are related to this one. This section is not used in this guide.

Screens

This is used to let OrbiterGen know about Orbiter screens that are not referenced directly but are still used by this device. This section is not use in this guide.

Running DCEGen

DCEGen is a program that uses the device template information to create a skeleton of c++ code that will comprise the basics of the device. It creates the necessary header files, source files and makefiles in order for the device's code to compile. Included in this are functions for the device data, commands, and events defined in the template. Under normal circumstances, you would do an initial sqlCVS checkin at this point in order to get a permanent Device Template number, but since this is a demonstration only this will not be performed.
Run DCEGen to create the source code skeleton:

# cd src/DCEGen
# /usr/pluto/bin/DCEGen -d 2181

It is important to be in src/DCEGen of the svn tree when running this command! Also make sure to use the correct device template number for your template in place of 2181. DCEGen can also be run again later if you change the device template options; it will leave your customizations alone and only update the device template specified options. DCEGen adds very verbose comments that makes the code very easy to read and modify.

Running sql2cpp

All database tables, rows, and columns are represented as c++ constants, and must be regenerated any time device template options change. sql2cpp performs this operation.

# cd ../sql2cpp
# /usr/pluto/bin/sql2cpp

As with DCEGen, it is important to be in src/sql2cpp of the svn tree when executing it, and it is safe to execute this again at any time.

Testing Compilation

Before compilation, you may need to install build packages required for some code. Its wise to do this in the start and spare yourself the headaches.

apt-get install $(cat home/src/LinuxMCE-1004/src/Ubuntu_Helpers_NoHardcode/conf-files/lucid-i386/build-packages)

This should install the packages needed for compilation.

At this point the device code is complete and will create a fully functioning device binary when compiled. DCEGen created a new directory in src for the device and placed all the code within that directory, so to compile it, simply cd into that directory and invoke the "make" command:

# cd ../Intelligent_Light_Switch
# ./make

Due to a bug in DCEGen, there will be an error during compilation about post_make.sh, however it is not fatal. If the error bothers you, you can simply make the file executable:

# chmod 755 post_make.sh

You should now have a binary of the device in the current dir: Intelligent_Light_Switch

Testing the Device

At this point you could create a device in the device tree and copy the binary to /usr/pluto/bin and the device would be started in a screen session after a router reload. However for testing purposes it is usually better to just run the device directly from where it is at. Go ahead and create a device in the device tree:
Sign in to the web admin, go to Advanced -> Configuration -> Devices, and browse to and select the "The core/hybrid" device under "CORE" in the tree to the left.
Click "Create Child Device", enter a description, and click the "Pick device template" button.
Enter your device template ID in the box next to the "Go" button, click the "Go" button, then click "Pick device template".
Write down the device number this is assigned to this device. For demonstration purposes, this guide will use "53" as the device number.
Now, start the device, providing it with the device number to use:

# ./Intelligent_Light_Switch -d 53

It will probably tell you that the router needs reloaded; go ahead and do this using the web admin or an Orbiter. You may need to restart the device afterwards. Note that at any time you can press ctrl-c to stop the device and exit back to the shell. To see the device in action, click on the "Send command to device" link at the top of it's web admin page. Choose one of the available commands and click "Send Message", providing any Device Data that you want. The terminal running the device will output messages saying that the command was received.

Implementing Code

Of course the device created so far doesn't actually do anything, other than provide some output when it is sent commands; hardly a useful device! Here begins the process of adding functionality and testing the results. Add/edit some code, then do the compiling and testing steps above to make sure things are going in the right direction. Repeat until the device does everything it should.
Refer to the source code for other devices if you get stuck or if you need ideas on how to implement something. And make sure to run DCEGen and sql2cpp as necessary if you change options in the device template.

Packaging the Device

Creating the Binary Package

Creating the Source Package