|
| 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 | + |
0 commit comments