Control Program for the X10 CM17A and MR26A

Home | John | Connie | Publications | Software | Correspondence | NtropiX | NdustriX | NformatiX | NdeX | Thanks


Spx10 is for asynchronous raw serial port communication with the X10 CM17A Computer Interface and MR26A RF Receiver used in many home automation systems. The program is intended to provide simple and reliable serial port communication between a computer running Linux and the X10 CM17A, (e.g., "Firecracker,") Computer Interface and MR26A RF Receiver, (both on the same port,) and allows X10 devices to be controlled, and monitored, via RF transmission by the computer, (the X10 UR81A Universal Remote, often distributed with the MR26A is supported, also.)

The default port is /dev/ttyS0 at 9600 baud. The default semaphore lock file is /var/lock/LCK..ttyS0, which has an fcntl(2) advisory lock applied. The serial port is controlled through termios(3), and is restored to original values on exit. The serial port child read process is created by fork(2) from the parent write process, and both processes respond to SIGINT = ^C and SIGTERM signals. Asynchronous serial port control is implemented with select(2). The input file, (usually stdin for commands,) uses canonical input for flow control. The X10 device and transmission codes are cross indexed in a binary search database using mmap(2), which also contains a command sequence field, (including shell calls,) that are executed in response to a specific transmission code. Variable names and states are supported via a hash lookup table.

The database file is a Unix tab delimited field file, in lexical order, (i.e., constructed with sort(1),) consisting of four fields:

  1. The X10 transmission code.
  2. The device code and command.
  3. A user defined alias.
  4. A command sequence to execute in response to the transmission code.

For example:

          d5 aa 64 00 ad  a9 on   porch motion  a11 on; \
              isset ix exec echo "motion detected" \
              | mailx -s "motion detected"


would turn on device A11, and then, send a message to my cell phone if motion was detected on my front porch, but only if the variable "ix" was set, (e.g., the variable "ix" enables transmission to my cell phone.) The motion detector is on house code A, device code 9, which has the transmission sequence, "d5 aa 64 00 ad." (The reason for including the transmission sequence in the database was for extensibility with other devices and products-the program will print unknown transmission sequences received for future inclusion in the database-or take evasive action in jamming or collision situations, etc.)

The language in field 4:

  • [a-p][1-9][0-6]?: house code and unit code, i.e., "b12"
  • on: turn a device on, i.e., "b12 on"
  • off: turn a device off, i.e., "b12 off"
  • dim ([0-9][0-2]?)?: dim a device, i.e., "b12 dim" or "b12 dim 5"
  • bright ([0-9][0-2]?)?: brighten a device, i.e., "b12 bright" or "b12 bright 5"
  • all_off: all devices off in a house, i.e., "b all_off"
  • all_on: all devices on in a house, i.e., "b all_on"
  • all_lamps_off: all lamps off in a house, i.e., "b all_lamps_off", (actually an alias for all_off)
  • all_lamps_on: all lamps on in a house, i.e., "b all_lamps_on", (actually an alias for all_on)
  • quit: stop the program
  • exit: alias for "quit"
  • set <variable>: set a variable, i.e., "set x123", (a variable is either set, or it isn't)
  • reset <variable>: reset a variable, i.e., "reset x123", (a variable is either set, or it isn't)
  • unset: alias for "reset"
  • isset <variable> <action>: test if a variable is set, i.e., "isset x123 b12 on", (a variable is either set, or it isn't)
  • isnotset <variable> <action>: test if a variable is not set, i.e., "isnotset x123 b12 on", (a variable is either set, or it isn't)
  • timeset <variable>: the last time a variable was set, in ctime(3)
  • istimeset <variable> seconds action: if a variable has been set at least seconds many seconds, (or has been set less than seconds many seconds if seconds is negative,) do action
  • exec <command>: execute a command
  • system: alias for "exec"
  • variable: any alphanumeric string not one of the above keywords
  • ';': command delimiter, i.e., "isset x123 b12 on; isset abc b11 off"

Note that the isset and isnotset commands allow simple constructs-the main function is to inhibit spawning a shell for every instance of a state change, (like a motion detector in a room,) for example:

           isset x123 exec myfile; isset abc exec myprogram


would invoke a shell process only if x123, (or abc,) is set; any more complicated constructs should be handled by the shell interpreter in a batch file.

The isset and isnotset commands can be chained to provide "and" boolean functionality, for example:

          isset x123 isnotset y456 exec myfile


would invoke a shell process only if x123 is set, and y456 is not set.

The program is not intended to be interactive, (although it does accept commands from stdin,) and is a network centric automaton, (daemon, 'bot., etc.,) launched in the computer's init scripts. An example invocation is:

          mknod myfile p
          spx10S0 -f spx10S0db -i myfile


Commands, to be sent to X10 devices are written to the named pipe, myfile, (the named pipe is also used by the program to send commands in response to transmission sequences-fcntl(2) advisory locking is provided for concurrency control,) and received transmissions, and database lookups, are printed to stdout for logging considerations.

The program is intended for inclusion in a network centric embedded home automation system, (based on a "live CD" version of Knoppix, with no hard disk for security considerations.) The Knoppix system is installed on a depreciated laptop, and since no display-or hard disk-is required, will run many hours without electricity. The laptop communicates sensor data, (internal motion, etc.,) via an attached, (RS232 serial port charging cable,) cell phone, through SMS text messaging. The communication is bidirectional for ancillary device control.

The CM17A section of the code is based on code from the BottleRocket program, by Tymm Twillman, Ashley Clark, David Anderson, Warner Losh, and, Christian Gafton. © 1999 Ashley Clark ( and Tymm Twillman ( Free Software. LGPL applies. No warranties expressed or implied.

The serial port code is based on the spcid program, the database code is based on the (NdeX program, and the hash table code on hash.shar.gz, available on

Notes to system integrators

  1. The program is quite efficient, and any machine of 486 class or better will suffice.
  2. The program does detect corrupt transmission sequences, (whether by jamming, transmission sequence collision, interference, etc.) Currently, nothing is done with this information-it is detected and discarded.
  3. The program is extensible to other command sets, (transceivers from different manufacturers, specialty remotes, etc.) The program prints the hexadecimal code of the transmission to stdout if it is not found in the database, (see the -V option.)
  4. The program's output monitor, (typically stdout,) is a tab delimited database format which can be monitored by other programs, specifically, those using fopen(3) or open(2). After each record is printed to the output, an fsync(2) is issued to flush the internal buffers.
  5. The command interpreter is a short routine based on a hash table lookup of enum elements, (and decoded with a switch construct,) and is quite extensible-there is currently no state information maintained, (as in look-ahead.)
  6. The CM17A does not use standard serial I/O-communication with the computer-communication is via "bit piddling" of RTS/DTS. This allows both devices, (the CM17A and MR26A,) to coexist on the same serial port, (the MR26A uses fairly standard protocols.) The program does a fork(2) and handles each device, independently. Interprocess communication is via the named pipe, (for example, sending an X10 command to the CM17A in response to a transmission sequence received from the MR26A.)
  7. An fcntl(2) advisory lock is provided for concurrency control when the program writes to the input file, (typically, a named pipe, which typically sends a response to a transmission sequence.) Any programs that write commands to this file, (typically a named pipe,) should be interoperable.

Some thoughts on using the X10 MS14A EagleEye Motion Sensor

The sensor should be mounted where traffic walks across the field of the sensor, as opposed to walking at the sensor. For internal use, this means mounting the sensor at a 45 degree angle to both walls in the corner of a room. For external use, this means the sensor should be mounted 45 degrees from perpendicular to the wall.

Additionally, the sensors should have a negative incidence, (i.e., looking down,) of about 21 degrees. Failure to do this will result in false alarms since sensor has considerable range under ideal conditions, (i.e., cold, clear nights.) Formulas for calculating the optimal incidence are available from my notes as jpeg images, surveillance-incidence.jpg, surveillance-incidence-1.jpg, surveillance-incidence-2.jpg, (which is probably the most useful,) and their xfig sources, surveillance-incidence.fig, surveillance-incidence-1.fig, surveillance-incidence-2.fig, (which is probably the most useful.)

I housed the external sensors in handmade brackets, (the only tools used were a 1/4" drill, and an inexpensive plastic miter box.) The material used was 1/4" x 3" x 2', (which measured 2.75",) popular and number 2 flat head screws for fasteners-all available at local hardware stores. Each bracket takes about 15 minutes to make, plus sanding and painting. The diagrams are available from my notes as jpeg images, surveillance.bracket.jpg, surveillance.bracket.exterior.jpg and their xfig sources, surveillance.bracket.fig, surveillance.bracket.exterior.fig. The latter is much easier to make, and was used where they were not visible. These look like bracket.jpg, and, outside.jpg.

The internal sensor bracket diagram is available from my notes as a jpeg image, surveillance.bracket.interior.jpg and its xfig source surveillance.bracket.interior.fig. The 45 degree mounting angle is clearly visible. This looks like inside.jpg

Other alternatives are brackets made from PVC pipe, with two elbows, (one adjusts sensor field of view up/down, the other left/right.) However, mounting the bracket and sensor is problematical. Flying model airplane control surface hinges, available at hobby shops, could be used with a little ingenuity, too.

The xfig source for plan field of view "paper dolls" for the X10 MS14A EagleEye Motion Sensor is available, surveillance-symbols.fig, to facilitate coverage planning-a 21 degree negative incidence is assumed on the sensor.

The X10 MS14A EagleEye motion sensor is not recommended for use as an intrusion detection device. However, their low cost, (particularly on Ebay,) permits the entire perimeter of a domicile to be surveilled to a distance of about twenty feet-usually using only two per outside wall. More sophisticated implementations would allow multiple devices to surveil a perimeter area in overlapping cross fields for false positive reduction. Since the sensors communicate via RF, it is wise to leave several blank house/unit addresses unused but monitored for scan/jamming detection-which is also relayed via cell phone. (The spx10 program can detect random transmissions-that's what the database file of valid unit addresses is for-as a simple countermeasure technique.)


The sources to program is available in the archive,


A license is hereby granted to reproduce this software source code and to create executable versions from this source code. The copyright notice included with the software must be maintained in all copies produced.


So there.

Copyright © 1992-2008, John Conover, All Rights Reserved.

The CM17A section of the code is based on code from the BottleRocket program by Tymm Twillman, Ashley Clark, David Anderson, Warner Losh, and, Christian Gafton. (c) 1999 Ashley Clark and Tymm Twillman Free Software. LGPL applies. No warranties expressed or implied.

Comments and/or problem reports should be addressed to:

Home | John | Connie | Publications | Software | Correspondence | NtropiX | NdustriX | NformatiX | NdeX | Thanks

Copyright © 1992-2008 John Conover, All Rights Reserved.
Last modified: Fri May 16 11:50:51 PDT 2008 $Id: index.html,v 1.0 2008/05/16 18:51:12 conover Exp $
Valid HTML 4.0!