From: Dirk Koopman Date: Thu, 12 Apr 2012 16:57:58 +0000 (+0100) Subject: add basic skeleton to git X-Git-Url: http://scm.dxcluster.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=dc4a7b485f2c395471e3f7b64667da3625dcdc64;p=dweather.git add basic skeleton to git --- dc4a7b485f2c395471e3f7b64667da3625dcdc64 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b25c15b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*~ diff --git a/DWeather/.gitignore b/DWeather/.gitignore new file mode 100644 index 0000000..b911764 --- /dev/null +++ b/DWeather/.gitignore @@ -0,0 +1,2 @@ +*.old +blib diff --git a/DWeather/Changes b/DWeather/Changes new file mode 100644 index 0000000..ce09e3d --- /dev/null +++ b/DWeather/Changes @@ -0,0 +1,6 @@ +Revision history for Perl extension DWeather. + +0.01 Thu Apr 12 16:55:53 2012 + - original version; created by h2xs 1.23 with options + -X -b 5.8.1 -O DWeather + diff --git a/DWeather/MANIFEST b/DWeather/MANIFEST new file mode 100644 index 0000000..6d9014a --- /dev/null +++ b/DWeather/MANIFEST @@ -0,0 +1,6 @@ +Changes +Makefile.PL +MANIFEST +README +t/DWeather.t +lib/DWeather.pm diff --git a/DWeather/Makefile.PL b/DWeather/Makefile.PL new file mode 100644 index 0000000..e8f153b --- /dev/null +++ b/DWeather/Makefile.PL @@ -0,0 +1,12 @@ +use 5.008001; +use ExtUtils::MakeMaker; +# See lib/ExtUtils/MakeMaker.pm for details of how to influence +# the contents of the Makefile that is written. +WriteMakefile( + NAME => 'DWeather', + VERSION_FROM => 'lib/DWeather.pm', # finds $VERSION + PREREQ_PM => {}, # e.g., Module::Name => 1.1 + ($] >= 5.005 ? ## Add these new keywords supported since 5.005 + (ABSTRACT_FROM => 'lib/DWeather.pm', # retrieve abstract from module + AUTHOR => 'Dirk Koopman ') : ()), +); diff --git a/DWeather/README b/DWeather/README new file mode 100644 index 0000000..073c370 --- /dev/null +++ b/DWeather/README @@ -0,0 +1,40 @@ +DWeather version 0.01 +===================== + +The README is used to introduce the module and provide instructions on +how to install the module, any machine dependencies it may have (for +example C compilers and installed libraries) and any other information +that should be provided before the module is installed. + +A README file is required for CPAN modules since CPAN extracts the +README file from a module distribution so that people browsing the +archive can use it get an idea of the modules uses. It is usually a +good idea to provide version information here so that people can +decide whether fixes for the module are worth downloading. + +INSTALLATION + +To install this module type the following: + + perl Makefile.PL + make + make test + make install + +DEPENDENCIES + +This module requires these other modules and libraries: + + blah blah blah + +COPYRIGHT AND LICENCE + +Put the correct copyright and licence information here. + +Copyright (C) 2012 by Dirk Koopman + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.12.4 or, +at your option, any later version of Perl 5 you may have available. + + diff --git a/DWeather/lib/DWeather.pm b/DWeather/lib/DWeather.pm new file mode 100644 index 0000000..cbe5b97 --- /dev/null +++ b/DWeather/lib/DWeather.pm @@ -0,0 +1,60 @@ +package DWeather; + +use 5.008001; +use strict; +use warnings; + +require Exporter; +use AutoLoader qw(AUTOLOAD); + +our @ISA = qw(Exporter); + +our $VERSION = '0.01'; + + +# Preloaded methods go here. + +# Autoload methods go after =cut, and are processed by the autosplit program. + +1; +__END__ +# Below is stub documentation for your module. You'd better edit it! + +=head1 NAME + +DWeather - A Distributed Weather Station + +=head1 SYNOPSIS + + use DWeather; + +=head1 DESCRIPTION + +This is a distributed weather station that takes data from various weather +station hardware (such as Davis VantagePro 2) and allows one to distribute +a normalised form of that data around more than one place and then display +it, hopefully nicely, in a web browser from a builtin web server. + +=head2 EXPORT + +None. + +=head1 SEE ALSO + +Davis Vantage documentation: L +and L + +=head1 AUTHOR + +Dirk Koopman, Edjk@tobit.co.ukE + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2012 by Dirk Koopman + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.12.4 or, +at your option, any later version of Perl 5 you may have available. + + +=cut diff --git a/DWeather/lib/DWeather/Debug.pm b/DWeather/lib/DWeather/Debug.pm new file mode 100644 index 0000000..bf81520 --- /dev/null +++ b/DWeather/lib/DWeather/Debug.pm @@ -0,0 +1,156 @@ +# +# The system variables - those indicated will need to be changed to suit your +# circumstances (and callsign) +# +# Copyright (c) 1998 - Dirk Koopman G1TLH +# +# $Id: Debug.pm,v 1.1 2001/05/18 14:02:10 djk Exp $ +# +# This library is free software; you can redistribute it and/or +# modify it under the same terms as Perl itself. +# + +package Debug; + +require Exporter; +@ISA = qw(Exporter); +@EXPORT = qw(dbginit dbg dbgadd dbgsub dbglist dbgdump isdbg dbgclose confess croak cluck carp); +$VERSION = sprintf( "%d.%02d", q$Revision: 1.1 $ =~ /(\d+)\.(\d+)/ ); + +use strict; +use vars qw(%dbglevel $fp); + +use SMGLog (); +use Carp qw(cluck); + +%dbglevel = (); +$fp = undef; + +# Avoid generating "subroutine redefined" warnings with the following +# hack (from CGI::Carp): +if (!defined $DB::VERSION) { + local $^W=0; + eval qq( sub confess { + \$SIG{__DIE__} = 'DEFAULT'; + Debug::dbg(\$@, Carp::shortmess(\@_)); + exit(-1); + } + sub croak { + \$SIG{__DIE__} = 'DEFAULT'; + Debug::dbg(\$@, Carp::longmess(\@_)); + exit(-1); + } + sub carp { Debug::dbg(Carp::shortmess(\@_)); } + sub cluck { Debug::dbg(Carp::longmess(\@_)); } + ); + + CORE::die(Carp::shortmess($@)) if $@; +} else { + eval qq( sub confess { Carp::confess(\@_); } + sub cluck { Carp::cluck(\@_); } + sub carp { Carp::cluck(\@_); } + ); +} + +dbginit(); + +sub dbg +{ + my $t = time; + my $ts = sprintf("%02d:%02d:%02d", (gmtime($t))[2,1,0]); + for (@_) { + my $r = $_; + chomp $r; + my @l = split /\n/, $r; + for (@l) { + s/([\x00-\x08\x0B-\x1f\x7f-\xff])/uc sprintf("%%%02x",ord($1))/eg; +# print "$_\n" if defined \*STDOUT; + $fp->writeunix($t, "$ts $_"); + } + } +} + +sub dbginit +{ + # add sig{__DIE__} handling + if (!defined $DB::VERSION) { + $SIG{__WARN__} = sub { dbg($@, Carp::shortmess(@_)); }; + $SIG{__DIE__} = sub { dbg($@, Carp::longmess(@_)); }; + } + + $fp = SMGLog->new('debug', 'dat', 'd'); +} + +sub dbgclose +{ + $SIG{__DIE__} = $SIG{__WARN__} = 'DEFAULT'; + $fp->close() if $fp; + undef $fp; +} + +sub dbgdump +{ + my $m = shift; + + foreach my $l (@_) { + my $p = $m; + for (my $o = 0; $o < length $l; $o += 16) { + my $c = substr $l, $o, 16; + my $h = unpack "H*", $c; + $c =~ s/[\x00-\x1f\x7f-\xff]/./g; + my $left = 16 - length $c; + $h .= ' ' x (2 * $left) if $left > 0; + dbg($p . sprintf("%4d:", $o) . "$h $c"); + $p = ' ' x (length $p); + } + } +} + +sub dbgadd +{ + my $entry; + + foreach $entry (@_) { + $dbglevel{$entry} = 1; + } +} + +sub dbgsub +{ + my $entry; + + foreach $entry (@_) { + delete $dbglevel{$entry}; + } +} + +sub dbglist +{ + return keys (%dbglevel); +} + +sub isdbg +{ + return undef unless $fp; + return $dbglevel{$_[0]}; +} + +sub shortmess +{ + return Carp::shortmess(@_); +} + +sub longmess +{ + return Carp::longmess(@_); +} + +1; +__END__ + + + + + + + diff --git a/DWeather/lib/DWeather/Log.pm b/DWeather/lib/DWeather/Log.pm new file mode 100644 index 0000000..4d801be --- /dev/null +++ b/DWeather/lib/DWeather/Log.pm @@ -0,0 +1,178 @@ +# +# the general purpose logging machine +# +# This module is designed to allow you to log stuff in SMG format +# +# The idea is that you give it a prefix which is a directory and then +# the system will log stuff to a directory structure which looks like:- +# +# ./logs//yyyy/mmdd.[log|new("sys_log"); +} + +# create a log object that contains all the useful info needed +# prefix is the main directory off of the data directory +# suffix is the suffix after the month/day +sub new +{ + my ($pkg, $prefix, $suffix) = @_; + my $ref = {}; + my $dir = "$path/$prefix"; + $ref->{prefix} = $dir; + $ref->{suffix} = $suffix || 'log'; + + # make sure the directory exists + mkpath($dir, 0, 0777) unless -d $dir; + die "cannot create or access $dir $!" unless -d $dir; + + return bless $ref, $pkg; +} + +# open the appropriate data file +sub open +{ + my ($self, $dayno, $mode) = @_; + + my ($year, $month, $day) = (gmtime($dayno * 86400))[5,4,3]; + $year += 1900; + $month += 1; + + # if we are writing, check that the directory exists + if (defined $mode) { + my $dir = "$self->{prefix}/$year"; + mkdir($dir, 0777) if ! -e $dir; + } + + $self->{fn} = sprintf "$self->{prefix}/$year/%02d%02d", $month, $day; + $self->{fn} .= ".$self->{suffix}" if $self->{suffix}; + + $self->{mode} = $mode || 'r'; + + my $fh = new IO::File $self->{fn}, $mode, 0666; + return unless $fh; + + $fh->autoflush(1) if $mode ne 'r'; # make it autoflushing if writable + $self->{fh} = $fh; + + $self->{year} = $year; + $self->{month} = $month; + $self->{day} = $day; + $self->{dayno} = $dayno; + +# DXDebug::dbg("dxlog", "opening $self->{fn}\n"); + + return $self->{fh}; +} + +# open the previous log file in sequence +sub openprev +{ + my $self = shift; + return $self->open($self->{dayno} - 1, @_); +} + +# open the next log file in sequence +sub opennext +{ + my $self = shift; + return $self->open($self->{dayno} + 1, @_); +} + +# write (actually append) to a file, opening new files as required +sub write +{ + my ($self, $dayno, $line) = @_; + if (!$self->{fh} || + $self->{mode} ne ">>" || + $dayno != $self->{dayno}) { + $self->open($dayno, ">>") or confess "can't open $self->{fn} $!"; + } + + return $self->{fh}->print("$line\n"); +} + +# read a line from an opened file +sub read +{ + my $self = shift; + confess "can't read $self->{fh} $!" unless $self->{fh}; + return $self->{fh}->getline; +} + +# write (actually append) using the current date to a file, opening new files as required +sub writenow +{ + my ($self, $line) = @_; + my $dayno = int (time / 86400); + return $self->write($dayno, $line); +} + +# write (actually append) using a unix time to a file, opening new files as required +sub writeunix +{ + my ($self, $t, $line) = @_; + my $dayno = int ($t / 86400); + return $self->write($dayno, $line); +} + +# close the log file handle +sub close +{ + my $self = shift; + undef $self->{fh}; # close the filehandle + delete $self->{fh}; +} + +sub DESTROY +{ + my $self = shift; + undef $self->{fh}; # close the filehandle + delete $self->{fh} if $self->{fh}; +} + +sub Log +{ + my $l = ref $_[0] ? shift : $log; + return unless $l; + my $t = time; + my $ts = sprintf("%02d:%02d:%02d", (gmtime($t))[2,1,0]); + $l->writeunix($t, "$ts $_") for @_; +} + +sub LogDbg +{ + Log(@_); + Debug::dbg(@_) if Debug::isdbg('chan'); +} + +1; diff --git a/DWeather/lib/DWeather/Serial.pm b/DWeather/lib/DWeather/Serial.pm new file mode 100644 index 0000000..44da24f --- /dev/null +++ b/DWeather/lib/DWeather/Serial.pm @@ -0,0 +1,90 @@ +# +# Module to do serial handling on perl FileHandles +# + +use strict; + +package Serial; + +use POSIX qw(:termios_h); +use Fcntl; + +our @ISA = qw(IO::File); + + +# Linux-specific Baud-Rates +use constant B57600 => 0010001; +use constant B115200 => 0010002; +use constant B230400 => 0010003; +use constant B460800 => 0010004; +use constant CRTSCTS => 020000000000; + +sub new +{ + my $pkg = shift; + my $class = ref $pkg || $pkg; + my $device = shift || "/dev/ttyS0"; + + my $self = $pkg->SUPER::new($device, O_RDWR|O_NOCTTY|O_EXCL|O_NDELAY) || return; + + # get my attributes + $$self->{ORIGTERM} = POSIX::Termios->new(); + my $term = $$self->{TERM} = POSIX::Termios->new(); + $$self->{ORIGTERM}->getattr(fileno($self)); + $term->getattr(fileno($self)); + my ($speed) = grep {/^\d+$/} @_; + my $baud; + { + no strict 'refs'; + $baud = &{'POSIX::B' . $speed}; + } + $term->setispeed($baud); + $term->setospeed($baud); + + my $cflag = $term->getcflag(); my $lflag = $term->getlflag(); + my $oflag = $term->getoflag(); my $iflag = $term->getiflag(); + + # set raw + ######################################################################## + $iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); + $oflag &= ~OPOST; + $lflag &= ~(ECHO|ECHONL|ICANON|ISIG); + $cflag &= ~(CSIZE|PARENB|HUPCL); + ######################################################################### + # + + $cflag |= CLOCAL|CREAD; + $cflag |= (grep {/^cs7$/i} @_) ? CS7 : CS8; + if (my ($parity) = grep {/^(odd|even)$/i} $@) { + $cflag |= PARENB; + $cflag |= PARODD if $parity =~ /odd/i; + } + $cflag |= CRTSCTS if grep /rtscts$/, $@; + $term->setcflag($cflag); $term->setlflag($lflag); + $term->setoflag($oflag); $term->setiflag($iflag); + $term->setattr(fileno($self), TCSANOW); + return $self; +} + +sub getattr +{ + my $self = shift; + $$self->{TERM}->getattr; + return $$self->{TERM}; +} + +sub setattr +{ + my $self = shift; + my $attr = shift || $$self->{TERM}; + $attr->setattr(fileno($self), &POSIX::TCSANOW); +} + +sub close +{ + my $self = shift; + $self->setattr($$self->{ORIGTERM}); + $self->SUPER::close; +} + +1; diff --git a/DWeather/t/DWeather.t b/DWeather/t/DWeather.t new file mode 100644 index 0000000..4889344 --- /dev/null +++ b/DWeather/t/DWeather.t @@ -0,0 +1,18 @@ +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl DWeather.t' + +######################### + +# change 'tests => 1' to 'tests => last_test_to_print'; + +use strict; +use warnings; + +use Test::More tests => 1; +BEGIN { use_ok('DWeather') }; + +######################### + +# Insert your test code below, the Test::More module is use()ed here so read +# its man page ( perldoc Test::More ) for help writing this test script. + diff --git a/manuals/VantageSerialProtocolDocs_v230.pdf b/manuals/VantageSerialProtocolDocs_v230.pdf new file mode 100644 index 0000000..ea2527a Binary files /dev/null and b/manuals/VantageSerialProtocolDocs_v230.pdf differ