use IO::Socket; use Tk; use File::Basename; $host = 'ysfs-hibuso.mydns.jp'; $port = 7910; $version = '02/05/07'; undef %APpos; $range = 1; $movex = 350; $movez = 350; undef %mapcfg; undef %linecfg; undef %dashcfg; undef @par_define; $file_path = "C:\\"; undef %tagmode_x; undef %tagmode_z; $connection = 0; $pi = 3.14159265; undef @mouse; $top = MainWindow->new(-title => 'YSATC Client'); $top->geometry( "+0+0" ); $m = $top->Menu( -type => 'menubar' ); $top->configure( -menu => $m ); $m1 = $m->cascade(-label => 'Power', -under => 0, -tearoff => 0); $m2 = $m->cascade(-label => 'RadarSetting', -under => 0, -tearoff => 0); $m3 = $m->cascade(-label => 'Other', -under => 0, -tearoff => 0); $m1->command(-label => 'Connect to ATCserver', -under => 0, -command => \&connectatc); $m1->separator; $m1->command(-label => 'Radar On', -under => 0, -command => \&pwron); $m1->command(-label => 'PAR', -under => 0, -command => \&par); $m1->separator; $m1->command(-label => 'Off(Disconnect and Exit)', -under => 0, -command => \&pwroff ); $m2->command(-label => 'range', -under => 0, -command => \&range); $m2->separator; $m2->command(-label => 'read .point', -under => 0, -command => \&read_map); $m2->command(-label => 'read .line', -under => 0, -command => [\&read_cfg, "line"]); $m2->command(-label => 'read .dash', -under => 0, -command => [\&read_cfg, "dash"]); $m2->separator; $m2->command(-label => 'initialize', -under => 0, -command => \&initdata); $m3->command(-label => 'Version', -command => \&version); $e0 = $top->Entry( -textvariable => \$host ); $e0->pack(-side => 'left' ,-anchor => 'nw'); $top->Button( -text => 'Connect', -command => \&connectatc )->pack(-anchor => 'nw'); $top->focus(); MainLoop(); sub pwron { if ($connection == 1) { if (! Exists( $sub_win ) ) { $sub_win = $top->Toplevel(-title => 'Radar'); if (@_) { my @window_xy = @_; $sub_win->geometry( "+$window_xy[0]+$window_xy[1]" ); } else { my $xw = $top->x + 20; my $yw = $top->y; $sub_win->geometry( "+$xw+$yw" ); } $canvas = $sub_win->Canvas( -width => 700, -height => 700,-bg => 'black' ); $canvas->pack(); $sub_win->focus; foreach my $key (keys %mapcfg) { my @pos = split (/:/,$mapcfg{$key}); $pos[0] = $pos[0] / $range + $movex; $pos[1] = $pos[1] / $range + $movez; $canvas->create( 'oval', $pos[0]-1, $pos[1]-1, $pos[0]+1, $pos[1]+1, -outline => 'darkgreen', -tags => "A$key"); $canvas->create( 'text', $pos[0]+1, $pos[1]-1, -fill => 'darkgreen', -text => $key, -font => 'Vrinda 8', -anchor => 'nw', -tags => "A$key"); $canvas->bind( "A$key", "" => [\&delAP,$key]); $canvas->bind( "A$key", "" => [\&setcenter,$key]); } foreach my $key (keys %linecfg) { my @pos = split (/:/,$linecfg{$key}); for (my $i=0; $i <= 1;$i++) { $pos[$i*2] = $pos[$i*2] / $range + $movex; $pos[$i*2 + 1] = $pos[$i*2 + 1] / $range + $movez; } $canvas->create( 'line', $pos[0], $pos[1], $pos[2], $pos[3], -fill => 'darkgreen', -tags => "Line$key"); $canvas->create( 'text', ($pos[0]+$pos[2])/2, ($pos[1]+$pos[3])/2, -fill => 'darkgreen', -text => $key, -font => 'Vrinda 8', -anchor => 'nw', -tags => "Line$key"); } foreach my $key (keys %dashcfg) { my @pos = split (/:/,$dashcfg{$key}); for (my $i=0; $i <= 1; $i++) { $pos[$i*2] = $pos[$i*2] / $range + $movex; $pos[$i*2 + 1] = $pos[$i*2 + 1] / $range + $movez; } $canvas->create( 'line', $pos[0], $pos[1], $pos[2], $pos[3], -fill => 'darkgreen', -dash => '.', -tags => "Dash$key"); $canvas->create( 'text', ($pos[0]+$pos[2])/2, ($pos[1]+$pos[3])/2, -fill => 'darkgreen', -text => $key, -font => 'Vrinda 8', -anchor => 'nw', -tags => "Dash$key"); } for (my $i = 1; $i <= 6; $i++) { $radius = $i * 50; $canvas->create('oval',350-$radius,350-$radius,350+$radius,350+$radius,-outline => 'darkgreen'); $canvas->create( 'text', 350, 350-$radius-4, -fill => 'darkgreen', -text => $radius * $range, -font => 'Vrinda 8',); } $canvas->create('oval',10,10,690,690,-outline => "brown"); for (my $i = 1; $i <= 36; $i++) { my $degree = $i * 10; my $rad = $degree / 360; my $x1 = (350-350) * cos($rad*2*$pi) - (10-350) * sin($rad*2*$pi); my $y1 = (350-350) * sin($rad*2*$pi) + (10-350) * cos($rad*2*$pi); my $x2 = (350-350) * cos($rad*2*$pi) - (20-350) * sin($rad*2*$pi); my $y2 = (350-350) * sin($rad*2*$pi) + (20-350) * cos($rad*2*$pi); my $x3 = (350-350) * cos($rad*2*$pi) - (30-350) * sin($rad*2*$pi); my $y3 = (350-350) * sin($rad*2*$pi) + (30-350) * cos($rad*2*$pi); $canvas->create('line',$x1+350,$y1+350,$x2+350,$y2+350,-fill => 'brown'); $canvas->create('text',$x3+350,$y3+350,-text => $degree,-fill => 'brown'); } for (my $i = 1; $i <= 360; $i++) { my $rad = $i / 360; my $x1 = (350-350) * cos($rad*2*$pi) - (10-350) * sin($rad*2*$pi); my $y1 = (350-350) * sin($rad*2*$pi) + (10-350) * cos($rad*2*$pi); my $x2 = (350-350) * cos($rad*2*$pi) - (15-350) * sin($rad*2*$pi); my $y2 = (350-350) * sin($rad*2*$pi) + (15-350) * cos($rad*2*$pi); $canvas->create('line',$x1+350,$y1+350,$x2+350,$y2+350,-fill => 'brown'); } $canvas->create( 'text', 1, 1, -fill => 'green', -text => "Connected:: $host:$port", -font => 'Vrinda 12', -anchor => 'nw'); $canvas->create( 'text', 1, 10, -fill => 'green', -text => "CenterPos:: x:${movex}px z:${movez}px", -font => 'Vrinda 12', -anchor => 'nw'); $canvas->create( 'text', 1, 19, -fill => 'green', -text => "Range:: $range", -font => 'Vrinda 12', -anchor => 'nw'); $sub_win->bind("",[\&calc_dme,Ev('x'), Ev('y')]); &refreshR; } } else { $top->messageBox( -type => 'ok', -icon => 'info', -title => "no connection", -message => "You should connect to ATC server firstly." ); } } sub refreshR{ my $range_2 = $range; if (! $range_2) { $range_2 = 1; } if ($range_2 eq "0\.") { $range_2 = 1; } foreach my $key ( keys %APpos ) { $canvas->delete("A$key"); } undef %APpos; &read_log; foreach my $key ( keys %APpos ) { my @xyz = split ( /:/, $APpos{$key}); if ( $xyz[1] <= 10 ) { next; } my $calc_x = $xyz[0] * 0.01; my $calc_z = (-$xyz[2]) * 0.01; $xyz[0] = $xyz[0] * 0.01 / $range_2 + $movex; $xyz[2] = (-$xyz[2]) * 0.01 / $range_2 + $movez; my $rad = $xyz[3] / 180; my $vectorX = - 5 / $range_2 * sin($rad * $pi); my $vectorY = 5 / $range_2 * cos($rad * $pi); $canvas->create( 'rectangle', $xyz[0]-2, $xyz[2]-2, $xyz[0]+2, $xyz[2]+2, -outline => 'green',-fill => 'green', -tags => "A$key"); $canvas->create( 'line', $xyz[0], $xyz[2], $xyz[0] + $vectorX, $xyz[2] - $vectorY, -fill => 'green', -tags => "A$key"); if (! exists( $tagmode_x{$key} ) ) { $tagmode_x{$key} = 30; $tagmode_z{$key} = 25; } $canvas->create( 'line', $xyz[0], $xyz[2], $xyz[0]+$tagmode_x{$key}, $xyz[2]+$tagmode_z{$key}, -fill => 'darkgreen', -tags => "A$key"); $canvas->create( 'text', $xyz[0]+$tagmode_x{$key}, $xyz[2]+$tagmode_z{$key}, -fill => 'orange', -text => $key, -font => 'Vrinda 10', -anchor => 'nw' , -tags => "A$key"); $xyz[1] = int ($xyz[1] * 0.1); $xyz[1] = sprintf( "%03d", $xyz[1] ); $canvas->create( 'text', $xyz[0]+$tagmode_x{$key}, $xyz[2]+$tagmode_z{$key}+8, -fill => 'orange', -text => "$xyz[1]", -font => 'Vrinda 10', -anchor => 'nw' , -tags => "A$key"); $xyz[4] = int ($xyz[4]); $xyz[4] = sprintf( "%04d", $xyz[4] ); $canvas->create( 'text', $xyz[0]+$tagmode_x{$key}+26, $xyz[2]+$tagmode_z{$key}+8, -fill => 'orange', -text => "$xyz[4]knt", -font => 'Vrinda 10', -anchor => 'nw' , -tags => "A$key"); my $truehdg = 360 - $xyz[3]; $canvas->create( 'text', $xyz[0]+$tagmode_x{$key}, $xyz[2]+$tagmode_z{$key}+16, -fill => 'orange', -text => "HDG:$truehdg", -font => 'Vrinda 10', -anchor => 'nw' , -tags => "A$key"); $canvas->bind( "A$key", "" => [\&delAP,$key]); $canvas->bind( "A$key", "" => [\&changetag,$key]); } $canvas->after( 2000, \&refreshR ); } sub calc_dme { if ($canvas_dme) { $canvas -> delete ($canvas_dme); } my (undef,$m_x, $m_z) = @_; if (! @mouse) { $mouse[0] = $m_x; $mouse[1] = $m_z; } else { my $calc_x1 = ($mouse[0] - $movex) * $range ; my $calc_z1 = ($mouse[1] - $movez) * $range ; my $calc_x2 = ($m_x - $movex) * $range ; my $calc_z2 = ($m_z - $movez) * $range ; my $dme = sqrt ( ($calc_x2-$calc_x1)**2 + ($calc_z2-$calc_z1)**2 ); $dme = int ($dme*100)/100; my $degree = int ( atan2($calc_z2-$calc_z1,$calc_x2-$calc_x1) / $pi *180 )+90; $canvas_dme = $canvas->create( 'text', 2, 40, -fill => 'green', -text => "${dme}mile : ${degree}deg", -font => 'Vrinda 12', -anchor => 'nw'); undef @mouse; } } sub read_log { print $socket "refresh\n"; $socket->flush(); my $ibuf = <$socket>; my @ebuf = split (/\\/,$ibuf); pop @ebuf; foreach my $ebuf ( @ebuf ) { my @dbuf = split (/:/,$ebuf); $APpos{$dbuf[0]} = "$dbuf[1]:$dbuf[2]:$dbuf[3]:$dbuf[4]:$dbuf[5]"; } } sub changetag { my $key = $_[1]; if ( $tagmode_x{$key} == 30 and $tagmode_z{$key} == 25) { $tagmode_x{$key} = 30; $tagmode_z{$key} = -35; } elsif($tagmode_x{$key} == 30 and $tagmode_z{$key} == -35) { $tagmode_x{$key} = -60; $tagmode_z{$key} = -35; } elsif($tagmode_x{$key} == -60 and $tagmode_z{$key} == -35) { $tagmode_x{$key} = -60; $tagmode_z{$key} = 25; } else { $tagmode_x{$key} = 30; $tagmode_z{$key} = 25; } } sub version { $top->messageBox( -type => 'ok', -icon => 'info', -title => 'Version', -message => "YSATC Client last update:$version" ); } sub delAP { my $killtarget = $_[1]; $canvas->delete("A$killtarget"); delete $APpos{$killtarget}; } sub pwroff{ if ($socket) { $socket->close(); } exit(); } sub range { $sub_win_range = $top->Toplevel(); my $x = $top->x + 10; my $y = $top->y + 10; my $entry; my $mapx = (350 - $movex) * $range; my $mapz = (350 - $movez) * $range; $sub_win_range->geometry( "+$x+$y" ); $sub_win_range->title('Input range.'); $entry = $sub_win_range->Entry( -textvariable => \$range ); $entry->bind( "", [\&sync,$mapx,$mapz,$range] ); $entry->focus; $entry->pack(); sub sync{ my (undef,$mapx,$mapz) = @_; if (! $range) { $range = 1; } $sub_win_range -> destroy; $movex = 350 - $mapx/$range; $movez = 350 - $mapz/$range; &restart_window; sub restart_window { if ( Exists( $sub_win ) ) { my $previous_x = $sub_win->x; my $previous_y = $sub_win->y; $sub_win->destroy; sleep 0.1; &pwron($previous_x,$previous_y); } } } } sub setcenter { my $key = $_[1]; my ($mapx,$mapz) = split (/:/,$mapcfg{$key}); $movex = 350 - $mapx/$range; $movez = 350 - $mapz/$range; my $previous_x = $sub_win->x; my $previous_y = $sub_win->y; $sub_win->destroy; sleep 0.1; &pwron($previous_x,$previous_y); } sub read_map { my $filename = $top->getOpenFile( -initialdir => $file_path,-filetypes => [['Point definition',['.point']],['All Files','*',],]); if ($filename) { $file_path = dirname( $filename ) . "\\"; my $buf; open(FH,"<$filename") or &error('mapdata'); while() { if (/^\#/) { next; } my @name_pos; @name_pos = split (/\\/,$_); my @xz = split (/:/,$name_pos[1]); $xz[0] = int ( $xz[0] * 0.00054 ); $xz[1] = int ( $xz[1] * 0.00054 ); $mapcfg{$name_pos[0]} = "$xz[0]:$xz[1]"; } close(FH); } } sub read_cfg { my $filekind = $_[0]; my $filename = $top->getOpenFile( -initialdir => $file_path,-filetypes => [["$filekind definition",[".$filekind"]],['All Files','*',],]); if ($filename) { $file_path = dirname( $filename ) . "\\"; my $buf; open(FH,"<$filename") or &error("$filekind"); while() { my @name_pos; @name_pos = split (/\\/,$_); my @point = split (/:/,$name_pos[1]); for (my $i=0; $i <=3; $i++) { $point[$i] = $point[$i] * 0.00054; } if ($filekind eq "line") { $linecfg{$name_pos[0]} = "$point[0]:$point[1]:$point[2]:$point[3]"; } elsif($filekind eq "dash") { $dashcfg{$name_pos[0]} = "$point[0]:$point[1]:$point[2]:$point[3]"; } } close(FH); } } sub initdata { if ( Exists( $sub_win ) ) { $top->messageBox( -type => 'ok', -icon => 'info', -title => "information", -message => 'Close radar window.Then select "initialize".'); } else { $range = 1; $movex = 350; $movez = 350; undef %mapcfg; undef %linecfg; undef %dashcfg; undef @par_define; } } sub connectatc{ if ($connection == 0) { $socket = IO::Socket::INET->new(PeerAddr => $host,PeerPort => $port,Proto => 'tcp',); if ( ! $socket ) { &error('connection'); } else { $top->messageBox( -type => 'ok', -icon => 'info', -title => "Connection Established", -message => "Connected to $host:$port" ); $connection = 1; } } else { $top->messageBox( -type => 'ok', -icon => 'warning', -title => "warning", -message => "A connection has been already established.Start radar." ); } } sub par{ if ( ! Exists ($par_win) ) { if ( ! Exists( $sub_win ) ) { my $filename = $top->getOpenFile( -initialdir => $file_path,-filetypes => [['PAR definition',['.par']],['All Files','*',],]); if ($filename) { $file_path = dirname( $filename ) . "\\"; open (FH,"<$filename") or &error("par"); my $buffer = ; close (FH); my @name_data = split (/\\/,$buffer); $par_win = $top->Toplevel(-title => $name_data[0]); $par_canvas = $par_win->Canvas( -width => 1000, -height => 700,-bg => 'black' )->pack(); $par_canvas->create( 'line', 0, 350, 1000, -50, -fill => 'darkgreen'); $par_canvas->create( 'line', 0, 350, 1000, 50, -fill => 'darkgreen'); $par_canvas->create( 'line', 0, 350, 1000, 150, -fill => 'darkgreen'); $par_canvas->create( 'line', 0, 500, 1000, 500, -fill => 'darkgreen'); $par_canvas->create( 'line', 0, 500, 1000, 300, -fill => 'darkgreen'); $par_canvas->create( 'line', 0, 500, 1000, 700, -fill => 'darkgreen'); @par_define = split (/:/,$name_data[1]); $par_canvas->create( 'text', 5, 5, -fill => 'orange', -text => "Runway heading:$par_define[0]", -font => 'Vrinda 12', -anchor => 'nw'); &refresh_par(); } } else { $top->messageBox( -type => 'ok', -icon => 'error', -title => "Could't turn on PAR", -message => 'PAR is available only when Radar is NOT showed up.'); } } } sub refresh_par { my ($par_heading, $par_x , $par_z, $par_start_dme, $par_start_height ,$z_range) = @par_define; my $rad = ($par_heading - 270)/180; undef %APpos; &read_log; foreach my $key ( keys %APpos ) { my @xyz = split ( /:/, $APpos{$key}); $xyz[0] -= int ($par_x*0.054) ; $xyz[2] += int ($par_z*0.054) ; my $trans_x = cos($rad * $pi) * $xyz[0] - sin($rad * $pi) * $xyz[2]; $trans_x = int ($trans_x * 10000); $trans_x /= 10000; my $trans_z = sin($rad * $pi) * $xyz[0] + cos($rad * $pi) * $xyz[2]; $trans_z = int ($trans_z * 10000); $trans_z /= -10000; if ($trans_x >=0 and $trans_x <= $par_start_dme*100 and $trans_z <= 100 and $trans_z >= -100) { $par_canvas->delete("par$key"); my $direction = ""; my $direction_z = int ($trans_z/0.054); if ($direction_z == 0) { $direction = "On course"; } elsif ($direction_z > 30) { $direction = "LEFT of course : $direction_z m"; } elsif ($direction_z < 30 and $direction_z > 0) { $direction = "Slightly LEFT of course : $direction_z m"; } elsif ($direction_z < 0 and $direction_z > -30) { $direction_z = -$direction_z; $direction = "Slightly RIGHT of course : $direction_z m"; } else { $direction_z = -$direction_z; $direction = "RIGHT of course : $direction_z m"; } $trans_z *= $z_range; $par_canvas->create( 'rectangle', $trans_x-1, $trans_z-1+500, $trans_x+1, $trans_z+1+500, -outline => 'green',-fill => 'green', -tags => "par$key"); $par_canvas->create( 'text', $trans_x, $trans_z + 500 + 20, -fill => 'orange', -text => $direction, -font => 'Vrinda 12', -anchor => 'nw' , -tags => "par$key"); $xyz[1] *= 10; my $trans_y = $xyz[1] * (300 / $par_start_height); $par_canvas->create( 'rectangle', $trans_x-1, 350-$trans_y-1, $trans_x+1, 350-$trans_y+1, -outline => 'green',-fill => 'green', -tags => "par$key"); $par_canvas->create( 'text', $trans_x, 350 - $trans_y -1 + 10, -fill => 'orange', -text => "$xyz[1]ft", -font => 'Vrinda 12', -anchor => 'nw' , -tags => "par$key"); $par_canvas->create( 'text', $trans_x, $trans_z + 500 + 32, -fill => 'orange', -text => "$xyz[4]knt", -font => 'Vrinda 12', -anchor => 'nw' , -tags => "par$key"); } } $par_canvas->after( 300, \&refresh_par ); } sub error { my $error_type = $_[0]; if($error_type eq "connection") { $top->messageBox( -type => 'ok', -icon => 'error', -title => "Couldn't Connect", -message => 'connection error. press ok to exit.'); } elsif($error_type eq "pointdata") { $top->messageBox( -type => 'ok', -icon => 'error', -title => "Couldn't open point definition file", -message => 'File open error. press ok to exit.'); } elsif($error_type eq "line") { $top->messageBox( -type => 'ok', -icon => 'error', -title => "Couldn't open line definition file", -message => 'File open error. press ok to exit.'); } elsif($error_type eq "dash") { $top->messageBox( -type => 'ok', -icon => 'error', -title => "Couldn't open dash definition file", -message => 'File open error. press ok to exit.'); } elsif($error_type eq "par") { $top->messageBox( -type => 'ok', -icon => 'error', -title => "Couldn't open par definition file", -message => 'File open error. press ok to exit.'); } exit(); }