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.