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.



No comments:

Post a Comment

My Linkedin profile