[Erledigt]: Anwesenheitserkennung/Batterieüberwachung

Begonnen von micky0867, 22 August 2016, 20:02:01

Vorheriges Thema - Nächstes Thema

micky0867

Ich habe einen Erweiterungsvorschlag zur Anwesenheitserkennung:
http://www.fhemwiki.de/wiki/Anwesenheitserkennung#Batterie.C3.BCberwachung_.28aktuell_nur_G-Tags.29

Die Batterieüberwachung sollte bei sehr vielen LE-Devices funktionieren.
Spezifikation: https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.battery_level.xml

Dazu habe ich ein Shellscript gebaut, mit dem alle Devices vom Typ "MODE=lan-bluetooth" in FHEM abgefragt werden.
Zu diesen Devices wird die BT-Adresse aus FHEM geholt, der Batteriestand per gatttool ermittelt und dieser unter dem gewählten Attribut wieder in FHEM zurück geschrieben.

Voraussetzung:
lepresenced, socat, bluez, gatttool, root Rechte

Getestet auf Opensuse 13.2, mit bluez 5.2.3


#! /bin/bash

# Falls unter allowed_telnetPort ein Passwort gesetzt ist
TELNETPASSWORD=""
# Das Attribut, fuer den Batteriezustand
ATTRIBUT="batterylevel"


[ ! -z "$TELNETPASSWORD" ] && TELNETPASSWORD="$TELNETPASSWORD\n"
TAGS=$(echo -e "${TELNETPASSWORD}list MODE=lan-bluetooth" | socat -t60 - TCP:127.0.0.1:7072 | grep -v "Password" | tr "[:cntrl:]" "\n" | sed 's/ //g')
for tag in $TAGS
do
  [ "$1" = "-v" ] && echo "Ermittle Adresse fuer $tag ..."
  ADDR=$(echo -e "${TELNETPASSWORD}list $tag" | socat -t60 - TCP:127.0.0.1:7072 | grep "ADDRESS" | awk '{print $2}' | tr "[:cntrl:]" "\n" | sed 's/ //g')
  [ "$1" = "-v" ] && echo "Ermittle $ATTRIBUT fuer $tag ($ADDR) ..."
  LEVEL=$(gatttool -t random -b $ADDR --char-read --uuid 0x2a19 2>&1 | awk '{if($1 == "handle:") {printf("%d\n",strtonum("0x"$4))}}')
  if [ ! -z "$LEVEL" ]; then
    echo -e "${TELNETPASSWORD}setreading $tag $ATTRIBUT $LEVEL" | socat -t60 - TCP:127.0.0.1:7072 | grep -v "Password"
    [ "$1" = "-v" ] && echo "Setze $ATTRIBUT fuer $tag auf $LEVEL"
  else
    [ "$1" = "-v" ] && echo "$tag ($ADDR) nicht in der Naehe"
  fi
  [ "$1" = "-v" ] && echo ""
done


Beispielausgabe, wenn das Script mit dem Parameter "-v" aufgerufen wird (ohne -v sagt das Script nichts):
Zitat
Ermittle Adresse fuer nut_A ...
Ermittle batterylevel fuer nut_A (FC:A5:B4:78:3B:AC) ...
Setze batterylevel fuer nut_A auf 100

Ermittle Adresse fuer nut_B ...
Ermittle batterylevel fuer nut_B (F3:44:04:81:54:89) ...
nut_B (F3:44:04:81:54:89) nicht in der Naehe



Micky

Devender

Hallo Micky,

vielen Danke für deine Erweiterung. Ich setzte es zusätzlich zu der bereits dokumentierten Variante ins Wiki.

Viele Grüße,
Dirk
FHEM 5.8 auf RasPi mit Jessy - CUL868, JeeLink Lacrosse
Komponenten: HM, IT, ELV, FB7390, FritzPL543,Sonos Play3
Mehrere Wandtablets sowie einen Smart Mirror
https://wiki.fhem.de/wiki/Anwesenheitserkennung#PRESENCE-Modul

Taasba

#2
Hallo Micky,

lieben Dank für Dein ShellScript  :)

Ich habe es mal unter Debian/Jessie (RasPi3) versucht, bekomme jedoch die Fehlermeldung, dass der G-Tag nicht in der Nähe ist.

Folgendes wirft das Script Aufruf in der Shell aus:
"Ermittle Adresse für (NAME unter fhem)
"Ermittle batterylevel für (NAME unter fhem) (MAC)
"(Name unter fhem) (MAC) nicht in der Naehe

Stimmt ja aber nicht, da die G-Tags in fhem und unter lescaned ja auch gefunden werden.

Nachtrag: "Wenn das Programm mit den Fehlermeldungen durchgelaufen ist, werden alle G-Tags auf "absent" gesetzt. Es hilft nur ein Neustart.

Hast Du eine Idee?

Lieben Dank

Torsten
- fhem mit RasPi3 (debian-jessie) - HomeMatic (CCU2 - HMLAN-Adapter) und diverse HM Komponenten - 6 G-Tags (Anwesenheitserkennung) - SolVisMax Remotecontrol
- CUL 433 (Eigenbau - Arduino Nano C1101) - Alexa

hermi

#3
Hallo zusammen,

habe heute erfolgreich einen Gigaset Keeper unter Debian/Jessie (RasPi3) mit in Betrieb genommen und anfänglich auch Probleme.

1) Ich habe nur einen G-Tag, weshalb die Anfrage "list MODE=lan-bluetooth" keine Liste von Tags ausgibt, sondern die "Internals" meines Tags. Deshalb funktioniert das Script im weiteren Verlauf nicht. Abhilfe schafft dieser kleine Zusatz:

if [ -z "$LETAGS" ]; then
   TAGS=$(echo -e "${TELNETPASSWORD}list MODE=lan-bluetooth" | socat -t60 - TCP:127.0.0.1:7072 | grep -v "Password" | tr "[:cntrl:]" "\n" | sed 's/ //g')
+  # If TAGS starts with "Internals:" we have only one TAG
+  if [ ! -z $(echo "$TAGS" | grep '^Internals:') ]; then
+    # Get its name from the NAME internals
+    TAGS=$(echo "$TAGS" | grep 'NAME' | sed s/NAME//)
+  fi
else
   TAGS="$LETAGS"
fi


2) Weiterhin musste ich im gatttool-Aufruf das "-t random" entfernen, da das Script sonst hängen blieb (und damit möglicherweise auch lepresenced störte?):

     ADDR=$(echo "$TCONFIG" | awk '{if($1=="ADDRESS") print $2}' | tr "[:cntrl:]" "\n" | sed 's/ //g')
     [ ! -z "$VERBOSE" ] && echo "Fetching $ATTRIBUT for $tag ($ADDR) ..."
-    LEVEL=$(gatttool -t random -b $ADDR --char-read --uuid 0x2a19 2>&1 | awk '{if($1 == "handle:") {printf("%d\n",strtonum("0x"$4))}}')
+    LEVEL=$(gatttool -b $ADDR --char-read --uuid 0x2a19 2>&1 | awk '{if($1 == "handle:") {printf("%d\n",strtonum("0x"$4))}}')
     if [ ! -z "$LEVEL" ]; then
       echo -e "${TELNETPASSWORD}setreading $tag $ATTRIBUT $LEVEL" | socat -t60 - TCP:127.0.0.1:7072 | grep -v "Password"


3) Zusätzlich musste ich gawk installieren, da ich sonst einen Fehler bezüglich der Funktion "strtonum()" bekam.

Mit diesen Änderungen kann ich jetzt problemlos den Batteriestatus auslesen. lepresenced wird zwar weiterhin gestört (wohl weil das hci0-Device vom gatttool übernommen wird), aber im bluetooth_thread() wird der lescan nach einer RETRY_SLEEP-Zeit von einer Sekunde wieder neu gestartet. Vielleicht macht es Sinn, diese RETRY_SLEEP-Zeit etwas zu erhöhen, damit der gatttool-Befehl etwas mehr Zeit hat?

Grüße,
Hermann

Nachtrag:
Die o.g. Änderungen betreffen nicht das Script, welches am Anfang dieses Themas gezeigt ist, sondern die erweiterte Version (https://raw.githubusercontent.com/micky0867/lebattery/master/lebattery), auf welche in http://www.fhemwiki.de/wiki/Anwesenheitserkennung#Batterie.C3.BCberwachung_.28alle_Devices_vom_Typ_.22MODE.3Dlan-bluetooth.22.29 Bezug genommen wird.

Mumpitz

hallo zusammen

ich habe das script soeben ausgeführt, direkt auf der Konsole des Raspi. Das Script holt die beiden MAC Adressen der G-Tags heraus und listet sie auf. Leider erscheint bei beiden die Meldung,


gtag_mumpitz (7C:XX:80:AA:5F:8C) nicht in der Naehe



gtag_weib (7C:XX:80:XX:5F:8C) nicht in der Naehe


Die beiden G-Tags sind jedoch gemäss fhem zu Hause....

hat jemand eine Idee?

hermi

Hallo Mumpiz,

hast Du das Script auch mit root-Rechten (sudo) ausgeführt?

Gruß,
Hermann

Mumpitz

Hallo hermi
Danke für die schnelle Antwort!

Hier meine Eingabe
root@raspberrypi:/opt/fhem# sudo ./batterie_gtag_neu.sh -v
Ermittle Adresse fuer gtag_mumpitz ...
Ermittle batterylevel fuer gtag_mumpitz (7C:2F:XX:AA:5F:8C) ...
gtag_reto (7C:2F:XX:AA:5F:8C) nicht in der Naehe


Daran kanns also nicht liegen. Wenn ich nur das gattool nehme erscheint: Connection refused

Weisst du Rat?

DeeSPe

Bei mir läuft das Skript wenn ich es so geändert habe sehr gut  (auch ohne gawk).
So werden auch nur Geräte berücksichtigt die present sind.

#! /bin/bash
# Falls unter allowed_telnetPort ein Passwort gesetzt ist
TELNETPASSWORD=""
# Das Attribut, fuer den Batteriezustand
ATTRIBUT="battery"

[ ! -z "$TELNETPASSWORD" ] && TELNETPASSWORD="$TELNETPASSWORD\n"
TAGS=$(echo -e "${TELNETPASSWORD}list MODE=lan-bluetooth:FILTER=presence=present" | socat -t60 - TCP:127.0.0.1:7072 | grep -v "Password" | tr "[:cntrl:]" "\n" | sed 's/ //g')
# If TAGS starts with "Internals:" we have only one TAG
if [ ! -z $(echo "$TAGS" | grep '^Internals:') ]; then
  # Get its name from the NAME internals
  TAGS=$(echo "$TAGS" | grep 'NAME' | sed s/NAME//)
fi
for tag in $TAGS
do
  [ "$1" = "-v" ] && echo "Ermittle Adresse fuer $tag ..."
  ADDR=$(echo -e "${TELNETPASSWORD}list $tag" | socat -t60 - TCP:127.0.0.1:7072 | grep "ADDRESS" | awk '{print $2}' | tr "[:cntrl:]" "\n" | sed 's/ //g')
  [ "$1" = "-v" ] && echo "Ermittle $ATTRIBUT fuer $tag ($ADDR) ..."
  stringZ=$(sudo gatttool -b 7C:2F:80:AB:FB:D1 --char-read --handle=0x001b)
  stringZ=${stringZ:33:2}
  stringZ=$(echo "$stringZ" | tr a-f A-F)
  LEVEL=$(echo "ibase=16; $stringZ" | bc)
  if [ ! -z "$LEVEL" ]; then
    echo -e "${TELNETPASSWORD}setreading $tag $ATTRIBUT $LEVEL" | socat -t60 - TCP:127.0.0.1:7072 | grep -v "Password"
    [ "$1" = "-v" ] && echo "Setze $ATTRIBUT fuer $tag auf $LEVEL"
  else
    [ "$1" = "-v" ] && echo "$tag ($ADDR) nicht in der Naehe"
  fi
  [ "$1" = "-v" ] && echo ""
done


Gruß
Dan
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe

hermi

@Mumpiz:
Ich hatte manchmal das Problem, dass der erste Aufruf des Scripts fehlschlug, bei zweiten Mal funktionierte es aber immer.

@DeeSPe:
Du benutzt das Original-Script von micky0867, welches den 'bc' zur Berechnung nutzt. Ich habe die Version von hier genommen: https://raw.githubusercontent.com/micky0867/lebattery/master/lebattery. Diese benutzt awk (gawk) zur Berechnung.

DeeSPe

Ich habe einfach beide (das hier vorgeschlagene und das aus dem Wiki) Skripte gemischt so dass es funktioniert.
So kommt jedenfalls immer ein Batteriewert wenn das Script läuft und es läuft nicht unnötig obwohl das Device absent ist.

Ich weiß dass das Skript aus github gawk benutzt! Das fand ich eben auch nicht so gut. Deswegen meine Änderungen.

Habe das Skript zwar umgeschrieben und getestet, benutze es aber nicht.
Bei mir läuft das Skript aus dem Wiki in leicht abgewandelter Form. Dieses wird dann von einem notify bei erkannter Anwesenheit ausgeführt.

Gruß
Dan
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe

Mumpitz

Hallo DeeSpe

ich habe Dein Script ebenfalls versucht. Ich kriege dabei folgende Meldung:


root@raspberrypi:/opt/fhem# sudo ./batterie_gtag_neu.sh -v
Ermittle Adresse fuer gtag_mumpitz ...
Ermittle battery fuer gtag_mumpitz (7C:2F:XX:AA:5F:8C) ...
connect: Connection refused (111)
gtag_reto (7C:2F:XX:AA:5F:8C) nicht in der Naehe

Ermittle Adresse fuer gtag_weib ...
Ermittle battery fuer gtag_weib (7C:2F:XX:AA:5F:03) ...
connect: Connection refused (111)
gtag_susanne (7C:2F:XX:AA:5F:03) nicht in der Naehe


ich habe auch versucht, das script mehrmals auszuführen, ebenfalls ohne Erfolg.

Hast Du sonst noch eine Idee?

DeeSPe

Zitat von: Mumpitz am 22 November 2016, 20:20:56
Hallo DeeSpe

ich habe Dein Script ebenfalls versucht. Ich kriege dabei folgende Meldung:


root@raspberrypi:/opt/fhem# sudo ./batterie_gtag_neu.sh -v
Ermittle Adresse fuer gtag_mumpitz ...
Ermittle battery fuer gtag_mumpitz (7C:2F:XX:AA:5F:8C) ...
connect: Connection refused (111)
gtag_reto (7C:2F:XX:AA:5F:8C) nicht in der Naehe

Ermittle Adresse fuer gtag_weib ...
Ermittle battery fuer gtag_weib (7C:2F:XX:AA:5F:03) ...
connect: Connection refused (111)
gtag_susanne (7C:2F:XX:AA:5F:03) nicht in der Naehe


ich habe auch versucht, das script mehrmals auszuführen, ebenfalls ohne Erfolg.

Hast Du sonst noch eine Idee?

Hmmm, keine Ahnung! Da es ja vom Script gefunden wurde muss es ja auch present sein.
Das "connect: Connection refused (111)" verstehe ich nicht!
Was ist mit dem Skript aus dem Wiki? Funktioniert es damit bei Dir?

Gruß
Dan
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe

Mumpitz

Zitat von: DeeSPe am 22 November 2016, 20:30:51
Hmmm, keine Ahnung! Da es ja vom Script gefunden wurde muss es ja auch present sein.
Das "connect: Connection refused (111)" verstehe ich nicht!
Was ist mit dem Skript aus dem Wiki? Funktioniert es damit bei Dir?

Gruß
Dan

hallo Dan

Wenn ich das betreffende Script nehme erscheint folgendes:

root@raspberrypi:/opt/fhem# ./batterie_gtag_mumpitz.sh
connect: Connection refused (111)
Usage: setreading <name> <reading> <value>
where <name> is a single device name, a list separated by komma (,) or a regexp. See the devspec section in the commandref.html for details.


Das script sieht so aus:
#!/bin/bash
stringZ=$(sudo gatttool -b 7C:2F:80:SS:5F:8C --char-read --handle=0x001b)
stringZ=${stringZ:33:2}
stringZ=$(echo "$stringZ" | tr a-f A-F)
decimal=$(echo "ibase=16; $stringZ" | bc)
perl /opt/fhem/fhem.pl 7072 "setreading gtag_mumpitz Batterie $decimal"

DeeSPe

Ich habe echt gerade keine Ahnung was da bei Dir schief läuft!
Auch bei dem Skript aus dem Wiki kommt ja bei Dir "connect: Connection refused (111)"!

Der GTag ist aber nicht mit irgendwas gekoppelt!?

Gruß
Dan
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe

Mumpitz

Zitat von: DeeSPe am 22 November 2016, 20:56:40
Ich habe echt gerade keine Ahnung was da bei Dir schief läuft!
Auch bei dem Skript aus dem Wiki kommt ja bei Dir "connect: Connection refused (111)"!

Der GTag ist aber nicht mit irgendwas gekoppelt!?

Gruß
Dan
Nein. Ich habe ihn auch nie auf dem Handy eingerichtet oder die App installiert.
In fhem funktioniert er einwandfrei! Sprich die Stati wechseln innerhalb Sekunden!


Gesendet von iPad mit Tapatalk