Dienstag, 19. November 2013

Installing OpenHAB on a Beaglebone Black

Just a few notes on how i installed the OpenHAB home automation software onto the beaglebone black single board computer.

For beaglebone black development, i found the homepage of Derek Molloy (http://derekmolloy.ie/) to be extremely helpful, most of the below setup-steps are found there. 

1. Installing the Java JRE

The Oracle JRE is reported to perform much better then the OpenJVM implementation,
so i chose to use that as java runtime. It can be downloaded here:

http://www.oracle.com/technetwork/java/embedded/downloads/javase/java-embedded-java-se-download-359230.html?ssSourceSiteId=ocomen

As i am using the original Ångström distribution, i took ejre-7u45-fcs-b15-linux-arm-vfp-sflt-client_headless-26_sep_2013.tgz

I copied this to /usr/java and extracted the file:
# mkdir /usr/java
# cd /usr/java
# tar xfvz ejre-7u45-fcs-b15-linux-arm-vfp-sflt-client_headless-26_sep_2013.tgz

The bin-folder can be added to the search-path by adding it to the PATH environment variable and i also exported the JAVA_PATH variable:
# export PATH=$PATH:/usr/java/jdk1.7.0_45/bin/
# export JAVA_HOME=/usr/java/jdk1.7.0_45/
These two lines can be added to ~/.profile (the users shell profile file) to have it set automatically upon next login.

2. Installing OpenHAB

The next step was to install OpenHAB. I copied the OpenHAB folder into /home/root/OpenHAB. Currently the OpenHAB process also runs as user root - i will change this in future, but as the system is not exposed to the public internet, it don't think its too critical.

I adapted the OpenHAB start-skript as follows:
#!/bin/sh
# turn off that annoying blue flashing LEDs on the beaglebone black
echo "taking over LEDs"
echo gpio > /sys/class/leds/beaglebone\:green\:usr0/trigger
echo gpio > /sys/class/leds/beaglebone\:green\:usr1/trigger
echo gpio > /sys/class/leds/beaglebone\:green\:usr2/trigger
echo gpio > /sys/class/leds/beaglebone\:green\:usr3/trigger
cd `dirname $0`
# set path to eclipse folder. If local folder, use '.'; otherwise, use /path/to/eclipse/
eclipsehome="server";
# set ports for HTTP(S) server
HTTP_PORT=8080
HTTPS_PORT=8443
# get path to equinox jar inside $eclipsehome folder
cp=$(find $eclipsehome -name "org.eclipse.equinox.launcher_*.jar" | sort | tail -1);
echo Launching the openHAB runtime...
 /usr/java/jdk1.7.0_45/bin/java -Dosgi.clean=true -Declipse.ignoreApp=true -Dosgi.noShutdown=true -Djetty.port=$HTTP_PORT -Djetty.port.ssl=$HTTPS_PORT -Djetty.home=.
 -Dlogback.configurationFile=configurations/logback.xml -Dfelix.fileinstall.dir=addons -Djava.library.path=lib -Djava.security.auth.login.config=./etc/login.conf -Do
rg.quartz.properties=./etc/quartz.properties -Dequinox.ds.block_timeout=240000 -Dequinox.scr.waitTimeOnBlock=60000 -Djava.awt.headless=true -jar $cp $* -console 5555
The first 4 echo commands are used for taking over control of the four blue User-LEDs on the beaglebone. By default these LEDs are controlled by the kernel and signal current CPU utilization and some other info. The flashing LEDs started to annoy me, so i turned them off.

OpenHAB will now run (when configured properly) when the start.sh skript is called. As i wanted the system to start automatically in a proper way after a reboot, some additional work had to be done:

3. NTP Support

Next thing was installing the NTP support for the beaglebone. As the systems RTC is not battery buffered,  the date and time information will be lost upon each power cycle. I worked around this by syncing the time via NTP upon each startup:

First i installed the NTP package:
# opkg update
# opkg install ntp
Then i edited the ntp config file, basically to use the local (germany based) NTP servers from the ntp.org timeserver pool. I also added a security rule that limits access to my local network.

/etc/ntp.conf:
# This is the most basic ntp configuration file
# The driftfile must remain in a place specific to this
# machine - it records the machine specific clock error
driftfile /etc/ntp.drift

server 0.de.pool.ntp.org
server 1.de.pool.ntp.org
server 2.de.pool.ntp.org
server 3.de.pool.ntp.org

# Defining a default security setting
restrict 192.178.2.0 mask 255.255.255.0 nomodify notrap
After that, the local timezone needed to be adapted by letting the symlink /etc/localtime point to the right zone-file:
# rm /etc/localtime
# ln -s /usr/share/zoneinfo/Europe/Paris /etc/localtime
After this, it is necessary to change the config file of the ntpdate service as follows:

/lib/systemd/system/ntpdate.service:
[Unit]
Description=Network Time Service (one-shot ntpdate mode)
Before=ntpd.service
[Service]
Type=oneshot
ExecStart=/usr/bin/ntpd -q -g -x
ExecStart=/sbin/hwclock --systohc
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
The setting ExecStart needs to be changed as shown above. The first ExecStart line is changed, the second is newly added. The second one syncs the hardware clock to the system time after the NTP sync was performed.

Next is to enable the NTP daemon, so that it is run upon system start:
# systemctl enable ntpdate.service 
# systemctl enable ntpd.service
Upon next reboot, the date and time should be correct.

4. Autostart OpenHAB

Next thing i installed was a configuration file for the systemctl service, so that OpenHAB gets started upon every reboot.


/lib/systemd/system/openhab.service:
[Unit]
Description=OpenHAB
ConditionPathExists=|/usr/bin
After=network.target

[Service]
ExecStart=/home/root/OpenHAB/start.sh
Restart=always
RestartSec=10
StartLimitInterval=0

[Install]
WantedBy=multi-user.target
Then this service is activated by
# systemctl enable openhab.service
and started by
# systemctl start openhab.service
The current state can be queried this way:
# systemctl status openhab.service
That should give an output like:
openhab.service - OpenHAB
  Loaded: loaded (/lib/systemd/system/openhab.service; enabled)
  Active: active (running) since Sat 2000-01-01 01:00:02 CET; 13 years 10 months ago
Main PID: 127 (start.sh)
  CGroup: name=systemd:/system/openhab.service
  |-127 /bin/sh /home/root/OpenHAB/start.sh
  `-247 /usr/java/jdk1.7.0_45/bin/java -Dosgi.clean=true -Declipse.ignoreApp=true -Dosgi.noShutdown=true -Djetty.port=8080 -Djetty.port.ssl=8443 -...
5. Setting up a Samba share for easy configuration

Install the SMB server via opkg:

         # opkg install samba
         # smbpasswd

Edit the Samba config file:

        # vi /etc/samba/smb.conf

I stepped through the config and configured samba to the local needs, most defaults already fitted. I installed a new share:

[openhab]
   comment = OpenHAB
   path = /home/root/OpenHAB
   public = yes
   writable = yes
   printable = no

   write list = root

Samba can be started using systemctl:


    # systemctl restart openhab.service


6. Setting up a static (non DHCP) IP configuration

I prefer to have static IPs for servers in my network. Here i found a description on how to set up a static config:

http://derekmolloy.ie/set-ip-address-to-be-static-on-the-beaglebone-black/



Freitag, 20. Januar 2012

A package for sensor data

As mentioned earlier, i thought on how to transport the sensor data my wireless nodes gather.

As i want the nodes to be able to run from battery power, they should consume as few energy for transmitting data as possible. While my former experiments with TCP/IP were pretty exciting (its awesome that you can run a website wirelessly off an 10€ battery driven uC!) its hard to get a node to become a low power device once you have to take care of all the TCP/IP protocol stack.

So i switched to a very basic network layer, based on the RFM12 lib. When there is data to transmit, it is packed to a simple protocol structure and transmitted over the air as bytestream. I wrote a little class to do all the packing and unpacking work named RadioNodePdu.

Each measurement is represented as the following datastructure:


So for each measurement reading, we have its type (as 8 Bit int) and its value (as 16 Bit int). As a header we then just add the ID of the sending node and pack all to a compact linear bytestream:


This bytestream then is transmitted to the accesspoint, which then decodes it and translates it back to the sensor data. As the length of each channel structure stays the same, we can very easily get the number of channels from the received bytestream:


The single channels then can be accessed very easily by their offsets:


After the data is received by the accesspoint, its receive is acknowledged and then it is converted to a JSON string and posted to my monitoring server via a HTTP POST request. Then a PHP skript jumps in and does the further processing of the data.

The nice thing about this is, that with the type of data transmitted, my monitoring system can automatically "learn" the new channels, once a new node goes online. It creates a new "datafeed" and automatically assigns the correct physical unit and scaling factors to the measurement data, so you just have to name the channel.

Next processing steps can follow!

Mittwoch, 18. Januar 2012

A portable wireless temperature sensor node

I recently wanted to compare the energy consumption in our house with the temperature inside the fridge. It is an old fridge we bought used together with our kitchen, so i expected it to consume quite a lot of energy.

This is what the actual power consumption of the AC phase, the fridge is connected to, looks like:

(I scaled the Y-Axis to 200W so the big peeks get cut off)

You can clearly see, that there is a regular pattern in that graph. There seem to be two different devices consuming power: One is active for about an hour consuming roughly 100W and then pauses for ca. 2 hours. The other device takes about 40 W and turns on for 40 minutes, 14 times a day. Both powers add up when both devices are running simultaneously, that explains the humps on the curve.

My guess was, that the 100 W device is the old fridge and the 40 W device the pretty up-to-date freezer. So - how to find out? One could simply plug out both devices  - but that would defrosts the groceries inside the freezer and would be much too simple :)

So i build a wireless sensor for embedding in the fridge :) This is what i came up with:



It is a small plastic box containing a Jeenode equipped with a 433 MHz RFM12 transceive, with the antenna folded inside the box. It is attached to a 3xAA battery box and to a DS1820 one-wire temperature sensor via a 3.5 mm audio jack.

Most of the time it is in deep power-down mode, but once every minutes it wakes up and transmits the temperature reading out of the fridge to the 433 MHz accesspoint. I found it quite impressive that it manages to establish a bidirectional communication out of what is basically a faraday cage! This is what the reading from inside the fridge looks like:



As you can see, it matches perfectly the power waveform above: whenever the 100 W device is running, temperature falls - until it reaches the lower point of the controllers hysteresis. Power then turns off and the fridge start to warm up, unitl it reaches the upper hysteresis temperature .. and so on.

So, that was fun - next!

Dienstag, 20. Dezember 2011

Shutdown a second harddisk in Mac OS after suspend

I recenctly replaced the main harddisk in my MBP wit an SDD (a Crucial M4, 256GB - runs perfect). As i wanted to have my photo library with me and also wanted more space media data and virtual machines in that device, i also replace the optical multidrive with a magnetic 1 TB disk mounted in a special adapter. All worked very nice, execep one thing: whenever the macbook woke up after a suspend, it would spin up the magnetic disk and keep it on all the time. Most of the time i dont need the additional HDD, so this was annoying. Tuning the energy options did not help, it was constantly running, wasting battery capacity and being noisy rotating. As i got tired of ejecting the disk manually in the diskutility, i eventually managed to put the disk to shutdown immediatly after the system wakes up. First ist installed sleepwatcher http://www.bernhard-baehr.de/ - you can download it as a .tgz there and install it as described in the readme file. After all components were placed at their locations in the filesystme (you need to use "sudo" for most copy operations) i installed two small shellskripts in my home directory: ".sleep" and ".wakeup". The .sleep file is completely empty, the .wakeup contains basically one statement:
#!/bin/sh  
/usr/sbin/diskutil eject /dev/disk1
Problem solved!

Mittwoch, 14. Dezember 2011

Energy monitor redesign

Yesterday i did a complete redesign of my energy monitor system. It is based on an Atmega32 running on a Pollin RF-Evaluation Board connected to three current clamps for measuring the current in the three phases of my house wiring. The current clamps are place just before the RCD in our home.


The software on the Mega32 Energy-Node was based on the ethersex-framework. It worked pretty well, until i added more wireless node to the 433 MHz network. After a Jeenode running ethersex went online, i experienced frequent hangups of the energy node.
So i had the choice between either fixing the hangups or port the Arduino-compatible JeeLib software to my controllers. As the ethersex framework  has grown to a really big project i found it hard to surf through all the source to check whats going on in the software. So i decided to go for the arduino stuff. This code basically consists of small hardware drivers and the main application loop. Clean, simple, easy to understand, and until now - stable.
Especially the JeeLib-Code is designed for low-power devices, and it will be easier to build a battery based application with this codebase.
So first i set up an Eclipse environment for development. I ported the arduino stuff to work inside a C++ Eclipse project and integrated support for automatic programming with avrdude. The arduino Mac application is fine for an easy start, but i like my used eclipse environment for development. This was all pretty straight forward due to the work auf the AVR-Eclipse-Plugin, the Crosspack AVR Crosscompiling-Toolchain for Mac OS X and theAVR-Netino project.

After the Basestation and Energymonitor-Node were able to run basic demo "sketches" (Arduino slang for 'main application loop'), is continued added more functionality. More on this later.

Protocol thoughts

As explained in my previous post, i will look for a way to push information into my monitoring system. I have not yet decided which protocol and format to use.

There are at least two protocol layers you have to care about: The application layer and the transport layer. While the application layer carries the payload data like sensor readings or actor commands, the transportation layers job is to ensure a correct transmission of that data.

For the application layer,  i thought about using something like XML or JSON. While these "full-grown" standard protocols offer the possibility to use the hole bunch of development tools and libraries, they add a lot of processing and transmission overhead. When thinking of wireless sensor networks, you always have to keep in mind the low bandwith of their connection and their sometimes very limited energy ressources. It would be cool to have a sensor node running of a mini solar panel for example. For this reason, i currently prefer a more simple binary protocol that just carries the data needed. 

Same thoughts apply to the transportation layer. First thing that came to my mind was "hey, lets just use TCP/IP". Cool things about IP and TCP are: it's
  • stable
  • provides a secure transportation layer
  • is easy to program with all programming languages (standard sockets)
  • easy to add a encryption layer and firewalling
  • and you got big pile of standard debug, development and monitor solutions for it
so at first i thought it would be the perfect solution for my wireless nodes. But there are a number of disadvantages when using TCP/IP.

First: Overhead. Both in transport data volume and processing efford. There is a lot of information involved that is needed to keep the internet running - e.g. routable addresses

Second disadvantage is: TCP tries to ensure that all data send to the remote receiver gets submitted, using various tricks like ACKs, sequence numbers, the three-way-handshake, retransmissions, growing timeouts and congestion control. When you are transmitting data from a sensor network this does not always make sense. While some events should be transmitted with high security (like "the mailbox was filled" or "open the garage door") some other just get outdated too fast. When you transmit a temperature reading every 5 seconds or so, it just makes no sense to try to resubmit a lost transmission over and over again, as there might be a new sensor reading while the last one still is not transmitted. You better just try to submit it for a few times, and if that does not work, you just wait for the next reading and try again. Its sometime no problem to loose readings, its not critical.

Montag, 12. Dezember 2011

Polling vs. Pushing

My current setup used a regular polling of the sensors to collect and update the environmental information. This was the easiest way to do it during development of the prototypes. The Ethersex-Framework provided all the functions necessary to run a webserver that could be reached via the 433 MHz transceiver (which is a pretty cool feature, BTW!). But of course HTTP adds a lot(!) of overhead to the payload data.

I now changing that polling method to something more efficient. Reading out HTTP is fine for fast progress during development, as you can use all the standard commandline tools like curl, cut, tail etc.. but is wont scale.

In general polling itself does not scale. When you think of running a battery operated sensor node, its just impossible to have the webserver reachable wireless all the time. What you need is an event-driven communication, where the senor wakes up upon an event or regularly, transmits its information and then goes back to low-power-suspend until next time. Only this way of operation will ensure an acceptable battery lifetime.