Hallo und erstmal frohe Ostern,
da ich keine Fritzbox habe sondern einen DRAYTEK Router versuche ich ich mir ein Presence Modul zu basteln. Ich dachte mir ich lese per Telnet die DHCP Tabelle des Draytek aus und schreibe diese in eine Datei.
Jetzt kommt aber wieder das Problem was ich immer hab weil ich es einfach nicht kapiere wies es geht. Wie kann ich aus dieser Datei jetzt die MAC Adressen einzeln auslesen um sie dann in einen Dummy als Reading zu schreiben damit es so wie bei der Fritzbox wäre?
Hier mal der Inhalt der Datei (nicht wundern hab die HOST ID rausgenommen und die IP Adressen etwas geändert):
Trying 192.168.xx.xx...
Connected to 192.168.xx.xx.
Escape character is '^]'.
Account:*******
^MPassword: *****
User login successful, expired time is "Unlimited".
^MType ? for command help
^MGroejNet-Berlin> srv dhcp status lan1
^MLAN1 : DHCP Server On IP Pool: 192.168.xx.xx ~ 192.168.xx.xx
^M Default Gateway: 192.168.xx.xx
^M--------------------------------------------------------------------------------
^MIndex IP Address MAC Address Leased Time HOST ID
^M--------------------------------------------------------------------------------
^M1 192.168.xx.xx 88-71-E5-FB-E7-04 22:43:48
^M2 192.168.xx.xx F0-81-73-EA-FB-8E 20:56:49
^M3 192.168.xx.xx A0-02-DC-EA-27-B5 21:52:46
^M4 192.168.xx.xx A0-20-A6-19-AC-0E 23:22:13
^M5 192.168.xx.xx 60-01-94-55-F7-8D 21:02:41
^M6 192.168.xx.xx EC-10-7B-0F-47-9B 23:22:43
^M7 192.168.xx.xx F8-B1-56-AF-25-C6 20:23:14
^M8 192.168.xx.xx C4-73-1E-D5-8F-C9 22:31:57
^M9 192.168.xx.xx D8-49-2F-39-2B-32 23:53:44
^M10 192.168.xx.xx 60-01-94-14-E1-7A 23:58:42
^M11 192.168.xx.xx 2C-3A-E8-31-57-46 21:02:41
^MGroejNet-Berlin> exit
Danke für Eure Hilfe.
Gruß
Jörg
Wieso willst du das in eine Datei schreiben und dann von FHEM die Datei auslesen?
Lass dich fhem die Daten direkt per telnet holen. Schau Dir das Fritzbox Modul an, da sollten noch Teile vom telnet Code vorhanden sein.
Hallo CoolTux,
danke für den Tipp aber da muß ich ja dann auch irgendwie die MAC Adressen einzeln auslesen und das ist bestimmt anders als bei der FritzBox. Ich schau mir das aber erstmal an.
Gruß
Jörg
Hallo Jörg
Wieso einzeln, du hast doch oben auch nur einen telnet Befehl eingegeben und somit die Liste bekommen.
srv dhcp status lan1
Nichts anderes sollte der telnet Befehl aus FHEM heraus abgesetzt machen. Musst halt ne 99_myUtils schreiben wo Du dann in einer Sub die telnet Anmeldung und ausführen des Befehles machst.
Grüße
Wo ist das Problem?
Den Dateiinhalt mit FileRead() einlesen, dann liegen alle Zeilen in einem Array vor und lassen sich auf einfachste Weise in FHEM weiterverarbeiten.
Das Problem ist der Unsinn des doppelten Abarbeiten. Einmal Daten holen und in Datei schreiben und dann auslesen und in FHEM verarbeiten.
Und genau das Array einlesen begreife ich immer nicht. :(
Zitat von: CoolTux am 31 März 2018, 17:08:18
Das Problem ist der Unsinn des doppelten Abarbeiten.
Das ist kein Unsinn, sondern erspart eine Menge möglicher Problemfälle und Störfaktoren.
Moin,
nu mal nicht streiten :). Ich formuliere meine Fragestellung mal um.
Wie bekomme ich aus der Datei die MAC Adressen ausgelesen und in einen Dummy geschrieben?
Ein Bespiel ist im ersten Beitrag bei dem Thema zu sehen.
Schönen Ostersonntag Euch allen hier.
Gruß
Jörg
Hallo Jörg
Das hatte Udo ja bereits geschrieben.
Suche Mal hier nach FileRead()
https://wiki.fhem.de/wiki/DevelopmentModuleAPI
Hallo,
alles klar da muß ich mich mal in Ruhe mit beschäftigen. Sieht heftig aus für mich als blutiger Anfänger in Programmierung in Perl. Mach zwar ein wegen mit Arduino und Co was aber ich wurstel mich da schon irgendwie durch.
Lese ich das gerade richtig das es dann Zeilenweise ausgegeben wird? Also muß ich ja aus jeder Zeile ja noch die MAC Adresse extrahieren.
Danke
Gruß
Jörg
Zitat von: Groej am 01 April 2018, 10:11:02
Hallo,
alles klar da muß ich mich mal in Ruhe mit beschäftigen. Sieht heftig aus für mich als blutiger Anfänger in Programmierung in Perl. Mach zwar ein wegen mit Arduino und Co was aber ich wurstel mich da schon irgendwie durch.
Lese ich das gerade richtig das es dann Zeilenweise ausgegeben wird? Also muß ich ja aus jeder Zeile ja noch die MAC Adresse extrahieren.
Danke
Gruß
Jörg
Ja das musst Du machen. Entweder RegEx verwenden oder versuchen mit split das hinzu biegen.
So hat mir keine Ruhe gelassen :).
Soweit hab ich das schon mal hingebkommen (siehe Bild). Jetzt muß ich ja quasi vom ersten bis zum zweiten TAB auslesen bzw. Leerzeichen.
Am besten ist Du gibst hier mal Deinen Code in Codetags ein und wir schauen.
Auf den ersten Blick würde ich ja sagen Du hast was Du wolltest ;D Aber ich gehe mal davon aus das Du nur die Mac Adressen haben willst, richtig. Da wäre vielleicht etwas Rohdaten nicht schlecht. Also wie stehen die Daten dann im Array zur Verfügung. Kannst die Daten auch gerne verfälschen, bitte nur nicht die Struktur ändern.
Also der Inhalt der Datei steht ja ganz oben im Thema. Hab da nur die IP Adressen geändert und die HOST ID rausgelöscht. Ja brauch nur die MAC Adressen und sonst nichts.
Blöde Frage was ist CODETAGS?
Das ist ne Formatierung im Forum.
Das was Du oben schon mit Deiner Datei gemacht hast.
Sicher das das der Inhalt der Datei ist. Sieht eher nach einer Konsolenausgabe aus
Trying 192.168.xx.xx...
Connected to 192.168.xx.xx.
Escape character is '^]'.
Account:*******
^MPassword: *****
User login successful, expired time is "Unlimited".
^MType ? for command help
^MGroejNet-Berlin> srv dhcp status lan1
^MLAN1 : DHCP Server On IP Pool: 192.168.xx.xx ~ 192.168.xx.xx
^M Default Gateway: 192.168.xx.xx
^M--------------------------------------------------------------------------------
^MIndex IP Address MAC Address Leased Time HOST ID
^M--------------------------------------------------------------------------------
^M1 192.168.xx.xx 88-71-E5-FB-E7-04 22:43:48
^M2 192.168.xx.xx F0-81-73-EA-FB-8E 20:56:49
^M3 192.168.xx.xx A0-02-DC-EA-27-B5 21:52:46
^M4 192.168.xx.xx A0-20-A6-19-AC-0E 23:22:13
^M5 192.168.xx.xx 60-01-94-55-F7-8D 21:02:41
^M6 192.168.xx.xx EC-10-7B-0F-47-9B 23:22:43
^M7 192.168.xx.xx F8-B1-56-AF-25-C6 20:23:14
^M8 192.168.xx.xx C4-73-1E-D5-8F-C9 22:31:57
^M9 192.168.xx.xx D8-49-2F-39-2B-32 23:53:44
^M10 192.168.xx.xx 60-01-94-14-E1-7A 23:58:42
^M11 192.168.xx.xx 2C-3A-E8-31-57-46 21:02:41
^MGroejNet-Berlin> exit
Ist es auch die in eine Datei geschrieben wurde.
Ah okay. Jetzt noch der Code bitte
Hatte es nur schnell in der Befehlzeile getestet hiermit:
{ open FILE, "/home/pi/draytekdhcp.log" or die "Couldn't open file: $!";; while (<FILE>){ $_ =~ /(.+?):(.+)/;; fhem("setreading dummy $1 $2") } close FILE }
Hatte ich hier im Forum gefunden vorhin ;)
Zitat von: Groej am 01 April 2018, 11:09:12
Hatte es nur schnell in der Befehlzeile getestet hiermit:
{ open FILE, "/home/pi/draytekdhcp.log" or die "Couldn't open file: $!";; while (<FILE>){ $_ =~ /(.+?):(.+)/;; fhem("setreading dummy $1 $2") } close FILE }
Hatte ich hier im Forum gefunden vorhin ;)
Ach so. Da habe ich keine Ahnung von. Dachte du hast ne vernünftige Sub in einer myUtils gemacht und Mit FileRead() das ganze ausgelesen.
Ich mach dann mal Ostern.
Bis die Tage
Zitat von: Groej am 01 April 2018, 11:09:12
Hatte es nur schnell in der Befehlzeile getestet hiermit:
Hatte ich hier im Forum gefunden vorhin ;)
Und hast Du das einfach nur kopiert oder hast Du wenigstens verstanden, was Du da tust?
So halbwegs. Ich sagte ja ich kappier das mit den Array auslesen nicht. Also das die Datei geöffnet wird und eine Schleife läuft bis die Datei durch ist und dann die Datei geschlossen wird ist klar. Dabei werden dann die Readings in den Test Dummy geschrieben.
Aber das hier versteh ich nicht: $_ =~ /(.+?):(.+)/
Damit wird ja gesagt wie und was er auslesen soll.
So ich hab schon mal das Script gebastelt was die Daten vom Router holt.
Jetzt ist nur die Frage in eine Datei schreiben und dann die MAC Adressen irgendwie auslesen oder in einen Rutsch die MAC Adressen auslesen und in einen FHEM Dummy schreiben als Reading?
Egal wie, die Frage ist wie man das macht. Da brauch ich wirklich Hilfe.
Wie gesagt da hab ich keine Peilung von. Googel aber fleißig weiter. Vielleicht komm ich ja auch selber drauf.
Script:
#!/usr/bin/perl
use warnings;
use Net::Telnet ();
print "Begin\n";
$remote = new Net::Telnet (Timeout => 10,Errmode=>'die');
$remote->open("192.168.xx.xx");
print "connect\n";
$remote->waitfor('/Account:$/i');
$remote->print("xxxx") or die $remote->errmsg;
$remote->waitfor('/Password: $/i');
$remote->print("xxxx") or die $remote->errmsg;
print "logged in\n";
$remote->waitfor('/GroejNet-Berlin> $/');
print "vor Ausgabe\n";
@output = $remote->cmd("srv dhcp status lan1");
#$remote->waitfor('/^MGroejNet-Berlin>$/');
print @output;
$remote->close;
Ausgabe:
LAN1 : DHCP Server On IP Pool: 192.168.10.50 ~ 192.168.10.78
Default Gateway: 192.168.10.1
--------------------------------------------------------------------------------
Index IP Address MAC Address Leased Time HOST ID
--------------------------------------------------------------------------------
1 192.168.xx.xx DC-4F-22-11-77-17 22:15:10 yyyyyyyyyyyyyyyy
2 192.168.xx.xx F0-81-73-EA-FB-8E 19:00:03 yyyyyyyyyyyyyyyy
3 192.168.xx.xx A0-02-DC-EA-27-B5 17:15:05 yyyyyyyyyyyyyyyy
4 192.168.xx.xx A0-20-A6-19-AC-0E 14:40:05 yyyyyyyyyyyyyyyy
5 192.168.xx.xx 60-01-94-55-F7-8D 18:45:59 yyyyyyyyyyyyyyyy
6 192.168.xx.xx EC-10-7B-0F-47-9B 22:10:24 yyyyyyyyyyyyyyyy
7 192.168.xx.xx D8-49-2F-39-2B-32 12:49:47
8 192.168.xx.xx 2C-3A-E8-31-57-46 18:43:07 yyyyyyyyyyyyyyyy
9 192.168.xx.xx 88-30-8A-EC-C9-CD 16:07:17 yyyyyyyyyyyyyyyy
Natürlich kann die Ausgabe länger oder kürzer sein je nach dem wieviele Geräte sich per DHCP eine Adresse geholt haben.
Meine persönliche Meinung kennst Du ja, ich würde das gleich verarbeiten.
Willst Du ausschließlich die MAC Adressen ohne jeglichen anderen Bezug?
Ich würde den Text
- über FileRead() in ein Array einlesen
- über das array loopen und in der Schleife
- jede Zeilen mit split anhand des Leerzeichens zerlegen
- eine Zeile nur dann verarbeiten, wenn das zweite Element 192.168. enthält
Funktionsprinzip:
my ($err,@inhalt) = FileRead(...);
foreach my $zeile (@inhalt){
my @z = split("[ \t]+",$zeile);
next unless($z[1] ~= m/192\.168\./);
# ab hier erfolgt das Verarbeiten der "gültigen" Zeilen
# in $z[1] steht die IP, in $z[2] steht die MAC usw.
}
Hallo,
danke für die weitere Hilfe.
ich hab das ganze jetzt mit meinem kleinen vorhandenen Wissen gemacht und es auf der Linux Ebene vom Raspi gemacht zum Testen mit folgenden Code:
#!/usr/bin/perl
use warnings;
use Net::Telnet ();
$remote = new Net::Telnet (Timeout => 10,Errmode=>'die');
$remote->open("192.168.10.1");
print "connect\n";
print "\n";
$remote->waitfor('/Account:$/i');
$remote->print("xxxx") or die $remote->errmsg;
$remote->waitfor('/Password: $/i');
$remote->print("xxxx") or die $remote->errmsg;
print "logged in\n";
$remote->waitfor('/GroejNet-Berlin> $/');
@output = $remote->cmd("srv dhcp status lan1");
#print @output;
#$data = $remote->cmd("srv dhcp status lan1");
$remote->close;
print "\n";
foreach my $zeile (@output){
my @z = split("[ \t]+",$zeile);
next unless($z[1] =~ m/192\.168\./);
# ab hier erfolgt das Verarbeiten der "gültigen" Zeilen
# in $z[1] steht die IP, in $z[2] steht die MAC usw.
print "mac_$z[2] $z[4]\n";
}
und bekomm dann folgendes raus:
connect
logged in
Use of uninitialized value $z[1] in pattern match (m//) at test.pl line 24.
Use of uninitialized value $z[1] in pattern match (m//) at test.pl line 24.
mac_EC-10-7B-0F-47-9B Galaxy-A3-2017
mac_F0-81-73-EA-FB-8E amazon-f5eccfdce
mac_DC-4F-22-11-77-17 Zaehler4OG0
mac_88-71-E5-FB-E7-04 amazon-ceabd40d8
mac_A0-02-DC-EA-27-B5 amazon-c8585ce31
mac_A0-20-A6-19-AC-0E FHEM-Status1
mac_D8-49-2F-39-2B-32
mac_88-30-8A-EC-C9-CD android-5b7ed7d1f40c56f5
Use of uninitialized value $z[1] in pattern match (m//) at test.pl line 24.
Use of uninitialized value $z[1] in pattern match (m//) at test.pl line 24.
Ich versteh nicht warum diese Zeilen kommen:
Use of uninitialized value $z[1] in pattern match (m//) at test.pl line 24.
Ja ich hab es jetzt mit einen Rustch gemacht ohne Datei zwischendurch. Weiß aber noch nicht ob ich das ins FHEM packe oder es vom Raspi machen lasse und dann im Script über Telnet zu FHEM schicke.
Könnte ich das eigentlich so 1 zu 1 in eine 99_myUtils packen? Klar mit sub usw . dann.
Gruß
Jörg
Zitat von: Groej am 05 April 2018, 19:19:28
Ich versteh nicht warum diese Zeilen kommen:
Use of uninitialized value $z[1] in pattern match (m//) at test.pl line 24.
Ja ich hab es jetzt mit einen Rustch gemacht ohne Datei zwischendurch. Weiß aber noch nicht ob ich das ins FHEM packe oder es vom Raspi machen lasse und dann im Script über Telnet zu FHEM schicke.
Könnte ich das eigentlich so 1 zu 1 in eine 99_myUtils packen? Klar mit sub usw . dann.
Hm, das my @z = split("[ \t]+",$zeile); führt zu einem nicht initialisiertem Element $z[1]. Um das zu kontrollieren gibt doch auch noch den Wert von $zeile aus.
Das Ganz in eine myUtils zu packen ist dann sicherlich eine gute Idee. Hier kannst Du dann die Readings eines Dummys füllen.
Grüße Jörg
Die perl Warnungen kannst Du getrost ignorieren, die sind nicht schlimm. Sie kommen daher,
- dass Du meinen als "Funktionsprinzip" gekennzeichneten Beispielcode einfach übernommen hast
- ohne ihn wirklich syntaktisch korrekt fertigzustellen
- und ohne ihn zu verstehen
Moin,
na Dein Code betateilchen verstehe ich so.
Die Ausgabe von meiner Telnetabfrage wird Zeilenweise eingelesen. Die Zeile wird dann in einzelne Teile geteilt und die Trennug ist ein Tab. Dann wird gesucht ob im zweiten Wert der Zeile Z1 ein Text steht der mit 192.168. anfängt. Wenn ja werden alle Werte in dieser Zeile in die Variable beginnend mit z0 und Endet mit zx geschrieben. Ich gebe dann mit meinem print Befehl Z2 und z4 aus. Das ganze wird so lange gemacht bis alle Zeilen durchgearbeitet sind durch foreach. Richtig verstanden?
In der Telnetausgabe sind Zeilen bei wo keine IP Adressen stehen bzw. wo welche stehen aber nicht an der richtigen stelle. Wahrscheinlich müßte ich noch eine if Anweisung schreiben nach next. Wenn der Inhalt in z1 nicht in da ist das er diese Zeile übergeht und zur nächsten geht um die Fehlermeldung weg zu bekommen. Bin ich da auf dem richtigen Weg mit? Weiß nur gerade nicht wann else stehen müßte bzw ob man überhaupt ein else braucht.
Gruß
Jörg
next unless(defined($z[1]) and $z[1] =~ m/192\.168\./);
Zitat von: Groej am 06 April 2018, 06:56:02
und zur nächsten geht um die Fehlermeldung weg zu bekommen.
Es fängt schon damit an, dass die Meldung überhaupt keine Fehlermeldung ist, sondern nur ein Hinweis.
Wäre es eine Fehlermeldung, würde das script nicht weiterarbeiten, sondern abbrechen.
Deshalb meine Aussage:
Zitat von: betateilchen am 05 April 2018, 21:34:56
Die perl Warnungen kannst Du getrost ignorieren, die sind nicht schlimm.
Achja - noch ein gut gemeinter Rat.
Wenn Du vorhast, Deinen Code aus dem script in die 99_myUtils.pm zu übernehmen, dann mach das bitte über "Edit files" direkt in FHEM.
Das hat den Vorteil, dass Du beim Abspeichern der Datei automatisch Hinweise auf die sonst noch bestehenden Syntaxfehler in Deinem Code bekommst.
Ich weiß :) aber danke für den Tipp.
Danke erstmal an alle hier die mir weitergeholfen haben bis jetzt.
Gruß
Jörg
Moin,
so bekomme es nicht in der 99_myUtils zum Laufen. Habs jetzt auf der Linux ebende gelassen und schick es per Telnet ins FHEM.
#!/usr/bin/perl
use warnings;
use Net::Telnet ();
$draytek = new Net::Telnet (Timeout => 10,Errmode=>'die');
$draytek->open("192.168.10.1");
#print "connect\n";
#print "\n";
$draytek->waitfor('/Account:$/i');
$draytek->print("xxx") or die $draytek->errmsg;
$draytek->waitfor('/Password: $/i');
$draytek->print("xxx") or die $draytek->errmsg;
#print "logged in\n";
$draytek->waitfor('/GroejNet-Berlin> $/'); @output = $draytek->cmd("srv dhcp status lan1");
#print @output;
#$data = $remote->cmd("srv dhcp status lan1");
$draytek->close;
#print "\n";
$fhem = new Net::Telnet (Timeout => 10,Port => 7072,Errmode=>'die');
$fhem->open("127.0.0.1");
$fhem->print("deletereading draytek_mac_addr .*");
$count = 1;
foreach my $zeile (@output){
my @z = split("[ \t]+",$zeile);
next unless(defined($z[1]) and $z[1] =~ m/192\.168\./);
# ab hier erfolgt das Verarbeiten der "gültigen" Zeilen
# in $z[1] steht die IP, in $z[2] steht die MAC usw.
#print "IP_$count $z[2]\n";
$fhem->print("setreading draytek_mac_addr IP_$count $z[2]");
$count=$count+1;
}
$fhem->print("quit");
$fhem->close;
Ich hab einen AT Befhel in FHEM geschrieben der so aussieht:
define draytek_mac_addr_at at +00:02:00 {system('sudo perl /home/pi/draytek_dhcp_mac.pl&');;}
Jetzt kommt das was ich nicht verstehen. Der AT wird einmal ausgeführt, die Daten werden auch in den Dummy geschrieben, und dann wird der komplette Befehl aus FHEM gelöscht. Er ist dann aus der fhem.cfg weg.
Im LOG von FHEM steht dazu nur:
2018.04.07 08:00:28 3: draytek_mac_addr_at: -1
Am Ende müßte doch eine 1 und nicht -1 stehen richtig?
Gruß
Jörg
In der Commandref zum at findest Du die Antwort auf Deine Frage.
Hallo,
danke nochmal für Eure Hilfe und Unterstützung. Ich glaub ich bin am Ziel und bin etwas stolz das mit meinen bescheidenen Kenntnisen hinbekommen zu haben. Ob das alles sauber programmiert ist sei bitte dahin gestellt.
Wie gesagt hab ich jetzt alles in einen PERL Script auf der Lunix Ebende vom RasPi gemacht. Ich bau eine Telnet Verbindung zu meinen Draytek Router auf und lese die DHCP Tabelle aus. @betateilchen Danke für den Anstoß mit dem Split Code von Dir :). Dann suche ich in der Tabelle bestimmte MAC Adressen und setze dann per Telnet die Readings in einen FHEM Dummy auf present oder absent.
Auch das Script über FHEM auszuführen klappt jetzt mit einen AT Befehl. @CoolTux was so ein * Stern doch ausmacht :).
Perl Code:
#!/usr/bin/perl
use warnings;
use Net::Telnet ();
# MAC Adressen eitragen in dem Format: ("xx-xx-xx-xx-xx-xx","xx-xx-xx-xx-xx-xx")
@macs = ("EC-10-7B-0F-47-9B","C8-D7-B0-F7-5F-D4");
$draytek = new Net::Telnet (Timeout => 10,Errmode=>'die');
$draytek->open("IPxxx.xxx.xxx.xxx");
$draytek->waitfor('/Account:$/i');
$draytek->print("Benutzerxxxx") or die $draytek->errmsg;
$draytek->waitfor('/Password: $/i');
$draytek->print("Passwordxxxx") or die $draytek->errmsg;
$draytek->waitfor('/GroejNet-Berlin> $/');
@output = $draytek->cmd("srv dhcp status lan1");
#print @output;
$draytek->close;
#print "\n";
#print "\n";
$fhem = new Net::Telnet (Timeout => 10,Port => 7072,Errmode=>'die');
$fhem->open("127.0.0.1");
#$fhem->print("deletereading draytek_mac_addr .*");
foreach $macs (sort @macs){
# print "MAC $macs\n";
foreach my $zeile (@output){
my @z = split("[ \t]+",$zeile);
next unless(defined($z[1]) and $z[1] =~ m/192\.168\./);
# ab hier erfolgt das Verarbeiten der "gültigen" Zeilen
# in $z[1] steht die IP, in $z[2] steht die MAC usw.
#print "Z $z[2]\n";
if ($z[2] eq $macs){
$fhem->print("setreading draytek_mac_addr mac_$macs present");
goto NEXT_MAC;
}
}
$fhem->print("setreading draytek_mac_addr mac_$macs absent");
NEXT_MAC:
#print "\n";
}
$fhem->print("quit");
$fhem->close;
Dummy in FHEM:
define draytek_mac_addr dummy
attr draytek_mac_addr event-on-change-reading .*
AT Befehl in FHEM:
define draytek_mac_addr_at at +*00:02:00 {system('sudo perl /home/pi/draytek_dhcp_mac.pl&');;}
Danke nochmal an alle die geholfen haben.
Schönen Sonntag
Jörg