2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-23 14:46:24 +00:00

git-svn-id: https://svn.fhem.de/fhem/trunk@4324 2b470e98-0d58-463d-a4d8-8e2adae1ed80

This commit is contained in:
pahenning 2013-12-05 07:26:24 +00:00
parent 1ab0a1e245
commit 3beb3f5f83

View File

@ -6,7 +6,7 @@
#
# Prof. Dr. Peter A. Henning, 2013
#
# Version 0.1 - November 2013
# Version 1.0 - December 2013
#
# Setup as:
# define <name> PT8005 <device>
@ -59,6 +59,15 @@ my $mode ="normal"; # min/max/...
my $range="50-100 dB"; # measurement range
my $over =""; # over/underflow
#-- arrays for averaging (60 values = max. 1 hour)
my @datarr;
my @timarr;
my $arrind=0;
my $arrmax=60;
#-- arrays for hourly values
my @hourarr;
#-- These we may get on request
my %gets = (
"present" => "",
@ -141,7 +150,81 @@ sub PT8005_Define($$) {
return undef;
}
#######################################################################################
#
# PT8005_Average - Average backwards over given period
#
# Parameter hash, secsincemidnight,period
#
########################################################################################
sub PT8005_Average($$$) {
my ($hash, $secsincemidnight, $period) = @_;
#-- max. 1 hour allowed
if( $period>3600 ){
Log 1,"PT8005_Average: wrong period, must be <=3600";
return 0;
}
my ($minind,$cntind,$oldtime,$ia,$ib,$fa,$fb,$ta,$tb,$fd,$avdata);
#-- go backwards until we have period covered (=max. 60 values)
$minind=$arrind-1;
$cntind=1;
$minind+=$arrmax if($minind<0);
$oldtime = $timarr[$minind];
$oldtime-=86400 if($oldtime > $secsincemidnight);
while( $oldtime > $secsincemidnight-$period ){
#Log 1,"===>index $minind is ".($secsincemidnight-$timarr[$minind])." ago";
$minind--;
$minind+=$arrmax if($minind<0);
$oldtime = $timarr[$minind];
$oldtime-=86400 if($oldtime > $secsincemidnight);
$cntind++;
if( $cntind > $arrmax) {
$cntind=$arrmax;
Log 1,"PT8005_Average: ERROR, cntind > $arrmax";
last;
}
}
#-- now go forwards
#-- first value must be done by hand
$ia = $minind;
$ib = $minind+1;
$ib-=$arrmax if($ib>=$arrmax);
$fa = $datarr[$ia];
$fb = $datarr[$ib];
$ta = $timarr[$ia];
$ta-= 86400 if($ta > $secsincemidnight);
$tb = $timarr[$ib];
$tb-= 86400 if($tb > $secsincemidnight);
$fd = $fa + ($fb-$fa)*($secsincemidnight-$period - $ta)/($tb - $ta);
$avdata = ($fd + $fb)/2 * ($tb - ($secsincemidnight-$period));
#Log 1,"===> interpolated value for data point between $ia and $ib is $fd and avdata=$avdata (tb=$tb, ssm=$secsincemidnight)";
#-- other values can be done automatically
for( my $i=1; $i<$cntind; $i++){
$ia = $minind+$i;
$ia-= $arrmax if($ia>=$arrmax);
$ib = $ia+1;
$ib-= $arrmax if($ib>=$arrmax);
$fa = $datarr[$ia];
$fb = $datarr[$ib];
$ta = $timarr[$ia];
$ta-= 86400 if($ta > $secsincemidnight);
$tb = $timarr[$ib];
$tb-= 86400 if($tb > $secsincemidnight);
$avdata += ($fa + $fb)/2 * ($tb - $ta);
#Log 1,"===> adding a new interval between $ia and $ib, new avdata = $avdata (tb=$tb ta=$ta)";
}
#-- and now the average for 15 minutes:
$avdata = int($avdata/($period/10))/10;
return $avdata;
}
#########################################################################################
#
# PT8005_Cmd - Write command to meter
#
@ -249,6 +332,9 @@ sub PT8005_GetStatus ($) {
my $nodata=1;
my $loop=0;
my $secsincemidnight;
my $av15=0;
#-- restart timer for updates
RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+ $hash->{INTERVAL}, "PT8005_GetStatus", $hash,1);
@ -279,7 +365,7 @@ sub PT8005_GetStatus ($) {
select(undef,undef,undef,0.15);
#-- loop for the data
while ( ($nospeed+$norange+$nofreq+$nodata > 0) and ($loop <3) ){
while ( ($nodata > 0) and ($loop <3) ){
#my $string_in=PT8005_Read($hash);
select(undef,undef,undef,0.02);
my ($count_in, $string_in) = $serport->read(64);
@ -350,20 +436,24 @@ sub PT8005_GetStatus ($) {
#-- data value
my $in_data = index($string_in,"\xA5\x0D");
if( $in_data != -1){
$nodata=0;
$bcd=ord(substr($string_in,$in_data+2,1));
$data=(int($bcd/16)*10 + $bcd%16)*10;
$bcd=ord(substr($string_in,$in_data+3,1));
$data+=(int($bcd/16)*10 + $bcd%16)*0.1;
my $s1=substr($string_in,$in_data+2,1);
my $s2=substr($string_in,$in_data+3,1);
if( ($s1 ne "") && ($s2 ne "") ){
$nodata = 0;
$bcd=ord($s1);
$data=(int($bcd/16)*10 + $bcd%16)*10;
$bcd=ord($s2);
$data+=(int($bcd/16)*10 + $bcd%16)*0.1;
}
}
}
#-- sleeping some time
select(undef,undef,undef,0.02);
select(undef,undef,undef,0.01);
#-- leave recording mode
$count_out = $serport->write($SKC{"rec"});
#-- sleeping some time
select(undef,undef,undef,0.02);
select(undef,undef,undef,0.01);
#--
$serport->close();
@ -389,11 +479,15 @@ sub PT8005_GetStatus ($) {
}
#-- put into readings
$hash->{READINGS}{"soundlevel"}{UNIT} = $freq
if( $nofreq ==0 );
$hash->{READINGS}{"soundlevel"}{UNITABBR} = $freq
if( $nofreq ==0 );
$hash->{READINGS}{"soundlevel"}{UNIT} = $freq;
$hash->{READINGS}{"soundlevel"}{UNITABBR} = $freq;
my $svalue = sprintf("%3.1f %s",$data,$freq);
#-- testing for wrong data value
if( $data <=30 ){
$nodata=1;
};
#-- put into READINGS
readingsBeginUpdate($hash);
@ -403,11 +497,25 @@ sub PT8005_GetStatus ($) {
readingsBulkUpdate($hash,"range",$range)
if( $norange ==0 );
readingsBulkUpdate($hash,"overflow",$over);
readingsBulkUpdate($hash,"soundlevel",$data)
if( $nodata ==0 );
#-- STATE
readingsBulkUpdate($hash,"state",$svalue)
if( $nodata ==0 );
if( $nodata==0 ){
my ($sec, $min, $hour, $day, $month, $year, $wday,$yday,$isdst) = localtime(time);
$secsincemidnight = $hour*3600+$min*60+$sec;
$datarr[$arrind] = $data;
$timarr[$arrind] = $secsincemidnight;
$av15 = PT8005_Average($hash,$secsincemidnight,900);
$arrind++;
$arrind-=$arrmax if($arrind>=$arrmax);
my $svalue = sprintf("%3.1f %s [av15 %3.1f %s]",$data,$freq,$av15,$freq);
my $lvalue = sprintf("%3.1f av15 %3.1f ",$data,$av15);
readingsBulkUpdate($hash,"state",$svalue);
readingsBulkUpdate($hash,"soundlevel",$lvalue);
}
readingsEndUpdate($hash,1);
}
@ -503,7 +611,7 @@ sub PT8005_Set ($@) {
$serport->handshake('none');
$serport->write_settings;
for(my $i = 0; $i < 4; $i++) {
for(my $i = 0; $i < 3; $i++) {
#-- read data and look if it is nonzero
my ($count_in, $string_in) = $serport->read(1);
if( $string_in eq "" ){
@ -512,10 +620,10 @@ sub PT8005_Set ($@) {
return 1;
} else {
#-- leave recording mode
select(undef,undef,undef,0.01);
select(undef,undef,undef,0.02);
my $count_out = $serport->write($SKC{"rec"});
#-- sleeping some time
select(undef,undef,undef,0.01);
select(undef,undef,undef,0.02);
}
}
$serport->close();