Problem mit versenden von UDP Paketen

Begonnen von TheMason76, 12 Juni 2016, 14:45:26

Vorheriges Thema - Nächstes Thema

TheMason76

So ...

Erstmal danke für die vielen Tipps und Hints.
Nach viel Versucherei hab ich es bei der Shell aufgegeben.
Ich nutze da eigentlich immer die Backticks, also { `bla bla` ;; } in der
Kommandozeile im Browser. Egal wie ich es angestellt habt. Geht nicht.
Ich habe zwischenzeitlich mal auf nem BananaPi ausprobiert, ebenfalls Fehlanzeige.
Letzenendes hab ich dann an eine kleine Perl-Routine zusammengeschnipselt
und das läuft nun. Hier mein zusammengekopiertes Code-Schnipsel.  ;D 8)

sub SendUDP (@) {

  my $FileName = $_[0];
  my $IP_Address = $_[1];
  my $IP_Port = $_ [2];
  my $AnzahlBytes = -s $FileName;
  my $Speicher;
  my ($socket,$client_socket);
 
  open(FILE, "<", $FileName) or die("File not found $!");
  binmode(FILE);
  my $geleseneBytes = read(FILE, $Speicher, $AnzahlBytes);
  close(FILE);

  $socket = new IO::Socket::INET (
    PeerHost => $IP_Address,
    PeerPort => $IP_Port,
    Proto => 'udp',
  ) or die "ERROR in Socket Creation : $!\n";
  $socket->send($Speicher);
  $socket->close();

}

rudolfkoenig

Achtung an Kopierer: der Funktionsaufruf die() ist generell keine gute Idee in FHEM-Funktionen.

Otto123

Auch wenn Deine Funktion jetzt gelöst ist würde ich an Deiner Stelle noch schauen warum so etwas wie { ` touch /opt/fhem/FHEM/tester.txt`;; } nicht geht. Das muss gehen und irgendeine Ursache in Deiner Installation haben!

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

Civicoid

Hallo TheMason76,

kannst du mir eine kleine Anleitung zum Mitschneiden der Pakete zum Steuern der Steckdosen geben.
Ich stehe zZ vor dem gleichen Problem.

mfg
Mike
Fhem v5.9 @ MS-7877 Board mit J1900 als Server
mit Ubuntu 18.04.1 LTS, Nginx, Php7, TabletUI, Framework7, MQTT, JeelinkClone, Sduino, nanoCUL, maxCube, Synology-NAS
---
Sensoren/Aktoren:
EdiPlug, LaCrosse-Sensoren, MAX! Thermostate und Fensterkonakte, Alexa

TheMason76

Hallo Civioid,

kann ich gerne machen. Kann wohl vllt noch 1-2 Tage dauern. Weiß noch nicht genau wann ich dazu komme.

Gruß
Rene

Civicoid

Das klingt doch super ...
... bin schon gespannt wie ein Flitzebogen :D :D
Fhem v5.9 @ MS-7877 Board mit J1900 als Server
mit Ubuntu 18.04.1 LTS, Nginx, Php7, TabletUI, Framework7, MQTT, JeelinkClone, Sduino, nanoCUL, maxCube, Synology-NAS
---
Sensoren/Aktoren:
EdiPlug, LaCrosse-Sensoren, MAX! Thermostate und Fensterkonakte, Alexa

TheMason76

#21
Hi Civicoid,

sry, bin erst jetzt dazu gekommen zu Antworten ....
Aaaalso ...

Ich hab das so gemacht. Zu den Broadlink Steckdosen gibt es die App "e-control". Mit der werden die Steckdosen ja gesteuert. Ich habe um die Pakete mitsniffen zu können mir die App "Pocket Capture" installiert.

Zuerst startest du die e-control App und gehst auf die Steckdose die du schalten willst. Dann startest du den Pocket Sniffer und kannst über das "Play" Symbol das sniffen starten. Dann gehst du wieder auf die "e-control" App, schaltest die Steckdose 2 mal an und aus (um nachher die Pakete einfacher zu finden), gehst dann wieder in den "Pocket Capture" und stoppst über das "Stop" Symbol das sniffen. Mit jedem Start/Stop macht Pocket Control eine neue Session bzw einen neuen Eintrag mit Datum/Uhrzeit.
Wenn du auf diesen Eintrag gehst siehst du alle Pakete die das Handy in der Zeit so rausschubst. Du suchst dann in dem Eintrag nach UDP Paketen mit der länge 176 Byte und Port 80. das sind (höchstwahrscheinlich) die Pakete die an die Steckdose gehen. Wichtig ist dabei das du dir die IP Adresse in dem Lokalen Netzwerk merkst.

Wenn du auf die UDP Pakete drückst, siehst du den ausgehenden Traffic und die eingehende Antwort dazu. Diese sind in Summe 176 Byte. Das (interessante) ausgehende Paket hat immer 72 Byte. Du speicherst nun den "Upload" über "Save upstream" (also das was vom Handy zur Steckdose geht) und speicherst es auf deinem Handy ab. (gut merken wo man es gespeichert hat und an welche IP Adresse im lokalen Netzwerk das Paket geschickt worden ist).

Am besten gibst du dem auch direkt "sprechende namen" also z.b. steckdose_kaffemaschine_104_0x ... da du nicht direkt weißt ob das das Paket fürs einschalten oder ausschalten ist, am besten einfach mit fortlaufender Nummer und IP Adresse speichern. Als nächstes mußt du die gespeicherten Upload Pakete irgendwie auf deinen Rechner (oder direkt den Raspberry oder welches System auch immer du nutzt) kopieren (Ich habs mit der Total Commander- und Filemanager-App gemacht).
Ich hab bei mir zuerst auf den Laptop gespeichert und bin unter Ubuntu hingegangen und habe die Pakete per "cat steckdose_xxx > /dev/udp/192.168.xxx.xxx/80"  an die entsprechende Steckdose gesendet und konnte dann auch herausfinden welche der laufenden nummern für ein und ausschalten zuständig war und habe diese dann umbenannt.

Wichtig ist auf jeden Fall das du dir die IP adresse merkst da in den Paketen wohl noch etwas "versteckt" ist was verhindert das du ein Paket was für eine bestimmte Steckdose (also mit einer bestimmten IP Adresse) ist, an eine andere schickst. Sprich : Du musst das gezumpel für jede Steckdose einzeln machen und dir merken an welche IP Adresse das ging. Ich bin nachher hingegangen und habe schon beim Abspeichern die IP-Adresse (in meinem Subnetz) im Namen drin gehabt. Also z.b. Steckdose_104_01 für das erste Paket was an die Steckdose 192.168.2.104 ging.

Durch das versenden der Pakete unter Ubuntu konnte ich dann sehen ob _01 die Steckdose ein oder ausgeschaltet hat und habe die Dateien dann umbenannt in "steckdose_104_an" und "steckdose_104_aus". Jede Datei ist bei mir 72 Byte groß (die 176 Byte die ich oben erwähnt habe kommen vom gesamten Traffic, also eingehend und ausgehend).

Mit diesen zwei Dateien pro Steckdose (die ich dann auf den Raspberry kopiert habe) brauchte ich dann nur das kleine Perl Snippet und konnte die Dateien direkt an die Steckdose senden. Praktisch ist wenn man die IP Adresse direkt im Dateinamen mitspeichert, dann kann man sich über die Perl Routine den passenden Dateinamen und die dazugehörige IP Adresse direkt zusammenbauen. Also steckdose_104_an an 192.168.2.104 verschicken.

Hoffe ich habe das halbwegs verständlich erklärt. Wenn du noch fragen hast ... feel free ... :-)

TheMason76

@rudolfkoenig

Ach ja .. jetzt wo ich es sehe ... das "or die" ist ja in "normalen" Perlprorgammen bzw Perlsnippets ja so "üblich" (zumindest exemplarisch). Aber was wäre unter Fhem der beste Weg bzw sinnvollste ? Ein "or die" ist ja schon ziemlich bruteral, aber wie gesagt bin was Perl angeht ein ziemlicher newbie. Komme aus der C Welt und hätte jetzt eine endlos verschachtelte if () { } else { } Anweisung daraus gebastelt. Ist das unter Perl praktikabel oder was bzw wie fängt man die Fehlerfälle am sinnvollsten ab ?

rudolfkoenig

@TheMason76: die() ist normal in perl Programmen, die nicht als daemon laufen. die() ist auch deswegen doof, weil es direkt auf STDERR schreibt, was dann ungefiltert im FHEM-Log landet. Loesung fuer FHEM: alles, was die() verwendet, mit eval ausfuehren, auf $@ pruefen, es per Log/Log3 melden, und passenden return generieren.

Du kannst in perl auch endlos lange if-elsif-else Kaskaden bauen, aber wenn elsif mehr als 3-mal vorkommt, dann ziehe ich andere Kostrukte vor, wie Programmcode in Liste oder Hash was per eval ausgefuehrt wird. Ich wandele damit Code in Daten um, wie das am Anfang von 10_ZWave.pm in %zwave_class zu sehen ist.

Achtung: ich bin kein perl-Papst, ich verwende nur perl seit mehreren Jahren.

P.S.: ab und zu ein return erleichtert das Lesen. Deinen bestimmt lesenswerten Beitrag habe ich deshalb bei der Haelfte abgebrochen.

TheMason76

#24
Danke für die Perl-Tips. Werds mal wenn ich mich wieder mit Perl befasse beherzigen :-)
Aber stimmt ... jetzt wo du es sagst hätten ein oder zwei Return nicht geschadet. Ich hols mal ganz fix nach. War schon was spät gestern Abend :-)

Edit : habs mal "entzerrt". Schaut direkt besser aus :-) Danke noch

Civicoid

@TheMason76

Danke für deine umfangreiche Anleitung. Leider befindet sich zZ kein Android-Gerät in meiner Reichweite um die von die beschriebene App zu testen. Wir sind im Haushalt eher mit angebissenen Äpfeln unterwegs. :-)
Um an die Pakete zu kommen habe ich jetzt mit Wireshark etwas mitsniffen können. Hierbei werden kontinuierlich Pakete von ~90Byte gesendet.
Im Falle eines Schaltzustandwechseln laufen vier Pakete ein. Diese wollte ich nun von einem im Netzwerk befindlichen Raspi schicken.
Wenn ich den Befehl
sudo cat /opt/fhem/FHEM/steckdose_an.pcap > /dev/udp/192.168.xxx.xxx/80
absende passiert leider noch nichts.
Weißt du, ob ich beim Raspi noch etwas nachinstallieren muss, um UDP-Pakete über den Befehl zu versenden.
In meinem /dev-Ordner gibt es nämlich kein /udp.
Fhem v5.9 @ MS-7877 Board mit J1900 als Server
mit Ubuntu 18.04.1 LTS, Nginx, Php7, TabletUI, Framework7, MQTT, JeelinkClone, Sduino, nanoCUL, maxCube, Synology-NAS
---
Sensoren/Aktoren:
EdiPlug, LaCrosse-Sensoren, MAX! Thermostate und Fensterkonakte, Alexa

TheMason76

#26
Hallo Civicoid,

hast du mal versucht die Pakete von deinem angeknabbertem Apfel einfach zurückzuschicken um sicher zu gehen das die Steckdose sich so überhaupt ansprechen lässt ? Hast du denn auch die Steckdosen von Broadlink ?
Mir kommt das komisch vor das permanent etwas gesendet wird. Alelrdings weiß ich auch nicht mit welchem Programm du das machst. Vllt das die Steckdosen sich dann auch anders angesteuert werden. Das UDP-Paket hab ich einfach mal als "gottgegeben" hingenommen. So richtig was an "Systematik" konnte ich den Daten nicht entnehmen, selbst wenn es "nur" 20-30 Bytes waren die sich jeweils verändert haben. Hab mir aber auch nicht weiter MAC Adresse und dergleichen angeschaut oder versucht da "rauszuinterpretieren".
Einfach gesnifft, gespeichert und rausgeschubst :-) Bei dem Android Handy von meinem Papa wurden z.b. auch ganz andere IP Adressen "verwendet" die mal so gar nicht mit 192.168.x.x übereingestimmt haben. Bin was das analysieren bzw "reverseengineeren" von Datenpaketen angeht bin ich leider kein Experte.

Das Problem mit dem fehlenden UDP-"Verzeichnis" hatte ich bei einem Raspberry (ich glaub ein Raspi Pi 3) auch. Daher das Perl-Skript. Mit /dev/udp/.... hab ich das auf nem BananaPi, nem OrangePI und unter Ubuntu getestet.

Wernieman

Was sind es denn für IP-Adressen?

Am optimalsten fürs Reverse-Engenieren wäre es, wenn Du die Steckdosen hinter einem Linux-Router packn könntest. Dann hättest Du die beste Möglichkeit, die entsprechenden Packete mitzuschneiden.
- Bitte um Input für Output
- When there is a Shell, there is a Way
- Wann war Dein letztes Backup?

Wie man Fragen stellt: https://tty1.net/smart-questions_de.html

Civicoid

#28
Hallo,

leider komme ich erst jetzt dazu euch zu antworten.
Die Lösung mit meinen Apfel-Geräten war eher weniger zufriendenstellend.
Schlussendlich habe ich ein GalaxyTab als zukünftige Komandozentrale günstig ersteigert.

Aber hier meine funktionierende Lösung:

1. Pakete per "Packet Capture" mitsniffen, speichern und auf den FHEM-Server packen
> bei mir heißen die Pakete 1on.pak und 1off.pak und liegen testweise im /root

2. Fhem den sudoers hinzufügen
> /etc/sudoers
fhem ALL=(ALL) NOPASSWD: ALL

3. zwei Dateien anlegen
1on.sh
#!/bin/bash

echo "Steckdose 1 an"
cat /root/1on.pak > /dev/udp/192.168.2.x/80

und 1off.sh
#!/bin/bash

echo "Steckdose 1 aus"
cat /root/1off.pak > /dev/udp/192.168.2.x/80


und mit

chmod +x 1on.sh
chmod +x 1off.sh

ausführbar machen

4. in FHEM
define LEDLicht dummy
attr LEDLicht setList on off
define LEDLichtAn notify LEDLicht:on "sudo /root/1on.sh&"
define LEDLichtAus notify LEDLicht:off "sudo /root/1off.sh&"


und was soll ich sagen, bei mir schaltet es auf einmal die Steckdosen wie gewolt :-)

PS:
Nun fehlt nur noch der automatische Statuswechsel  wenn ein anderer Teilnehmer schaltet :-[

EDIT:
- Entschuldigung für diese Majestätsbeleidigung. Änderungen werde ich testen und umgehend anpassen. Danke!
-- getestet, funktioniert, geändert
- Die *.sh müssen noch ausführbar sein
Fhem v5.9 @ MS-7877 Board mit J1900 als Server
mit Ubuntu 18.04.1 LTS, Nginx, Php7, TabletUI, Framework7, MQTT, JeelinkClone, Sduino, nanoCUL, maxCube, Synology-NAS
---
Sensoren/Aktoren:
EdiPlug, LaCrosse-Sensoren, MAX! Thermostate und Fensterkonakte, Alexa

rudolfkoenig

Fuer die Nachahmer: bitte statt {system("bla&");;} einfach nur "bla" verwenden, sonst bin ich traurig, dass der fuer diesen Zweck extra seit 10 Jahren in FHEM eingebaute Code von keinem verwendet wird. Von commandref.html nicht zu lesen will ich gar nicht reden.