Vorwort
Im Rahmen unseres Projektes Mosliboss-SmartHome sind
wir natürlich auch mit der Idee konfrontiert worden, gewisse Dinge
unterschiedlich zu steuern, wenn wir zu Hause oder abwesend sind.
Implementierung
Wir haben uns entschieden, die Anwesenheit von unseren Handys im lokalen WLAN
zu benutzen, um zu entscheiden, wer zu Hause iat. Dazu war es notwendig, bei
unserem Router permanente (lokale) IP-Adressen für die (Android-)Handys
zu definieren.
Das Prinzip wurde im Verlauf des letzten Jahres wegen gelegentlich auftretenden
falschen Negativ-Einträgen (Handy wird als abwesend beurteilt, obwohl es
anwesend war) geändert und seit mehreren Wochen haben wir nun eine Methode
implementiert, die sich fehlerfrei bewährt hat:
- Jede Minute werden mittels cron-job unsere Handys mehrmals angepingt
- Alle 5 Minuten wird gecheckt, ob eines oder beide der Handys in den letzten
5 Minuten erfolgreich angepingt werden konnte.
Cron-Jobs:
* * * * * $HOME/smarthome/handyhome/ping_handys.sh >> /mnt/ramdisk/handyhome/ping_handys.log 2>>$HOME/smarthome/handyhome/ping_handys.errlog
*/5 * * * * $HOME/smarthome/handyhome/gethandyhome.sh >> /mnt/ramdisk/handyhome/gethandyhome.log 2>>$HOME/smarthome/handyhome/gethandyhome.errlog
Unten ist das Script ping_handys.sh widergegeben, welches jede Minute
gestartet
wird, um festzustellen, ob und welches der beiden Handys mit dem lokalen WLAN
verbunden sind. Etlicher Aufwand wurde geleistet, damit das Error-Log-File
im Normalfall leer bleibt.
#!/bin/bash # ping_handys.sh 14Jun2025/uk mkdir -p /mnt/ramdisk/handyhome/ cd $HOME/smarthome/handyhome source $HOME/smarthome/HA/MASTER.file if test "$MASTER" = "no" ; then exit fi PING_FILES="/mnt/ramdisk/Ping_Devices" LOGFILE="/mnt/ramdisk/handyhome/ping_handys.log" PING_TARGETS="$HOME/smarthome/handyhome/ping_handys.txt" # retries=5 und delay=3 dauert für ein abwesendes Handy ca. 23 Sekunden retries=5 delay=3 sleep 2 # Staffelung der cron-jobs # Sicherstellen, dass die Datei ping_handys.txt existiert if [ ! -f "$PING_TARGETS" ]; then echo "Die Datei $PING_TARGETS wurde nicht gefunden!" exit 1 fi # Führt fping aus und verarbeitet die Ausgabe while IFS= read -r ip; do echo "$(date +%d-%m-%Y_%H:%M:%S) Pinge $ip..." ipREPORT=`echo $ip | cut -c 3-4` # muss VOR fping stehen!!! # Durchführung von 13 Pings, wenn IP nicht erreichbar ist for i in $(seq 1 $retries); do fping --retry=1 "$ip" >/dev/null 2>&1 # Prüfen, ob der Ping erfolgreich war if [ $? -eq 0 ]; then # Wenn erfolgreich, schreibe in die Logdatei und breche den Loop ab echo "$(date +%d-%m-%Y_%H:%M:%S) $ipREPORT home $(date +%s)" >> "/mnt/ramdisk/handyhome/${ipREPORT}_ping_log" echo "$(date +%d-%m-%Y_%H:%M:%S) Ping-Versuch Nr. $i" break else echo "$(date +%d-%m-%Y_%H:%M:%S) $ipREPORT away $(date +%s)" >> "/mnt/ramdisk/handyhome/${ipREPORT}_ping_log" echo "$(date +%d-%m-%Y_%H:%M:%S) Ping-Versuch Nr. $i" fi # Warten vor dem nächsten Versuch sleep $delay done # Wenn nach $retires Versuchen der Ping immer noch fehlschlägt if [ $? -ne 0 ]; then echo "$(date +%d-%m-%Y_%H:%M:%S) $ipREPORT away $(date +%s)" >> "/mnt/ramdisk/handyhome/${ipREPORT}_ping_log" fi done < "$PING_TARGETS" # Für jede IP in der Datei ping_handys.txt echo "$(date +%d-%m-%Y_%H:%M:%S) Ping-Prozess abgeschlossen!" >> $LOGFILE
Das Script gethandyhome.sh testet alle 5 Minuten, ob in den letzten 5 Minuten ein Ping erfolgreich war. Allenfalls "verlorene" Pings werden absichtlich nicht geloggt. Im folgenden Script müssen 'AB' und 'ab' sowie 'CD' und 'cd' durch die passenden Initialen ersetzt werden!
#!/bin/bash # gethandyhome.sh neue Version 06Jun2025/uk 30Nov2023/uk # # Die Idee kam kam ursprünglich beim Studium der Seite # https://www.tryption.ch/de/blog/systeminformationen-aus-swisscoms-internet-box-auslesen/ # und dann einfach einmal DeviceInfo weglassen... :-) # source $HOME/smarthome/HA/MASTER.file if test "$MASTER" = "no" ; then # echo "Nicht Master. gethandyhome.sh - exit! `date +%d.%m.%Y_%H:%M`" exit fi sleep 5 # Staffelung der cron-jobs # cd $HOME/smarthome/handyhome # mkdir -p /mnt/ramdisk/handyhome/ OUTFILE="/mnt/ramdisk/handyhome/${0##*/}.result" # if test ! -r /mnt/ramdisk/handyhome/lastALLEstatus ; then echo "no" > /mnt/ramdisk/handyhome/lastALLEstatus fi lastALLEstatus=`cat /mnt/ramdisk/handyhome/lastALLEstatus` # # Handy-IPs im Router (DHCP) fest vergeben --> siehe /etc/hosts !!! # Im File /etc/hosts hat es zwei Einträge für die beiden Handys der # Benutzer 'AB' und 'CD' : # 192.168.0.nn ipAB # Handy AB # 192.168.0.mm ipCD # Handy CD # echo " " grep -q "home" /mnt/ramdisk/handyhome/AB_ping_log if test $? -eq 0 ; then AB="home" else AB="away" fi echo "$AB" > /mnt/ramdisk/handyhome/AB grep -q "home" /mnt/ramdisk/handyhome/CD_ping_log if test $? -eq 0 ; then CD="home" else CD="away" fi echo "$CD" > /mnt/ramdisk/handyhome/CD # Ausgabe des Status echo "`date +%d.%m.%Y_%H:%M` AB: $AB, CD: $CD" # Leere alte ping-log-Files: > /mnt/ramdisk/handyhome/AB_ping_log > /mnt/ramdisk/handyhome/CD_ping_log # Statusänderung erkennen currentstatus="no" if [ "$AB" = "away" ] && [ "$CD" = "away" ]; then currentstatus="yes" ## echo "yes" > /mnt/ramdisk/handyhome/lastALLEstatus fi # Wenn sich der Status von ALLE_WEG geändert hat, führe die entsprechenden Aktionen aus echo "currentstatus = $currentstatus - lastALLEstatus $lastALLEstatus" if [ "$currentstatus" != "$lastALLEstatus" ]; then echo "`date +%d.%m.%Y_%H:%M` Neue ALLE-Statusänderung - WebHook-Befehle senden" echo "$currentstatus" > /mnt/ramdisk/handyhome/lastALLEstatus new_ALLE_status="true" if test "$AB" = "away" && test "$CD" = "away" ; then echo " yes " > /mnt/ramdisk/handyhome/HOME else echo " no " > /mnt/ramdisk/handyhome/HOME fi else echo "Keine ALLE-Statusänderung" new_ALLE_status="false" fi echo "HOME = `cat /mnt/ramdisk/handyhome/HOME`" # Eintrag für AB erstellen, wenn Status von "home" zu "away" geändert wurde rm -f /mnt/ramdisk/handyhome/neu.dat last_ab_status=$(cat /mnt/ramdisk/handyhome/history.dat | grep "AB" | awk '{print $3}' | head -n 1) # Status aus dritter Spalte extrahieren echo "last_ab_status $last_ab_status - AB $AB" if [ "$last_ab_status" != "$AB" ]; then new_entryAB="true" echo "`date +%d.%m.%Y_%H:%M:%S` AB $AB ALLE_WEG:`cat /mnt/ramdisk/handyhome/HOME`" >> /mnt/ramdisk/handyhome/neu.dat else new_entryAB="false" fi # Eintrag für CD erstellen, wenn Status von "home" zu "away" geändert wurde last_cd_status=$(cat /mnt/ramdisk/handyhome/history.dat | grep "CD" | awk '{print $3}' | head -n 1) # Status aus dritter Spalte extrahieren echo "last_cd_status $last_cd_status - CD $CD" if [ "$last_cd_status" != "$CD" ]; then new_entryCD="true" echo "`date +%d.%m.%Y_%H:%M:%S` CD $CD ALLE_WEG:`cat /mnt/ramdisk/handyhome/HOME`" >> /mnt/ramdisk/handyhome/neu.dat else new_entryCD="false" fi # Wenn Einträge vorhanden sind, die in neu.dat geschrieben wurden if [ -s /mnt/ramdisk/handyhome/neu.dat ]; then cat /mnt/ramdisk/handyhome/history.dat >> /mnt/ramdisk/handyhome/neu.dat mv /mnt/ramdisk/handyhome/neu.dat /mnt/ramdisk/handyhome/history.dat fi # # Daten von MASTER auf SLAVE kopieren: scp -p -o ConnectTimeout=5 /mnt/ramdisk/handyhome/* $SLAVE:/mnt/ramdisk/handyhome/ # if test "$new_entryAB" = "false" && test "$new_entryCD" = "false" ; then echo "Kein neuer Status für AB oder CD --> exit!" if test "$new_ALLE_status" = "false" ; then exit fi else echo "Neuer Status für AB oder CD -> neue Webseite bauen" fi # Web-Seite bauen: rm -f /mnt/ramdisk/handyhome/index_new.html echo "" >> /mnt/ramdisk/handyhome/index_new.html echo "<h1>" >> /mnt/ramdisk/handyhome/index_new.html echo "Aufenthalt Handys/Personen" >> /mnt/ramdisk/handyhome/index_new.html echo "" >> /mnt/ramdisk/handyhome/index_new.html echo "CD: `cat /mnt/ramdisk/handyhome/CD` AB: `cat /mnt/ramdisk/handyhome/AB` " >> /mnt/ramdisk/handyhome/index_new.html echo "
" >> /mnt/ramdisk/handyhome/index_new.html alleweg=$(cat /mnt/ramdisk/handyhome/HOME | cut -d" " -f 3) if [ "$alleweg" = "yes" ]; then echo "Alle sind weg: `cat /mnt/ramdisk/handyhome/HOME` - Aktion_niemand_zuhause" >> /mnt/ramdisk/handyhome/index_new.html else echo "Alle sind weg: `cat /mnt/ramdisk/handyhome/HOME` - Aktion_alle_zuhause" >> /mnt/ramdisk/handyhome/index_new.html fi echo "<h1>" >> /mnt/ramdisk/handyhome/index_new.html echo "Updated: `date +%d-%m-%Y_%H:%M`" >> /mnt/ramdisk/handyhome/index_new.html echo "
" >> /mnt/ramdisk/handyhome/index_new.html echo "<h2>" >> /mnt/ramdisk/handyhome/index_new.html echo "CD und AB - neuste Einträge
" >> /mnt/ramdisk/handyhome/index_new.html echo "" >> /mnt/ramdisk/handyhome/index_new.html echo "`cat /mnt/ramdisk/handyhome/history.dat | head -n 60`" >> /mnt/ramdisk/handyhome/index_new.html echo "" >> /mnt/ramdisk/handyhome/index_new.html echo "" >> /mnt/ramdisk/handyhome/index_new.html echo "<hr>" >> /mnt/ramdisk/handyhome/index_new.html echo "
Last (automatic) update: `date +%d-%m-%Y_%H:%M` (`uname -n`) - Created: 28Nov2023/uk" >> /mnt/ramdisk/handyhome/index_new.html echo "" >> /mnt/ramdisk/handyhome/index_new.html echo "<<h2>" >> /mnt/ramdisk/handyhome/index_new.html echo "" >> /mnt/ramdisk/handyhome/index_new.html # # Webseite auf Web-Server schicken: scp -p -o ConnectTimeout=5 /mnt/ramdisk/handyhome/index_new.html WEBSERVER:/var/www/HandyHome/index.html # Falls keine generelle Statusaenderung (ALLE_WEG) vorhanden ist, # dann keinen WebHook senden: if test "$new_ALLE_status" = "false" ; then echo "new_ALLE_status = $new_ALLE_status --> Keine Webhooks! - exit" exit else echo "new_ALLE_status = $new_ALLE_status --> Webhooks senden!" fi if test "$CD" = "away" && test "$AB" = "away" ; then echo "Niemand zu Hause" echo "Aktion wenn niemand zu Hause ist" # Hier kommt der entprechende Befehl hin... else echo "Jemand zu Hause" echo "Aktion wenn jwmand zu Hause ist" # Hier kommt der entprechende Befehl hin... fi #
Die Webseite - gespeichert im File /mnt/ramdisk/handyhome/index_new.html -
sieht dann beispielsweise so aus und kann auf den WEBSERVER kopiert werden.