Inhalt
1. Vorwort
2. Installation des Nukis mit CH-Zylinder
3. Voraussetzungen zur Steuerung des Nuki via API
4. API-Befehle
5. Automatisches Sperren von manuell aufgesperrten Türen
6. Alarm bei offengelassener Türe
7. Abrufen des Protokolls (Activity-Log)
1, Vorwort
Im Rahmen unseres Projektes Mosliboss SmartHome und in
Anbetracht der Tatsache, dass die Kinder gelegentlich das Haus verlassen, ohne
die Haustüre abzuschliessen, wurden Überlegungen in Richtung SmartLock gemacht
und nach etlichen Recherchestunden fiel unsere Wahl auf ein
Nuki Smart Lock Pro (5. Gen).
Gestaunt haben wir ob der Geschwindigkeit der Lieferung: Am Sonntag, 25. Mai
2025 wurde die Bestellung online aufgegeben und am Dienstag, 27. Mai 2025
lag das Paket bereits im Briefkasten!! Seltsamerweise wurde im Nuki-Club-Account
die Bestellung bis am 27. Mai 2025 stets nur als 'In Bearbeitung' angezeigt und
entsprechend gross war die Überraschung, als das Paket bereits weniger als
48 Stunden nach der Bestellung in Graz/Österreich bei uns in der
Schweiz angekommen war...
Zwar ist dieses Schloss für EU-Zylinder offiziell nur bedingt geeignet für
Schweizer
Rund-Schloss-Zylinder, doch im folgenden Abschnitt wird erklärt, wie dies bei
uns recht einfach erfolgreich realisiert worden ist.
2. Installation des Nukis mit CH-Zylinder
Wir haben ein Keso2000-Schloss mit einem Zylinder, der einen Durchmesser von
22mm aufweist und auf der Türinnenseite vom Schild ca. 14mm übersteht.
Die mit dem Nuki mitgelieferte
Klebe-Platte weist eine Dicke von ca. 4mm auf. Somit benötigen wir ein
Zwischenstück von ca. 10mm Dicke, damit das Zylinderende ungefähr bündig
mit der Oberfläche der Klebeplatte ist. Da wir heute im Jumbo keine passende
Scheibe in Metall oder Kunststoff gefunden haben, kauften wir ein kleines Stück
beschichtete Spanplatte mit 10mm Dicke. Davon wurde ein 5x5 cm grosses Stück
ausgesägt und in der Mitte mittels einem 25mm-Forstnerbohrer ein
Loch gebohrt. Das Türschild und das Holzstück wurden jeweils mittels
Brennsprit gereinigt und das Holzstück mittels dem sehr gut klebenden und
dünnen "tesa Powerbond" (beidseitig klebend, transparent, 5mx19mm) verbunden,
so, dass der Zylinder schön mittig im Loch platziert ist
(Foto 1).
Anschliessend wurde die gelieferte selbstklebende Nuki-Platte mit der aussen
befindlichen Kerbe
nach oben auf das (mit Brennsprit gereinigte) Holzstück geklebt (Foto 2)
und schliesslich das Nuki Pro
gemäss Anleitung darauf aufgesteckt, leicht im Uhrzeigersinn gedreht und
fixiert (Fotos 3 und 4, jeweils unten mit dem magnetischen Ladekabel
angeschlossen).
Mit diesem Vorgehen konnte das Nuki Pro 5 problemlos in Betrieb genommen werden!
3. Voraussetzungen zur Steuerung des Nuki via API
Um das Nuki Pro mittels API von einem Linux-Rechner anzusteuern, muss zuerst
ein Konto auf dem Nukiweb https://web.nuki.io eingerichtet werden.
Dort kann unter API ein API-Token generiert werden. Dieser sehr lange String
vom Typ (hier fiktiv) 87f095d9c2b390dbf5dbfd1e457848bc4bc4665315a3
sollte irgendwo sicher abgespeichert werden, solange er noch angezeigt wird.
Das Nuki-Gerät muss unbedingt via Nuki-App (Einstellungen -
Funktionen&Konfiguration - NukiWeb) in der Nuki Web API angemeldet werden.
Anschliessend muss noch der hexadezimale SmartLock-ID bestimmt werden.
Dazu geht man in der Nuki-App zuerst in folgendes Menu:
Einstellungen - Funktionen&Konfiguration - Allgemein - Dort findet man die Geräte ID: AB123CDFür die API wird jedoch die dezimale ID benötigt, wobei (nach Recherchen im Web) folgendes gilt:
4. API-Befehle
In diesem Abschnitt sollen einige Beispiele von API-Steuer-Befehlen
erklärt werden.
API_token="87f095d9c2b390dbf5dbfd1e457848bc4bc4665315a3" Nuki_ID="1521558477" # Status abfragen: curl --no-sessionid -X GET \ --header "Accept: application/json" \ --header "Authorization: Bearer $API_token" \ "https://api.nuki.io/smartlock" \ --output out.out 2>/dev/null
Falls der Output im File out.out eine Fehlermeldung der Form
{"detailMessage":"Your access token is not authorized","stackTrace":[],"suppressedExceptions":[]}
enthält, ist irgendetwas schief gelaufen. Insbesondere ist es wichtig, dass
bei den curl-Parametern Gänsefüsschen (") und nicht Apostrophe (') verwendet
werden, weil letztere die Variablen wie $API_token und $Nuki_ID nicht
in die wahren Werte übersetzen!
Um nun z.B. den Status von zwei Nukis in entsprechenden Files zu listen und einige kritische Parameter in der Konsole darzustellen, kann folgendes Script namens get_nuki_status.sh verwendet werden:
#!/bin/bash # get_nuki_status.sh 28May2025/uk OUTFILE="out.out" API_token="87f095d9c2b390dbf5dbfd1e457848bc4bc4665315a3" Nuki1="1521558477" Nuki2="1521558488" # Status abfragen curl --no-sessionid -X GET \ -H "Accept: application/json" \ -H "Authorization: Bearer $API_token" \ "https://api.nuki.io/smartlock" \ --output $OUTFILE 2>/dev/null if test $? -ne 0 ; then echo "Fehler bei der curl-Abfrage - exit!" exit fi # Die Daten der beiden Nukis extrahieren und jeweils in eine Datei speichern jq '.[0]' "$OUTFILE" > Nuki1.status jq '.[1]' "$OUTFILE" > Nuki2.status #echo "Statusdateien erstellt: Nuki1.status und Nuki2.status" # Kritische Parameter: tuerstatus=$(jq '.[0].state.doorState' "$OUTFILE") schlossstatus=$(jq '.[0].state.state' "$OUTFILE") batteriestatus=$(jq '.[0].state.batteryCharge' "$OUTFILE") echo "Nuki1:" echo "Tuere: $tuerstatus (2: geschlossen, 3: offen)" echo "Schloss: $schlossstatus (1: zugesperrt, 3: entsperrt)" echo "Akku: $batteriestatus%" tuerstatus=$(jq '.[1].state.doorState' "$OUTFILE") schlossstatus=$(jq '.[1].state.state' "$OUTFILE") batteriestatus=$(jq '.[1].state.batteryCharge' "$OUTFILE") echo " " echo "Nuki2:" echo "Tuere: $tuerstatus (2: geschlossen, 3: offen)" echo "Schloss: $schlossstatus (1: zugesperrt, 3: entsperrt)" echo "Akku: $batteriestatus%" #
Dies ergibt dann z.B. folgenden Output:
Nuki1: Tuere: 2 (2: geschlossen, 3: offen) Schloss: 1 (1: zugesperrt, 3: entsperrt) Akku: 100% Nuki2: Tuere: 2 (2: geschlossen, 3: offen) Schloss: 3 (1: zugesperrt, 3: entsperrt) Akku: 80%und die gesamten Statusinformationen der Nukis sind in recht gut lesbarer Form in den Files Nuki1.status und Nuki2.status enthalten.
5. Automatisches Sperren von manuell aufgesperrten Türen
Es kann vorkommen, dass jemand ein Nuki von innen absichtlich aufsperrt, die
Türe dann jedoch nicht öffnet. In diesem Fall greift die Regel "Autolock"
nicht, welche nachdem Schliessen der Türe diese automatisch verriegelt
(zusperrt). Für diesen Fall wurde bei uns ein Script
check_locked_doors.sh implementiert, welches via Cron-Job
*/3 * * * * nice -n 15 $HOME/smarthome/nuki/check_locked_doors.sh >> $HOME/smarthome/nuki/check_locked_doors.log 2>>$HOME/smarthome/nuki/check_locked_doors.errlog
alle drei
Minuten kontrolliert, ob eine Türe zwar geschlossen,, aber nicht zugesperrt
ist. Falls dies der Fall ist, wird die Türe automatisch zugesperrt.
Bemerkung: In den folgenden Scripts ist jeweils eine Zeile
source $HOME/smarthome/HA/MASTER.file zu finden. Die steht deshalb
da, weil wir ein Hochverfügbarkeitssystem in Betrieb
haben und diverse Scripts nur dann ausgeführt werden sollen, wenn der
Rechner den Status MASTER hat. Zudem sind etliche Files, die sich öfters
ändern, in einer RAM-Disk abgespeichert - siehe dazu
"RAM-Disk auf Raspi einrichten zur Schonung der SD-Karte".
#!/bin/bash # check_locked_doors.sh 29May2025/uk # source $HOME/smarthome/HA/MASTER.file if test "$MASTER" = "no" ; then # echo "Not MASTER - exit! `date +%d.%m.%Y_%H:%M`" exit fi mkdir -p /mnt/ramdisk/Nuki cd $HOME/smarthome/nuki # Nicht, dass alle 3 Minuten 0 Sekunden mehrere Prozesse laufen: sleep 13 # OUTFILE="/mnt/ramdisk/Nuki/check.out" # API_token="87f095d9c2b390dbf5dbfd1e457848bc4bc4665315a3" Nuki_EG_ID="1521558477" Nuki_UG_ID="1521558488" # get_status() { curl --no-sessionid -X GET \ -H "Accept: application/json" \ -H "Authorization: Bearer $API_token" \ "https://api.nuki.io/smartlock" \ --output $1 2>/dev/null if test $? -ne 0 ; then echo "check_locked_doors.sh - Fehler bei der curl-Status-Abfrage - exit! `date +%d.%m.%Y_%H:%M`" exit 1 fi EGtuerstatus=$(jq '.[0].state.doorState' "$OUTFILE") EGschlossstatus=$(jq '.[0].state.state' "$OUTFILE") UGtuerstatus=$(jq '.[1].state.doorState' "$OUTFILE") UGschlossstatus=$(jq '.[1].state.state' "$OUTFILE") } # lock_door() { action="lock" curl --no-sessionid -X POST \ -H "Authorization: Bearer $API_token" \ -H "Accept: application/json" \ "https://api.nuki.io/smartlock/$2/action/$action" \ --output $1 2>/dev/null if test $? -ne 0 ; then echo "check_locked_doors.sh - Fehler beim curl-Lock-Befehl - exit! `date +%d.%m.%Y_%H:%M`" exit 1 fi } # get_status $OUTFILE if test $EGtuerstatus -eq 2 && test $EGschlossstatus -eq 1 ; then # echo "Türe EG geschlossen und zugesperrt" : fi if test $UGtuerstatus -eq 2 && test $UGschlossstatus -eq 1 ; then # echo "Türe UG geschlossen und zugesperrt" : fi # if test $EGtuerstatus -eq 2 && test $EGschlossstatus -eq 3 ; then echo "check_locked_doors.sh - EG-Türe geschlossen aber nicht zugesperrt - 10 Sek. warten `date +%d.%m.%Y_%H:%M`" sleep 10 get_status $OUTFILE if test $EGtuerstatus -eq 2 && test $EGschlossstatus -eq 3 ; then lock_door $OUTFILE $Nuki_EG_ID echo "check_locked_doors.sh - EG-Türe geschlossen aber nicht zugesperrt - wird zugesperrt `date +%d.%m.%Y_%H:%M`" fi fi if test $UGtuerstatus -eq 2 && test $UGschlossstatus -eq 3 ; then echo "check_locked_doors.sh - UG-Türe geschlossen aber nicht zugesperrt - 10 Sekunden warten `date +%d.%m.%Y_%H:%M`" sleep 10 get_status $OUTFILE if test $UGtuerstatus -eq 2 && test $UGschlossstatus -eq 3 ; then lock_door $OUTFILE $Nuki_UG_ID echo "check_locked_doors.sh - UG-Türe geschlossen aber nicht zugesperrt - wird zugesperrt `date +%d.%m.%Y_%H:%M`" fi fi #
6. Alarm bei offengelassener Türe
Bei all diesen Automatismen kann in findiger Junior, der nur "kurz" draussen
ein bisschen Turnen woltle, auf die Idee kommen, die Haustüre einfach offen
stehen zu lassen, was verantwortliche Eltern natürlich nicht gutheissen können.
Aus diesem Grund wurde für jede Türe mit einem Nuki ein Cron-Job eingerichtet,
der jede Minute testet, ob eine Türe geöffnet ist:
* * * * * nice -n 15 $HOME/smarthome/nuki/check_closed_doors.sh EG >> $HOME/smarthome/nuki/check_closed_doors.log 2>>$HOME/smarthome/nuki/closed_doors.errlog
* * * * * nice -n 15 $HOME/smarthome/nuki/check_closed_doors.sh UG >> $HOME/smarthome/nuki/check_closed_doors.log 2>>$HOME/smarthome/nuki/closed_doors.errlog
Falls eine Türe längere Zeit offen bleibt, wurde mittels einem von früheren
Experimenten vorhandenen "Shelly Plug S" zum Schalten einer
günstigen kleinen Sirene und einem
12 Volt Netzteil eine Alarmeinheit beschafft.
Das Script namens check_closed_doors.sh sieht wie folgt aus:
#!/bin/bash # check_closed_doors.sh 02Jun2025/uk - flexible Alarme source $HOME/smarthome/HA/MASTER.file if test "$MASTER" = "no" ; then exit fi if test $# -ne 1 ; then echo "Usage: $0 {EG|UG} `date +%d.%m.%Y_%H:%M`" exit 1 fi door="$1" # Damit nicht zu viele Jobs um *:00 Minuten laufen: if test "$door" = "EG" ; then sleep 2 fi if test "$door" = "UG" ; then sleep 7 fi mkdir -p /mnt/ramdisk/Nuki cd $HOME/smarthome/nuki OUTFILE="/mnt/ramdisk/Nuki/check_closed_doors_$door.out" LOCKFILE="/mnt/ramdisk/Nuki/check_closed_doors_$door.lock" STATEFILE="/mnt/ramdisk/Nuki/check_closed_doors_${door}.state" ALARM_INDEX_FILE="/mnt/ramdisk/Nuki/alarm_index_${door}.txt" API_token="87f095d9c2b390dbf5dbfd1e457848bc4bc4665315a3" Nuki_EG_ID="1521558477" Nuki_UG_ID="1521558488" [ "$door" = "EG" ] && Nuki_ID="$Nuki_EG_ID" [ "$door" = "UG" ] && Nuki_ID="$Nuki_UG_ID" # Alarm- und Sirenenkonfiguration Alarms_after=(60 120 180 240 300 360 420 480 540 600 660 720) Siren_duration=(0 1.0 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0 3.0) # Längen vergleichen if [ "${#Alarms_after[@]}" -ne "${#Siren_duration[@]}" ]; then echo "<font color=orange>Fehler: Die Arrays Alarms_after und Siren_duration sind nicht gleich lang!" echo "Länge Alarms_after: ${#Alarms_after[@]}" echo "Länge Siren_duration: ${#Siren_duration[@]}" exit 1 fi get_status() { curl --no-sessionid -X GET \ -H "Accept: application/json" \ -H "Authorization: Bearer $API_token" \ "https://api.nuki.io/smartlock" \ --output "$OUTFILE" 2>/dev/null if test $? -ne 0 || ! test -s "$OUTFILE" ; then echo "<font color=orange>Fehler bei curl - keine oder leere Antwort! - exit! `date`" rm -f "$LOCKFILE" exit 1 fi # Prüfe, ob die Datei wirklich JSON ist if ! jq . "$OUTFILE" >/dev/null 2>&1; then echo "<font color=orange>Fehler: Ungültige JSON-Antwort in $OUTFILE (`date`)" rm -f "$LOCKFILE" exit 1 fi if [ "$door" = "EG" ]; then TuerStatus=$(jq '.[0].state.doorState' "$OUTFILE") SchlossStatus=$(jq '.[0].state.state' "$OUTFILE") else TuerStatus=$(jq '.[1].state.doorState' "$OUTFILE") SchlossStatus=$(jq '.[0].state.state' "$OUTFILE") fi # Prüfen, ob TuerStatus eine Zahl ist if ! [[ "$TuerStatus" =~ ^[0-9]+$ ]]; then echo "<font color=orange>Fehler: Kein gültiger Türstatus (doorState=$TuerStatus) - Abbruch! `date`" rm -f "$LOCKFILE" exit 1 fi # Prüfen, ob SchlossStatus eine Zahl ist if ! [[ "$SchlossStatus" =~ ^[0-9]+$ ]]; then echo "<font color=orange>Fehler: Kein gültiger Schlossstatus (LockState=$SchlossStatus) - Abbruch! `date`" rm -f "$LOCKFILE" exit 1 fi } if test -e "$LOCKFILE" ; then exit 0 else touch "$LOCKFILE" fi get_status # Prüfen, ob TuerStatus eine Zahl ist if ! [[ "$TuerStatus" =~ ^[0-9]+$ ]]; then echo "<font color=orange>Fehler: Kein gültiger Türstatus - wahrscheinlich Fehler bei der API/JSON. Türstatus: '$TuerStatus' (`date`)" rm -f "$LOCKFILE" exit 1 fi # Prüfen, ob SchlossStatus eine Zahl ist if ! [[ "$SchlossStatus" =~ ^[0-9]+$ ]]; then echo "<font color=orange>Fehler: Kein gültiger Schlossstatus - wahrscheinlich Fehler bei der API/JSON. Schlossstatus: '$SchlossStatus' (`date`)" rm -f "$LOCKFILE" exit 1 fi if [ "$TuerStatus" -ne 3 ]; then # Tür nicht offen → alles ok, State-Dateien löschen rm -f "$STATEFILE" "$ALARM_INDEX_FILE" "$LOCKFILE" exit 0 fi # Türe OFFEN und gleichzeitig GESCHLOSSEN - sollte nie der Fall sein --> Alarm!! if test "$TuerStatus" -eq 3 && test "$SchlossStatus" -eq 1 ; then siren_time=5 message="Türe $door OFFEN und gleichzeitig GESCHLOSSEN! (SD=$siren_time) `date +%d.%m.%Y_%H:%M`" echo "<font color=yellow>$message" /usr/local/bin/send_telegram "$message" ./sirene_schalten.sh $siren_time rm -f "$STATEFILE" "$ALARM_INDEX_FILE" "$LOCKFILE" exit 0 fi now=$(date +%s) if test -e "$STATEFILE"; then start=$(cat "$STATEFILE") else start=$now echo "$start" > "$STATEFILE" echo "Tür $door seit jetzt offen: `date +%d.%m.%Y_%H:%M`" fi duration=$((now - start)) # Aktueller Alarm-Index if test -e "$ALARM_INDEX_FILE"; then ALARM_INDEX=$(cat "$ALARM_INDEX_FILE") else ALARM_INDEX=0 fi # Prüfen, ob nächster Alarm fällig ist if [ $ALARM_INDEX -lt ${#Alarms_after[@]} ]; then next_alarm=${Alarms_after[$ALARM_INDEX]} if [ $duration -ge $next_alarm ]; then # Sende Alarm minutes=$((duration / 60)) siren_time=${Siren_duration[$ALARM_INDEX]} message="Türe $door seit $minutes Minuten offen! (SD=$siren_time) `date +%d.%m.%Y_%H:%M`" echo "<font color=yellow>$message" /usr/local/bin/send_telegram "$message" ./sirene_schalten.sh $siren_time # Sirene auslösen (nur Beispiel, anpassen) # /usr/local/bin/trigger_siren $siren_time # Index erhöhen ALARM_INDEX=$((ALARM_INDEX + 1)) echo "$ALARM_INDEX" > "$ALARM_INDEX_FILE" fi fi rm -f "$LOCKFILE" #In diesem Script wird auch das Script sirene_schalten.sh verwendet, welches wie folgt aussieht:
#!/bin/bash # sirene_schalten.sh 02Jun2025/uk # # Schaltet einen Shelly-PlugS ein oder aus # Einschalten kann auch nur für eine bestimmte Zeitdauer gelten # Statusabfrage: EIN oder AUS # sirene_starten () { taskON="http://$shelly/relay/0?turn=on" taskOFF="http://$shelly/relay/0?turn=off" # curl --fail --silent --show-error --no-sessionid --request $request_method \ $taskON --output $OUTFILE sleep 0.01 curl --fail --silent --show-error --no-sessionid --request $request_method \ $taskOFF --output $OUTFILE sleep 1 # curl --fail --silent --show-error --no-sessionid --request $request_method \ $taskON --output $OUTFILE sleep 0.01 curl --fail --silent --show-error --no-sessionid --request $request_method \ $taskOFF --output $OUTFILE sleep 1 # curl --fail --silent --show-error --no-sessionid --request $request_method \ $taskON --output $OUTFILE sleep $duration curl --fail --silent --show-error --no-sessionid --request $request_method \ $taskOFF --output $OUTFILE # } # n=$# if test $n -ne 1 ; then echo "Usage: ./sirene_schalten.sh duration" echo "Example: ./sirene_schalten.sh 0.3" fi duration=$1 # shelly="shellyplugs" request_method="get" # source $HOME/smarthome/HA/MASTER.file if test "$MASTER" = "no" ; then # echo "Nicht Master. shelly_schalten.sh - exit! `date +%d.%m.%Y_%H:%M`" exit fi # mkdir -p /mnt/ramdisk/Nuki cd $HOME/smarthome/nuki # OUTFILE="/mnt/ramdisk/Nuki/${0##*/}.result" # # Set PlugS to default power-on state to OFF: taskDefaultOFF="http://$shelly/settings/relay/0?default_state=off" curl --fail --silent --show-error --no-sessionid --request $request_method \ $taskDefaultOFF --output $OUTFILE # sirene_starten #wobei der shellyplugs im File /etc/hosts mit dessen IP-Nummer definiert ist. Das Script /usr/local/bin/send_telegram ist im Beitrag Automatisierte Message an Handy erklärt.
7. Abrufen des Protokolls (Activity-Log)
Um die letzten Aktivitäten der Nukis abzurufen und auf einer Web-Seite
darzustellen, wurde ein entsprechendes Script get_activity_log.sh
geschrieben:
#!/bin/bash # get_activity_log.sh 30May2025/uk # source $HOME/smarthome/HA/MASTER.file if test "$MASTER" = "no" ; then # echo "Not MASTER - exit! `date +%d.%m.%Y_%H:%M`" exit fi mkdir -p /mnt/ramdisk/Nuki cd $HOME/smarthome/nuki # OUTFILE="/mnt/ramdisk/Nuki/activity_log.out" # API_token="87f095d9c2b390dbf5dbfd1e457848bc4bc4665315a3" Nuki_EG_ID="1521558477" Nuki_UG_ID="1521558488" # echo "Nuki EG" curl -X GET \ -H "Accept: application/json" \ -H "Authorization: Bearer $API_token" \ "https://api.nuki.io/smartlock/$Nuki_EG_ID/log?limit=50" \ --output $OUTFILE 2>/dev/null # if test $? -ne 0 ; then echo "get_activity_log.sh - Fehler bei der curl-Status-Abfrage - exit! `date +%d.%m.%Y_%H:%M`" exit 1 fi # jq -r '.[] | "\(.date) - \(.action|tostring|gsub("1";"Lock")|gsub("2";"Unlock")|gsub("3";"Unlatch")) - \(.name)"' /mnt/ramdisk/Nuki/activity_log.out INPUT="/mnt/ramdisk/Nuki/activity_log.out" jq -c '.[]' "$INPUT" | while read -r entry; do date_utc=$(echo "$entry" | jq -r '.date') action=$(echo "$entry" | jq -r '.action') name=$(echo "$entry" | jq -r '.name') if test "$name" = "User1" ; then name="<font color=blue>User1" fi if test "$name" = "User2" ; then name="<font color=blue>User2" fi # if test "$name" = "- Nuki Keypad" ; then # name="- Ungültiger Fingerprint" # fi source=$(echo "$entry" | jq -r '.source') trigger=$(echo "$entry" | jq -r '.trigger') if test $trigger -eq 6 ; then name="AutoLock" fi if test $trigger -eq 1 || test $trigger -eq 2 ; then name="manual_Nuki" fi # Aktion umsetzen case $action in 1) action_txt="Unlock" ;; 2) action_txt="Lock" ;; 3) action_txt="Unlatch" ;; 4) action_txt="Lock'n'go" ;; 240) action_txt="Door opened" name="" ;; 241) action_txt="Door closed" name="" ;; 242) action_txt="<font color=yellow>DoorSensor jammed!!" name="" ;; *) action_txt="Other (action=$action)" ;; esac # Source umsetzen source_nr=$source case $source in # 0) source_txt="default" ;; 0) source_txt="" source_nr="" ;; 1) source_txt="KeypadCode" ;; 2) source_txt="Fingerprint" ;; *) source_txt="Other (source=$source)" ;; esac if test "$source_txt" = "KeypadCode" && test "$name" = "Nuki Keypad" ; then name="<font color=yellow>ungültig" # Fingerprint fi if test "$name" = "Zutrittscode" ; then name="OK" fi if test "$name" = "Nuki Keypad" ; then name="manual_Keypad" fi if test "$name" = "Nuki Web" ; then name="<font color=blue>via_API" fi # UTC → Lokalzeit date_local=$(date -d "$date_utc" +"%Y-%m-%d %H:%M:%S") # Zeile MIT Codes: # echo "$date_local $action $action_txt $source_nr $source_txt $name" | tr -s ' ' ' ' # Zeile OHNE Codes: echo "$date_local $action_txt $source_txt $name" | tr -s ' ' ' ' done # echo " " echo "Nuki UG" curl -X GET \ -H "Accept: application/json" \ -H "Authorization: Bearer $API_token" \ "https://api.nuki.io/smartlock/$Nuki_UG_ID/log?limit=50" \ --output $OUTFILE 2>/dev/null # if test $? -ne 0 ; then echo "get_activity_log.sh - Fehler bei der curl-Status-Abfrage - exit! `date +%d.%m.%Y_%H:%M`" exit 1 fi # jq -r '.[] | "\(.date) - \(.action|tostring|gsub("1";"Lock")|gsub("2";"Unlock")|gsub("3";"Unlatch")) - \(.name)"' /mnt/ramdisk/Nuki/activity_log.out INPUT="/mnt/ramdisk/Nuki/activity_log.out" jq -c '.[]' "$INPUT" | while read -r entry; do date_utc=$(echo "$entry" | jq -r '.date') action=$(echo "$entry" | jq -r '.action') name=$(echo "$entry" | jq -r '.name') if test "$name" = "Urs" ; then name="<font color=blue>User1" fi if test "$name" = "Caro" ; then name="<font color=blue>User2" fi source=$(echo "$entry" | jq -r '.source') trigger=$(echo "$entry" | jq -r '.trigger') if test $trigger -eq 6 ; then name="AutoLock" fi if test $trigger -eq 1 || test $trigger -eq 2 ; then name="manual_Nuki" fi # Aktion umsetzen case $action in 1) action_txt="Unlock" ;; 2) action_txt="Lock" ;; 3) action_txt="Unlatch" ;; 4) action_txt="Lock'n'go" ;; 240) action_txt="Door opened" name="" ;; 241) action_txt="Door closed" name="" ;; 242) action_txt="DoorSensor jammed!!" name="" ;; *) action_txt="Other (action=$action)" ;; esac # Source umsetzen source_nr=$source case $source in # 0) source_txt="default" ;; 0) source_txt="" source_nr="" ;; 1) source_txt="KeypadCode" ;; 1) source_txt="KeypadCode" ;; 2) source_txt="Fingerprint" ;; *) source_txt="Other (source=$source)" ;; esac if test "$source_txt" = "KeypadCode" && test "$name" = "Nuki Keypad" ; then name="<font color=yellow>ungültig" # Zahlencode fi if test "$source_txt" = "Fingerprint" && test "$name" = "Nuki Keypad" ; then name="<font color=yellow>ungültig" # Fingerprint fi if test "$name" = "Zutrittscode" ; then name="OK" fi if test "$name" = "Nuki Keypad" ; then name="manual_Keypad" fi if test "$name" = "Nuki Web" ; then name="<font color=blue>via_API" fi # UTC → Lokalzeit date_local=$(date -d "$date_utc" +"%Y-%m-%d %H:%M:%S") # Zeile MIT Codes: # echo "$date_local $action $action_txt $source_nr $source_txt $name" | tr -s ' ' ' ' # Zeile OHNE Codes: echo "$date_local $action_txt $source_txt $name" | tr -s ' ' ' ' done #