#!/usr/bin/perl -w # # dvwatcher # John Simpson 2009-02-15 # # watches diagnostic output from DVTool.jar # looks up callsigns on QRZ.com, prints name and address info # keeps a local cache of callsign data (so as not to overload QRZ's servers) # ############################################################################### # # Copyright (C) 2009 John Simpson. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # or visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html # ############################################################################### require 5.003 ; use strict ; # if you don't already have these modules on your system, you can download # and install them from CPAN, http://www.cpan.org/ use HTML::TreeBuilder 3 ; use LWP ; # CHANGE THIS to point to the directory where the DVTool software, and this # script, reside on your system.) my $workdir = "/Users/jms1/DVTool" ; # this is the filename where it stores the locally cached callsign data my $callfile = "$workdir/calls.txt" ; # this is the hash where it keeps the callsign data my %calldata = () ; # this is the user agent string sent with the QRZ servers. my $browserid = "DVWatcher/0.1 (perl script by KG4ZOW; Mac OS X)" ; ############################################################################### sub readcalls() { if ( open ( I , "<$callfile" ) ) { my $call = "" ; my $entry = "" ; while ( my $line = ) { if ( $line =~ /^\s*$/ ) { $calldata{$call} = $entry ; $call = $entry = "" ; } elsif ( $line =~ /^(\S+)/ ) { $call = $1 ; $entry = "" ; } elsif ( $line =~ /^\s+(.+?)\s*$/ ) { $entry .= "$1\n" ; } } close I ; } } sub writecalls() { my @calls = sort keys %calldata ; open ( O , ">$callfile" ) or die "Can't create $callfile: $!\n" ; for my $call ( @calls ) { ######################################## # don't save empty blocks next unless ( $calldata{$call} ) ; ######################################## # print data to file print O "$call\n" ; for my $line ( split ( /\n/ , $calldata{$call} ) ) { print O "\t$line\n" ; } } close O ; } sub lookup_qrz($) { my $call = shift ; my $entry = "" ; ######################################## # create user agent my $ua = new LWP::UserAgent ; $ua->agent ( $browserid ) ; ######################################## # grab the page my $url = "http://www.qrz.com/db/$call" ; my $resp = $ua->get ( $url ) ; unless ( $resp->is_success ) { my $err = $resp->code . " " . $resp->message ; die "$url\n$err\n" ; } ######################################## # if QRZ doesn't know them, give up if ( $resp->content =~ / produced no results/ ) { print "\t(not listed in QRZ.com)\n" ; } else { ######################################## # find the data container in $resp->content my $root = new HTML::TreeBuilder ; $root->parse ( $resp->content ) ; my $block = $root->look_down ( sub { ($_[0]->attr("id")||"") eq "jq" } ) ; if ( $block ) { ######################################## # enumerate all

..

nodes within the block # stop at the "Lookups:" line (don't need vanity info) # skip the line which is just their call sign # store everything else for my $e ( $block->look_down ( "_tag" , "p" ) ) { my $t = $e->as_text ; last if ( $t =~ /Lookups:/ ) ; next if ( "\u$t" eq "\u$call" ) ; $entry .= "$t\n" ; } } else { print "(No element with id=\"jq\" found in page)\n" ; } } ######################################## # store the data (or no data) in memory $calldata{$call} = $entry ; ######################################## # if it's new, write the updated file ( $entry ne "" ) && writecalls() ; } ############################################################################### ############################################################################### ############################################################################### # # read known calls into memory readcalls() ; ############################################################################### # # start the program and watch its output stream $ENV{"PATH"} = join ( ":" , $ENV{"PATH"} , "." ) ; open ( J , "java -jar DVTool.jar |" ) or die "Can't run DVTool.jar: $!\n" ; while ( my $line = ) { ######################################## # print timestamp and input line my @d = localtime ; printf "%04d-%02d-%02d %02d:%02d:%02d %s" , $d[5]+1900 , $d[4]+1 , $d[3] , $d[2] , $d[1] , $d[0] , $line ; ######################################## # ignore lines which don't start with "my " # if it does, capture the callsign next unless ( $line =~ /^my (........)\// ) ; ######################################## # drop any space-separated suffixes my $call = $1 ; $call =~ s/\s.*$// ; ######################################## # get data unless ( exists $calldata{$call} ) { lookup_qrz ( $call ) ; } ######################################## # print it map { print "\t$_\n" } split ( /\n/ , ( $calldata{$call} || "" ) ) ; } close J ; print "done\n" ;