Hallo, wie oben schon im Thema geschrieben, suche ich nach einer Möglichkeit zu prüfen ob eine bestimmte url innerhalb eines timeout´s von 15 sec. erreichbar ist oder nicht. Leider habe ich bis jetzt im Netz oder meinen zwei Perl Handbüchern da nicht das Richtige gefunden oder vlt. nach den falschen Begriffen gesucht.
Hat da jemand einen Tip wo ich suchen könnte?
VG
Frank
das kannst du nur prüfen in dem du die url abrufst. wenn es klappt schmeißt du die rückgabe weg, wenn es einen fehler gibt reagierst du.
in fhem geht das am sinnvollsten über ein at und eine routine die HttpUtils_NonblockingGet. presence im function mode (dann auch mit HttpUtils_BlockingGet ) wäre auch ein ansatz. dann kannst du auch den verbindungsaufbau im hintergrund machen. das schliesst noch ein paar blockierungsmöglichkeiten mehr aus.
gruss
andre
Ich habe etwas in der Art mit dem HTTPMOD-Modul umgesetzt.
das ist auch eine idee. aber ich glaube das dann noch ein watchdog oder ähnliches nötig ist wenn es eine gewisse zeit keine readings änderung ergeben hat weil httpmod nur im erfolgsfall etwas tut und fehler mehr oder weniger ignoriert.
gruss
andre
Danke Andre. Hintergrund ist, dass der Netzwerkcontroller ENC28J60 auf dem avr-net-io, trotz zusätzlichen Stützkondensatoren, ab und an hängt. Per Ping ist das Board noch erreichbar und das PRESENCE Modul liefert auch brav present zurück. Versucht man jedoch den Webserver des Boards zu erreichen, dauert das ewig und mitunter gibt es einen Timeout. Die Heizungssteuerung über das Board und einen nachgeschalteten DAC funktioniert zum Glück trotzdem weiter und es lassen sich auch neue Werte setzen nur eben der Webserver des AVR-IO-Boards ist nicht mehr erreichbar. Nach einem Reset (Netzteil kurz vom Netz) ist die Weboberfläche dann wieder da.
Das wollte ich auswerten und dann das Board kurz vom Netz trennen.
VG
Frank
Habe jetzt gerade mal begonnen etwas mit HTTPMOD rumzuspielen, leider wird folgender Log ausgegeben:
2015.09.30 21:23:05 3: AVR_Status: Defined with URL 192.168.2.111 and interval 60
2015.09.30 21:23:07 3: AVR_Status: Read callback: request type was Update, no headers, buffer empty,
Error 192.168.2.111: malformed or unsupported URL
2015.09.30 21:24:07 3: AVR_Status: Read callback: request type was Update, no headers, buffer empty,
Error 192.168.2.111: malformed or unsupported URL
Laut commandref müsste die Def doch stimmen? Das Error 192.168.2.111: malformed or unsupported URL macht mich stutzig.
Warum wird die URL nicht unterstützt, das Format müsste doch auch stimmen, sehr viel kann ja in der DEF nicht angegeben werden.
P.S. Der Slash hat gefehlt ;)
VG
Frank
hast du http:// mit angegeben ?
gruss
andre
Habs schon gefunden, die volltändige url muss natürlich http://192.168.2.111/ sein.
Zitat von: justme1968 am 30 September 2015, 10:03:43
das ist auch eine idee. aber ich glaube das dann noch ein watchdog oder ähnliches nötig ist wenn es eine gewisse zeit keine readings änderung ergeben hat weil httpmod nur im erfolgsfall etwas tut und fehler mehr oder weniger ignoriert.
Ja sicher. Ein einfaches DOIF überwacht, ob die Readings regelmäßig aktualisiert werden (also kein Timeout auftritt) und auch, ob ein bestimmter Inhalt in der Antwort enthalten ist (also keine Fehlerseite o. ä. kommt).
Habe jetzt mal versucht mit HTTPMOD etwas hin zubekommen, doch leider werde ich da nicht so ganz schlau draus. Einfach gesagt, ich weis nicht was ich da auswerten könnte. Habe mit http://192.168.2.111/adc.ht 60 versucht von der Weboberfläche der ADC channels Informationen zu bekommen, woraus man present/absent herleiten könnte, da komme ich aber nicht weiter.
Ein list vom device gibt:
Internals:
BUSY 0
CFGFN
CHANGED
DEF http://192.168.2.111/adc.ht 60
GetSeq 0
HTTPHEADER
Interval 60
LASTSEND 1443719914.11635
MainURL http://192.168.2.111/adc.ht
NAME AVR_Status
NR 10101
STATE ???
TRIGGERTIME 1443719974.11506
TRIGGERTIME_FMT 2015-10-01 19:19:34
TYPE HTTPMOD
addr http://192.168.2.111:80
buf HTTP/1.1 400 Bad Request
Connection: close
Content-Type: text/plain; charset=utf-8
Content-Length: 12
Bad Request
conn
data 1
displayurl http://192.168.2.111/adc.ht
header
host 192.168.2.111
httpheader
hu_blocking 0
hu_filecount 12
ignoreredirects 0
loglevel 4
path /adc.ht
protocol http
redirects 0
timeout 2
url http://192.168.2.111/adc.ht
QUEUE:
Readings:
Request:
data 1
header
ignoreredirects 0
retryCount 0
type Update
url http://192.168.2.111/adc.ht
Sslargs:
Attributes:
DbLogExclude .*
disable 0
requestData.* 1
room Heizung
userattr disable requestData.*
Es fehlt mir hier ein weiterführenden Tip.
VG
Frank
in Bus steht die seite die der web server zurück geliefert hat. das ist bei dir gerade 'HTTP/1.1 400 Bad Request' da stimmt also etwas noch nicht.
wie schaut die seite denn aus wenn du per browser oder wget abrufst?
gruss
andre
Im Browser gibt ein http://192.168.2.111/adc.ht
dann versuch mal wget und schau ob vielleicht noch bestimmte header gesetzt werden müssen damit es geht.
Mit wget kann ich doch aber nur Dateien vom Server laden, wenn ich das richtig in Erinnerung habe. Und das macht es auch:
frank1@zotac:~$ wget http://192.168.2.111/adc.ht
--2015-10-01 21:32:45-- http://192.168.2.111/adc.ht
Verbindungsaufbau zu 192.168.2.111:80... verbunden.
HTTP-Anforderung gesendet, warte auf Antwort... 200 OK
Länge: 624 [text/html]
In »»adc.ht.1«« speichern.
100%[================================================================================================================================================================>] 624 --.-K/s in 0,008s
2015-10-01 21:32:45 (71,9 KB/s) - »»adc.ht.1«« gespeichert [624/624]
VG
Frank
das was du mit wget lädst ist genau das was ein browser unter der gleichen url ausgeliefert bekommt. das können genau so gut webseiten wie andere daten sein. wget ist sozusagen ein browser ohne gui. was steht in dem geladenen file?
wenn hier etwas richtigeres drin steht starte mal wget mit den debug und verbose optionen und schau dir an welche header gesetzt sind. die fehlen dann eventuell in der httpmod version.
Hab das File mal angehangen
dein file ist noch gepackt. wenn du es umbenennst und mit gunzip auspackst steht dort glaube ich der html quelltext der deinem screenshot entspricht.
warum httpmod damit scheinbar nicht klar kommt sehe ich auf den ersten blick nicht. eventuell liegt es an der kompression oder an anderen fehlenden headern.
gruss
andre
In der Info zur Seite steht
Request-Header
Keine Request Header
Hab mir die Seite mal auf der Webinfo-Console angesehen, dass sieht so aus als wenn beim Zugriff kurz die Daten geladen werden und dann sofort wieder ein closed folgt.
Ich entpackte das File jetzt mal und dann kommt man vlt. weiter.
Entpackt und mit Firefox geöffnet steht da
Ethersex ADC Status
drinn und das ist
<body>
<h1>Ethersex ADC Status</h1>
Hallo Frank,
Httpmod reagiert bisher auf Verbindungsfehler nur mit einem Log-Eintrag und ändert die Readings nicht.
In der nächsten Version wird es da aber eine Reaktionsmöglichkeit geben.
Was das Problem mit dem Seitenabruf angeht, so könnte das an der Kompression liegen. Httpmod verwendet ja auch nur die HttpUtils zum Abruf der Seite und da ist meines Wissens noch Kompression bisher nicht vorgesehen.
Zum Debuggen verwende ich immer die Burp Suite. Da kann man auch sehr schön mit den Headern spielen.
Gruß
Stefan
@Stefan
Ich danke dir für die "Auflösung des Rätsels", dann warte ich mal auf deine neue Version. In der Zwischenzeit könnte man ja auch über at ein wget auf die url machen und mittels regex das OK (200) oder bad connection (400) auswerten, mal sehen. Habe leider z.Zt. nicht viel Muße für fhem, da jede Menge Arbeit in der Firma ansteht.
VG
Frank
Mit {system("wget http://192.168.2.111/adc.ht")} bekomme ich zumindest im Log was, daran kann man ja arbeiten (aber die geladenen Daten müssten immer wieder verworfen werden)
--2015-10-01 22:50:50-- http://192.168.2.111/adc.ht
Connecting to 192.168.2.111:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 624 [text/html]
Saving to: `adc.ht'
0K 100% 66.7K=0.009s
2015-10-01 22:50:50 (66.7 KB/s) - `adc.ht' saved [624/624]
Aber das OK wäre ja das, was ich möchte ;)
Hallo, heute habe ich nun mal versucht eine Grundlage zum Abfragen present/absent zu schaffen. Leider fehlen mir dazu weiterreichende Kenntnisse in Perl.
Mit:
{system("wget http://192.168.2.111/adc.ht")}
kann ich adc.ht nach /opt/fhem downloaden, klappt das, dann ist der Server erreichbar.
Mit:
{system("rm /opt/fhem/adc.ht")}
verwerfe ich dann die Datei adc.ht wieder. Leider erzeugt wget im Log natürlich eine Meldung, wenn ich diesen Logeintrag als return auswerten könnte, wäre ich schon fast am Ziel.
Im Log erhalte ich:
--2015-10-03 10:51:13-- http://192.168.2.111/adc.ht
Connecting to 192.168.2.111:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 624 [text/html]
Saving to: `adc.ht'
0K 100% 67.0K=0.009s
2015-10-03 10:51:13 (67.0 KB/s) - `adc.ht' saved [624/624]
Jetzt könnte man das awaiting response... 200 OK oder 0K 100% 67.0K=0.009s auswerten aber dafür fehlt mir das programmiertechnische Fingerspitzengefühl, leider.
VG
Frank
system sollte dir einen rückgabe wert liefern der dem exit value von weit entspricht. welche exit values du erwarten kannst steht in der wget manual page.
du kannst wget im quiet modus starten um die log meldungen los zu werden und du kannst den namen des ausgabe files fest vorgeben damit nicht jedes mal ein neues erzeugt wird.
wenn du über presence gehst würde ich nicht wget aufrufen sondern die httputils verwenden. entweder über die alten GetFileFromURLQuiet/GetFileFromURL/GetHttpFile varianten oder direkt über das neue HttpUtils_BlockingGet. mit über presence und system startest du bei jedem aufruf zwei prozesse statt nur einem wenn du über presence und die httputils gehst. über die httputils hast du auch gleich den response code aus dem header.
gruss
andre
Zitatsystem sollte dir einen rückgabe wert liefern der dem exit value von weit entspricht
Da bekomme ich als Rückgabe leider nur -1
{system("wget -q - http://192.168.2.111/adc.ht")} unterdrückt die Logausgabe aber leider gibt es nur ein -1 zurück
du musst den rückgabe wert auch auswerten und dann in die 0 oder 1 die presence erwartet umwandeln
etwas in der art:{my $ret = system("wget -q -O /dev/null http://192.168.2.111/adc.ht"); return ($ret >> 8) ? 0 : 1;}
-q für quiet
-O /dev/null um die empfangenen daten weg zu schmeissen
wenn der exit code != 0 ist absent zurück gegeben sonst present. die auswertung des rückgabe wertes sollte man eventuell noch verfeinern. siehe z.b. hier: my $ret = system("wget -q -O /dev/null http://havanna"); (http://my%20$ret%20=%20system("wget%20-q%20-o%20/dev/null%20http://havanna");)
gruss
andre
Hallo Andre,
ich hab das jetzt völlig trivial gelöst.
sub
AVR_Stat
{
{system("wget -q - http://192.168.2.111/adc.ht")};
my $dname = "adc.ht";
if(-e $dname){
fhem "set adc_dummy ja";
{system("rm /opt/fhem/adc.ht")};
}
else {
fhem "set adc_dummy nein";
}
}
funktioniert.
VG
Frank
aber diese variante blockiert fhem wenn dein host nicht richtig antwortet.
gruss
andre
Mmh, daran hab ich natürlich nicht gedacht, ich simuliere das heute Nachmittag mal, ist blos schlecht da dann die Steuerung der Heizungsanlage aus ist.
Sonst teste ich mal deine Variante.
VG
Frank
Mit
{my $ret = system("wget -q -O /dev/null http://192.168.2.111/adc.ht"); return ($ret >> 8) ? 0 : 1;}
und eingebauten
Log 3, "$ret";
bekomme ich jedesmal -1 zurück, somit klappt die Auswertung auf != 0 absent sonst present leider nicht. Ich lasse das jetzt erst einmal ruhen. Richtig testen kann man es sowieso nur, wenn die Website unter realen Bedingungen nicht erreichbar sein sollte, wobei die ADC/DAC Steuerung dann ja trotzdem noch funktioniert und nur der Aufruf der Weboberfläche des Ethersex mit einem Timeout endet.
VG
Frank
Melde mich doch noch mal, da es mir keine Ruhe lässt.
Mit:
{my $ret = system("wget -q -O /dev/null http://192.168.2.111/adc.ht"); return ($ret >> 8) ? 0 : 1;}
in einer sub, wird die Subroutine doch durch das return beendet, wohin wird dann $ret zurück gegeben. Wenn ich die Auswertung ob $ret 0 oder 1 ist müsste ich das doch gleich noch in der sub mit unterbringen aber durch return wird ja die sub verlassen. Und >> ist doch eigendlich eine bitweise Verschiebung?
Den Anfang vom Code verstehe ich aber das return ($ret >> 8) ? 0 : 1; ist mir ein Rätsel.
VG
Frank
hab es gerade mal angepasst, um es auf dem Rechner, außerhalb von fhem testen zu können
frankdonathsmbp:Desktop frdonath$ perl -w AVR_test.pl
Argument "wget -q -O /dev/null http://192.168.2.111/adc.ht" isn't numeric in right bitshift (>>) at AVR_test.pl line 4.
set adc_dummy present
Can't return outside a subroutine at AVR_test.pl line 12.
#!/usr/local/bin/perl -w
{
my $ret = ("wget -q -O /dev/null http://192.168.2.111/adc.ht");
($ret >> 8) ? 0 : 1;
if($ret != 0){
print "set adc_dummy absent\n";
}
if($ret == 0){
print "set adc_dummy present\n";
}
return ($ret >> 8) ? 0 : 1;
#Log 3, "$ret";
print "$ret\n";
}
Hierbei wird richtigerweise set adc_dummy present zurück gegeben, führe ich den Code in der sub in fhem aus, wird absent zurück gegeben.
Die sub in fhem:
sub
AVR_Stat2
{
my $ret = system("wget -q -O /dev/null http://192.168.2.111/adc.ht");
($ret >> 8) ? 0 : 1;
if($ret != 0){
fhem "set adc_dummytest absent";
}
if($ret == 0){
fhem "set adc_dummytest present";
}
return ($ret >> 8) ? 0 : 1;
Log 3, "$ret";
}
Scheint jetzt zu funktionieren.
Es bleibt nur die Warnung:
2015.10.04 10:20:40 1: PERL WARNING: Argument "wget -q -O /dev/null http://192.168.2.111/adc.ht" isn't numeric in right bitshift (>>) at ./FHEM/99_myUtils.pm line 693.
sub
AVR_Stat2
{
my $ret = system("wget -q -O /dev/null http://192.168.2.111/adc.ht");
($ret >> 8) ? 0 : 1;
if($ret != 0){
fhem "set adc_dummy ja";
}
if($ret == 0){
fhem "set adc_dummy nein";
fhem "set Leistungsmesser_AVR_Board_Sw off; sleep 20; set Leistungsmesser_AVR_Board on";
}
return ($ret >> 8) ? 0 : 1;
}
P.S. Seltsam, dass hat genau einmal funktioniert, jetzt geht das dummy immer auf "nein"(absent) obwohl die Website definitiv erreichbar ist.
VG
Frank
ich nutze HttpUtils_NonblockingGet um mit einem webserver auf meinem arduino zu kommunizieren. hier der code aus der fhem.cfg. in $_[1] steht ein fehler, wenn zb der arduino nicht erreichbar war, sonst ist die variable leer. die variable schreibe ich regelmässig ins fhem.log und in ein reading. in $_[2] stehen die die daten. die brauchst du wahrscheinlich nicht. das ganze funktioniert halt nonblocking. vielleicht ein versuch wert.
HttpUtils_NonblockingGet( {\
url=>"http:\/\/192.168.1.5\/?HZG1_KOMF=$TraumD",\
callback=>sub($$$){\
if($_[1]) {\
$err = $_[1];;\
}\
else {\
$err = "no problem";;\
}\
Log 3,"ERR:$err DATA:$_[2]";;\
fhem("setreading Broetje httpErr [?HZG1_KOMF=$TraumD] => $err");;\
}\
} );;\
Hallo Frank, wie rufst du HttpUtils_NonblockingGet auf? Mittlerweile bin ich ziemlich betriebsblind und blicke gerade gar nicht mehr durch, habe seit 3h etliches an Code Zeilen geschrieben.
Zu HttpUtils_NonblockingGet riet mir Andre auch schon.
VG
Frank
genauso wie es gepostet ist.
bei dir eventuell
HttpUtils_NonblockingGet( {\
url=>"http:\/\/192.168.2.111\/adc.ht",\
callback=>sub($$$){\
if($_[1]) {\
$err = $_[1];;\
}\
else {\
$err = "no problem";;\
}\
Log 1,"ERR:$err DATA:$_[2]";;\
}\
} );;\
dann sollte bei jedem verbindungsversuch eine logzeile geschrieben werden.
OK, danke dir, ziehe ich mir heute Nachmittag mal raus und passe es an. Das seltsame ist, das nur die Weboberfläche vom Server nicht mehr erreichbar ist, der Server AVR-NET-IO aber noch brav die Heizung steuert, dass kommt vlt. einmal im Monat vor, je nachdem was für eine Netztlast vorlag.
VG
Frank
zb einfach in ein at einpacken:
define Check at *00:10:00 {\
HttpUtils_NonblockingGet( {\
url=>"http:\/\/192.168.2.111\/adc.ht",\
callback=>sub($$$){\
if($_[1]) {\
$err = $_[1];;\
}\
else {\
$err = "no problem";;\
}\
Log 1,"ERR:$err DATA:$_[2]";;\
}\
} );;\
}
Hallo Frank, wenn ich das erweitere (ich muss ein dummy setzen ja/nein) funktioniert das Ganze scheinbar nicht, leider sehe ich iMo nicht warum.
nein==> Server nicht erreichbar
ja==> Server erreichbar, alles OK
Bekomme leider im Log:
2015.10.04 17:20:00 3: Check: Global symbol "$err" requires explicit package name at (eval 318315) line 6.
Global symbol "$err" requires explicit package name at (eval 318315) line 9.
Global symbol "$err" requires explicit package name at (eval 318315) line 11.
VG
Frank
geht es ohne dummy?
im ersten post von mir habe ich ja auch eine fhem anweisung.
schalte mal verbose vom at ein und schau im log.
Das dummy ist erst einmal nur zum testen, wenn das richtig läuft wird ein HM-ES-PMSw1-Pl Switch für 10sec. auf off gesetzt und nach sleep 10 wieder auf on. Der Switch trennt das AVR-Board für 10sec. vom Netz und setzt es damit zurück und die GUI vom Board ist wieder erreichbar.
Da die Erreichbarkeit keinerlei Regeln folgt, wollte ich über das dummy erst einmal sehen, wann das Board wieder weg ist.
P.S. Da ich seit etlicher Zeit alles was mehr als 3 Codezeilen umfasst, in die Utils auslagere, habe ich iMo. nicht den richtigen Durchblick wenn das in der DEF steht ;)
VG
Frank
Mit verbose 5:
2015.10.04 18:00:00 5: exec at command Check
2015.10.04 18:00:00 3: Check: Global symbol "$err" requires explicit package name at (eval 325156) line 6.
Global symbol "$err" requires explicit package name at (eval 325156) line 9.
Global symbol "$err" requires explicit package name at (eval 325156) line 11.
2015.10.04 18:00:00 5: redefine at command Check as +*00:10:00 {
HttpUtils_NonblockingGet( {
url=>"http:\/\/192.168.2.111\/adc.ht",
callback=>sub($$$){
if($_[1]) {
$err = $_[1];
}
else {
$err = "no problem";
}
Log 1,"ERR:$err DATA:$_[2]";
}
} );
}
die definition von $err fehlt. my $err; zb in die erste zeile vom at.
Sag ich doch ;)
in der Utils wäre es mir sofort aufgefallen das $err nicht definiert ist und jetzt bekomme ich auch ein return :) :)
ImLog:
2015.10.04 18:30:00 5: redefine at command Check as +*00:10:00 {my $err = "undef";
HttpUtils_NonblockingGet( {
url=>"http:\/\/192.168.2.111\/adc.ht",
callback=>sub($$$){
if($_[1]) {
$err = $_[1];
}
else {
$err = "no problem";
}
Log 1,"ERR:$err DATA:$_[2]";
}
} );
}
2015.10.04 18:30:00 1: ERR:no problem DATA:HTTP/1.1 200 OK
Connection: close
Content-Length: 624
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
���=UuT�n�0}�W���$-!6��� ��7�Vn2�qq�`{oB�w��f/�}I<�s��3��Zw''Q�"o�焓8��Z4���/>���na��wF��7�cf�F�m���l̮�&��M�c�p���ZV��Ft���W����n���6��~�g=�fU;�`}�LySO
�IR���1��|�{O�����#��媑h�Qt�p���z�֝@��$��� M#�丅Q��܀��p0�- 7h;�,^�m��L0�3m �A�rD��g��ܵ��e��x�� �q*�咀�)~���/H��_&��Z9�8�ƙ�iH�4�1d B�`����J4�#�p�N�
����˔(��s�Rh>_��g<�{���suc��w�ؠ�gv/�[{�z(ࡄ4w��Xc���Z��m�Dv�O��J��j�*�Jj�P������R��o$=lg>Z���١I�E�~�U"�#�q���W���pG�b�k&���֎ٮ��X�h��Ld���Lb���'$s�8���khϢ����r���^j��eY�V9h�"L��F7?FN���pt�>
���AR��A�н�#�-�KK=�'k�w�&�����_�}֎C�
So hab ich jetzt fertig:
+*00:10:00 {my $err = "undef";
HttpUtils_NonblockingGet( {
url=>"http:\/\/192.168.2.111\/adc.ht",
callback=>sub($$$){
if($_[1]) {
$err = $_[1];
fhem "set adc_dummy nein";
}
else {
$err = "no problem";
fhem "set adc_dummy ja";
}
#Log 1,"ERR:$err DATA:$_[2]";
}
} );
}
VG
Frank