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:
parent
1ab0a1e245
commit
3beb3f5f83
@ -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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user