Homebridge on Raspberry Pi

December 20, 2017

There are two main types of devices I have in my home.

1. Homekit compatible devices such as EVE devices and HUE lights
2. Non-homekit compatible devices such as Panasonic TV, Wemo switch, TP-Link switch and Panasonic IP Cam.

Such situation greatly limited the power of home automation as some of them just don’t talk to the other.

That’s why I want to try homebridge. I decided to install homebridge on raspberry pi. There is one very stable pi which I built over a year ago which contains lots of REST API I written to automate those non-homekit devices. I named that pi as homehub.

The software installed on homehub is fairly old. It can’t install homebridge. I can’t upgrade it because homehub have a lots service running on it like openldap, freeradius, dns, openvpn blah blah blah. I can’t risk the risk bricking that box.

So I rebuild another pi which I usually used to experiment on gpio and testing software. I renamed that pi as homebridge because homebridge will be the only service running on it right now.

Below is the setup process

  1. Format the sdcard
  2. Download the latest NOOB
  3. Unzip NOOB zip and copy to sdcard
  4. Insert the sdcard to pi and continue the OS setup.
  5. SSH to pi
  6. apt-get update
  7. apt-get upgrade
  8. apt-get install libavahi-compat-libdnssd-dev
  9. apt-get install nodejs
  10. apt-get install npm
  11. npm install -g –unsafe-perm homebridge
  12. npm install -g homebridge-http
  13. run homebridge, then quit
  14. mkdir /var/homebridge
  15. cp -r ~/.homebridge/accessories /var/homebridge
  16. cp -r ~/.homebridge/persist /var/homebridge
  17. useradd homebridge
  18. create a run script at /etc/init.d

    # vi /etc/init.d/homebridge

    #!/bin/sh
    ### BEGIN INIT INFO
    # Provides:
    # Required-Start:    $remote_fs $syslog
    # Required-Stop:     $remote_fs $syslog
    # Default-Start:     2 3 4 5
    # Default-Stop:      0 1 6
    # Short-Description: Start daemon at boot time
    # Description:       Enable service provided by daemon.
    ### END INIT INFO
    
    dir="/var/homebridge"
    cmd="DEBUG=* /usr/local/bin/homebridge -U /var/homebridge"
    user="homebridge"
    
    
    name=`basename $0`
    pid_file="/var/run/$name.pid"
    stdout_log="/var/log/$name.log"
    stderr_log="/var/log/$name.err"
    
    get_pid() {
        cat "$pid_file"
    }
    
    is_running() {
        [ -f "$pid_file" ] && ps -p `get_pid` > /dev/null 2>&1
    }
    
    case "$1" in
        start)
        if is_running; then
            echo "Already started"
        else
            echo "Starting $name"
            cd "$dir"
            if [ -z "$user" ]; then
                sudo $cmd >> "$stdout_log" 2>> "$stderr_log" &
            else
                sudo -u "$user" $cmd >> "$stdout_log" 2>> "$stderr_log" &
            fi
            echo $! > "$pid_file"
            if ! is_running; then
                echo "Unable to start, see $stdout_log and $stderr_log"
                exit 1
            fi
        fi
        ;;
        stop)
        if is_running; then
            echo -n "Stopping $name.."
            kill `get_pid`
            for i in 1 2 3 4 5 6 7 8 9 10
            # for i in `seq 10`
            do
                if ! is_running; then
                    break
                fi
    
                echo -n "."
                sleep 1
            done
            echo
    
            if is_running; then
                echo "Not stopped; may still be shutting down or shutdown may have failed"
                exit 1
            else
                echo "Stopped"
                if [ -f "$pid_file" ]; then
                    rm "$pid_file"
                fi
            fi
        else
            echo "Not running"
        fi
        ;;
        restart)
        $0 stop
        if is_running; then
            echo "Unable to stop, will not attempt to start"
            exit 1
        fi
        $0 start
        ;;
        status)
        if is_running; then
            echo "Running"
        else
            echo "Stopped"
            exit 1
        fi
        ;;
        *)
        echo "Usage: $0 {start|stop|restart|status}"
        exit 1
        ;;
    esac
    
    exit 0
    

    Script copy from https://raw.githubusercontent.com/fhd/init-script-template/master/template

  19. chmod 755 /etc/init.d/homebridge
  20. update-rc.d homebridge defaults
  21. vi /var/homebridge/config.json

    {
    "bridge": {
        "name": "HomeBridge",
        "username": "CC:22:3D:E3:CE:30",
        "port": 51826,
        "pin": "031-45-154"
      },
    
      "description": "HomeBridge HTTP Status Control",
    
    "accessories": [
            {
                    "accessory": "Http",
                    "name": "TV",
                    "switchHandling": "realtime",
                    "http_method": "GET",
                    "on_url" : "http://192.168.1.3/tv/power_on.php",
                    "off_url": "http://192.168.1.3/tv/power.php",
                    "status_url": "http://192.168.1.3/tv/ping.php",
                    "sendimmediately": "",
                    "username": "",
                    "password": ""
            }
    ]
    }
    

The sample config.json I created above allow me to turn off the Panasonic TV and allow the home app query the on/off status of the tv. This requires three php running on the apache, the power.php, power_on.php and the ping.php.

ping.php

To ping the status of the TV. Returning 1 = on, 0 = off.

<?php

$host = '192.168.1.9';
$port = 55000;
$waitTimeoutInSeconds = 1;
if($fp = fsockopen($host,$port,$errCode,$errStr,$waitTimeoutInSeconds)){
        print 1;
} else {
        print 0;
}
fclose($fp);

?>

power.php

To submit a HTTP request to the TV to turn it off.

<?php

$request_file = "./req/power.xml";

$fh=fopen($request_file, 'r');
$xml_data = fread($fh, filesize($request_file));
fclose($fh);

$url = "http://192.168.1.9:55000/nrc/control_0";
$page = "/nrc/control_0";
$headers = array(
        "POST " . $page . " HTTP/1.0",
        "Content-Type: text/xml; charset=\"utf-8\"",
        "SOAPACTION: \"urn:panasonic-com:service:p00NetworkControl:1#X_SendKey\"",
        "Content-Length: " . strlen($xml_data)
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_USERAGENT, $defined_vars['HTTP_USER_AGENT']);

// Apply the XML to our curl call
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_data);

$data = curl_exec($ch);
?>

power.xml

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
 <s:Body>
  <u:X_SendKey xmlns:u="urn:panasonic-com:service:p00NetworkControl:1">
   <X_KeyEvent>NRC_POWER-ONOFF</X_KeyEvent>
  </u:X_SendKey>
 </s:Body>
</s:Envelope>

power_on.php

To send an infra-red signal to the TV in order to turn it on. At the same time, flashing the LED light on the breadboard for 1 second.

<?php
shell_exec('/usr/local/bin/gpio -g mode 18 out');
shell_exec('/usr/local/bin/gpio -g write 18 1');
exec('/usr/bin/irsend SEND_ONCE MYTV KEY_POWER');
sleep(1);
shell_exec('/usr/local/bin/gpio -g write 18 0');
?>

Reference

https://github.com/nfarina/homebridge/wiki/Homebridge-autostart-at-boot-(init.d)-on-Ubuntu-(linux)

Now homebridge is running. Open Home App, add homebridge to Home app by scanning the QR code generated while starting homebridge.

By further expanding config.json, I can add a lots more service to Home app which actually trigger REST API I installed on pi. Now I can add complex rule likes

1. Turn on Fan by trigger EVE switch when HUE motion detected motion and temperature is higher than 24 degree.
2. Play alarm mp3 on pi and email me screen capture from Panasonic IP cam when EVE motion detected movement and I’m not home.



Leave a Reply

Your email address will not be published. Required fields are marked *