Capturing serial events

My home automation and monitoring system runs off two separate radio networks; RF12 and XRF. The RF12 network communicates with a JeeNode LED board, which also runs the light strip for the centre cabinet. The XRF network uses a USB stick made by the makers of the XRF radio.


Both of these devices create a serial port instance on the Ubuntu server, and pass through exactly what is sent or received – either PC to radio, or radio to PC. In order for my web apps to communicate with them, I had to find a way to constantly monitor what was received, and also a way to send commands out.

I first tried PHP in a while(true) loop which certainly worked, but used an astronomical amount of CPU cycles just sitting there. After trawling the internet for better ideas, I found a Python tutorial which was designed to be a serial TCP bridge; exactly what I was looking for.

Now, I didn’t know shit about Python, but I’d used a XBEE ConnectPort which is a little embedded Linux box with a XBEE radio bolted on. It uses Python almost exclusively to add functionality to its ethernet and XBEE networks. At the time I didn’t know what I was doing, and had no purpose to be playing around further – I now have a reason.

Using the sample code from the PySerial site, I managed to piece together a method of monitoring the serial port, and also allowing messages to be sent via telnet. The telnet side of things means I can easily connect PHP to it, or any other language. Perfect.

After faffing around trying to get different USB devices to appear as the same name every time, I finally had a method to receive radio traffic, process it, and then persist it in any database needed.

These Python scripts now form the basis of my home automation network and use almost 0 CPU to do so.

#!/usr/bin/env python

import sys
import os
import time
import string
import threading
import socket
import codecs
import serial
import httplib

except NameError:
True = 1
False = 0

class SerRead:
def __init__(self, serial_instance):
self.serial = serial_instance
self._write_lock = threading.Lock()


def startReader(self):
self.thread_read = threading.Thread(target = self.reader)

def setConnection(self, socket):
self.socket = socket

def reader(self):
global connection
self.sendHTTP(‘1’, ‘starting_reader’);
while True:
data =
if data:
data = data + self.serial.readline(1024)
string_items = data.rstrip().split(‘|’);
# Example string
# ========================
# 8|temp=23.2&relay=ON

sys.stderr.write(‘|—— [RX] TTY: ‘ + data.rstrip() + ‘\n’)

if (len(string_items) > 1): # Make sure we have a second item before trying to reference it
if string_items[0] != ‘SELF’:
self.sendHTTP(string_items[0], string_items[1]) # Send nodeID, data

except socket.error, msg:
sys.stderr.write(‘|—- [ERR] %s\n’ % msg)

# Send the data to the PHP script
def sendHTTP(self, node, data):
global running
conn = httplib.HTTPConnection(‘’)
conn.request(‘GET’, ‘/rf12.php?node=’ + node + ‘&’ + data)
sys.stderr.write(‘|—— HTTP: node=’ + node + ‘&’ + data + ‘\n’)
except (httplib.HTTPException, socket.error) as ex:
sys.stderr.write("|– [ERR] Failed to send HTTP" + ‘\n’)
running = False

connection = False
running = True

if __name__ == ‘__main__’:
ser = serial.Serial();
#ser.port = ‘/dev/ttyJeeNode’
ser.port = ‘/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AM01Z7UF-if00-port0’
ser.baudrate = 115200
ser.parity = ‘N’
ser.rtscts = False
ser.xonxoff = False
ser.timeout = 1

except serial.SerialException, e:
sys.stderr.write("|– [ERR] Could not open serial port %s: %s\n" % (ser.portstr, e))

# Bind to localhost:7777
srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
srv.bind((‘’, 7777))
sys.stderr.write("|– Listening on port 7777\n");
sys.stderr.write("|– [START] %s %s,%s,%s,%s \n" % (ser.portstr, ser.baudrate, 8, ser.parity, 1))

while True:
if running is False:
sys.stderr.write(‘|—— [ERR] Serial capture thread not running!’+’\n’)

# Block and wait for someone to connect
sys.stderr.write("|—- [WAIT] On port %s…\n" % 7777)
connection, addr = srv.accept()
sys.stderr.write(‘|—- [CONN] %s\n’ % (addr,))
while True:
data = connection.recv(1024)
if not data:
sys.stderr.write(‘|—— [TX] TTY: ‘ + data.rstrip() + ‘\n’)
except socket.error, msg:
sys.stderr.write(‘|– [ERR] %s\n’ % msg)

# If we’re here, it means the connection has dropped
connection = False
sys.stderr.write(‘|—- [DISC] %s\n’ % (addr,))

# Looks like we’re looping again
except KeyboardInterrupt:
except socket.error, msg:
sys.stderr.write(‘|– [ERR] %s\n’ % msg)

sys.stderr.write(‘|– [EXIT]\n’)


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.