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.

The smart light inside this moon will turn deep red if someone indicates they are busy

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