The K-Zone: twseriald: a Linux driver for TW723/TWSERIAL X10 controller

Download source code for current version (C0.2)

What is twseriald?

twseriald is a Linux driver/daemon for the `TWSERIAL' X10 device. TWSERIAL is a serial interface to the TW723 automation controller, which is an X10-compatible home automation controller. The TW723 supports two-way operation, that is, it can control power devices, determine their status, and monitor remote control events. The TW723 itself is not seen very often, but it is very similar to the more common TW523 and PL513, and the software in this package should work with these devices as well.

twseriald allows the TW723/TW523 home automation controllers to be controlled over a TCP/IP port, using a very simple, text-based protocol. twseriald runs on the computer that is connected to the TWSERIAL, but can be controlled from anywhere by a network connection. This software was written to allow Java servlets to control power devices, but may have other applications. It networked mode of operation allows it to be used over the Internet, but its rudimentary security may make this inadvisable.

This software was developed for Linux, although it may be possible to adapt it for other Unix varieties. However, it does require a serial port with specific properties (see below). Not all hardware is suitable, either under Linux or anything else.

Package contents

This package contains the following components

System requirements

To use any of this software you will need the following

Serial port issues

The TW723 uses half-duplex operation at approximately 300 baud, and is synchronized to zero-crossings of the AC mains voltage. Thus it has very strict timing requirements. When the hardware sends a poll request (00) byte to the computer, it expects a response within 100 msec. Ironically, dumb serial ports like those found in PCs don't have a problem with this, because they don't do much buffering. The `SE' serial hardware used in Sun Ultra workstations does not work, because its buffer size is too big, and can't be controlled in software. What happens is that this serial hardware only interrupts the PC every 8 bytes, which takes longer than 100 msec at 300 baud. twseriald does not, therefore, work with Sun Ultra hardware (but this is a limitation of the TW723, not this software). twseriald has been tested with a number of different Intel PC platforms with reasonable success. With some systems I have had to slow down the transmission of data artificially; the places in the source where this might be necessary are well marked.

Building the package

Pre-requisites

To build the twseriald server, which is written in C++, you will need the following:

Building and installing the server

Edit the Makefile as appropriate, and then do:
make 

Testing the server

Start the server by executing the compiled program, with full debugging output.
./twseriald -v 2
To test the server you don't necessarily need to have TW723 hardware attached, but you will need an accessible serial port. If you do have the hardware, then you should expect to see this message:
twseriald: TW723 is stable
Shortly after startup. This indicates that the server has received the `00' byte from the controller that indicates that it is ready to receive data.

Now you should be able to control hardware using the TELNET prompt. For example:

telnet localhost 30000
abc on 1 1
Here `abc' is the password (password checking is not enabled by default, but the protocol requires something in that field). `on' is an instruction to switch something on, and the two `1's are housecode 1, unit 1. Of course, you will need to adapt this to suit your hardware. If the command is successful, the server should respond with
0 OK
Full details of the protocol are provided below.

Installing the server

The command make install will copy the binary to the installation directory, which by default is /usr/sbin. In the distribution is an `init' script to start and stop the server at boot time and shutdown time. This is not installed by default. Typically you would copy this script to /etc/init.d and create links to it from /etc/rc3.d with names denoting the requires startup order. This is a Linux issue, not a twseriald issue.

The twseriald server

Overview

The server is fully multithreaded, meaning that it can support a number of simultaneous clients. It multiplexes access to the TW723 hardware so multiple clients can, in theory, be controlling devices at the same time. It takes some trouble to avoid signalling contention, but problems can still arise as a result of limitations of the X10 protocol. The server itself does not manage retries; it is the job of the client to do this if an operation does not appear to have succeeded. In addition, the server does not do anything `smart', it simply converts text to X10 commands and vice versa. There is, for example, no X10 command that means `set brightness level to 50%', so twseriald can't do this either. Again, clients can implement this by interacting with the server in a more appropriate way.

Command line

twseriald accepts the following command-line switches.
  -p, -port=port             IP listen port
  -v, -verbose=level         logging verbosity (0, 1 or 2)
  -d, -device=device         serial device
  -w, -password=password     password
The default IP port number is 30000. There is no compelling reason to change this unless it clashes with something else. The serial device defaults to /dev/twserial, which could be symbolically-linked to the real device; alternatively specify the device on the command line. The verbosity and password switches are discussed below.

Client security issues

twseriald supports a very simple security mechanism; each command sent from the client must be preceded by a password. There is only one password, and it is sent in plaintext, so it is best not used over the Internet. If the `-password' option is not supplied, password checking is disabled, but the client must supply some text in the password field (it doesn't matter what it is).

System security issues

twseriald must not be run as root; there is no need to, and it may present a security hazard. Ensure that whatever account does run it has read and write permissions on the serial device. To use twserial in an init script, use `su -c' to run the twseriald command as a named user. A sample is the provided `twserial.d' script.

Logging

twseriald writes logging information to standard output. The amount of logging can be set on the command line to 0 (critical errors only), 1 (errors and warnings), or 2 (heaps of debugging output). On a Linux system you can use initlog to redirect the standard output to the system logger if necessary (see the twserial.d script for details).

Shutting down twseriald

twserial attempts to shut down gracefully if it receives an INT or TERM interrupt. So, at the command line, the `elegant' way to shut it down is: killall -INT tweriald If you must shut down over the network connection, the `shutdown' command has this effect, but is not very graceful (it is difficult to shutdown gracefully using an open network connection).

twseriald protocol

overview

The client-server protocol is text-based, and could -- at a pinch -- be managed at a TELNET prompt. It's certainly possible to do this for debugging. The protocol is strictly request-response: the client issues a request and the server responds to it. Although the server logs remote control events, it only issues them to the client on demand. This makes writing the client very simple.

Requests

Each request has the following form: [password] [action] [arguments...] The password field must have something in it, even if passwords are disabled. The `action' and `arguments' are as follows. There is no specific `quit' request; the client should just break the connection when it has finished.

All control operations are carried out using the `send' command, which takes an event code, a housecode, and a unit code (not always relevant). There are 7 different event codes, defined in x10event.h

#define X10EVENT_LIGHTS_OFF			100
#define X10EVENT_LIGHTS_ON			101
#define X10EVENT_ALL_OFF			102
#define X10EVENT_DIM				103
#define X10EVENT_BRIGHT				104
#define X10EVENT_ON				105
#define X10EVENT_OFF				106
Of these, only ON and OFF require both a unitcode and a housecode. The other either operate on the unit last selected (e.g, `dim') or affect all units with the same housecode.

For example, to send an `on' event to unit 1 on housecode 1, the string is:

[password] send 105 1 1

Responses

The response to all commands is an integer, followed by a space, followed by an arbitrary text string. The integer is either zero, meaning `success', or an error code. Error codes are 100 or greater. With the exception of the `status' and `events' requests, the text string is simply a textual representation of the error code.

For the `status' request, the text is a digit `1' meaning `device is on' or `0' meaning `device is off'.

For the `events' request, the text is a list of event codes, and the whole reponse looks like this:

0 E:H:U E:H:U
Where `E' is the event code (same meaning as above), `H' is the housecode (1-16) and `U' is a unit code. Where there is no unit code, the U field is zero.

Error codes

Errors are indicated by a non-zero return code from the server. Usually a short textual description of the error is given as well. This section describes the error codes in more detail. C-language constants are defined for these errors in twserial_protocol.h.
100 Syntax error: the client sent something meaningless like an empty string
101 Bad command: the client send a command other than send, listen, unlisten, events, status, shutdown,
102 Although the command was recognized, an incorrect number of arguments was supplied.
103 A non-number was received where a number was expected.
104 Invalid argument: typically a number was out of range
105 Client tried to get events, but event listening is not enabled
106 Timed out while waiting for X10 line activity to subside. This can happen in normal circumstances in a very `busy' environment. The client should wait a short time and try again.
107 Timed out while waiting for a device to respond to a status request. This normally indicates that the device simply does not understand status requests. The X10 protocol does not provide a way to find out.
108 X10 protocol error reported by TWSERIAL. This may happen in normal circumstances, but if it is frequent it may indicate that your serial port hardware is incompatible.
109 Access denied; client did not supply the correct password. The server password is set using the `-w' switch on its command line.

Notes

Known issues

Legal

This software was written by Kevin Boone and is (c)2000-2001 Kevin Boone/Web-Tomorrow. It is distributed free-of-charge in the hope that it will be useful, but there is no warranty or commitment to support. Use at your own risk.
©1994-2006 Kevin Boone, all rights reserved