diff --git a/sw/logalizer/plot.pl b/sw/logalizer/plot.pl index 104c918890..9b62949353 100755 --- a/sw/logalizer/plot.pl +++ b/sw/logalizer/plot.pl @@ -8,20 +8,24 @@ use Tk::LabEntry; use Tk::FileSelect; use Tk::DialogBox; use XML::Parser; +use XML::DOM; use Expect; +use Data::Dumper; +use Getopt::Long; -my $paparazzi_home; +my $paparazzi_lib; BEGIN { - $paparazzi_home = "/home/drouin/work/savannah/paparazzi2"; - $paparazzi_home = $ENV{PAPARAZZI_HOME} if defined $ENV{PAPARAZZI_HOME}; + $paparazzi_lib = (defined $ENV{PAPARAZZI_SRC}) ? + $ENV{PAPARAZZI_SRC}."/sw/lib/perl" : "/usr/lib/paparazzi/"; } -use lib ($paparazzi_home.'/sw/lib/perl'); +use lib ($paparazzi_lib); #use ChildrenSpawner; @ISA = qw(Subject); use strict; use warnings; use diagnostics; +use Paparazzi::Environment; use Subject; @@ -33,21 +37,29 @@ my $log_filename; my $time_range="[]"; my $tr_entry; +my $pi = 3.14159; + sub populate { my ($self, $args) = @_; - $self->SUPER::populate($args); + my $paparazzi_src = Paparazzi::Environment::paparazzi_src(); + my $paparazzi_home = Paparazzi::Environment::paparazzi_home(); + Paparazzi::Environment::check_paparazzi_home(); +# $args->{-variables} = {paparazzi_home => $paparazzi_home}; #A quoi ça sert ? +# $args->{-bin_base_dir} = $paparazzi_src; #A quoi ça sert ? +# $self->SUPER::populate($args); #A quoi ça sert ? $self->configspec(-log => [S_NOINIT, S_PASSIVE, S_RDWR, S_OVRWRT, S_NOPRPG, undef]); $self->configspec(-log_start_date => [S_NOINIT, S_PASSIVE, S_RDWR, S_OVRWRT, S_NOPRPG, undef]); $self->configspec(-protocol => [S_NOINIT, S_PASSIVE, S_RDWR, S_OVRWRT, S_NOPRPG, undef]); $self->configspec(-listbox => [S_NOINIT, S_PASSIVE, S_RDWR, S_OVRWRT, S_NOPRPG, undef]); $self->configspec(-gnuplots => [S_NOINIT, S_PASSIVE, S_RDWR, S_OVRWRT, S_NOPRPG, undef]); + $self->configspec(-variables => [S_SUPER, S_SUPER, S_SUPER, S_SUPER, S_SUPER, {}]); # print("in Ploter::populate\n"); } sub completeinit { my $self = shift; $self->SUPER::completeinit; - $self->configure('-protocol' => undef); + $self->configure('-protocol' => undef); #A retirer je suppose $self->build_gui(); # print("in Ploter::completeinit\n"); } @@ -56,79 +68,101 @@ sub completeinit { # XML # sub parse_messages_xml() { - my $filename = $paparazzi_home."/conf/messages.xml"; - my $p = new XML::Parser (Style => 'Tree') ; - my @msg_xml_tree = $p->parsefile ($filename) ; + my $self = shift; + my $filename = Paparazzi::Environment::paparazzi_src()."/conf/messages.xml"; + my $parser = XML::DOM::Parser->new(); + my $doc = $parser->parsefile($filename); + $self->{messages} = $doc; print STDOUT "successfully parsed $filename\n"; - return \@msg_xml_tree; + return $doc; } # # Menus # sub build_menu_msg() { - my ($self, $xml_top_node, $menubar) = @_; - my $plot_menu = $menubar->cascade(-label => "~Data"); - while ( defined ( my $element = shift @{ $xml_top_node } )) { - my $child = shift @{ $xml_top_node }; - if ( ref $child ) { - my %attr = %{ shift @{ $child } }; - if ($element eq "protocol") { - print "found protocol\n"; - $self->build_msg_menu($child, $plot_menu); - } - } - } + my ($self, $doc, $menubar) = @_; + my $data_menu = $menubar->cascade(-label => "~Data"); + $self->{data_menu} = $data_menu; } -sub build_msg_menu() { - my ($self, $msg_node, $data_menu) = @_; -# sort @{$msg_node}; - while ( defined ( my $element = shift @{ $msg_node } )) { - my $child = shift @{ $msg_node }; - if ( ref $child ) { - my $attr = shift @{ $child }; - if ($element eq "message") { - my $id = $attr->{id}; -# print "found message $id\n"; - my $msg_menu = $data_menu->cascade(-label => $id); - $self->build_field_commands($child, $id, $msg_menu); - } - } - } +sub update_menu_msg() { + my ($self, $ac_name, $ac_id) = @_; + my $data_menu = $self->{data_menu}; + my $doc = $self->{messages}; + my $menubar = $self->{menubar}; + my $ac_menu = $data_menu->cascade(-label => "$ac_name ($ac_id)"); + $self->parse_protocol($doc, $ac_menu, $ac_id); +} + +sub parse_protocol() { + my ($self, $doc, $ac_menu, $ac_id) = @_; + my $protocol = $doc->getElementsByTagName('protocol')->[0]; + print "found protocol \n"; + $self->parse_class($protocol, $ac_menu, $ac_id); +} + +sub parse_class() { + my ($self, $protocol, $ac_menu, $ac_id) = @_; + my $class_name; + foreach my $class ($protocol->getElementsByTagName('class')) { + $class_name = $class->getAttribute('name'); + if ($class_name eq "telemetry_ap") { + print "found telemetry_ap class \n"; + $self->parse_msg($class, $ac_menu, $ac_id); + } + } +} + +sub parse_msg() { + my ($self, $class, $ac_menu, $ac_id) = @_; + my $msg_name; + foreach my $message ($class->getElementsByTagName('message')) { + $msg_name = $message->getAttribute('name'); + # print "found message $msg_name \n"; + my $msg_menu = $ac_menu->cascade(-label => $msg_name); + $self->build_field_commands($message, $msg_name, $msg_menu, $ac_id); + } } sub build_field_commands() { - my ($self, $fields_node, $msg_name, $msg_menu) = @_; + my ($self, $message, $msg_name, $msg_menu, $ac_id) = @_; my $no_field = 0; - while ( defined ( my $element = shift @{ $fields_node } )) { - my $child = shift @{ $fields_node }; - if ( ref $child ) { - my $attr = shift @{ $child } ; - if ($element eq "field") { - my $field_name = $attr->{id}; -# print "found field $field_name\n"; - my $no_field1 = $no_field; - my $file_menu = $msg_menu->command(-label => $field_name, - -command => sub { on_plot($self, $msg_name, $field_name, $no_field1 )}); - $no_field++; - } - } - } + foreach my $field ($message->getElementsByTagName('field')) { + my $field_name = $field->getAttribute('name'); + my $field_unit = $field->getAttribute('unit'); + # print "found field $field_name \n"; + my $no_field1 = $no_field; + my $file_menu = $msg_menu->command(-label => $field_name, + -command => sub {on_plot($self, $msg_name, $field_name, $no_field1, $ac_id, $field_unit)}); + $no_field++; + } +} + +sub build_log_menu() { + my ($self, $mainwindow, $menubar) = @_; + my $log_menu = $menubar->cascade(-label => "~Log",); + my $new_log_menu = $log_menu->command(-label => "~Open new log", + -command => sub { on_new_log($self, $mainwindow)}); +# my $add_log_menu = $log_menu->command(-label => "~Add new log", +# -command => sub { on_add_log($self, $mainwindow)}); } sub build_gui() { my ($self) = @_; - my $width = 450; + my $width = 700; my $height = 300; my $mw = MainWindow->new; $mw->geometry(sprintf("%dx%d", $width, $height)); $mw->title("Paparazzi (gnu)plotter"); my $mb = $mw->Menu(); - my $log_menu = $mb->command(-label => "~Log", - -command => sub { on_load($self, $mw)}); - $self->build_menu_msg(@{$self->parse_messages_xml()}, $mb); + $self->{menubar} = $mb; + $self->build_log_menu($mw, $mb); +# my $log_menu = $mb->command(-label => "~Log", +# -command => sub { on_load($self, $mw)}); + $self->build_menu_msg($self->parse_messages_xml(), $mb); +# $self->build_compiled_msg_menu($mb); $mw->configure(-menu => $mb); my $padx = 10; @@ -143,9 +177,9 @@ sub build_gui() { $tr_entry->grid (-column=>1, -row=>3, -ipadx=>$padx); $tr_entry->insert(0, $time_range); - my $button = $mw->Button (-text => "update", - -command => sub { update_time_range($self)}, - ); + my $button = $mw->Button (-text => "update", + -command=> sub { update_time_range($self)}, + ); $button->grid (-column=>2, -row=>3, -ipadx=>$padx); my $listbox = $mw->Listbox(); @@ -166,29 +200,59 @@ sub add_label() { sub on_list_clicked() { my ($self, $listbox, $mw) = @_; my $key = $listbox->get('active'); - my $dialog = $mw->DialogBox( -title => "Plot command", - -buttons => [ "Replot", "Cancel" ], - ); - $dialog->add("Label", -text => "Plot command")->pack(); my $gnuplots = $self->get('-gnuplots'); my $gnuplot = $gnuplots->{$key}; my $plot_cmd = $gnuplot->{'plot_cmd'}; - print "plot_cmd $plot_cmd\n"; + my $dialog; + if ($gnuplot->{'normal'}) { + $dialog = $mw->DialogBox( -title => "Plot command", + -buttons => [ "Replot", "Print", "Remove", "Add points", "Cancel" ], + ); } + else { + $dialog = $mw->DialogBox( -title => "Plot command", + -buttons => [ "Replot", "Remove", "Cancel" ], + ); } + + $dialog->add("Label", -text => "Plot command")->pack(); + # print "plot_cmd $plot_cmd\n"; my $entry = $dialog->add("Entry", -width => 150)->pack(); $entry->insert(0,$plot_cmd); print "selected key $key\n"; my $answer = $dialog->Show(); print "selected $answer\n"; + my ($new_plot_cmd, $exp); + my $timeout = 1; + if ($answer eq "Add points") { + $key =~ /([^\.]+).([^\.]+).([^\.]+).([^\.]+)/ or return; + my ($msg_name, $ac_id, $field_name, $field_pos) = ($1, $2, $3, $4); + my $rpos = $field_pos + 3; + + my $last_plot_cmd = $entry->get(); + my $plot_points_cmd = "\"/tmp/plot_data.$msg_name.$ac_id\" using 1:$rpos w p not"; + $new_plot_cmd = $last_plot_cmd.", ".$plot_points_cmd; + $entry->configure(-text => $new_plot_cmd); + + print("add points to $key \n"); + $gnuplot->{'plot_cmd'} = $new_plot_cmd; + $exp = $gnuplot->{'exp'}; + $exp->send($new_plot_cmd."\n"); + $exp->expect($timeout); + } if ($answer eq "Replot") { - my $new_plot_cmd = $entry->get(); + $new_plot_cmd = $entry->get(); print("new_plot_cmd $new_plot_cmd \n"); $gnuplot->{'plot_cmd'} = $new_plot_cmd; - my $exp = $gnuplot->{'exp'}; - print "exp $exp\n"; + $exp = $gnuplot->{'exp'}; +# print "exp $exp\n"; $exp->send($new_plot_cmd."\n"); - my $timeout = 1; $exp->expect($timeout); } + if ($answer eq "Print") { + $self->print_plot($key, $entry); + } + if ($answer eq "Remove") { + $self->remove_plot($key); + } } sub update_time_range() { @@ -196,23 +260,26 @@ sub update_time_range() { my $gnuplots = $self->get('-gnuplots'); $time_range = $tr_entry->get(); foreach my $key (keys %{$gnuplots}) { - print "update_range_for_key $key ($gnuplots->{$key})\n"; my $gnuplot = $gnuplots->{$key}; - my $plot_cmd = $gnuplot->{'plot_cmd'}; my $exp = $gnuplot->{'exp'}; - print "plot_cmd $time_range [$plot_cmd]\n"; - $plot_cmd =~ s/\[.*\]/$time_range/; - print "new_plot_cmd $plot_cmd\n\n"; - $gnuplot->{'plot_cmd'} = $plot_cmd; - $exp->send($plot_cmd."\n"); - my $timeout = 1; - $exp->expect($timeout); + if (defined $exp) { + print "update_range_for_key $key ($gnuplots->{$key})\n"; + my $plot_cmd = $gnuplot->{'plot_cmd'}; + print "plot_cmd $time_range [$plot_cmd]\n"; + $plot_cmd =~ s/\[.*\]/$time_range/; + print "new_plot_cmd $plot_cmd\n\n"; + $gnuplot->{'plot_cmd'} = $plot_cmd; + $exp->send($plot_cmd."\n"); + my $timeout = 1; + $exp->expect($timeout); + } } } -sub on_load() { +sub open_log() { my ($self, $mw) = @_; - my $fs = $mw->FileSelect(-directory => $paparazzi_home."/var"); + my $fs = $mw->FileSelect(-directory => Paparazzi::Environment::paparazzi_home()."/var/logs"); + $fs->geometry("600x350"); my $file_name = $fs->Show(); if (defined $file_name) { print "file_name: $file_name\n"; @@ -221,15 +288,21 @@ sub on_load() { } sub on_plot() { - my ($self, $msg_name, $field_name, $field_pos) = @_; - # print "in on_plot msg_name $msg_name field_name $field_name field_pos $field_pos\n"; + my ($self, $msg_name, $field_name, $field_pos, $ac_id, $field_unit) = @_; + print "in on_plot msg_name $msg_name, field_name $field_name, field_pos $field_pos, ac_id $ac_id, field_unit $field_unit \n"; - my $key = $msg_name.".".$field_name.".".$field_pos; - $self->gen_data_file($msg_name); - $self->add_plot($key); + my $key = $msg_name.".".$ac_id.".".$field_name.".".$field_pos; + $self->gen_data_file($msg_name, $ac_id); + $self->add_plot($key, $field_unit); } - +sub on_new_log() { + my ($self, $mainwindow) = @_; + my $log; + push (@{$log}, {date=>"", ac_id=>"", type=>"", args=>""}); + $self->configure('-log' => $log); + $self->open_log($mainwindow); +} sub load_log() { my ($self, $filename) = @_; @@ -238,12 +311,15 @@ sub load_log() { open(INFILE, $filename) or die print STDERR "Cant open $filename: $!"; my $log = $self->get('-log'); $log_date = undef; + my $ac_list; my $line; while ($line = ) { # assigns each line in turn to $_ - if ($line =~ /(^\d+\.\d+) (\w+) (.+)/) { + if ($line =~ /(^\d+\.\d+) (\d+) (\w+) (.+)/) { $log_date = $1 unless defined $log_date; my $rel_date = $1 - $log_date; - push (@{$log}, { date=>$rel_date, type=>$2, args=>$3}); + push (@{$log}, {date=>$rel_date, ac_id=>$2, type=>$3, args=>$4}); + $self->{ac_list}->{name}->{$2} = 1; +# push (@{$self->{ac_list}->{$2}}, {date=>$rel_date, type=>$3, args=>$4}); $nb_lines++; } } @@ -253,16 +329,37 @@ sub load_log() { $log_duration = "aaa"; - print STDERR "read $nb_lines lines\n" + print STDERR "read $nb_lines lines\n"; + $self->parse_conf(); } - +sub parse_conf() { + my ($self) = @_; + my $filename = Paparazzi::Environment::paparazzi_src()."/conf/conf.xml"; + my $parser = XML::DOM::Parser->new(); + my $doc = $parser->parsefile($filename); + my ($aircraft_name, $aircraft_id); + my $aircraft_no = 0; + foreach my $aircraft ($doc->getElementsByTagName('aircraft')) { + $aircraft_name = $aircraft->getAttribute('name'); + $aircraft_id = $aircraft->getAttribute('ac_id'); + # print "search aircraft $aircraft_name with id $aircraft_ac_id... \n"; + if (defined $self->{ac_list}->{name}->{$aircraft_id}) { + print "found aircraft $aircraft_name \n"; + $self->{ac_list}->{name}->{$aircraft_id} = $aircraft_name; + $aircraft_no++; + $self->update_menu_msg($aircraft_name, $aircraft_id); + } + } + print "=> found $aircraft_no aircrafts \n"; +} sub add_plot() { - my ($self, $data_key) = @_; + my ($self, $data_key, $field_unit) = @_; - $data_key =~ /([^\.]+).([^\.]+).([^\.]+)/ or return; - my ($msg_name, $field_name, $field_pos) = ($1, $2, $3); + $data_key =~ /([^\.]+).([^\.]+).([^\.]+).([^\.]+)/ or return; + my ($msg_name, $ac_id, $field_name, $field_pos) = ($1, $2, $3, $4); + my $ac_name = $self->{ac_list}->{name}->{$ac_id}; my $gnuplots = $self->get('-gnuplots'); @@ -271,52 +368,93 @@ sub add_plot() { my $rpos = $field_pos + 3; my $nb_plots = scalar(keys(%{$gnuplots})); - my $h = $nb_plots * 240; - my $plot_cmd = "plot $time_range \"/tmp/plot_data.$msg_name\" using 1:$rpos t \"$field_name\" w l"; - my $pid = $exp->spawn("/usr/bin/gnuplot", ("-geometry","1600x200+0+$h" )); - my $gnuplot = { 'plot_cmd' => $plot_cmd, - 'exp' => $exp - }; - $gnuplots->{$data_key} = $gnuplot; - $self->configure('-gnuplots' => $gnuplots); + my $h = $nb_plots * 260; + my $timeout = 1; + + #Do not open again already open keys. Just show it. + if (defined $gnuplots->{$data_key}) { + print ("$data_key is already open \n"); + $exp = $gnuplots->{$data_key}->{'exp'}; + $exp->send($gnuplots->{$data_key}->{'plot_cmd'}."\n"); + $exp->expect($timeout); + } + #Key is not in current list. Show it. + else { + my $plot_cmd = "plot $time_range \"/tmp/plot_data.$msg_name.$ac_id\" using 1:$rpos t \"$ac_name : $field_name ($field_unit)\" w l"; + my $pid = $exp->spawn("/usr/bin/gnuplot", ("-geometry", "1350x200+0+$h", "-title", "$msg_name.$field_name")); + $pid->log_stdout(0); + my $gnuplot = { 'plot_cmd' => $plot_cmd, + 'exp' => $exp, + 'normal' => 1 + }; + $gnuplots->{$data_key} = $gnuplot; + $self->configure('-gnuplots' => $gnuplots); + + $exp->send($plot_cmd."\n"); + $exp->expect($timeout); + + my $listbox = $self->get('-listbox'); + $listbox->insert('end', "$data_key"); + } +} - $exp->send($plot_cmd."\n"); +sub print_plot() { + my ($self, $data_key, $entry) = @_; + + $data_key =~ /([^\.]+).([^\.]+).([^\.]+).([^\.]+)/ or return; + my ($msg_name, $ac_id, $field_name, $field_pos) = ($1, $2, $3, $4); + my $ac_name = $self->{ac_list}->{name}->{$ac_id}; + + my $set_terminal_cmd = "set terminal jpeg giant size 1350,400"; + my $set_output_cmd = "set output \"$log_filename\_print/$ac_name.$msg_name.$field_name.jpg\""; + my $plot_cmd = $entry->get(); + my $print_cmd = "$set_terminal_cmd; $set_output_cmd; $plot_cmd"; + + mkdir $log_filename."_print/"; + + my $gnuplots = $self->get('-gnuplots'); + my $exp = new Expect(); + $exp->raw_pty(1); + + my $pid = $exp->spawn("/usr/bin/gnuplot", ("-geometry", "1x1+0+0")) or die "Don't find gnuplot"; + $pid->log_stdout(0); + print("Printing $plot_cmd \n"); + $exp->send($print_cmd."\n"); my $timeout = 1; $exp->expect($timeout); - - my $listbox = $self->get('-listbox'); - $listbox->insert('end', "$data_key"); - + $exp->hard_close(); } sub remove_plot() { - my ($self, $data_key) = @_; - my $gnuplots = $self->get('-gnuplots'); - my $gnuplot = $gnuplots->{$data_key}; - my $exp = $gnuplot->{'exp'}; - $exp->soft_close(); - $gnuplots->{$data_key} = undef; - $self->configure('-gnuplots' => $gnuplots); - my $listbox = $self->get('-listbox'); -# my $idx = $listbox->index($key); -# $listbox->delete($idx); + my ($self, $data_key) = @_; + my $gnuplots = $self->get('-gnuplots'); + my $gnuplot = $gnuplots->{$data_key}; + my $exp = $gnuplot->{'exp'}; +# $exp->soft_close(); + $exp->hard_close(); + $gnuplots->{$data_key} = undef; + $self->configure('-gnuplots' => $gnuplots); + my $listbox = $self->get('-listbox'); + print "remove $data_key\n"; + my $idx = $listbox->index('active'); + $listbox->delete($idx); } sub gen_data_file() { - my ($self, $msg_name) = @_; + my ($self, $msg_name, $ac_id) = @_; my $nb_msgs = 0; - my $tmp_file = "/tmp/plot_data.$msg_name"; + my $tmp_file = "/tmp/plot_data.$msg_name.$ac_id"; open(OUTFILE, ">".$tmp_file) or die "Can t open $tmp_file: $!"; foreach (@{$self->get('-log')}) { # print "$_->{type} eq $msg_name \n"; - if ($_->{type} eq $msg_name) { + if (($_->{type} eq $msg_name && $_->{ac_id} == $ac_id) || $_->{type} eq " ") { print OUTFILE "$_->{date} $_->{type} $_->{args}\n"; $nb_msgs++; } } close OUTFILE; - print STDERR "$nb_msgs $msg_name msgs\n"; + print STDERR "Number of messages $nb_msgs for $msg_name \n"; } sub catchSigTerm() { @@ -329,12 +467,14 @@ sub catchSigTerm() { } } +sub tan { sin($_[0]) / cos($_[0]) } + $SIG{TERM} = \&catchSigTerm ; #$SIG{KILL} = \&catchSigTerm ; my $ploter = Ploter->new(); -#$ploter->load_log("../../var/log_04_07_01__13_06_33"); +#$ploter->load_log("../../var/log_05_08_04__12_50_09"); Tk::MainLoop(); $ploter->catchSigTerm(); printf STDOUT "ploter over\n";