Vista ICM Panel Development
This page details the development of the Vista ICM device driver for compatible security panels from Honeywell/Ademco. It intends to show the overview of the development process for the interested developers who wish to create new device support for LinuxMCE.
Contents
Initial Research
Initially, you need any specifications that you can retrieve to tell about the device you wish to implement. These can be gotten from a variety of sources, including:
- Manufacturer's website
- Various google searches on the web (try the following search words: protocol specification, rs-232, technical reference, and custom installer specification along with the name and model of your intended device.)
- Existing literature that you may have, check the appendices.
In our case, the following web link proved especially useful: http://bliny.net/blog/post/HoneywellAdemco-Vista-ICM-network.aspx
Consideration: C++ or Generic Serial Device ?
This link provided a reverse engineered protocol specification of a device that provides:
- 1 TCP port for sending commands using the HTTP protocol
- 1 UDP port for retrieving panel status information, that is sent to the global broadcast address of the network (INADDR_ANY)
There were two other ports exposed, but were deemed not to be useful for the implementation of this device.
This brings up two very important points:
- If your device communicates on more than one port. You can not use the Generic Serial Device.
- If your device communicates on anything other than TCP or RS232, You can not use the Generic Serial Device.
Because we failed both criteria, the device was written as a C++ device.
Installation of a basic development environment
See Developing_a_DCE_Device for information relating to initial environment setup.
Device Template
Device Templates are at the heart of LinuxMCE. They provide needed information so that the system can properly manage a device, such as:
- The Name of the device
- The Category of device (a TV, a Security Panel Interface, a Media Player, etc.)
- Device Data the device may need to function
- Commands the device may wish to respond to
- Events the device may wish to emit for other devices to respond to.
- Information for Plug and Play such as a MAC address range, or a Vendor/Model pair for PCI or USB
We used the Apex Destiny 6100 as the basis for our device template, opening its window via Advanced > Configuration > Device Templates in the Web Admin
A quick note before making the new template: Update your DCE repository via SqlCVS!
Before we make a new template, we use the Advanced > sqlCVS > update menu to update all the tables in the DCE repository. This is to make sure we are up to date before we make a new template. Please do this.
Important notes on the device template
We then made a new device template, and told the system that it was to be a device implemented via C++.
Of course, we called it the VistaICM, and it is a Security Interface, so the category is set appropriately. We also specified that the Device is controlled by Category Computers - CORE So that the system understands that this device will run on the core. This was done because the device is a network device that will have its device driver run on the core, and will be an immediate child of the core in terms of where it is in the device tree.
We then specify that the device is IP Based
Device Data
Any device may need any number of parameters that you can change, or that other things can change over time. This is referred to as Device Data and in our case, we're not needing anything other than a parameter to specify Zone maps, so we select Zones from the Add Parameter list, and select Add.
Commands
Any device should have a number of commands that it can respond to. Some suggested commands may be presented if your device belongs to a certain category. For example, a Security Panel has commands for setting house modes, getting the list of sensors, and reporting child devices. This seems applicable for us, so we check that command group. Spend some time looking through the command groups using the Edit Commands button to look at the commands present to see if they apply to you.
We simply choose security panel.
Events
Here, you can specify what events that the device EMITS. This does not mean that the device recieves those events, it merely specifies what events the device can send. For a C++ device, it amounts to creating a series of convienience functions beginning with EVENT_, such as EVENT_Sensor_Tripped(true), etc. that you can call from the program code. As per the Apex 6100 template, I added events for the following:
- Alarm Panel Mode Change
- Fire Alarm
- Sensor Tripped
If I knew I could have introspected child devices, I would have added an event for reporting a child device.
Plug and Play
Because this is a network device, It can be detected via plug and play. In our case, we look for a MAC address range. The simplest way to get this MAC address range is to use a network tool such as nmap running as root to get the MAC address of the device. You can then use the returned information to get a MAC address range from this site:
http://standards.ieee.org/regauth/oui/index.shtml
For simplicity, we used the entire MAC address range from AA:BB:CC:00:00:00 to AA:BB:CC:FF:FF:FF. However the entries for the MAC range From and To do not use the hex:colon notation, they are represented in decimal. Use the convert_mac utility to get the decimal numbers, for example:
linuxmce@dcerouter:/home/src/LinuxMCE-0710/src/Security_Plugin$ /usr/pluto/bin/convert_mac 00:19:45:00:00:00 108531810304 linuxmce@dcerouter:/home/src/LinuxMCE-0710/src/Security_Plugin$ /usr/pluto/bin/convert_mac 00:19:45:FF:FF:FF 108548587519
Using those ranges in the from and to are sufficient enough to be able to detect our device.
I put Vista ICM in the comment field and pressed Add.
We don't have any related devices, but if we needed another device template to function properly (such as a streamer device to run on the core, or a media streamer plugin, or any children devices that we know we would need), we could specify them here, along with any parameters needed in the form of devicedata#|paramvalue|devicedata#|paramvalue
We can then press Save, because the device template is finished for now. We will come back later and add the package definition once it's complete.
Code Development
Now that the device template is complete, we can run DCEGen to generate the code stubs, sql2cpp to generate any needed device constants, and start implementing the code.
Running DCEGen
DCEgen needs to run from the DCEGen source directory. It should only need one parameter, the # of your new device template that you created. If you do not have it readily available, go back to the web admin and get the device template #.
cd /home/src/LinuxMCE-0810/src/DCEGen /usr/pluto/bin/DCEGen -d xxxx
your new device template will be present in the parent directory.
Running Sql2cpp
Now, you will need to run sql2cpp to generate needed defines that DCEGen created within your new code.
cd /home/src/LinuxMCE-0810/src/sql2cpp /usr/pluto/bin/sql2cpp
The defines will be generated.
prep.sh and unprep.sh
Before continuing, you need to create the following tools and place them in /usr/local/bin
prep.sh
#!/bin/bash ### Use this script to prepare the build for dev work. ### NOTE: Be sure to run unprep to revert the prepped ### makefiles! ## Back up the original unprepped makefiles. for i in $(find . -name Makefile) do echo Backing up $i to $i.unprep cp $i $i.unprep done echo Prepping sources... find . -iname Makefile -exec sed -e 's/<-mkr_t_compile_defines->/-DKDE_LMCE -DDEBUG -DTHREAD_LOG -DLOG_ALL_QUERIES -I\/opt\/libxine1-pluto\/include -I\/opt\/libsdl1.2-1.2.7+1.2.8cvs20041007\/include -I\/opt\/libsdl1.2-1.2.7+1.2.8cvs20041007\/include\/SD/' -i '{}' \; find . -iname Makefile -exec sed -e 's/<-mkr_t_compile_libs->/-L\/opt\/libxine1-pluto\/lib -L\/opt\/libsdl1.2-1.2.7+1.2.8cvs20041007\/lib/' -i '{}' \;
unprep.sh
#!/bin/bash ### this script undoes all of the prepping steps done by prep.sh by ### simply moving the old prep files back into place. for i in $(find . -name Makefile.unprep) do echo Undoing Prep for $i mv $i `dirname $i`/Makefile done
Implementing code
You can then use the prep.sh script to prep the code appropriately, so that you can build it. In the future, this process will be removed once we have removed the old Pluto MakeRelease tags.
When you are done hacking on code and are ready to make a patch, you must run unprep.sh before making the patch!
cd /home/src/LinuxMCE-0810/src/VistaICM2 prep.sh
Basic hacking process
Once you have made changes to the source, you can use make bin (for a standard DCE device), or make so (for a DCE plugin) to create the necessary binary. make clean will delete the object files, etc.
In order to test the device, you'll need to go into the Web Admin, and create an instance of the device. Note its device #. Once you have this, you can start the device from its directory by typing:
./VistaICM2 -d 105
where -d xxx is the device # assigned by the system.
Any time the device needs to be reloaded, it will stop, and you will need to reload it again. This is because the device is not being managed by Spawn_Device.sh.
Running the device in gdb
To debug runtime errors, gdb can be used, I run the devices as such:
gdb --args ./VistaICM2 -d 105
and use gdb as normal.
Some Basic Notes on the code design
The code skeleton generated by DCEGen provides the bare skeleton that you will need to create the device. It provides some basic examples on calling DCE to send commands, and events, in various permutations, as well as how to access device data using the convienience accessors provided. ndo, to make the device function.
I chose a design like the following:
- Main Thread, runs the DCE device and its runloop. This handles the commands, and sending events etc to the system
- the ccp Thread, for dealing with the CCP port, it has its own runloop. I connect to the instance of the main running class to do method calls from this outside thread, as well as setting some basic states (is the ccp thread running or not, etc.)
Testing
Sending it all In
Sending in the Patch
Creating the Package Definition
Checking in the sqlCVS changes anonymously
You should be done at this point. The driver will now be built as part of our release process, and will become part of the autobuilds, so that you can either do your own builder as described in Building LinuxMCE 0810 or you can wait for the build process to produce packages for your new driver.