Home Assistant API Tool

The ultimate development tool for the Home Assistant API. Connect to your hub, load in your entities and start exploring the capabilities of Home Assistant’s REST API. Edit entity states, trigger automations, send data and call services.

Custom Binary Sensors

Using the binary sensor component, we can define virtual sensors in our Home Assistant configuration that allow us to track states derived from related input data.

Add the following to your configuration to start using binary sensors.

binary_sensor:
  - platform: template
    sensors:
      sensor_1:
        ...
      sensor_2:
        ...

Laundry sensor

Let’s say we want to receive notifications when laundry cycles start and end. Since I don’t think its worth investing in smart appliances, I’ve figured out a way to use virtual sensors and Home Assistant instead.

The following sensor uses a power meter attached to my laundry appliances to determine the state of the cycle (whether a load is running or not).


load_on:
  friendly_name: "Load is running"
  value_template: '{{ states.sensor.laundry_power.state > 5}}'
  delay_off:
    minutes: 5

The idea is that if it is washing a load of laundry, the power consumption will likely be more than 5 watt. I’ve added a delay_off such that the sensor does not flip to off when the washer drum is stationary for a few seconds.

Using this virtual sensor in an automation, we can send ourselves a notification:


- alias:             Laundry Notification
  trigger:
    platform:        state
    entity_id:       binary_sensor.load_on
  action:
    - service:       notify.pushbullet
      data_template:
        message:     >
          Washing load{% if trigger.to_state.state == 'true' %} started{% else %} finished{% endif %} at {{ now().time() }}.

I usually set up the laundry but use the machines delay start feature to schedule the start time such that the load finishes when im expected to come home from work the next day. The notifications keep me up to date on the program cycle and serve as a reminder.

Simples.

I actually had a power meter hooked up to the laundry and TV already, so it was just a matter of defining the binary_sensor and automation in Home Assistant.

TV Sensor

Applying a similar configuration, we can create a sensor telling us whether we left the TV on or not.


tv_on:
  friendly_name: "TV is on"
  value_template: "{{ states.sensor.tv_power.state > 20 }}"

I am using this sensor in an automation that turns off all devices at night (in case I forget to turn off a light before going to bed.)

For determining whether someone is watching TV, I can use the media_player.cast component, which is more relable than basing a virtual sensor on TV power consumption. I don’t have cable TV hooked up to my TV as I watch Netflix and YouTube on Chromecast. If you have other inputs, then defining this tv_on sensor is a nifty way for you to check whether the TV is running. You might even be able to distinguish between different states using the power consumption for each state.

Say playing a movie consumes 40 to 40w, but just playing some music consumes 20watts. It’s not perfect, but you might be able to make it work.

Arduino Types and Use Cases

Arduinos come in all shapes and sizes and it can be intimidating to choose between them. This post should clear up some confusions you might have. This is based on my experience and opinion, because I have spent time figuring what works and what doesn’t in different situations.

How to use Logic Level Shifters

How to use Logic Level Shifters

If you need to use an Arduino that outputs 3.3v logic in a circuit that requires 5v logic signals, you can use a component known as a logic level shifter.

4-channel logic level shifter

I am using this component in circuits controlling addressable LED strips. A NodeMCU ESP8266 chip (which outputs 3.3v logic) can then be used to drive 5v logic signals to the LED strip.

This circuit requires:

  1. A logic level shifter to shift 3.3v logic signals to 5v.
  2. A 3.3v and 5v reference voltage to be applied across its pins.
  3. Which in turn requires a DC voltage converter to splice off 3.3v off of whatever your power supply generates. I only found out recently that the NodeMCU (and Arduinos) have a built-in DC voltage converter. It turns out you can connect any voltage 3.3-12V to the chip’s Vin and GND pins, and the built-in converter steps down the voltage to run the chip! This is great because we do not need our own voltage converter. Using a 5v power supply, we can connect the NodeMCU’s Vin to 5v and the NodeMCU creates a 3.3v voltage across its 3.3v pins. Voltage converter built in! Awesome!

How to wire LLS

The shifter has a high voltage and a low voltage side. LV1, LV2, LV3 and LV4 take in low voltage signals that you want to convert. You can input 4 independent signals to be stepped up to 5v. HV1 to HV4 are the corresponding output pins.

LV and GND on the low voltage side require the expected input signal voltage to be applied to it. In our case you would connect the Arduino’s 3.3v and adjacent GND pins to those pins respectively.

HV and GND on the high voltage side require the “high” potential to be applied to it. In our case that is +5v and ground, respectively.

The component then converts all incoming LV signals to the supplied HV voltage.

As we are working with different voltages here it is easy to mix them up and damage your components. Be very careul about connecting your wires correctly the first time.

How to get around not using LLS

Avoid using logic level shifters if possible. They complicate your circuit and add room for error.

It is a good idea to eliminate having to use a logic level shifter if it can be avoided at all. How? Different ways:

  • If you need to control 5V logic, get a controller that runs on 5v and outputs uses 5v logic on its pins. That way you don’t need to work with different voltages and theres no need to convert logic signals.
  • (for LED controller projects): Use of RGB adapters. These adapters take low voltage PWM signal (say 5v) and a target voltage (12V) on one side and automatically step up the signal to the required voltage. They are essentially compact circuits that integrate the DC voltage converter and transistors. This is a lot easier to use than creating a custom circuit. They are made to step up the PWM signal voltage to control common anode LED strips (which run on 12V). This makes for a much neater and simpler circuit than wiring your own MOSFETS.

Hosting a Jekyll Blog on Raspberry Pi (using Docker)

In an attempt to self-host this blog, I have built an ARM/RPi compatible Docker image for Jekyll. You can build it yourself by running docker build -t jekyll-rpi . or download my image from Dockerhub using docker pull danobot/jekyll-rpi.

The image is 1GB in size and any suggestions to reduce this file size would be appreciated. Leave a comment or edit this page using the link near the post title to submit your changes.

Dockerfile (if you want to build yourself)

FROM arm32v7/ruby:2.4.2-jessie

RUN apt-get update \
  && apt-get install -y --no-install-recommends \
    node \
    python-pygments \
  && apt-get clean \
  && rm -rf /var/lib/apt/lists/
RUN wget https://cmake.org/files/v3.10/cmake-3.10.1.tar.gz
RUN tar xzf cmake-3.10.1.tar.gz && rm cmake-3.10.1.tar.gz

RUN cd cmake-3.10.1 && ls && ./configure --prefix=/opt/cmake  && make
RUN  cd cmake-3.10.1 &&  make install


RUN gem install \
  github-pages \
  jekyll \
  jekyll-redirect-from \
  kramdown \
  rdiscount \
  rouge
VOLUME /src
EXPOSE 4000
WORKDIR /src
RUN cd /bin && ln -s /opt/cmake/bin/cmake cmake

ENV LC_ALL C.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US.UTF-8
ENV JEKYLL_ENV production
ENTRYPOINT ["bash"]

This image packages jekyll, allowing you to run jekyll build without having to set up ruby, bundler, gem and all that good Ruby stuff1 (which can get incredibly frustrating).

We can run this image using the following command:

docker run -it --name jekyll-build -v /home/pi/repos/blog:/src danobot/jekyll-rpi

We then need to run bundle install inside the container before we can use it.

docker exec jekyll-build bundle install

We can now use our image:

docker exec jekyll-build jekyll build JEKYLL_ENV=production

Serving

Now that we’ve got our jekyll-build container ready to build our jekyll blog, we need a way to serve the generated HTML. Jekyll stores the generated site in the _site directory. All we need to do is set up an nginx web server to serve that directory.

Create a docker-compose.yaml file with the following contents:

version: '3.3'
services:
  web:
    container_name: blog-serve
    image: lroguet/rpi-nginx:latest
    ports:
      - 80:80
    volumes:
      - ~/repos/blog/_site:/var/www/html

If you followed my previous tutorial on how to set up SSL and a reverse proxy, then add the labels, networks and expose section as explained in the linked post. This configures your reverse proxy to route internet traffic to your Jekyll webserver container.

Automated Daily Builds

The following script pulls your latest repository changes and rebuilds your _site directory. It starts up your jekyll-build container, regenerates your blog, and then shuts down that container (as its only required to generate the static HTML).

rebuild-blog.sh

JEKYLL_DIR=~/repos/blog

cd $JEKYLL_DIR
git pull

docker stop blog-serve
sudo rm -rf _site

docker start jekyll-build
docker exec jekyll-build jekyll build JEKYLL_ENV=production
docker stop jekyll-build

docker start blog-serve

You can add this script to a Cron job by typing crontab -e and adding the following line to it:

0 2 * * * /bin/bash /home/pi/repos/blog/rebuild-blog.sh
  1. I find setting up Ruby/Rails development environments an absolute pain in the butt. Hence the docker image. ↩︎

Automating Linux File Backups using Rsync, Bash script and Cron

This is a script that copies directories from A to B. It does not compress directories into an archive, though you are welcome to adapt your script using snippets from this post.

The following is a bash script that mounts an external storage device for you (given the /dev/sda1 device name), copies files contained in a SOURCE directory to a DESTINATION directory. You can specify files to ignore in a separate rsync-ignore.txt file. Check out this post for the various ways you can exclude files with rsync.

#!/bin/bash
MOUNTDIR="/home/pi/ssd"
DEVICE="/dev/sda1"
SOURCE="/home/pi/documents/*"
DESTINATION="$MOUNTDIR/documents"
DIR=$(ls $SOURCE)

#echo "DIR: $DIR"

if [ -n "$DIR" ]; then

  if [ $(mount | grep -c $MOUNTDIR) != 1 ]
  then
    echo "Mounting $DEVICE"
    mount -t exfat $DEVICE $MOUNTDIR || exit 1
    echo "$MOUNTDIR is now mounted"
  else
    echo "$MOUNTDIR already mounted"
  fi
  echo "Commencing copy of files"
  rsync -ahvWi --exclude-from='rsync-ignore.txt' --progress $SOURCE $DESTINATION
  umount $MOUNTDIR
else
  echo "The directory is empty."
fi

You can find out where your device is mounted by running tail -f /var/log/syslog and checking the mount location log entry when you plug in your storage device.

rsync-ignore.txt Add and remove files types to exclude. THis file must be in the same directory as your bash script.

*.txt
*.jpeg
*.jpg
*.png
*.exe
*.msi
*.deb
*.gif

Automatic execution using Crontab

Type crontab -e, and paste this:

0 2 * * * /bin/bash /home/pi/rsync-script.sh

This will run your script daily at 2 am.

Spotify Button

Wouldn’t if be great if all you had to do to add a song to your Spotify is smack a big red buzzer button when you hear a song you like? The currently playing song is added to a playlist on your Spotify Account and you can listen to it again later!

Motivation

It happens all too often when I have people over that there is a song playing on Spotify that I really like. In that moment it would be nice (and probably a lot of fun) to be able to smack a button on the table which instantly saves that song to a playlist. I have also been looking for an opportunity to write some backend Javascript in NodeJS and dockerize a NodeJS application server. This project presents the perfect opportunity to try these things out.

Requirements

Hardware

  • Small box (~10cm by 10cm) with large (>60mm emergency buzzer button)
  • (probably) Small OLED screen to display song name and artist
  • (possibly) Battery operated
  • (optional) LED Matrix display for showing the currently playing song name and artist

Software

Backend

  • NodeJS backend serivce written in Express1
  • Communicate with Spotify API to fetch song information
  • Keep track of “buzzed” songs by adding them to a playlist.
  • Respond to “button pressed” events by adding currently playing song to a playlist.
  • Send a websocket or MQTT message2 at the beginning of a new song to update the LED display.

Button Firmware

  • Send a simple “button pressed” API request to Express backend
  • provide visual feedback to show button press has been registered
  • Open a websocket or MQTT connection to backend and listen for song change messages and update the LED display when a message is received.

Backend Features

I got a little carried away with the backend and came up with a web interface with the following features (in development):

Unfortunately, I developed this with the assumption that the Spotify API would allow adding new songs to the play queue. This is not possible yet but the feature seems to be in development.

Auto DJ
Specify one or more playlists on your Spotify account and Auto DJ will add a song from those playlist every couple of songs. This is useful for adding the occasional “sing along” songs to the mix. Just create a playlist with sing-along songs and Auto DJ will automatically insert those songs into the mix at bearable intervals without duplicates!
Party Mode
Enter other Spotify usernames and let your friends add a playlist of their own to the mix! The server keeps track of played songs to ensure there are no duplicates. Keeps everyone happy whilst minimizing the amount of time spent selecting music. Plus, if you hear a song you like smack that button and it is added to a public playlist accessible to everyone.
Normal Distribution Player
Kind of like intelligent shuffle. The randomness of this shuffle mode is based on a normal distribution. We start by sorting the playlist by new to old songs. You can then specify the mean and variance of the normal distribution curve. For example, if you want to hear predominantly songs that you recently discovered then you would place the mean nearer to 100%. Say there are 100 songs in your playlist sorted from old to new. Using the normal distrution as input, we can generate a series of numbers clustered around the mean of, say, 80 percent. The next song played is determined by the output of the normal distribution. Say the output is 75, in this case we play a song in position 75/100. Any played songs are removed from the list. So the next song played will be X% along a scale of 1 to 99, where X is the next number generated by the normal distribution. The benefit of the normal distribution is that you won’t be bombarded with all the latest songs (making you despise them after a while). The normal distribution will add in the occasional “olderish” song into the mix, while playing mostly new material.

How well this will work in practise will be discovered later.

Implementation

Some photos and a video showing the prototype:

Some photos of the NodeMCU breadboard prototype with 1 led and a small red button.

The video above shows the following steps:

  1. Red button is pressed
  2. Arduino makes GET web request to /recents/save to save the currenlty playing song.
  3. Server handled GET request, retrieves currently playing song, saves it to playlist.
  4. Server returns song info and custom message back to client. (The custom messages are inside jokes among my friends)
  5. The request returns song information as well as a random message.
  6. Arduino prints those to serial console (prototype does not include OLED screen) and flashes LED to indicate success.
  7. The banger button is pressed again for the same song (whether thats by accident or deliberately).
  8. The server returns 304 (HTTP status code for “no change/duplicate”) along with song information and a message to display. The song is not logged again as it has already been marked a “banger” (a great song).

Here is the Arduino console output:

Connecting to ***
..............
WiFi connected
IP address:
10.1.1.69
Attempting MQTT connection...connected
making GET request
Status code: 200
{"status":200,"message":"Whatta tune."}
Whatta tune.
Mi Gente
J Balvin
Attempting MQTT connection...connected
making GET request
Status code: 200
{"status":304,"message":"Duplicate, but we'll let it slide."}
Duplicate, but we'll let it slide.
Mi Gente
J Balvin
Attempting MQTT connection...connected

Installation

The NodeJS backend is mostly completed and you can install it by cloning the repository or starting the Docker container. Access it by going to localhost:3000. You need to authenticate with your Spotify account first by clicking on the Login menu option.

docker run -d -p 3000:3000 danobot/spotify-button
  1. Express for no particular reason other than it seems popular and lightweight. I had a look at some API route examples and it seems to be just what I am looking for. ↩︎

  2. Depends if I can be bothered implementing a websocket. An MQTT implementation would probably be simpler because the nature of the protocol implies pushing data messages into the network and then forgetting about them. It is not mission critical that the receiver acknowledges the receipt of new data. A websocket allows two way communication through a dedicated connection between the browser and server. ↩︎

Pagination