#!/usr/bin/perl

use DBI;
use strict;
use Time::HiRes;
use Serial;
use Device::SerialPort;
use Mojo::IOLoop;
use Mojo::IOLoop::Stream;

my $devname = "/dev/davis";

#my $ob = Serial->new ($devname, 19200) || die;
my $ob = Device::SerialPort->new ($devname) || die;

$ob->user_msg(1);				# misc. warnings
$ob->error_msg(1);				# hardware and data errors

$ob->baudrate(19200);
$ob->parity("none");
#$ob->parity_enable(1); 	# for any parity except "none"
$ob->databits(8);
$ob->stopbits(1);
$ob->handshake('none');
$ob->read_const_time(15000);	# ultimate timeout (15 seconds)
$ob->write_settings||die"setting failed";

$ob->read_char_time(0);
$ob->read_const_time(300);

my $awake=0;
my $attempts=0;
$ob->write("\n");				# initial wak

my $awake = 0;
my $attempts;

while ($awake==0) {
	$ob->write("\n");				   # wake for real
	my ($count, $result) = $ob->read(10); # read up to 10 chars
	if ($result eq "\n\r") {
		print "awoke on attempt $attempts :)\n";
		$awake=1;
	} else {
		print "wake error on attempt $attempts :(\n";
	}
	$attempts++;
	die("failed to wake device - tried $attempts times\n") unless $attempts<6;
}

$ob->write("STRMON\n");

my $end;

$SIG{TERM} = $SIG{INT} = sub {++$end; print "\nending $end\n";};

while (!$end) {

#	print "end: $end\n";
	
	my ($count, $l) = $ob->read(255); 
	next unless $count;

	s|\cM|<CR>|g;
	s|\cJ|<NL>|g;
	s|\cI|<TAB>|g;
	
	my @l = split /[\cJ\cM]/, $l;
	my ($wspeed, $wdir, $val1, $val2, $sort, $batt);

	my @hex;
	
	for (@l) {
		next unless $_;
		my ($k, $v) = $_ =~ /^(\d)\s+=\s+([\dabcdef]+)/;
		next unless defined $k && defined $v;
		my $h = hex $v;
		push @hex, $h;
		if ($k == 0) {
			if (($h & 0xf0) == 0x80) {
				$sort = "T";
			} elsif (($h & 0xf0) == 0xa0) {
				$sort = 'H';
			} elsif (($h & 0xf0) == 0xe0) {
				$sort = 'R';
			} elsif (($h & 0xf0) == 0x50) {
				$sort = 'P';
			} else {
				$sort = 'W';	# wind only
			}
			if ($h & 0x08) {	# new battery required
				$batt = ' NB';
			}
		} elsif ($k == 1) {
			$wspeed = $h;
		} elsif ($k == 2) {
			$wdir = int($h * 360 / 255);
		} elsif ($k == 3) {
			$val2 = $val1 = $h;
		} elsif ($k == 4) {
			if ($sort eq 'H') {
				$val2 = (($h >> 4) << 8) | $val2;
			} elsif ($sort eq 'T') {
				$val2 = ($h << 8) | $val2;
			} else {
				$val2 = ($val2 << 8) | $h;
			}
		}
	}
	if ($sort) {
		printf("%02X ", $_) for (@hex);
		if ($sort eq 'T') {	
			printf "$sort$batt %3d %3d %0.1f\n", $wspeed, $wdir, (($val2/160) - 32) * 5/9;
		} elsif ($sort eq 'H') {
			printf "$sort$batt %3d %3d %0.1f\n", $wspeed, $wdir, $val2/10;
		} elsif ($sort eq 'P') {
			printf "$sort$batt %3d %3d %0.2f\n", $wspeed, $wdir, $val2 / 1000;
		} elsif ($sort eq 'R') {
			printf "$sort$batt %3d %3d $val1\n", $wspeed, $wdir;
		} elsif ($sort eq 'W') {
			printf "$sort$batt %3d %3d\n", $wspeed, $wdir, $val2;
		} else {
			print "\n";
		}
	}
}

$ob->write("STRMOFF\n");
$ob->read(255);
exit(0);



