X-Git-Url: http://dxcluster.net/gitweb/gitweb.cgi?a=blobdiff_plain;f=perl%2FRBN.pm;h=aac6fa90da9246f9ec04fa75bb95b61f45999c77;hb=9ea25ac2d6b1a44f346c4c14e94caaa83789f156;hp=492b1ac5331d68cddae9939c37e380595537ad45;hpb=535e44d1449d219bb8479d6f824118e3b31dde7a;p=spider.git diff --git a/perl/RBN.pm b/perl/RBN.pm index 492b1ac5..aac6fa90 100644 --- a/perl/RBN.pm +++ b/perl/RBN.pm @@ -22,9 +22,9 @@ use Time::HiRes qw(clock_gettime CLOCK_REALTIME); our @ISA = qw(DXChannel); -our $startup_delay =0;#3*60; # don't send anything out until this timer has expired +our $startup_delay = 10*60; # don't send anything out until this timer has expired # this is to allow the feed to "warm up" with duplicates - # so that the "big rush" doesn't happen. + # so that the "big rush" doesn't happen. our $minspottime = 60*60; # the time between respots of a callsign - if a call is # still being spotted (on the same freq) and it has been @@ -184,20 +184,9 @@ sub normal if ($mode eq 'RTTY') { $mode = 'RTT'; } - - # We have an RBN data line, dedupe it very simply on time, ignore QRG completely. - # This works because the skimmers are NTP controlled (or should be) and will receive - # the spot at the same time (velocity factor of the atmosphere and network delays - # carefully (not) taken into account :-) - - # Note, there is no intelligence here, but there are clearly basic heuristics that could - # be applied at this point that reject (more likely rewrite) the call of a busted spot that would - # useful for a zonal hotspot requirement from the cluster node. - # In reality, this mechanism would be incorporated within the cluster code, utilising the dxqsl database, - # and other resources in DXSpider, thus creating a zone map for an emitted spot. This is then passed through the - # normal "to-user" spot system (where normal spots are sent to be displayed per user) and then be - # processed through the normal, per user, spot filtering system - like a regular spot. + # The main de-duping key is [call, $frequency], but we probe a bit around that frequency to find a + # range of concurrent frequencies that might be in play. # The key to this is deducing the true callsign by "majority voting" (the greater the number of spotters # the more effective this is) together with some lexical analsys probably in conjuction with DXSpider @@ -215,21 +204,32 @@ sub normal # process to just the standard "message passing" which has been shown to be able to sustain over 5000 # per second (limited by the test program's output and network speed, rather than DXSpider's handling). - my $nqrg = nearest(.5, $qrg); # normalised to nearest Khz + my $nqrg = nearest(1, $qrg); # normalised to nearest Khz my $sp = "$call|$nqrg"; # hopefully the skimmers will be calibrated at least this well! + my $spp = sprintf("$call|%d", $nqrg+1); # but, clearly, my hopes are rudely dashed + my $spm = sprintf("$call|%d", $nqrg-1); # in BOTH directions! # do we have it? my $spot = $spots->{$sp}; + $spot = $spots->{$spp}, $sp = $spp, dbg('SPP') if !$spot && exists $spots->{$spp}; + $spot = $spots->{$spm}, $sp = $spm, dbg('SPM') if !$spot && exists $spots->{$spm}; + # if we have one and there is only one slot and that slot's time isn't expired for respot then return my $respot = 0; - if ($spot && @$spot == 1) { - unless ($self->{minspottime} > 0 && $tim - $spot->[0] >= $self->{minspottime}) { - dbg("RBN: key: '$sp' call: $call qrg: $qrg DUPE \@ ". atime(int $spot->[0])) if isdbg('rbn'); - return; + if ($spot && ref $spot) { + if (@$spot == 1) { + unless ($self->{minspottime} > 0 && $tim - $spot->[0] >= $self->{minspottime}) { + dbg("RBN: key: '$sp' call: $call qrg: $qrg DUPE \@ ". atime(int $spot->[0])) if isdbg('rbn'); + return; + } + + dbg("RBN: key: '$sp' RESPOTTING call: $call qrg: $qrg last seen \@ ". atime(int $spot->[0])) if isdbg('rbn'); + ++$respot; } - dbg("RBN: key: '$sp' RESPOTTING call: $call qrg: $qrg last seen \@ ". atime(int $spot->[0])) if isdbg('rbn'); - ++$respot; + } elsif ($spot) { + dbg("RBN: key '$sp' = '$spot' not ref"); + return; } # here we either have an existing spot record buildup on the go, or we need to create the first one @@ -241,7 +241,7 @@ sub normal # add me to the display queue unless we are waiting for initial in rush to finish return unless $self->{inrushpreventor} < $main::systime; - push @queue, $sp if @$spot == 1; # queue the KEY (not the record) + push @{$self->{queue}}, $sp if @$spot == 1; # queue the KEY (not the record) # build up a new record and store it in the buildup # deal with the unix time @@ -250,7 +250,7 @@ sub normal $utz -= 86400 if $utz > $tim+3600; # too far ahead, drag it back one day # create record and add into the buildup - my $r = [$origin, nearest(.1, $qrg), $call, $mode, $s, $t, $utz, $respot]; + my $r = [$origin, nearest(.1, $qrg), $call, $mode, $s, $t, $utz, $respot, $u]; dbg("RBN: key: '$sp' ADD RECORD call: $call qrg: $qrg origin: $origin") if isdbg('rbn'); push @$spot, $r; @@ -259,13 +259,17 @@ sub normal my $now = clock_gettime(CLOCK_REALTIME); # now run the waiting queue which just contains KEYS ($call|$qrg) - foreach $sp (@queue) { + foreach $sp (@{$self->{queue}}) { my $cand = $spots->{$sp}; - if ($now >= $cand->[0]+$dwelltime ) { + unless ($cand && $cand->[0]) { + dbg "RBN Cand " . ($cand ? 'def' : 'undef') . " [0] " . ($cand->[0] ? 'def' : 'undef') . " dwell $dwelltime"; + next; + } + if ($now >= $cand->[0] + $dwelltime ) { # we have a candidate, create qualitee value(s); unless (@$cand > 1) { dbg "RBN: QUEUE key '$sp' MISSING RECORDS " . dd($cand) if isdbg 'rbn'; - shift @queue; + shift @{$self->{queue}}; next; } my $savedtime = shift @$cand; # save the start time @@ -283,8 +287,9 @@ sub normal # clear out the data and make this now just "spotted", but no further action required until respot time dbg "RBN: QUEUE key '$sp' cleared" if isdbg 'rbn'; + $spots->{$sp} = [$savedtime]; - shift @queue; + shift @{$self->{queue}}; } else { dbg sprintf("RBN: QUEUE key: '$sp' SEND time not yet reached %.1f secs left", $spot->[0] + $dwelltime - $now) if isdbg 'rbnqueue'; } @@ -366,15 +371,20 @@ sub dx_spot my $saver; my %zone; + my %qrg; + my $respot; + foreach my $r (@$spot) { - # $r = [$origin, $qrg, $call, $mode, $s, $t, $utz, $respot]; + # $r = [$origin, $qrg, $call, $mode, $s, $t, $utz, $respot, $qra]; # Spot::prepare($qrg, $call, $utz, $comment, $origin); my $comment = sprintf "%-3s %2ddB $quality", $r->[3], $r->[4]; my @s = Spot::prepare($r->[1], $r->[2], $r->[6], $comment, $r->[0]); - + $respot = 1 if $r->[7]; ++$zone{$s[11]}; # save the spotter's zone + ++$qrg{$s[0]}; # and the qrg + # save the highest strength one if ($r->[4] < $strength) { @@ -397,9 +407,23 @@ sub dx_spot if ($saver) { my $buf; + # create a zone list of spotters delete $zone{$saver->[11]}; # remove this spotter's zone (leaving all the other zones) my $z = join ',', sort {$a <=> $b} keys %zone; - $saver->[3] .= " Z:$z" if length $z; + + # determine the most likely qrg and then set it + my $mv = 0; + my $fk; + my $c = 0; + while (my ($k, $v) = each %qrg) { + $fk = $k, $mv = $v if $v > $mv; + ++$c; + } + $saver->[0] = $fk; + $saver->[3] .= '*' if $c > 1; + $saver->[3] .= '+' if $respot; + $saver->[3] .= " Z:$z" if $z; + dbg("RBN: SENDING call: $saver->[1] qrg: $saver->[0] origin: $saver->[4] $saver->[3]") if isdbg 'rbn'; if ($dxchan->{ve7cc}) { $buf = VE7CC::dx_spot($dxchan, @$saver); @@ -408,6 +432,12 @@ sub dx_spot } $buf =~ s/^DX/RB/; $dxchan->local_send('N', $buf); + + if ($saver->[8] && is_qra($saver->[8])) { + my $user = DXUser::get_current($s[1]) || DXUser::new($s[1]); + $user->qra($saver->[8]) unless $user->qra; + $user->lastseen($main::systime); + } } }