Hallo,
mein Ölstand wird mir über einen "LevelJet" seriell geliefert. Der sendet 24 Bytes einmal pro Sekunde.
Zum Auslesen hab ich mir eine Funktuin in MyUtils geschrieben. Funktioniert soweit, allerdings nach längerm Stillstand nicht mehr, d.h. am nächsten Tag bekomme ich keine Daten mehr an der Schnittstelle.
Wenn ich die Myutils in FHEM öffnen und nur neu speichere, funktioniert die Abfrage sofort wieder. Anders bekomme ich die Funktion nicht mehr zum laufen.
Wiederholungen sind genuegend eingebaut.
Was passiert beim speichern der Datei in FHEM bzw. warum funktioniert es danach IMMER ?
sub LevelJet_Read ($$)
{
Log 1, "LevelJet->Start-------------------------------------------";
my ($index, $PortName) = @_;
my $data = '';
my $count = 0;
my $result = 0;
my $liter = 0;
my $idx = 0;
my $port = 0;
my $abstand = 0;
my $hoehe = 0;
my $oldvalue = 0;
my $newvalue = 0;
$| = 1;
$port = Device::SerialPort->new ($PortName);
if (!defined ($port))
{
Log 1, "LevelJet-Port ($PortName) konnte nicht geoeffnet werden !";
return;
}
$port->databits(8);
$port->baudrate(19200);
$port->parity('none');
$port->stopbits(1);
$port->datatype('raw');
$port->handshake("none");
$port->read_char_time(5); # wait for each character
$port->read_const_time(150); # max. read time in milliseconds
$port->write_settings ();
# Puffer leeren
$data = $port->input;
$port->purge_all;
$data = $port->input;
# in Intervallen versuchen, die 12 Worte zu lesen
# kommen normalerweise im Sekundentakt vom Leveljet
for ($idx = 1 ; $idx <= 100 ; $idx ++)
{
# ($count,$data) = $port->read(255);
$data = $port->input;
$data= unpack('H*',$data);
$count = length($data)/2;
#print "\nLevelJet->(Read($idx): ".$data.", Laenge: ".$count."\n";
# Falls zu viele Daten, dann die letzten 12 Worte nehmen
if ($count > 12) {
$data = substr($data, length($data)-24, 24);
$count = 12;
#print "\nLevelJet->Letzte 12 Bytes: ".$data." CRC: ".LevelTestCRC($data)."\n";
}
# Wenn alles passt, dann raus aus Schleife
if ($count == 12) {
if ((LevelTestCRC($data) == 1) && (substr($data, 0,2) eq "00") && (substr($data, 2,2) eq "10")) {last};
}
$port->read_char_time($idx); # wait for each character. Zum Test erhoehen
$port->purge_all;
sleep(0.1);
}
$port->close();
...
...
...
Ideen ?
Gruss
Joe
Warum beim Speichern von 99_myUtils.pm weitergeht, kann ich nicht wirklich erklaeren, es wird dabei eigentlich nur 99_myUtils.pm erneut eingelesen. Evtl. hilft dabei ein Blick ins fhem.log.
Fuer alle Mitleser/Anfaenger: Abhaengig davon, wie diese Routine aufgerufen wird, kann sie FHEM blockieren. "Richtige" Module verwenden DevIo_OpenDev zum oeffnen der Schnittstelle und eine ReadFn, die aufgerufen wird, falls Daten zur Verfuegung stehen. Bin aber unsicher, ob ein Umbau auf diese Methode das hier beschriebene Problem loest.
Globale Parameter wie $| zu aendern kann in anderen Modulen Nebeneffekte haben.
Hier (https://forum.fhem.de/index.php?topic=27315.0) gibt es ein sinngemäß passendes Modul zum abgucken.
Hi,
Der LevelJet liefert seine Daten im Sekundentakt und das ist nicht aenderbar.
Im Modul das ich nun erstellt habe liest FHEM jetzt im Sekundentakt die Schnittstelle aus was meine Prozessorzeit hoch nach oben zieht was ja nicht gewünscht war.
Deshalb hatte ich eine Funktion, die mir einmal am Tag den Wert auslas. Lieber einmal am Tag eine Sekunde CPU-Last als unnötig den ganzen Tag lang.
Wie kann ich das auslesen im Sekundentakt im Modul verhindern und meine CPU-Last wieder senken ?
Gruss
Joe
die internaltimer Funktion ist dafür hilfreich. Anwendung findest Du z.B. im OBIS-Modul, wo ein "attr device interval sec" angelegt werden kann.
Grüße Markus
Das KM271 FHEM Modul liest Daten, die ununterbrochen mit 2400Baud gesendet werden, und mein Rechner bzw. FHEM hat damit seit ca 8 Jahren kein Problem. Will sagen: wenn man das richtig macht (mit DevioOpendev/ReadFn, und nur bei relevanten Aenderungen Event generieren), dann belastet sowas das System kaum.