logFromArray
Häufig besteht in FHEM das Problem, dass man in einem Plot, dargestellt durch das SVG-Modul, zusätzliche Daten darstellen möchte. Das Hilfsmodul logProxy bietet dafür u.a. die Möglichkeit, eine horizontale oder vertikale Linie zu ziehen.
Mit dem folgenden Code kann man nun beliebige Array-Daten aus irgendeinem Device passgenau so umwandeln, dass sie in einen Plot eingefügt werden können. Das Perl-Programm logFromArray wird mit mehreren Parametern aufgerufen:
- filename - der Name der zu beschreibenden Log-Datei
- device - Der Name des FHEM-Device, welches die zu schreibenden Array-Daten enthält
- reading - Der Name des Readings, in welchem die zu schreibenden Array-Daten liegen. Diese Daten müssen in Form einer durch einen Separator (z.B. ein Komma) getrennten Liste vorliegen.
- optional: fcsep - Ein String, der den Separator enthält (default=Komma)
- optional: fcday - Eine Zahl, die angibt, wie viele Tage in die Zukunft das Log verschoben werden soll. 0=default heißt, die Log-Datei wird für den heutigen Tage angelegt, 1 bedeutet den folgenden Tag, etc.
- optional: fcstart - Eine Uhrzeitangabe, wann das Log beginnen soll. 00:00 ist der Default-Wert
- optional: fctype - 0=default oder 1. Wenn man die configDB verwendet, schreibt FHEM Daten gerne in diese. Um das zu vermeiden, kann mit einem Wert 1 erzwungen werden, dass das Logfile im Dateisystem landet.
Hier nun zunächst der Code: (Klicke auf "Ausklappen", um die Anzeige auszuklappen)
Code:
############################################################################### # # Log file format from array # # Parameter: filename:obvious, isn't it? # device: FHEM device for reading data # reading: Name of the reading containing a data array # optional # fcsep: separator for the array, default= "," # fcres: time resolution for the array in minutes, 1..1440; # deafult= 60 # ==> Determines the number of expected values # fcday: 0=today=default,1=tomorrow,2=day after tomorrow, etc. # fcstart: starting time for log xx:xx, default= 00:00 # fctype: 0=default or 1. In case of using configDB, a value # of 1 enforces writing to the file system instead of the # configdb # ############################################################################### sub logFromArray($$$;$$$$$){ my ($filename,$device,$reading,$fcsep,$fcres,$fcday,$fcstart,$fctype) = @_; #-- get data my $raw = ReadingsVal($device,$reading,undef); if( !$raw){ Log 1,"[logFromArray] no data available in reading $reading of device $device"; return } #-- default values $fcsep = "," if(!$fcsep); $fcres = 60 if(!$fcres); $fcday = 0 if(!defined($fcday)); $fcstart = "00:00" if(!defined($fcstart)); $fctype = 1 if(!defined($fctype)); #-- check data my $num = int(1440/$fcres); if( $num < 1 || $num > 1440){ Log 1,"[logFromArray] invalid time resolution, must be 1..1440"; return } if( $fcstart !~ /(\d\d):(\d\d)/){ Log 1,"[logFromArray] improper start time specification, must be xx:xx with x=digit"; return } my $lhour=$1; my $lmin=$2; my @data = split($fcsep,$raw); if( int(@data)!=$num){ Log 1,"[logFromArray] invalid data number in reading $reading of device $device, expecting $num values sepatated by $fcsep"; return } #-- prepare output my @ldata=(); my $lstart=int(time-time%86400-7200)+$fcday*86400+$lhour*3600+$lmin*60; for (my $i=0;$i<$num;$i++){ push(@ldata,strftime( "%Y-%m-%d_%H:%M:%S",localtime( $lstart+$i*$fcres*60))." $device $reading $data[$i]"); } #-- write data my $ret; if( $fctype !=1 ){ $ret=FileWrite($filename,@ldata); }else{ my $param = { FileName => $filename, ForceType => "file", NoNL => 0 }; $ret=FileWrite($param,@ldata); } return $ret }
Diese Code sollte in eine Utils-Datei eingefügt werden, z.B. in die 99_myUtils.pm. Nicht vergessen, diese neu zu laden.