Integrate BusyBoard into HomeAssistant
and trigger automations when you are busy
Let’s take the little app created in the previous post up to the next level and integrate it into a home automation platform Home Assistant (HA). That way if you change your status on the BusyBoard, Home Assistant can pick this up and trigger an automation. Here we’ll add an API to BusyBoard which can be read easily from Home Assistant so we can turn a smart light on (and switch the color to red).
While the BusyBoard was a nifty solution to indicate to your household when you are busy with work and should not be interrupted, this does require everyone to check the BusyBoard regularly. Not the most user-friendly experience! It would be far more convenient if we can somehow indicate thi in the real world … similar to an “On Air” sign in radio- and tv-studios. As I’ve already got a few smart lights linked up with HA this can fairly easily be done, but we’ll need an API in BusyBoard we can read from Home Assistant, so let’s implement this.
Adding an API to BusyBoard
If you are developing a larger application an you need an API, have a look at packages like Flask-Restful
or even a framework designed specifically for APIs like FastAPI! Here however we don’t need bells and whistles, we
simply need an endpoint for each users where we can see if they are busy or not. The first step is do add a function to the
database model to export a user to a dictionary. To do this a little code needs to be added to the model
(in ./busyboard/models.py
) as shown below.
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.Text)
busy = db.Column(db.Boolean)
busy_with = db.Column(db.Text)
can_be_disturbed = db.Column(db.Boolean)
notes = db.Column(db.Text)
path = db.Column(db.Unicode(128))
last_change = db.Column(db.DateTime, default=datetime.utcnow)
### see repository for the full code, new function below
def to_dict(self):
return {
'id': int(self.id),
'name': str(self.name),
'busy': bool(self.busy),
'busy_with': str(self.busy_with),
'can_be_distrubed': bool(self.can_be_disturbed),
'last_change': str(self.last_change)
}
This couldn’t be more straightforward, a single function that an export the data from the model as a dictionary. Here, all fields are explicitly converted to integers, strings and bools. This isn’t strictly necessary for all fields, but it helps avoiding errors when converting them to JSON later on.
Next, we’ll need to add the routes to ./busyboard/__init__.py
, again this is very simple. A few lines of code
shown below will do the trick.
@app.route('/api/users')
@app.route('/api/users/')
def api_users():
users = User.query.all()
return jsonify(list([u.to_dict() for u in users]))
@app.route('/api/users/<int:user_id>')
def api_user(user_id: int):
user = User.query.get(user_id)
return jsonify(user.to_dict())
So now if we go to e.g. \<busyboard_url\>/api/users/1
we’ll get a JSON response which looks like:
{
"busy": false,
"busy_with": "programming",
"can_be_distrubed": false,
"id": 1,
"last_change": "2020-07-26 12:51:05.656357",
"name": "Sebast-I-AH-n"
}
That was easy enough, now let’s move over to Home Assistant to read this API and do something cool in response.
Configuring Home Assistant
Home Assistant comes with support to read REST APIs, so also here there is very little configuration required. The
only thing needed is to add a rest-sensor for each user that reads the field “busy”. In the Home Assistant settings
folder open the file configuration.yml
with a text editor and add the following part to the sensor section. Note that
the URL will have to be adjusted to the spot where your instance of BusyBoard is running.
sensor:
- platform: rest
resource: <busyboard_url>/api/users/1
name: user_name
value_template: '{{ value_json.busy }}'
After this you’ll have to restart Home Assistant and the sensor will be available as sensor.user_name
. Now using the
GUI or directly in the configuration file automations.yaml
you can create a new automation that triggers another device, like a light.
You’ll have to add a trigger that goes of once the sensor goes from False to True and the other way around, the action will
be a service, in this case a smart light, will be switched on or off. Details how to do this will depend a lot on the
type of light you are using and how it is configured in HA. Though feel free to use the section from my automations.yaml
file as a reference (shown below).
- id: '1597674094193'
alias: User Busy
trigger:
- entity_id: sensor.user_name
from: 'False'
platform: state
to: 'True'
condition: []
action:
service: light.turn_on
data:
brightness: 255
rgb_color:
- 255
- 0
- 0
entity_id:
- light.blinkstick
- id: '1597674578965'
alias: User No Longer Busy
trigger:
- entity_id: sensor.user_name
from: 'True'
platform: state
to: 'False'
condition: []
action:
service: light.turn_off
entity_id: light.blinkstick
Conclusion
I’ve got it set up that if someone is busy in the office, this BlinkStick Square, built into a 3D printed moon, which is in the living room, will light up red. A clear sign the office is off limits for the time being.
With a few lines of code a custom webservice can easily be integrated into Home Assistant and we can trigger devices in the real world. If you want to look at the full code, this can be found on GitHub
Liked this post ? You can buy me a coffee