Thursday, April 24, 2014

Interfacing XBee with OpenHAB

Purpose of this article is to provide you a kick start for interfacing XBee modules in to openHAB.
Things you need;
1. Preferably Ubuntu machine for openHAB development
2. WINE setup on Ubuntu machine or Windows machine for running X-CTU (XBee configuration utility)
3. XBee Series 2 modules (Series 1 would also fine. But configurations would slightly differ)
4. XBee Explore USB - 1(and XBee 3.3 v power source) or 2 (Both can be powered up from USB)
5. 1 hour of good time :)

Setting up development environment

For setting up Eclipse IDE for OpenHAB, you could follow the instructions at OpenHAB Eclipse IDE setup. Basically it can be installed using 3 methods; install the required plug-ins in Eclipse, install both Eclipse + required plug-ins from Yoxos installer, download the pre-packaged Eclipse + required plug-ins. I used the 3rd method on 64 bit Ubuntu installation. (Note: All 3 methods failed on 32 bit Windows 7)

Tips in case the build fails:
1. Eclipse > Window > Preferences > Java > Compiler > Compiler compliance level to 1.7.
2. Eclipse > Window > Preferences > Installed JREs > Execution Environments > Set 1.7 as compatible environment for each execution environment.
3. Eclipse > Window > Preferences > Plug-in Development > Target Platform > Select openHAB and Reload it.
4. Make sure you have generated the required code by executing org.openhab.model.codegen. 
5. Do a maven clean install
6. Clean the complete workspace

Binding for XBee modules

Original OpenHAB source tree does not include the bindings required for XBee. So we shall pull it from another branch (diaoulael-xbee).  A checked out modified version can be found at openhab_ext

1. Just download the source code, then copy the content of /bundles/binding/org.openhab.binding.xbee in to previously cloned original source tree's /bundles/binding/.
2. Using a text editor, add following XML tag to /bundles/binding/pom.xml, inside the <modules> element.
<module>org.openhab.binding.xbee</module> 
3. Import the new project into Eclipse workspace (openHAB)
4. In Eclipse Run/Debug configurations, Eclipse Application > openHAB runtime > Plug-ins, set org.openhab.binding.xbee Auto start 'true' and start level 'default'

Configurations of XBee modules

One going to be interfaced with the openHAB server machine has to be configured as a coordinator and other as an End device.
1. Download and install X-CTU Next gen Xbee configuration too. I used a Windows machine for XBee configurations.
2. Mount a XBee module on XBee Exlorer USB and add it in X-CTU.
3. Upload the ZNet Coordinator API latest firmware 
4. Configure following setting
     a) Set AP mode to 2
     b) Set serial settings 9600 bps, No flow control, No parity
5. Mount the next XBee module
6. Upload ZNet router/End device API latest firmware
     a) Set AP mode to 2
     b) Set serial settings 9600 bps, No flow control, No parity
     c) Disable all IO lines except DIO-0 to Digital input
   d) Set IR (sampling interval) to 1388 (5 seconds). So it will sample the DIO-0 (pin number 20) and transmit IOSample packet each 5 seconds.

Letting openHAB know about XBee and how to bind it

1. Connect XBee module which was configured as the coordinator to openHAB server machine (running on Ubuntu).
2. Connect/Disconnect to find out the USB device interface assigned to Xbee Explorer USB. For my case it was /tty/USB0
3. Make sure your user account is provided with dialing out permissions 
sudo adduser $USER dialout 
and logout/login
4. In Eclipse openHAB workspace, distribution/openhabhome/configurations/openhab_default.cfg, add following.

################################ XBee Binding #########################################
# Serial port of XBee interface
# Valid values are e.g. COM1 for Windows and /dev/ttyS0 or /dev/ttyUSB0 for Linux
xbee:serialPort=/dev/ttyUSB0

#Baudrate (optional)
xbee:baudRate=9600
5. In Eclipse openHAB workspace, distribution/openhabhome/configurations/items/demo.items, add following. Here I am going to introduce a contact (binary two state "Open" and "Closed") item named Window_FF_Bed2 under "FF_Bed" location and "Windows" groups. Item would appear in web interface under First floor > Bed Room > Bed Room2.

Contact Window_FF_Bed2            "Bedroom2 [MAP(en.map):%s]"         (FF_Bed, Windows)     { xbee="<znetrxiosampleresponse@0013A20040A2206C#D0:" }

Replace the highlighted 64 bit address with your XBee end device's address which can be queried from API/AT commands or printed in the backside of the module.

Running things together

1. Mount the XBee coordinator on XBee Explorer USB and interface it to the openHAB server machine
2. Mount the XBee end device on another XBee Explorer USB and power it up(or simply provide it 3.3v). No need to provide any signaling interface as XBee modules is programmed to sample DIO 0 (pin 20) and transmit the status each 5 seconds by itself.
In Eclipse > Run > Run configurations > openHAB runtime > Run.
2. Once the openHAB runtime is fully started, you should be able to browse 
http://192.168.0.3:8080/openhab.app?sitemap=demo
Replace highlighted IP with your local machine's IP.
3. Navigate to First floor > Bed room, Observe the Bedroom2 status. Initially this is set to "open"
4. Now short the pin 10 (GND) and pin 20 (DIO 0) to emulate a window being closed. Observe the status of Bedroom2 is changed from "open" to "closed". As you make the DIO pin voltage zero and open, changes are reflected in UI (remember we set the sampling to happen each 5 seconds). Hurray!


 
    





Tuesday, November 26, 2013

Running openHAB smart home automation server on Raspberry Pi

openHAB is an excellent vendor and technology agnostic open source software framework for smart home automation. It provides Java based implementation with bindings for more than 20 commonly used smart home automation technologies (KNX, Modbus, PCLBus, Z-Wave, etc) and homogeneous user interface for Web and Mobile (Android and iOS devices). This article presents how you can kick start running this great solution on Raspberry Pi.

Things you need
Raspberry Pi Type B single board computer
Raspberry Pi compatible Wi-Fi dongle (Wi-Pi)
SD Card
5V micro USB power supply
Cross-over Ethernet cable
Wireless router/access point with Internet connectivity (static public IP address at WLAN interface)
A laptop/PC preferably with Ubuntu installation
About 1 hour of good time :)

Installing Raspbian image on SD card
Latest Raspbian comes with Java Runtime Environment (JRE) included. You need to write the downloaded image in to SD card as detailed in http://www.raspberrypi.org/documentation/installation/installing-images/README.md according your development machine's operating system.

Configuring Ethernet (for SSHing) and Wi-Fi (for internet connectivity)
In my situation, I just have a laptop. So I want to access the Raspberry Pi from Laptop using SSH. Default network configuration for Raspbian is set for DHCP. Since IP address assigned by a DHCP server could change each time it connects, therefore a static IP configuration is required. You need to mount the SD card (can be done easily on Ubuntu) and then edit /etc/network/interfaces file.

1) with df command on Ubuntu find the mount point for SD card. 
2) then fire up the editor using sudo gedit /mounting/point/sdcard/etc/network/interfaces
3) replace the file content with following. In doing this match the WLAN configurations so that it has a static IP address in your Wi-Fi network's subnet and password/ssid of that.

auto lo
iface lo inet loopback
#iface eth0 inet dhcp this is a comment
iface eth0 inet static
address 192.168.1.100
netmask 255.255.255.0
gateway 192.168.1.1

auto wlan0
allow-hotplug wlan0
iface wlan0 inet static
address 192.168.0.25
netmask 255.255.255.0
gateway 192.168.0.1
wpa-passphrase mypassword
wpa-ssid myssid

4) After saving the file above, insert the SD card and Wi-Pi dongle in to R-Pi, connect cross over cable between the R-Pi and the development machine and power it up.
5) Change development machine's LAN configurations to following
       IP Address: 192.168.1.2
       Netmask: 255.255.255.0
       Gateway: 192.168.1.1

6) Now do a ssh to the Raspberry Pi ssh pi@192.168.1.100
Assuming default username/password: pi/raspberry

Installing openHAB
Via SSH, we need to download and copy openHAB server configuration
1) Make a directory for openhab sudo mkdir /opt/openhab and cd in to it
2) wget https://github.com/openhab/openhab/releases/download/v1.4.0/distribution-1.4.0-runtime.zip
3) sudo unzip distribution-1.4.0-runtime.zip -d /opt/openhab
4) wget https://github.com/openhab/openhab/releases/download/v1.4.0/distribution-1.4.0-addons.zip
5) sudo unzip distribution-1.4.0-addons.zip -d /opt/openhab
6) wget https://github.com/openhab/openhab/releases/download/v1.4.0/distribution-1.4.0-demo-configuration.zip
7) sudo unzip distribution-1.4.0-demo-configuration.zip -d /opt/openhab
8) Rename default configuration file to be active
sudo mv /opt/openhab/configurations/openhab_default.cfg /opt/openhab/configurations/openhab.cfg
9) sudo chmod u+x start.sh
10) Now run openHAB sever with ./start.sh
It will take couple of minutes to load the modules and openHAB ready for access.
11) Ready to rock!!! Access http://192.168.1.100:8080/openhab.app?sitemap=demo in your favourite browser in the development machine. Again it will take around a minute to fully load the home page for your openHAB server. However you will get the page eventually as shown below. Hurray!!!
At the moment I am exploring the possible tweaks to speed up openHAB responsiveness on R-Pi.

Accessing openHAB server via Internet 
You just accessed openHAB server inside your local network. What if you need to access it from anywhere in the world via internet. By default, NATing on the router won't allow specific port on a specific machine in the network  from the outside world. That's where you need to set up port forwarding in your wireless router/access point. 

How the configurations are done vary from one wireless router model to another. In my case, it was a Netgear DVG100. You should be able to find similar for your router model as well.

1) Login to your wireless router administration page. 
2) Find out the WLAN IP address assigned to your Wireless router. Circled in red below.

3) Then add a service for openHAB for TCP/From port 8080 to port 8080 (So all the inbound traffic for port 8080 are not translated and instead forwarded to machines in WLAN as 8080)
4) Then add a firewall rule to forward openHAB(TCP:8080) inbound service requests to the R-Pi WLAN address (configured in /etc/network/interfaces)
5) Now your openHAB is ready to access from anywhere in this world(even from Mars :) )where an internet connection is available by replacing previous WLAN address with wireless router public IP address identified in step 2.
Auto starting openHAB server on power up of R-Pi
Till up to now, you had to manually start the openHAB server. Let's make it automated so you don't need bother about SSHing and starting it each time.
sudo nano /etc/init.d/openhab, copy the following and save it. I have assumed the default port HTTP number (8080), openHAB installation location (/opt/openhab) and root user (pi).
#! /bin/sh
### BEGIN INIT INFO
# Provides:          openhab
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: OpenHAB Daemon
### END INIT INFO
# Author: Thomas Brettinger 
# Do NOT "set -e"
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin

DESC="Open Home Automation Bus Daemon"
NAME=openhab
DAEMON=/usr/bin/java
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
ECLIPSEHOME="/opt/openhab";
HTTPPORT=8080
HTTPSPORT=8443
TELNETPORT=5555
RUN_AS=pi
# get path to equinox jar inside $eclipsehome folder
cp=$(find $ECLIPSEHOME/server -name "org.eclipse.equinox.launcher_*.jar" | sort | tail -1);

DAEMON_ARGS="-Dosgi.clean=true -Declipse.ignoreApp=true -Dosgi.noShutdown=true -Djetty.port=$HTTPPORT -Djetty.port.ssl=$HTTPSPORT -Djetty.home=$ECLIPSEHOME -Dlogback.configurationFile=$ECLIPSEHOME/configurations/logback.xml -Dfelix.fileinstall.dir=$ECLIPSEHOME/addons -Djava.library.path=$ECLIPSEHOME/lib -Djava.security.auth.login.config=$ECLIPSEHOME/etc/login.conf -Dorg.quartz.properties=$ECLIPSEHOME/etc/quartz.properties -Djava.awt.headless=true -jar $cp -console ${TELNETPORT}"
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions
#
# Function that starts the daemon/service
#
do_start()
{
    # Return
    #   0 if daemon has been started
    #   1 if daemon was already running
    #   2 if daemon could not be started
    start-stop-daemon --start --quiet --make-pidfile --pidfile $PIDFILE --chuid $RUN_AS --chdir $ECLIPSEHOME --exec $DAEMON --test > /dev/null \
        || return 1
    start-stop-daemon --start --quiet --background --make-pidfile --pidfile $PIDFILE --chuid $RUN_AS --chdir $ECLIPSEHOME --exec $DAEMON -- $DAEMON_ARGS \
        || return 2
    # Add code here, if necessary, that waits for the process to be ready
    # to handle requests from services started subsequently which depend
    # on this one.  As a last resort, sleep for some time.
    return 0
}
#
# Function that stops the daemon/service
#
do_stop()
{
    # Return
    #   0 if daemon has been stopped
    #   1 if daemon was already stopped
    #   2 if daemon could not be stopped
    #   other if a failure occurred
    start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
    RETVAL="$?"
    [ "$RETVAL" = 2 ] && return 2
    # Wait for children to finish too if this is a daemon that forks
    # and if the daemon is only ever run from this initscript.
    # If the above conditions are not satisfied then add some other code
    # that waits for the process to drop all resources that could be
    # needed by services started subsequently.  A last resort is to
    # sleep for some time.
    start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
    [ "$?" = 2 ] && return 2
    # Many daemons don't delete their pidfiles when they exit.
    rm -f $PIDFILE
    return "$RETVAL"
}
#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
    #
    # If the daemon can reload its configuration without
    # restarting (for example, when it is sent a SIGHUP),
    # then implement that here.
    #
    do_stop
    sleep 1
    do_start
    return 0
}
case "$1" in
  start)
    log_daemon_msg "Starting $DESC"
    do_start
    case "$?" in
        0|1) log_end_msg 0 ;;
        2) log_end_msg 1 ;;
    esac
    ;;
  stop)
    log_daemon_msg "Stopping $DESC" 
    do_stop
    case "$?" in
        0|1) log_end_msg 0 ;;
        2) log_end_msg 1 ;;
    esac
    ;;
  status)
       status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
       ;;
  #reload|force-reload)
    #
    # If do_reload() is not implemented then leave this commented out
    # and leave 'force-reload' as an alias for 'restart'.
    #
    #log_daemon_msg "Reloading $DESC" "$NAME"
    #do_reload
    #log_end_msg $?
    #;;
  restart|force-reload)
    #
    # If the "reload" option is implemented then remove the
    # 'force-reload' alias
    #
    log_daemon_msg "Restarting $DESC" 
    do_stop
    case "$?" in
      0|1)
        do_start
        case "$?" in
            0) log_end_msg 0 ;;
            1) log_end_msg 1 ;; # Old process is still running
            *) log_end_msg 1 ;; # Failed to start
        esac
        ;;
      *)
          # Failed to stop
        log_end_msg 1
        ;;
    esac
    ;;
  *)
    #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
    echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
    exit 3
    ;;
esac
:
[Original source of the script: https://code.google.com/p/openhab-samples/wiki/Tricks]

Then make it executable with sudo chmod a+x /etc/init.d/openhab 
and update rc.d with sudo update-rc.d openhab defaults.
 Fantastic! Now your openHAB server will start automatically on each power up cycle.

Though the setup done in this article specifically targeted Raspberry-Pi, most of that is valid for any linux based device. In the next article, we would explore how actual devices can be automated using openHAB.



My Linkedin profile