Category Archives: Software hacking

A wide sample of software I’ve written over the years.

Pi-Hole on a Raspberry Pi 3

Just a few notes on my setting up Pi-Hole on a Raspberry Pi 3:

  • I used NOOBS to initially install Raspbian linux (jessie)
  • I wanted to set up 2 of them, one on my internal network and one on my DMZ, so I bought/configured two of everything.
  • It’s then an easy process to run the Pi-Hole installation command found on the projects home page
  • I have a PoE switch and was hoping to use that to power the  Pi instead of having an additional power supplies & cables running everywhere. I found this handy PoE splitter that provides the necessary power to the Pi. It’s working like a charm!
  • I was also interested in having a display on the Pi, so I bought a pair of these TFT displays and these enclosures that work nicely with them.
  • To get the TFT display to work you need to install the driver found in LCD-show-170703.tar.gz by following the instructions found here.
  • After the drivers are installed the Pi reboots and the display should start working.
  • To display the Pi-Hole stats I’m using the chronometer2 script.
  • To select the appropriate font size for the display:
    pi@pi-hole:~ $ sudo  dpkg-reconfigure console-setup

    • Encoding: UTF-8
    • Character Set: Guess optional character set
    • Font for the console: Terminus
    • Font size: 8×14
  • To prevent the display from going to sleep add ‘consoleblank=0’ to the end of /boot/cmdline.txt

Modifications to chronometer2

I like the basic concept of chronometer2 quite a bit, but I felt it could be improved upon slightly. For example, I don’t use my pi-hole as a DHCP server, so the few lines of the display showing it’s disabled is just wasted screen real estate as far as I’m concerned. I would much rather see the top client, top domain, and top advertiser that the original chronometer displays. I also wanted an easy way to be able to restart the chronometer2 display on my TFT display that didn’t require rebooting the whole Pi. When I’m tinkering with the chronometer2 script it’s annoying to keep rebooting the Pi and causing brief DNS outages on my network.

Given these thoughts I decided to make some tweaks to the script. Having spent years as a software developer I had one other small detail that I kept in mind – I didn’t want to change the default behavior in any way. So if you’re using the existing chronometer2 script and just drop my version into place on your pi-hole then you won’t see any difference unless/until you start playing with the new parameters I added. Without further ado, the parameters I added include:

    • -f | –format <format_string>
      This option lets you customize the display by being able to change the order of items that are displayed or even removing them. Each section of the display has been assigned an arbitrary letter. You just specify a format string in the order in which you want items displayed:

      a : Logo
      b: Pihole Information
      c: Pihole Statistics
      d: Network Details
      e: DHCP Information
      f: System Information

      The default formatting string is simply ‘abcdef’, so if you don’t specify a custom format string then chronometer2 will use this value, which means the display will look exactly like the one you’re used to. If, like me, you don’t want to display the DHCP details then you would simply include ‘-f abcdf’ on the command line, leaving ‘e’ out of the format string.


  • -t | –top
    This will tell chronometer2 to include the top client/domain/advertiser information in the Statistics section of the display
  • -p | –pid <filename>
    This will write the PID (process ID) of chronometer2 to the specified file, making it easy to kill the script if you ever need to.

Why include the –pid option, you might ask? Good question! As I mentioned above, I wanted a way to be able to restart chronometer2 on my TFT display without having to reboot my Pi or doing any other tricky shenanigans. Most people set up their chronometer script to run out of /etc/profile or /home/pi/.bashrc by simply adding either ‘pihole -c’ or ‘./’ to the bottom of one of those files. Here’s how I have my .bashrc set up:

if [ "$TERM" == "linux" ] ; then
 while :
   /home/pi/ $(cat /home/pi/chronometer2.cmdline)
   sleep 1

For those of you who aren’t terribly familiar with shell scripting, here’s a breakdown of what this does:

  1. is run only if the TERM environment variable is set to “linux”. This is what my Pi sets the TERM variable to when running locally on the TFT display. When I ssh into my Pi the TERM variable is set to “xterm”, so I’m not greeted by the script starting up every time I ssh into it.
  2. is run in an infinite loop (inside the while/do/done block). So if/when the script dies for any reason it will automatically restart after a one second delay.
  3. The script gets its command line arguments by reading them from the file /home/pi/chronometer2.cmdline each time it starts up.

The file /home/pi/chronometer2.cmdline looks like this:

-f abcdf -t -p /home/pi/

I also have a command called ‘killc2’ set up in my .bashrc:

alias killc2='kill $(cat /home/pi/'

So now whenever I want to tinker with the chronometer2 script in any way I just edit the script and/or my chronometer2.cmdline file, invoke the command ‘killc2‘, and after a short pause the script restarts on the TFT display with the new parameters and any other changes I made.

My modifications to the chronometer2 script can currently be found here. If they’re merged into the official chronometer2 project I’ll update this to point there instead.


Indigo Plugin for Haiku Fans with SenseME v 0.3

Version 0.3 of the Indigo plugin is now available.  This version mostly improves the internal handling of events from the fan, and also adds both state and address information to the Devices display in the Indigo GUI.

Download the plugin here.

If you have any questions, comments, suggestions, etc. please post them to the Indigo plugin forum.

Indigo Plugin for Haiku Fans with SenseME v 0.1

The Indigo Plugin for Haiku Fans with SenseME provides the ability to remotely control fans from Big Ass Solutions from within Indigo software. Currently the plugin is limited to support the following functionality:

  • Turn the fan on/off and adjust the fan speed
  • Turn the optional light, if installed, on/off and adjust its brightness
  • Turn the fan motion sensor on/off
  • Turn the light motion sensor on/off
  • Trigger actions based on changes to any of the above states

Disclaimer: The API for SenseME is not published by Big Ass Solutions, and this plugin is in no way supported by them.  This plugin was written by analyzing the network traffic between the SenseME iPhone app and a Haiku fan with SenseME. There is no guarantee that this plugin will continue to work if Big Ass Solutions releases new firmware/software for the fan.

To use this plug-in simply download this ZIP file and uncompress it, then double-click on the SenseME.indigoPlugin file to install it in Indigo.  Once installed, simply create a new Indigo “SenseME Fan” device.  In the device settings, enter the name of the fan and its IP address, both of which can be found in the SenseME smartphone app.

Once the SenseME Fan device is created simply create actions or triggers as you would for any other Indigo device.

If you are interested in learning more about the SenseME API for communicating with the fan then see this post. The source code for the plugin is also hosted on github.


Hacking Big Ass fans with SenseME to control them remotely

Big Ass Solutions (I love that name) has an advanced ceiling fan called Haiku that includes an optional wifi-enabled component called SenseME, which is designed to be controlled by a smartphone app. Big Ass Solutions does not currently make an API available for SenseME, which is very unfortunate for folks who would like to incorporate their fans into third party home automation systems.

DISCLAIMER: What follows is information that I gleaned solely by analyzing the network traffic between the SenseME app and a Haiku fan.  None of this information is provided or supported by Big Ass Solutions, and it may change at any moment if Big Ass Solutions decides to do so. Use this information solely at your own risk. I make no guarantees whatsoever as to the current accuracy of this information. I also make no guarantees that by using this information you won’t irreparably damage your Haiku fan (bricking the SenseME, etc).

Fortunately, they use a relatively simple protocol for controlling the fans. To figure out exactly how the smartphone app and the fan communicate with one another I simply ran wireshark or tcpdump to trace network traffic to/from my iPhone. Fortunately Apple makes it fairly easy to capture packet traces of iPhones by creating a remote virtual interface (RVI) on a Mac.  All it requires is XCode, which you can download from the Mac App Store.  I won’t go into details of setting up an RVI since Apple provides fairly easy instructions on how to do it.

By tracing the network activity of the SenseME app I was able to quickly determine that the app and the fan communicate via UDP on port 31415, and the commands are all in a fairly simple plaintext format.  A command sent from the app to the fan is just a text string that looks like this:


Responses sent from the fan back to the app are in a similar format, but uses parenthesis instead:

(Living Room;LIGHT;PWR;ON)

The number & meaning of each parameter in the command or response varies depending on the command/response.

When the smartphone app starts up it broadcasts a <ALL;DEVICE;ID;GET> message on UDP port 31415 so that all the fans on the same network can receive it.  The fans, in response, send a series of responses back as a number of parenthesis-delimited strings to the IP address that issued the request.  In this way the smartphone app gets a snapshot of the entire current state of the fan.

When the SenseME app sends a command to a specific fan then the first parameter in the message is typically the MAC address of the fan.  It appears that the fan will also respond if the first parameter is the name of the fan, so the following two commands should effectively be identical, assuming “Living Room” is the name given to the fan with the MAC address 20:F8:5E:AB:31:1B:


The fan will send some status messages via UDP broadcast so that all devices on the network that are listening on port 31415 can get updates. This way if you happen to have two or more smartphones all running the SenseME app and one of them changes the speed of the fan then all the apps are notified of the new fan speed.

Here are a few of the more basic commands that I’ve made use of in my testing/analysis of the fan.  Remember that the SenseME app sends commands enclosed in <> and the response(s) from the fan are enclosed in ().  I’ve also colored the commands in blue and the responses in red:

Set fan speed to 3:

Command from app: <Living Room;FAN;SPD;SET;3>
Responses from fan:
(Living Room;FAN;SPD;ACTUAL;3)
(Living Room;FAN;PWR;ON)
(Living Room;FAN;SPD;CURR;3)

Turn the fan off:

Command from app: <Living Room;LIGHT;PWR;OFF>
Responses from fan:
(Living Room;LIGHT;PWR;OFF)
(Living Room;LIGHT;LEVEL;CURR;0)
(Living Room;LIGHT;PWR;OFF)
(Living Room;LIGHT;LEVEL;CURR;0)

Turn the fans motion detector on:

Command from app: <Living Room;FAN;AUTO;ON>
Responses from fan:
(Living Room;FAN;AUTO;ON)
If the motion detector senses motion then this may be immediately followed by:
(Living Room;FAN;PWR;ON)
(Living Room;FAN;SPD;CURR;3) 
(Living Room;FAN;AUTO;ON)

As you can see from the above examples it’s not uncommon to receive multiple responses from a single command sent to the fan. In some cases it’s also possible to see the exact same response twice, like receiving “LIGHT;LEVEL;CURR;0” when the light is turned off.

I’m currently only interested in basic functionality like turning the fan on/off, adjusting the speed, and turning features like the motion sensor on/off so I haven’t delved into a lot of these responses.  There are some responses like “(Living Room;LIGHT;LEVEL;SCALE;16383)” that I haven’t bothered to try to understand, or why you might receive both a “FAN;SPEED;CURR” and “FAN;SPEED;ACTUAL” when they seem to always appear together and provide the same data.

This should provide enough of a basic primer for how to interact with Haiku Fans that have the SenseME option installed.  Good luck!



We use PagerDuty where I work at to manage on-call notifications, escalations, etc. It’s a great tool to manage alerts from tools and services like Nagios, New Relic, and dozens of others. They also provide a handy dandy REST API, and it should be no surprise that somebody then wrote a Python module to encapsulate it (thanks DropBox!).  Thanks to that I wrote a handy-dandy command line tool called pdmaint for my company to schedule maintenance windows in PagerDuty. Since we’ve found it incredibly useful I was able to get the powers-that-be to let us open source it.  So you can find pdmaint over at Github if you’re interested.  There’s a full set of documentation there as well.