+ Antworten
Ergebnis 1 bis 5 von 5
  1. #1
    Registriert seit
    May 2013
    Beiträge
    355

    Standard Raspberry Pi als Beacon Scanner für Gigaset G-Tags - Reloaded

    Hallo miteinander,

    ich habe lange versucht ein sehr zuverlässiges System für die Anwesenheitssteuerung zu finden. Es gibt hier im Forum verschiedene Ansätze um Beacons zu nutzen. Die Scripte sind teilweise einige Jahre alt und ich wollte das hier nochmal zusammenfassen.

    Danke an @TomW für die Hilfe und fürs Teilen seiner Scripte.

    Mehr Infos gibts vor allem hier:
    https://www.symcon.de/forum/threads/30936-Raspberry-Pi-als-iBeacon-Scanner-f%C3%BCr-Schl%C3%BCsselbunddongle/page8?highlight=Beacon

    Das Konzept sieht bei mir so aus, dass ich mehrere Pis (am liebsten Zero W) einsetze, um nach den G-Tags zu scannen. Auf diesen Pis läuft ein Script, welches im Hintergrund in Echtzeit alle G-Tags sieht. Das Script wird zusätzlich jede Minute als cronjob neu gestartet um festzustellen, ob der Dienst noch läuft und sich für den Fall, dass das nicht so ist, neu zu starten. Das ist dann notwendig, wenn der Empfänger nicht erreichbar ist, also unser Symcon System.

    Es gibt zwei Möglichkeiten. Entweder man installiert auf den Scanner Pis auch Symcon und schickt die Ausgabe an 127.0.0.1 also localhost oder eben an jeden anderen Empfänger im Netzwerk. Die Ausgabe an das Haupt Symcon System zu senden empfiehlt sich nicht, denn es kommen bei meinen 5 Tags ca. 300 000 Meldungen pro Tag an. Das macht das ganze etwas unübersichtlich wenn man andere Meldungen erkennen möchte. Für Symcon selbst wäre das natürlich kein Problem.

    Mein Setup sieht im Moment 4 Scanner vor. Auf diesen läuft nur das Script und diese schicken ihre Meldungen an ein Symcon System, welches nur für den Empfang und die Verwaltung der Tags verantwortlich ist. Dieses überträgt bei Änderung dann den Status der Anwesenheit an mein Hauptsystem. Dieses Scanner Empfangs Symcon kann natürlich auf einem der Scanner Pis laufen.

    Jetzt gehts los:

    Pi mit integriertem Wlan und Bluetooth LE. Also ab 3B. Bestens geeignet Zero W.
    Raspbian Buster, Upgrades, Mit eigenem Wlan verbinden und per SSH erreichbar machen.

    Anlegen eines init Scripts:

    sudo nano /etc/init.d/BLEScan

    PHP-Code:
    #! /bin/sh
    ### BEGIN INIT INFO
    # Provides: skeleton
    # Required-Start: $syslog
    # Required-Stop: $syslog
    # Default-Start: 2 3 4 5
    # Default-Stop: 0 1 6
    # Short-Description: BLE Scanner by DarthWeber
    # Description:
    ### END INIT INFO
     
    case "$1" in
        start
    )
            echo 
    "BLEScan wird gestartet"
            
    var=`ps -eaf | grep BLEscan0 | wc -l`
            if [ 
    $var -lt "2" ]; then
                    su 
    root -"/usr/local/bin/BLEscan0.sh&"
            
    else
                    echo 
    "BLEscan0 läuft bereits - Bus:"`hciconfig hci0 | grep Bus | cut -d " " -f5`
            
    fi
             
    ;;
        
    stop)
            echo 
    "BLEScan wird beendet"
            
    # Beende Programm
            
    killall BLEscan0.sh
            killall hcitool
            
    ;;
        
    restart)
            echo 
    "BLEScan wird beendet"
            
    killall BLEscan0.sh
            killall hcitool
            
    echo "BLEScan wird gestartet"
            
    # Starte Programm
            
    su root -"/usr/local/bin/BLEscan0.sh&"
            
    ;;
        
    status)
            var=`
    ps -eaf | grep BLEscan0 | wc -l`
            if [ 
    $var -lt "2" ]; then
                    
    echo "Error - BLEscan0 läuft nicht"
            
    else
                    echo 
    "OK - BLEscan0 läuft - Bus:"`hciconfig hci0 | grep Bus | cut -d " " -f5`
            
    fi
            
    ;;
        *)
            echo 
    "Benutzt: /etc/init.d/BLEScan {start|stop|status}"
            
    exit 1
            
    ;;
    esac
     
    exit 
    ausführbar machen
    sudo chmod +x /etc/init.d/BLEScan

    Das Script welches scannt anlegen. Hier muss man sich nun die Ziel IP Adresse des Scanner Empfangs Symcon eintragen. Ausserdem ist es wichtig, für jeden Scanner einen eigenen beliebigen ID zu vergeben, so kann man später unterscheiden, welcher Scanner den G-Tag gesehen hat. In dem Beispiel ist die Ziel IP Adresse 192.168.1.20 und der ID des Scanners ist ble1

    sudo nano /usr/local/bin/BLEscan0.sh

    PHP-Code:
    #!/bin/bash
    # BLEscan0.sh
    hciconfig hci0 down > /dev/null && hciconfig hci0 up > /dev/null
    if [ $? = ]; then
       stdbuf 
    -i0 -o0 -e0 hcitool -i hci0 lescan --duplicates grep --line-buffered "Giga" sed -'s/^/ble1 /' > /dev/udp/192.168.1.20/8173
    else
       echo 
    "hci0 Error" > /dev/udp/192.168.1.20/8173
    fi 
    wieder ausführbar machen
    sudo chmod +x /usr/local/bin/BLEscan0.sh

    Gestartet wird der Dienst dann per
    sudo /etc/init.d/BLEScan start

    stop und restart und status gehen auch. Der Empfänger ist aber im Moment noch nicht erreichbar. Deshalb wird da gleich ERROR als status angezeigt.

    Jetzt noch in den crontab mit minütlicher Ausführung
    sudo crontab -e

    Unten die Zeile einfügen:
    * * * * * /etc/init.d/BLEScan start

    Speichern. Fertig mit den bash Scripten auf dem Sende Pi.


    Der Empfang in Symcon:

    I/O Instanzen. Neue Instanz. Multicast Socket
    Sendehost: bei mir steht da localhost, spielt aber keine Rolle, es kommt von überall her an.
    Sendeport: 8173
    Empfänger Host: die IP Adresse des Symcon Scanner Empfangsystems oder All. Das ist das auf dem ihr gerade arbeitet.
    Empfangsport: 8173

    Socket öffnen

    Den Rest so lassen. Änderungen übernehmen.

    Damit empfängt Symcon die Nachrichten des Scanners. Wenn ihr jetzt auf dem Sende Pi den Dienst startet oder diesen rebootet, könnt ihr im Debug Fenster die Nachrichten sehen.

    Weiter geht es mit einer Register Variable. Diese verarbeitet die eingehenden Nachrichten. Da mein Empfangs Symcon jungfräulich ist, erstelle ich die Register Variable im Hauptverzeichnis und die folgenden Scripte alle unterhalb der Variable. Das hat den Vorteil, dass man sehr einfach die IDs nach Namen bei gleichem Parent finden kann.


    IP-Symcon, Hinzufügen Instanz, Register Variable

    Diese wird erstellt, kann aber nicht gespeichert werden, solange kein Script hinterlegt ist. Also zurück zum Objektbaum und unterhalb der erstellten Register Variable ein script erstellen. Das Script legt entsprechend der vergebenen Namen Variablen für die Tags an. Unterhalb der Variablen wird eine weitere Variable pro Scanner angelegt. Diese heisst wie der Scanner (ihr erinnert euch an die ID die ihr im Scanner Script vergeben solltet?) und enthält den timestamp des letzten Empfangs. Praktisch für eine watchdog Funktion oder zum Auswerten eines bestimmten Scanners.

    Name register

    PHP-Code:
    <?php

    $s 
    IPS_GetScript(IPS_GetObjectIDByName ('Tags'IPS_GetParent($_IPS['SELF'])));
    include(
    $s['ScriptFile']);

    $Verzeichnis IPS_GetParent($_IPS['SELF']);   
     

    function 
    CheckMacs($Data)  {
      global 
    $Macs;  
      
    $Returnvalue = Array();
      
    $Returnvalue[0]=false
      foreach(
    $Macs as $Name => $Address
        {
          
    $pos strpos($Data,$Address);
          if (
    $pos === false) continue;
          
    $Returnvalue[0]=true;
          
    $Returnvalue[1]=$Name;
          
    $Returnvalue[2]=substr($Data,0,4);
        }
      return 
    $Returnvalue;  
    }  
    // end function CheckMacs

    function CreateVar($Path,$Name,$Typ) {
        global 
    $Verzeichnis;
        
    $Id = @IPS_GetVariableIDByName($Name,$Path);
        
       if (
    $Id === false)
        {
          
    $Id=IPS_CreateVariable($Typ); 
          
    IPS_SetParent($Id,$Path);
          
    IPS_SetName($Id,$Name);
        }
        return 
    $Id;
    }

    if (
    $_IPS['SENDER'] == 'RegisterVariable')
      {
         
    $str $_IPS['VALUE'];   
         
    $R CheckMacs($str); 
       
         if (
    $R[0] === true 
           { 
             
    $id CreateVar($Verzeichnis,$R[1],0);
             
    SetValue($id,true);   
             
    $idx CreateVar($id,$R[2],1);
             
    SetValue($idx,time());     
           }


      }


    ?>
    Speichern und zurück zur Register Variable. Dort das Script register als Ziel auswählen. Dann oben unter Gateway ändern unseren vorhin erstellen Mulitcast Socket auswählen. Änderungen übernehmen.

    Damit das register Script weiss, nach was es suchen muss legen wir wieder unterhalb der Register Variable ein weiteres Script an mit dem Namen

    Tags

    PHP-Code:
    <?php

    $Macs 
    = Array(
        
    'Buzz2' => '58:9E:C6:0E:EC:6F',
        
    'Buzz' => '58:9E:C6:0E:EE:3F',
        
    'Elli' => '58:9E:C6:0E:EF:68',
        
    'Car2' => '58:9E:C6:0E:ED:53',
        
    'Car1' => '58:9E:C6:0E:EC:CB'
        
    );

    ?>
    Jetzt sollten Eure Tags angelegt werden. Falls ihr die MAC Adressen eurer Tags nicht kennt, könnt ihr diese im Debug Fenster des Mulicast Socket sehen. Dazu stellt ihr von HEX auf Text um.

    Damit diese auch auf abwesend gesetzt werden, brauchen wir ein weiteres Script. Hier sind zwei Minuten eingestellt und ich rufe das Script mit einem Timer alle 30s auf. Das ist aber natürlich beliebig.

    Wieder unterhalb der Register Variable
    Name setfalse

    PHP-Code:
    <?php
    $now 
    time();
    $s IPS_GetScript(IPS_GetObjectIDByName ('Tags'IPS_GetParent($_IPS['SELF'])));
        include(
    $s['ScriptFile']);

    function 
    setfalse()
    {
    global 
    $Macs$now;
    foreach(
    $Macs as $Name => $Address
        {  
         
    $eins=GetValue(IPS_GetObjectIDByName ($NameIPS_GetParent($_IPS['SELF'])));
         
    $eins_info IPS_GetVariable(IPS_GetObjectIDByName ($NameIPS_GetParent($_IPS['SELF'])));
         
    $time_eins =  $eins_info["VariableUpdated"];
         if (
    $now $time_eins 120) if (GetValue(IPS_GetObjectIDByName ($NameIPS_GetParent($_IPS['SELF'])))) SetValue(IPS_GetObjectIDByName ($NameIPS_GetParent($_IPS['SELF'])),false);      
        }

    }    

    setfalse();

    ?>
    Damit sollte alles laufen.

    Die Übertragung ins Hauptsystem mache ich per webhook. Das ist im ursprünglichen Thread sehr gut erklärt. Gleich auf der ersten Seite.

    Hier mein Script dazu. Der Webhook muss natürlich im Hauptsystem eingerichtet werden und zwar für jeden Beacon. Dazu die passende Variable und ein hook Script darunter. Damit das script funktioniert, müssen die hooks im Empfanhssystem so aussehen:

    /hook/Buzz
    also /hook/'Name des Tags' so wie er im Script Tags hinterlegt wurde.

    Wieder unterhalb der Register Variable
    webhhook

    PHP-Code:
    <?php
    $now 
    time();
    $s IPS_GetScript(IPS_GetObjectIDByName ('Tags'IPS_GetParent($_IPS['SELF'])));
        include(
    $s['ScriptFile']);

    function 
    webhook()
    {
    global 
    $Macs$now;
    foreach(
    $Macs as $Name => $Address
        {
          
    $status GetValue(IPS_GetObjectIDByName ($NameIPS_GetParent($_IPS['SELF'])));
           
    $string "http://192.168.1.21:3777/hook/{$Name}?Status={$status}";
         
    file_get_contents($string);
        }

    }    

    webhook();

    ?>
    Auf der Empfangsseite sieht mein Script unterhalb der Empfangsvariablen so aus

    hook

    PHP-Code:
    <?

    if ($_GET['Status'] == 1)
    {
    SetValue(IPS_GetParent($_IPS['SELF']), true);
    }
    if (
    $_GET['Status'] == 0)
    {
    SetValue(IPS_GetParent($_IPS['SELF']), false);
    }

    ?>
    Viel Spass und danke an alle für die großartige Vorarbeit!

    Sebastian
    Geändert von Buzz2912 (10.11.19 um 20:24 Uhr)

  2. #2
    Registriert seit
    May 2013
    Beiträge
    355

    Leider kann ich kein Modul schreiben, aber hier wären meine Gedanken dazu.

    Die Scanner Pis werden wie gehabt angelegt. Mit der Scanner ID und der Empfangs IP Adresse.

    Ich stelle mir ein Modul im Haupt Symcon System vor. Also kein extra System für die vielen Meldungen.

    Das Modul legt den Socket und die Register Variable an, unterdrückt aber die eingehenden Meldungen. Behält diese nur für sich und wertet diese aus.

    In einem Formular trägt man den Namen und die MAC Adresse der Tags ein. Vielleicht könnte das Modul auch unbekannte Tags in einem Debug Fenster zeigen, damit man einfach neue hinzufügen kann.
    Außerdem gibt es ein Feld fürs Zeitintervall bis zum abwesend setzen.
    Es gibt ein weiteres Feld für die ID des Parent Verzeichnis unter dem dann automatisch die Variablen angelegt werden. Unterhalb dieser Variablen wie gehabt die Scanner Ids mit timestamp.

    Sebastian

  3. #3
    Registriert seit
    Jul 2009
    Ort
    Bremen
    Beiträge
    667

    Hi Sebastian,

    den Watchdog brauchst du eigentlich nicht. Mein BLEScan script prüft beim Start, ob der Dienst bereits läuft - und startet nur in diesem Fall neu.

    Du kannst also einfach in deiner cronatb das BLEScan minütlich starten, dann prüft es sich selbst jede Minute und startet ggf. neu:
    * * * * * root /etc/init.d/BLEScan start
    Das war bei meinem RasPi leider auch notwendig, denn zumindest der Dienst am externen hci1 BT Dongle schmiert aller paar Stunden ab, so stört das aber nicht sonderlich. Der interne hci0 ist bei mir da deutlich stabiler.

    Damit ist auch das "update-rc.d BLEScan defaults" obselet (ich wußte das letzte Woche noch nicht)

    Vielleicht kannst du das oben in deiner Beschreibung noch aufnehmen ?

    Ich bastel gerade daran, alles in einem python script aufzunehmen und per mqtt durchzureichen, damit bräuchte man insgesamt nur noch ein script....

  4. #4
    Registriert seit
    May 2013
    Beiträge
    355

    Hab ich erledigt.

    Es gibt schon ein Python Script hier im Forum, von 2017. Kann man die Verwaltung der Tags dann trotzdem in symcon machen? Der Scanner Pi schickt alles durch und Symcon regelt den Rest?
    Veränderungen in Symcon sind immer leicht, weil zentral durchführbar. Alle Pis umstellen ist da aufwendiger.

    Gruss Sebastian

  5. #5
    Registriert seit
    Jul 2009
    Ort
    Bremen
    Beiträge
    667

    Theoretisch ja, bzw. genau so wie mit dem shell Script von mir, es muss halt eben auch die Daten per socket oder mqtt durchreichen. Hast du einen Link ?

Ähnliche Themen

  1. Raspberry Pi als iBeacon Scanner für Schlüsselbunddongle
    Von lahlor im Forum Anleitungen / Nützliche PHP Skripte
    Antworten: 77
    Letzter Beitrag: 08.11.19, 19:33
  2. Gigaset G-TAg als Anwesenheitskontrolle
    Von tommy86 im Forum Sonstige Funkkomponenten / Wetterstationen
    Antworten: 0
    Letzter Beitrag: 29.10.19, 10:17
  3. Win10 Beacon Scanner -> IPS
    Von sallos im Forum Projekt Showcase
    Antworten: 5
    Letzter Beitrag: 25.06.18, 21:43
  4. Raspberry Pi + Python + MQTT + BLE = BTL Scanner
    Von drapple im Forum Anleitungen / Nützliche PHP Skripte
    Antworten: 4
    Letzter Beitrag: 06.03.18, 19:20