#!/usr/bin/perl
#
# (c) 20060318 by Ewald
# http://www.oiepoie.nl


use Device::SerialPort;		# to read serial port data
use Getopt::Std;		# to handle cmdline options

my $V="0.9 20060318";		# version and date of latest modification
my $DEBUG = 0;			# do we want debugging output?
my $WAIT = 300;			# how many seconds to wait between reads
my $ONCE = 0;			# run only once?
my $UT = 0; 			# display timestamp in Unix format?
my $DONE = 0;
my $now;
my $TS=1;			# do we want timestamps at all? (yes)
my $C=1;			# display C to denote Celsius? (yes)
my $P = "/dev/ttyS0";		# default serial port to monitor

my %Options;
$ok = getopts('t:w:1uhdnc', \%Options);

if (defined $Options{h}) {
	print "logger.pl version: $V\n";
	print "Program to read temperature data from Papouch serial temp probe\n";
	print "Possible options:\n";
	print "-h	Help (this output)\n";
	print "-d	print debugging output\n";
	print "-c	Don't print C for celsius after values?\n";
	print "-n	Don't display timestamps\n";
	print "-1	Output temperature and exit\n";
	print "-u	show timestamp in Unix format (seconds since epoch)\n";
	print "-t x	read data from /dev/ttySx (default: $P) \n";
	print "-w N	wait N seconds between readouts (default $WAIT)\n";
	exit 0;
	}

$ONCE  = 1 if defined $Options{1};
$DEBUG = 1 if defined $Options{d};
$TS    = 0 if defined $Options{n};
$C     = 0 if defined $Options{c};

$WAIT = $Options{w} if defined $Options{w};
$UT   = $Options{u} if defined $Options{u};

if (defined $Options{t}) {
	$P = "/dev/ttyS";
	$P .= $Options{t};
	}

$DEBUG && print "monitoring serial port: $P\n";
$DEBUG && print "wait interval is $WAIT\n";
$DEBUG && print "run once? $ONCE\n";
$DEBUG && print "Unix timestamps? $UT\n";

# Serial Port initialization
my $port=Device::SerialPort->new($P) || die "cannot open $P: $!";

$port->user_msg(ON);
$port->error_msg(ON);
$DEBUG && $port->debug($DEBUG);

$port->baudrate(9600)    || die "failed setting baudrate";
$port->parity("none")    || die "failed setting parity";
$port->databits(8)       || die "failed setting databits";
$port->stopbits(2)       || die "failed setting databits";
$port->handshake("none") || die "failed setting handshake";
$port->write_settings    || die "cannot write settings";

# unset RTS and DTR
$port->rts_active(0);
$port->dtr_active(0);
sleep 1;		# just a little wait to be sure we get stable data later on

if (($port->can_modemlines) && $DEBUG) {
	$ModemStatus = $port->modemlines;
	if ($ModemStatus & $port->MS_RTS_ON) { print "RTS ON\n"; }
	else { print "RTS OFF\n"; }
	if ($ModemStatus & $port->MS_DTR_ON) { print "DTR ON\n"; }
	else { print "DTR OFF\n"; }
        print "\n";
	}

# by setting RTS and DTR high we supply power to the device
# and in return it will supply us with data
$port->rts_active(1);
$port->dtr_active(1);

if (($port->can_modemlines) && $DEBUG) {
	$ModemStatus = $port->modemlines;
	if ($ModemStatus & $port->MS_RTS_ON) { print "RTS ON\n"; }
	else { print "RTS OFF\n"; }
	if ($ModemStatus & $port->MS_DTR_ON) { print "DTR ON\n"; }
	else { print "DTR OFF\n"; }
        print "\n";
	}

$port->read_char_time(0);     # don't wait for each character
$port->read_const_time(1000); # 1 second per unfulfilled "read" call

while (!$DONE) {
  my ($count,$saw)=$port->read(8);		# we should get 8 chars
  if ($count > 0) {

	$port->rts_active(0);			# power-off device for now
	$port->dtr_active(0);

	$saw =~ s/([\+\-]\S+C)\r/$1/e;		# value will be something like: +020.9C^M or -001.3C^M
						# so we want to strip of the ^M (\r)
	if (!$C) { $saw =~ s/(\S+)C/$1/e; }	# strip of the C char
	if ($TS) {
	   if ($UT) {
	      $now = time;			# UNIX timestamp
	      }
   	   else {
	      $now = localtime time;		# human readable timestamp
	      }
	   printf "%s\t%s\n", $now,$saw;
	   }
	else {
	   printf "%s\n", $saw;			# output just the data
	   }

	if ($ONCE) {				# are we done?
	   $DONE = 1;
	   }
	else {
	   sleep $WAIT;				# sleep a little while before reading the next value
	   $port->rts_active(1);		# power-on
	   $port->dtr_active(1);
	   }
	}
  else {
	print "ERR: we got $count bytes of data\n";
	}
}

$port->rts_active(0);			# power-off device
$port->dtr_active(0);
undef $port;
