Last year I created a project to Internet enable my doorbell (iDoorbell v1). The idea was to send an alert to my iPhone using Prowl whenever someone presses the doorbell. An Arduino equipped with a WiFi shield was used to monitor the bell circuit and invoke the Prowl HTTP web service. The system worked well enough but after a couple of months it just stopped working. As far as I could tell the Opto-Isolator I was using to sense the bell push had blown. There was obviously too much current in the bell circuit for the isolator’s internal LED. I decided to redesign the whole project and start again.
For iDoorbell V2 I decided to introduce a number of improvements to the whole system design.
- Use a current sensor to detect a change in current in the bell circuit when the button is pressed. The Bell circuit is powered by a transformer that produces AC current. The current sensor outputs a voltage on its signal line proportional to the current passing through it. This voltage can then be easily measured on an Arduino input pin. The current sensor provides complete isolation between the AC bell circuit and the simple DC Arduino circuit. The current sensor I chose was the ACS712 that is easy to pick up in a breakout board on eBay for just a few pounds.
- Use XBee modules to create a ZigBee wireless network. Whilst the WiFly shield worked, it did not cope well with WiFi access point restarts or changes. These shields are also relatively expensive, costing around 5 or 6 times more than a regular USB wifi adapter you might use with a PC. Longer term I’m hoping to have a number of sensors around my home so I want a cheaper and more suitable way to network them. I purchased a couple of XBee series 2 modules along with the excellent Ciseco XBee Arduino shield and a Sparkfun XBee Explorer USB.
- Use my home Linux server as a gateway to Prowl. For iDoorbell v1, I was able to construct the correct byte arrays all on the Arduino to form the Prowl API HTTP call, but the programming just felt a bit too low level. It would be much easier and a probably less fragile to use a readily available HTTP Client in a higher level language on my server. This new gateway would also have to connect to the ZigBee network and be able to determine which end device was sending it data (in case I have additional ZigBee connected sensors in the future). I found Andrew Rapp’s excellent XBee-Api on Google Code to implement this part of the Gateway interface.
- Use an integration framework to manage the end points. Assuming I do end up with a number of home sensors connected to this gateway, each will require some custom logic to perform actions based on sensed data. For me this would probably be implemented in a mixture of Java, Ruby or some other scripting language. I considered using a queueing system such as RabbitMQ and MQTT to give some separation between processes but I would end up with dozens of simple server processes all performing specific tasks, each consuming more and more RAM. I’d also have to figure out a way to manage all these processes. I decided to use Apache Camel running inside Apache ServiceMix to manage my integration logic.
This is a diagram showing all the solution components and how they are connected.
Here’s an explanation of how each component works.
The Doorbell Sensor is just an ACS712 current sensor connected to an Arduino with an XBee module. The ACS712 is wired in series in the doorbell circuit and produces a voltage on the Arduino input relative to the current passing through it. On start up, the Arduino initialises the XBee radio then polls the input pin looking for a change in voltage. The current I am sensing is AC (i.e. alternating) so the when the doorbell is pressed the voltage will fluctuate around a midpoint as the current swings +ve and -ve. For my simple application I don’t need to know exactly how much current is flowing, just that the voltage at the input pin, and therefore the current flowing in the doorbell circuit, has changed significantly. If a change is detected a message is sent via the XBee using the serial connection. The sensor then goes to sleep for 30 seconds to prevent additional presses from generating unnecessary messages. For debugging purposes I also have the sensor sending ping messages at regular intervals so I can check the connection is still alive.
Digi’s XBee Series 2 modules are used to create the ZigBee network. On the module connected to my Linux server, I updated it’s firmware to make it run in API mode. This is a requirement of the XBee-Api library and it also means that I can determine the sender of a message from the message meta data in code. This XBee module is also configured to be the Network Coordinator. I also updated the firmware on the XBee module running on the Arduino just to be sure, but left it configured as a Router. I initially configured it as an End Device but found the module would regularly go into sleep mode and would miss bell button presses. I could have fixed this by wiring up the XBee’s sleep pin to wake it up at the appropriate time but it was easier just to use the Router firmware which doesn’t sleep automatically.
Apache ServiceMix is an OSGI service container that acts as a communication bus between services. The actual service integration is implemented using the Apache Camel integration framework. Camel comes with a large number of pre-built and highly configurable components. These components make it very easy to integrate with external services via many different technologies such as queues, over http or flat files. Components are connected together into integration flows using a straight forward XML script. Managing services is relatively straight forward using the ServiceMix console. The Fuse ESB Integration platform from FuseSource is built using Apache ServiceMix, I found much of their documentation really helpful and much better than that on the Apache site.
Whilst Apache Camel comes with a lot of components that will satisfy most integration needs, it doesn’t have a component to integrate with XBee devices. You could say I threw myself into the deep end when it comes to learning and using Camel since I started by developing my own custom component. I also had to learn a lot about Apache Maven quickly too as Camel heavily relies on Maven for build and dependency management.
The built in HTTP client was straight forward to configure to invoke the Prowl HTTP API directly from XML. It constructs a HTTP message with the appropriate headers and body. My Prowl API key is stored as a configuration parameter with Apache Service Mix.
Links to my code on GitHub
Links to useful information
- Running Camel as a Java application:
- Useful example connecting Camel to Twitter:
- Writing your own Camel components: