Skip to content

Commit

Permalink
Merge pull request #369 from f34rdotcom/fix_improve_daviswm2
Browse files Browse the repository at this point in the history
fixed to work with newer MH and perl5. Added trending of barom the wm2 d...
  • Loading branch information
krkeegan committed Mar 27, 2014
2 parents 8307d23 + 2512206 commit eb70d79
Showing 1 changed file with 130 additions and 11 deletions.
141 changes: 130 additions & 11 deletions lib/Weather_daviswm2.pm
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package Weather_daviswm2;
# $Date$
# $Revision$

use Tie::IxHash;
use strict;
use Weather_Common;
eval 'use Digest::mhCRC qw(crc16);';
Expand All @@ -20,6 +21,43 @@ for the Davis Weather Monitor II weather stations.
Matt Williams reworked it to interface correctly with mh and to make it a module
Jack Edin was heavily involved in testing and was the impedus behind the creation of this module.
1/27/2014
Sean Mathews <coder at f34r dot com>
sponsored by a close friend and fellow maker Jack Edin 1961-2012 RIP
Movie nights and project days will be missed.
added barometric tendency calculation. The wm2 has a visual indicator of the barometric trend but
it can not be accessed via the serial port protocol.
the barometric tendency indications based upon a given change over a one hour period.
http://www.erh.noaa.gov/box/glossary.htm
"Rising Rapidly" is indicated if the pressure increases > 2 mb (0.06")
"Rising Slowly" is indicated if the pressure increases >1 mb but < 2 mb (> 0.02" but < 0.06")
"Steady" is indicated if the pressure changes < 1 mb (< 0.02")
"Falling Slowly" is indicated if the pressure falls > 1 mb but < 2 mb (> 0.02" but < 0.06")
"Falling Rapidly" is indicated when the pressure decreases > 2 mb (>0.06")
"Unsteady" unknown lack of samples or last sample fluctuated by 0.03 or more
in order to still get some trends before I have a long enough sample time I have opted to use this
psudo code.
collect a sample and add to fifo array
expire any samples older than 1 hours from the sample we just took
if last > 0 and deviation from last > .03" ( last is 0 on startup )
report "Unsteady"
else
if the sample array has a minimum of 10 samples
find average oldest(head) 5 samples for oldest barom
find average newest(tail) 5 samples for current barom
report indicator based upon this calculation above
else
report ""
Note: You must enable this module by setting the following parameters in mh{.private}.ini.
Obviously you must point the port to the actual port to which the station is connected.
serial_daviswm2_port=COM10
Expand All @@ -33,13 +71,18 @@ our $loopCommand = join "", "LOOP", chr(255), chr(255), chr(13);
our $DavisWMII_port;
our $lastRainReading = undef;
our $lastRainReadingTime = undef;
my $barom_tendency = "";
my %barom_samples = undef;
my $barom_samples = undef;

$barom_samples = tie %barom_samples, 'Tie::IxHash';

sub startup{
my ($instance)=@_;
$DavisWMII_port = new Serial_Item(undef, undef, 'serial_daviswm2');
&requestData;
&::MainLoop_pre_add_hook(\&Weather_daviswm2::update,1);
&::trigger_set('&new_minute','&Weather_daviswm2::requestData','NoExpire','daviswm2 data request')
&::trigger_set('new_minute(1)','&Weather_daviswm2::requestData','NoExpire','daviswm2 data request')
unless &::trigger_get('daviswm2 data request');
}

Expand Down Expand Up @@ -93,7 +136,7 @@ sub process{
my @data = unpack('C*',$data);
my $gotheader = 0;

if ($::Debug{Weather}) {
if ($::Debug{weather}) {
my $debugInfo='daviswm2: Read from Davis WM II ';
for (@data) {
$debugInfo .= sprintf ("0x%x ",$_);
Expand All @@ -118,15 +161,15 @@ sub process{
$rain_rate);

# go through data until we have found a header
&::print_log ("daviswm2: looking for header") if $::Debug{Weather};
&::print_log ("daviswm2: looking for header") if $::Debug{weather};
my $headerByte;
while (defined($headerByte=shift(@data))) {
next if $headerByte != 1; # need a 1 at start of data
&::print_log ("daviswm2: found header, checking length and crc16 of remaining data") if $::Debug{Weather};
&::print_log ("daviswm2: found header, checking length and crc16 of remaining data") if $::Debug{weather};
$data=pack('C*',@data);
if (length($data) < 17) { # we need 17 bytes left to proceed
&::print_log("daviswm2: not enough bytes left to process") if $::Debug{Weather};
return $headerByte.$data; # need to return the header byte as well
&::print_log("daviswm2: not enough bytes left to process") if $::Debug{weather};
return chr($headerByte).$data; # need to return the header byte as well
}
($indoor_temp,
$outdoor_temp,
Expand All @@ -139,7 +182,7 @@ sub process{
$not_used,
$crc16)=unpack('vvCvvCCvvn', $data);
if (Digest::mhCRC::crc16(substr($data,0,15)) != $crc16) {
&::print_log ("daviswm2: wrong crc16, looking again for header") if $::Debug{Weather};
&::print_log ("daviswm2: wrong crc16, looking again for header") if $::Debug{weather};
next;
}
# remove the 17 bytes that we just processed, we'll use the remainder as our return value
Expand All @@ -149,20 +192,94 @@ sub process{

# return because we didn't find a header :-(
if ($headerByte != 1) {
&::print_log ("daviswm2: ran out of bytes and didn't find a header") if $::Debug{Weather};
&::print_log ("daviswm2: ran out of bytes and didn't find a header") if $::Debug{weather};
# don't use $data as return value as it only has a valid
# value if a good header/packet is found
return '';
}

&::print_log ("daviswm2: found a header with the right checksum") if $::Debug{Weather};
&::print_log ("daviswm2: found a header with the right checksum") if $::Debug{weather};

# correct reading from reported to actual (just moving the decimal point)
$indoor_temp/=10.0;
$outdoor_temp/=10.0;
$barometer/=1000.0;
$total_rain/=10.0;


# barometric trend analysis
my $btr_current_sample_time = time;

## save our barometric reading
$barom_samples{$btr_current_sample_time} = $barometer;

&::print_log ("daviswm2: barometric samples") if $::Debug{weather};

## do the analysis on our dataset
my $btr_tmp_counter = 0;
my $btr_sum_head = 0.0;
my $btr_sum_tail = 0.0;
my ( $btr_datetime, $btr_barom , $btr_exflag, @btr_expire_list );
while (( $btr_datetime, $btr_barom ) = each %barom_samples ) {

# If the sample is older then 1 hour add to our remove list
my $datediff = $btr_current_sample_time - $btr_datetime;
if ( $datediff > 3600 ) { # 3600s = 1 hour
push ( @btr_expire_list, $btr_datetime );
$btr_exflag = "*" if $::Debug{weather};
} else {
$btr_exflag = " " if $::Debug{weather};
}
if ( $barom_samples->Length >= 10 ) {
if ( $btr_tmp_counter < 5 ) {
$btr_sum_head += $btr_barom;
$btr_exflag .= "T" if $::Debug{weather};
} else {
if ( $btr_tmp_counter >= $barom_samples->Length - 5 ) {
$btr_sum_tail += $btr_barom;
$btr_exflag .= "H" if $::Debug{weather};
}
}
}
if ( $::Debug{weather} ) {
&::print_log ("daviswm2: " . localtime($btr_datetime) . " -> $btr_barom $btr_exflag $datediff" );
}
$btr_tmp_counter++;
}

## calculate our average over 5 samples
$btr_sum_head /= 5.0;
$btr_sum_tail /= 5.0;

## calculate our difference
my $btr_diff = $btr_sum_tail - $btr_sum_head;

## fetch last sample
my $btr_last_diff = abs($barometer - $barom_samples->Values( $barom_samples->Length - 2 ));
my $btr_last_value = $barom_samples->Values( $barom_samples->Length - 2 );

&::print_log ("daviswm2: last value($btr_last_value) diff($btr_last_diff)" ) if $::Debug{weather};

## calculate tendency
if ( $btr_last_diff >= .03 or $barom_samples->Length < 15 ) {
&::print_log ("daviswm2: unsteading reading $btr_last_diff $btr_last_value" ) if $::Debug{weather};
$barom_tendency = "unsteady";
} else {
$barom_tendency = "rising rapidly" if $btr_diff > 0.06;
$barom_tendency = "rising slowly" if $btr_diff > 0.02 and $btr_diff < 0.06;
$barom_tendency = "steady" if abs($btr_diff) < 0.02;
$barom_tendency = "falling rapidly" if $btr_diff < -0.06;
$barom_tendency = "falling slowly" if $btr_diff < -0.02 and $btr_diff > -0.06;
}

&::print_log ("daviswm2: head($btr_sum_head) tail($btr_sum_tail)") if $::Debug{weather};

## remove expired values
foreach ( @btr_expire_list ) {
$barom_samples->DELETE($_);
}


# calculate sea level pressure
my $barometer_sea=convert_local_barom_to_sea_in($barometer);

Expand Down Expand Up @@ -241,8 +358,9 @@ sub process{
$$wptr{HumidOutdoor}=$outdoor_humidity;
$$wptr{RainTotal}=$total_rain;
$$wptr{RainRate}=$rain_rate;

if ($::Debug{Weather}) {
$$wptr{BaromDelta}=$barom_tendency;

if ($::Debug{weather}) {
foreach my $key qw(
TempIndoor
TempOutdoor
Expand All @@ -252,6 +370,7 @@ sub process{
WindAvgDir
Barom
BaromSea
BaromDelta
HumidIndoor
HumidOutdoor
RainTotal
Expand Down

0 comments on commit eb70d79

Please sign in to comment.