Raspberry Pi: mit dem Amazon Dash Button eine WLAN-Steckdose schalten

Komplette Anleitung für das Verbinden eines Amazon Dash Button mit einer TP Link HS 100 WLAN – Steckdose

In diesem Artikel möchte ich zeigen, wie du mit einem Amazon Dash Button als Taster und einem Raspberry Pi  eine TP-Link HS 100 Funksteckdose steuern kannst. Dazu zeige ich, welche Artikel du brauchst, welche Software du auf dem Raspberry Pi installieren musst und wie am Ende eine Kommunikation hergestellt wird.

Der Minirechner: Raspberry Pi kann mit einem Amazon Dash Button die TP-Link HS100 bedienen

Amazon Dash Button, Raspberry Pi und die WLAN Steckdose TP-Link HS100

kostenloses Buch für die persönliche Entwicklung

Etwas Allgemeines:

Wie kann der Dash Button dazu genutzt werden, um die Funksteckdose zu schalten? Exemplarisch habe ich für diesen Blogeintrag eine TP-Link HS 100 Steckdose genutzt.

Der Amazon Dash Button ist ein WLAN fähiger Taster. Er verbindet sich mit deinem WLAN und würde eigentlich ein von dir vorgesehenes Produkt bestellen. Ausschließlich nach dem Tastendruck stellt der Button eine WLAN-Verbindung her, sonst ist der Button außer Betrieb und somit wird kein Strom verbraucht. Um das Signal des Button aufzufangen überwacht ein Raspberry Pi permanent den kompletten WLAN Datenverkehr und löst bei entsprechendem Ereignis eine beliebige Aktion aus. Diese Aktion kann dann das Schalten einer Funksteckdose sein. Andere Szenerien, wie eine Türklingel, Garagentoröffner, Arbeitszeiterfassung oder ähnliches sind ebenso denkbar.

Artikelliste:

Was brauchen wir für den Aufbau?

mögliche Wege den Dash Button an den Raspberry Pi zu koppeln:

Ich möchte kurz die Möglichen Wege skizzieren, die es gibt, um den Dash Button mit der Funksteckdose zu koppeln:

Möglichkeit 1: DNS-Redirect

Der Dash Button baut bei jedem Tastendruck eine Verbindung zu der Webseite parker-gw-eu.amazon.com auf. Den Request könntest du lokal abfangen und durch eine DNS-Umleitung auf ein lokales System führen. Dieses lokale System führt dann die entsprechende Aktionen aus.

Möglichkeit 2: Ping-Test

Der Dash Button bekommt am Router eine feste IP vergeben. Auf dem Raspberry Pi lasst man ein Python Script laufen, welches z.B. jede Sekunde diese IP des Buttons via ping zu erreichen versucht und je nach Rückgabe, bzw. ob der Button antwortet oder nicht, lässt man ein Script eine Aktion ausführen.

Möglichkeit 3: ARP-Sniff

Du installierst auf deinem Raspberry Pi eine Python-Software ( Scapy ) welches den WLAN-Netzwerkverkehr auf dem Raspberry Pi überwacht. Du startest ein Script, in dem du diese Überwachung aktiviert. Als Überwachungsparameter gibst du die MAC-Adresse deines Dash Buttons an. Wenn dann der Dash Button ein sogenannten ARP-Request macht, stellt das der Raspberry Pi fest und du weißt somit, dass der Button gedrückt worden ist. In deinem Script reagierst du darauf, in dem du z.B. deine Steckdose schaltest.

Möglichkeit 4: DCHP-Sniff

Ist identisch zur Möglichkeit 3. Jedoch wird hier nicht geprüft, ob ein ARP-Request durchgeführt wird, sondern ob ein DHCP-Request kommt. D.h. wenn der Dash Button sich vom Router, bzw. dem DHCP Server, eine IP holt, registriert der Raspberry Pi die Anfrage und das überwachende Script löst das Schaltsignal für die WLAN-Steckdose aus. Ich habe für mich für die Implementierung dieser Variante entschieden, da der Raspberry Pi im Vortest nicht jeden ARP-Request aufgezeichnet hatte. Im Folgenden gehe ich auf die Implementierung ein.

Möglichkeit 5: Dash AWS IoT Button

Amazon bietet seit neustem auch einen AWS IoT Button an ( Amazon IoT Button 25€ ). Der Button sieht aus, wie der normale Dash-Button, verbindet sich aber zur AWS-Infrastruktur, die man selbst nutzen kann. Amazon bietet auch eine kostenlose 12 monatige Testphase an. Das Einbinden vorhandener API ist damit möglich und bietet somit einen deutlich erweiterten Funktions- und Nutzungsumfang. Die Nutzung der AWS-Infrastruktur ist für professionelle Bereiche durchaus besser geeignet als das sniffen von ARP oder DHCP Request. Solltet ihr Interesse haben, kann ich gern  zum AWS IoT Button ein Tutorial erstellen.

Vorbereitung:

Amazon Dash Button in das WLAN einbinden

Die Einbindung des Amazon Dash Button ist sehr einfach gestaltet:

Auf dem Smartphone muss die Amazon Shopping App installiert sein. Alle weiteren Schritte für die Installation sind in der Bildergalerie nachvollziehbar:

Die Steckdose in das WLAN einbinden:

Das Einrichten der WLAN Funksteckdose TP-Link HS100 ist sehr einfach und über die von TP-Link bereitgestellt App „Kasa“ möglich. Die notwendigen Schritte sind in der Bildergalerie zu sehen:

Nachdem der Dash Button sowie die Funksteckdose in das WLAN eingebunden sind, werden weitere Konfiguration durchgeführt:

DHCP: statische IP-Adressen auf dem Router vergeben

Auf dem Router, der die IP-Adressen für die Clients vergibt, solltest du eine statische IP-Adresse für die Funksteckdose vergeben. Das Script, welches auf dem Raspberry Pi läuft und die Steckdose steuert, kann dann die statisch vergebene IP-Adresse genutzt werden. Somit muss kein Steckdosen-Suchprozess implementiert werden.  Ich habe auf meinem DHCP-Server in den Service-Optionen die statische IP 192.168.1.113 vergeben.

vergeben einer statischen IP Adresse für die Funksteckdose

Beispielhaft: statische IP für Funksteckdose

Implementierung:

Ich setze jetzt einen fertigen vorkonfigurierten Raspberry Pi mit WLAN und SSH voraus ( siehe dazu: Raspberry Pi: meine Standardkonfiguration)

Als erstes installiere ich den Sniffer scapy

Scapy

Scapy ist ein Python-Tool mit dem der Netzwerktraffic analysiert werden kann, sowie sich Pakete gezielte manipulieren lassen. Ich nutze scapy, um den WLAN-Verkehr zu überwachen und die DHCP-Requests abzufangen. Das heißt, wenn ein DHCP – Request von der MAC Adresse des Dash-Button aufgezeichnet wird, ist das der Trigger, mit dem nun beliebige Aktionen ausgelöst werden können

sudo apt-get install -y scapy

Node.JS

Ich nutze einen Raspberry Pi Zero für den Aufbau. Das ist wichtig zu wissen, da wir jetzt einen Node.js Server installieren. Der Raspberry Pi Zero verwendet eine ARMv6 CPU-Architektur und benötigt deshalb eine andere Version als z.B. der Raspberry Pi 3 (ARMv8). In der Wikipedia-Übersicht erkennt man, welcher Raspberry Pi welche CPU-Architektur verwendet und unter Link findet man jeweils die aktuelle Node.js Verison.

Was macht Node.js? Node.js ist ein Webserver, der serverseitig JavaScript ausführt und eignet sich besonders für eine Client/Server Kommunikation. Ich nutze den Node.js Server an dieser Stelle, da die API zum Ansprechen der Funksteckdose für Node.js zur Verfügung gestellt wurde.

Wir laden also das Node.js Paket herunter, entpacken es und kopieren es nach /usr/local

cd /home/pi/
wget https://nodejs.org/dist/v7.9.0/node-v7.9.0-linux-armv6l.tar.gz
tar -xvf node-v7.9.0-linux-armv6l.tar.gz
cd node-v7.9.0-linux-armv6l/
sudo cp -R * /usr/local/

HS100 API

Die API, die die Kommunikation zur Funksteckdose bereitstellt wurde auf GitHub bereit gestellt. Wir legen die API der Einfachheit halber direkt im PI Home Verzeichnis ab – dafür clonen wir das Git Repository. Wer gern mit der API weiter arbeiten möchte, sollte einen Blick in die Readme werfen.

sudo apt-get install -y git 
git clone https://github.com/plasticrake/hs100-api.git

trigger.py : das Dash Button Signal mit dem Raspberry Pi abfangen

Dieses python script lauscht auf den WLAN-Netzwerkverkehr, überwacht die DHCP Requests und prüft, ob die MAC Adresse vom Dash Button stammt. Wenn das Script feststellt, dass ein DHCP-Request von einem Dash Button stammt, ruft es die plug_switch.js -Datei auf.

from scapy.all import *
import sys, os
def arp_display(pkt):
    if pkt.haslayer(DHCP):
        if pkt[Ether].src == "ac:63:be:xx:xx:xx": #die MAC Adresse des Button mit Kleinbuchstaben!
            #print (pkt[Ether].src)
            os.system("node /home/pi/plug_switch.js")
print sniff(prn=arp_display, store=0,count=0)

plug_switch.js

Der js-code zur Steuerung der Funksteckdose (liegt bei mir im Home Verzeichnis des pi-User /home/pi/ )

Ablauf:

  • Zuerst wird eine Verbindung via API zur Steckdose hergestellt
  • der aktuelle Schaltzustand der Steckdose wird abgefragt
  • der gegenteilige neue Schaltzustand wird gesendet
const Hs100Api = require('./hs100-api');
const client = new Hs100Api.Client();
// Meine lokale IP der Steckdose:
const ip =  '192.168.1.113';
const lightplug = client.getPlug({host: ip});
// Hole den aktuellen Schaltzustand und sende es negiert an die Steckdose zurück 
lightplug.getPowerState()
.then(value => {if (value) { lightplug.setPowerState(false)} else {lightplug.setPowerState(true)};})
.catch(error => {console.log(error)});

setInterval(() => {
    process.exit();
},1000);

Autostart

Damit das trigger.py script ausgeführt wird, wenn der Raspberry Pi bootet, lasse ich es über einen Eintrag in der Crontab starten:

sudo cronbtab -e

Am Ende der Datei folgende Zeile einfügen:

@reboot sudo python /home/pi/trigger.py

Soweit sollte das Funktionieren. Wenn Du noch Fragen haben solltes oder mir Hinweise geben möchtest, hinterlasse bitte einen Kommentar. Wenn Du willst, trage dich in die E-Mail-Abonnenten-Liste ein, um stets über Updates informiert zu werden!

Quellen:

https://www.golem.de/news/reverse-engineering-mehr-spass-mit-amazons-button-1701-125359.html (Sehr lesenswerter Artikel)

Controlling the TP-LINK HS100 Wi-Fi smart plug

Raspberry PI for controlling TP-Link POWER

https://github.com/plasticrake/hs100-api

http://t3n.de/magazin/serverseitige-javascript-entwicklung-nodejs-einsatz-231152/

https://de.wikipedia.org/wiki/Raspberry_Pi#Eigenschaften

http://hypfer.de/blog/2016/09/02/amazon-button-zweckentfremden-ohne-arp-1n

Befehlesreferenz: Linux Befehlsreferenz

Und hier noch eine klare Empfehlung für alle, die auch außerhalb des IT-Bereiches mehr erreichen wollen:

kostenloses Buch für die persönliche Entwicklung

 

Heiko

Heiko

Ich bin Entwickler und Koordinator für Datenbanken, Data Warehouse Systeme und IT im Gesundheitswesen. Spezialisiert habe ich mich auf MS-SQL SSIS, SSAS und Data Vault. Im Jahr 2008 startete ich bei einem Pharmaunternehmen in Leipzig und seit 2015 bin ich in im Forschungsumfeld beschäftig. Ich persönlich beschäftige mich vor allem mit den Themen Datenintegration, -qualität und -analyse. Das Tolle an meinem Job ist, dass ich immer sehr abwechslungsreiche und verantwortungsvolle Projekte begleiten darf. Im privaten Umfeld beschäftige ich mich gern mit den Themen Fotografie, Flugmodellbau und dem Wassersport. Ich freue mich darauf hier einige interessante Beiträge zu publizieren und überentsprechende Kritiken und Feedback.
Heiko

30 Comments

  1. Antworten Wolfgang

    Hallo und Danke für die tolle Anleitung,

    leider habe ich NULL Wissen über Python, Script usw. aber RasPi läuft (Jessie light) mit verschiedenen Programmen (Hyperion, Motion, io.broker usw.). Habe alles so umgesetzt wie beschrieben, aber leider funzt nix.
    Wenn ich direkt über Konsole den Befehl: „sudo python /home/pi/trigger.py“ absetze kommt folgende Fehlermeldung:
    >>WARNING: No route found for IPv6 destination :: (no default route?)<<
    Scheinbar (laut Google) läuft irgendwas mit Scapy falsch.
    Vielleicht kannst du mir einen Tipp geben. Danke vorab.

    Mit freundlichen Grüßen
    Wolfgang

    • Heiko Böhme
      Antworten Heiko Böhme

      Hallo Wolfang,
      vielen Dank für Deine Frage. Was genau geht denn nicht? D.h. du hast das script laufen und die Steckdose schaltet nicht?
      Du kannst im trigger.py Script die Zeile 6 mal aktivieren, d.h. einfach die # wegnehmen – dann siehst du die MAC-Adresse deines Button als Ausgabe auf der Konsole.
      Die Ausgabe WARNING: No route found for IPv6 destination :: (no default route?)<< ist eher unkritisch und kannst du so stehen lassen, da sie auf eine unvollständige IPv6-Netz Konfiguration hinweist, Du sie aber sicher (so wie ich) nicht haben wirst sondern eine IPv4-WLAN-Konfiguration. Also das ist m.E. nicht das Problem.

      Hast du die MAC-Adresse auch nur mit kleinen Buchstaben geschrieben? Scapy empfängt sie in kleinen Buchstaben und der Vergleich gegen Großbuchstaben würde fehlschlagen. (Sicherheitshalber frage ich auch mal, ob Du die Einrückungen in dem Script berücksichtigt hast? Bei Python sind die wichtig..)

      Um tatsächlich mal alle DHCP-Request in deinem Netz anzeigen zu lassen, kannst Du das Script auch so abändern: (Zeile 5 und 7 auskommentiert aber Zeile 6 zeigt alle DHCP-Anfragen unabhängig von der MAC-Adresse. Zeile 7 würde ich auskommentieren, da nicht bei jedem Empfang einer DHCP-Anfrage geschaltet werden soll, kannst du aber auch aktiviert lassen)

      from scapy.all import *
      import sys, os
      def arp_display(pkt):
          if pkt.haslayer(DHCP):
              #if pkt[Ether].src == "ac:63:be:xx:xx:xx": #die MAC Adresse des Button mit Kleinbuchstaben!
                  print (pkt[Ether].src)
                  #os.system('node /home/pi/plug_switch.js')
      print sniff(prn=arp_display, store=0,count=0)
      

      Um noch mehr zu sehen, könntest du in einem zweiten Terminalfenster iptraf auf dem Raspberry PI installieren und starten, um deinen kompletten Netzwerkverkehr aufzuzeigen (ggf. kannst du die übrigen WLAN-Geräte mal kurz ausmachen, um etwas Ruhe im Netz zu bekommen)

      sudo apt-get install iptraf
      sudo iptraf

      (Hinweis: Unter Filters sollte ARP visible stehen)
      Wenn Du dann den IP-Traffic-Monitor startest siehst Du deine Netzwerkpakete in einer Liste angezeigt. Da solltest du auf jeden Fall mal die MAC-Adresse deines Dash-Button mal angezeigt bekommen.

      Ich hoffe, ich konnte dir damit ein klein wenig helfen? Wenn nicht, melde dich gern nochmal!
      Beste Grüße und gutes Gelingen
      Heiko

      • Antworten Wolfgang

        Hallo Heiko,

        vielen Dank für deine schnelle und sehr hilfreiche und umfassende Rückantwort.

        Es lag an der MAC-Adresse vom Button. Habe zwar alles in Kleinbuchstaben gesetzt aber einen Eingabefehler (anstatt 50 habe ich 5O -> eingegeben).

        Nun klappt alles wunderbar. Aber es ist schon eine deutliche Verzögerung bemerkbar, macht aber nix.
        Hauptsache es klappt mit einem nun 1,99 EUR (kurzfristige Preissenkung von Amazon) Wifi-Schalter.
        Das ist sensationel 🙂
        Vielen Dank nochmals.

        Gruß Wolfgang

        • Heiko Böhme
          Antworten Heiko Böhme

          Ok, perfekt! Das kann schonmal passieren aber es freut mich, wenn meine Anleitung Dir helfen konnte. Zur Info, die Buchstaben in MAC-Adressen gehen nur von a-f 🙂 Für das nächste mal 🙂

          Die Verzögerung kommt wohl daher, dass der Dash Button erstmal booten muss und sich in das WLAN verbindet – das scheint wohl etwas Zeit zu kosten.

          Beste Grüße
          Heiko

          • Antworten Wolfgang

            Hallo Heiko,

            nochmal ich – habe noch eine Frage…
            Wenn man einen weiteren Button verwenden will und damit einfach (per URL-Befehl) ein WLAN-Device starten oder stoppen möchte, was muß zusätzlich (natürlich die andere MAC-Adresse) in der trigger.py stehen und wie kann ich den Befehl absetzen (*.sh ???) oder??
            Danke vorab.

            Grüße aus Bayern
            Wolfgang

            • Heiko Böhme
              Antworten Heiko Böhme

              Hallo Wolfgang,
              angenommen du hättest jetzt drei Dash-Button, sähe der der Code wie folgt aus:

              from scapy.all import *
              import sys, os
              def arp_display(pkt):
                  if pkt.haslayer(DHCP):
                      if pkt[Ether].src == "ac:63:be:xx:xx:xx": #die MAC Adresse des Button mit Kleinbuchstaben!
                          #print (pkt[Ether].src)
                          os.system('node /home/pi/plug_switch.js')
                      elif pkt[Ether].src == "ac:64:be:xx:xx:xx": #die MAC des zweiten Button
                          os.system('sudo ./mache_irgendwas.sh')
                      elif pkt[Ether].src == "ac:65:be:xx:xx:xx": #die MAC des dritten Button
                          os.system('sudo python ./irgendein_python_script.py')
              print sniff(prn=arp_display, store=0,count=0)
              

              In dem Script kannst du auch gleich beliebige URL aufrufen: Ggf. hilft dir hier ( https://pythonprogramming.net/urllib-tutorial-python-3/ ) oder ( https://docs.python.org/3/library/http.client.html ) weiter

              Jetzt hängt es natürlich ganz davon ab, was du konkret im WLAN ansprechen willst. Ggf. hast du ja schon Frameworks im Einsatz, oder IFTTT ist möglich. Für die verschiedenen WLAN-Geräte gibt es ja auch verschiedene Implementierungen und eine generelle Empfehlung ist da schwierig. Die TP-Link HS 100 Steckdose spreche in in diesem Blogbeitrag ja auch über eine dedizierte API ( https://github.com/plasticrake/hs100-api.git ) an. Je nachdem, was du wie aufrufen willst, musst Du das in dem Python-Script in die if-elif Struktur einbauen.

              Ich hoffe, das hat Dir etwas geholfen?

              Beste Grüße
              Heiko

              • Antworten Wolfgang

                Hallo Heiko,

                vielen Dank für deine ausführliche Erklärung und die Geduld mit mir.
                Soweit ist mir das mit der trigger.py nun klar. 🙂

                In meinem privaten Netzwerk möchte ich damit gezielt Geräte ansteuern, deren Http-Adresse und URL-Befehle ich kenne, z.B um eine Gerät (hier eine Funksteckdose) EIN und auch wieder AUS zu schalten.
                EIN: http://192.168.xxx.xxx/connair/index.php?action=on&type=device&id=4
                AUS: http://192.168.xxx.xxx/connair/index.php?action=off&type=device&id=4

                Ich müsste den URL-Befehl also in ein Python-script einbauen. Ich denke, da keine Rückmeldung kommt oder sonstiger Status abgefragt wird, dass dann nur ein Befehl geht -> Button drücken -> Lampe an?!
                Kannst du mir zeigen wie das script hierzu aussehen würde?
                Und – Danke für die links, werde sie mir heute Abend oder am WE mal durchsehen – vielleicht versteh ich dann etwas mehr davon 😉
                Danke vorab

                Grüße
                Wolfgang

                • Heiko Böhme
                  Antworten Heiko Böhme

                  Hallo Wolfgang,
                  das sollte tatsächlich recht einfach sein:
                  Ich hab dir mal zwei Varianten (ungetestet) in das Script gepackt:
                  Variante 1: nutze zwei Button, Button 1 schaltet ein, Button 2 schaltet aus.

                  Variante 2: nutze nur einen Button -> schalte ein und lege eine Datei im aktuellen Ordner an (wenn die Datei da ist, weißt du, dass du da mal eingeschaltet hast (also so eine Art Statusdatei)) -> drücke den Button nochmal – existiert die Datei? -> Dann schalte aus und lösche die Datei.

                  from scapy.all import *
                  import sys, os
                  import urllib #für Variante 1
                  from pathlib import Path #für Variante 2
                  my_file = Path("./connair") #für Variante 2
                  
                  def arp_display(pkt):
                      if pkt.haslayer(DHCP):
                          if pkt[Ether].src == "ac:63:be:xx:xx:xx": #Variante 1 - immer anschalten
                              #print (pkt[Ether].src)
                              os.system('node /home/pi/plug_switch.js')
                              return urllib.urlopen('http://192.168.xxx.xxx/connair/index.php?action=on&amp;type=device&amp;id=4')
                          elif pkt[Ether].src == "ac:64:be:xx:xx:xx": #Variante 1 - immer ausschalten
                              os.system('sudo ./mache_irgendwas.sh')
                              urllib.urlopen('http://192.168.xxx.xxx/connair/index.php?action=off&amp;type=device&amp;id=4')
                          elif pkt[Ether].src == "ac:65:be:xx:xx:xx": #Variante 2- wenn Datei existiert: anschalten, sonst ausschalten
                              if my_file.exists():
                                  os.system('rm ./connair') #Datei löschen
                                  return urllib.urlopen('http://192.168.xxx.xxx/connair/index.php?action=on&amp;type=device&amp;id=4')
                               else:
                                  os.system('touch ./connair') #Datei anlegen
                                  return urllib.urlopen('http://192.168.xxx.xxx/connair/index.php?action=offn&amp;type=device&amp;id=4')
                                   
                                  
                  print sniff(prn=arp_display, store=0,count=0)
                  

                  Ich hoffe, das konnte dir etwas helfen – schwierig ist es immer, wenn man den aktuellen Status eines Aktors nicht abfragen kann und man sich mit so etwas behelfen muss. Wenn Du dann über einen anderen Weg (direkt im Browser .. ) schaltest, gerät das Script natürlich etwas außer tritt.

                  Beste Grüße
                  Heiko

                  • Antworten Wolfgang

                    Hallo Heiko,

                    vielen Dank für das Script. Habe es natürlich gleich ausprobiert (Variante 2 – da ich momentan nur einen Button habe). Dein Script sieht daher so aus:
                    ______________________________________________

                    from scapy.all import *
                    import sys, os
                    from pathlib import Path
                    my_file = Path("./connair")
                    
                    def arp_display(pkt):
                        if pkt.haslayer(DHCP):
                            if pkt[Ether].src == "50:f5:da:e9:cb:e7":
                                if my_file.exists():
                                    os.system('rm ./connair')
                                    return urllib.urlopen('http://192.168.xxx.xxx/connair/index.php?action=on&amp;type=device&amp;id=4')
                                elif my_file.exist():
                                     os.system('touch ./connair')
                                     return urllib.urlopen('http://192.168.xxx.xxx/connair/index.php?action=off&amp;type=device&amp;id=4')
                    
                    
                    print sniff(prn=arp_display, store=0,count=0)
                    

                    ________________________________________________

                    Leider gibts eine Fehlermeldung – siehe unten:
                    ________________________________________________
                    pi@HA-Bridge:~ $ sudo python /home/pi/trigger2.py
                    WARNING: No route found for IPv6 destination :: (no default route?)
                    Traceback (most recent call last):
                    File „/home/pi/trigger2.py“, line 3, in
                    from pathlib import Path
                    ImportError: No module named pathlib
                    ________________________________________________

                    Ich habe Python Version 2.7.9 aufm RasPi und Jessie Light ist up to date.
                    Habe nun Python 3.6.2 installiert, aber da gibts dann diese Meldung:

                    ________________________________________________
                    pi@HA-Bridge:~ $ sudo python3 /home/pi/trigger2.py
                    File „/home/pi/trigger2.py“, line 17
                    print sniff(prn=arp_display, store=0,count=0)
                    ^
                    SyntaxError: invalid syntax
                    ________________________________________________

                    Kannst du mir nochmals auf die Sprünge helfen.
                    Danke vorab.

                    Grüße
                    Wolfgang

                    • Heiko Böhme
                      Heiko Böhme

                      Guten Morgen,
                      python 2.7 ist schon ok – vor Ausführung des Scripts müsstest Du pathlib noch installieren.

                      sudo pip install pathlib
                      

                      Dann habe ich gerade noch gesehen, dass in Zeile 20 des Beispiels nicht elif sondern else stehen sollte – habe es in meinem Kommentarbeispiel noch angepasst – müsstest Du auch noch machen.

                      Das sollte dann schon helfen!
                      Beste Grüße
                      Heiko

                    • Wolfgang

                      Hallo Heiko,

                      das Ein-/Ausschalten mit 1 DashButton klappt nun einwandfrei. 🙂
                      Wenn der 2. Button da ist, teste ich mal beide mit 2 verschiedenen URL-Befehlen in der trigger.py und auch deine Variante 1!

                      Vielen Dank für deine freundliche Hilfe und Unterstützung.
                      Sollte ich aber – wider erwarten – Probleme haben, bin ich so frei und melde mich nochmals hier bei dir. 😉

                      Ich wünsche dir noch eine schöne Woche, hoffentlich mit mehr Sonnenschein als bei uns.
                      Hier regnet es seit gestern immer wieder …. bei tollen 15 Grad

                      Grüße
                      Wolfgang

  2. Antworten Tuncer

    Hallo, zuerst vielen Dank für das sehr gute Tutorial. Ich möchte gerne mit dem Raspberry Pi 1 (Model B) per WOL einen Rechner im gleichen Netzwerk mit einem Dash Button (JK29LP) starten. Der Mini-Rechner ist immer an. Leider kenne mich mit Python nicht so gut aus. Daher habe ich mich zum größten Teil an die Anletung gehalten, bis auf eine Ausnahme:

    from scapy.all import *
    import sys, os
    def arp_display(pkt):
        if pkt.haslayer(DHCP):
            if pkt[Ether].src == "ac:63:be:xx:xx:xx": #MAC wurde angepasst
                 os.system("node /home/pi/wol.js")
    print sniff(prn=arp_display, store=0,count=0)
    

    Damit wollte ich folgende Datei (wol.js) starten:

    wakeonlan ac:63:be:xx:xx:xx 
    'MAC wurde angepasst
    

    Leider passiert nach dem Drücken der Taste nichts. Sobald ich die wol.js manuell anstoße, fährt der entfernte Rechner hoch.

    Kannst du mir einen Tipp geben?

    • Heiko Böhme
      Antworten Heiko Böhme

      Hallo Tuncer,
      vielen Dank für deine Nachricht – ich versuche die heute Abend oder morgen eine Rückmeldung zu geben.
      Beste Grüße
      Heiko

    • Heiko Böhme
      Antworten Heiko Böhme

      Hallo Tuncer,
      füge doch mal zum Debuggen statt des WOL-Aufrufes ein

       print (&quot; Test 123 -Aufruf&quot;) 

      ein. So kannst der erstmal sehen, ob das Drücken des Buttons richtig abgefangen wird.
      Funktioniert das?
      Beste Grüße
      Heiko

      • Antworten Tuncer

        Hallo Heiko,

        vielen Dank für deine Rückmeldung.

        Ich konnte es in der Zwischenzeit lösen:

        import socket
        import struct
        import binascii
        import os
        import sys
        
        BUTTON = "MAC" # change this to your mac for the demo  ###MAC ohne Doppelpunkte und Kleinschreibung
        
        buttons = {}
        
        def add_handler(mac, handler):
            buttons[mac.replace(":", "")] = handler
        
        def listen():
            last_tid = {}
            rawSocket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0003))
            while True:
                packet = rawSocket.recvfrom(2048)
                ethernet_header = struct.unpack("!6s6s2s", packet[0][0:14])
                
                if ethernet_header[2] != 'x080':
                    continue # not ip
                
                ip_header = struct.unpack("!1s1s2s2s1s1s1s1s2s4s4s", packet[0][14:34])
                
                if ip_header[7] != 'x11':
                    continue # not udp
        
                if len(packet[0][42:]) &lt; 240:
                    continue # not dhcp
                
                dhcp_header = struct.unpack(&quot;!1s1s1s1s4s2s2s4s4s4s4s6s10s64s128s4s&quot;, packet[0][42:282])
        
                for b in buttons.keys():
                    if b in binascii.hexlify(ethernet_header[1]) and b in binascii.hexlify(dhcp_header[11]):
                        # filter duplicate presses
                        tid = binascii.hexlify(dhcp_header[4])
                        if b in last_tid and last_tid[b] == tid:
                            continue
                        last_tid[b] = tid
                        buttons[b](&quot;:&quot;.join([b[i:i+2] for i in range(0, len(b), 2)]))
        
        def demo_print(mac):
            print(&quot;%s pressed&quot; % (mac))
            os.system(&quot;sh wol.sh&quot;)  ###Was soll gestartet werden?
        
        if __name__ == &quot;__main__&quot;:
            add_handler(BUTTON, demo_print)
            listen()
        
        
  3. Antworten Christian

    Ich bin am verzweifeln. Bekomme folgenden Fehler:

    outsider2002@raspberrypi:~ $ node plug_switch2.js
    module.js:472
        throw err;
        ^
    
    Error: Cannot find module './hs100-api'
        at Function.Module._resolveFilename (module.js:470:15)
        at Function.Module._load (module.js:418:25)
        at Module.require (module.js:498:17)
        at require (internal/module.js:20:19)
        at Object. (/home/outsider2002/plug_switch2.js:1:80)
        at Module._compile (module.js:571:32)
        at Object.Module._extensions..js (module.js:580:10)
        at Module.load (module.js:488:32)
        at tryModuleLoad (module.js:447:12)
        at Function.Module._load (module.js:439:3) 

    Was mache ich falsch?
    Ist ein Raspberry PI Zero W mit Raspbian stretch. Image ist neu und aktuell.

    Habe genau nach anleitung gemacht.

    Hab hs100-api im rootverzeichniss, im home verzeichniss und im home/pi verzeichniss ausprobiert.
    Jedesmal der gleiche fehler.

    • Heiko Böhme
      Antworten Heiko Böhme

      Hallo Christian,
      ich hab den Ordner „hs-100-api“ unter /home/pi gelegt und rufe das trigger.py (bzw. du das plug_switch2.js) script auch aus dem Ordner /home/pi heraus auf.

      Befindest du dich in /home/pi beim Aufruf?
      Beste Grüße
      Heiko

      • Antworten Christian

        Hallo,

        ja, ich habe alles in /home/pi
        auch den ordner hs100-api habe ich in /home/pi

        hab auch den beiden dateien (trigger.py sowie plug_switch.js) chmod +x

        • Heiko Böhme
          Antworten Heiko Böhme

          Hallo Christian,
          hab mal geprüft – es gab eine Änderung in der API. Lösch mal den Order hs100-api
          Dann zieh dir bitte die alte Version, entpacke sie und benenn den Ordner um:

          cd /home/pi
          wget https://github.com/plasticrake/hs100-api/archive/v0.4.0.zip
          unzip v0.4.0.zip
          mv ./hs100-api-0.4.0 ./hs100-api 
          

          Das sollte erstmal auf die Schnelle helfen – die Anpassung an die aktuelle Version des API versuche ich in den nächsten Tagen in den Beitrag einzuarbeiten
          Beste Grüße
          Heiko

          • Antworten Christian

            vielen vielen Dank. Genau dies löst mein Problem. Einfach Top 😉

            Wie löse ich es jetzt am besten, das ich am Smartphone nicht immer diese Meldung bekomme das mein Dash Button fast fertig konfiguriert sei?
            Ich habe ihm jetzt einfach in der Fritzbox den Internetzugang gesperrt. Oder gibt es noch eine „elegantere“ Lösung?

            Euch ein schönes Wochenende.

            Und danke nochmals für diese tolle Anleitung

            • Heiko Böhme
              Antworten Heiko Böhme

              Hallo Christian,
              das Sperren in der Fritzbox ist schon genau richtig so – es gäbe auch andere Lösungen aber die sind alle wesentlich aufwändiger..
              (Routing, Firewall, Proxy, Content / Reputationsfilter … )
              Beste Grüße
              Heiko

  4. Antworten Maxime

    Hi,
    ich krieg auf Teufel komm raus Scapy auf meinem Raspberry Pi nicht zum laufen.
    Ich bekomme in verschiedenen python-Versionen verschiedene Fehler ausgeworfen.
    Bei python ./script.py
    NameError: name 'arp_display' is not defined
    Bei /usr/bin/python3.5 ./script.py
    SyntaxError: invalid syntax mit Pfeil auf „sniff“.

    Bin neu unter Linux und Python…

    from scapy.all import *
    import sys, os
    def arp_display(pkt):
        if pkt.haslayer(DHCP):
            if pkt[Ether].src == "ac:63:be:xx:xx:xx": #die MAC Adresse des Button mit Kleinbuchstaben!
                #print (pkt[Ether].src)
                os.system("node /home/pi/plug_switch.js")
    print sniff(prn=arp_display, store=0,count=0)
    
  5. Antworten Sven

    Hey Heiko,
    ich habe ein grundsätzliches Problem mit dem Dash Button.

    Ich nutze einen Raspi (allererste Generation), soweit läuft alles auch ganz gut. Ich drücke den Dash Button und manchmal gehen meine Philips Hue Birnen auch an.

    Weiterhin nutze ich auf dem Raspi die ARP-Sniff Methode per Scapy. Hier ist mir bei einer Analyse aufgefallen, dass mein Dash Button oftmals (aber unregelmäßig) zwei Anfragen direkt hintereinander ins Netzwerk sendet. Somit toggelt das Script kurz die Birne an und danach sofort wieder aus.

    Habt ihr eine Idee, wieso der Dash Button das macht? Habt ihr auch das „Problem“? Vielleicht sogar eine Idee, wie man das umgehen kann?

    Vielen Dank für Eure Hilfe
    Sven

    • Heiko Böhme
      Antworten Heiko Böhme

      Hallo Sven,
      leider kann ich dir nicht sagen, war dein Dash-Button mehrere Anfragen sendet. Um das Problem zu umgehen, könnte man es Softwareseitig „entprellen“ siehe dazu: https://de.wikipedia.org/wiki/Prellen
      dazu würde ich in dem Python-Script mir nach dem Aufruf einen Zeitstempel merken lastToggel oder so ähnlich und nur wenn der aktuelle Aufruf mindestens X (milli)Sekunden nach dem letzten gemerkten liegt, den Schaltvorgang auslösen lassen. (und dann wieder den aktuellen Zeitstempel merken lassen)

      Hilft dir das soweit erstmal?
      Beste Grüße
      Heiko

  6. Antworten Martin

    Hallo Heiko,

    habe zu meinem Anliegen keine Antwort im Internet gefunden. Vielleicht kannst du ja helfen.

    Wenn das python-Script rund um die Uhr läuft, ist das nicht mit Kanonen auf Spatzen geschossen, wenn ich das „nur“ für einen Lichtschalter nutzen will?

    Wie sieht es mit der Arbeitsspeicher- und Prozessorauslastung und Behinderung eventueller anderer Programme aus? Habe Apache laufen und nutze das auch mal zur Videoüberwachung oder als Baby phone und zur Temperatur-/Luftfeuchtigkeits-Aufzeichnung.

    Viele Grüße
    Martin

    • Heiko
      Antworten Heiko

      Hallo Martin,
      deine Überlegung ist völlig richtig – jedoch ist die Challenge ja nicht den Schalter zu schalten sondern den Netzwerkverkehr zu überwachen. Das Schalten wird ja nur bei Bedarf ausgeführt, die Netzwerküberwachung muss permanent für jedes Paket durchgeführt werden. Konkrete Werte für den zusätzlichen overhead, der entsteht, kann ich dir ad hoc nicht nennen. Ggf. magst du das selbst mal prüfen und hier posten? Interessant wäre tatsächlich mal zu wissen, welche CPU-Zeiten verbraucht werden o.ä. und ob andere konkurrierende Prozesse noch performant laufen.

      Beste Grüße
      Heiko

  7. Antworten Martin

    Hallo Heiko,

    noch eine Frage: beim Rebooten wird der cron job manchmal nicht erfolgreich durchgeführt. Dazu habe ich mir ein log file erstellen lassen und folgende Fehlermeldung ist enthalten:
    „IndexError: Layer [ARP] not found“

    Das ist der Grund, warum das script manchmal beim AUfruf abstürzt.

    Hast du eine Idee, wie man das beheben kann?

    Danke und Grüße
    Martin

    • Heiko
      Antworten Heiko

      Hallo Martin,
      ein spannender Ansatz, kannst du hier posten, wie du die Scripte für das Logging erweitert hast?
      Mir ist das persönlich noch nicht aufgefallen aber ich würde es mir gern mal ansehen.
      Beste Grüße
      Heiko

      • Antworten Martin

        Hallo Heiko,

        das Logging findet im crontab selbst statt:

        @reboot sudo python /home/pi/amazon.py >> /home/pi/amazon.log 2>&1

        Viele Grüße
        Martin

Hinterlasse eine Antwort

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

Translate »