#!/usr/bin/perl
#
# Weather beacon.
# Copyright 1999 by Jonathan Bradshaw, N9OXE (n9oxe@arrl.net)
#
# Licensed under the GPL (see LICENSE file for details)
# Uses weather protocol information from APRS (see LICENSE file for details)
#
# Requirements:
#       Perl 5.004
#       aprsd (http://www.wa4dsy.ampr.org/)
#       datalogger.pl (to create wx.dat file)
#
use POSIX;
use Socket;
use Sys::Syslog;
use strict;

require 5.004;

my $DATAFILE = "/var/log/weather/u2000.dat";
my $MYCALL = "KG9AE-1";
my $aprsServer = "localhost";
my $aprsPort = 1315;

my $wxdelay = 5;     # 5 minutes between each transmission

sub xmit {
  # Send (via UDP) our weather information to aprs server
  # This code was taken from aprsd udp_example code
  #
  my ($data) = @_;
  my ($d1, $d2, $d3, $d4, $rawserver) = gethostbyname($aprsServer);
  my $serveraddr = pack("Sna4x8",2,$aprsPort,$rawserver);
  my $prototype = getprotobyname('udp');
  socket(SOCKET,2,SOCK_DGRAM,$prototype) || die("Unable to create socket");
    #Send to the TNC... Note: you must end the string with a NULL 
    #Note that only the data after the ":" is actually sent to the TNC.
    send SOCKET, "$MYCALL>TNC:$data\0" , 0 , $serveraddr;
  close(SOCKET);
}

sub cvttime {
  # Convert local date/time string into gmtime
  #
  my ($month, $day, $year, $hour, $minute) = @_;
  return mktime(0,$minute,$hour,$day,$month-1,$year-1900,0,0,0);
}

sub wxstring {
  # Read weather data file into hash table and return an APRS formatted
  # weather string for transmission. The date and time used are from the
  # weather station and is converted to GMT.
  #
  my ($key, $data, $tm, %wx);

  # Check the datafile even exists
  return unless ( -s $DATAFILE );

  open(WXDATFILE,"<$DATAFILE") || die "Unable to open weather data file!";
  while (<WXDATFILE>) {
    chop;
    ($key, $data) = split(/: /);
    $wx{$key}=$data;
  }
  close(WXDATFILE);

  $data = "_" . strftime("%m%d%H%M", gmtime(cvttime(substr($wx{Date},0,2),
			substr($wx{Date},3,2), substr($wx{Date},6,4),
                        substr($wx{Time},0,2), substr($wx{Time},3,2)))) .
          "c" . sprintf("%03d", $wx{WindDirection}) .
          "s" . sprintf("%03d", $wx{CalcWindAvg1Min}) .
          "g" . sprintf("%03d", $wx{WindPeakSpeed5Min}) .
          "t" . sprintf("%03d", $wx{OutdoorTemp});

  if ($wx{CalcRainLastHour}) {
    $data .= "r" . sprintf("%03d", $wx{CalcRainLastHour}*100) # last 60 mins
  } else {
    $data .= "r...";
  }

  if ($wx{CalcRainLast24hr}) {
    $data .= "p" . sprintf("%03d", $wx{CalcRainLast24hr}*100) # last 24 hrs
  } else {
    $data .= "p...";
  }

  $data .= "P" . sprintf("%03d", $wx{RainTotalToday}*100);    # since midnight

  if ($wx{OutdoorHumidity} > 0) {
    $data .= "h" . sprintf("%02d", $wx{OutdoorHumidity})
  } else {
    $data .= "h.."
  }

  $data .= "b" . sprintf("%05d", $wx{Barometer} / 0.002953) .  "xU2k";

  return $data;
}

#
# Main
#
fork && exit;
setsid();
Sys::Syslog::setlogsock('unix');
openlog('wxbeacon', 'pid', 'daemon');
syslog('notice', 'wxbeacon starting');

my ($wx, $lastwx);
while (1) {
  $wx = &wxstring();
  if ($wx) {
    syslog('debug', 'Sending: %s', $wx);
    &xmit($wx) unless ($wx eq $lastwx);
    $lastwx = $wx;
  }
  sleep($wxdelay * 60);
}
syslog('notice', 'wxbeacon exiting');
closelog();

# End of wxbeacon.pl
