#!/usr/bin/perl
#
# Written by Travis Kent Beste
# Mon Aug 9 08:47:24 CDT 2010
use lib qw( ./lib ../lib );
use BT368i;
use strict;
use warnings;
use Tk;
use Tk::Dialog;
use Tk::Graph;
use Tk::NoteBook;
use Data::Dumper;
#----------------------------------------#
# main
#----------------------------------------#
my $bt368i = new BT368i(
Port => '/dev/tty.BT-GPS-38BD5D-BT-GPSCOM',
Baud => '115200',
);
my $rmc = new BT368i::NMEA::GP::RMC();
my $gsa = new BT368i::NMEA::GP::GSA();
my $gga = new BT368i::NMEA::GP::GGA();
my $gsv = new BT368i::NMEA::GP::GSV();
my $gll = new BT368i::NMEA::GP::GLL();
my $vtg = new BT368i::NMEA::GP::VTG();
$bt368i->BT368i::log('./log/all.log');
$rmc->BT368i::log('./log/rmc.log');
$gsa->BT368i::log('./log/gsa.log');
$gga->BT368i::log('./log/gga.log');
$gsv->BT368i::log('./log/gsv.log');
$gll->BT368i::log('./log/gll.log');
$vtg->BT368i::log('./log/vtg.log');
my $VERSION = '1.0';
my $mw = MainWindow->new;
my $notebook;
my $menubar;
# tabs
my $gga_tab;
my $gll_tab;
my $gsa_tab;
my $vtg_tab;
my $gsv_tab;
my $gsv_graph;
my $gsv_graph_data;
my $rmc_tab;
init();
MainLoop();
#----------------------------------------#
# subroutines
#----------------------------------------#
#----------------------------------------#
# process all serial data
#----------------------------------------#
sub parse_serial_data {
my $sentances = $bt368i->get_sentances();
foreach my $sentance (@$sentances) {
if ($sentance =~ /^\$GPGSA/) {
$gsa->parse($sentance);
#$gsa->print();
} elsif ($sentance =~ /^\$GPRMC/) {
$rmc->parse($sentance);
#$rmc->print();
} elsif ($sentance =~ /^\$GPGGA/) {
$gga->parse($sentance);
#$gga->print();
} elsif ($sentance =~ /^\$GPGSV/) {
$gsv->parse($sentance);
if ( defined($gsv->{'sentance_1'}->{'prn_0'}->{'id'}) && ( $gsv->{'sentance_1'}->{'prn_0'}->{'id'} ne "" ) ) { $gsv_graph_data->{$gsv->{'sentance_1'}->{'prn_0'}->{'id'}} = $gsv->{'sentance_1'}->{'prn_0'}->{'signal_to_noise'}; }
if ( defined($gsv->{'sentance_1'}->{'prn_1'}->{'id'}) && ( $gsv->{'sentance_1'}->{'prn_1'}->{'id'} ne "" ) ) { $gsv_graph_data->{$gsv->{'sentance_1'}->{'prn_1'}->{'id'}} = $gsv->{'sentance_1'}->{'prn_1'}->{'signal_to_noise'}; }
if ( defined($gsv->{'sentance_1'}->{'prn_2'}->{'id'}) && ( $gsv->{'sentance_1'}->{'prn_2'}->{'id'} ne "" ) ) { $gsv_graph_data->{$gsv->{'sentance_1'}->{'prn_2'}->{'id'}} = $gsv->{'sentance_1'}->{'prn_2'}->{'signal_to_noise'}; }
if ( defined($gsv->{'sentance_1'}->{'prn_3'}->{'id'}) && ( $gsv->{'sentance_1'}->{'prn_3'}->{'id'} ne "" ) ) { $gsv_graph_data->{$gsv->{'sentance_1'}->{'prn_3'}->{'id'}} = $gsv->{'sentance_1'}->{'prn_3'}->{'signal_to_noise'}; }
if ( defined($gsv->{'sentance_2'}->{'prn_0'}->{'id'}) && ( $gsv->{'sentance_2'}->{'prn_0'}->{'id'} ne "" ) ) { $gsv_graph_data->{$gsv->{'sentance_2'}->{'prn_0'}->{'id'}} = $gsv->{'sentance_2'}->{'prn_0'}->{'signal_to_noise'}; }
if ( defined($gsv->{'sentance_2'}->{'prn_1'}->{'id'}) && ( $gsv->{'sentance_2'}->{'prn_1'}->{'id'} ne "" ) ) { $gsv_graph_data->{$gsv->{'sentance_2'}->{'prn_1'}->{'id'}} = $gsv->{'sentance_2'}->{'prn_1'}->{'signal_to_noise'}; }
if ( defined($gsv->{'sentance_2'}->{'prn_2'}->{'id'}) && ( $gsv->{'sentance_2'}->{'prn_2'}->{'id'} ne "" ) ) { $gsv_graph_data->{$gsv->{'sentance_2'}->{'prn_2'}->{'id'}} = $gsv->{'sentance_2'}->{'prn_2'}->{'signal_to_noise'}; }
if ( defined($gsv->{'sentance_2'}->{'prn_3'}->{'id'}) && ( $gsv->{'sentance_2'}->{'prn_3'}->{'id'} ne "" ) ) { $gsv_graph_data->{$gsv->{'sentance_2'}->{'prn_3'}->{'id'}} = $gsv->{'sentance_2'}->{'prn_3'}->{'signal_to_noise'}; }
if ( defined($gsv->{'sentance_3'}->{'prn_0'}->{'id'}) && ( $gsv->{'sentance_3'}->{'prn_0'}->{'id'} ne "" ) ) { $gsv_graph_data->{$gsv->{'sentance_3'}->{'prn_0'}->{'id'}} = $gsv->{'sentance_3'}->{'prn_0'}->{'signal_to_noise'}; }
if ( defined($gsv->{'sentance_3'}->{'prn_1'}->{'id'}) && ( $gsv->{'sentance_3'}->{'prn_1'}->{'id'} ne "" ) ) { $gsv_graph_data->{$gsv->{'sentance_3'}->{'prn_1'}->{'id'}} = $gsv->{'sentance_3'}->{'prn_1'}->{'signal_to_noise'}; }
if ( defined($gsv->{'sentance_3'}->{'prn_2'}->{'id'}) && ( $gsv->{'sentance_3'}->{'prn_2'}->{'id'} ne "" ) ) { $gsv_graph_data->{$gsv->{'sentance_3'}->{'prn_2'}->{'id'}} = $gsv->{'sentance_3'}->{'prn_2'}->{'signal_to_noise'}; }
if ( defined($gsv->{'sentance_3'}->{'prn_3'}->{'id'}) && ( $gsv->{'sentance_3'}->{'prn_3'}->{'id'} ne "" ) ) { $gsv_graph_data->{$gsv->{'sentance_3'}->{'prn_3'}->{'id'}} = $gsv->{'sentance_3'}->{'prn_3'}->{'signal_to_noise'}; }
if (defined ($gsv_graph) ) {
$gsv_graph->set($gsv_graph_data);
}
#$gsv->print();
} elsif ($sentance =~ /^\$GPGLL/) {
$gll->parse($sentance);
#$gll->print();
} elsif ($sentance =~ /^\$GPVTG/) {
$vtg->parse($sentance);
#$vtg->print();
} else {
#print "sentance : $sentance\n";
}
}
}
#----------------------------------------#
# initialization
#----------------------------------------#
sub init {
$mw->geometry("500x450+1000+100");
$mw->repeat(100, \&parse_serial_data);
$mw->title("bt368i $VERSION");
$mw->iconname('bt368i');
# notebook
$notebook = $mw->NoteBook()->pack(-fill=>'both', -expand=>1);
# build menubar
$menubar = build_menubar();
$gsv_tab = $notebook->add("Sheet 5", -label=>"GSV", -createcmd=>\&gsv);
$rmc_tab = $notebook->add("Sheet 6", -label=>"RMC", -createcmd=>\&rmc);
$gga_tab = $notebook->add("Sheet 2", -label=>"GGA", -createcmd=>\&gga);
$gll_tab = $notebook->add("Sheet 4", -label=>"GLL", -createcmd=>\&gll);
$gsa_tab = $notebook->add("Sheet 1", -label=>"GSA", -createcmd=>\&gsa);
$vtg_tab = $notebook->add("Sheet 3", -label=>"VTG", -createcmd=>\&vtg);
}
#----------------------------------------#
#
#----------------------------------------#
sub rmc {
$rmc_tab->Label(-height=>1, -text => "utc_time", -anchor=>'w', -width=>25)->grid(-row=>0, -column=>0);
$rmc_tab->Entry(-textvariable=>\$rmc->{'utc_time'})->grid(-row=>0, -column=>1);
$rmc_tab->Label(-height=>1, -text => "status", -anchor=>'w', -width=>25)->grid(-row=>1, -column=>0);
$rmc_tab->Entry(-textvariable=>\$rmc->{'status'})->grid(-row=>1, -column=>1);
$rmc_tab->Label(-height=>1, -text => "latitude", -anchor=>'w', -width=>25)->grid(-row=>2, -column=>0);
$rmc_tab->Entry(-textvariable=>\$rmc->{'latitude'})->grid(-row=>2, -column=>1);
$rmc_tab->Label(-height=>1, -text => "latitude_hemisphere", -anchor=>'w', -width=>25)->grid(-row=>3, -column=>0);
$rmc_tab->Entry(-textvariable=>\$rmc->{'latitude_hemisphere'})->grid(-row=>3, -column=>1);
$rmc_tab->Label(-height=>1, -text => "longitude", -anchor=>'w', -width=>25)->grid(-row=>4, -column=>0);
$rmc_tab->Entry(-textvariable=>\$rmc->{'longitude'})->grid(-row=>4, -column=>1);
$rmc_tab->Label(-height=>1, -text => "longitude_hemisphere", -anchor=>'w', -width=>25)->grid(-row=>5, -column=>0);
$rmc_tab->Entry(-textvariable=>\$rmc->{'longitude_hemisphere'})->grid(-row=>5, -column=>1);
$rmc_tab->Label(-height=>1, -text => "speed", -anchor=>'w', -width=>25)->grid(-row=>6, -column=>0);
$rmc_tab->Entry(-textvariable=>\$rmc->{'speed'})->grid(-row=>6, -column=>1);
$rmc_tab->Label(-height=>1, -text => "course", -anchor=>'w', -width=>25)->grid(-row=>7, -column=>0);
$rmc_tab->Entry(-textvariable=>\$rmc->{'course'})->grid(-row=>7, -column=>1);
$rmc_tab->Label(-height=>1, -text => "utc_date", -anchor=>'w', -width=>25)->grid(-row=>8, -column=>0);
$rmc_tab->Entry(-textvariable=>\$rmc->{'utc_date'})->grid(-row=>8, -column=>1);
$rmc_tab->Label(-height=>1, -text => "magnetic_variation", -anchor=>'w', -width=>25)->grid(-row=>9, -column=>0);
$rmc_tab->Entry(-textvariable=>\$rmc->{'magnetic_variation'})->grid(-row=>9, -column=>1);
$rmc_tab->Label(-height=>1, -text => "magnetic_variation_direction", -anchor=>'w', -width=>25)->grid(-row=>10, -column=>0);
$rmc_tab->Entry(-textvariable=>\$rmc->{'magnetic_variation_direction'})->grid(-row=>10, -column=>1);
}
#----------------------------------------#
#
#----------------------------------------#
sub gsv {
$gsv_tab->Label(-height=>1, -text => "gsv_sentance_count", -anchor=>'w', -width=>25)->grid(-row=>0, -column=>0);
$gsv_tab->Entry(-textvariable=>\$gsv->{'gsv_sentance_count'})->grid(-row=>0, -column=>1);
$gsv_tab->Label(-height=>1, -text => "current_gsv_sentance", -anchor=>'w', -width=>25)->grid(-row=>1, -column=>0);
$gsv_tab->Entry(-textvariable=>\$gsv->{'current_gsv_sentance'})->grid(-row=>1, -column=>1);
$gsv_tab->Label(-height=>1, -text => "number_of_satilites", -anchor=>'w', -width=>25)->grid(-row=>2, -column=>0);
$gsv_tab->Entry(-textvariable=>\$gsv->{'number_of_satilites'})->grid(-row=>2, -column=>1);
$gsv_graph = $gsv_tab->Graph(
-type => 'HBARS',
-printvalue => '%s %d',
-max => 99,
-width => 300,
-barwidth => 20,
-xformat => '',
-height => 300,
-sortnames => 'alpha',
-sortreverse => '1',
)->grid(-row=>3, -column=>0, -columnspan=>2);
#$gsv_graph->set($gsv_graphdata); # no need to assign nothing to the graph, it'll show up soon enough
}
#----------------------------------------#
#
#----------------------------------------#
sub gga {
$gga_tab->Label(-height=>1, -text => "utc_time", -anchor=>'w', -width=>25)->grid(-row=>0, -column=>0);
$gga_tab->Entry(-textvariable=>\$gga->{'utc_time'})->grid(-row=>0, -column=>1);
$gga_tab->Label(-text => "latitude", -anchor=>'w', -width=>25)->grid(-row=>1, -column=>0);
$gga_tab->Entry(-textvariable=>\$gga->{'latitude'})->grid(-row=>1, -column=>1);
$gga_tab->Label(-text => "latitude_hemisphere", -anchor=>'w', -width=>25)->grid(-row=>2, -column=>0);
$gga_tab->Entry(-textvariable=>\$gga->{'latitude_hemisphere'})->grid(-row=>2, -column=>1);
$gga_tab->Label(-text => "longitude", -anchor=>'w', -width=>25)->grid(-row=>3, -column=>0);
$gga_tab->Entry(-textvariable=>\$gga->{'longitude'})->grid(-row=>3, -column=>1);
$gga_tab->Label(-text => "longitude_hemisphere", -anchor=>'w', -width=>25)->grid(-row=>4, -column=>0);
$gga_tab->Entry(-textvariable=>\$gga->{'longitude_hemisphere'})->grid(-row=>4, -column=>1);
$gga_tab->Label(-text => "fix_type", -anchor=>'w', -width=>25)->grid(-row=>5, -column=>0);
$gga_tab->Entry(-textvariable=>\$gga->{'fix_type'})->grid(-row=>5, -column=>1);
$gga_tab->Label(-text => "satilites_in_use", -anchor=>'w', -width=>25)->grid(-row=>6, -column=>0);
$gga_tab->Entry(-textvariable=>\$gga->{'satilites_in_use'})->grid(-row=>6, -column=>1);
$gga_tab->Label(-text => "antenna_height", -anchor=>'w', -width=>25)->grid(-row=>7, -column=>0);
$gga_tab->Entry(-textvariable=>\$gga->{'antenna_height'})->grid(-row=>7, -column=>1);
$gga_tab->Label(-text => "geoidal_height", -anchor=>'w', -width=>25)->grid(-row=>8, -column=>0);
$gga_tab->Entry(-textvariable=>\$gga->{'geoidal_height'})->grid(-row=>8, -column=>1);
$gga_tab->Label(-text => "dgps_data_age", -anchor=>'w', -width=>25)->grid(-row=>9, -column=>0);
$gga_tab->Entry(-textvariable=>\$gga->{'dgps_data_age'})->grid(-row=>9, -column=>1);
$gga_tab->Label(-text => "dgps_reference_station_id", -anchor=>'w', -width=>25)->grid(-row=>10, -column=>0);
$gga_tab->Entry(-textvariable=>\$gga->{'dgps_reference_station_id'})->grid(-row=>10, -column=>1);
}
#----------------------------------------#
#
#----------------------------------------#
sub gll {
$gll_tab->Label(-text => "latitude", -anchor=>'w', -width=>25)->grid(-row=>0, -column=>0);
$gll_tab->Entry(-textvariable=>\$gll->{'latitude'})->grid(-row=>0, -column=>1);
$gll_tab->Label(-text => "latitude_hemisphere", -anchor=>'w', -width=>25)->grid(-row=>1, -column=>0);
$gll_tab->Entry(-textvariable=>\$gll->{'latitude_hemisphere'})->grid(-row=>1, -column=>1);
$gll_tab->Label(-text => "longitude", -anchor=>'w', -width=>25)->grid(-row=>2, -column=>0);
$gll_tab->Entry(-textvariable=>\$gll->{'longitude'})->grid(-row=>2, -column=>1);
$gll_tab->Label(-text => "longitude_hemisphere", -anchor=>'w', -width=>25)->grid(-row=>3, -column=>0);
$gll_tab->Entry(-textvariable=>\$gll->{'longitude_hemisphere'})->grid(-row=>3, -column=>1);
$gll_tab->Label(-text => "utc_time", -anchor=>'w', -width=>25)->grid(-row=>4, -column=>0);
$gll_tab->Entry(-textvariable=>\$gll->{'utc_time'})->grid(-row=>4, -column=>1);
$gll_tab->Label(-text => "data_valid", -anchor=>'w', -width=>25)->grid(-row=>5, -column=>0);
$gll_tab->Entry(-textvariable=>\$gll->{'data_valid'})->grid(-row=>5, -column=>1);
}
#----------------------------------------#
#
#----------------------------------------#
sub gsa {
$gsa_tab->Label(-text => "mode", -anchor=>'w', -width=>25)->grid(-row=>0, -column=>0);
$gsa_tab->Entry(-textvariable=>\$gsa->{'mode'})->grid(-row=>0, -column=>1);
$gsa_tab->Label(-text => "fix_type", -anchor=>'w', -width=>25)->grid(-row=>1, -column=>0);
$gsa_tab->Entry(-textvariable=>\$gsa->{'fix_type'})->grid(-row=>1, -column=>1);
$gsa_tab->Label(-text => "prn_00", -anchor=>'w', -width=>25)->grid(-row=>2, -column=>0);
$gsa_tab->Entry(-textvariable=>\$gsa->{'prn_00'})->grid(-row=>2, -column=>1);
$gsa_tab->Label(-text => "prn_01", -anchor=>'w', -width=>25)->grid(-row=>3, -column=>0);
$gsa_tab->Entry(-textvariable=>\$gsa->{'prn_01'})->grid(-row=>3, -column=>1);
$gsa_tab->Label(-text => "prn_02", -anchor=>'w', -width=>25)->grid(-row=>4, -column=>0);
$gsa_tab->Entry(-textvariable=>\$gsa->{'prn_02'})->grid(-row=>4, -column=>1);
$gsa_tab->Label(-text => "prn_03", -anchor=>'w', -width=>25)->grid(-row=>5, -column=>0);
$gsa_tab->Entry(-textvariable=>\$gsa->{'prn_03'})->grid(-row=>5, -column=>1);
$gsa_tab->Label(-text => "prn_04", -anchor=>'w', -width=>25)->grid(-row=>6, -column=>0);
$gsa_tab->Entry(-textvariable=>\$gsa->{'prn_04'})->grid(-row=>6, -column=>1);
$gsa_tab->Label(-text => "prn_05", -anchor=>'w', -width=>25)->grid(-row=>7, -column=>0);
$gsa_tab->Entry(-textvariable=>\$gsa->{'prn_05'})->grid(-row=>7, -column=>1);
$gsa_tab->Label(-text => "prn_06", -anchor=>'w', -width=>25)->grid(-row=>8, -column=>0);
$gsa_tab->Entry(-textvariable=>\$gsa->{'prn_06'})->grid(-row=>8, -column=>1);
$gsa_tab->Label(-text => "prn_07", -anchor=>'w', -width=>25)->grid(-row=>9, -column=>0);
$gsa_tab->Entry(-textvariable=>\$gsa->{'prn_07'})->grid(-row=>9, -column=>1);
$gsa_tab->Label(-text => "prn_08", -anchor=>'w', -width=>25)->grid(-row=>10, -column=>0);
$gsa_tab->Entry(-textvariable=>\$gsa->{'prn_08'})->grid(-row=>10, -column=>1);
$gsa_tab->Label(-text => "prn_09", -anchor=>'w', -width=>25)->grid(-row=>11, -column=>0);
$gsa_tab->Entry(-textvariable=>\$gsa->{'prn_09'})->grid(-row=>11, -column=>1);
$gsa_tab->Label(-text => "prn_10", -anchor=>'w', -width=>25)->grid(-row=>12, -column=>0);
$gsa_tab->Entry(-textvariable=>\$gsa->{'prn_10'})->grid(-row=>12, -column=>1);
$gsa_tab->Label(-text => "prn_11", -anchor=>'w', -width=>25)->grid(-row=>13, -column=>0);
$gsa_tab->Entry(-textvariable=>\$gsa->{'prn_11'})->grid(-row=>13, -column=>1);
$gsa_tab->Label(-text => "position_diliution", -anchor=>'w', -width=>25)->grid(-row=>14, -column=>0);
$gsa_tab->Entry(-textvariable=>\$gsa->{'position_diliution'})->grid(-row=>14, -column=>1);
$gsa_tab->Label(-text => "horizontal_diliution", -anchor=>'w', -width=>25)->grid(-row=>15, -column=>0);
$gsa_tab->Entry(-textvariable=>\$gsa->{'horizontal_diliution'})->grid(-row=>15, -column=>1);
$gsa_tab->Label(-text => "vertical_diliution", -anchor=>'w', -width=>25)->grid(-row=>16, -column=>0);
$gsa_tab->Entry(-textvariable=>\$gsa->{'vertical_diliution'})->grid(-row=>16, -column=>1);
}
#----------------------------------------#
#
#----------------------------------------#
sub vtg {
$vtg_tab->Label(-text => "true_track", -anchor=>'w', -width=>25)->grid(-row=>0, -column=>0);
$vtg_tab->Entry(-textvariable=>\$vtg->{'true_track'})->grid(-row=>0, -column=>1);
$vtg_tab->Label(-text => "magnetic_track", -anchor=>'w', -width=>25)->grid(-row=>1, -column=>0);
$vtg_tab->Entry(-textvariable=>\$vtg->{'magnetic_track'})->grid(-row=>1, -column=>1);
$vtg_tab->Label(-text => "ground_speed_knots", -anchor=>'w', -width=>25)->grid(-row=>2, -column=>0);
$vtg_tab->Entry(-textvariable=>\$vtg->{'ground_speed_knots'})->grid(-row=>2, -column=>1);
$vtg_tab->Label(-text => "ground_speed_kilometers", -anchor=>'w', -width=>25)->grid(-row=>3, -column=>0);
$vtg_tab->Entry(-textvariable=>\$vtg->{'ground_speed_kilometers'})->grid(-row=>3, -column=>1);
}
#----------------------------------------#
#
#----------------------------------------#
sub select_port {
my $port = shift;
#print "selecing $port...\n";
if ($port ne $bt368i->{serialport}) {
if ($bt368i->{serial}) {
$bt368i->{serial}->close || die "failed to close serialport";
undef $bt368i->{serial}; # frees memory back to perl
}
# assign what they selected
$bt368i->{serialport} = $port;
# connect to the serial port
$bt368i->connect();
}
}
#----------------------------------------#
# build the menu bar
#----------------------------------------#
sub build_menubar {
# Create the menubar and File and Quit menubuttons. Note
# that the cascade's menu widget is automatically created.
my $menubar = $mw->Menu;
$mw->configure(-menu => $menubar);
my $file = $menubar->cascade(-label => '~File');
my $port = $menubar->cascade(-label => '~Port');
my $help = $menubar->cascade(-label => '~Help', -tearoff => 0);
open(CMD, "ls -l /dev/tty.*|");
while(<CMD>) {
chomp();
$_ =~ /tty\.(.*)$/;
my $tty = $1;
# Create the menuitems for each menu. First, the File menu item.
$port->command(-label => $tty, -command => [\&select_port, $tty]);
}
close(CMD);
# Create the menuitems for each menu. First, the File menu item.
$file->command(-label => "~Quit", -command => \&quit);
# Finally, the Help menuitems.
$help->command(-label => 'Version');
$help->separator;
$help->command(-label => 'About');
my $ver_dialog = $mw->Dialog(
-title => 'BT368i Version',
-text => "BT368i\n\nVersion $VERSION",
-buttons => ['OK'],
-bitmap => 'info');
my $about_dialog = $mw->Dialog(
-title => 'About BT368i',
-text => 'BT368i was built by Travis Kent Beste. He can be reached at travis@tencorners.com',
-buttons => ['OK']);
my $menu = $help->cget('-menu');
$menu->entryconfigure('Version', -command => [$ver_dialog => 'Show']);
$menu->entryconfigure('About', -command => [$about_dialog => 'Show']);
$menubar; # return the menubar
}
#----------------------------------------#
# quit
#----------------------------------------#
sub quit {
exit(0);
}