Ich probiere schon eine Weile und kriege es nicht zum laufen, dabei müsste es gefühlt ganz einfach sein.
Ich möchte eine Lampe schalten per HTTP request und den neuen Status der Lampe als Rückgabewert. Ich erhalten aber immer den alten Status von vor dem Schalten.
(Escaping habe ich zwecks besserer Lesbarkeit hier weggelassen)
http://meineip:8083/fhem?cmd=set Farbwuerfel toggle;list Farbwuerfel state&XHR=1&fwcsrf=csrf_meintoken
Beispielausgabe: Farbwuerfel 2019-04-21 08:53:30 off
Rückgabe ist "off", Lampe ist aber in Wirklichkeit schon "on", wegen des toggle Befehls.
Wenn ich noch ein sleep einbaue
set Farbwuerfel toggle;sleep 1;list Farbwuerfel state
Erhalte ich nur eine leere Seite zurück. Ich vermute, dass hier nur noch die Rückgabe des Befehls "set Farbwuerfel toggle" ankommt.
Hat jemand eine Idee?
Hintergrund ist der, dass es eine Android App "HTTP request shortcuts" gibt, mit der man sich HTTP requests als Widgets auf den Homescreen legen kann. Beim Anklicken eines Widgets kann die APP auch einen Rückgabewert anzeigen.
Hast Du mit doppel Semikolon schon versucht?
Moin,
der Schaltbefehl und die Aktualisierung des State sind zwei getrennte Vorgänge. Die Zeit dazwischen hängt vom Gerät ab.
Bei einem Dummy funktioniert das was Du willst, bei jedem anderen Gerät wäre es rein zufällig.
Gruß Otto
Doppel Semikolon hab ich auch schon probiert, dann funktioniert der Befehl garnicht da kommt "Unknown argument toggle;............"usw..
Zitatder Schaltbefehl und die Aktualisierung des State sind zwei getrennte Vorgänge. Die Zeit dazwischen hängt vom Gerät ab.
Ich habe ein bisschen im telnet damit experimentiert. Wenn ich beide Befehle ins telnet paste, so dass sie praktisch zeitgleich ausgeführt werden, dann klappt es nicht. Mache ich ca. 1 Sek. Pause dazwischen, dann klappt es wie gewünscht. Die Frage ist nur, kann ich eine kleine Pause in die URL für den HTTP request einbauen?
Ich habe auch schon ein eigenes Modul gebaut, mit folgendem code drin:
sub
mySwitch(){
fhem("set Farbwuerfel toggle");
sleep 1;
fhem("list Farbwuerfel state");
}
Erstaunlicherweise (für mich zumindest) erscheint, wenn ich das Modul über
http://meineip:8083/fhem?cmd={mySwitch()}&XHR=1&fwcsrf=csrf_meintoken
aufrufe, trotzdem der alte Zustand :o
perl sleep blockiert fhem und es gibt keinen fortschritt.
du musst ein fhem sleep verwenden.
d.h. nicht mehrfach zwischen perl und fhem ebene wechseln.
Zitatperl sleep blockiert fhem und es gibt keinen fortschritt.
Ein guter Einwand und jetzt kann ich mein Problem glaube ich wirklich reduziert auf den Punkt bringen.
Wenn ich oben im Webinterface von FHEM in das Eingabefeld folgenden Befehl eingebe (also fhem sleep):
set Farbwuerfel toggle; sleep 5; set Farbwuerfel toggle
Dann schaltet die Lampe um, dass Webinterface wird neu geladen und 5 Sekunden später schaltet die Lampe wieder um.
Wenn ich im Webinterface eingebe:
set Farbwuerfel toggle; sleep 5; list Farbwuerfel state
Dann schaltet die Lampe um, dass Webinterface wird neu geladen und 5 Sekunden erscheint garnichts. (Die Ausgabe vom list Befehl erscheint im Logfile anstatt im Webinterface)
Man müsste irgendwie den ersten Teil "set Farbwuerfel toggle" stumm schalten können bzw. die Ausgabe verzögern, bis alle Befehle abgearbeitet wurden aber ich vermute, das geht garnicht so wie ich mir das vorstelle.
fhem arbeitet asynchron und event basiert. es ist nicht vorgesehen synchron auf ein ergebnis zu warten.
mit fhem sleep wird der rest des kommandos im hintergrund ausgeführt und dort landet dann auch die ausgabe.
das beißt sich mit dem verbindungslosen http.
ich fürchte das was du möchtest geht so nicht.
wenn du telnet verwenden kannst wäre das vermutlich einfacher.
Ok danke für eure Tipps. Ich bin auch ziemlich überzeugt jetzt, dass ich es nur mit FHEM alleine nicht lösen kann. Habe ein kleines Script gebastelt, welches auf Port 8181 lauscht und die Befehle dann an Fhem weitergibt. Über Sicherheitsaspekte usw. habe ich mir aber erstmal keine Gedanken gemacht. Das script läuft bei mir als normaler user von der Konsole ausgeführt. Wenn ich es ein paar Tage getestet habe und zufrieden bin, werde ich es vielleicht dämonisieren. Erstmal scheint es aber das zu tun, was ich will ;D
Fhem wird vom Script so ausgeführt:
system ("/opt/fhem/fhem.pl 7072 \"set $device $command\"");
my $result = `/opt/fhem/fhem.pl 7072 "list $device state"`;
Bei dieser Ausführungsart dauern die Befehle so lang, dass ich mir das sleep sparen konnte ::).
Man kann das script dann so ansteuern: http://fhemip:8181/fhem?c=befehl&d=device
Für mein Bespiel von vorhin also http://fhemip:8181/fhem?c=toggle&d=Farbwuerfel
#!/usr/bin/perl
{
package MyWebServer;
use HTTP::Server::Simple::CGI;
use base qw(HTTP::Server::Simple::CGI);
use strict;
my %dispatch = (
'/fhem' => \&fhem,
# ...
);
sub handle_request {
my $self = shift;
my $cgi = shift;
my $path = $cgi->path_info();
my $handler = $dispatch{$path};
if (ref($handler) eq "CODE") {
print "HTTP/1.0 200 OK\r\n";
$handler->($cgi);
} else {
print "HTTP/1.0 404 Not found\r\n";
print $cgi->header,
$cgi->start_html('Not found'),
$cgi->h1('Not found'),
$cgi->end_html;
}
}
sub fhem {
my $cgi = shift; # CGI.pm object
return if !ref $cgi;
my $device = $cgi->param('d');
my $command = $cgi->param('c');
print "Content-type: text/plain\n\n";
system ("/opt/fhem/fhem.pl 7072 \"set $device $command\"");
my $result = `/opt/fhem/fhem.pl 7072 "list $device state"`;
$result =~ s/\n//g;
$result =~ /^(\w+)?.*\s(\w+)$/;
my $result = "$1 $2";
print "$result";
}
}
# start the server on port 8181
my $pid = MyWebServer->new(8181)->background();
print "Use 'kill $pid' to stop server.\n";
Bespielcode war von: https://metacpan.org/pod/HTTP::Server::Simple
Jetzt kann ich mir meine ganzen Devices direkt auf den Android home screen legen, wie ich es mir gewünscht hatte, mit aktuellem state als Rückgabe.
gefällt mir,
bin auf mobilteil ausschließlich per http-request unterwegs (waf!). Responses war allerdings noch nicht im Fokus.
Fein wär noch, dass man den aktuellen status bekommt zum device, was am shortcut hängt.
Stell ich mir aber schwierig vor, das zu korrellieren, da man für dummys z.B. ein
list TYPE=dummy state
absetzen müßte und diese den shortcuts mit commando 'd'==device zuordnen müßte. Das müßte auch gepollt werden bzw. on-change aktualisiert werden...
Oder man baut sich einen zweiten shortcut, der eben den nur "state" des angesprochenen devices ausgibt.
Ich war mal so frei und hab's erweitert:
somit erzeugt ein http://fhemip:8181/fhem?c=state&d=device (http://fhemip:8181/fhem?c=state&d=device) den aktuellen Status, ohne Schalt-aktion
#!/usr/bin/perl
{
package MyWebServer;
use HTTP::Server::Simple::CGI;
use base qw(HTTP::Server::Simple::CGI);
use strict;
my %dispatch = (
'/fhem' => \&fhem,
# ...
);
sub handle_request {
my $self = shift;
my $cgi = shift;
my $path = $cgi->path_info();
my $handler = $dispatch{$path};
if (ref($handler) eq "CODE") {
print "HTTP/1.0 200 OK\r\n";
$handler->($cgi);
} else {
print "HTTP/1.0 404 Not found\r\n";
print $cgi->header,
$cgi->start_html('Not found'),
$cgi->h1('Not found'),
$cgi->end_html;
}
}
sub fhem {
my $cgi = shift; # CGI.pm object
return if !ref $cgi;
my $device = $cgi->param('d');
my $command = $cgi->param('c');
print "Content-type: text/plain\n\n";
if($command ne "state")
{
system ("/opt/fhem/fhem.pl 7072 \"set $device $command\"");
}
my $result = `/opt/fhem/fhem.pl 7072 "list $device state"`;
$result =~ s/\n//g;
$result =~ /^(\w+)?.*\s(\w+)$/;
#my $result = "$1 $2";
my $result = "device:\t$1\nstate:\t\t$2";
print "$result";
}
}
# start the server on port 8181
my $pid = MyWebServer->new(8181)->background();
print "Use 'kill $pid' to stop server.\n";
Hat jemand ne ahnung, wie ich dem teil das telnet-passwd mitgebe?
echo {passwd}| etc schon probiert, ohne erfolg. vielleicht weiß es ja doch einer :-)
ich schlage diesen weg ein, damit komm ich via user/passwd zum ziel, auch das list. ich meld mich...
https://forum.fhem.de/index.php/topic,68133.msg722644.html#msg722644 (https://forum.fhem.de/index.php/topic,68133.msg722644.html#msg722644)
Sollte so gehen:
https://forum.fhem.de/index.php/topic,14332.msg90785.html#msg90785
Gruß Otto
hatte ich schon versucht... bringt fehler, auxh mit passwd-argument
perl /opt/fhem/fhem.pl 7072 "list TV_BackgroundLight state" Use of uninitialized value in numeric gt (>) at /opt/fhem/fhem.pl line 524.
perl /opt/fhem/fhem.pl 7072 list TV_BackgroundLight state Use of uninitialized value in numeric gt (>) at /opt/fhem/fhem.pl line 524.
Gesendet von meinem SM-J510FN mit Tapatalk
Was Du da schreibst ist für mich nicht nachvollziehbar. Da solltest Du mehr Infos liefern. Was genau hast Du wie konfiguriert?
Ich habe ein allowedWEB Device konfiguriert, dort dann:
set allowedWEB password password
attr allowedWEB validFor telnetPort
Dann funktioniert folgender Befehl im Terminal
perl /opt/fhem/fhem.pl 7072 password "list global"
Gruß Otto
hier die Infos:
#################################
define telnetPort telnet 7072 global
setuuid telnetPort 5c4613d2-f33f-35e2-3875-c2ea646c190bcaaf
attr telnetPort SSL 0
#################################
define allowed_telnetPort allowed
setuuid allowed_telnetPort 5c4613d2-f33f-35e2-11df-a9cba40532aa0d1c
attr allowed_telnetPort password mypassword
attr allowed_telnetPort validFor telnetPort
identisch wie du, jedoch mit Fehler:
perl /opt/fhem/fhem.pl 7072 mypassword "list global"
Use of uninitialized value in numeric gt (>) at /opt/fhem/fhem.pl line 524.
oder ohne passwd
perl /opt/fhem/fhem.pl 7072 "list global"
Use of uninitialized value in numeric gt (>) at /opt/fhem/fhem.pl line 524.
kann ich noch was liefern? weiß sonst nicht, was telnet seitig fehlerhaft wäre. normaler telnet login auf 7072 funktioniert jedenfalls mit passwd-abfrage
ich hab
# $Id: fhem.pl 19085 2019-04-01 17:00:24Z rudolfkoenig $
Gesendet von meinem SM-J510FN mit Tapatalk
ich kanns gerade nicht testen aber wie wäre es mit sowas
use Net::Telnet ();
$t = new Net::Telnet (Timeout => 10,
Prompt => '/bash\$ $/');
$t->open($host);
$t->login($username, $passwd);
@lines = $t->cmd("who");
print @lines;
Moin knopf_piano,
ich habe irgendwie das Gefühl die Fehlermeldung hat mit etwas anderem zu tun. Die Frage wäre ja noch: bekommst DU mit oder ohne password denn eine Ausgabe.
Bei mir gibt es wenn Passwort aber dann kein Passwort angegeben einfach keine Ausgabe.
Kommt der Fehler auch beim normalen FHEM Start im Log?
Gruß Otto
Hi Otto,
das bekomme ich ins log, wenn ich den http-request abschicke und wie oben mittels perl webserver ans telnet anschieße. Gleicher log-Eintrag bei Kommando via shell
telnet SSL/HTTPS error: SSL accept attempt failed error:1408F10B:SSL routines:ssl3_get_record:wrong version number (peer: 192.168.178.22)
egal ob
attr telnetPort SSL 1
oder
attr telnetPort SSL 0
ssl und telnet - habe ich noch nicht gemacht. Da kann ich nicht helfen.
Gruß Otto
dank dir!
war ja off-topic-problem :-\
moin,
*puuuust* bissl staubig hier ;D
nur für den fall, das es jemanden interessiert, oder wie ich zufällig in dem Beitrag landen;
Habe in HTTP Request Shortcuts Jetzt mal folgendes gemacht;
3 "Schalter"
- 1. Schalten des Device mit set Befehl
- 2. Status mit list device state abfragen
- 3. Multischalter welcher 1 und 2 "Bündelt
habe bei beiden befehlen &XHR=1 angegeben um das öffnen der Webseite zu unterdrücken.
Response-Einstellungen: Bei Erfolg Nichts anzeigen
Shortcut Nr2. bei Auslöse&Ausführ-Einstellungen: Verzögerung 1 Sekunde einstellen
etwas Feenstaub unter Scripting - "Im Erfolgsfall ausführen"
const myB = response.body.trim().split(" ");
const myS = myB[myB.length-1];
showToast(myS);
if (myS === "on") {
changeIcon(/[shortcut]/"53fec09f-62d4-4a6c-b6be-502e7f66e2c3"/[/shortcut]/, "flat_color_brightness_5");
} else {
changeIcon(/[shortcut]/"53fec09f-62d4-4a6c-b6be-502e7f66e2c3"/[/shortcut]/, "flat_color_brightness");
}
den Ausführungsbereich vom if else würde ich löschen, und über das "Code Einfügen" Menü auswählen, - so hat man sicher die richtige Shortcut ID und Buttons die man will.
Das wars, Fertig ist ein Widget fähiger Button fürs Android Gerät welcher sogar den Status anzeigt.
ACHTUNG: die APP bietet, zumindest Stand jetzt, wohl keine Möglichkeit etwas periodisch abfragen zu lassen, d.h. es kann immer nur der last known state angezeigt werden, wenn danach in fhem oder so geschaltet wird, bekommt die APP das erst mit wenn man an dieser Schaltet.
Finde ich, da ich sehr frei darin bin WAS ich schalten will und sogar eigene Icons verwenden kann, doch recht nett ;)
Lg
Jens
€dit: habe die Zeile
const myS = myB[myB.length-1];
nun dynamisch gemacht, der wert ist, abhängig vom Namen, nicht immer gleich, aber immer die letzte stellte des arrays (länge -1 weil Zähler bei 0 beginnt!)