#!/usr/bin/perl -w

use strict;
use IO::Socket;

my $MAX_STILL_GPS = 60;
my $NETWORK_INTERVAL = 30;
my $NO_GPS_WARN = 15;
my $host = 'localhost';
#my $port = 2947; #gpsd
my $port = 2501; #kismet

my $proto = getprotobyname( 'tcp' );

my $iaddr = inet_aton( $host );
my $paddr = sockaddr_in( $port, $iaddr );
my $socket = new IO::Socket::INET( PeerAddr => $host, PeerPort => $port, Proto => 'tcp');
$socket	or die "socket error: $!";
# print "connected\n";

my $lastlat = 0;
my $lastlon = 0;
my $lastspeed = 0;
my $lastgpschange = time;
my $lastgpsread = 0;
my $lastgpsfix = 0;
my $lastgpsfixcount = 0;
my $lastgpsnoread = 0;
my $lastnetread = 0;
my $readgpschange = 0;
my $lastssid = 'none';
my $lastac = -1;

while ( defined ( my $line = <$socket> ) ) {
	my $now = time;
	# print "line: $line";
	if ( $line =~ /^\*INFO: (.*?)$/si ) {
		my $networks = $1;
		# print "networks: $networks\n";
		my $diff = $now - $lastnetread;
		if ( $diff >= $NETWORK_INTERVAL ) {
			my $saytxt = "Networks $networks.";# Speed $lastspeed."
			$saytxt .= " fix $lastgpsfix." if $lastgpsfix != 3;
			&say( $saytxt );
			# &say( "Last $lastssid." );
			$lastnetread = $now;
		}
	}
	elsif ( $line =~ /^\*GPS: (.*?)$/si ) {
		my $data = $1;
		my @gps = split / /, $data;
		my $lat = $gps[0];
		my $lon = $gps[1];
		my $speed = $gps[3];
		my $fix = $gps[4];
		$speed =~ s/\..*$//sgi;
		# print "lat: $lat lon: $lon speed: $speed\n";
		if ( $lat != $lastlat or $lon != $lastlon ) {
			$lastgpschange = $now;
			if ( $readgpschange ) {
				&say( "GPS now changed. speed $speed. fix $fix\n" );
				$readgpschange = 0;
			}
		}
		if ( $fix != $lastgpsfix ) {
			$lastgpsfixcount = 0;
		}
		else {
			$lastgpsfixcount++;
		}
		if ( ($fix == 1 and $fix != $lastgpsfix) or $lastgpsfixcount == 5 ) {
			my $say = "gps fix $fix";
			$say = "warning. no GPS fix." if $fix <= 1;
			$say = "GPS 2D fix" if $fix == 2;
			$say = "GPS 3D fix" if $fix == 3;
			if ( $fix == 1 ) {
				my $diff = $now - $lastgpsnoread;
				if ( $diff >= $NO_GPS_WARN ) {
					&say( $say );
					$lastgpsnoread = $now;
				}
			}
			else {
				&say( $say );
			}
		}

		$lastlat = $lat;
		$lastlon = $lon;
		$lastspeed = $speed;
		$lastgpsfix = $fix;
		my $diff = $now - $lastgpschange;
		my $diffread = $now - $lastgpsread;
		if ( $diff >= $MAX_STILL_GPS and $diffread >= $MAX_STILL_GPS ) {
			&say( "GPS unchanged $diff seconds. speed $speed. fix $fix\n" );
			$lastgpsread = $now;
			$readgpschange = 1;
		}
	}
	elsif ( $line =~ /^\*SSID: (.*?)$/si ) {
		my $ssid = $1;
		$ssid =~ s/[\\]\d+//sgi;
		$ssid =~ s/[\;\n\r\\]//sgi;
		$lastssid = $ssid;
	}
	elsif ( $line =~ /^\*BATTERY: (.*?)$/si ) {
		my $data = $1;
		my @batt = split / /, $data;
		if ( $lastac != $batt[2] ) {
			my $status = $batt[2] == 1 ? "On" : "Off";
			&say( "AC now $status." );
		}
		$lastac = $batt[2];
	}
	elsif ( $line =~ /^\*KISMET:/si ) {
	}
	elsif ( $line =~ /^\*ACK:/si ) {
	}
	elsif ( $line =~ /^\*ALERT: (.*?)$/si ) {
		my $alert = $1;
		&say( "Alert $alert" );
	}
	elsif ( $line =~ /^\*PROTOCOLS:/si ) {
		# print "sending goo\n";
		print $socket "!1 REMOVE TIME\r\n";
		print $socket "!1 ENABLE INFO networks\n";
		# print $socket "!1 ENABLE SSID ssid\n";
		# print $socket "!1 ENABLE ALERT *\n";
		print $socket "!1 ENABLE BATTERY percentage,charging,ac,remaining\n";
		print $socket "!1 ENABLE GPS lat,lon,alt,spd,fix\n";
		#print $socket "!1 ENABLE GPS lat,lon,alt,spd,heading,fix,satinfo,hdop,vdop\n";
	}
}

&say( "disconnected. disconnected. disconnected. disconnected. crud." );
print "closing connection\n";
close $socket or die "close error: $!";

sub say {
	my $txt = shift;
	`/bin/echo "$txt" | /usr/bin/festival --tts`;
}
