#!c:\Perl\bin\Perl
#
# This is an example file showing how to send data to the serial port.
#
# It does not include error checking.
#
use strict;

#use Device::SerialPort; # on UNIX
use Win32::SerialPort; # on Windows
##use Term::Getch;
##use Term::ReadKey;
##ReadMode('cbreak');

#my $DEVICE = "/dev/ttyS1"; # on UNIX
my $DEVICE = "COM5";  # on Windows
my $start_time = time();
my $msg = "Hello World!";
my $dbgon1 = 0; # off for normal running
my $dbgon2 = 0; # off for normal running
my $maxperfile = 30; # for testing 60; # assume one-per-second
my $cnt = 0;
my $InBytes = 256;
my $maxmsg = 512;
###my $cfgfile = "com1.cfg";
my $cfgfile = "c:/Gtools/perl/comm5.txt";
my $gpsbgn = '\$GPRMC';
my ($OF, $HOUT);
my $logfile = "templ001.txt";
my $logdir = 'pos/';
my $outfile = $logdir . $logfile;
open ($OF, ">$outfile") or die "Can NOT open log file ... [$outfile]!!! ...";

sub openPort($);
sub closePort($);

my $gps_first = 1;
# Now process the new RMC record - example
### $GPRMC,130210.030,A,3352.3955,S,15113.3678,E,0.257256,125.59,260605,,*10                                                                        
my $gps_time_rmc = ''; # join ':', unpack "a2" x 3, $field[1];
my $gps_ok_rmc = 0; # $field[2];
my $gps_lat_rmc = 0; # latitude(@field[3..4]);
my $gps_long_rmc = 0; # longitude(@field[5..6]);
my $gps_speed = 0; # $field[7];
my $gps_cmg = ''; # $field[8];
my $gps_date = ''; # join '/', unpack "a2" x 3, $field[9];
my $gps_mvar = ''; # $field[10] . $field[11];
my @field = (); # split /[,*]/, $line; # split on comma, and * (checksum)

my $currhr = -1; #$hms[0];
my $currmin = -1; #$hms[1];
my $currsec = -1; #$hms[2];
my $currday = -1; #$dte[0];
my $currmth = -1; #$dte[1];
my $curryr = -1; #$dte[2];
my $currtimed = ''; #"$currhr:$currmin:$currsec";
my $currdated = ''; #"$curryr/$currmth/$currday";
my $dispdt = ''; #"$currdated $currtimed";
my $gps_lat_curr = 0; # latitude(@field[3..4]);
my $gps_long_curr = 0; # longitude(@field[5..6]);

print "Started on " . localtime($start_time) . "...\n";

print "Openning $DEVICE ...\n";
my $serial = openPort($DEVICE);

print "Reading $InBytes from $DEVICE ...\n";
my ($count_in, $string_in); ### = $serial->read($InBytes);
### warn "read unsuccessful\n" unless ($count_in == $InBytes);
$msg = $string_in;
my $msglast = '';
my $msgend = "";
my $gotstg = 0;
my $pos1 = 0;
my $pos2 = 0;
my $gpsmsg = '';
my $outcnt = 0;
my $totcnt = 0;
###my $maxperfile = 60; # assume one-per-second

my ($count_in, $string_in); ### = $serial->read($InBytes);
$msg = "";
print "Awaiting first GPS message ... Ctrl+C to exit!\n" if $gotstg;
while (1) {
	# stay here until FIRST GPS message received, or at least the $GPRMC beginning
	($count_in, $string_in) = $serial->read($InBytes);
	$msglast = $msg; # keep last
	$msg .= $string_in; # accumulate the input
	print "Read $count_in of $InBytes ... $string_in.\n";
	if ( $msg =~ /\$GPRMC/om ) {
		$pos1 = index ($msg, '$GPRMC');
		if ($pos1 > 0) {
			$msg = substr( $msg, $pos1 );
		}
		print "$msg ... Ctrl+C to exit";
		$gotstg = 1;
		last;
	}
}

print "\nBeginning GPS message accumulation ... Ctrl+C to exit\n" if $gotstg;
$| = 1; # set file flush on
while ($gotstg) {
	($count_in, $string_in) = $serial->read($InBytes);
	$msglast = $msg;
	$msg .= $string_in;
	if ($gotstg) {
		# we already have a start of cycle on $GPRMC sentence
		$msgend = substr($msg,6);
		if ($msgend =~ /\$GPRMC/om) { # got NEXT
			$outcnt++; # bump the GPS message set count
			$totcnt++; # bump the GPS message total count
			if ($dbgon1) {
				print "\nGot GPS Count $totcnt\n";
			} else {
				print "\rGot GPS Count $totcnt/$outcnt ... Ctrl+C to exit!";
			}
			$pos2 = index ($msgend, '$GPRMC');
			$gpsmsg = '$GPRMC' . substr($msgend, 0, $pos2);
			print $gpsmsg if $dbgon2;
			print $OF $gpsmsg;
			process_GPRMC_msg ( $gpsmsg );
			$msg = substr ($msgend, $pos2);
			print "NEW START: $msg" if $dbgon2;
			if ($outcnt >= $maxperfile) {
				close ($OF);
				$logfile = nextfilename($logfile);
				$outfile = $logdir . $logfile;
				print "\nNew log file = $outfile ...\n";
				open ($OF, ">$outfile") or die "Can NOT open log file ... $outfile ...";
				write_html_pos ( $dispdt, $gps_lat_curr, $gps_long_curr );
				$outcnt = 0;
			}
		}
	}

##	if (defined ($char = ReadKey(-1)) ) {
##	if (defined ($char = getch()) ) {
##		# input was waiting and it was $char
##		last;
##	}
}

print "\nExit while ... len=" . length($msg) . "\n";
print "$msg\n";
close ($OF);

###print "Writing $DEVICE ...\n";
###$serial->write("Hello World");
###$cnt = $serial->write($msg);
###print "Written $cnt (", length($msg), ") ... Closing $DEVICE ...\n";
closePort($serial);
###ReadMode('normal');     # restore normal tty settings

### end of program
##############################################
######## subs

# @_ = (3352.3955,S) == -33 52.3955 == -33.8732583333333
sub latitude {
	my ($deg, $min) = unpack "a2a*", $_[0];
	my $lat = $deg + $min / 60;
	$lat = - $lat if $_[1] =~ /[Ss]/;
	return $lat;
}

# @_ = (15113.3678,E) == +151 13.6678 == 151.222796666667
sub longitude {
	my ($deg, $min) = unpack "a3a*", $_[0];
	my $long = $deg + $min / 60;
	$long = - $long if $_[1] =~ /[Ww]/;
	return $long;
}

### always have this set of CURRENT variables
### filled with the MOST recent date,time,lat,lon,...
sub gps_output {
	if ($gps_ok_rmc eq 'A') {
		# valid record
#	print OUTFILE $time_rmc, ',', $ok_rmc, ',', $lat_rmc, ',',
#		$long_rmc, ',', $speed, ',', $cmg, ',', $date, ',',
#		$mvar, ',';
		# $time_rmc = '13:02:10' HH:MM:SS format
		my (@hms) = split ':', $gps_time_rmc; # split TIME
		# $date = 26/07/05 # split DATE
		my (@dte) = split '/', $gps_date; # split date
		$currhr = $hms[0];
		$currmin = $hms[1];
		$currsec = $hms[2];
		$currday = $dte[0];
		$currmth = $dte[1];
		$curryr = $dte[2];
		if( ( ($currhr >=  0) && ($currhr  < 24) ) &&
			( ($currmin >= 0) && ($currmin < 60) ) &&
			( ($currsec >= 0) && ($currsec < 60) ) ) {
			# got a VALID time
			$currtimed = "$currhr:$currmin:$currsec";
			$currdated = "$curryr/$currmth/$currday";
			$dispdt = "$currdated $currtimed";
			$gps_lat_curr = $gps_lat_rmc; # latitude(@field[3..4]);
			$gps_long_curr = $gps_long_rmc; # longitude(@field[5..6]);
		}
	}
}

sub process_GPRMC_msg {
	my ($line) = @_;
	@field = split /[,*]/, $line; # split on comma, and * (checksum)
	# recommended minimum specific GPS/Transit data
	if ($field[0] eq '$GPRMC') {
		#  Each time we see this
		# sentence, print out the accumulated information
		# from the previous burst.
		gps_output() unless ($gps_first) ;
		$gps_first = 0;

		# Now process the new RMC record - example
### $GPRMC,130210.030,A,3352.3955,S,15113.3678,E,0.257256,125.59,260605,,*10                                                                        
		$gps_time_rmc = join ':', unpack "a2" x 3, $field[1];
		$gps_ok_rmc = $field[2];
		$gps_lat_rmc = latitude(@field[3..4]);
		$gps_long_rmc = longitude(@field[5..6]);
		$gps_speed = $field[7];
		$gps_cmg = $field[8];
		$gps_date = join '/', unpack "a2" x 3, $field[9];
		$gps_mvar = $field[10] . $field[11];
		# field[12] is checksum
		###last SWITCH;
	}
}


#**************************************************************************
#*  Serial functions
#**************************************************************************

#* Open raw serial port using:
#*    8 data bits
#*    1 stop bit
#*    19200 bps
#*    no parity
sub openPort($)
{
	my ($device) = @_;
	print "openPort $device ...\n";
	#my $serial = Device::SerialPort->new ($device, 1); # on UNIX
	my $serial = Win32::SerialPort->new ($device, 1); # on Windows
	die "Can't open serial port $serial: $^E\n" unless ($serial);

  my ($BlockingFlags, $InBytes, $OutBytes, $LatchErrorFlags) = $serial->status
        || warn "could not get port status\n";
  if ($BlockingFlags) { warn "Port is blocked"; }
#  if ($BlockingFlags & BM_fCtsHold) { warn "Waiting for CTS"; }
  if ($BlockingFlags & $serial->BM_fCtsHold) { warn "Waiting for CTS"; }
#  if ($LatchErrorFlags & CE_FRAME) { warn "Framing Error"; }
  if ($LatchErrorFlags & $serial->CE_FRAME) { warn "Framing Error"; }
        # The API resets errors when reading status, $LatchErrorFlags
        # is all $ErrorFlags seen since the last reset_error

	$serial->user_msg(1);
	$serial->databits(8);
	###$serial->baudrate(19200);
	$serial->parity("none");
	$serial->stopbits(1);
	###$serial->handshake("rts");

	$serial->buffers( 4096, 4096 );

#  my ($BlockingFlags, $InBytes, $OutBytes, $LatchErrorFlags) = $serial->status
#        || warn "could not get port status\n";
#  if ($BlockingFlags) { warn "Port is blocked"; }
#  if ($BlockingFlags & BM_fCtsHold) { warn "Waiting for CTS"; }
#  if ($LatchErrorFlags & CE_FRAME) { warn "Framing Error"; }
# $PortObj->transmit_char(0x03);        # bypass buffer (and suspend)
# $ModemStatus = $PortObj->modemlines;
# if ($ModemStatus & $PortObj->MS_RLSD_ON) { print "carrier detected"; }

	$serial->write_settings || die "Setting port FAILED";
	$serial->save($cfgfile); # = 'comm?.txt';

    return $serial;
}

sub closePort($)
{
	my ($serial) = @_;
	print "closePort ...\n";
	$serial->close();
}

# using 'templ' + '001-999' numbers
sub nextfilename {
	my ($tx) = @_;
	my $tx1 = substr ($tx, 0, 5);
	my $tx2 = substr ($tx, 5);
	my $tx3 = substr ($tx2, 0, 3);
	my $tx4 = substr ($tx2, 3);
	$tx3++;
	if ($tx3 > 999) {
		$tx3 = '001';
	}
	return ($tx1 . $tx3 . $tx4);
}

sub write_html_pos {
	my ($dt, $lat, $lon ) = @_;
	my $ct = localtime(time());
	if (open ($HOUT, ">../java/position.htm")) {
		print $HOUT <<EOF;
<html>
<head>
<meta http-equiv="Content-Language" content="en-au">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta http-equiv="refresh" content="10;url=position.htm">
<title>GPS Position - The Flower King</title>
</head>
<body>
<h1 align="center"><b>GPS Position - The Flower King</b></h1>
<div align="center">
  <center>
  <table border="2" cellpadding="6" cellspacing="6">
    <tr>
      <td>Date/Time</td>
      <td>Latitude</td>
      <td>Logitude</td>
    </tr>
    <tr>
      <td><b>$dt</b></td>
      <td><b>$lat</b></td>
      <td><b>$lon</b></td>
    </tr>
  </table>
  </center>
</div>
<p align="center"><img border="1" src="map2011s.jpg" width="581" height="373"></p>
<p><center>
<a href="index.html">Index</a>
</center></p>
<p align="right"><font size="-2">$ct</font></p>
</body>
</html>
<!-- auto-generated by comread2.pl - transferred to site by FtpPut.java -->
EOF
		close $HOUT;
		# transfer this HTML file up to the site ...
		system ("PutPos.BAT"); ### how to CHECK?
		# onto next messages ...
	}
}

# eof

