March 15, 2017

Button Box for Home Assistant

Here I show you how to make a simple button box that can be used to control lights, set scenes, or other automation things connected to your Home Assistant system.

 


It works by detecting short or long presses of 4 momentary push buttons, and sending an appropriate message over MQTT. The software detects "short" and "long" presses of each button. If you press and release in less time than a "long" press, then it is "short".

You set up a corresponding automation rule in Home Assistant to take action based on the incoming MQTT message. You can have different rules for long and short presses of each button.

Why build this?

I have a Home Assistant system running controlling the lighting in my flat. While the web UI for Home Assistant is excellent, sometimes it's handy to just have a button to press.

I already had most of the components to build this project, and so ... why not?

Hardware

My project is based on a Freetronics EtherTen board. I used this because I had a few lying around. It's an Arduino compatible board with Wiznet W5100 chip. The same sketch would work with any similar board.

I purchased 4 momentary push buttons. Essentially I just wanted something with a definite action. I ended up with these red and black buttons from Jaycar.

Connections

The sketch is designed to use 4 digital inputs with the inbuilt pullup resistors enabled. The buttons are wired to connect the digital input to ground when the button is pressed. In the photo the black wire is connected to ground.


The other connection for the buttons goes to a free digital input. Partly I chose ones that were a little bit apart so that I didn't need to put heat shrink on the pins, and partly because this board uses a couple of the inputs to talk to the ethernet hardware.

I used some breadboard connecting wires. I cut off one end and soldered the wires to the buttons, and the other end goes into the sockets on the Arduino. The wires used to have black insulating plastic around the pins, but I removed it so that they fit in the case.


The connections look like this:



The only other connections are power (micro-USB) and the ethernet cable.

Software

The Arduino sketch is included here. The README shows which part of the code should be configured to match your situation.

Want more or less buttons? No problem. Just choose pins, and also a bit mask (powers of 2).

Of course you need to configure;
  • The address of your MQTT server
  • The login and password for your MQTT server
  • The base topic that you will send updates on (this should match your automation script in Home Assistant)
  • The topic names for each button. (I use b1, b2, r1, r2)
  • How long you need to hold the button for to be a "long" press. I chose 1 second.
  • The topic that Home Assistant sends status updates on. Initially I thought I might use discovery, so I was watching for the startup message, but for momentary buttons, discovery actually makes it harder to configure.
  • If your board doesn't assign a MAC address, then you need to make one up. If it is written on the board, then use the appropriate one.
After startup, the software tries to connect to the MQTT server repeatedly if disconnected. Then it watches for button presses, and sends a payload of either "short" or "long" to the appropriate topic when you press the button.

Automation rules

On the Home Assistant side, set up an automation rule listening to the appropriate topic and payload. Your rule can do whatever you think is appropriate.

I have my buttons configured this way:
  • Short press of black 1 turns on one of the lounge lights.
  • Long press of black 1 turns on all the lounge lights.
  • Short press of red 1 turns off all the lounge lights.
  • Long press of red 1 turns off all lights.
etc

The automation rule will end up looking like this in your configuration.yaml

automation:
  - alias: Turn lounge lights 1 on when black 1 short pressed
    trigger:
      platform: mqtt
      topic: myhome/buttons/b1
      payload: short
    action:
      service: light.turn_on
      entity_id: group.loungelights1
  - alias: Turn all lounge lights on when black 1 long pressed
    trigger:
      platform: mqtt
      topic: myhome/buttons/b1
      payload: long
    action:
      service: light.turn_on
      entity_id: group.loungelights
  - alias: Turn off all lights when red 1 long pressed
    trigger:
      platform: mqtt
      topic: mhome/buttons/r1
      payload: long
    action:
      service: light.turn_off
      entity_id: group.all_lights



1 comment:

Eb said...

Just some thoughts on what I might have done differently:

Battery power? I considered if the power requirements were low enough to make this battery powered. In theory you could have the Arduino sleeping most of the time, until you press a button. You want it to wake up pretty fast, so that it is responsive to presses. Reconnecting using ethernet is fairly fast (esp if you don't do DHCP). Given the box needs an ethernet cable connected, I didn't see much benefit in this.

A smaller case? Yes a smaller form factor 'duino clone and a smaller box would work fine. I just used what I had lying around.

How about wireless? Similar code would run pretty well on an ESP8266 powered module. I will probably build some wireless stuff at some point. Wireless means that battery power is attractive. The ESP8266 can power down pretty well, but reconnecting the wireless is a bit slower than ethernet.

Button double press? I see there are switches on the market that allow a double press. In theory the software could be modified to support this, but I'm not convinced it is a good UX. I guess if you made a long press longer, double press could work.