The uWasp project has been on hold for a while as I have been working on another project. I'm calling this a Wireless Reticulation Controller. In fact, I have plans for an entire wireless home automation platform but this just the first real step.
Figure 1 – Reticulation
Controller
This is a 4 station domestic
reticulation controller which I designed and built. It runs on 24V
AC from a plug pack. It has no buttons or display – at least for
now. It receives commands via a custom protocol over UHF. The
controller utilises the ultra cheap 433MHz radio modules that are
available everywhere. I got mine from Little Bird Electronics.
More on the RF side of things a bit later on.
The controller simply plugs into an
outdoor power socket and any reticulation solenoids terminate on the
terminal block. Once powered up, the controller runs a schedule which
is uploaded via the RF link. Manual Override is also supported over
RF. Any station can be switched on independently and also in any
combination – though I need to disable that as I don't want to see
too much current draw on the plug pack. The controller receives it's
clock over RF, so no battery backup is required. A simple Ping
exchange is implemented too. I'm currently seeing a 300ms round trip
which is not too bad considering I haven't optimised anything yet.
The packet loss can also be measured by the ping facility as a bonus
and this help to position the UHF Access Point (more on that later)
as multi-path fading is an issue as far as I can tell.
The heart of the controller is a
ATMega328p (same as Arduino Uno etc). The firmware is (in my humble
opinion) properly designed for extensibility and maintainability.
I'm using a simple Task abstraction and a few different libraries for
queues and other primitives. AES128 encryption is in place but not
activated. I don't plan to activate crypto for my reticulation
system. Sure, someone can drive by and turn on my sprinklers – an
effective water pressure denial-of-service attack is possible if i'm
in the shower at the time. The individual would have to be nearby
since the range on the RF modules is not that great... I digress.
UHF Access Point
Figure 2 – UHF Access
Point (UAP)
Figure 2 above is the UHF
Access Point (UAP) I created to communicate with the controller (and
other devices to come later). It connects to my server over a
USB-to-RS232 cable from SparkFun. Eventually I want to connect this
to a Raspberry Pi to make a nice self contained UAP. I have a
headless server at home which is simply a VM host for a number of
different VMs – one of which runs my Reticulation Web Application.
The Web App talks via UDP multicast (using the fine LCM library) to
an RFGateway application which talks to the board above. I'm using
socat to move data between the USB port on the VM host and the RF
Gateway application which runs inside the guest VM.
Web and RF Gateway Applications
I used the project as an
excuse to learn a few new frameworks. The Web Application is written
in Sencha's ExtJS 4.1 framework heavily using their new MVC features.
Figure 3 – The Simple
Controller
I wrote an administrative
interface for the system which can be extended to support different
types of devices. Currently it allows for Retic Systems to be
defined and the schedule defined too.
Figure 4 –
Administrative Web Application
I did write a previous
version of this web application in Django and JQueryUI. That was
shelved due to desire to learn ExtJS. ExtJS certainly raises the
productivity bar a lot for a RIA-type application. That said, the
Javascript front-end was probably the least productive part of the
entire suite. I'm really keen to get into Microsoft's TypeScript.
I'd really like to stick to Eclipse though due to the cross-platform
advantages. I need to look into writing Eclipse tooling for
TypeScript. I'll probably be proved wrong but I think TypeScript is
going to be huge if it gets Eclipse support. People are starting to
write some really big applications in JavaScript and I feel that when
a project gets really large, IDE support becomes essential. Being a
weakly-typed language means it is difficult to develop great tooling.
TypeScript appears to add in basic features that I think you need to
support serious IDE-driven refactors and being strongly-typed means
the compiler is able to pick up a massive class of bugs for you. It
is Apache licensed which I think is important for adoption outside of
the enterprise world. There is a JQueryUI binding for TypeScript
which I'm very keen to have try out.
Architecture
System Goals
The goal was to build a
system that could be evolved toward an entire home automation
platform. Another really important goal was to pick an RF technology
that was super low-cost – partly because I was really curious as to
whether it could be done and partly because I want to have a lot of
devices in the network. For example, I might want to put sensors on
every window lock or my garage door, or water sensors in the lawn and
gardens. I also wanted to allow for hard-wired devices (such as a
house Alarm).
Reticulation Controller Architecture
The architecture of the
Reticulation Controller is based around a couple of principles:
- Subsystems should be decoupled to the implementation to be changed easily.
- Collaborators should be “injected” using IoC techniques.
- Portability should be maintained in order to allow easy unit testing on a Macbook or a Linux PC.
I imposed a number of design
constraints at the hardware level that influence the architecture
including:
- The target device is 8-bit AVR with at least 32KB Flash and 1KB SRAM.
- The language would be C++ with no RTTI used.
- The RF interface would be cost optimised.
Low-coupling and
high-cohesion is 101 stuff as far as Software Engineering is
concerned but you do need to be careful when all you have is 32KB of
flash to work with. I wanted to try and structure things well and
decided that I would pull back from ideals as space came under
pressure. This turned out to be a great choice because I'm only
using 50% of flash currently and because I've retained good
structure, adding features has been very quick. That said there is
lot's of room for improvement and I think I trim off 1-2KB without
losing the plot.
I wanted to be able to
easily swap out sub-systems to support ease of system evolution,
testability and re-usability. I defined or utilised a number of
interfaces (using pure virtual classes in C++) such as Task, Handler
and Message. Queues are used to communicate Messages between Tasks
in system. For example, once a valid ManualControlMessage is decoded
by the RFTask, this POCO (Plain Old C++ Object) is placed in the
CommandQueue for the CommandPostTask to process. The CommandPostTask
pulls the message from the Queue, and using a simple dispatcher feeds
it to the appropriate Handler. The figure below shows some of the
classes/interfaces in the system.
Figure 5 – Important
classes
Most classes within the
system heavily rely on Dependency Injection (or IoC). I love this
pattern because it let's me unit test components easily. I swap out
dependencies during unit testing for mocks that let me capture and
assert the correctness of certain behavioural interactions.
Portability was important
too. I wanted to be able to develop on my Macbook Air or my Linux
PC. I wanted to be able to use tools like Valgrind and CGDB. So, I
picked a nice easy subset of C++ and no RTTI (I don't think that is
supported on AVR-GCC anyway). The build system is an
SConstruct-based contraption. That was new for me as I'm used to
Make, Ant, Ivy, Maven and MSBuild/TFS. I like it and I'd definitely
use it again.
Reticulation Web Application
The Web
Application is a typical n-Tier setup which is written in Java. I
decided (after scraping the DJango application) that it was time to
have a look at the Play! Framework that i'd heard so much about. I
downloaded Play! 2.0 and started reading the tutorials. It took me a
long time (probably more than 8 hours) to integrate Maven and Play!
together. It was an absolute nightmare but I got it working. You
might ask why, after all Play! includes a build system. I didn't
want to lose the power of Maven and I wanted the ability to work in
Eclipse. The work flow ended up being something like this:
- Make sure everything compiles in Eclispe
- Run a Maven install from the command line
- Run a Play (well SBT) command to pull dependencies from Maven
- Run the Play Server
- Attach debugger from Eclipse
In the
end I got sick of this workflow and ported the solution to Jetty. It
took only 30 minutes and now I have massive amounts of flexibility
back. Please don't read too much into this. Play! Is not design for
my type of application. I just wanted to highlight that you do some
flexibility in order to maintain a Maven build system. Perhaps these
issues have been resolved recently...
The
rest of the application is typical. I have a Service (Business Logic
Layer) which exposes the functionality of the server. As per
defacto-standard Fowler layering, all database transactions (my Unit
of Work) are bracketed within the Service Layer. I'm using Hibernate
for the Data Access Layer and SQL-Lite at the moment.
The
various server side components communicate cross-process via UDP
multicast. I'm using the LCM library to make this easy.
Future Topics
In
another post I might describe the communications protocol and how it
allows (well tries to allow) reliable communication over this type of
radio network. I might also explain how I made the PCBs on my Zen
Toolworks CNC.