2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-22 02:10:32 +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 # Prof. Dr. Peter A. Henning, 2013
# #
# Version 0.1 - November 2013 # Version 1.0 - December 2013
# #
# Setup as: # Setup as:
# define <name> PT8005 <device> # define <name> PT8005 <device>
@ -59,6 +59,15 @@ my $mode ="normal"; # min/max/...
my $range="50-100 dB"; # measurement range my $range="50-100 dB"; # measurement range
my $over =""; # over/underflow 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 #-- These we may get on request
my %gets = ( my %gets = (
"present" => "", "present" => "",
@ -141,7 +150,81 @@ sub PT8005_Define($$) {
return undef; 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 # PT8005_Cmd - Write command to meter
# #
@ -249,6 +332,9 @@ sub PT8005_GetStatus ($) {
my $nodata=1; my $nodata=1;
my $loop=0; my $loop=0;
my $secsincemidnight;
my $av15=0;
#-- restart timer for updates #-- restart timer for updates
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+ $hash->{INTERVAL}, "PT8005_GetStatus", $hash,1); InternalTimer(gettimeofday()+ $hash->{INTERVAL}, "PT8005_GetStatus", $hash,1);
@ -279,7 +365,7 @@ sub PT8005_GetStatus ($) {
select(undef,undef,undef,0.15); select(undef,undef,undef,0.15);
#-- loop for the data #-- 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); #my $string_in=PT8005_Read($hash);
select(undef,undef,undef,0.02); select(undef,undef,undef,0.02);
my ($count_in, $string_in) = $serport->read(64); my ($count_in, $string_in) = $serport->read(64);
@ -350,20 +436,24 @@ sub PT8005_GetStatus ($) {
#-- data value #-- data value
my $in_data = index($string_in,"\xA5\x0D"); my $in_data = index($string_in,"\xA5\x0D");
if( $in_data != -1){ if( $in_data != -1){
$nodata=0; my $s1=substr($string_in,$in_data+2,1);
$bcd=ord(substr($string_in,$in_data+2,1)); my $s2=substr($string_in,$in_data+3,1);
$data=(int($bcd/16)*10 + $bcd%16)*10; if( ($s1 ne "") && ($s2 ne "") ){
$bcd=ord(substr($string_in,$in_data+3,1)); $nodata = 0;
$data+=(int($bcd/16)*10 + $bcd%16)*0.1; $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 #-- sleeping some time
select(undef,undef,undef,0.02); select(undef,undef,undef,0.01);
#-- leave recording mode #-- leave recording mode
$count_out = $serport->write($SKC{"rec"}); $count_out = $serport->write($SKC{"rec"});
#-- sleeping some time #-- sleeping some time
select(undef,undef,undef,0.02); select(undef,undef,undef,0.01);
#-- #--
$serport->close(); $serport->close();
@ -389,11 +479,15 @@ sub PT8005_GetStatus ($) {
} }
#-- put into readings #-- put into readings
$hash->{READINGS}{"soundlevel"}{UNIT} = $freq
if( $nofreq ==0 );
$hash->{READINGS}{"soundlevel"}{UNITABBR} = $freq
if( $nofreq ==0 );
$hash->{READINGS}{"soundlevel"}{UNIT} = $freq; #-- testing for wrong data value
$hash->{READINGS}{"soundlevel"}{UNITABBR} = $freq; if( $data <=30 ){
$nodata=1;
my $svalue = sprintf("%3.1f %s",$data,$freq); };
#-- put into READINGS #-- put into READINGS
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
@ -403,11 +497,25 @@ sub PT8005_GetStatus ($) {
readingsBulkUpdate($hash,"range",$range) readingsBulkUpdate($hash,"range",$range)
if( $norange ==0 ); if( $norange ==0 );
readingsBulkUpdate($hash,"overflow",$over); readingsBulkUpdate($hash,"overflow",$over);
readingsBulkUpdate($hash,"soundlevel",$data)
if( $nodata ==0 ); if( $nodata==0 ){
#-- STATE
readingsBulkUpdate($hash,"state",$svalue) my ($sec, $min, $hour, $day, $month, $year, $wday,$yday,$isdst) = localtime(time);
if( $nodata ==0 ); $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); readingsEndUpdate($hash,1);
} }
@ -503,7 +611,7 @@ sub PT8005_Set ($@) {
$serport->handshake('none'); $serport->handshake('none');
$serport->write_settings; $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 #-- read data and look if it is nonzero
my ($count_in, $string_in) = $serport->read(1); my ($count_in, $string_in) = $serport->read(1);
if( $string_in eq "" ){ if( $string_in eq "" ){
@ -512,10 +620,10 @@ sub PT8005_Set ($@) {
return 1; return 1;
} else { } else {
#-- leave recording mode #-- leave recording mode
select(undef,undef,undef,0.01); select(undef,undef,undef,0.02);
my $count_out = $serport->write($SKC{"rec"}); my $count_out = $serport->write($SKC{"rec"});
#-- sleeping some time #-- sleeping some time
select(undef,undef,undef,0.01); select(undef,undef,undef,0.02);
} }
} }
$serport->close(); $serport->close();