Thursday, 28 February 2019

Whose Turn Is it? An OpenHAB Hack (part 1)

As my young family grows up, we have our little routines - one of which is the weekly Movie Night. On a rotating basis, each family-member gets to choose the movie that we'll watch, as a family, on a Saturday night. Looking at other screens is not allowed during this time - it's a Compulsory Family Fun Night if you like. The thing is, maybe I'm getting too old, but it frequently seems very difficult to remember whose turn it is. Maybe we skipped a week due to some other activity, or nobody can remember exactly because it was a group decision. Anyway, something that computers are especially good at is remembering things, so I decided to extend my existing OpenHAB home (device) automation to include home process automation too!

Unlike the similarly-named Amazon Alexa "skill" which appears to a) be totally random and b) not actually work very well, I wanted something that would intelligently rotate the "turn" on a given schedule (weekly being my primary requirement). I also wanted to keep the essentials running locally, on the Raspberry Pi that runs my OpenHAB setup. I'm sure you could move this entirely into the cloud should you wish, but doing it this way has allowed me to start with the basics and scale up.

First step; create a simple text file with one participant name per line: /home/pi/movienight.txt:

Charlotte
Mummy
Daddy
Sophie
Give it world-readable permissions (chmod 644 /home/pi/movienight.txt) so that the openhab user can read it.

Now we use the exec binding to create a Thing that reads the first line of this file via the head command-line tool, once every 6 hours (21600 seconds):

$OPENHAB_CONF/things/householdrota.things:

Thing exec:command:movienight "Movie Night" @ "Living Room" 
  [command="head -1 /home/pi/movienight.txt", 
   interval=21600,
   timeout=5, 
   autorun=true
]
$OPENHAB_CONF/items/householdrota.items:
String MovieNight "Whose turn is it?" 
  {channel="exec:command:movienight:output"}
$OPENHAB_CONF/sitemaps/default.sitemap:
  ...
        Frame label="Household rotas" {
                Text item=MovieNight label="Whose Movie Night is it?"
        }
  ...
Which results in the following in Basic UI:

Now for the weekly-rotation part. First, a simple Bash script to rotate the lines of a text file such as the one above. That is, after running ./rotate.sh movienight.txt, the topmost line becomes the bottom-most:

Mummy
Daddy
Sophie
Charlotte
/home/pi/rotate.sh:
#!/bin/bash

TMPFILE=$(mktemp)
HEAD=`head -1 $1`
tail -n +2 $1 > $TMPFILE 
echo ${HEAD} >> $TMPFILE
mv $TMPFILE $1

And now we can automate it using a time-based rule in OpenHAB - each Saturday night at 9pm:
$OPENHAB_CONF/rules/householdrota.rules:
rule "Rotate Movie Night"
when
    Time cron "0 0 21 ? * SAT *"    
then 
    logInfo("Rotating movie night...")
    executeCommandLine("/home/pi/rotate.sh /home/pi/movienight.txt")
end

Now this is fine, but believe me when I tell you that having a text field available in a web page somewhere is simply not enough to achieve a winning SAF (Spousal Acceptance Factor). So onwards we must plunge into being able to ask the Google Home whose turn it is ...

Thursday, 31 January 2019

New Year, New Side Project

Launching into the new year with a clean-slate restart of an old side-project that I got stuck on a few years back. I'd built it using Scala and the Play Framework, as was my preference at that time. The problem was, this "purely server-side" solution was simply wrong for this particular problem, which would be far better served being entirely client-side (this will make more sense when I release it!).

Thus, the 2019 reboot of this project will be featuring and utilising all the front-end tech I've been enjoying in the last couple of years:

  • React - for me, the most enjoyable way to build dynamic websites; and with the introduction of Hooks, it's just getting better and better
  • Next.js - a framework that elegantly combines hand-in-glove with React, doing all the hard work to get code-splitting, server-side rendering and routing to be as easy as it can be
  • now.sh - from the makers of Next, this is like the next evolution of Heroku - push code and it's deployed. To a global CDN. Awesome
  • TypeScript - 2018's surprise packet was the explosive arrival of TypeScript as a serious way to write, build and ship JavaScript code. As a types fan and Babel-phobe from way back, this is a win for me in a couple of ways
  • Styled-Components with Styled-System - Although I could argue that CSS-in-JS isn't really needed on a one-man project, the power of Styled-Components combined with the control of Styled-System is just too nice to ignore

The output of all this tech will be a responsive PWA that you can "install" to your device and use completely offline. No network connection, no data, no native Android/iOS code. This is the future!