I put this sensor in the same box as the AC outlet relay, connecting to the same Pi Zero. Cost breakdown for comparing DIY to retail products:

Totals about ~$60, for a DIY smart outlet + temperature/humidity sensor. This cost of course could be brought down significantly if you can find a 99¢ Pi Zero at Microcenter or use a cheaper Wi-Fi adapter.

Server Intelligent Platform Management Interface: homebridge-ipmi

If you have a home server, it may support IPMI for out-of-band management:

This includes reading the system/peripheral temperatures, monitoring cooling fan speeds, power cycling the server (not bridged yet), or other useful server maintenance related functions. The command-line ipmitool (installed on FreeBSD with sysutils/ipmitools, or `sudo apt-get install ipmitool` on Raspbian) can be used to read all sensor values:

Found the node-ipmi package to call this tool in Node.js. Not much we can do about the voltage sensors (any ideas for what Homebridge service would be appropriate?) but creating the TemperatureSensor and Fan services is straightforward, developed the homebridge-ipmi plugin:

Since IPMI is networked, you can run this plugin on another system, such as a Raspberry Pi running Homebridge, or on another instance of Homebridge running locally on the server itself. My configuration, specifying local IPMI, two temperature sensors, and five fans:

There are lots of future possibilities for bridging IPMI: should the chassis intrusion detector be exposed as a ContactSensor? The power supply state as an Outlet? The out-of-band VNC server as a camera? For now, I am sticking with monitoring temperature and fans on my IPMI-capable server, but also added a “chassis identify” switch. Toggling it blinks the server’s identification LED via IPMI so it can be identified in a large rack of lots of servers.

CPU digital thermal sensors: homebridge-temperature-sysctl

Beyond IPMI, also on a server: measuring the on-die thermal sensors, inside the CPU itself. This is the only plugin in this article that doesn’t work on the Raspberry Pi, since it doesn’t expose temperatures in the same fashion, but it works well on *BSD servers using e.g. coretemp.

Monitoring an 8-core CPU, wrote homebridge-temperature-sysctl:

In principle, this plugin could be adopted for other platforms, but the stock Raspbian on the Pi doesn’t reveal the system temperature in `sysctl -a`. Instead, see homebridge-pi which I already covered above. On a server with an Intel Xeon E3–1230 V2 processor:

$ sysctl -a|grep temperature

hw.acpi.thermal.tz1.temperature: 29.9C

hw.acpi.thermal.tz0.temperature: 27.9C

dev.cpu.7.temperature: 38.1C

dev.cpu.6.temperature: 38.1C

dev.cpu.5.temperature: 35.1C

dev.cpu.4.temperature: 35.1C

dev.cpu.3.temperature: 42.1C

dev.cpu.2.temperature: 42.1C

dev.cpu.1.temperature: 39.1C

dev.cpu.0.temperature: 41.1C

All this data is now available through Homebridge as TemperatureSensors.

LG TV webOS: homebridge-lgtv2

Found the homebridge-lgtv2 plugin, using the lgtv2 WebOS Smart TV plugin to control LG television sets. This plugin is very vendor-specific, there may be other plugins for your TV models. Let’s see if it works with an 55EC9300:

First I had to connect the TV to the network over Wi-Fi. It listens on a WebSocket server, port 3000. Connecting with lgtv2 will show a prompt on the TV asking if you want to give it control.

After confirming this prompt, and installing the homebridge-lgtv2 plugin, I was able to turn off the TV through Homebridge. Turning on the TV is more problematic, however.

homebridge-lgtv2 uses Wake-on-LAN (WoL) via wake_on_lan to send a magic packet to the TV’s MAC address. I tried both over Wi-Fi and a hardwired Ethernet connection to the TV, with the corresponding MAC addresses, neither were able to successfully wake the TV (in fact, I don’t think I’ve ever seen wake-on-LAN work on anything ever in my entire life!). WoL is an Ethernet technology, there is a Wake on Wireless LAN (WoWLAN) standard for Wi-Fi. But I had zero luck with either on this LG 55EC9300 TV.

There are alternative technologies to consider. The LG 55EC9300 Owner’s Manual does not seem to mention WoL, but page 35 documents “external control devices”, first a USB to Serial converter (PL2303 chip-based (Vendor ID : 0x0557, Product ID : 0x2008)):

and phone jack type, via the service port:

Fortunately I happen to have some old broken headphones, unfortunately, soldering the thin wire is extremely difficult (but see some tips at Soldering The Thinnest Wires Ever Conceived: Headphone Modding), I was only able to successfully solder the outer sleeve wire:

However, the jack can be removed from the headphone wires, with careful application of an X-Acto knife and abuse of a large Hakko soldering iron tip:

There actually already is a small amount of solder present already, and wires can be practically soldered onto each of the pads:

then plugged into the Service Only port of the TV:

Wire up the other end to a USB-to-Serial adapter, I used a SparkFun FTDI Basic Breakout — 3.3V, then connect:

screen -L /dev/tty.usbserial* 9600

Turning on the TV while the serial port is connected shows.. something:

bBckcccKC

Based on my reading of the documentation, sending “ka 0 FF” then a carriage return should turn the TV on or off, and commands should be acknowledged. I wasn’t able to get this far in my initial tests, more investigation would be needed. Nonetheless, even if this did work, there’s the problem of turning on the set-top box I have connected to the TV: usually I use its remote control to turn it on or off simultaneously with the TV via IR.

For this reason, a potentially better option may be something like using an ESP8266 + an IR LED to build a “smartphone TV remote”, sending via Homebridge the exact same commands a remote control would. But for now, I’m sticking with homebridge-lgtv2 and only being able to turn the TV off. Update: I since removed this plugin, as it kept trying to connect when the TV was off (TODO: have it ping to show TV online, use WS only for on/off?)

Desk fan, 3-wire PC fan with tachometer: homebridge-pwm-fan

How about a combined sensor and actuator? Consider the humble PC fan, modern versions of which have adjustable speed and also report back their RPM. I had a few spare PC fans sitting unused in a cabinet, let’s try them.

@pavouk documents this 4-wire fan example motherboard logic:

but you have to wonder, why do some PC fans have 2-wires, 3-wires, and 4-wires? PCBHeaven explains How PC Fans Work, 4 wire is essentially:

3-wire lacks the control (although can still be pulse-width modulated through the power supply), but has a tachometer. 2-wire has neither. A 2-wire fan, the Thermaltake TT-9025A 90mm Case Cooling Fan:

This fan was wired up to the +12V wire of the Molex connector, but it can also be powered by +5V and +3.3V from the Raspberry Pi, albeit slower. Without a tachometer it is not too interesting. Moving onto the 3-wire fan, a slightly more modern Insignia NS-PCF8050 80mm Case Cooling Fan:

I didn’t have any 4-wire PC fans readily available for this project, since I was already using them inside a PC.

For this particular 3-wire fan, the red and black wires are for power, the blue is the tachometer (yellow is also common). So that the tachometer outputs an acceptable logic level for GPIO input, wire up the power to +3.3V, ground to ground, then the tach to a GPIO pin: I used physical pin #36, aka BCM 16, G16 on the Pi Wedge. Write a simple script to read and print the input, pulled up high:

#!/usr/bin/python -u

import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BOARD)

TACH = 36 # BCM 16

GPIO.setwarnings(False)

GPIO.setup(TACH, GPIO.IN, pull_up_down=GPIO.PUD_UP)

while True:

print GPIO.input(TACH),

If it is working, when the fan is spinning you should see alternating runs of 1’s and 0's:

… 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 …

Corresponding to activation of the Hall effect sensor:

Adding a 0.001 second sleep and counting the length of the runs:

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 = 21

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 = 29

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 = 20

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 = 29

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 = 20

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 = 27

The 1’s are consistently about 25–30, and 0’s about 19–21. Occasionally there are short runs of an individual 0 or 1. How to interpret this output? Found at StackExchange: How to interpret the output of a 3-pin computer fan speed sensor? which points to 4-Wire Pulse Width Modulation (PWM) Controlled Fans — Specification July 2004, Revision 1.2:

Since it is open-collector, we use pull_up_down=GPIO.PUD_UP to enable the Pi’s internal pull-up resistor, and the tachometer drives the output low when activated. The width of the low pulse itself shouldn’t matter as much as the timing of the falling-edges, which would be at a consistent position on the motor. Interrupts, as I covered in Interrupt-driven I/O on Raspberry Pi 3 with LEDs and pushbuttons: rising/falling edge-detection using RPi.GPIO, are a perfect application for this purpose:

t = time.time()

def fell(n):

global t

dt = time.time() - t # reject spuriously short pulses

if dt < 0.01: return

freq = 1 / dt

rpm = (freq / 2) * 60

print rpm

t = time.time()

GPIO.add_event_detect(TACH, GPIO.FALLING, fell)

while True: time.sleep(1e9)

Consistently reads about 500 RPM, looks reasonable for low voltage. Slowing down the fan by (gently) touching it lowers to 400 RPM or lower. You may be tempted to try increasing the RPM by applying a higher voltage, but note that the tachometer outputs the same voltage, so additional circuitry would be needed to run it on anything other than +3.3V, for use with the Pi’s GPIO.

Complete script: tachfan.py. Now for controlling the fan speed. This is done using PWM, as previously described in Pulse-width modulation: using PWM to build a breathing nightlight and alarm. Using software PWM via pigpiod:

The limitations of the 3-wire PC fan design now become clear: as the power supply is cut between the pulses of the pulse-width modulated power supply, the RPM sensor readings become wildly inaccurate — since you’re also cutting the control circuitry power! At 1 Hz and 99.6% duty cycle:

494

1448

749

492

496

496

494

1838

At even higher frequencies and lower duty cycles, the RPM reading becomes completely worthless. The 4th wire on newer PC fans neatly solves this problem, by providing a control signal independent of the power rail.

Enough with the Python protoyping. As Homebridge is written in JavaScript, this script should be rewritten. Fortunately there is a pigpio NPM package which ought to make it straightforward. But there are some downsides:

The library uses Broadcom pin numbers not physical (ok, I can deal)

The pigpio NPM module uses the pigpio C library directly, conflicting with the pigpiod daemon I am running for other scripts to use within Python (attempts to use fail with an “already in use” error).

Consequentially, the script has to run as root (or permissions adjusted appropriately? but chmod’ing /dev/mem is insufficient):

pi@raspberrypi:~/gpio/homebridge-pwm-fan $ node fan.js

2016–10–09 07:24:36 initCheckPermitted:

+ — — — — — — — — — — — — — — — — — — — — — — — — — — — — -+

|Sorry, you don’t have permission to run this program. |

|Try running as root, e.g. precede the command with sudo. |

+ — — — — — — — — — — — — — — — — — — — — — — — — — — — — -+

There is a module to use the pigpiod daemon in Node.js: pi-fast-gpio. Looks promising, but the source code shows it only implements setPwmDutycycle. Also found pigpio.js, but @jedahan’s GitHub page no longer has https://github.com/jedahan/pigpio.js (broken link, 404 Not Found). To do this Homebridge plugin right, what would be really useful is a complete pigpiod daemon interface for Node.js.

Until then, as an ugly workaround I wrote the GPIO control code in Python, as a helper script, and spawned it from the Node.js module. The helper continuously monitors the RPM and emits on stdout, also accepting PWM frequency and duty cycle parameters as command-line arguments. Not the most elegant approach, but it works. Here it is, homebridge-pwm-fan:

The fan wiring diagram, to two Raspberry Pi GPIO ports:

And the addition to ~/.homebridge/config.json:

You can now monitor and adjust this fan’s speed through Homebridge.

Camera with Motion Detector: homebridge-camera-motion

Raspberry Pi has an official camera, aptly named the Pi Camera V2:

There is also a “NoIR” version, same price but without the infrared filter. I’ll be using the regular camera instead. Originally I was interested in using the camera on a Pi Zero 1.3, which now has a camera connector, but an additional FPC adapter cable is required so I’ll be using it on the Raspberry Pi 3, which has an appropriately sized CSI connector.

The Getting Started with picamera tutorial uses, you guessed it, Python. There will be no further Python in this blog post. Nothing against Python, but it doesn’t advance the goal of writing Homebridge plugins in JavaScript.

Good news: there exists an NPM module node-picamera. Curiously, it just executes the raspistill shell command. The official RaspiCam Documentation says raspistill and raspivid are command-line utilities “written to take advantage of the mmal API which runs over OpenMAX. The mmal API provides an easier to use system than that presented by OpenMAX. Note that mmal is a Broadcom specific API used only on Videocore 4 systems.”

Homebridge’s wiki page Supporting IP Camera says “a plugin can publish camera by invoking api.publishCameraAccessories(pluginName, [PlatformAccessory]).”, details at HAP-NodeJS: IP Camera.

There are two existing Homebridge camera plugins:

I opted instead for using the Motion project, which includes integrated motion detection:

sudo apt-get install motion

Motion is highly configurable, so be sure to read the extensive User’s Guide, but a decent initial config in ~/.motion/motion.conf to start out with is:

run motion then visit http://raspberrypi.local:8081 to watch it stream live!

To force writing a snapshot, visit http://raspberrypi.local:8082/0/action/snapshot

How to get notified from a Homebridge plugin when motion is detected? Motion supports event triggers, the most straightforward is to trigger when a new picture is written (either from motion detection, a periodic snapshot interval, or invoking /action/snapshot), and write various data in realtime:

on_picture_save printf ‘%f\t%n\t%v\t%i\t%J\t%K\t%L\t%N\t%D

’ > /tmp/motion-pipe

If this is added to motion.conf as-is, it’ll be written to a file on disk, however, a FIFO named pipe would be more appropriate. To make one:

mkfifo /tmp/motion-pipe

or run the Homebridge plugin. The plugin can now stream motion events from this pipe using fifo-js. To get snapshots, edit motion.conf

target_dir /tmp

then the plugin will read from /tmp/lastsnap.jpg.

Live streaming requires transcoding through ffmpeg:

sudo apt-get install ffmpeg

fails with “no such package”, for some reason. To build it yourself see: Installing FFMPEG for Raspberry Pi. This takes an unreasonably long time, however. To speed up compilation you can cross-compile. Or just download a precompiled version, this one is from 2016/07/16: @fattylewis Latest ffmpeg cross-compiled for pi. Took 20+ minutes to download and I had to resume the transfer after it was interrupted. Rehosted on Dropbox if you want a copy, the hash for comparison is:

SHA1(/tmp/arm-ffmpeg-20161009.tar.gz)= 84dd63bca3cbfbc5fdefe30b71d1d0f6c935c353

Cribbed some code from homebridge-camera-ffmpeg, but so far I wasn’t able to get the client to perform a streaming request, needs more testing. In the meantime, you can still stream live from http://raspberrypi.local:8081/ directly instead of via Homebridge. Camera snapshots are working, as is the motion sensor. Anyways without further ado, homebridge-camera-motion:

Much more work is to be done on this plugin, but at least basic services (still image snapshots and motion detection) are functional.

Conclusions

This has been a been a whirlwind tour of an initial foray into home automation, built on top of Homebridge and Raspberry Pi. Plugins used:

homebridge-gpio-cmd for an AC power outlet switch

homebridge-pi for system temperature sensors

homebridge-lightsensor-analog for an ambient light sensor

homebridge-bme280 for ambient temperature and humidity

homebridge-ipmi for server temperature, fans, chassis identification

homebridge-temperature-sysctl for even more temperatures

homebridge-lgtv2 for controlling an LG webOS 2 television set

homebridge-pwm-fan for tachometer RPM and PWM fan control

homebridge-camera-motion for motion detection and still snapshots

Services used: Switch, TemperatureSensor, LightSensor, HumiditySensor, Fan, MotionSensor, and CameraControl.

Update 2016/10/11: also added the ContactSensor service using homebridge-contactsensor, see new article: Interrupt-driven contact sensors with Homebridge and Raspberry Pi GPIO

While a lot of ground was covered configuring/developing/using these 9 plugins, this is only the beginning. With home automation is still in its infancy, Homebridge serves an important niche in bridging the gap in vendor support, as well as a vibrant testbed for home automation hobbyists.