HMLAN Disconnect

Begonnen von oniT, 13 Mai 2013, 22:19:58

Vorheriges Thema - Nächstes Thema

martinp876

Hallo Toni,

ja, das ist seltsam.
@wert sollte eigentlich ein array aller Zeilen sein.

Ich habe verstanden, dass im logfile
Testidx 2
Testval xxx
auftaucht. Somit wird die schleife 2-mal durchlaufen, aber nicht oefter. Stellt sich die Frage, was eigentlich in @wert steht. 2 Tests sind moeglich, schicke doch die ergebnisse des Logfiles.

Zitatdefine html_aufruf_test at +*00:00:30 {\
my @werte=GetHttpFile("192.168.1.150", "/usr-cgi/xml.cgi?|A|1|10");;\
Log 1, "Werte ".join '+++',@wert;;\
}

oder/und

Zitatdefine html_aufruf_test at +*00:00:30 {\
my @werte=GetHttpFile("192.168.1.150", "/usr-cgi/xml.cgi?|A|1|10");;\
foreach my $line (@werte){\
   Log 1, "line: $line";;\
}\
}

Gruss Martin

oniT

Hallo Martin,

beides liefert folgenden Eintrag zurück:


2013.05.23 20:43:21 1: Werte bzw. line: HTTP/1.0 200 OK
Content-type: text/xml
Cache-Control: no-cache
Expires: -1
<WEB>
<PCO>
<ANALOG>
<VARIABLE>
<INDEX>1</INDEX>
        <VALUE>22.1</VALUE>
</VARIABLE>
<VARIABLE>
<INDEX>2</INDEX>
        <VALUE>21.0</VALUE>
</VARIABLE>
<VARIABLE>
<INDEX>3</INDEX>
<VALUE>27.5</VALUE>
</VARIABLE>
<VARIABLE>
<INDEX>4</INDEX>
<VALUE>36.4</VALUE>
</VARIABLE>
<VARIABLE>
<INDEX>5</INDEX>
<VALUE>-999.9</VALUE>
</VARIABLE>
<VARIABLE>
<INDEX>6</INDEX>
<VALUE>20.9</VALUE>
</VARIABLE>
<VARIABLE>
<INDEX>7</INDEX>
<VALUE>-999.9</VALUE>
</VARIABLE>
<VARIABLE>
<INDEX>8</INDEX>
<VALUE>36.3</VALUE>
</VARIABLE>
<VARIABLE>
<INDEX>9</INDEX>
<VALUE>21.7</VALUE>
</VARIABLE>
<VARIABLE>
<INDEX>10</INDEX>
<VALUE>10.2</VALUE>
</VARIABLE>
</ANALOG>
</PCO>
</WEB>


Gruß
TinoB


BBB - debian weezy - FHEM 5.7
HMLAN - HM-LC-Bl1-FM, HM-ES-PMSw1-PI, HM-LC-Sw1-FM, HM-TC-IT-WM-W-EU, HM-WDS40-TH-I, HM-Sen-Wa-Od, HM-Sec-RHS
Dimplex Wärmepumpe / Dimplex ZL 300 - Modbus TCP
SDM630M - Modbus TCP
SolarLog 200 / SMA SonnyBoy 1.5/2.5 - Modbus TCP

martinp876

Hi Toni,

wenn dies die Antwort aus beiden Abfragen ist bedeuted es, dass nicht ein Array sondern ein String zurueckgegeben wird.
Daher hat auch bislang alles nicht funktioniert. In der Loop war nur ein Element mit mehreren Zeilen.

Wir muessen also erst einmal die Struktur analysieren und dann den String in ein array zerlegen.

Um sicher zu gehen, dass es nur ein Element ist hier ein Test:

Zitatdefine html_aufruf_test at +*00:00:30 {\
my @werte=GetHttpFile("192.168.1.150", "/usr-cgi/xml.cgi?|A|1|10");;\
Log 1, "Elemente: ".scalar(@wert);;\
}

Es sollte "Elemente: 1" gelogt werden.

Nun muessen wir also den String in Zeilen zerlegen. Gehen wir davon aus, dass jede Zeile mit einem \n endet, dann sieht es so aus:

define html_aufruf_test at +*00:00:30 {\
my @ret=GetHttpFile("192.168.1.150", "/usr-cgi/xml.cgi?|A|1|10");;\
my @werte=split "\n",$ret[0];;\
my $val=0;;\
my $idx=0;;\
foreach (@werte){\
 if($_ =~m"</VARIABLE>"){\
   if ($idx && $val){\
     if ($idx == 1) {fhem("set aussenwert $val");;}\
     if ($idx == 2) {fhem("set feuchte $val");;}\
     if ($idx == 3) {fhem("set ATgestern $val");;}\
     if ($idx == 7) {fhem("set rain $val");;}\    
   }\
   $idx=0;;\
   $val=0;;\
 }\
 if($_ =~m"<INDEX>(.*)</INDEX>"){\
   $idx = $1;;\
   Log 1, "Testidx $idx";;\
 }\
 if($_ =~m"<VALUE>(.*)</VALUE>"){\
   $val = $1;;\
   Log 1, "Testval $val";;\
 }\
}\
}


Dann sollte auch das elsif funktionieren. Das war sicher kein Fehler sondern der Input war nicht verstanden.

Zitatdefine html_aufruf_test at +*00:00:30 {\
my @werte=GetHttpFile("192.168.1.150", "/usr-cgi/xml.cgi?|A|1|10");;\
Log 1, "Elemente: ".scalar(@wert);;\
}

Es sollte "Elemente: 1" gelogt werden.

Nun muessen wir also den String in Zeilen zerlegen. Gehen wir davon aus, dass jede Zeile mit einem \n endet, dann sieht es so aus:

define html_aufruf_test at +*00:00:30 {\
my @ret=GetHttpFile("192.168.1.150", "/usr-cgi/xml.cgi?|A|1|10");;\
my @zeile=split "\n",$ret[0];;\
my $val=0;;\
my $idx=0;;\
foreach (@zeile){\
 if($_ =~m"</VARIABLE>"){\
   if ($idx && $val){\
     if    ($idx == 1) {fhem("set aussenwert $val");;}\
     elsif ($idx == 2) {fhem("set feuchte $val");;}\
     elsif ($idx == 3) {fhem("set ATgestern $val");;}\
     elsif ($idx == 7) {fhem("set rain $val");;}\    
   }\
   $idx=0;;\
   $val=0;;\
 }\
 elsif($_ =~m"<INDEX>(.*)</INDEX>"){\
   $idx = $1;;\
   Log 1, "Testidx $idx";;\
 }\
 elsif($_ =~m"<VALUE>(.*)</VALUE>"){\
   $val = $1;;\
   Log 1, "Testval $val";;\
 }\
}\
}


Gruss
Martin

oniT

Hi Martin,

ja, das Splitten habe ich verstanden. Es werden nun auch alle gesuchten Werte zum jeweiligen Index ausgegeben.

Eines habe ich jedoch genau Deine Befürchtung festgestellt.

ZitatProbleme koennte es geben, wenn der Wert (val) = 0 ist (kein Regen?). Dann wuerde nicht geschrieben. Du kannst daher auch

Hat ein Wert einmal eine 1 angenommen, bleibt dieser für immer stehen und die Triggertime wird nicht mehr aktualisiert. Der Wert selbst ist jedoch inzwischen wieder eine 0. Hat es damit etwas zu tun?


   .....
     if ($idx == 7) {fhem("set rain $val");;}\    
   }\
  $idx=0;;\
   $val=0;;\

 }\
 if($_ =~m"<INDEX>(.*)</INDEX>"){\
   ....


Was bedeutet das? Der Wert wird nach dem Durchlauf dann immer wieder auf 0 gesetzt? Zumindest funktioniert das so nicht.

Gruß
Tino
BBB - debian weezy - FHEM 5.7
HMLAN - HM-LC-Bl1-FM, HM-ES-PMSw1-PI, HM-LC-Sw1-FM, HM-TC-IT-WM-W-EU, HM-WDS40-TH-I, HM-Sen-Wa-Od, HM-Sec-RHS
Dimplex Wärmepumpe / Dimplex ZL 300 - Modbus TCP
SDM630M - Modbus TCP
SolarLog 200 / SMA SonnyBoy 1.5/2.5 - Modbus TCP

martinp876

wenn die Werte geschrieben wurden 'lösche' ich sie. Ist sauberer.

Du kannst folgendes machen:
nur auf den index abfragen, also
   if ($idx && $val){\
ersetzen durch
   if ($idx){\

dann kannst du noch
   $val=0;;\
ersetzen durch beispielsweise
   $val=999;;\

damit erkennst du, ob es ein Problem bei der Übertragung gegeben hat. Wenn kein Wert geliefert wird bekommst du 999 (oder einen Wert wie du willst).

Beispiel: Wenn der Wert fehlt, keine Ausgabe:

define html_aufruf_test at +*00:00:30 {\
my @ret=GetHttpFile("192.168.1.150", "/usr-cgi/xml.cgi?|A|1|10");;\
my @werte=split "\n",$ret[0];;\
my $val=0;;\
my $idx=0;;\
foreach (@werte){\
 if($_ =~m"</VARIABLE>"){\
   if ($idx && $val != 999){\
     if ($idx == 1) {fhem("set aussenwert $val");;}\
     elsif ($idx == 2) {fhem("set feuchte $val");;}\
     elsif ($idx == 3) {fhem("set ATgestern $val");;}\
     elsif ($idx == 7) {fhem("set rain $val");;}\    
   }\
   $idx=0;;\
   $val=999;;\
 }\
 elsif($_ =~m"<INDEX>(.*)</INDEX>"){\
   $idx = $1;;\
   Log 1, "Testidx $idx";;\
 }\
 elsif($_ =~m"<VALUE>(.*)</VALUE>"){\
   $val = $1;;\
   Log 1, "Testval $val";;\
 }\
}\
}


oder bei einem Fehler ausgaben des defaults (hier 999)
define html_aufruf_test at +*00:00:30 {\
my @ret=GetHttpFile("192.168.1.150", "/usr-cgi/xml.cgi?|A|1|10");;\
my @werte=split "\n",$ret[0];;\
my $val=0;;\
my $idx=0;;\
foreach (@werte){\
 if($_ =~m"</VARIABLE>"){\
   if ($idx){\
     if ($idx == 1) {fhem("set aussenwert $val");;}\
     elsif ($idx == 2) {fhem("set feuchte $val");;}\
     elsif ($idx == 3) {fhem("set ATgestern $val");;}\
     elsif ($idx == 7) {fhem("set rain $val");;}\    
   }\
   $idx=0;;\
   $val=999;;\
 }\
 elsif($_ =~m"<INDEX>(.*)</INDEX>"){\
   $idx = $1;;\
   Log 1, "Testidx $idx";;\
 }\
 elsif($_ =~m"<VALUE>(.*)</VALUE>"){\
   $val = $1;;\
   Log 1, "Testval $val";;\
 }\
}\
}

oniT

Hallo Martin,

Danke für Deine Hilfe. Es tut was es soll.

Eine letzte Anfrage noch dazu:

ZitatWenn es daran liegt wie lange dein device zum Antworten braucht sollte man den Prozess auslagern. Das ist auf User-level etwas komplexer (jedenfalls habe ich noch nicht nachgedacht darüber).

Meinst Du damit die Auslagerung in ein Modul?

Danke,

Gruß
TinoB
BBB - debian weezy - FHEM 5.7
HMLAN - HM-LC-Bl1-FM, HM-ES-PMSw1-PI, HM-LC-Sw1-FM, HM-TC-IT-WM-W-EU, HM-WDS40-TH-I, HM-Sen-Wa-Od, HM-Sec-RHS
Dimplex Wärmepumpe / Dimplex ZL 300 - Modbus TCP
SDM630M - Modbus TCP
SolarLog 200 / SMA SonnyBoy 1.5/2.5 - Modbus TCP

martinp876

Hallo TinoB,

nein, auslagern in einen anderen Prozess - ist hier zu kompliziert, besonders wenn es so funktioniert.
Zum Verstaendniss - manchmal muss man auf Antworten warten, so wie in deinem Fall. Wenn man aktiv wartet steht der Prozess und keiner kann mehr etwas machen bis es Warten beendet ist. Manchmal kann man passiv warten, sprich man startet und schaut nach ob ein Ergebnis nach einer Zeit eingetroffen ist - oder wird vom Ergebniss geweckt. Hierbei arbeitet der Process weiter an anderen Aufgaben.
FHEM ist (im Wesentlichen) nur ein Prozess. Wenn man also aktiv wartet (warten muss wie in deinem Fall auf die Antwort des 'Ethernet') bleibt alles andere liegen.
Man kann das Warten auch auslagern, also einen 2. Prozess starten. Dann kann der hauptprozess weiter arbeiten. Der 2. muss dann irgendwann sein Ergebniss an den Ersten ruecksenden.
FHEM hat mittlerweile Mechanismen um ein paar Dinge 'auszulagern' in einen 2. Prozess.

Module in FHEM arbeiten alle in einem Prozess - das wuerde also nichts bringen.

Gruss Martin

oniT

Hallo Martin,

Danke für die Erklärung. Das würde ja bedeuten, dass immer nur ein Prozess nach dem anderen abgearbeitet würde. Das würde doch dann wiederum aber auch bedeuten, dass wenn zu viele Prozesse in FHEM integriert sind, dann FHEM irgendwann überfordert ist. Ist das dann auch abhängig vom System? Also in meinem Fall einer FritzBox. Die macht ja nebenbei auch noch andere Dinge.

Ein Beispiel wo mir dies in FHEM aufgefallen ist, beim Plotaufruf von zu großen Logdateien steigt HMLAN ebenfalls mit den Disconnects aus. Also wenn dieser eine gewisse Zeit übersteigt.

Somit kann man dies dann nur mit Tunning umgehen. Richtig? Aber irgendwann kann man dann tunnen wie man will, wenn zu viele Aufgaben anstehen. Richtig? Das System ist also irgendwann voll.

Ist dann sozusagen wie im richtigen Leben, irgendwann ist dann eine Überforderung da, wenn man zu viel will ;-)

Danke

Gruß,
TinoB
BBB - debian weezy - FHEM 5.7
HMLAN - HM-LC-Bl1-FM, HM-ES-PMSw1-PI, HM-LC-Sw1-FM, HM-TC-IT-WM-W-EU, HM-WDS40-TH-I, HM-Sen-Wa-Od, HM-Sec-RHS
Dimplex Wärmepumpe / Dimplex ZL 300 - Modbus TCP
SDM630M - Modbus TCP
SolarLog 200 / SMA SonnyBoy 1.5/2.5 - Modbus TCP

martinp876

Hallo TinoB,

Zum einen hast du eine begrenzte Anzahl CPUs (die FB nur eine). Linux auf der FB verwaltet alle Prozesse und steuert, wer dran kommt. Da kommen wir nicht vorbei, FHEM muss sich mit den anderen Processen arrangieren.

FHEM läuft primär in einem Prozess, nur in Ausnahmen werden anderen Prozesse gestartet. Also alle Aufgaben werden innerhalb FHEM nacheinander abgearbeitet.

Der Plot laeuft im FHEM Prozess. Es sind hier viele Dinge zu berücksichtigen
- die benötigte CPU zeit wird benötigt, da geht nichts vorbei
- falls der Task warten muss, muss dies auch FHEM (wie bei deinem Problem)

Generell ist deine Beschreibung korrekt. Was man in einem sicherheitsrelevanten Echtzeitsystem machen muesste ist, alle backend Tasks in low-prio Processe auslagern, eine ganze Struktur von Processen starten (schon das Schreiben auf ein File sollte nicht mit der Kommunikation und den Schaltkommandos auf einem Level stehen). Eine inter-prozess kommunikation aufbauen, damit sich die Prozesse unterhalten koennen.

Das waere ziemlich viel Arbeit. Dennoch koennte ein Prozess, der nicht zu FHEM gehört alles zu nichte machen.

Erste Aktionen sind im werden, dass herausragend lange wartende Tasks ausgelagert werden.

Gruss Martin