#!/usr/bin/perl -w
#
# therm-logger.pl
# version 1.0 -- 7 September 2003
#
# Query Sensatronics TempTrax2000 thermometer and log results
# 
# Copyright 2003 by John R. Ackermann  N8UR (jra@febo.com)
# Licensed under the GPL version 2 or later; see the file COPYING
# included with this distribution.  I request, but do not require, that
# any modifications that correct bugs or errors, or increase the program's
# functionality, be sent via email to the author at the address above.

use strict;
use vars qw( $OS_win $ob $port );
use POSIX qw(setsid);
use Getopt::Std;
use Device::SerialPort;
use Time::HiRes qw(usleep);

#----------
# some variables that need to be declared
my $quiet = "1";
my $count = 0;
my $lockfile;
my $reading;
my $temp1;
my $temp2;
my $tmp1 = 0;
my $tmp2 = 0;
my $bat;

#----------
# handle signals and errors -- mainly to clear lockfile on termination
sub sig_handler {
	undef $ob;
	if (-e $lockfile) {unlink $lockfile;}
	close LOG;
	exit(0);
}

# there's got to be a better way!
$SIG{'HUP'} = 'sig_handler';
$SIG{'INT'} = 'sig_handler';
$SIG{'KILL'} = 'sig_handler';
$SIG{'STOP'} = 'sig_handler';
$SIG{'TERM'} = 'sig_handler';
#----------

#----------
# display usage
my $opt_string = 'adhi:f:p:';

sub usage() {
print STDERR << "EOF";

usage: $0 [-adh] -f logfile -i log_interval -p serial_port
-a	: average 10 readings (only if interval > 11 seconds)
-d	: run as daemon
-h	: this (help) message
-f	: logfile using full pathname;
	  for output to console, use "-f -"
-i	: logging interval in seconds
-p	: serial port ("ttyS1")

EOF
}
#----------

#----------
# daemonize
sub daemonize {
	chdir '/' or die "Can't chdir to /: $!";
	umask 0;
	open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
	open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!";
	open STDERR, '>/dev/null' or die "Can't write to /dev/null: $!";
	defined(my $pid = fork) or die "Can't fork: $!";
	exit if $pid;
	setsid or die "Can't start a new session: $!";
}
#----------

getopts( "$opt_string", \my %opt ) or usage() and exit;

# print usage
usage() and exit if $opt{h};

# average readings
my $average = 0;
if ($opt{a}) {
	$average = 1;
	}

# run as daemon?
&daemonize if $opt{d};

# set variables to command line params
my $interval = $opt{i};
my $portbase = $opt{p};
my $logfile = $opt{f};

#----------
# set up serial port
my $port = "/dev/" . $portbase;
$lockfile = "/var/lock/LCK.." . $portbase;
$ob = Device::SerialPort->new ($port,$quiet,$lockfile);
die "Can't open serial port $port!\n" unless ($ob);

$ob->baudrate(9600)	|| die "fail setting baud after 0";
$ob->parity("none")	|| die "fail setting parity";
$ob->databits(8)	|| die "fail setting databits";
$ob->stopbits(1)	|| die "fail setting stopbits";
$ob->handshake("none")	|| die "fail setting handshake";
$ob->write_settings || die "no settings";

#----------
# set up logfile
open (LOG, ">>$logfile") ||
	die "Can't open logfile $logfile!\n";
# set nonbuffered mode
select(LOG), $| = 1;

#----------
# turn thermometer on
$ob->dtr_active(1) || die "fail setting DTR";
sleep 2;
# take an initial reading to clear buffers
$ob->write("a");
# sleep to get reading;
sleep 1;
# get serial port reading
$reading = $ob->input;

#----------
# main loop
while (1) {
	if ($average) {
		while ($count < $interval) {
			$ob->write("a");
			# sleep to get reading -- just under 1 sec. to
			# account for processing time;
			usleep(990000);

			# get serial port reading
			$reading = $ob->input;
			($temp1,$temp2,$bat) = split("\r\n",$reading);

			chomp($temp1);
			$temp1 =~ s/^\000//; ## Remove leading NUL characters
			$temp1 =~ s/\000$//; ## Remove trailing NUL characters
			$tmp1 = $tmp1 + $temp1;

			chomp($temp2);
			$temp2 =~ s/^\000//; ## Remove leading NUL characters
			$temp2 =~ s/\000$//; ## Remove trailing NUL characters
			$tmp2 = $tmp2 + $temp2;

			$count++;
			}
		$tmp1 = $tmp1/$interval;
		$tmp2 = $tmp2/$interval;
		$count = 0;
		}
	else {
			$ob->write("a");
			# sleep to get reading;
			sleep 1;

			# get serial port reading
			$reading = $ob->input;
			($temp1,$temp2,$bat) = split("\r\n",$reading);

			chomp($temp1);
			chomp($temp2);

			$temp1 =~ s/^\000//; ## Remove leading NUL characters
			$temp1 =~ s/\000$//; ## Remove trailing NUL characters
			$tmp1 = $temp1;
			$temp2 =~ s/^\000//; ## Remove leading NUL characters
			$temp2 =~ s/\000$//; ## Remove trailing NUL characters
			$tmp2 = $temp2;
		}

	# print routine
	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime;
	printf LOG 
  	"%4.4u-%2.2u-%2.2uT%2.2u:%2.2u:%2.2u %5.1f %5.1f\n",
  	$year+1900,$mon+1,$mday,$hour,$min,$sec,$tmp1,$tmp2;

	$tmp1 = 0;
	$tmp2 = 0;

	# sleep for loop if not averaging; subtract reading sleep
	if (!$average) {
		sleep $interval - 1;
		}
}	
#----------

exit 0;
