Home Assistant & Timebutler

Es ist mal wieder so weit: Wir machen uns das Leben ein bisschen schöner.

Äh. Fauler.

Wir nutzen bei uns im Unternehmen die Zeiterfassung von Timebutler.  Timebutler hat eine kleine API, mit der es sich wunderbar spielen und automatisieren lässt. So aktiviere ich zum Beispiel meine Pause, wenn ich 3:15 nicht am Rechner bin (bzw. mein MacBook den Bildschirmschoner / die Sperre aktiviert) und setze mich wieder auf Anwesend, wenn ich ihn entsperre. Auch beende ich jeden Abend täglich meine Zeiterfassung um 23:59 Uhr, da ich andernfalls meinen Zeiteintrag bearbeiten und ein anderer Kollege ihn bestätigen muss. Das spart doppelt Arbeit: Ich muss nicht dran denken ihn anzupassen und meine Kollegen müssen sich nicht mit dem Bestätigen meiner Änderung herumplagen (höhö).

Welche Zutaten benötigen wir dafür?

Wir brauche Zugang zur Timebutler API. Dieser wird über einen Bearer Token erlaubt / genehmigt / erstellt, sodass sich die Timebutler API dann z.B. über einen gezielten cURL Aufruf bedienen lässt.

Home Assistant. War irgendwie zu erwarten, oder?

Und die einen oder anderen Sensoren, die dann mit der API das machen, was ihr machen möchtet. Bei mir ist es die HA Companion App auf dem MacBook, aber es sind natürlich auch andere Sensoren denkbar (Bewegungsmelder unter dem Schreibtisch, Kontaktsensor im Stuhl verbaut, ein Beschleunigungssensor in eurer Kaffeetasse – okay das wäre irgendwie cool). Irgendwas, womit ihr festmachen könnt „Okay, ich arbeite – oder auch nicht“.

Konfiguration in Home Assistant

Die Konfiguration in Home Assistant ist fix erledigt. Wir benötigen einen zusätzlichen Eintrag in der configuration.yaml (oder in einer eurer Wunsch-Configs, falls ihr sie aufgetrennt habt – dafür war ich bisher zu faul, ich suche stattdessen lieber in der configuration.yaml, lol).

command_line:
  - sensor:
      name: Timebutler Status
      unique_id: timebutler_status
      command: curl -s -X POST -d 'auth={BEARER_TOKEN}' -d 'userid={USER_ID}' -d 'command=status' https://timebutler.de/api/v1/timeclock | awk -F";" '{print$2}'
      scan_interval: 5

shell_command: 
  timebutler_pause: curl -X POST -d 'auth={BEARER_TOKEN}' -d 'userid={USER_ID}' -d 'command=pause' https://timebutler.de/api/v1/timeclock
  timebutler_start: curl -X POST -d 'auth={BEARER_TOKEN}' -d 'userid={USER_ID}' -d 'command=start' https://timebutler.de/api/v1/timeclock
  timebutler_ende: curl -X POST -d 'auth={BEARER_TOKEN}' -d 'userid={USER_ID}' -d 'command=stop' https://timebutler.de/api/v1/timeclock

Das ist auch schon alles. Viel zu erklären gibt es auch gar nicht. Das bisschen configuration macht folgendes:

Es wird ein Sensor mit dem Namen timebutler_status erstellt. Dieser erhält dann den jeweiligen Status der eure Zeiterfassung gerade hat:

RUNNING: Joa, Ihr arbeitet / Zeiterfassung läuft
PAUSED: Ihr seid in Pause / Zeiterfassung pausiert
IDLE: Ihr seid nicht angemeldet / Zeiterfassung läuft nicht

Gleichzeitig legen wir uns drei Shell_Commands an (die dann auch nur ein cURL auf die API sind) um Timebutler zu starten, pausieren oder zu beenden.

Die beiden Variablen {BEARER_TOKEN} und {USER_ID} müsst ihr oben natürlich jeweils ersetzen. Man hätte da auch sicher mit nem Insert oder so arbeiten können, aber für normal muss das ja nicht dauernd geändert werden. Beides findet ihr in Timebutler (ich weiß leider nicht genau wo, da ich es selbst nur angefragt habe) und die User-ID ist eure persönliche ID und sie lässt sich ebenfalls über die API Abfragen (steht aber bestimmt auch irgendwo in Timebutler selbst).

Über scan_interval: 5 können wir die Häufigkeit der Aktualisierung steuern. Hier sind es 5 Sekunden, sprich wenn ihr euch auf Pause schaltet, dauert es maximal 5 Sekunden, bis Home Assistant es mitbekommt. Denkbar wäre wahrscheinlich auch eine 1 oder ein höherer Wert. Aber ich fand 5 Sekunden völlig ausreichend.

Die Entität

So sieht das nun aus. Das obere ist meine Automation, die Timebutler bei mir steuert und darunter haben wir die Entität mit dem Sensor, die uns den aktuellen Status ausgibt.

Die Automatisierung

alias: "Arbeitszimmer: Timebutler"
description: ""
trigger:
  - platform: state
    entity_id:
      - binary_sensor.mbp_inwx_active
    to: true
    for:
      hours: 0
      minutes: 3
      seconds: 15
    attribute: Locked
    id: mbp-inwx-locked
  - platform: state
    entity_id:
      - binary_sensor.mbp_inwx_active
    to: false
    for:
      hours: 0
      minutes: 0
      seconds: 0
    attribute: Locked
    id: mpb-inwx-unlocked
  - platform: time
    at: "23:59:00"
    alias: "23:59"
    id: "23:59"
condition: []
action:
  - alias: Timebutler abmelden
    if:
      - condition: trigger
        id:
          - "23:59"
      - condition: or
        conditions:
          - condition: state
            entity_id: sensor.timebutler_status
            state: RUNNING
          - condition: state
            entity_id: sensor.timebutler_status
            state: PAUSED
    then:
      - service: shell_command.timebutler_ende
        data: {}
      - service: notify.mobile_app_iphone_monty
        data:
          title: Timebutler
          message: Zeiterfassung automatisch beendet.
      - service: script.tts_queue
        metadata: {}
        data:
          important: false
          target:
            - media_player.alexa_kuche
            - media_player.alexa_arbeitszimmer
            - media_player.alexa_schlafzimmer
            - media_player.alexa_wohnzimmer
          announce: false
          message: Zeiterfassung beendet.
  - alias: Timebutler anmelden
    if:
      - condition: trigger
        id:
          - mpb-inwx-unlocked
      - condition: state
        entity_id: sensor.mbp_inwx_primary_display_name
        state: LG HDR WQHD
      - condition: zone
        entity_id: person.montgomery_banse
        zone: zone.home
      - condition: time
        after: "08:30:00"
        before: "17:30:00"
        weekday:
          - mon
          - tue
          - wed
          - thu
          - fri
      - condition: or
        conditions:
          - condition: state
            entity_id: sensor.timebutler_status
            state: IDLE
          - condition: state
            entity_id: sensor.timebutler_status
            state: PAUSED
    then:
      - service: shell_command.timebutler_start
        data: {}
      - service: notify.mobile_app_iphone_monty
        data:
          title: Timebutler
          message: Zeiterfassung gestartet.
      - service: script.tts_queue
        metadata: {}
        data:
          target:
            - media_player.alexa_arbeitszimmer
          message: Zeiterfassung gestartet.
          announce: true
  - alias: Timebutler pausieren
    if:
      - condition: trigger
        id:
          - mbp-inwx-locked
      - condition: zone
        entity_id: person.montgomery_banse
        zone: zone.home
      - condition: state
        entity_id: sensor.mbp_inwx_primary_display_name
        state: LG HDR WQHD
      - condition: time
        after: "08:30:00"
        before: "17:30:00"
        weekday:
          - mon
          - tue
          - wed
          - thu
          - fri
      - condition: state
        entity_id: sensor.timebutler_status
        state: RUNNING
    then:
      - service: shell_command.timebutler_pause
        data: {}
      - service: notify.mobile_app_iphone_monty
        data:
          title: Timebutler
          message: Zeiterfassung pausiert.
      - service: script.tts_queue
        metadata: {}
        data:
          target:
            - media_player.alexa_arbeitszimmer
          message: Zeiterfassung pausiert.
          announce: true
mode: single

Hier gebe ich euch einmal meine komplette Automatisierung durch.

Ich reagiere hier auf drei Trigger: Einmal die Zeit 23:59 Uhr, und dann ob mein Macbook gesperrt oder entsperrt wird. Beim letzteren ändert sich das Attribut Locked von binary_sensor.mbp_inwx_active auf true oder false.

Die einzelnen Aktionen sind dann jeweils wieder WENNs, die auf die Trigger-IDs hören und gleichzeitig noch eine entsprechende Bedingung haben um die Sinnhaftigkeit des Pausieren oder Beenden zu testen.

Also es findet z.B. um 23:59 auch nur der Aufruf von service: shell_command.timebutler_ende statt, wenn der aktuelle Status auch wirklich RUNNING oder PAUSED ist. Wäre ja auch Quatsch sich abzumelden, wenn man nicht angemeldet ist. (Die API würde dann ohnehin einen Fehler ausgeben, der aber nicht stören würde, da wir die Rückgaben nicht auswerten, hierfür habe ich keinen Sinn gesehen, da es außer einem Status-Code keine wirklichen Infos gibt die man verwerten könnte)

Das Einstempeln und Pausieren habe ich übrigens nur aktiv, wenn ich mich in der HomeZone befinde und mein MacBook meinen LG Monitor als Primären Monitor nutzt (er ist immer als Primärer eingestellt, daher ist es egal ob ich das MacBook zugeklappt oder aufgeklappt lasse). Dadurch stelle ich sicher, dass ich auch am Schreibtisch sitze. Gleichzeitig wird noch die Zeit zwischen 8:30 Uhr und 17:30 Uhr überprüft. Das ist die übliche Arbeitszeit in der ich aktiv bin. Davor oder Danach muss ich mich selbst Einstempeln (genauso z.B. wenn ich auf dem Balkon sitze oder im Büro bin).

Zusätzlich als Feedback lasse ich mir eine Notify aufs Handy und MacBook schicken und eine Info via Alexa ausgeben. Hierfür nutze ich mein TTS Skript (guckst du hier, wenn du wissen möchtest was das feines macht: TTS (-Queue) mit Home Assistant und Alexa als Skript).

Das ist es auch schon gewesen. Somit habe ich mit 3 Minuten ein kleines Puffer, in dem ich mal kurz zur Kaffeemaschine kann ohne das ich pausiert werde, aber falls ich mich auf der Keramik zulange durch Instagram scrollen würde, gehe ich in Pause und schröpfe meinen Arbeitgeber nicht ;). 

(Ja, mir ist bekannt das Toilettengänge arbeitsrechtlich zur Arbeitszeit zählen, aber ich empfinde es unfair dies zuhause unnötig auszunutzen. Und manchmal erwische ich mich auch, wie ich nicht nur fix Kaffee nachschenke, sondern auch noch 5 Minuten lang den Spüler ausräume – und das ist nun definitiv keine Arbeitszeit).

Viel Spaß damit, vielleicht kann es ja jemand gebrauchen. 

Übrigens: Es gibt für Timebutler noch keine Integration. Eine Integration zu schreiben übersteigt aber definitiv mein Wissen. Falls du das hier also liest und eine Integration schreiben kannst oder möchtest und ich dich jetzt auf eine Idee gebracht hab: Lass mich doch teilhaben! Ich würde es gerne kennenlernen und verstehen. 

Bildquellen

Kategorien: Smarthome

0 Kommentare

Schreibe einen Kommentar

Avatar-Platzhalter

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.

DSGVO Cookie Consent mit Real Cookie Banner