# Graph exporter Perl script for Netstumbler # Version 1.0 # Author: Shane Connelly (eskimoboy [at] gmail [dot] com) # Release Date: June 16 2005 # Required Perl Modules: GD::Graph::bars // GD::Graph::mixed # License: GPL # configuration: my $width = 800; #in pixels my $height = 300; #in pixels my $directory = "C:\\Documents and Settings\\shane\\Desktop\\wireless"; #directory to save files. no trailing slash # end configuration use strict; use GD::Graph::bars; use GD::Graph::mixed; my %macs; my %strengths; my %noises; my $i; my $lognum; sub OnEnableScan { $i = 0; $lognum = 1; } sub OnScanComplete { my ($newnets, $oldnets, $lostnets, $bestsnr) = @_; $i++; if ($i > ($width - 60)) { &OnDisableScan(); $lognum++; $i = 0; foreach my $k (keys %macs) { delete $macs{$k}; delete $strengths{$k}; delete $noises{$k}; } } } sub OnScanResult { my ( $ssid, $mac, $flags, $signal, $noise, $lastseen) = @_; if ($macs{$mac} eq '') { $macs{$mac} = $ssid . ' ' . $flags; $strengths{$mac} = $i . ':' . $signal; $noises{$mac} = $i . ':' . $noise; } else { $strengths{$mac} = $strengths{$mac} . ';' . $i . ':' . $signal; $noises{$mac} = $noises{$mac} . ';' . $i . ':' . $noise; } } sub OnDisableScan { my $k; my %strongest; my %averages; my $mytime = localtime(time); open(FIL,">$directory\\wireless.$lognum.html"); print FIL <Wireless Graphs

Wireless SNRs


Graphs generated $mytime

EOHTML foreach $k (keys %macs) { my @data; my @nums; my @averaged; my $numover; my $strongest = 0; my $total = 0; #this accounts for large amounts of data. it simply drops the first readings that dont fit. i should probably redo this if ($i > ($width - 30)) { $numover = $i - ($width - 30); $i = ($width - 30); } #initialize data. this is a little CPU intensive, but i dont know a better way for (my $j = 0; $j < $i; $j++) { $data[$j] = 0; $nums[$j] = $j; } #first, set the data as the strengths foreach my $p (split ('\;',$strengths{$k})) { my ($j,$s) = split('\:',$p); if ($j > $numover) { $data[$j - $numover] = $s; } } #subtract the noises foreach my $p (split ('\;',$noises{$k})) { my ($j,$s) = split('\:',$p); if ($j > $numover) { $data[$j - $numover] = $data[$j - $numover] - $s; } } #and you have SNR #the following for loop generates a 5 point averaging filter for (my $j=0;$j<$i;$j++) { my $tot = 0; $total+=$data[$j]; for (my $l=$j-2;$l<$j+3;$l++) { if ($l>=0 && $l<$i) { $tot+=$data[$l]; if ($data[$l] > $strongest{$k}) { $strongest{$k} = $data[$l]; } } } $averaged[$j] = $tot / 5; } #and thats that $averages{$k} = $total / $i; @data = ([@nums], [@data], [@averaged]); my $graph = GD::Graph::mixed->new($width,$height); $graph->set(types => ['bars','lines'], x_label => 'Time ->', y_label => 'SNR', title => "SNR for " . $k, x_label_skip => 20, y_min_value => 0, x_max_value => $i, dclrs => ['#99FFCC','#993333'], ); my $gd = $graph->plot(\@data) or die $graph->error; open(IMG,">$directory\\$k.$lognum.png") or die $!; binmode(IMG); print IMG $gd->png; close(IMG); print FIL "" . (split(' ',$macs{$k}))[0] . " - $k


"; } my $graph = GD::Graph::bars->new($width,$height); my @data = ([keys (%strongest)],[values (%strongest)],[values(%averages)]); $graph->set(x_label => 'AP Name', y_label => 'SNR', title => 'Averages and Strongest Impulses', bar_spacing => 1, show_values => 1, dclrs => ['#99FFCC','#993333']); $graph->set_legend('Strongest Impulses','Average Signal Strength'); open(IMG,">$directory\\stats.$lognum.png") or die $!; binmode(IMG); print IMG $graph->plot(\@data)->png; close(IMG); print FIL "
"; close(FIL); }