Skip to content

Commit 90842b6

Browse files
committed
Initial commit
0 parents  commit 90842b6

36 files changed

+2701
-0
lines changed

LICENSE

+661
Large diffs are not rendered by default.

MANIFEST

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
MANIFEST
2+
MANIFEST.SKIP
3+
config.yml
4+
Makefile.PL
5+
lib/Wihlo.pm
6+
bin/app.pl
7+
t/002_index_route.t
8+
t/001_base.t
9+
environments/production.yml
10+
environments/development.yml
11+
views/index.tt
12+
views/layouts/main.tt
13+
public/404.html
14+
public/500.html
15+
public/dispatch.fcgi
16+
public/dispatch.cgi
17+
public/favicon.ico
18+
public/javascripts/jquery.js
19+
public/css/style.css
20+
public/css/error.css
21+
public/images/perldancer.jpg
22+
public/images/perldancer-bg.jpg

MANIFEST.SKIP

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
^\.git\/
2+
maint
3+
^tags$
4+
.last_cover_stats
5+
Makefile$
6+
^blib
7+
^pm_to_blib
8+
^.*.bak
9+
^.*.old
10+
^t.*sessions
11+
^cover_db
12+
^.*\.log
13+
^.*\.swp$
14+
MYMETA.*
15+
^.gitignore
16+
^.svn\/
17+
^Wihlo-

Makefile.PL

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use strict;
2+
use warnings;
3+
use ExtUtils::MakeMaker;
4+
5+
# Normalize version strings like 6.30_02 to 6.3002,
6+
# so that we can do numerical comparisons on it.
7+
my $eumm_version = $ExtUtils::MakeMaker::VERSION;
8+
$eumm_version =~ s/_//;
9+
10+
WriteMakefile(
11+
NAME => 'Wihlo',
12+
AUTHOR => q{YOUR NAME <[email protected]>},
13+
VERSION_FROM => 'lib/Wihlo.pm',
14+
ABSTRACT => 'YOUR APPLICATION ABSTRACT',
15+
($eumm_version >= 6.3001
16+
? ('LICENSE'=> 'perl')
17+
: ()),
18+
PL_FILES => {},
19+
PREREQ_PM => {
20+
'Test::More' => 0,
21+
'YAML' => 0,
22+
'Dancer2' => 0.11,
23+
},
24+
dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
25+
clean => { FILES => 'Wihlo-*' },
26+
);

README.md

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
Wihlo
2+
=====
3+
4+
Wihlo was created out of my frustration with the lack of a simple, good quality Linux weather station application for the Davis Vantage Pro2. At the moment it is still very much a work in progress, and as such is not ready for general use. Please keep checking back here for updates, or if you want further information please email [email protected]
5+
6+
Features
7+
--------
8+
* Display configurable weather graphs in a web browser
9+
* Download data from a Vantage Pro2
10+
* Import data from wview
11+
12+
Timezones
13+
---------
14+
Wihlo stores all times in the database as UTC. However, converting local times from a data logger into UTC can be difficult, when the timezone information is not fully known. The following section lists any specific datalogger issues.
15+
16+
### VantagePro2
17+
* If possible, it is recommended that you set the VP2 datalogger for a named timezone, not an offset from GMT, and keep this consistent. This is because the time field contained in a VP2 record is a local time, with no information as to its timezone.
18+
* When downloading a set of records, Wihlo first asks the datalogger for its timezone. This information is used to convert the times of all the records received into a UTC time.
19+
* If the timezone is a named timezone (as recommended), then this is used to compensate for DST, if required.
20+
* If the timezone is simply an offset from GMT, then Wihlo queries the datalogger as to whether its internal clock is set to DST. If it is, then the time for each record is further adjusted to compensate. Therefore, when changing the local time on the VP2 to copmensate for DST, you should download all records before making the change, otherwise the time of the earlier records will be changed incorrectly for DST.
21+
* Because the VP2 uses the local time in a download record, sometimes a record will contain exactly the same time as a previous record (if the clocks have gone back by an hour). Wihlo tries to spot this, by monitoring for times in records received during such "go back" hours: the first record received will be assumed to be in DST; Wihlo will jump to standard time once a record is received that has a time earlier than one already received.
22+
* If importing from a wview database, it is assumed that the time in the wview database is already in UTC. It should be noted that wview calcuates UTC based on the local computer's timezone, not the timezone of the VP2 datalogger. Therefore, if the timezone on the computer that the VP2 is connected to is different to the timezone of the VP2 itself, then the times imported will probably be incorrect.
23+
24+

bin/app.pl

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/usr/bin/env perl
2+
3+
use FindBin;
4+
use lib "$FindBin::Bin/../lib";
5+
6+
use Wihlo;
7+
Wihlo->dance;

bin/read.pl

+142
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
#!/usr/bin/env perl
2+
3+
=pod
4+
Wihlo - Web-based weather logging and display software
5+
Copyright (C) 2014 A Beverley
6+
7+
This program is free software: you can redistribute it and/or modify
8+
it under the terms of the GNU Affero General Public License as
9+
published by the Free Software Foundation, either version 3 of the
10+
License, or (at your option) any later version.
11+
12+
This program is distributed in the hope that it will be useful,
13+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
GNU Affero General Public License for more details.
16+
17+
You should have received a copy of the GNU Affero General Public License
18+
along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
=cut
20+
21+
use FindBin;
22+
use lib "$FindBin::Bin/../lib";
23+
24+
use Dancer2 ':script';
25+
use Dancer2::Plugin::DBIC qw(schema resultset rset);
26+
use Wihlo;
27+
use Device::VantagePro;
28+
use DateTime;
29+
use DateTime::Format::DBI;
30+
31+
my %arg_hsh;
32+
$arg_hsh{baudrate} = config->{stations}->{vp}->{baudrate};
33+
$arg_hsh{port} = config->{stations}->{vp}->{device};
34+
35+
my $vp = new Device::VantagePro(\%arg_hsh);
36+
error "Failed to wake up device" && exit unless $vp->wake_up() == 1;
37+
38+
my $timezone = $vp->get_timezone;
39+
my $arc_period = $vp->get_archive_period;
40+
my $setup_bits = $vp->get_setup_bits;
41+
my $rain_collector_size = $setup_bits->{RainCollectorSize};
42+
my $raindiv = $rain_collector_size == 2 ? 10
43+
: $rain_collector_size == 1 ? 5
44+
: 100;
45+
46+
my $data;
47+
if (my $dt = rset('Station')->find(1)->lastdata) # The last item of data retrieved
48+
{
49+
my ($dstamp, $tstamp) = split /,/, $dt;
50+
$data = $vp->do_dmpaft($dstamp,$tstamp);
51+
} else
52+
{
53+
# Otherwise get everything
54+
$data = $vp->do_dmpaft;
55+
}
56+
57+
unless ( @{$data} ) { info "No records retrieved" && exit };
58+
59+
my $dtf = schema->storage->datetime_parser; # XXXX Is this expensive? Move inside loop?
60+
my $changing = 0; my $lastdata;
61+
foreach my $d ( @{$data} )
62+
{
63+
# Don't use unixtime parameter, as it depends on
64+
# timezone of PC, not datalogger
65+
my $dt = DateTime->new(
66+
year => $d->{year},
67+
month => $d->{month},
68+
day => $d->{day},
69+
hour => $d->{hour},
70+
minute => $d->{min},
71+
time_zone => $timezone,
72+
);
73+
74+
# Monitor for a DST "ambiguous" time, when the clocks change.
75+
# For an hour when the clocks go back, the winter time minus
76+
# an hour equals the DST. See DateTime manual.
77+
if ($dt->clone->subtract( hours => 1 )->hms eq $dt->hms)
78+
{
79+
# Uh-oh, clocks are about to go back or have just gone back
80+
$changing = 1;
81+
82+
# If the time stamp of the current reading is greater than
83+
# the maximum received so far, then we're probably still in DST.
84+
# DateTime defaults to local standard time, so take an hour
85+
# off it to adjust to DST.
86+
my $maxdst = rset('Station')->find(1)->maxdst || 0;
87+
if ( $maxdst < $d->{time_stamp} )
88+
{
89+
$dt->subtract( hours => 1);
90+
# Update status
91+
rset('Station')->find(1)->update({ maxdst => $d->{time_stamp} });
92+
}
93+
94+
} elsif ($changing == 1)
95+
{
96+
# We've just finished a clock change. Reset status for next time.
97+
rset('Station')->find(1)->update({ maxdst => undef });
98+
}
99+
100+
# Store time as UTC in database
101+
$dt->set_time_zone( 'UTC' );
102+
103+
my $row =
104+
{
105+
# Return undef in event of dashed value
106+
usunits => 1,
107+
usunitsrain => $rain_collector_size == 0 ? 1 : 0,
108+
intvl => $arc_period,
109+
et => $d->{ET} == 0 ? undef : $d->{ET},
110+
rainrate => $d->{Rain_Rate_Clicks} / $raindiv,
111+
rain => $d->{Rain_Clicks} / $raindiv,
112+
intemp => $d->{Air_Temp_Inside} == 32767 ? undef : $d->{Air_Temp_Inside},
113+
outtemplo => $d->{Air_Temp_Lo} == 32767 ? undef : $d->{Air_Temp_Lo},
114+
outhumidity => $d->{Relative_Humidity} == 255 ? undef : $d->{Relative_Humidity},
115+
outtemp => $d->{Air_Temp} == 32767 ? undef : $d->{Air_Temp},
116+
radiationmax => $d->{Solar_Max} == 0 ? undef : $d->{Solar_Max},
117+
inhumidity => $d->{Relative_Humidity_Inside} == 255 ? undef : $d->{Relative_Humidity_Inside},
118+
windspeed => $d->{Wind_Speed} == 255 ? undef : $d->{Wind_Speed},
119+
barometer => $d->{Barometric_Press} == 0 ? undef : $d->{Barometric_Press},
120+
outtemphi => $d->{Air_Temp_Hi} == -32768 ? undef : $d->{Air_Temp_Hi},
121+
uv => $d->{UV} == 255 ? undef : $d->{UV},
122+
uvmax => $d->{UV_Max} == 0 ? undef : $d->{UV_Max},
123+
datetime => $dt,
124+
windgust => $d->{Wind_Gust_Max} == 0 ? undef : $d->{Wind_Gust_Max},
125+
windgustdir => $d->{Wind_Dir_Max} == 255 ? undef : $d->{Wind_Dir_Max} * 22.5,
126+
radiation => $d->{Solar} == 32767 ? undef : $d->{Solar},
127+
winddir => $d->{Wind_Dir} == 255 ? undef : $d->{Wind_Dir} * 22.5
128+
};
129+
if (rset('Reading')->search({ datetime => $dtf->format_datetime($row->{datetime}) })->count)
130+
{
131+
warning "Reading already exists for DTG $row->{datetime}. Not inserting.";
132+
} else
133+
{
134+
my $id = rset('Reading')->create($row);
135+
debug "Inserted record ID ".$id->id;
136+
}
137+
$lastdata = "$d->{date_stamp},$d->{time_stamp}"; # if $d->{unixtime} > $lastunix;
138+
}
139+
140+
# Last item of data revieved, so we can start where we left off
141+
rset('Station')->find(1)->update({ lastdata => $lastdata });
142+

config.yml

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# This is the main configuration file of your Dancer2 app
2+
# env-related settings should go to environments/$env.yml
3+
# all the settings in this file will be loaded at Dancer's startup.
4+
5+
# Your application's name
6+
appname: "Wihlo"
7+
8+
# The default layout to use for your application (located in
9+
# views/layouts/main.tt)
10+
layout: "main"
11+
12+
# when the charset is set to UTF-8 Dancer2 will handle for you
13+
# all the magic of encoding and decoding. You should not care
14+
# about unicode within your app when this setting is set (recommended).
15+
charset: "UTF-8"
16+
17+
# template engine
18+
# simple: default and very basic template engine
19+
# template_toolkit: TT
20+
21+
template: "simple"
22+
23+
# template: "template_toolkit"
24+
# engines:
25+
# template:
26+
# template_toolkit:
27+
# start_tag: '<%'
28+
# end_tag: '%>'
29+
30+
plugins:
31+
DBIC:
32+
default:
33+
# dsn: dbi:SQLite:dbname=some.db
34+
# schema_class: MyApp::Schema
35+
# foo:
36+
dsn: dbi:mysql:database=wihlo;mysql_enable_utf8=1;host=localhost
37+
schema_class: Wihlo::Schema
38+
user: wihlo
39+
pass: wihlo
40+
options:
41+
RaiseError: 1
42+
PrintError: 1
43+
44+
stations:
45+
vp:
46+
baudrate: 19200
47+
device: /dev/ttyUSB0

environments/development.yml

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# configuration file for development environment
2+
3+
# the logger engine to use
4+
# console: log messages to STDOUT (your console where you started the
5+
# application server)
6+
# file: log message to a file in log/
7+
logger: "console"
8+
9+
# the log level for this environment
10+
# core is the lowest, it shows Dancer2's core log messages as well as yours
11+
# (debug, info, warning and error)
12+
log: "core"
13+
14+
# should Dancer2 consider warnings as critical errors?
15+
warnings: 1
16+
17+
# should Dancer2 show a stacktrace when an error is caught?
18+
show_errors: 1
19+
20+
# print the banner
21+
startup_info: 1

environments/production.yml

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# configuration file for production environment
2+
3+
# only log warning and error messsages
4+
log: "warning"
5+
6+
# log message to a file in logs/
7+
logger: "file"
8+
9+
# don't consider warnings critical
10+
warnings: 0
11+
12+
# hide errors
13+
show_errors: 0
14+
15+
# cache route resolution for maximum performance
16+
route_cache: 1
17+

0 commit comments

Comments
 (0)