| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818 |
- ########################################################################################
- #
- # PT8005.pm
- #
- # FHEM module to read the data from a PeakTech PT8005 sound level meter
- #
- # Prof. Dr. Peter A. Henning, 2014
- #
- # Version 1.3 - January 2014
- #
- # setup, set/get functions and attributes see HTML text at bottom
- #
- ########################################################################################
- #
- # This programm is free software; you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation; either version 2 of the License, or
- # (at your option) any later version.
- #
- # The GNU General Public License can be found at
- # http://www.gnu.org/copyleft/gpl.html.
- # A copy is found in the textfile GPL.txt and important notices to the license
- # from the author is found in LICENSE.txt distributed with these scripts.
- #
- # This script is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- ########################################################################################
- package main;
- use strict;
- use warnings;
- use Device::SerialPort;
- use vars qw{%attr %defs};
- sub Log($$);
- #-- globals on start
- my $freq ="db(A)"; # dB(A) or dB(C)
- my $speed="fast"; # response speed fast or slow
- my $mode ="normal"; # min/max/...
- my $range="50-100 dB"; # measurement range
- my $over =""; # over/underflow
- #-- arrays for averaging (max 60 values per hour)
- my @noisearr;
- my @timearr;
- my $arrind=0;
- my $arrmax=70;
- my @noisehour;
- my $noisenight="";
- my $noiseday="";
- #-- arrays for hourly values
- my @hourarr;
- #-- These we may get on request
- my %gets = (
- "present" => "",
- "reading" => "R",
- );
- #-- These occur in a pulldown menu as settable values
- my %sets = (
- "interval" => "T",
- "Min/Max"=> "",
- "off" => "O",
- "rec" => "",
- "speed" => "",
- "range" => "", # toggle the measurement range
- "auto" => "", # set the measurement range to auto
- "dBA/C" => "", # toggle the frequency curve
- "freq" => "" # set the frequency curve to a value db(A) or db(C)
- );
- #-- Single key commands to the PT8005
- my %SKC = ("Min/Max","\x11", "off","\x33", "rec","\x55", "speed","\x77", "range","\x88", "dBA/C","\x99");
- ########################################################################################
- #
- # PT8005_Initialize
- #
- # Parameter hash
- #
- ########################################################################################
- sub PT8005_Initialize ($) {
- my ($hash) = @_;
-
- $hash->{DefFn} = "PT8005_Define";
- $hash->{GetFn} = "PT8005_Get";
- $hash->{SetFn} = "PT8005_Set";
- # LogM, LogY = name of the monthly and yearly log file
- $hash->{AttrList}= "LogM LogY LimNight LimDay ".
- "loglevel ".
- $readingFnAttributes;
- }
- ########################################################################################
- #
- # PT8005_Define - Implements DefFn function
- #
- # Parameter hash, definition string
- #
- ########################################################################################
- sub PT8005_Define($$) {
- my ($hash, $def) = @_;
- my @a = split("[ \t][ \t]*", $def);
- return "Define the serial device as a parameter"
- if(@a != 3);
-
- my $dev = $a[2];
- Log 1, "PT8005 opening device $dev";
- my $pt8005_serport = new Device::SerialPort ($dev);
- return "PT8005 Can't open $dev: $!" if(!$pt8005_serport);
- Log 1, "PT8005 opened device $dev";
- $hash->{USBDev} = $pt8005_serport;
- sleep(1);
- $pt8005_serport->close();
-
- $hash->{DeviceName} = $dev;
- $hash->{interval} = 60; # call every 60 seconds
-
- $modules{PT8005}{defptr}{$a[0]} = $hash;
- #-- InternalTimer blocks if init_done is not true
- my $oid = $init_done;
- $init_done = 1;
- readingsSingleUpdate($hash,"state","initialized",1);
-
- PT8005_GetStatus($hash);
- $init_done = $oid;
- 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>60*$arrmax ){
- Log 1,"PT8005_Average: wrong averaging period $period, must be <= ".(60*$arrmax);
- return "";
- }
- my ($minind,$cntind,$oldtime,$ia,$ib,$fa,$fb,$ta,$tb,$fd,$avdata);
-
- #-- go backwards until we have period covered (=max. arrmax values)
- $minind=$arrind-1;
- $cntind=1;
- $minind+=$arrmax if($minind<0);
- $oldtime = $timearr[$minind];
- #-- no average if the previous time is undefined
- if( (!defined($oldtime)) || !($oldtime>0) ){
- Log 4,"PT8005_Average: invalid measurement at index $minind, no average possible";
- return "";
- }
- $oldtime-=86400 if($oldtime > $secsincemidnight);
- while( $oldtime > ($secsincemidnight-$period) ){
- #Log 1,"===>index $minind is ".($secsincemidnight-$timearr[$minind])." ago";
- $minind--;
- $minind+=$arrmax if($minind<0);
- $oldtime = $timearr[$minind];
- #-- no average if the previous time is undefined
- if( (!defined($oldtime)) || !($oldtime>0) ){
- Log 4,"PT8005_Average: invalid measurement at index $minind, no average possible";
- return "";
- }
- $oldtime-=86400 if($oldtime > $secsincemidnight);
- $cntind++;
- if( $cntind > $arrmax) {
- $cntind=$arrmax;
- Log 4,"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 = $noisearr[$ia];
- $fb = $noisearr[$ib];
- $ta = $timearr[$ia];
- $ta-= 86400 if($ta > $secsincemidnight);
- $tb = $timearr[$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 = $noisearr[$ia];
- $fb = $noisearr[$ib];
- $ta = $timearr[$ia];
- $ta-= 86400 if($ta > $secsincemidnight);
- $tb = $timearr[$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 the period
- $avdata = int($avdata/($period/10))/10;
-
- return $avdata;
- }
-
- #########################################################################################
- #
- # PT8005_Cmd - Write command to meter
- #
- # Parameter hash, cmd = command
- #
- ########################################################################################
- sub PT8005_Cmd ($$) {
- my ($hash, $cmd) = @_;
- my $res;
- my $dev= $hash->{DeviceName};
- my $name = $hash->{NAME};
- my $serport = new Device::SerialPort ($dev);
-
- if(!$serport) {
- Log GetLogLevel($name,1), "PT8005: Can't open $dev: $!";
- return undef;
- }
- $serport->reset_error();
- $serport->baudrate(9600);
- $serport->databits(8);
- $serport->parity('none');
- $serport->stopbits(1);
- $serport->handshake('none');
- $serport->write_settings;
-
- #-- calculate checksum and send
- #my $cmd="\x33";
- my $count_out = $serport->write($cmd);
- Log GetLogLevel($name,3), "PT8005 write failed\n" unless ($count_out);
- #-- sleeping 0.05 seconds
- select(undef,undef,undef,0.05);
- my ($count_in, $string_in) = $serport->read(4);
- #-- control
- #my ($i,$j,$k);
- #my $ans="receiving:";
- #for($i=0;$i<$count_in;$i++){
- # $j=int(ord(substr($string_in,$i,1))/16);
- # $k=ord(substr($string_in,$i,1))%16;
- # $ans.="byte $i = 0x$j$k\n";
- #}
- #Log 1, $ans;
- #-- sleeping 0.05 seconds
- select(undef,undef,undef,0.05);
- $serport->close();
- }
-
- ########################################################################################
- #
- # PT8005_Get - Implements GetFn function
- #
- # Parameter hash, argument array
- #
- ########################################################################################
- sub PT8005_Get ($@) {
- my ($hash, @a) = @_;
- #-- check syntax
- return "PT8005_Get needs exactly one parameter" if(@a != 2);
- my $name = $hash->{NAME};
- my $v;
- #-- get present
- if($a[1] eq "present") {
- $v = ($hash->{READINGS}{"state"}{VAL} =~ m/.*dB.*/) ? 1 : 0;
- return "$a[0] present => $v";
- }
- #-- current reading
- if($a[1] eq "reading") {
- $v = PT8005_GetStatus($hash);
- if(!defined($v)) {
- Log GetLogLevel($name,2), "PT8005_Get $a[1] error";
- return "$a[0] $a[1] => Error";
- }
- $v =~ s/[\r\n]//g; # Delete the NewLine
- } else {
- return "PT8005_Get with unknown argument $a[1], choose one of " . join(" ", sort keys %gets);
- }
- Log GetLogLevel($name,3), "PT8005_Get $a[1] $v";
- return "$a[0] $a[1] => $v";
- }
-
- #######################################################################################
- #
- # PT8005 - GetStatus - Called in regular intervals to obtain current reading
- #
- # Parameter hash
- #
- ########################################################################################
- sub PT8005_GetStatus ($) {
- my ($hash) = @_;
- my $name = $hash->{NAME};
-
- my ($bcd,$i,$j,$k);
- my $data = 0.0;
- my $nospeed = 1;
- my $norange = 1;
- my $nofreq = 1;
- my $nodata = 1;
- my $loop = 0;
-
- my $secsincemidnight;
- my $av15 = "";
- my $av60 = "";
- my $avnight = 0;
- my $avday = 0;
- my $avcnt = 0;
-
- my $svalue;
- my $lvalue;
- my $hvalue;
- #-- restart timer for updates
- RemoveInternalTimer($hash);
- InternalTimer(gettimeofday() + $hash->{interval}, "PT8005_GetStatus", $hash,1);
- #-- check if rec is really off
- PT8005_Unrec($hash);
-
- #-- Obtain the current reading
- my $res;
- my $dev= $hash->{DeviceName};
- my $serport = new Device::SerialPort ($dev);
-
- if(!$serport) {
- Log GetLogLevel($name,3), "PT8005_Read: Can't open $dev: $!";
- return undef;
- }
- $serport->reset_error();
- $serport->baudrate(9600);
- $serport->databits(8);
- $serport->parity('none');
- $serport->stopbits(1);
- $serport->handshake('none');
- $serport->write_settings;
-
- #-- switch into recording mode
- my $count_out = $serport->write($SKC{"rec"});
- Log GetLogLevel($name,3), "PT8005_GetStatus: Switch to REC failed" unless ($count_out);
- #-- sleeping some time
- select(undef,undef,undef,0.15);
-
- #-- loop for the data
- 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);
- $loop++;
-
- #--find data items
- if( index($string_in,"\xA5\x02") != -1){
- $nospeed=0;
- $speed="fast";
- } elsif( index($string_in,"\xA5\x03") != -1){
- $nospeed=0;
- $speed="slow";
- }
-
- if( index($string_in,"\xA5\x04") != -1){
- $mode="max";
- }elsif( index($string_in,"\xA5\x05") != -1){
- $mode="min";
- }else{
- $mode="normal";
- }
-
- if( index($string_in,"\xA5\x10") != -1){
- $norange=0;
- $range="30-80 dB";
- }elsif( index($string_in,"\xA5\x20") != -1){
- $norange=0;
- $range="50-100 dB";
- }elsif( index($string_in,"\xA5\x30") != -1){
- $norange=0;
- $range="80-130 dB";
- }elsif( index($string_in,"\xA5\x40") != -1){
- $norange=0;
- $range="30-130 dB";
- }
-
- if( index($string_in,"\xA5\x07") != -1){
- $over="over";
- }elsif( index($string_in,"\xA5\x08") != -1){
- $over="under";
- }else{
- $over="";
- }
-
- if( index($string_in,"\xA5\x1B") == -1){
- $nofreq=0;
- $freq="dB(A)";
- } elsif ( index($string_in,"\xA5\x1C") != -1){
- $nofreq=0;
- $freq="dB(C)";
- }
-
- #-- time not needed
- #my $in_time = index($string_in,"\xA5\x06");
- #if( $in_time != -1 ){
- # $bcd=ord(substr($string_in,$in_time+2,1));
- # $hour=int($bcd/16)*10 + $bcd%16 - 20;
- # $bcd=ord(substr($string_in,$in_time+3,1));
- # $min = int($bcd/16)*10 + $bcd%16;
- # $bcd=ord(substr($string_in,$in_time+4,1));
- # $sec = int($bcd/16)*10 + $bcd%16;
- # $time=sprintf("%02d:%02d:%02d",$hour,$min,$sec);
- #} else {
- # $time="undef";
- # Log GetLogLevel($name,3),"PT8005_GetStatus: no time value obtained"
- #}
-
- #-- data value
- my $in_data = index($string_in,"\xA5\x0D");
- if( $in_data != -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.01);
- #-- leave recording mode
- $count_out = $serport->write($SKC{"rec"});
- #-- sleeping some time
- select(undef,undef,undef,0.01);
- #--
- $serport->close();
-
- #-- could not find a value
- if( $nofreq==1 ){
- Log GetLogLevel($name,4), "PT8005_GetStatus: no dBA/C frequency curve value obtained";
- };
- if( $norange==1 ){
- Log GetLogLevel($name,4), "PT8005_GetStatus: no range value obtained";
- };
- if( $nospeed==1 ){
- Log GetLogLevel($name,4), "PT8005_GetStatus: no speed value obtained";
- };
- if( $nodata==1 ){
- Log GetLogLevel($name,4), "PT8005_GetStatus: no data value obtained";
- };
-
- #-- addnl. messages
- if( $over eq "over"){
- Log GetLogLevel($name,4), "PT8005_GetStatus: Range overflow";
- }elsif( $over eq "under" ){
- Log GetLogLevel($name,4), "PT8005_GetStatus: Range underflow";
- }
-
- #-- put into readings
- $hash->{READINGS}{"soundlevel"}{UNIT} = $freq
- if( $nofreq ==0 );
- $hash->{READINGS}{"soundlevel"}{UNITABBR} = $freq
- if( $nofreq ==0 );
-
- #-- testing for wrong data value
- if( $data <=30 ){
- $nodata=1;
- };
-
- #-- put into READINGS
- readingsBeginUpdate($hash);
- readingsBulkUpdate($hash,"speed",$speed)
- if( $nospeed ==0 );
- readingsBulkUpdate($hash,"mode",$mode);
- readingsBulkUpdate($hash,"range",$range)
- if( $norange ==0 );
- readingsBulkUpdate($hash,"overflow",$over);
-
- if( $nodata==0 ){
- my ($sec, $min, $hour, $day, $month, $year, $wday,$yday,$isdst) = localtime(time);
-
- $secsincemidnight = $hour*3600+$min*60+$sec;
- $noisearr[$arrind] = $data;
- $timearr[$arrind] = $secsincemidnight;
-
- #-- average last 15 minutes
- $av15 = PT8005_Average($hash,$secsincemidnight,900);
-
- #-- output
- if( $av15 ne "" ){
- $svalue = sprintf("%3.1f %s [av15 %3.1f %s]",$data,$freq,$av15,$freq);
- $lvalue = sprintf("%3.1f av15 %3.1f ",$data,$av15);
- }else{
- $svalue = sprintf("%3.1f %s",$data,$freq);
- $lvalue = sprintf("%3.1f",$data);
- }
- readingsBulkUpdate($hash,"state",$svalue);
- readingsBulkUpdate($hash,"soundlevel",$lvalue);
-
- #-- average last hour if hour is past
- my $oldtime = $timearr[
- $arrind>0 ? $arrind-1 : $arrmax-1];
- if( defined($oldtime) ){
- my $oldhour = int($oldtime/3600);
- if( ($hour == ($oldhour+1)) || ($hour == ($oldhour-23)) ){
- my $longav = PT8005_Average($hash,$secsincemidnight,3600+$min*60+$sec);
- my $shortav = PT8005_Average($hash,$secsincemidnight,$min*60+$sec);
- if( ($longav ne "") && ($shortav ne "") ){
- $av60 = ($longav*(3600+$min*60+$sec)-$shortav*($min*60+$sec))/3600;
- $noisehour[$hour]=int($av60*10)/10;;
- Log GetLogLevel($name,4),"PT8005 gives average for hour $oldhour as $av60";
- #-- output
- $hvalue = sprintf("%3.1f",$av60);
- readingsBulkUpdate($hash,"soundav60",$hvalue);
-
- #-- check if nightly or daily average
- if( $hour==6 ){
- $avnight = 0.0;
- $avcnt = 0;
- if( defined($noisehour[23])){
- $avnight += $noisehour[23];
- $avcnt++;
- }
- for( my $i=0;$i<=6;$i++ ){
- if( defined($noisehour[$i])){
- $avnight += $noisehour[$i];
- $avcnt++;
- }
- }
- if( $avcnt > 0){
- $noisenight = int($avnight/$avcnt*10)/10;
- Log GetLogLevel($name,1),"PT8005: Nightly average = $avnight from $avcnt values";
- #-- output
- $hvalue = sprintf("%3.1f %s",$noisenight,$freq);
- readingsBulkUpdate($hash,"soundavnight",$hvalue);
- } else {
- $noisenight = "";
- }
- } elsif( $hour==22 ){
- $avday = 0.0;
- $avcnt = 0;
- for( my $i=7;$i<=22;$i++ ){
- if( defined($noisehour[$i])){
- $avday += $noisehour[$i];
- $avcnt++;
- }
- }
- if( $avcnt > 0){
- $noiseday = int($avday/$avcnt*10)/10;
- Log GetLogLevel($name,1),"PT8005: Daily average = $avnight from $avcnt values";
- #-- output
- $hvalue = sprintf("%3.1f %s",$noiseday,$freq);
- readingsBulkUpdate($hash,"soundavday",$hvalue);
- } else {
- $noiseday = "";
- }
- $hvalue = sprintf("%3.1f %3.1f",$noisenight,$noiseday);
- readingsBulkUpdate($hash,"soundday",$hvalue);
- }
- } else {
- $noisehour[$hour]=undef;
- Log GetLogLevel($name,4),"PT8005 NOT calculating new hourly average";
- }
- }
- }
-
- $arrind++;
- $arrind-=$arrmax if($arrind>=$arrmax);
-
- }
- readingsEndUpdate($hash,1);
- }
-
- ########################################################################################
- #
- # PT8005_Set - Implements SetFn function
- #
- # Parameter hash, a = argument array
- #
- ########################################################################################
- sub PT8005_Set ($@) {
- my ($hash, @a) = @_;
- my $name = shift @a;
- my $res;
- #-- for the selector: which values are possible
- #return join(" ", sort keys %sets) if(@a != 2);
- return "PT8005_Set: With unknown argument $a[0], choose one of " . join(" ", sort keys %sets)
- if(!defined($sets{$a[0]}));
-
- my $dev= $hash->{DeviceName};
-
- #-- Set single key value
- for (keys %SKC){
- if( $a[0] eq "$_" ){
- Log GetLogLevel($name,1),"PT8005_Set called with arg $_";
- PT8005_Cmd($hash,$SKC{$_});
- }
- }
-
- #-- Set timer value
- if( $a[0] eq "interval" ){
- #-- only values >= 5 secs allowed
- if( $a[1] >= 5){
- $hash->{interval} = $a[1];
- $res = 1;
- } else {
- $res = 0;
- }
- }
-
- #-- Set frequency curve to db(A) or db(C)
- if( $a[0] eq "freq" ){
- my $freqn = $a[1];
- if ( (!defined($freqn)) || (($freqn ne "dB(A)") && ($freqn ne "dB(C)")) ){
- return "PT8005_Set $name ".join(" ",@a)." with missing parameter, must be dB(A) or dB(C) ";
- }
- if ( (($freq eq "dB(A)") && ($freqn eq "dB(C)")) ||
- (($freq eq "dB(C)") && ($freqn eq "dB(A)")) ){
- Log GetLogLevel($name,1),"PT8005_Set freq $freqn";
- $res=PT8005_Cmd($hash,$SKC{"dBA/C"});
- }
- }
-
- #-- Set measurement range to auto
- if( $a[0] eq "auto" ){
- if ($range eq "30-80 dB"){
- $res =PT8005_Cmd($hash,$SKC{"range"});
- select(undef,undef,undef,0.05);
- $res.=PT8005_Cmd($hash,$SKC{"range"});
- select(undef,undef,undef,0.05);
- $res.=PT8005_Cmd($hash,$SKC{"range"});
- }elsif ($range eq "50-100 dB"){
- $res =PT8005_Cmd($hash,$SKC{"range"});
- select(undef,undef,undef,0.05);
- $res.=PT8005_Cmd($hash,$SKC{"range"});
- }elsif ($range eq "80-130 dB"){
- $res=PT8005_Cmd($hash,$SKC{"range"});
- }
-
- Log GetLogLevel($name,1),"PT8005_Set auto";
- }
-
- Log GetLogLevel($name,3), "PT8005_Set $name ".join(" ",@a)." => $res";
- return "PT8005_Set $name ".join(" ",@a)." => $res";
- }
- ########################################################################################
- #
- # PT8005_Unrec - switch recording mode off
- #
- # Parameter hash
- #
- ########################################################################################
- sub PT8005_Unrec ($) {
- my ($hash) = @_;
- my $res;
- my $dev= $hash->{DeviceName};
- my $name = $hash->{NAME};
- my $serport = new Device::SerialPort ($dev);
-
- if(!$serport) {
- Log GetLogLevel($name,3), "PT8005_UnRec: Can't open $dev: $!";
- return undef;
- }
- $serport->reset_error();
- $serport->baudrate(9600);
- $serport->databits(8);
- $serport->parity('none');
- $serport->stopbits(1);
- $serport->handshake('none');
- $serport->write_settings;
-
- 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 "" ){
- $serport->close();
- Log GetLogLevel($name,4),"PT8005_UnRec: REC is off ";
- return 1;
- } else {
- #-- leave recording mode
- select(undef,undef,undef,0.02);
- my $count_out = $serport->write($SKC{"rec"});
- #-- sleeping some time
- select(undef,undef,undef,0.02);
- }
- }
- $serport->close();
- Log GetLogLevel($name,4),"PT8005_UnRec: REC cannot be turned off ";
-
- return 0;
- }
- 1;
- =pod
- =begin html
- <a name="PT8005"></a>
- <h3>PT8005</h3>
- <p>FHEM module to commmunicate with a PeakTech PT8005 soundlevel meter<br />
- </p>
- <h4>Example</h4>
- <p>
- <code>define pt8005 PT8005 /dev/ttyUSB0 </code>
- </p><br />
- <a name="PT8005define"></a>
- <h4>Define</h4>
- <p>
- <code>define <name> PT8005 <device> </code>
- <br /><br /> Define a PT8005 soundlevel meter</p>
- <ul>
- <li>
- <code><name></code>
- Serial device port
- </li>
- </ul>
- <a name="PT8005set"></a>
- <h4>Set</h4>
- <ul>
- <li><a name="pt8005_interval">
- <code>set <name> interval <value></code>
- </a>
- <br />sets the time period between measurements in seconds (default
- is 60 seconds, minimum is 5 seconds).
- </li>
- <li><a name="pt8005_auto">
- <code>set <name> auto</code>
- </a>
- <br />set the measurement range to auto (30 -130 dB) (displayed in status)
- </li>
- <li><a name="pt8005_freq">
- <code>set <name> freq dB(A)|dB(C)</code>
- </a>
- <br />set frequency curve to A or C (displayed in status)
- </li>
- <li><a name="pt8005_rec">
- <code>set <name> rec</code>
- </a>
- <br />toggle the recording mode
- </li>
- <li><a name="pt8005_minmax">
- <code>set <name> Min/Max</code>
- </a>
- <br />toggle the display between min value, max value and running measurement (displayed in status)
- </li>
- <li><a name="pt8005_dBA/C">
- <code>set <name> dBA/C</code>
- </a>
- <br />toggle the frequency curve (displayed in status)
- </li>
- <li><a name="pt8005_off">
- <code>set <name> off</code>
- </a>
- <br />switch off the device
- </li>
- </ul>
- <br />
- <a name="PT8005get"></a>
- <h4>Get</h4>
- <ul>
- <li><a name="pt8005_reading">
- <code>get <name> reading</code></a>
- <br /> read all current data </li>
- <li><a name="pt8005_present">
- <code>get <name> present</code></a>
- <br /> 1 if device present, 0 if not </li>
- </ul>
- <br />
- <a name="PT8005attr"></a>
- <h4>Attributes</h4>
- <ul>
- <li>Standard attributes <a href="#alias">alias</a>, <a href="#comment">comment</a>, <a
- href="#event-on-update-reading">event-on-update-reading</a>, <a
- href="#event-on-change-reading">event-on-change-reading</a>, <a
- href="#stateFormat">stateFormat</a>, <a href="#room"
- >room</a>, <a href="#eventMap">eventMap</a>, <a href="#loglevel">loglevel</a>,
- <a href="#webCmd">webCmd</a></li>
- </ul>
-
- =end html
- =cut
|