Laten we de kleine app uit het vorige artikel naar een hoger niveau tillen en integreren in het domoticaplatform Home Assistant (HA). Wanneer je je status op BusyBoard wijzigt, kan Home Assistant die zo oppikken en een automatisering activeren. We voegen een API aan BusyBoard toe die Home Assistant gemakkelijk kan uitlezen, zodat we een slimme lamp kunnen inschakelen (en rood laten kleuren).

Hoewel BusyBoard een handige oplossing was om je huisgenoten te laten weten wanneer je aan het werk bent en niet gestoord wilt worden, moet iedereen BusyBoard daarvoor wel regelmatig controleren. Niet bepaald de gebruiksvriendelijkste ervaring! Het zou veel handiger zijn als we dit op de een of andere manier in de echte wereld konden tonen … vergelijkbaar met een bordje “On Air” in radio- en tv-studio’s. Omdat ik al enkele slimme lampen aan HA heb gekoppeld, kan dat vrij eenvoudig. We hebben wel een API in BusyBoard nodig die Home Assistant kan uitlezen, dus laten we die implementeren.

Een API aan BusyBoard toevoegen

Als je een grotere toepassing ontwikkelt en een API nodig hebt, bekijk dan pakketten zoals Flask-Restful of zelfs een framework dat specifiek voor API’s is ontworpen, zoals FastAPI! Hier hebben we echter geen toeters en bellen nodig: we willen gewoon voor elke gebruiker een endpoint waarop we kunnen zien of die bezig is. Eerst voegen we aan het databankmodel een functie toe die een gebruiker naar een dictionary exporteert. Daarvoor moet een beetje code aan het model (in ./busyboard/models.py) worden toegevoegd, zoals hieronder.

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)
        }

Eenvoudiger kan haast niet: één functie die de gegevens uit het model als een dictionary exporteert. Hier worden alle velden expliciet naar gehele getallen, strings en booleans omgezet. Dat is niet strikt noodzakelijk voor elk veld, maar helpt fouten te voorkomen wanneer we ze later naar JSON omzetten.

Vervolgens voegen we de routes toe aan ./busyboard/__init__.py. Ook dat is heel eenvoudig: enkele regels code zoals hieronder volstaan.

    @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())

Als we nu bijvoorbeeld naar \<busyboard_url\>/api/users/1 gaan, krijgen we een JSON-antwoord dat er als volgt uitziet:

{
  "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"
}

Dat was eenvoudig genoeg. Nu gaan we naar Home Assistant om deze API uit te lezen en daar iets leuks mee te doen.

Home Assistant configureren

Home Assistant ondersteunt het uitlezen van REST-API’s, dus ook hier is er weinig configuratie nodig. Je hoeft alleen voor elke gebruiker een REST-sensor toe te voegen die het veld “busy” uitleest. Open in de instellingenmap van Home Assistant het bestand configuration.yml met een teksteditor en voeg het volgende deel aan de sensorsectie toe. Merk op dat je de URL moet aanpassen aan de locatie waar jouw BusyBoard-versie draait.


sensor:
  - platform: rest
    resource: <busyboard_url>/api/users/1
    name: user_name
    value_template: '{{ value_json.busy }}'

Daarna moet je Home Assistant herstarten en is de sensor beschikbaar als sensor.user_name. Via de GUI of rechtstreeks in het configuratiebestand automations.yaml kun je nu een nieuwe automatisering maken die een ander apparaat activeert, bijvoorbeeld een lamp. Voeg een trigger toe die afgaat wanneer de sensor van False naar True verandert en omgekeerd. De actie is een service die in dit geval een slimme lamp in- of uitschakelt. De details hangen sterk af van het type lamp dat je gebruikt en hoe die in HA is geconfigureerd. Gebruik gerust het onderstaande deel uit mijn bestand automations.yaml als referentie.

- 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

Conclusie

Ik heb het zo ingesteld dat deze BlinkStick Square, ingebouwd in een 3D-geprinte maan in de woonkamer, rood oplicht wanneer iemand in het kantoor bezig is. Een duidelijk teken dat het kantoor voorlopig verboden terrein is.

De slimme lamp in deze maan kleurt dieprood wanneer iemand aangeeft bezig te zijn

Met enkele regels code kun je een eigen webservice eenvoudig in Home Assistant integreren en apparaten in de echte wereld activeren. De volledige code vind je op GitHub.