|
| 1 | +#!/usr/bin/perl |
| 2 | +# Network Wearthermap - version 1.1.1 (20040422) |
| 3 | +# http://netmon.grnet.gr/weathermap/ |
| 4 | +# Panagiotis Christias, <christias@noc.ntua.gr> |
| 5 | + |
| 6 | +$VERSION = "1.1.1"; |
| 7 | + |
| 8 | +use Getopt::Long; |
| 9 | +use GD; |
| 10 | + |
| 11 | +################################################################ |
| 12 | +# |
| 13 | +# Configuration parameters |
| 14 | +# |
| 15 | +$WGET = "/usr/local/bin/wget -qO -"; |
| 16 | +$CONFIG = "weathermap.conf"; |
| 17 | +$OUTPUT = "weathermap.png"; |
| 18 | +$DEBUG = 0; |
| 19 | +$WIDTH = 880; |
| 20 | +$HEIGHT = 750; |
| 21 | +# |
| 22 | +################################################################ |
| 23 | + |
| 24 | + |
| 25 | +%optctl=(); |
| 26 | +GetOptions(\%optctl, "config:s", "output:s", "version", "help", "debug", "") || exit(1); |
| 27 | + |
| 28 | +if($optctl{"config"}) { $CONFIG = $optctl{"config"} }; |
| 29 | + |
| 30 | +if($optctl{"output"}) { $OUTPUT = $optctl{"output"} }; |
| 31 | + |
| 32 | +if($optctl{"version"}) { &version; exit; } |
| 33 | + |
| 34 | +if($optctl{"help"}) { &usage; exit; } |
| 35 | + |
| 36 | +if($optctl{"debug"}) { $DEBUG=1; } |
| 37 | + |
| 38 | +&read_config($CONFIG); |
| 39 | + |
| 40 | +if($background){ |
| 41 | + open (PNG,"$background") || die "$background: $!\n"; |
| 42 | + $map = newFromPng GD::Image(PNG) || die "newFromPng failed."; |
| 43 | + close PNG; |
| 44 | +} else { |
| 45 | + $map=new GD::Image($WIDTH,$HEIGHT) |
| 46 | +} |
| 47 | + |
| 48 | +&alloc_colors; |
| 49 | + |
| 50 | +print "Opening log files...\n\n" if($DEBUG); |
| 51 | +foreach $link (keys %target){ |
| 52 | + |
| 53 | + $data = $target{$link}; |
| 54 | + print "FILE: $data\n" if($DEBUG); |
| 55 | + |
| 56 | + if(($data =~ /^https?:\/\//i) || ($data =~ /^ftp:\/\//i) ) { |
| 57 | + open(LOG, "$WGET $data |") or warn "$data: $!\n"; |
| 58 | + } else { |
| 59 | + open(LOG, "$data") or warn "data file $data: $!\n"; |
| 60 | + } |
| 61 | + |
| 62 | + while(<LOG>){ |
| 63 | + # <!-- cuin d 5585966 --> |
| 64 | + # <!-- cuout d 10589424 --> |
| 65 | + if(/<\!-- cuin d (\d+) -->/){ |
| 66 | + $input{$link}=$1; |
| 67 | + print "LINK: $link, Input: $input{$link}\n" if($DEBUG); |
| 68 | + } |
| 69 | + if(/<\!-- cuout d (\d+) -->/){ |
| 70 | + $output{$link}=$1; |
| 71 | + print "LINK: $link, Output: $output{$link}\n" if($DEBUG); |
| 72 | + } |
| 73 | + } |
| 74 | + close(LOG); |
| 75 | +} |
| 76 | + |
| 77 | +print "\nCalculating rates...\n\n" if($DEBUG); |
| 78 | + |
| 79 | +foreach $link (keys %target){ |
| 80 | + $outrate=(int(($output{$link}/$maxbytes{$link}+0.005)*100)>100) ? 100:int(($output{$link}/$maxbytes{$link}+0.005)*100); |
| 81 | + $inrate=(int(($input{$link}/$maxbytes{$link}+0.005)*100)>100) ? 100:int(($input{$link}/$maxbytes{$link}+0.005)*100); |
| 82 | + |
| 83 | + if($output{$link} != 0 && $outrate == 0) { $outrate=1 } |
| 84 | + if($input{$link} != 0 && $inrate == 0) { $inrate=1 } |
| 85 | + |
| 86 | + print "$target{$link}: outrate=$outrate%, inrate=$inrate%\n" if($DEBUG); |
| 87 | + |
| 88 | + # draw lines... |
| 89 | + |
| 90 | + $width=7; |
| 91 | + |
| 92 | + &draw_arrow( |
| 93 | + $xpos{$nodea{$link}}, |
| 94 | + $ypos{$nodea{$link}}, |
| 95 | + &middle($xpos{$nodea{$link}},$xpos{$nodeb{$link}}), |
| 96 | + &middle($ypos{$nodea{$link}},$ypos{$nodeb{$link}}), |
| 97 | + $width, 1, &select_color($outrate)); |
| 98 | + &draw_arrow( |
| 99 | + $xpos{$nodea{$link}}, |
| 100 | + $ypos{$nodea{$link}}, |
| 101 | + &middle($xpos{$nodea{$link}},$xpos{$nodeb{$link}}), |
| 102 | + &middle($ypos{$nodea{$link}},$ypos{$nodeb{$link}}), |
| 103 | + $width, 0, $black); |
| 104 | + |
| 105 | + &label(&middle($xpos{$nodea{$link}},&middle($xpos{$nodea{$link}},$xpos{$nodeb{$link}})), |
| 106 | + &middle($ypos{$nodea{$link}},&middle($ypos{$nodea{$link}},$ypos{$nodeb{$link}})), |
| 107 | + $outrate . "%", 0); |
| 108 | + |
| 109 | + &draw_arrow( |
| 110 | + $xpos{$nodeb{$link}}, |
| 111 | + $ypos{$nodeb{$link}}, |
| 112 | + &middle($xpos{$nodea{$link}},$xpos{$nodeb{$link}}), |
| 113 | + &middle($ypos{$nodea{$link}},$ypos{$nodeb{$link}}), |
| 114 | + $width, 1, &select_color($inrate)); |
| 115 | + &draw_arrow( |
| 116 | + $xpos{$nodeb{$link}}, |
| 117 | + $ypos{$nodeb{$link}}, |
| 118 | + &middle($xpos{$nodea{$link}},$xpos{$nodeb{$link}}), |
| 119 | + &middle($ypos{$nodea{$link}},$ypos{$nodeb{$link}}), |
| 120 | + $width, 0, $black); |
| 121 | + |
| 122 | + &label(&middle($xpos{$nodeb{$link}},&middle($xpos{$nodea{$link}},$xpos{$nodeb{$link}})), |
| 123 | + &middle($ypos{$nodeb{$link}},&middle($ypos{$nodea{$link}},$ypos{$nodeb{$link}})), |
| 124 | + $inrate . "%", 0); |
| 125 | +} |
| 126 | +print "\n" if($DEBUG); |
| 127 | + |
| 128 | +foreach(keys %xpos){ |
| 129 | + &label($xpos{$_},$ypos{$_},$label{$_}, 3); |
| 130 | +} |
| 131 | + |
| 132 | + |
| 133 | +&annotation; |
| 134 | + |
| 135 | +# print image... |
| 136 | +print "Generating image file $OUTPUT...\n\n" if($DEBUG); |
| 137 | +open(PNG,">$OUTPUT")||die("$OUTPUT: $!\n"); |
| 138 | +print PNG $map->png; |
| 139 | +close PNG; |
| 140 | + |
| 141 | +# hint, resizing the image could make it look better |
| 142 | + |
| 143 | +exit; |
| 144 | + |
| 145 | + |
| 146 | +# print labels |
| 147 | +sub label{ |
| 148 | + my($xpos,$ypos,$label,$pad)=@_; |
| 149 | + my($strwidth)=gdLargeFont->width*length($label); |
| 150 | + my($strheight)=gdLargeFont->height; |
| 151 | + $map->filledRectangle( |
| 152 | + $xpos-$strwidth/2-$pad-2, $ypos-$strheight/2-$pad+1, |
| 153 | + $xpos+$strwidth/2+$pad+1, $ypos+$strheight/2+$pad, |
| 154 | + $black); |
| 155 | + $map->filledRectangle( |
| 156 | + $xpos-$strwidth/2-$pad-1, $ypos-$strheight/2-$pad+2, |
| 157 | + $xpos+$strwidth/2+$pad, $ypos+$strheight/2+$pad-1, |
| 158 | + $white); |
| 159 | + $map->string(gdLargeFont, |
| 160 | + $xpos-$strwidth/2, $ypos-$strheight/2+1, |
| 161 | + $label, $black) |
| 162 | +} |
| 163 | + |
| 164 | + |
| 165 | +# print annotation |
| 166 | +sub annotation{ |
| 167 | + my($title)="Traffic load"; |
| 168 | + $strwidth=gdLargeFont->width*length($label{$_}); |
| 169 | + $strheight=gdLargeFont->height; |
| 170 | + |
| 171 | +# $t=localtime(time); |
| 172 | + $t=gmtime(time); |
| 173 | + $map->string(gdSmallFont, 0, 785, "Last update on $t UTC", $black); |
| 174 | + |
| 175 | + $map->filledRectangle($keyxpos,$keyypos, |
| 176 | + $keyxpos+gdLargeFont->width*length($title)+10, |
| 177 | + $keyypos+gdLargeFont->height*($scales+1)+10, |
| 178 | + $gray); |
| 179 | + $map->rectangle($keyxpos,$keyypos, |
| 180 | + $keyxpos+gdLargeFont->width*length($title)+10, |
| 181 | + $keyypos+gdLargeFont->height*($scales+1)+10, |
| 182 | + $black); |
| 183 | + $map->string(gdLargeFont, |
| 184 | + $keyxpos+4, |
| 185 | + $keyypos+4, |
| 186 | + "Traffic load", $black); |
| 187 | + |
| 188 | + my($i)=1; |
| 189 | + foreach(sort {$scale_low{$a}<=>$scale_low{$b}} keys %scale_low){ |
| 190 | + $map->filledRectangle( |
| 191 | + $keyxpos+6, |
| 192 | + $keyypos+gdLargeFont->height*$i+8, |
| 193 | + $keyxpos+6+16, |
| 194 | + $keyypos+gdLargeFont->height*$i+gdLargeFont->height+6, |
| 195 | + $color{$_}); |
| 196 | + $map->string(gdLargeFont, |
| 197 | + $keyxpos+6+20, |
| 198 | + $keyypos+gdLargeFont->height*$i+8, |
| 199 | + "$scale_low{$_}-$scale_high{$_}%", $black); |
| 200 | + $i++ |
| 201 | + } |
| 202 | +} |
| 203 | + |
| 204 | +sub select_color { |
| 205 | + my($rate)=($_[0]>100) ? 100:$_[0]; |
| 206 | + if($rate=="0"){return($darkgray)} |
| 207 | + foreach(sort {$scale_high{$a}<=>$scale_high{$b}} keys %scale_high){ |
| 208 | + if($scale_low{$_}<=$rate && $rate<=$scale_high{$_}){ |
| 209 | + return($color{$_}); |
| 210 | + } |
| 211 | + } |
| 212 | +} |
| 213 | + |
| 214 | +sub alloc_colors { |
| 215 | + $white=$map->colorAllocate(255,255,255); |
| 216 | + $gray=$map->colorAllocate(248,248,248); |
| 217 | + $black=$map->colorAllocate(0,0,0); |
| 218 | + $darkgray=$map->colorAllocate(128,128,128); |
| 219 | + |
| 220 | + foreach(keys %scale_red){ |
| 221 | + $color{$_} = $map->colorAllocate($scale_red{$_},$scale_green{$_},$scale_blue{$_}); |
| 222 | + } |
| 223 | +} |
| 224 | + |
| 225 | + |
| 226 | +sub read_config { |
| 227 | +my($config)=shift; |
| 228 | +my($node,$link); |
| 229 | + |
| 230 | +print "\nReading configuration file...\n\n" if($DEBUG); |
| 231 | + |
| 232 | +$scales=0; |
| 233 | +open(CONF,$config) or die "$config: $!\n"; |
| 234 | +while(<CONF>){ |
| 235 | + if(/^\s*BACKGROUND\s+(\S+)/i){ |
| 236 | + if(-s "$1"){ |
| 237 | + $background=$1; |
| 238 | + print "found BACKGROUND: $background\n" if($DEBUG); |
| 239 | + } |
| 240 | + } |
| 241 | + if(/^\s*WIDTH\s+(\d+)/i){ |
| 242 | + if("$1" ne ""){ |
| 243 | + $WIDTH=$1; |
| 244 | + print "found WIDTH: $WIDTH\n" if($DEBUG); |
| 245 | + } |
| 246 | + } |
| 247 | + if(/^\s*HEIGHT\s+(\d+)/i){ |
| 248 | + if("$1" ne ""){ |
| 249 | + $HEIGHT=$1; |
| 250 | + print "found HEIGHT: $HEIGHT\n" if($DEBUG); |
| 251 | + } |
| 252 | + } |
| 253 | + if(/^\s*NODE\s+(\w+)/i){ |
| 254 | + $node=$1; |
| 255 | + print "found NODE: $node\n" if($DEBUG); |
| 256 | + } |
| 257 | + if(/^\s*POSITION\s+(\d+)\s+(\d+)/i){ |
| 258 | + $xpos{$node}=$1; |
| 259 | + $ypos{$node}=$2; |
| 260 | + print "found NODE: $node XPOS: $xpos{$node} YPOS: $xpos{$node}\n" if($DEBUG); |
| 261 | + } |
| 262 | + if(/^\s*LABEL\s+(\S+)/i){ |
| 263 | + $label{$node}=$1; |
| 264 | + print "found NODE: $node LABEL: $label{$node}\n" if($DEBUG); |
| 265 | + } |
| 266 | + |
| 267 | + if(/^\s*LINK\s+(\S+)/i){ |
| 268 | + $link=$1; |
| 269 | + print "found LINK: $link\n" if($DEBUG); |
| 270 | + } |
| 271 | + if(/^\s*NODES\s+(\S+)\s+(\S+)/i){ |
| 272 | + $nodea{$link}=$1; |
| 273 | + $nodeb{$link}=$2; |
| 274 | + print "found LINK: $link NODEA: $nodea{$link} NODEB: $nodeb{$link}\n" if($DEBUG); |
| 275 | + } |
| 276 | + if(/^\s*TARGET\s+(\S+)/i){ |
| 277 | + $target{$link}=$1; |
| 278 | + print "found LINK: $link TARGET: $target{$link}\n" if($DEBUG); |
| 279 | + } |
| 280 | + if(/^\s*BANDWIDTH\s+(\d+)/i){ |
| 281 | + $bandwidth{$link}=$1; |
| 282 | + $maxbytes{$link}=$bandwidth{$link}*1024/8; |
| 283 | + print "found LINK: $link BANDWIDTH: $bandwidth{$link}\n" if($DEBUG); |
| 284 | + } |
| 285 | + if(/^\s*KEYPOS\s+(\d+)\s+(\d+)/i){ |
| 286 | + $keyxpos=$1; |
| 287 | + $keyypos=$2; |
| 288 | + print "found KEY POSITION: $keyxpos $keyypos\n" if($DEBUG); |
| 289 | + } |
| 290 | + if(/^\s*SCALE\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/i){ |
| 291 | + $scale_low{"$1:$2"}=$1; |
| 292 | + $scale_high{"$1:$2"}=$2; |
| 293 | + $scale_red{"$1:$2"}=$3; |
| 294 | + $scale_green{"$1:$2"}=$4; |
| 295 | + $scale_blue{"$1:$2"}=$5; |
| 296 | + $scales++; |
| 297 | + print "found SCALE DATA: $1:$2 $3:$4:$5\n" if($DEBUG); |
| 298 | + } |
| 299 | +} |
| 300 | +print "\n" if($DEBUG); |
| 301 | +} |
| 302 | + |
| 303 | + |
| 304 | +sub middle{ |
| 305 | + return int( $_[0] + ($_[1]-$_[0])/2 ) |
| 306 | +} |
| 307 | + |
| 308 | +sub dist{ |
| 309 | + return int( sqrt( $_[0]*$_[0] + $_[1]*$_[1] ) ) |
| 310 | +} |
| 311 | + |
| 312 | +sub newx{ |
| 313 | + my($a,$b,$x,$y)=@_; |
| 314 | + return int( cos( atan2($y,$x) + atan2($b,$a) ) * sqrt( $x*$x + $y*$y ) ); |
| 315 | +} |
| 316 | + |
| 317 | +sub newy{ |
| 318 | + my($a,$b,$x,$y)=@_; |
| 319 | + return int( sin( atan2($y,$x) + atan2($b,$a) ) * sqrt( $x*$x + $y*$y ) ); |
| 320 | +} |
| 321 | + |
| 322 | + |
| 323 | + |
| 324 | +sub draw_arrow { |
| 325 | + my($x1,$y1,$x2,$y2,$w,$solid,$color)=($_[0],$_[1],$_[2],$_[3],$_[4],$_[5],$_[6]); |
| 326 | + my($arrow)=new GD::Polygon; |
| 327 | + |
| 328 | + $arrow->addPt( |
| 329 | + $x1 + &newx($x2-$x1, $y2-$y1, 0, $w), |
| 330 | + $y1 + &newy($x2-$x1, $y2-$y1, 0, $w) |
| 331 | + ); |
| 332 | + |
| 333 | + $arrow->addPt( |
| 334 | + $x2 + &newx($x2-$x1, $y2-$y1, -4*$w, $w), |
| 335 | + $y2 + &newy($x2-$x1, $y2-$y1, -4*$w, $w) |
| 336 | + ); |
| 337 | + |
| 338 | + $arrow->addPt( |
| 339 | + $x2 + &newx($x2-$x1, $y2-$y1, -4*$w, 2*$w), |
| 340 | + $y2 + &newy($x2-$x1, $y2-$y1, -4*$w, 2*$w) |
| 341 | + ); |
| 342 | + |
| 343 | + $arrow->addPt( $x2, $y2); |
| 344 | + |
| 345 | + $arrow->addPt( |
| 346 | + $x2 + &newx($x2-$x1, $y2-$y1, -4*$w, -2*$w), |
| 347 | + $y2 + &newy($x2-$x1, $y2-$y1, -4*$w, -2*$w) |
| 348 | + ); |
| 349 | + |
| 350 | + $arrow->addPt( |
| 351 | + $x2 + &newx($x2-$x1, $y2-$y1, -4*$w, -$w), |
| 352 | + $y2 + &newy($x2-$x1, $y2-$y1, -4*$w, -$w) |
| 353 | + ); |
| 354 | + |
| 355 | + $arrow->addPt( |
| 356 | + $x1 + &newx($x2-$x1, $y2-$y1, 0, -$w), |
| 357 | + $y1 + &newy($x2-$x1, $y2-$y1, 0, -$w) |
| 358 | + ); |
| 359 | + |
| 360 | + if($solid){ |
| 361 | + $map->filledPolygon($arrow,$color); |
| 362 | + }else{ |
| 363 | + $map->polygon($arrow,$color); |
| 364 | + } |
| 365 | +} |
| 366 | + |
| 367 | + |
| 368 | +sub version { |
| 369 | + print <<EOM; |
| 370 | +Network Wearthermap v$VERSION - http://netmon.grnet.gr/weathermap/ |
| 371 | +EOM |
| 372 | +} |
| 373 | + |
| 374 | +sub usage { |
| 375 | + print <<EOM; |
| 376 | +Network Wearthermap v$VERSION - http://netmon.grnet.gr/weathermap/ |
| 377 | +Usage: $0 [OPTION]... |
| 378 | +
|
| 379 | + -c, --config=FILE configuration file (default $CONFIG) |
| 380 | + -o, --output=FILE output image file default (default $OUTPUT) |
| 381 | + -v, --version print version |
| 382 | + -h, --help print this text |
| 383 | + -d, --debug enable debug output |
| 384 | +
|
| 385 | +EOM |
| 386 | +} |
0 commit comments