Run homebridge as a service upon reboot


This post shows how to run homebridge automatically upon reboot using upstart.

Install upstart

sudo apt-get install upstart

Create configuration file /etc/init/homebridge.conf with

start on stopped rc
stop on shutdown

setuid pi

script
    export HOME="/home/pi"
    export NODE_PATH=$HOME/node_modules/
    gpio -g mode 27 out
    gpio -g mode 27 down
    gpio export 27 out
    exec /usr/local/bin/homebridge
end script

start on stopped rc ensures that avahi-daemon has been started by its SysV script under /etc/init.d before homebridge is started.

Test the job by running it thus

sudo start homebridge

Use the following command to check the output of the job

sudo tail -f /var/log/upstart/homebridge.log

The following command can be used to verify that homebridge job has been started

sudo initctl list | grep homebridge

To stop the above job

sudo stop homebridge

To run job as a service that will run automatically at boot

sudo service homebridge start

To stop the service forever

sudo service homebridge stop

Toggle GPIO on Raspberry Pi using HomeKit


In this post, I take my HomeKit Raspberry Pi integration a step further, by turning on/off a LED using the homebridge-gpio-wpi plugin. With the ability to control the GPIO pins, I should be able to turn on/off much bigger things using solid state relays and such.

Install homebridge-gpio-wpi

The installation should be pretty straightforward. Assuming you are at the command line in the home folder, run

npm install homebridge-gpio-wpi

That should install all node modules under ~/node_modules/.

Configure homebridge by editing ~/.homebridge/config.json. Here’s mine

{
    "bridge": {
        "name": "Homebridge",
        "username": "CC:22:3D:E3:CE:32",
        "port": 51826,
        "pin": "031-45-155"
    },
    
    "description": "This has some fake accessories",

    "accessories": [
        {
            "accessory":      "FakeBulb",
            "name":           "Test lamp",
            "bulb_name":      "Lamp 1"
        },
        {
            "accessory": "GPIO",
            "name": "GPIO2",
            "pin": 27
        }
    ],

    "platforms": []
}

Configure GPIO2 using the gpio utility, and start homebridge

gpio -g mode 27 out
gpio -g mode 27 down
gpio export 27 out
export NODE_PATH=$HOME/node_modules/
homebridge

See also how to run homebridge as a service upon reboot.

Test with HomeKit

If you’ve configured the Homebridge peripheral in an iOS app such as Hesperus, it should now show you a new device called GPIO2, and allow you to switch it on/off.

LED

Hesperus allows you to create a schedule to turn on and off devices.

Schedule

Make things smart with HomeKit and Raspberry Pi


As an avid iOS user I have been keen on using HomeKit. That’s when I read about a new – and currently free – HomeKit app in the iOS App Store called Hesperus. I don’t have a HomeKit compatible thing at home, but a quick internet search revealed that I could run a HomeKit compatible service called homebridge on a Raspberry Pi. This post only goes so far as configuring a fictitious light bulb plugin that can be controlled remotely.

Setup Raspberry Pi Image

I decided to download a headless (console-only) version of Raspbian called RASPBIAN JESSIE LITE. Instructions for setting up an SD card appropriately can be found here. I tend to use the Windows based Win32 Disk Imager, I trust it and have used it – for as long as I can remember – to write Ubuntu ARM images.

Powering the Raspberry Pi

I didn’t want to use an HDMI display with the Raspberry Pi, and wanted to power it using my laptop. I have used a USB to serial adapter to do that in the past. This time, I went with Adafruit’s USB Serial TTL cable as described in this lesson. That done, I was able to power up and login to the Raspberry Pi using a serial terminal. I tend to use screen on Linux or Mac OS X

screen /dev/ttyUSB0

Configuring Wi-Fi

RASPBIAN JESSIE LITE lacks a full-fledged user interface, making Wi-Fi configuration slightly painful. I am using a Wi-Fi stick and had some issues getting the driver to work. Hopefully, you’ve got a Raspberry Pi 3, or a compatible Wi-Fi stick that does not require too much tinkering. You can also use Ethernet. The following can be used to check whether your network interface can be listed

ifconfig

Look for an interface called wlan0 if using Wi-Fi, or eth0 if using ethernet.

This is how you can create a configuration file for your Wi-Fi access point

wpa_passphrase your_SSID your_passphrase > your_SSID.conf

Copy the contents of your_SSID.conf and paste them into /etc/wpa_supplicant/wpa_supplicant.conf using any text editor. I used vi thus

sudo vi /etc/wpa_supplicant/wpa_supplicant.conf

Having done that, Wi-Fi was up and running. I had internet access, and could access the Raspberry Pi on the local network via ssh.

Installing packages

A few additional Linux packages and configuration steps are required before homebridge may be installed. Packages can be installed thus

sudo apt-get update
sudo apt install nodejs npm git libavahi-compat-libdnssd-dev

Updating Node.js

The version of Node.js installed by apt-get is rather dated, and will not work with homebridge. To update node, use the following commands

sudo npm install -g n
sudo n stable

Install homebridge

homebridge can be installed using npm thus

sudo npm install -g homebridge

Find and install plugins

To do anything interesting with homebridge you’ll require a plugin, and have it configured in ~/.homebridge/config.json. One simple plugin called homebridge-fakebulb can be installed thus

sudo npm install -g homebridge-fakebulb

Its sample configuration file can be used to create the config.json file mentioned above. This is what my config.json looks like

{
    "bridge": {
        "name": "Homebridge",
        "username": "CC:22:3D:E3:CE:32",
        "port": 51826,
        "pin": "031-45-155"
    },

    "description": "This has some fake accessories",

    "accessories": [
        {
            "accessory":      "FakeBulb",
            "name":           "Test lamp",
            "bulb_name":      "Lamp 1"
        }
    ],

    "platforms": []
}

Use with HomeKit

Apple’s HomeKit has been app-less since launch. Siri is the only way you were able to control HomeKit devices. HomeKit has a rich API and it didn’t take long for paid apps to appear in the App Store. Hesperus is a new free app that I opted to use to control homebridge.

Here’s Hesperus with the Homebridge peripheral paired and working, showing the Test lamp device’s status. I can control the Test lamp (turn it on/off) anywhere I have an internet connection because I have an Apple TV (generation 4 – but 3 should also work) at home. Apple TV needs to be signed into the same iCould account as the iOS device paired with the Homebridge peripheral.

IMG_1979

Enable IP multicast routing in Linux kernel


In this post I discuss how to enable multicast routing in a Linux system. It is a continuation to the post Wireless Router with Buildroot and Raspberry Pi, where I discussed how to build a basic Wi-Fi router with a Raspberry Pi. You’ll want to read that first.

Linux kernel configuration

Besides the Kernel modules mentioned in the post(s) linked above, you’ll need a few additional modules.

IP multicast routing and tunneling

IPv6 protocol

Under Networking support, Networking options, enable

  • IP: multicasting
  • IP: tunneling – this is required if you want to use tunneling with mrouted
  • IP: multicast routing and its sub-options
  • The IPv6 protocol

In the absence of IPv6 smcroute fails with an error such as

Starting static multicast router daemon: INIT: ICMPv6 socket open; Errno(97): Address family not supported by protocol
INIT: MRT6_INIT failed; Errno(97): Address family not supported by protocol
smcroute.

IPv6 Multicast Routing

Under Networking support, Networking options, The IPv6 protocol, enable IPv6: multicast routing and its sub-options.

Packet Mangling

Enable packet mangling with TTL target support if you require support for changing TTL values with iptables.

Buildroot package configuration

The following Buildroot packages provide daemons for performing multicast routing. Enable mrouted and smcroute under Target packages, Networking applications. mrouted requires a glibc based toolchain, you will have to enable it instead of uClibc if you want to use mrouted.

mrouted

smcroute

Perform build and prepare the SD card.

Setup multicast routing

The following procedure is performed from a root console. I usually use the serial console through the expansion header.

Use mrouted when proper IGMP signaling exists

mrouted

The default configuration file /etc/mrouted.conf should be enough, unless you want to perform tunneling.

If you don’t have proper IGMP signaling happening, you can still perform static multicast routing using

smcroute -d

smcroute requires a configuration file, which in my case is /etc/smcroute.conf and looks something like

mgroup from wlan0 group 225.0.0.1
mroute from wlan0 group 225.0.0.1 to usb0

If you don’t have an application and want to use ping to test mutlicast, you can enable ICMP echo responses thus

echo "0" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts

You can use ping requests and receive responses from destination hosts

ping -t 10 225.0.0.1

Note the use of the time to live (TTL) parameter -t. Linux and Mac OS X will set TTL to 1 before forwarding message to the default gateway. You can dump ping messages with TTL parameter using

tcpdump -v host 224.0.0.1 or 225.0.0.1

Note change in TTL from 10 to 1 in a packet routed through Mac OS X in the following dump

14:49:19.642140 IP (tos 0x0, ttl 10, id 0, offset 0, flags [DF], proto ICMP (1), length 84)
    10.211.55.12 > 225.0.0.1: ICMP echo request, id 4113, seq 92, length 64
14:49:19.642190 IP (tos 0x0, ttl 1, id 32573, offset 0, flags [none], proto ICMP (1), length 84)
    192.168.2.10 > 225.0.0.1: ICMP echo request, id 4113, seq 92, length 64

If all is well with the routing daemon, IP variable /proc/sys/net/ipv4/conf/{all,interface}/mc_forwarding will be set to 1.

Some other files offer useful hints related to multicast routing. The following lists interfaces where multicast routing is active

cat /proc/net/ip_mr_vif

This lists multicast routing cache entries

cat /proc/net/ip_mr_cache

When using static multicast routing with smcroute, routing will work only when TTL is greater than 1. If the downstream hosts are transmitting packets with TTL at 1, you can use iptables to set TTL thus

iptables -t mangle -A PREROUTING -i wlan0 -j TTL --ttl-set 64

I’ve also had to wait a while after executing smcroute for NAT to kick in, so that source IP address is translated to address of interface on the destination network. Note the change in source IP address in a message sequence captured using

tcpdump -v -i usb0 host 224.0.0.1 or 225.0.0.1
03:03:25.393056 IP (tos 0x0, ttl 63, id 16103, offset 0, flags [none], proto UDP (17), length 41)
    192.168.2.10.61312 > 225.0.0.1.4007: UDP, length 13
03:04:22.277348 IP (tos 0x0, ttl 63, id 8095, offset 0, flags [none], proto UDP (17), length 41)
    192.168.10.2.61312 > 225.0.0.1.4007: UDP, length 13

Mono .NET runtime on Raspberry Pi with Buildroot


Mono is a popular way to run .NET applications on platforms other than Windows. In this post I’ll show how to build and copy Mono onto a Raspberry Pi, with Buildroot.

Obtain source code for Mono

Let’s start by obtaining Mono from GitHub. I suggest using a folder outside of Buildroot. Later, we’ll prepare Buildroot to fetch the source code from this folder.

git clone https://github.com/mono/mono.git

Let’s head into the cloned repo. We’ll need to switch to a different branch. After much trial and error I’ve discovered that branch mono-3.6.0-branch builds without any error

cd mono
git checkout mono-3.6.0-branch

Create a package for Mono in Buildroot

We’ll create a new package called mono in Buildroot, that will fetch the source code for Mono from the cloned repo, and prepare and build it.

The location of source code for the mono package needs to be specified in file local.mk in Buildroot’s root folder

MONO_OVERRIDE_SRCDIR = /home/parallels/mono/

Add a new package called mono to package/Config.in. I’ve added it under menu “Interpreter languages and scripting”, but you can choose another menu

menu "Interpreter languages and scripting"
        source "package/mono/Config.in"

We’ll create a new folder called mono under folder package, and make a configuration file called Config.in

mkdir package/mono
vi package/mono/Config.in

Here’s the content of Config.in

config BR2_PACKAGE_MONO
	bool "mono"
	help
	  Sponsored by Xamarin, Mono is an open source implementation of Microsoft's .NET Framework based on the ECMA standards for C# and the Common Language Runtime.

	  https://github.com/mono/mono

Next, we’ll tell Buildroot how to build the mono package

vi package/mono/mono.mk

Here’s the content for package/mono/mono.mk

################################################################################
#
# mono
#
################################################################################

MONO_AUTORECONF = YES
MONO_DEPENDENCIES = libglib2

$(eval $(autotools-package))

Configure Buildroot and perform the build

Now that package mono has been created, select it by invoking the configuration menu

make menuconfig

You’ll also need to switch to glibc under Toolchain. Build with uClibc fails with

os_dep.c:3990:23: execinfo.h: No such file or directory

glibc

Now, all that’s left to do is to perform the build

make clean
make

After the build, prepare the SD card. Mono’s build does not copy .NET core libraries to the target filesystem. You’ll need to copy those manually, like so

sudo cp -R output/build/mono-custom/mcs/class/lib/basic/* /media/parallels/System/usr/lib/mono/2.0

If you forget to do that, .NET applications will fail with a message such as

The assembly mscorlib.dll was not found or could not be loaded.
It should have been installed in the `/usr/lib/mono/2.0/mscorlib.dll' directory.

Other notes

Builds on branches master and mono-3.12.0-branch fail with

mono/mini/Makefile.am:86: error: JIT_SUPPORTED does not appear in AM_CONDITIONAL
mono/mini/Makefile.am:722: error: JIT_SUPPORTED does not appear in AM_CONDITIONAL
mono/unit-tests/Makefile.am:7: warning: variable 'TEST_LDFLAGS' is defined but no program or
mono/unit-tests/Makefile.am:7: library has 'TEST' as canonical name (possible typo)
autoreconf: /home/devendra/buildroot-2014.08/output/host/usr/bin/automake failed with exit status: 1

Builds on branches mono-3.8.0-branch and mono-3.10.0-branch fail with link time error

mini.c:(.text+0x7878): undefined reference to `mono_cross_helpers_run'

Enable Debugging on Raspberry Pi with Buildroot


This is a quick post that shows how to enable gdb and/or gdbserver on the Raspberry Pi when using Buildroot.

Enable option Build packages with debugging symbols, under Build Options

debugging symbols

Enable the following options under Toolchain

  • Build cross gdb for the host – to facilitate remote debugging
  • Thread library debugging – to enable adding gdb and gdbserver packages to the device’s root file system

cross gdb on host

Thread library debugging

Select gdb and gdbserver (useful for remote debugging), under Target packages, “Debugging, profiling and benchmark”

gdb and gdbserver

Wireless Router with Buildroot and Raspberry Pi


This post shows how to build a basic wireless router, using the Raspberry Pi. It is driven by a custom Linux system built with Buildroot 2014.08, that boots up in no time at all.

Add all appropriate Kernel modules and Buildroot packages referenced in the following posts, before proceeding

Kernel Configuration

I’m using a different USB Wi-Fi adapter in this post. It has the RTL8188CUS chipset that supports access point mode. The Kernel driver is Realtek 8192C USB WiFi, available under Device Drivers, Network device support, Wireless LAN

Realtek 8192C USB WiFi

Package Configuration

Invoke make menuconfig within the buildroot folder from a command prompt. Under Target Packages, select option Show packages that are also provided by busybox

BR2_PACKAGE_BUSYBOX_SHOW_OTHERS

Under Target packages, Networking application, select dhcp and its sub-packages

BR2_PACKAGE_DHCP

If you’re using a different wireless adapter, select hostapd and its sub-packages

BR2_PACKAGE_HOSTAPD

Perform build by invoking make, copy the newly minted system to an SD card, and use it to boot up your Raspberry Pi.

Custom hostapd

The hostapd built by Buildroot does not work with the chosen Wi-Fi adapter. We need to build the hostapd module provided by Realtek for RTL8188CUS.

Download the driver package from Realtek. It contains the GPL source code for hostapd. In my case, I expanded RTL8188C_8192C_USB_linux_v4.0.2_9000.20130911.zip, then expanded wpa_supplicant_hostapd-0.8_rtw_r7475.20130812.tar.gz under folder wpa_supplicant_hostapd.

Proceed to folder hostapd from the command line, and use the toolchain built by Buildroot to build hostapd

export PATH=/home/parallels/buildroot-2014.08/output/host/usr/bin:$PATH
make CC=arm-buildroot-linux-uclibcgnueabi-gcc

Copy hostapd binary to SD card.

Router Setup

Bring up wireless interface with a static IP address

ifconfig wlan0 up 192.168.2.1 netmask 255.255.255.0

Or, when using iproute2

ip addr add 192.168.2.1/24 dev wlan0
ip link set wlan0 up

Configure and bring up dhcpd. Edit /etc/dhcp/dhcpd.conf. Edit following lines so that they are commented (as shown)

#option domain-name "example.org";
#option domain-name-servers ns1.example.org, ns2.example.org;

Edit following line so that it is uncommented (as shown)

authoritative;

Add following lines at the end

subnet 192.168.2.0 netmask 255.255.255.0 {
  range 192.168.2.10 192.168.2.50;
  option broadcast-address 192.168.2.255;
  option routers 192.168.2.1;
  default-lease-time 600;
  max-lease-time 7200;
  option domain-name "local";
  option domain-name-servers 8.8.8.8, 8.8.4.4;
}

Create leases file

touch /var/lib/dhcp/dhcpd.leases

Instantiate dhcpd

dhcpd -cf /etc/dhcp/dhcpd.conf

Configure and bring up hostapd. Create file /etc/hostapd/hostapd.conf with

interface=wlan0
driver=rtl871xdrv
ssid=pi
hw_mode=g
channel=6
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=raspberry
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

Run hostapd

hostapd -B /etc/hostapd/hostapd.conf

Try driver=nl80211 if you’re using a new netlink interface compatible driver. If you get the following error when starting hostapd, you probably need a different driver

Configuration file: /etc/hostapd/hostapd.conf
Line 2: invalid/unknown driver 'nl80211'
1 errors found in configuration file '/etc/hostapd/hostapd.conf'

If you get the following error using the Wi-Fi adapter mentioned earlier, you need to use the Realtek hostapd compiled above, with driver=rtl871xdrv in hostapd.conf

rfkill: Cannot open RFKILL control device
nl80211: Could not configure driver mode
nl80211 driver initialization failed.
hostapd_free_hapd_data: Interface wlan0 wasn't started

Join the pi network from any other device using password raspberry, and you’re good to go. Configure NAT routing, if you want to access internet over the wired ethernet interface like so

echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o usb0 -j MASQUERADE
iptables -A FORWARD -i usb0 -o wlan0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i wlan0 -o usb0 -j ACCEPT

Change usb0 to eth0 if that is where your ISP link is at.

Check where your default route is configured for with

netstat -nr

Or

route

If default route is set for usb0 (or eth0) add route through wlan0 for subnet 192.168.2.0 thus

route add -net 192.168.2.0/24 dev wlan0