mark :: blog :: ha
When I moved to a new house in 2001 I designed and installed my own home-brew
home automation system in it to control things like the heating, lighting,
alarm system, and more. The messaging system I picked was to use standard
XMPP (Jabber) because most platforms have existing open source XMPP libraries
so writing clients is easy. The back-end is just a load of XMPP bots written
in Perl. Around the house I had a number of Fujitsu Point 1600 tablets
running an interface I designed and wrote using Perl/Tk. The tablets are
great, but they're starting to show their age with limited resolution
of 800x600 and CPU speed making full-screen video not really possible.
So last year I obtained an Archos 101 10.1" android tablet with the plan being
to replace the existing tablets with android powered ones. It was a good excuse
to dust off the old skills and learn programming apps for Android. Converting
the app was straightforward and tooks a couple of weekends, troubles with the
tablet took quite a bit more work.
Finding a way to mount the Archos tablet on a wall proved tricky, the back
of the device isn't perfectly flat and it has an annoying desk stand in
the middle. I ended up using a PadTab
for mounting, but having to custom modify it to handle not being in the
centre of the device, and add thick sticky strips (normally used to dampen
fans). The build quality of these tablets is pretty poor.
The display panel on the tablet isn't very good either and has limited viewing angles
from three sides, so in order to be able to see the screen when mounted to
the wall I had to turn it upside down. Android can happily handle a rotated
display, the only downside is that the Archos logo is the wrong way up (a bit of
black tape covers it up now).
I left the Archos mounted on the wall and running for a week, permanently
attached to its charger. At the end of the week I noticed it wasn't sitting
straight on the wall, and in fact the internal batteries had both swelled up
and burst out of the case. I read online a few other stories from folks who
had bought Archos tablets which had failed in the same way, I guess they're
really not designed to be left on charge permanently (that's really bad
design Archos, this could have easily caught fire!)
I figured I didn't really need to have batteries installed, the tablet is
going to be permanently powered on anyway, and it would be safer to leave
the house knowing there was no risk of exploding batteries. So I took the
tablet apart and removed them. Without batteries the Archos starts its
power up cycle, displays a logo, then gets to a certain part of the boot process
and powers down. I guess it does a check on the state of the batteries
and it fails. This presented a real problem and I gave up trying to
use the tablet. Over the Christmas holidays I heard that you could flash an
alternative OS, CyanogenMod, and that actually booted and ran just fine without batteries,
but it wasn't stable and featured enough for running the Home Automation app I'd written.
So I decided to try to debug the Archos OS, so connected it to USB to get
debug messages, and interestingly it powered up perfectly first time. Removing
the USB connection caused it to lock up a few seconds later. Strange
behaviour! I tried just connecting power to the USB port, and that worked
too. So if you want to run your Archos 101 android tablet without internal
batteries you can, but you need to splice your power cable and feed 5v to
both the power socket and the USB socket.
So now I had a working tablet again I changed the power adaptor so it
mounted neatly against the wall:
Here are a couple of pics of it in use:
We keep all our friends and family contacts in a single text file in vCard
format. We sync this file to our phones (mobile and house DECT phones) and home
automation system (for caller ID and phone book). I also print out a copy to
take when travelling. Except I rarely print out an update as I've failed to
find any useful program to pretty print the contacts. Previously I used a quick
hack script in perl to convert the vcard entries to HTML, but it wasn't clever
enough to handle page breaks and needed manual setting all the margins and page
sizes correctly. I like to print it to fit in my paper planner, a Compact size
Franklin Covey planner system.
I've been using Scribus for a few months,
mostly for our
wedding invites and
stationary, and spotted that Scribus had a Python API. So a few hours later and
out has popped a Python script you can use to pretty print a vCard vcf file,
handling page breaks, images, and large margins to skip the hole punches.
Here is an extract from a sample vCard file:
BEGIN:VCARD
ADR;TYPE=work:;;10 Downing Street;London;SW1A 2AA
TEL;TYPE=fax:+44 2079 250918
NICKNAME:Prime Minister
FN:Gordon Brown
N:Brown;Gordon
PHOTO;VALUE=URI:http://www.number10.gov.uk/wp-content/uploads/pm-official-pic-234x300.jpg
VERSION:3.0
END:VCARD
You'll need a few things:
- a sample vCard
file or your own one
- vcf2scribus.py
script (version 1.0)
- A recent version of Scribus. 1.3.5 works, but earlier ones will not.
- You'll also need the python vobject library installed
if you haven't already got it
Use the "Script"
"Execute Script" option, find and select vcf2scribus.py and
hopefully you'll end up with something like this:
You can then save it as a pdf or print it direct.
The script is a bit of a hack and has hard-coded page sizes, fonts, margins,
vcard sections used, and so on. But I figure it might save someone a couple of
hours and only needs a bit of modification to suit. It would be fairly easy to
extend the script to use the Scribus API to let folks select the vcard file,
page sizes, fonts, and things. Bonus points if you fix it to figure out the final sizes of the
images and right align them. This is my second ever python program so no
sniggering at the code!
A few years ago I automated the treadmill in our guest room as a way of motivating
Tracy and I to keep fit. The treadmill sent us emails when we used it, and the
touch panels around the house showed how much we'd used it in the last week and
month. This worked really well for some time; until the point we realised if we both
agreed to stop using it on the same day then there would be no competition, no winner, no loser,
and neither us would feel bad.
Last winter the Red Hat video team came to my house to record some footage for both
internal and external use. On one of the internal videos they look at my home
automation system, point the camera at a wall tablet, and figure out that I'd not
used my treadmill in over two years. So there were really two options (1) remove the
year from the display so it would never look like we were slacking for more than
a year, or (2) find a way to get motivated again.
Recently we both started using Twitter, so it seemed like a natural progression to
hook the treadmill to twitter and have it publicly embarrass us for slacking
off.
So the treadmill now has it's own twitter page.
We called it 'twedmill' ('tweadmill' perhaps is more correct, but just sounds like a
factory that weaves twead jackets).
Here is how it works:
The treadmill itself is pretty standard; it's from Trimline and has a fancy
computer. When I looked inside and saw a PIC I was tempted to interface direct
to the computer, but didn't really have the time to get around to that.
Although the treadmill does things like have a variable incline and measurement of heart
rate, all I really care about it making sure we were using it, for how long,
and how far we got.
Under a cover in the base are the PWM controllers, motors, and the belt
drive to the treadmill deck. The treadmill itself measures the belt speed
by having a single magnet on the wheel and a small sensor next to it, one
revolution giving one pulse. So to keep things simple I just hot-glued a
spare reed switch I had around so the same magnet would trigger it. The reed
switch happily copes with the treadmill even on top speed, so no real need
for anything more fancy.
I didn't have anything that could accurately measure the diameter of the roller, so
by counting pulses at various speeds and comparing to the onboard
display it worked out at 8122 pulses/revolutions per (uk) mile (so that's
about 198mm of travel per pulse, making the diameter of the
roller about 63mm).
I use a 1-wire network in the house to measure temperatures, watch the doorbell,
and control the central heating system, so I wanted to use the same system
to deal with the treadmill. So the reed switch connects to a DS2423
counter (Unfortunately it seems the DS2423 is discontinued now). The DS2423 was
only available in a surface-mount package, so I found some converters on ebay
to save having to design a PCB just for three components. The
DS2423 connects into a 1-wire hub in node0, then to a 1-wire USB adapter on our main
server, currently running Fedora 10.
The software used in based on the source code from 'digitemp'
as it includes
code in cnt1d.c to read the counter values. Every ten
seconds the jabber treadmill bot switches to the right network segment
on the 1-wire hub then polls the counter of the DS2423 to see
if the treadmill has moved. Once the treadmill has stopped moving for
a while the software stores the total distance travelled and time in
a database, sends an email, and uses the perl Net::Twitter module to
post a mesage to twitter. (It can also draw a graph showing speed over
time, but that turned out to be not very interesting)
For the future I'd quite like to hook directly into the
treadmill computer, perhaps giving two way control of the treadmill programs, as
well as recording the incline and heart rate. Another idea has been to use the
current treadmill speed to decide which music video to play next based on bpm (the tv is
connected to an old XBOX running XMBC so could easilly be remotely controlled to
switch videos). Or perhaps link it to google streets for a virtual jog through
some random town. Finally, you currently have to select who is using the
treadmill before (or very quickly after) using it using the touch panels in the
house; which seems like a good excuse to play with some RFID in our shoes, perhaps
also using that to select a playlist of music videos per person.
ZoneMinder is an amazing Linux video camera
security and surveillance application I use as part of my home automation
system. ZoneMinder prior to version 1.23.3 contains unescaped
PHP exec() calls which can allow an authorised remote user the ability to run
arbitrary code as the Apache httpd user (CVE-2008-1381)
CVSS
v2 Base Score 6.5
(AV:N/AC:L/Au:S/C:P/I:P/A:P)
This is really a moderate severity flaw because you need a remote attacker who
has the ability to start/stop/control ZoneMinder, and you really should protect
your ZoneMinder installation so you don't allow arbitrary people to control your
security system. (Although I think at least one distributor package of
ZoneMinder doesn't protect it by default, and you can find a few unprotected
ZoneMinder consoles using a web search).
I discovered this because when we went on holiday early in April I forgot to
turn down the heating in the house. Our heating system is controlled by
computer and you can change the settings locally by talking to a Jabber heating
bot (Figure 1). But remotely over the internet it's pretty locked down and the only thing
we can access is the installation of ZoneMinder. So without remote shell access,
and with an hour to spare at Heathrow waiting for the connecting flight to
Phoenix, I figured the easiest way to correct the temperature was to find a
security flaw in ZoneMinder and exploit it. The fallback plan was to explain to
our house-minder how to change it locally, but that didn't seem as much fun.
So I downloaded ZoneMinder and took a look at the source. ZoneMinder is a
mixture of C and PHP, and a few years ago I found a buffer overflow in one of
the C CGI scripts, but as I use Red Hat Enterprise Linux exploiting any new
buffer overflow with my ZoneMinder compiled as PIE definately wouldn't be
feasible with just an hours work. My PHP and Apache were up to date too. So I
focussed on the PHP scripts.
A quick grep of the PHP scripts packaged with ZoneMinder found a few cases where
the arguments passed to PHP exec() were not escaped. One of them was really
straightforward to exploit, and with a carefully crafted URL (and if you have
authorization to a ZoneMinder installation) you can run arbitrary shell code as
the Apache httpd user. So with the help of an inserted semicolon and one reverse shell
I had the ability to remotely turn down the heating, and was happy.
I notified the ZoneMinder author and the various vendors shortly after and
updates were released today (a patch is also
available)
Figure 1: Local heating control
Last month I read a blog entry from
hadess via Fedora Planet about hardware to let you run homebrew
applications on Nintendo DS. There is a ton of homebrew applications
available, but as of yet no jabber client.
My home automation system is all based around XMPP, with a standard Jabber
server to which all the home automation systems connect to share messages. I
wrote it like this so that it would be easy to just take some existing Jabber
client for a platform and be able to come up with a nice looking front end with
minimal effort.
I found Iksemel, a portable
C XML parser and protocol library that looked perfect, and it only
took a couple of hours to have it ported on the NDS, and a couple
more hours to get it working with PAlib for wifi. It's not a generic
Jabber chat client, but it wouldn't take too much work to make it into
one (although I didn't bother with encryption support so you won't be
able to use it with Google talk servers for example). Anyway, the code
might save someone a few hours, so I've made the source available.
I've included a copy of Iksemel, so if you want to build this yourself
all you need is a working development environment: devkitpro and PAlib. This
still needs some work, I need to integrate a library to handle displaying
images from the network (when the phone rings it can pop up the callers
picture or a streaming picture from one of the cameras when the doorbell
is pushed)
Over the Christmas holiday I joined Second Life. I wasn't expecting to find it interesting as I don't use chat systems at all outside of work (all of the Red Hat Security Response Team work in different locations around the world so irc provides a good crisis room). But I was quickly hooked and started creating shirts, figuring out ways that Sonik could play a live gig, playing Myst-like adventure puzzles, and virtually dancing to great music.
Having discovered libsecondlife and having a few spare hours this weekend I installed mono development tools and knocked up a quick libsecondlife to Jabber interface. All my home automation communicates using XMPP, so by giving my second life avatar the ability to communicate to my Jabber server he can do all sorts of things. My avatar gets notification when the phone rings and can tell me the callers number (and do a cute little animation to pick up a phone), the avatar can turn on and off the house lights, or find the temperatures of rooms.
I've not figured out a use for this yet. I've a few ideas though which will need to wait until there's more free time.
The biggest problem with my home-grown Home Automation system was that
I'm not a graphic designer. My displays all looked a little clunky, like
they'd come out of the 1980s. Guests only ever see the user interface
displayed on the tablets around the house, so I took some time over the
Easter holiday to make the user interface look a bit nicer.
The user interface is written in Perl/Tk and was designed to be
snappy even on the original Point 510 (100Mhz) tablets. I'd already
replaced these tablets around the house with Point 1600 tablets (most
picked up on ebay for about 50-100 pounds each) with the main
advantage that the Point 1600 can run at 800x600 in full-colour rather
than the 256 colours of the 510 in the same resolution.
I first looked around the web to see if there were any existing
Perl/Tk projects that had exciting graphic design I could base on, but
I didn't find anything very useful. In the end I decided to make
the UI look like a web site design proposed by a colleague at Red Hat
for some internal site that didn't get used.
Screenshots from the new design
Heat
The Heating interface lets you look at graphs of past readings for
any sensor or change the target temperature of the house.
Light
Actually we only have a couple of X10 lights in the house, and
we really only ever control the living room lights.
Weather
This is just screen-scraped from the BBC website and updated
every hour.
Cams
We use this screen to look at the security cameras as well
as some other Glasgow web cameras. The interface allows
multipart-jpeg streaming (compatible with ZoneMinder).
Phone
This actually displays a number of events such as the status
of the house alarm, capturing when the doorbell is pressed,
as well as popping up details of who calls us.
Screenshots of the original design
Old heating interface for comparison.
See my original software page to see
how the other screens looked.
Software
I was previously using the Tk/TabBar module from Jarl to provide the
nice tab bars, and a bit of hacking gave the simplified tabbar (with
the advantage that the bar will still nicely wrap over two rows if
needed)
The rest of it was just messing around with frames and alignment and
creating the curved edges. I used the gimp to get a curve I was happy
with, then coverted it from a GIF to xpm with reduced colours. The
xpm was then coded into the application and simplified so that the
program can generate the right curves for any font size.
The Perl/Tk I used to create the headings is
available here and
running that program displays the following:

My home automation tablets use Perl/Tk as their user interface which
makes coding and prototyping really quick and easy and works on both
Linux and Windows platforms.
I use ZoneMinder for looking after the security cameras around the house and had
set up the tablets to be able to display a static image from any camera
on demand. But what I really wanted to do was to let the tablets display
a streaming image from the cameras.
ZoneMinder is able to stream to browsers by making use of the Netscape
server
push functionality. In response to a HTTP request, ZoneMinder
will send out a multipart replace header, then the current captured
frame as a jpeg image, followed by a boundary string, followed by the
next frame, and so on until you close the connection. It's perhaps
not as efficient as streaming via mpeg or some other streaming format,
but it's simple and lets you stream images to browsers without requiring
plugins.
So I wrote the quick Perl/Tk program below to test streaming from
ZoneMinder. It does make some horrible assumptions about the format
of the response, so if you want to use this with anything other than
ZoneMinder you'll need to edit it a bit. It also assumes that your
network is quite good between the client and ZoneMinder; the GUI will
become unresponsive if the network read blocks.
My first attempt ran out of memory after an hour -- I traced the memory
leak to Tk::Photo and it seems that you have to use the undocumented 'delete'
method on a Tk::Photo object otherwise you get a large memory leak. The
final version below seems to work okay though.
# Test program to decode the multipart-replace stream that
# ZoneMinder sends. It's a hack for this stream only though
# and could be easily improved. For example we ignore the
# Content-Length.
#
# Mark J Cox, mark@awe.com, February 2006
use Tk;
use Tk::X11Font;
use Tk::JPEG;
use LWP::UserAgent;
use MIME::Base64;
use IO::Socket;
my $host = "10.0.0.180";
my $url = "/cgi-bin/zms?mode=jpeg&monitor=1&scale=50&maxfps=2";
my $stop = 0;
my $mw = MainWindow->new(title=>"test");
my $photo = $mw->Label()->pack();
$mw->Button(-text=>"Start",-command => sub { getdata(); })->pack();
$mw->Button(-text=>"Stop",-command => sub { $stop=1; })->pack();
MainLoop;
sub getdata {
return unless ($stop == 0);
my $sock = IO::Socket::INET->new(PeerAddr=>$host,Proto=>'tcp',PeerPort=>80,)
;
return unless defined $sock;
$sock->autoflush(1);
print $sock "GET $url HTTP/1.0\r\nHost: $host\r\n\r\n";
my $status = <$sock>;
die unless ($status =~ m|HTTP/\S+\s+200|);
my ($grab,$jpeg,$data,$image,$thisbuf,$lastimage);
while (my $nread = sysread($sock, $thisbuf, 4096)) {
$grab .= $thisbuf;
if ( $grab =~ s/(.*?)\n--ZoneMinderFrame\r\n//s ) {
$jpeg .= $1;
$jpeg =~ s/--ZoneMinderFrame\r\n//; # Heh, what a
$jpeg =~ s/Content-Length: \d+\r\n//; # Nasty little
$jpeg =~ s/Content-Type: \S+\r\n\r\n//; # Hack
$data = encode_base64($jpeg);
undef $jpeg;
eval {
$image = $mw->Photo(-format=>"jpeg",-data=>$data);
};
undef $data;
eval {
$photo->configure(-image=>$image);
};
$lastimage->delete if ($lastimage); #essential as Photo leaks!
$lastimage = $image;
}
$jpeg .= $1 if ($grab =~ s/(.*)(?=\n)//s);
last if $stop;
$mw->update;
}
$stop = 0;
}
Russell Handorf used threads to support
more than one camera at a time (although I would probably do this in
a loop or with select instead of threads)
I use a Dallas 1-wire
network for temperature sensing and control around the house.
Ideally you run a single cable from the PC interface and attach
sensors along the wire, but I didn't think of that before the house
was wired. So instead I use a star network using the existing
cat5 networking to each room, with a one-wire hub from AAG
handling switching between the different spokes of the hub.
At the Home Automation server is a USB to 1-wire interface unit.
This interface connects directly to the one-wire hub. 6 outputs
from the hub go to various places around the house.
Output C6 has a ds18s20 temperature sensor plugged straight into
it, this provides the temperature of the home automation cupboard.
Output C5 goes to the lounge, which has a single ds18s20 temperature
sensor plugged straight into it, this provides the temperature of
the lounge which is used as the master control for the heating system.
Output C2 goes to the master bedroom, again with a single ds18s20
temperature sensor.
Output C1 goes to the garage, where a temperature
sensor is connected and poked out of the vent to get the outdoor
temperature, and on the same wire is a 1-wire switch used to
control the heating system.
The final output C4 goes to a hacked wireless doorbell. A one-wire
switch detects when the doorbell is activated. The one-wire hub
provides a 5v supply and so we use this to power the doorbell to save
on batteries.
The home automation sensor polls each device in turn to get a reading.
For short events (like a doorbell push) it monitors a latched register
which shows if the state of the input has changed since the last time
the device was polled. I'll write more about the software side of
this and give my source code in a later article.
More photos of 1-wire:
see all at flickr.com

|