Thursday, October 30, 2014

Sensor Networks with Java (Part II)

Hi there,

Getting back from GeeCON Prague and EclipseCon Europe I thought it might be time for part 2 of my Sensor Networks post.
In the last post I've explained how to setup the network and how to use Java to read out the data from the Coordinator Node.

For a session at Java One this year I've created a little demo project that also shows another example on how to connect to a XBee Series 2 using Java. You can find the code for that little demo here.

But now back to my Sensor Network, now that I've setup all the hardware I needed a way to store and visualize the data.

Storing data
To store the sensor data you have different options

  • local
  • cloud

Because a cloud solution was a bit overkill for the kind of stuff that I would like to do and I also like to keep as much data in-house as possible I've decided to go with solution one...local storage.
Well like I've mentioned in the last post I would like to use as many embedded devices as possible (at least because they are small, cheap and I can setup them up in my office easily). The easiest way would be installing a little database on a Raspberry Pi, BeagleBoneBlack or similar hardware and store the Sensor Network data in this database.
But because these devices are using SD-Cards as their hard-drive this would mean I would have to install the database on the SD-Card. In principle no problem BUT SD-Cards are not made for continuous file access which means your SD-Card will get corrupted very soon. One solution would be using an USB memory stick on these devices and store the data on the stick. The disadvantage of this approach might be the speed of the memory stick and to be honest I don't really like the idea :)
So I was looking for an embedded board that has a SATA port where I could attach a real hard-drive. Long story short I've decided to go with the CubieBoard 2 which you could see on the following picture

The CubieBoard 2 is a really nice board with following specs

  • DualCore ARM A7 1 GHz CPU
  • Mali-400 MP GPU
  • 1 GB RAM
  • 1 Micro SD slot
  • 1 SATA 2.0 connector
  • RJ45 Ethernet
  • I2C, SPI, LVDS and more

So with the ability to connect a SATA hard-drive I'll be able to put the database to the hard-drive which will give me more speed. Even if a SSD drive is also not the best solution for a database drive I decided to use one because it's faster and if you take a small size SSD it will be cheap (I'm using a 64GB SATA 2 drive from Sandisk which costs around 40 €).
As database I decided to go with mongoDB but you can use whatever you like. I used mongoDB because there was an ARM port available (which is not really up to date but works). 
The problem with mongoDB was that you have to build the version on your own, means there is no out of the box binary that you can use. You will find some blogposts on the web that describe how to do that (e.g. here).
After that was done my CubieBoard based database-server was ready to go.
So let's take a look at the current setup, we have the Raspberry Pi that acts as Coordinator Node in my Sensor Network and that get events everytime a XBee is sending data. Then I have the CubieBoard 2 which is running mongoDB and could store the data in that database.
The question is how should the data get from the Coordinator Node into the database?
Well the simplest solution would be using the mongoDB Java driver to store the data directly from the Raspberry Pi over my internal network into the mongoDB on the CubieBoard. But I used a different approach...

Because all the embedded devices are running on my local network at home I needed to find a way to access my internal network from the outside. I could have open ports for each device and access it from outside but I decided to use some kind of a central communication server.
Therefor I decided to go with MQTT (Message Queue Telemetry Transport). When using MQTT you need a so called MQTT broker that receives all incoming messages and forwards them to the subscribed clients. Lucky me there is a very small free MQTT broker available called Mosquitto. Because this broker is small and doesn't need huge hardware to run it was the perfect fit for my project. My broker is running on an Odroid-U3 from hardkernel which looks like this.

This board has more than enough power to run Mosquitto as you will find out when taking a look at the specs.
So with the MQTT broker in place I had a central communication server where all devices can talk to. 
The Coordinator Node now publishes a MQTT message every time it receives data from a XBee Sensor Node in the Sensor Network.
Because of the Publish-Subscribe model now everybody that is interested in that data can subscribe to the topic and can use it.
Instead of directly writing the data from the Coordinator Node into the mongoDB instance on the CubieBoard 2 I've wrote another small Java program that is running on the CubieBoard 2 and that is listening to data from the Coordinator Node.
With this approach I could also place the mongoDB server where ever I like. But the main reason for the additional Java program was the reason that I can now also do some data preprocessing on the CubieBoard 2 before storing the data to the database which is nice.
So now we have the Raspberry Pi Coordinator Node that receives the XBee data and publishes it via MQTT. Then there is the CubieBoard 2 that is running the mongoDB instance and is listening to MQTT messages from the Coordinator to store the preprocessed data in the mongoDB.

Ok now that I can measure the and store the data it was time to create something to visualize the data and because I love Java I decided to create a JavaFX based desktop client to visualize the measured data.
Instead of only monitoring the Sensor Network data I've added more features like getting the current weather conditions from the closest airport, showing weather information from my own weather station outside (because the airport is around 30km away) and more.
But here let's only focus on the Sensor Network Data...
Now that we have all the data available in the database we can use different kind of visualizations, first of all we can visualize the live Sensor Node data which I did like follows

As you can see I use a gauge to visualize the last measured temperature of each Sensor Node (the three gauges without a value are ran out of battery...waiting for new batteries at the moment :)). The color of the gauge will change with the temperature and in addition also the current supply voltage will be visualized with a little battery icon. The color of the battery also indicates the state of the battery.
Well it's nice to see the current situation but I'm interested in the temperature of the last 7 I simply used a line chart to visualize the data from the database like this...

Here you can see the temperature variation of each Sensor Node over the last 7 days which is useful to indicate weather trends etc.
Because we have the supply voltage also available in the database why not visualizing the voltage of each Sensor you go...

As you can see on this chart I can easily identify Sensor Nodes that will need a new battery soon (e.g. Anton in the chart above). This is very useful because the batteries will last for a long time but when they are going down the drain it will just take a fews days before they will die. So with this chart I can identify weak batteries by looking at the chart once a week.

Because the temperature do not only vary from day to day but also within one day I was interested in how the temperature in each room varies over the day. Therefor I've created a little RadarChart that shows the temperature for each room, here is a screenshot...

As you can see I can select each Sensor Node on the left side and one of the last 7 days on the bottom. With this you can monitor the temperature variation from each Sensor Node on each of the last 7 days which is really interesting some times.

All the controls that you see on the screen shots above are taking from the Enzo JavaFX controls library that you can find here.
Please keep in mind that all controls in that library are made for my personal demos and are not production ready (but might be useful as a start) :)

Because this post is long enough I won't show you all the mobile clients that I've also created like an iOS and Android client and also a SmartWatch client. But in principle they all look like the desktop version and thanx to Gradle I build all these versions for all these platforms in one Multiproject Gradle build which means more than 90% of the code is the same for all platforms...remember the credo of Java...write once run anywhere :)

That's it for today...keep coding...