Device-WxM2
view release on metacpan or search on metacpan
Note: I found that I had to fiddle with a parameter in the SerialPort,
called 'read_const_time', which is like a timeout value when
waiting for read data. I found that the value needed to be
increased significantly for the WxM2. I use 5000 (units are
milliseconds) and this is the default setting in this package.
Should you need to change it, use
B<&setSerialPortReadTime>(time_in_millseconds). Then call
B<&configPort>, which puts the new setting into effect.
If you want to change to archive period, use B<&setArchivePeriod> and
B<&getArchivePeriod>. Just remember that if you screw up the values,
you station's archive will behave strangely until you fix it.
Use B<&getLastArcTime> and B<&setLastArcTime> to establish the time at which
the archives are captured into the weather station's archive
memory.
=head2 Individual Access Functions
There are a bunch of individual functions that retrieve one weather
value from the weather station, such as b<&getOutsideTemp>. These are
fairly self-explanatory.
=head2 Archive Retrieval and Logging Functions
There are 2 primary archive retrieval functions:
&getArcImg - get Archive Image
&getSensorImage - get the "live" sensor data image
B<&getArcImg> retrieves the archive image at the address given to it as
a parameter. To retrieve the most recent archived image, use this:
my $lastPtr = $ws->getLastPtr;
my @archiveData = $ws->getArcImg($lastPtr);
B<&getArcImg> takes the archive data, reformats it where necessary,
stores the results in class variables, and returns an array of the
data.
@array= ($avgInsideTempInArchivePeriod,
$averageOutsideTempInArchivePeriod,
$outsideTempMaximumInPeriod,
$outsideTempMinimumInPeriod,
$barometricPressure,
$avgWindSpeedInPeriod,
$avgWindDirInPeriod,
$maxWindGustInPeriod,
$rainInPeriod,
$insideHumidity,
$outsideHumidity,
$monthOfSample,
$dayOfSample,
$hourOfSample,
$minuteOfSample,
$outsideTempHumIndex,
$outsideTempHumIndexMaximum,
$avgWindChill,
$windChillMinimum);
B<&getSensorImage> enables a continuous streaming of "live" weather
data from the Davis Wx Station. I've found this stream to be very
easy to get out of sync, so this funcion reads a single block, stops
the streaming, and flushes the serial receive buffer. The data
returned by this function are the current values and not average
values within a sample period, like &getArcImg returns. The array
returned is as follows:
@array = ($insideTemp,
$outsideTemp,
$windSpeed,
$windDirection,
$barometricPressure,
$insideHumidity,
$outsideHumidity,
$totalRainfallToday);
There are 4 configuration functions for logging the archive data:
&setArchiveLogFilename - set the name of the log file to write
archive data
&getArchiveLogFilename - returns the name of the log file
&setStationDescription - sets the station description text (used by
&printRawLogHeader)
&getStationDescription - returns the station description string
Use B<&setArchiveLogFilename> to set the log file name. It is used by
all logging function calls in the class.
There are two logging functions:
&archiveCurImage - Writes the periodic data samples to a file
&printRawLogHeader - Prints Header for the periodic samples log file
B<&archiveCurImage> writes the data samples held in the class variables
to a filename passed in as its only parameter. For example,
$ws->archiveCurImage();
will write the data samples as 1 line of data in the file
B<&getArchiveLogFilename>.
B<&printRawLogHeader> writes a header for the data samples into the
filename in B<&getArchiveLogFilename>. The second line of the header for your
weather station description. Set it with
B<&setStationDescription>("description"). Typically it contains the
name and location of the weather station.
The function B<&batchRetrieveArchives> is handy for retrieving multiple
archived images from the WxM2's archive memory. I use it primarily
after an extended power outage, but there are lots of other reasons to
use it. Us is at follows:
$ws->batchRetrieveArchives($number, $filename);
where $number is the number of archives to retrieve starting with the most
recent and counting back. And $filename is the string for the file to
write all the archive to.
The function B<&updateArchiveFromPtr> is a low-level function that retrieves archives from an initial pointer value. B<&batchRetrieveArchives> is a user-friendly front-end for this funtion. In most all cases B<&batchRetrieveArchives> should be used...
$ws->updateArchiveFromPtr($lastArchivePtr, $file);
where $lastArchivePtr is the address of the last archive image that
# 21 bytes does not divide evenly into 32K bytes. The last valid
# pointer address is 0x7fe3. The next pointer would be 0x7ff8,
# but it would not have the full 21 bytes before wrapping to
# address 0x0. So an additional 8 bytes are subtracted when
# calculating the wrap address.
my $firstPtr;
if ($sizeOfBatch > $lastPtr) {
$firstPtr = ($lastPtr - $sizeOfBatch - 8) & 0x7fff;
} else {
$firstPtr = $lastPtr - $sizeOfBatch;
}
printf "firstPtr=%d lastPtr=%d\n", $firstPtr, $lastPtr;
return $self->updateArchiveFromPtr($firstPtr, $file);
}
sub updateArchiveFromPtr {
my ($self, $lastArchivedPtr, $file) = @_;
my $i;
my $rdFailed = 0;
my $newPtrHex = $self->getNewPtr();
return 0 unless defined $newPtrHex;
my $newPtr = hex($newPtrHex) - 21;
$lastArchivedPtr += 21;
if ($lastArchivedPtr > 0x7FFF) {
$lastArchivedPtr -= 0x7FFF;
}
# Push $file using local
local $self->{archiveLogFile} = $file;
printf "Update from %x to %x\n", $lastArchivedPtr, $newPtr
if $DEBUG > 0;
# test for address wrapping here
if ($newPtr < $lastArchivedPtr) {
# Last valid ptr addr = 0x7fe3. 0x7ff8 is NOT valid.
for ($i=$lastArchivedPtr; $i < 0x7FF8; $i+=21) {
unless ($self->getArcImg($i)) {
$rdFailed = 1;
last;
}
$self->archiveCurImage();
printf "Archived address %x\n",$i if $DEBUG > 0;
}
$lastArchivedPtr = 0;
}
return 0 if $rdFailed;
for ($i=$lastArchivedPtr; $i <= $newPtr; $i+=21) {
$self->getArcImg($i);
#unless ($self->getArcImg($i)) {
# return 0;
#}
$self->archiveCurImage();
printf "Archived address %x\n",$i if $DEBUG > 0;
}
return 1;
}
##
## `getSensorImage' enables a continuous streaming of 18 byte chunks of
## weather data from the Davis Wx Station. I've found this stream to be
## very easy to get out of sync, so this funcion read a single 18 byte chunk,
## stops the streaming, and flushes the serial Rx buffer
##
sub getSensorImage {
##### LOOP ######
# Monitor, Wizard, and Perception Sensor Image:
# start of block 1 byte
# inside temperature 2 bytes
# outside temperature 2 bytes
# wind speed 1 byte
# wind direction 2 bytes
# barometer 2 bytes
# inside humidity 1 byte
# outside humidity 1 byte
# total rain 2 bytes
# not used 2 bytes
# CRC checksum 2 bytes
# --------
# 18 bytes
#################
my $self = shift;
$wxPort->write("LOOP");
# $wxPort->write(pack "C2", 65535); # doesn't work in perl 5.8
$wxPort->write(pack "C2", 255, 255);
$wxPort->write(pack "C", 0xD);
return undef unless ($self->_get_ack());
my ($count, $string_in) = $wxPort->read(16);
warn "read unsuccessful\n" unless (($count == 16) && ($DEBUG > 0));
my @str_in = unpack "C16", $string_in;
my $inTemp = $self->tempConv($str_in[1], $str_in[2]);
my $outTemp = $self->tempConv($str_in[3], $str_in[4]);
my $baro = ($str_in[9]*256 + $str_in[8])/1000;
if ($self->{isBaroCalSet}) {
# subtract baroCal, to compensate for lower absolute pressure at
# higher altitudes
$baro -= $self->{baroCal};
}
my $tot_rain = ($str_in[13]*256 + $str_in[12])/100;
my $wind = $str_in[5];
my $windAdjDir = ($str_in[7]*256 + $str_in[6] + 11) % 360;
my $windDirDegree = $windAdjDir;
my $windDirDeg16 = int $windDirDegree/22.5;
my $windDir = $compass_rose[$windDirDeg16];
my $inHum = $str_in[10];
my $outHum = $str_in[11];
if ($DEBUG > 1) {
printf "Inside Temp is %f Degrees F\n", $inTemp;
printf "Outside Temp is %f Degrees F\n", $outTemp;
printf "Wind speed is %d\n", $wind;
printf "Wind dir is %d\n", $windDir;
printf "Barometer reads %f\n", $baro;
printf "Inside Humidity is %d%\n", $inHum;
printf "Outside Humidity is %d%\n", $outHum;
printf "Total rainfall is %f\n", $tot_rain;
}
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
$self->{outTemp} = sprintf("%02.1f", $outTemp);
$self->{inTemp} = sprintf("%02.1f",$inTemp);
( run in 1.445 second using v1.01-cache-2.11-cpan-39bf76dae61 )