Fixes and additions to Grayline

Fixes and additions to Grayline and command line startup

	- Removed RBNThread from Grayline. It seems to work without: I can not see any need
	  for it as LNET telnet connection has event based receive and so can handle receiving
	  without polling.

	  Removing thread made QT5 compiled version to connect to RBN too!
	  There is still an option to link the Grayline map to RBNMonitor so that only one
	  connection to RBN server is needed.

	- RBN spots are now handled by timer. Changed remove routine to use UnixTime as using
	  FPC's DateTime as plain value does count seconds since day changed and then does
	  not take account day changes that may cause unwanted functions at midnight.

	- RBN spots are now band specific as original help file says. I am not sure were they
	  before, or did I just lost that property when dropping RBNThread away.

	- Added more options to popup menu:
	  -- Show GreatCircle path
		This is an alternative to straight line between myQTH and QSOstn.

		My math skills are limited, but I think I finally managed to create working
		procedure for great circle line. There may be some glitches at top and bottom
		corner grid squares (but very seldom there are stations!)

		There are some probeĺems with layouts compared with GTK2 and QT5.
		With QT5 the GCline looks quite acceptable, but getting the myQTH spot
		visible (when no qso call entered) is Grayline map zoom size depended.
		With GTK2 the myQTH spot shows up better, but GCline looks worse in some cases.
		(try myQTH with Ctrl+L to BL55ll and enter CR01ll (and leave column) to
		Grid of empty NewQSO. Compare QT5 and GTK2).
		In common: the bigger the map the better the gray line look.
		But these are things we just have to live with (or write completely new
		Grayline map with better resolution)

	 -- Clear all spots
		This clears all RBN spots from map that are normally cleared by timer

	 -- Watch for:
		Here you can set callsign or prefix followed by asterisk that you want to use
		as spot trigger. It is the same as in preferences/RBN support/Watch for
		Just quicker to access.

	- Fixed help files

	- Fixed command line startup help to have a list of all special debug values

Squashed commit of the following:

commit f4390be7cab08099138a3faee228ae812525a77e
Author: OH1KH <oh1kh@sral.fi>
Date:   Fri Jan 21 09:22:39 2022 +0200

    Added gline2.pas to project. Fixed command line help

commit 3b67c16c60
Author: OH1KH <oh1kh@sral.fi>
Date:   Thu Jan 20 15:18:43 2022 +0200

    trying to make own qth dot a bit bigger

commit 57f3337ad0
Author: OH1KH <oh1kh@sral.fi>
Date:   Thu Jan 20 10:36:47 2022 +0200

    Now passing 180/-180 works. Just small problems with edge locators (supposed to be from inaccurate calculations)

commit a17ef56185
Author: OH1KH <oh1kh@sral.fi>
Date:   Thu Jan 20 09:21:35 2022 +0200

    Great circle works now better on high latituses. Still the vertical border 180/-180 crossing fails.

commit e32500bc30
Author: OH1KH <oh1kh@sral.fi>
Date:   Wed Jan 19 18:46:28 2022 +0200

    Now dot blinking seems to be fixed. Also dots are now band related as the help says

commit cdcdc83cc8
Author: OH1KH <oh1kh@sral.fi>
Date:   Wed Jan 19 12:27:18 2022 +0200

    Combined grat_circle and gray_spots. Help files fixed. Still needs check why map spots are blinking and are they really band releted as original help says

commit 8c69eb6b0a
Merge: 89aed72 f5d72ff
Author: OH1KH <oh1kh@sral.fi>
Date:   Wed Jan 19 10:15:17 2022 +0200

    Merge branch 'gray_spots' into gray_fix

commit f5d72ff423
Author: OH1KH <oh1kh@sral.fi>
Date:   Fri Jan 14 14:56:10 2022 +0200

    Removed RBNThread to see what is the effect.
    Now connects ALSO WITH QT5  !!!
    Code cleanups
    Defined localdbg with value -16 to see debug only from this form

commit 696e372dc4
Author: OH1KH <oh1kh@sral.fi>
Date:   Tue Jan 11 18:50:47 2022 +0200

    This seems to work. Return to this if thread remove does not succeed
This commit is contained in:
OH1KH 2022-01-21 10:11:00 +02:00
parent 89aed72b1d
commit dfb6406526
14 changed files with 557 additions and 441 deletions

View File

@ -708,7 +708,7 @@ There are no known dependencies issues.<br><br>
<img src="img/h1114.png"><br><br>
<ul>
<li><strong>Login:</strong> - your user name to log in to RBN. It's usually your own callsign.</li>
<li><strong>Watch for:</strong> the callsign you are watching for, also usually your own callsign.
<li><strong>Watch for:</strong> the callsign you are watching for, usually your own callsign but can be any. You can also type in prefix followed by asterisk I.E. OK* etc.
If you leave this field empty, every spot will be shown on the grayline map.</li>
<li><strong>Signal strength</strong> How strong you are will be clear very quickly when you look
at the map with the dots in different colours. Which colour will be used can be set here.</li>
@ -716,19 +716,20 @@ There are no known dependencies issues.<br><br>
to RBN when the Grayline and/or RBN Monitor window opens. If you have closed cqrlog with window(s) open they will open at next program start
and so also connection is made.</li>
<ul>
<li><strong>Autoconnect RBN Grayline</strong> connects Grayline map to RBN.</li>
<li><strong>Autoconnect RBN Monitor</strong> connects RBN Monitor to RBN. See: <a href="./h31.html">Operation/RBN monitor</a></li>
<li><strong>Link Grayline to RBN Monitor.</strong> links Grayline to same connection as RBN Monitor uses and does not allow to create a new connection to Grayline itself. This is usefull with QT5 widgets compiled version as there the direct Grayline RBN connection does not work. It also saves one connection in all cases as the same RBN connection can be used for both Grayline dotting and RBN Monitor listing.
<br>Linking alone does not start Grayline dotting. Connection to RBN must be done either here with <strong>Autoconnect RBN Monitor</strong> or <strong>manually</strong> at RBM Monitor window side.</li>
<strong>Note:</strong> Even when linked, Grayline dotting and RBN Monitor listing both uses their own settings what call(s) to follow.
<li><strong>Autoconnect RBN Grayline</strong> connects Grayline map to RBN.
<br>Connection to RBN must be done either here with <strong>Autoconnect RBN Monitor</strong> or <strong>manually</strong> at Grayline window side.</li>
<li><strong>Autoconnect RBN Monitor</strong> connects RBN Monitor to RBN site. See: <a href="./h31.html">Operation/RBN monitor</a></li>
<li><strong>Link Grayline to RBN Monitor</strong> links Grayline to same connection as RBN Monitor uses. It saves one connection as the same RBN connection can be used for both Grayline dotting and RBN Monitor listing.
</li>
<strong>Note:</strong> Linking alone does not start Grayline dotting.When linked, Grayline dotting and RBN Monitor listing both uses their own filter settings what call(s) to follow.
<br><strong>Note:</strong> "Connect RBN Grayline" and "Link Grayline to RBN Monitor" are alternatives. You can not select both of them at same time.</li>
</ul>
<li><strong>Delete old information after XX seconds</strong> The dots won't stay on the map forever.
180 seconds (3 minutes) is a good default value. Please note, it also depends on the band,
if you change band, dots will always be deleted. All data is band related.</li>
180 seconds (3 minutes) is a good default value.
<br><b>Note:</b> Dots also depend on the band, if you change band, dots will always be deleted. All data is band related.</li>
</ul>
<br><br>
<img src="img/h1114b.png"><br><br>
<a name=ch7><h2><strong>Online log upload support</strong></h2></a>
CQRLOG supports online log upload to <a href="http://HamQTH.com">HamQTH</a>,
<a href="https://secure.clublog.org/loginform.php">ClubLog.org</a> and

65
help/h32.html Normal file
View File

@ -0,0 +1,65 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<head>
<title>CQRLOG </title>
</head>
<body>
<table border="0" cellpadding="5" cellspacing="2" width="100%">
<tbody>
<tr>
<td valign="top"><img src="img/exc.png"></td>
<td bgcolor=ffffcc valign="top" align="justify"><strong>
<font color="red">WARNING!</font></strong>
Backup your data often! BACKUP your log directory at the end of EVERY session!
All that you need to backup and store in a safe place is the log database directory
located in the ~/.config/cqrlog/database folder, or you can enable the autobackup function
in Preferences. This autobackup function creates an ADIF file with a backup of your log.
/td>
</tr>
</tbody>
</table>
<table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td width="33%" align="center">[<a href="index.html" target="_top">Menu</a>]</td>
</tr>
</tbody>
</table>
<br>
<div style="text-align: left;"><strong>CQRLOG for LINUX by OK2CQR &amp; OK1RR</strong></div>
<p align="center"><img src=img/line.png></p>
<h3>Grayline map</h3>
<p> Grayline window opens from NewQSO/Window/Grayline.</p>
<p>
Grayline map has speed button at top right corner that opens a popup menu containing:
<ul>
<li> <b>Connect to RBN</b> If autoconnect is not seleceted, see: <a href="h1.html#ch6">RBN support</a>, the connect and disconnect to RBN can be done here.</li>
<li> <b>Link to RBNMonitor</b> This is alternative to RBN connection and will use same connection as RBN monitor window has (if connected).</li>
<li> <b>Show statusbar</b> Shows connection or linking state</li>
<li> <b>Show GreatCirclePath</b> By default Grayline map will show straight line from your station (from your locator defined) to station you enter to NewQSO/callsign.
With this selection you can switch the straight line to plotted great circle path. </li>
<li> <b>Clear all spots</b> Clears all RBN spots from map.
<br><b> Note:</b> Dots also depend on the band, if you change band, dots will always be deleted. All data is band related.</li>
<li> <b>Watch for</b> Opens an edit window where you can change callsign or prefix watched without opening preferences. see: <a href="h1.html#ch6">RBN support</a></li>
</ul>
<img src="img/h1114b.png"><br><br>
<img src="img/h1114c.png"><br><br>
<img src="img/h1114d.png"><br><br>
<p align="center"><img src=img/line.png></p>
<br>
<table width="100%" border="0" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td width="33%" align="center">[<a href="index.html" target="_top">Menu</a>]</td>
</tr>
</tbody>
</table>
<br>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 205 KiB

After

Width:  |  Height:  |  Size: 208 KiB

BIN
help/img/h1114c.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

BIN
help/img/h1114d.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -63,6 +63,7 @@
<li><a target="right" href="wsjt.html">Digital modes:</a> <em>wsjt-x</em></li>
<li><a target="right" href="h21.html#ah19">DX Cluster Operation</a></li>
<li><a target="right" href="h23.html#ah22">Filtering</a></li>
<li><a target="right" href="h32.html">Grayline map</a></li>
<li><a target="right" href="h25.html#grp">Group edit</a></li>
<li><a target="right" href="gridmap.html">Grid Map</a></li>
<li><a target="right" href="h7.html">LoTW</a></li>

View File

@ -105,7 +105,7 @@
<MinVersion Major="1" Minor="2" Release="1" Valid="True"/>
</Item10>
</RequiredPackages>
<Units Count="119">
<Units Count="120">
<Unit0>
<Filename Value="cqrlog.lpr"/>
<IsPartOfProject Value="True"/>
@ -881,6 +881,10 @@
<Filename Value="znacmech.pas"/>
<IsPartOfProject Value="True"/>
</Unit118>
<Unit119>
<Filename Value="gline2.pas"/>
<IsPartOfProject Value="True"/>
</Unit119>
</Units>
</ProjectOptions>
<CompilerOptions>

View File

@ -5,26 +5,27 @@ uses
cmem,cthreads,uScrollBars,
Interfaces, // this includes the LCL widgetset
Forms, sysutils, Classes, fMain, fPreferences, dUtils, fNewQSO, dialogs,
fChangeLocator, fChangeOperator, dData, dDXCC, fMarkQSL, fDXCCStat, fSort, fFilter,
fImportProgress, fImportTest, TAChartLazarusPkg, RunTimeTypeInfoControls,
fSelectDXCC, fGrayline, fCallbook, fTRXControl, fFreq, fChangeFreq,
fAdifImport, fSplash, fSearch, fQTHProfiles, fNewQTHProfile, fEnterFreq,
fExportProgress, fNewDXCluster, fDXCluster, fDXClusterList, dDXCluster,
fWorking, fSerialPort, fQSLMgr, fSendSpot, fQSODetails, fUpgrade, fWAZITUStat,
fIOTAStat, fClubSettings, fLoadClub, fRefCall, fGraphStat, fBandMap,
fBandMapWatch, fLongNote, fDatabaseUpdate, fExLabelPrint, fImportLoTWWeb,
fLoTWExport, fGroupEdit, fDefaultFreq, fCustomStat, fKeyTexts, fCWType,
fSplitSettings, MemDSLaz, SDFLaz, turbopoweripro, fShowStations, uMyIni,
fPropagation, fSQLConsole, fCallAttachment, fEditDetails, fQSLViewer, fCWKeys,
fSCP, fDBConnect, fNewLog, fRebuildMembStat, uVersion, fAbout, fChangelog,
fBigSquareStat, feQSLDownload, feQSLUpload, fSOTAExport, fEDIExport,
fNewQSODefValues, fQSLExpPref, fRotControl, dLogUpload, fLogUploadStatus,
frCWKeys, fCallAlert, fNewCallAlert, fConfigStorage, fRbnFilter, fRbnMonitor,
fRbnServer, fRadioMemories, fAddRadioMemory, fException, fCommentToCall,
fChangeLocator, fChangeOperator, dData, dDXCC, fMarkQSL, fDXCCStat, fSort,
fFilter, fImportProgress, fImportTest, TAChartLazarusPkg,
RunTimeTypeInfoControls, fSelectDXCC, fGrayline, fCallbook, fTRXControl,
fFreq, fChangeFreq, fAdifImport, fSplash, fSearch, fQTHProfiles,
fNewQTHProfile, fEnterFreq, fExportProgress, fNewDXCluster, fDXCluster,
fDXClusterList, dDXCluster, fWorking, fSerialPort, fQSLMgr, fSendSpot,
fQSODetails, fUpgrade, fWAZITUStat, fIOTAStat, fClubSettings, fLoadClub,
fRefCall, fGraphStat, fBandMap, fBandMapWatch, fLongNote, fDatabaseUpdate,
fExLabelPrint, fImportLoTWWeb, fLoTWExport, fGroupEdit, fDefaultFreq,
fCustomStat, fKeyTexts, fCWType, fSplitSettings, MemDSLaz, SDFLaz,
turbopoweripro, fShowStations, uMyIni, fPropagation, fSQLConsole,
fCallAttachment, fEditDetails, fQSLViewer, fCWKeys, fSCP, fDBConnect, fNewLog,
fRebuildMembStat, uVersion, fAbout, fChangelog, fBigSquareStat, feQSLDownload,
feQSLUpload, fSOTAExport, fEDIExport, fNewQSODefValues, fQSLExpPref,
fRotControl, dLogUpload, fLogUploadStatus, frCWKeys, fCallAlert,
fNewCallAlert, fConfigStorage, fRbnFilter, fRbnMonitor, fRbnServer,
fRadioMemories, fAddRadioMemory, fException, fCommentToCall,
fNewCommentToCall, fFindCommentToCall, frExportPref, fExportPref,
fWorkedGrids, fPropDK0WCY, fRemind, fContest, fMonWsjtx, fXfldigi,
dMembership, dSatellite, uRigControl, uRotControl, azidis3, aziloc,
fDOKStat, fCabrilloExport, uDbUtils, dQTHProfile, uConnectionInfo, znacmech;
dMembership, dSatellite, uRigControl, uRotControl, azidis3, aziloc, fDOKStat,
fCabrilloExport, uDbUtils, dQTHProfile, uConnectionInfo, znacmech, gline2;
var
Splash : TfrmSplash;
@ -42,10 +43,22 @@ begin
Begin
Writeln('Cqrlog Ver:',cVERSION,' Date:',cBUILD_DATE);
if Application.HasOption('v','version') then exit;
Writeln;
Writeln('-h --help Print this help and exit');
Writeln('-r KEY --remote=KEY Start with remote mode KEY= one of J,M,K');
Writeln(' (for KEY see: NewQSO shortcut keys)');
Writeln('-v --version Print version and exit');
Writeln(' --debug=NR Set debug level to NR');
Writeln;
Writeln('Debug level NRs:');
Writeln(' 0 No debug meesages');
Writeln(' 1 All debug messages');
Writeln(' 2 All debug messages + some additional RBNmonitor & DXCluster debugs');
Writeln('Negative values can be combined (binary bitwise OR)');
Writeln(' -4 Wsjtx remote & Worked grids debug messages');
Writeln(' -8 CW keying & TRXControl debug messages');
Writeln(' -16 Grayline map RBN debug messages');
Writeln;
Exit;
end;

View File

@ -1096,7 +1096,10 @@ begin
Writeln('Cqrlog Ver:',cVERSION,' Date:',cBUILD_DATE);
Writeln('**** DEBUG LEVEL ',fDebugLevel,' ****');
if fDebugLevel=0 then
Writeln('**** CHANGE WITH --debug=1 PARAMETER ****');
Begin
Writeln('**** CHANGE WITH --debug=NR PARAMETER ****');
Writeln('*** Parameter -h or --help for details ***');
end;
Writeln('');
Writeln('OS:');

View File

@ -121,7 +121,7 @@ object frmGrayline: TfrmGrayline
OnPaint = FormPaint
OnShow = FormShow
ShowHint = True
LCLVersion = '2.0.8.0'
LCLVersion = '2.0.12.0'
object sbtnGrayLine: TSpeedButton
Left = 400
Height = 16
@ -168,8 +168,8 @@ object frmGrayline: TfrmGrayline
end
object sbGrayLine: TStatusBar
Left = 0
Height = 21
Top = 227
Height = 19
Top = 229
Width = 419
Panels = <>
end
@ -177,28 +177,44 @@ object frmGrayline: TfrmGrayline
Enabled = False
Interval = 60000
OnTimer = tmrGrayLineTimer
left = 40
top = 32
Left = 40
Top = 32
end
object popGrayLine: TPopupMenu
left = 336
top = 24
OnPopup = popGrayLinePopup
Left = 336
Top = 24
object pumConnect: TMenuItem
Action = acConnect
end
object MenuItem2: TMenuItem
object pumLinkToRBNMonitor: TMenuItem
Action = acLinkToRbnMonitor
end
object pumMnuLine1: TMenuItem
Caption = '-'
end
object pumShowStatusbar: TMenuItem
Action = acShowStatusBar
end
object pumLinkToRBNMonitor: TMenuItem
Action = acLinkToRbnMonitor
object pumShowGreatCircle: TMenuItem
Caption = 'Show GreatCirclePath'
OnClick = pumShowGreatCircleClick
end
object pumMnuLine2: TMenuItem
Caption = '-'
end
object pumClearAllSpots: TMenuItem
Caption = 'Clear all spots'
OnClick = pumClearAllSpotsClick
end
object pumWatchFor: TMenuItem
Caption = 'Watch for: '
OnClick = pumWatchForClick
end
end
object acGrayLine: TActionList
left = 336
top = 80
Left = 336
Top = 80
object acConnect: TAction
Caption = 'Connect to RBN'
OnExecute = acConnectExecute
@ -216,13 +232,13 @@ object frmGrayline: TfrmGrayline
Enabled = False
Interval = 2000
OnTimer = tmrAutoConnectTimer
left = 158
top = 32
Left = 158
Top = 32
end
object tmrRemoveDots: TTimer
Interval = 60000
OnTimer = tmrRemoveDotsTimer
left = 40
top = 32
object tmrSpotDots: TTimer
Enabled = False
OnTimer = tmrSpotDotsTimer
Left = 40
Top = 32
end
end

View File

@ -7,7 +7,7 @@ interface
uses
Classes,SysUtils,LResources,Forms,Controls,Graphics,Dialogs,gline2,TAGraph,
ExtCtrls,Buttons,inifiles,FileUtil,Menus,ActnList,ComCtrls,lNetComponents,
lnet, lclType, LazFileUtils, StrUtils;
lnet, lclType, LazFileUtils, StrUtils, DateUtils, Math;
type
TRBNList = record
@ -22,27 +22,6 @@ type
const
MAX_ITEMS = 300;
type
TRBNThread = class(TThread)
private
lTelnet : TLTelnetClientComponent;
login : String;
watchFor : String;
delAfter : Word;
cs : TRTLCriticalSection;
function ConnectToRBN : Boolean;
function GetEmptyPos : Word;
function SpotterExists(spotter : String) : Word;
procedure lConnect(aSocket: TLSocket);
procedure lDisconnect(aSocket: TLSocket);
procedure lReceive(aSocket: TLSocket);
procedure AddToList(spot : String);
protected
procedure Execute; override;
end;
type
@ -53,8 +32,12 @@ type
acConnect : TAction;
acShowStatusBar : TAction;
acLinkToRbnMonitor: TAction;
pumShowGreatCircle: TMenuItem;
pumMnuLine2: TMenuItem;
pumClearAllSpots: TMenuItem;
pumWatchFor: TMenuItem;
pumConnect : TMenuItem;
MenuItem2 : TMenuItem;
pumMnuLine1 : TMenuItem;
pumShowStatusbar : TMenuItem;
pumLinkToRBNMonitor: TMenuItem;
popGrayLine : TPopupMenu;
@ -62,7 +45,7 @@ type
sbtnGrayLine : TSpeedButton;
tmrAutoConnect : TTimer;
tmrGrayLine: TTimer;
tmrRemoveDots: TTimer;
tmrSpotDots: TTimer;
procedure acConnectExecute(Sender : TObject);
procedure acLinkToRbnMonitorExecute(Sender: TObject);
procedure acShowStatusBarExecute(Sender : TObject);
@ -74,13 +57,27 @@ type
procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormPaint(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure popGrayLinePopup(Sender: TObject);
procedure pumClearAllSpotsClick(Sender: TObject);
procedure pumShowGreatCircleClick(Sender: TObject);
procedure pumWatchForClick(Sender: TObject);
procedure sbtnGrayLineClick(Sender : TObject);
procedure tmrAutoConnectTimer(Sender : TObject);
procedure tmrGrayLineTimer(Sender: TObject);
procedure tmrRemoveDotsTimer(Sender: TObject);
procedure tmrSpotDotsTimer(Sender: TObject);
private
lTelnet : TLTelnetClientComponent;
csRBN : TRTLCriticalSection;
RBNThread : TRBNThread;
login : String;
delAfter : integer;
watchFor : String;
LocalDbg : boolean;
procedure lConnect(aSocket: TLSocket);
procedure lDisconnect(aSocket: TLSocket);
procedure lReceive(aSocket: TLSocket);
function ConnectToRBN : Boolean;
public
RBNSpotList : array[1..MAX_ITEMS] of TRBNList;
@ -90,11 +87,12 @@ type
pfx : String;
rbn_status : String;
procedure kresli;
procedure PlotGreatCircleArcLine(longitude1,latitude1,longitude2,latitude2:extended);
procedure SavePosition;
procedure SynRBN;
function GetEmptyPos : Word;
function SpotterExists(spotter : String) : Word;
procedure RemoveOldSpots;
procedure RemoveOldSpots(RemoveAfter:integer);
procedure AddSpotToList(spot : String);
end;
@ -107,19 +105,17 @@ implementation
uses dUtils, dData, uMyIni, dDXCluster, fNewQSO;
procedure TRBNThread.lConnect(aSocket: TLSocket);
procedure TfrmGrayline.lConnect(aSocket: TLSocket);
begin
frmGrayline.rbn_status := 'Connected';
Synchronize(@frmGrayline.SynRBN)
rbn_status := 'Connected';
end;
procedure TRBNThread.lDisconnect(aSocket: TLSocket);
procedure TfrmGrayline.lDisconnect(aSocket: TLSocket);
begin
frmGrayline.rbn_status := 'Disconnected';
Synchronize(@frmGrayline.SynRBN)
rbn_status := 'Disconnected';
end;
procedure TRBNThread.lReceive(aSocket: TLSocket);
procedure TfrmGrayline.lReceive(aSocket: TLSocket);
const
CR = #13;
LF = #10;
@ -140,19 +136,19 @@ begin
begin
tmp := Copy(Buffer, sStart, sStop - sStart);
tmp := trim(tmp);
if dmData.DebugLevel >=1 then Writeln(tmp);
if LocalDbg then Writeln('Rcvd:',tmp);
itmp := Pos('DX DE',UpperCase(tmp));
if (itmp > 0) or TryStrToFloat(copy(tmp,1,Pos(' ',tmp)-1),f) then
begin
//Writeln('RBN:',tmp);
AddToList(tmp);
if LocalDbg then Writeln(' RBN:',tmp);
AddSpotToList(tmp);
end
else begin
if (Pos('LOGIN',UpperCase(tmp)) > 0) and (cqrini.ReadString('RBN','login','') <> '') then
lTelnet.SendMessage(cqrini.ReadString('RBN','login','')+#13+#10);
if (Pos('please enter your call',LowerCase(tmp)) > 0) and (cqrini.ReadString('RBN','login','') <> '') then
lTelnet.SendMessage(cqrini.ReadString('RBN','login','')+#13+#10);
//Writeln('RBN:',tmp)
if LocalDbg then Writeln('RBN:',tmp)
end;
sStart := sStop + 1;
if sStart > Length(Buffer) then
@ -166,14 +162,14 @@ begin
lTelnet.CallAction
end;
function TRBNThread.GetEmptyPos : Word;
function TfrmGrayline.GetEmptyPos : Word;
var
i : Integer;
begin
Result := 0;
for i:= 1 to MAX_ITEMS do
begin
if frmGrayline.RBNSpotList[i].band='' then
if RBNSpotList[i].band='' then
begin
Result := i;
break
@ -181,14 +177,14 @@ begin
end
end;
function TRBNThread.SpotterExists(spotter : String) : Word;
function TfrmGrayline.SpotterExists(spotter : String) : Word;
var
i : Integer;
begin
Result := 0;
for i:= 1 to MAX_ITEMS do
begin
if frmGrayline.RBNSpotList[i].spotter=spotter then
if RBNSpotList[i].spotter=spotter then
begin
Result := i;
break
@ -196,145 +192,7 @@ begin
end
end;
procedure TRBNThread.AddToList(spot : String);
procedure GetRealCoordinate(lat,long : String; var latitude, longitude: Currency);
var
s,d : String;
begin
s := lat;
d := long;
if ((Length(s)=0) or (Length(d)=0)) then
begin
longitude := 0;
latitude := 0;
exit
end;
if s[Length(s)] = 'S' then
s := '-' +s ;
s := copy(s,1,Length(s)-1);
if pos('.',s) > 0 then
s[pos('.',s)] := FormatSettings.DecimalSeparator;
if not TryStrToCurr(s,latitude) then
latitude := 0;
if d[Length(d)] = 'W' then
d := '-' + d ;
d := copy(d,1,Length(d)-1);
if pos('.',d) > 0 then
d[pos('.',d)] := FormatSettings.DecimalSeparator;
if not TryStrToCurr(d,longitude) then
longitude := 0;
if dmData.DebugLevel>=4 then
begin
//Writeln('Lat: ',latitude);
//Writeln('Long: ',longitude);
end;
end;
procedure ParseSpot(spot : String; var spotter, dxstn, freq, mode, stren : String);
var
i : Integer;
y : Integer;
b : Array of String[50];
p : Integer=0;
begin
SetLength(b,1);
for i:=1 to Length(spot) do
begin
if spot[i]<>' ' then
b[p] := b[p]+spot[i]
else begin
if (b[p]<>'') then
begin
inc(p);
SetLength(b,p+1)
end
end
end;
spotter := b[2];
i := pos('-', spotter);
if i > 0 then
spotter := copy(spotter, 1, i-1);
dxstn := b[4];
freq := b[3];
mode := b[5];
stren := b[6]
end;
var
spotter : String;
call : String;
stren : String;
freq : String;
lat : String;
long : String;
index : Word;
band : String;
tmp : Integer;
wCall : String;
mode : String;
latitude, longitude: Currency;
begin
ParseSpot(spot, spotter, call, freq, mode, stren);
if watchFor<>'' then
begin
if Pos('*',watchFor) > 0 then //ZL*
begin
wCall := copy(watchFor,1,Pos('*',watchFor)-1);
if (Pos(wCall,call) <> 1) then //all callsign started with ZL
exit
end
else begin
if (call <> watchFor) then exit;
end
end;
if dmData.DebugLevel>=1 then
begin
Writeln('Spotter:',spotter,'*');
Writeln('Signal: ',stren,'*');
Writeln('*Freq: ',freq,'*')
end;
dmDXCluster.id_country(spotter,lat,long);
index := SpotterExists(spotter);
if index = 0 then //spotter doesn't exist, we need new position
index := GetEmptyPos;
if index = 0 then
begin
Writeln('CRITICAL ERROR! THIS SHOULD NOT HAPPEN, RBN LIST IS FULL');
exit
end;
band := dmDXCluster.GetBandFromFreq(freq,True);
frmGrayline.RBNSpotList[index].band := band;
frmGrayline.RBNSpotList[index].spotter := spotter;
frmGrayline.RBNSpotList[index].time := now;
if TryStrToInt(stren,tmp) then
frmGrayline.RBNSpotList[index].strengt := tmp
else
frmGrayline.RBNSpotList[index].strengt := 0;
GetRealCoordinate(lat,long,latitude, longitude);
frmGrayline.RBNSpotList[index].lat := latitude;
frmGrayline.RBNSpotList[index].long := longitude;
if dmData.DebugLevel>=1 then
begin
Writeln('call: ',call);
Writeln('spotter:',spotter);
Writeln('stren: ',stren);
Writeln('freq: ',freq);
Writeln('band: ',dmDXCluster.GetBandFromFreq(freq,True));
Writeln('Lat: ',lat);
Writeln('Long: ',long)
end;
end;
function TRBNThread.ConnectToRBN : Boolean;
function TfrmGrayline.ConnectToRBN : Boolean;
var
server : String;
port : Integer;
@ -349,7 +207,7 @@ begin
if not TryStrToInt(tmp,port) then
port := 7000; //default value
if dmData.DebugLevel>=1 then Writeln('Server:',server,' Port:',port);
if LocalDbg then Writeln('Server:',server,' Port:',port);
lTelnet.OnConnect := @lConnect;
lTelnet.OnDisconnect := @lDisconnect;
@ -362,66 +220,11 @@ begin
on E : Exception do
begin
Result := False;
if dmData.DebugLevel>=1 then Writeln('Can not connect to RBN! ',E.Message)
if LocalDbg then Writeln('Can not connect to RBN! ',E.Message)
end
end
end;
procedure TRBNThread.Execute;
begin
if not ConnectToRBN then
begin
if dmData.DebugLevel>=1 then Writeln('Can not connect to RBN!');
FreeAndNil(lTelnet);
exit
end;
InitCriticalSection(cs);
while not Terminated do
begin
EnterCriticalsection(cs);
try
login := cqrini.ReadString('RBN','login','');
watchFor := cqrini.ReadString('RBN','watch','');
delAfter := cqrini.ReadInteger('RBN','deleteAfter',60)
finally
LeaveCriticalsection(cs)
end;
//RemoveOldSpots; done now by tmrRemoveDots
Synchronize(@frmGrayline.SynRBN);
sleep(1000)
end;
lTelnet.Disconnect(true);
DoneCriticalsection(cs)
end;
procedure TfrmGrayline.FormCreate(Sender: TObject);
var
ImageFile : String;
i : Integer;
begin
InitCriticalSection(csRBN);
RBNThread := nil;
for i:=1 to MAX_ITEMS do
RBNSpotList[i].band := '';
ImageFile := dmData.HomeDir+'images'+PathDelim+'grayline.bmp';
if not FileExists(ImageFile) then
ImageFile := ExpandFileNameUTF8('..'+PathDelim+'share'+PathDelim+'cqrlog'+
PathDelim+'images'+PathDelim+'grayline.bmp');
ob:=new(Pgrayline,init(ImageFile));
tmrRemoveDots.Interval:= cqrini.ReadInteger('RBN','deleteAfter',60)*1000;
tmrRemoveDots.Enabled:=true;
end;
procedure TfrmGrayline.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
if RBNThread<>nil then RBNThread.Terminate;
cqrini.WriteBool('Grayline','Statusbar',sbGrayLine.Visible);
dmUtils.SaveWindowPos(frmGrayline)
end;
procedure TfrmGrayline.acShowStatusBarExecute(Sender : TObject);
begin
if acShowStatusBar.Checked then
@ -443,16 +246,17 @@ begin
else begin
if acConnect.Caption = 'Disconnect' then
begin
RBNThread.Terminate;
acConnect.Caption := 'Connect to RBN';
sbGrayLine.SimpleText := 'Disconnected';
pumLinkToRBNMonitor.Enabled:=true;
if ltelnet <> nil then
Begin
lTelnet.Disconnect;
sleep(100);
FreeAndNil(lTelnet);
rbn_status := 'Disconnected';
end;
end
else begin
acLinkToRbnMonitor.Checked :=false;
RBNThread := TRBNThread.Create(True);
RBNThread.FreeOnTerminate := True;
RBNThread.Start
ConnectToRBN;
end
end
end;
@ -466,20 +270,77 @@ begin
rbn_status := 'Linked to RBNMonitor'
else
rbn_status := 'Disconnected';
sbGrayLine.SimpleText := rbn_status;
end;
procedure TfrmGrayline.FormCreate(Sender: TObject);
var
ImageFile : String;
i : Integer;
begin
InitCriticalSection(csRBN);
tmrSpotDots.Enabled:=false;
for i:=1 to MAX_ITEMS do
begin
RBNSpotList[i].band := '';
RBNSpotList[i].spotter := '';
RBNSpotList[i].time := DateTimeToUnix(now);
RBNSpotList[i].strengt := 0;
RBNSpotList[i].lat := 0;
RBNSpotList[i].long := 0;
end;
ImageFile := dmData.HomeDir+'images'+PathDelim+'grayline.bmp';
if not FileExists(ImageFile) then
ImageFile := ExpandFileNameUTF8('..'+PathDelim+'share'+PathDelim+'cqrlog'+
PathDelim+'images'+PathDelim+'grayline.bmp');
ob:=new(Pgrayline,init(ImageFile));
//set debug rules for this form
// bit 5, %10000, ---> -16 for routines in this form
LocalDbg := dmData.DebugLevel >= 1 ;
if dmData.DebugLevel < 0 then
LocalDbg := LocalDbg or ((abs(dmData.DebugLevel) and 16) = 16 );
end;
procedure TfrmGrayline.FormShow(Sender: TObject);
begin
dmUtils.LoadWindowPos(frmGrayline);
sbGrayLine.Visible := cqrini.ReadBool('Grayline','Statusbar',True);
pumShowGreatCircle.Checked:= cqrini.ReadBool('Grayline','GreatCircle',False);
acShowStatusBar.Checked := sbGrayLine.Visible;
rbn_status :='Disconnected';
sbGrayLine.SimpleText := rbn_status;
tmrGrayLine.Enabled := True;
tmrGrayLineTimer(nil);
tmrAutoConnect.Enabled := True;
delAfter := cqrini.ReadInteger('RBN','deleteAfter',60);
tmrSpotDots.Interval :=1000; //remove Spots(DOts) timer will always run 1 sec period.
tmrSpotDots.Enabled :=true;
end;
procedure TfrmGrayline.FormCloseQuery(Sender: TObject; var CanClose: boolean);
begin
tmrGrayLine.Enabled := False;
tmrAutoConnect.Enabled:=False;
tmrRemoveDots.Enabled:=False;
sleep(100)
tmrSpotDots.Enabled:=False;
if ltelnet <> nil then
Begin
lTelnet.Disconnect;
sleep(100);
FreeAndNil(lTelnet);
end;
RemoveOldSpots(0);
end;
procedure TfrmGrayline.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
cqrini.WriteBool('Grayline','Statusbar',sbGrayLine.Visible);
dmUtils.SaveWindowPos(frmGrayline)
end;
procedure TfrmGrayline.FormDestroy(Sender: TObject);
begin
if dmData.DebugLevel>=1 then Writeln('Closing GrayLine window');
if LocalDbg then Writeln('Closing GrayLine window');
dispose(ob,done);
DoneCriticalsection(csRBN)
end;
@ -514,16 +375,40 @@ begin
ob^.kresli(r,Canvas)
end;
procedure TfrmGrayline.FormShow(Sender: TObject);
procedure TfrmGrayline.popGrayLinePopup(Sender: TObject);
begin
dmUtils.LoadWindowPos(frmGrayline);
sbGrayLine.Visible := cqrini.ReadBool('Grayline','Statusbar',True);
acShowStatusBar.Checked := sbGrayLine.Visible;
rbn_status :='Disconnected';
sbGrayLine.SimpleText := rbn_status;
tmrGrayLine.Enabled := True;
tmrGrayLineTimer(nil);
tmrAutoConnect.Enabled := True
watchFor := cqrini.ReadString('RBN','watch','');
pumWatchFor.Caption:='Watch for: '+watchFor;
end;
procedure TfrmGrayline.pumClearAllSpotsClick(Sender: TObject);
begin
tmrSpotDots.Enabled:=False;
RemoveOldSpots(0);
delAfter := cqrini.ReadInteger('RBN','deleteAfter',60);
tmrSpotDots.Enabled:=true;
end;
procedure TfrmGrayline.pumShowGreatCircleClick(Sender: TObject);
begin
pumShowGreatCircle.Checked:= not pumShowGreatCircle.Checked;
cqrini.WriteBool('Grayline','GreatCircle',pumShowGreatCircle.Checked);
end;
procedure TfrmGrayline.pumWatchForClick(Sender: TObject);
var inpWF:string;
begin
inpWF := cqrini.ReadString('RBN','watch','');
if InputQuery('Watch for:','Enter up- or lowcase callsign or prefix and asterisk like OK2* ', false, inpWF) then
Begin
EnterCriticalsection(csRBN);
watchFor:= uppercase(inpWF);
pumWatchFor.Caption:='Watch for: '+watchFor;
cqrini.WriteString('RBN','watch',watchFor);
LeaveCriticalsection(csRBN);
RemoveOldSpots(0);
end;
end;
procedure TfrmGrayline.sbtnGrayLineClick(Sender : TObject);
@ -545,7 +430,9 @@ begin
exit;
end;
if cqrini.ReadBool('RBN','AutoConnect',False) and (cqrini.ReadString('RBN','login','') <> '')
and (RBNThread = nil) then acConnect.Execute;
and (lTelnet = nil) then acConnect.Execute;
tmrAutoConnect.Enabled:=False; //job is done, nex initiate when FormShow run
end;
procedure TfrmGrayline.tmrGrayLineTimer(Sender: TObject);
@ -553,9 +440,32 @@ begin
Refresh
end;
procedure TfrmGrayline.tmrRemoveDotsTimer(Sender: TObject);
procedure TfrmGrayline.tmrSpotDotsTimer(Sender: TObject);
begin
RemoveOldSpots
tmrSpotDots.Enabled:=false;
dec(delAfter);
if delAfter < 1 then
Begin
delAfter := cqrini.ReadInteger('RBN','deleteAfter',60);
RemoveOldSpots(delAfter);
end;
sbGrayLine.SimpleText := rbn_status;
if rbn_status='Connected' then
Begin
acConnect.Caption := 'Disconnect';
pumLinkToRBNMonitor.Enabled:=false;
end
else
Begin
acConnect.Caption := 'Connect to RBN';
pumLinkToRBNMonitor.Enabled:=True;
end;
SynRBN;
tmrSpotDots.Enabled:=true;
end;
procedure TfrmGrayline.kresli;
@ -568,7 +478,7 @@ begin
if (s='') or (d='') then
dmUtils.GetCoordinate(pfx,lat1,long1)
else begin
if s[Length(s)] = 'S' then //pokud je tam S musi byt udaj zaporny
if s[Length(s)] = 'S' then //if S is there, the data must be negative
s := '-' +s ;
s := copy(s,1,Length(s)-1);
if pos('.',s) > 0 then
@ -576,7 +486,7 @@ begin
if not TryStrToCurr(s,lat1) then
lat1 := 0;
if d[Length(d)] = 'W' then //pokud je tam W musi byt udaj zaporny
if d[Length(d)] = 'W' then // if there is a W it must be negative
d := '-' + d ;
d := copy(d,1,Length(d)-1);
if pos('.',d) > 0 then
@ -587,11 +497,105 @@ begin
s := '';
d := '';
dmUtils.CoordinateFromLocator(dmUtils.CompleteLoc(my_loc),lat,long);
lat := lat*-1;
lat1 := lat1*-1;
ob^.jachcucaru(true,long,lat,long1,lat1);
if pumShowGreatCircle.Checked then
PlotGreatCircleArcLine(long,lat,long1,lat1)
else
ob^.jachcucaru(true,long,lat*-1,long1,lat1*-1);
Refresh
end;
procedure TfrmGrayline.PlotGreatCircleArcLine(longitude1,latitude1,longitude2,latitude2:extended);
{ Ref: http://www.movable-type.co.uk/scripts/latlong.html }
Const
Basestep = 0.0174532925; //1 degree in radians
PolarStep = 0.00174532925; // base/10
var
lat1,lat2,lon1,lon2,
latFrom,lonFrom,
step,
dist,
bearing : extended;
CountLimit : integer;
BearingIsPositive : boolean;
//-------------------------------------------------------------------
procedure LatLongToDistance(const lat0, long0, lat1, long1: extended;
var dist, bearing: extended);
var
R: double = 6371000; // earth radius in meters
dlat, dlong, slat, slong, a, c, x, y: double;
begin
// dist
dlat := lat1 - lat0;
dlong := long1 - long0;
slat := Sin(0.5 * dlat);
slong := Sin(0.5 * dlong);
a := slat * slat + Cos(lat0) * Cos(lat1) * slong * slong;
c := 2.0 * ArcTan2(Sqrt(a), Sqrt(1.0-a));
dist := R * c;
// bearing
y := Sin(long1 - long0) * Cos(lat1);
x := Cos(lat0) * Sin(lat1) - Sin(lat0) * Cos(lat1) * Cos(long1 - long0);
bearing := ArcTan2(y, x);
end;
//-------------------------------------------------------------------
Begin
ob^.GC_line_clear;
if LocalDbg then
begin
writeln ('-------------------------------------------------------------------');
writeln ('Start:',round(latitude1),' ',round(longitude1),' ',round(latitude2),' ',round(longitude2));
end;
step := BaseStep;
dist :=0;
bearing :=0;
longitude1 := degToRad(longitude1);
latitude1 := degToRad(latitude1);
longitude2 := degToRad(longitude2);
latitude2 := degToRad(latitude2);
LatLongToDistance(latitude1, longitude1, latitude2, longitude2, dist, bearing);
BearingIsPositive := (bearing > 0);
CountLimit:=ob^.GC_Points_Max;
while (CountLimit > 0) do
Begin
latFrom:=latitude1;
lonFrom:=longitude1;
dec(CountLimit);
if abs(latFrom) > 1.45 then
step:=PolarStep
else
step:=BaseStep;
LatLongToDistance(latFrom, lonFrom, latitude2, longitude2, dist, bearing);
if ((bearing > 0) <> BearingIsPositive) then CountLimit:=0;;
if LocalDbg then
writeln ('Dist:',round(dist * 0.001) ,' Bearing:',round(radTodeg(bearing)));
longitude1 := longitude1 + (sin(bearing) * step) / cos(latitude1);
latitude1 := latitude1 + (cos(bearing) * step);
if longitude1 < -Pi then longitude1 := 2*Pi+longitude1;
if longitude1 > Pi then longitude1 := -2*Pi+longitude1;
if latitude1 > Pi/2 then latitude1:= Pi/2 - (latitude1-Pi/2);
if latitude1 < -Pi/2 then latitude1:= -Pi/2 - (latitude1+Pi/2);
if LocalDbg then
writeln ('To: ',Round(RadToDeg(latitude1)),' ',Round(RadToDeg(longitude1)),' (',Round(RadToDeg(latFrom)),' ',Round(RadToDeg(lonFrom)),')');
// 170 degrees = 2,96705972839 rad
if not (((lonFrom > 2.96705972839) and (longitude1 < -2.96705972839)) //right crossing
or ((lonFrom < -2.96705972839) and (longitude1 > 2.96705972839)) //left crossing
) then
ob^.GC_line_part(RadToDeg(lonFrom),RadToDeg(latFrom)*-1,RadToDeg(longitude1),RadToDeg(latitude1)*-1);
end;
end;
procedure TfrmGrayline.SavePosition;
begin
@ -605,36 +609,30 @@ procedure TfrmGrayline.SynRBN;
var
i : Integer;
c : TColor;
CqrBand:String;
begin
sbGrayLine.SimpleText := rbn_status;
if rbn_status='Connected' then
Begin
acConnect.Caption := 'Disconnect';
pumLinkToRBNMonitor.Enabled:=false;
end
else
Begin
acConnect.Caption := 'Connect to RBN';
pumLinkToRBNMonitor.Enabled:=True;
end;
ob^.body_smaz;
CqrBand := dmUtils.GetBandFromFreq(frmNewQSO.cmbFreq.Text);
for i:=1 to MAX_ITEMS do
begin
if (RBNSpotList[i].band='') then
if (RBNSpotList[i].band='') then //skip empty
Continue;
if (band <> '') then
if (CqrBand = '') or (CqrBand<>RBNSpotList[i].band) then //skip if no cqrlog band or it differs from spot band
Continue;
if LocalDbg then
begin
if band<>RBNSpotList[i].band then
Continue
writeln('Cqr:band: ',cqrband);
Writeln('Syn:spotter:',RBNSpotList[i].spotter);
Writeln('Syn:stren: ',RBNSpotList[i].strengt);
Writeln('Syn:band: ',RBNSpotList[i].band);
Writeln('Syn:lat: ',RBNSpotList[i].lat);
Writeln('Syn:long: ',RBNSpotList[i].long);
end;
{
Writeln('Syn:spotter:',RBNSpotList[i].spotter);
Writeln('Syn:stren: ',RBNSpotList[i].strengt);
Writeln('Syn:band: ',RBNSpotList[i].band);
Writeln('Syn:lat: ',RBNSpotList[i].lat);
Writeln('Syn:long: ',RBNSpotList[i].long);
}
case RBNSpotList[i].strengt of
11..20 : c := cqrini.ReadInteger('RBN','20db',clPurple);
21..30 : c := cqrini.ReadInteger('RBN','30db',clMaroon);
@ -642,59 +640,28 @@ begin
else
c := cqrini.ReadInteger('RBN','10db',clWhite)
end; //case
//procedure body_add(typ:byte;x1,y1,x2,y2:extended;popis:string;barva:tcolor;vel_bodu:longint);
ob^.body_add(3,RBNSpotList[i].long,RBNSpotList[i].lat*-1,RBNSpotList[i].long,RBNSpotList[i].lat*-1,RBNSpotList[i].spotter,c,1);
end;
Refresh
end;
function TfrmGrayline.GetEmptyPos : Word;
procedure TfrmGrayline.RemoveOldSpots(RemoveAfter:integer); //setting RemoveAfter:=0 removes all Spots
var
i : Integer;
begin
Result := 0;
for i:= 1 to MAX_ITEMS do
begin
if frmGrayline.RBNSpotList[i].band='' then
begin
Result := i;
break
end
end
end;
i : Integer;
time,
SpotTime: int64;
function TfrmGrayline.SpotterExists(spotter : String) : Word;
var
i : Integer;
begin
Result := 0;
for i:= 1 to MAX_ITEMS do
begin
if frmGrayline.RBNSpotList[i].spotter=spotter then
begin
Result := i;
break
end
end
end;
procedure TfrmGrayline.RemoveOldSpots;
var
i : Integer;
time : TDateTime;
delAfter: word;
begin
tmrRemoveDots.Enabled:=false;
delAfter := cqrini.ReadInteger('RBN','deleteAfter',60);
tmrRemoveDots.Interval:=delAfter*1000;
time := now;
time := DateTimeToUnix(now);
EnterCriticalsection(csRBN);
for i:=1 to MAX_ITEMS do
begin
if frmGrayline.RBNSpotList[i].time+delAfter/86400 < time then
frmGrayline.RBNSpotList[i].band := ''
end;
begin
if ((time - RBNSpotList[i].time) > RemoveAfter) then
RBNSpotList[i].band :='';
end;
SynRBN;
tmrRemoveDots.Enabled:=true;
LeaveCriticalsection(csRBN);
end;
procedure TfrmGrayline.AddSpotToList(spot : String);
@ -726,10 +693,10 @@ procedure TfrmGrayline.AddSpotToList(spot : String);
d[pos('.',d)] := FormatSettings.DecimalSeparator;
if not TryStrToCurr(d,longitude) then
longitude := 0;
if dmData.DebugLevel>=4 then
if LocalDbg then
begin
//Writeln('Lat: ',latitude);
//Writeln('Long: ',longitude);
Writeln('Lat: ',latitude);
Writeln('Long: ',longitude);
end;
end;
@ -748,7 +715,6 @@ procedure TfrmGrayline.AddSpotToList(spot : String);
end;
var
watchFor: String;
spotter : String;
call : String;
stren : String;
@ -778,7 +744,7 @@ begin
end
end;
if dmData.DebugLevel>=1 then
if LocalDbg then
begin
Writeln('Spotter:',spotter,'*');
Writeln('Signal: ',stren,'*');
@ -800,7 +766,7 @@ begin
frmGrayline.RBNSpotList[index].band := band;
frmGrayline.RBNSpotList[index].spotter := spotter;
frmGrayline.RBNSpotList[index].time := now;
frmGrayline.RBNSpotList[index].time := DateTimeToUnix(now);
if TryStrToInt(stren,tmp) then
frmGrayline.RBNSpotList[index].strengt := tmp
else
@ -809,17 +775,18 @@ begin
GetRealCoordinate(lat,long,latitude, longitude);
frmGrayline.RBNSpotList[index].lat := latitude;
frmGrayline.RBNSpotList[index].long := longitude;
if dmData.DebugLevel>=1 then
if LocalDbg then
begin
Write('call: ',call);
Write(' spotter:',spotter);
Write(' stren: ',stren);
Write(' freq: ',freq);
Write(' band: ',dmDXCluster.GetBandFromFreq(freq,True));
Write(' Lat: ',lat);
Writeln(' Long: ',long)
Write('Add call: ',call);
Write('Add spotter:',spotter);
Write('Add stren: ',stren);
Write('Add freq: ',freq);
Write('Add band: ',band);
Write('Add Lat: ',lat);
Writeln('Add Long: ',long)
end;
SynRBN;
end;
end.

View File

@ -1243,9 +1243,11 @@ procedure TfrmNewQSO.ClearGrayLineMapLine;
var
lat,long :currency;
Begin
frmGrayLine.ob^.GC_line_clear;
dmUtils.CoordinateFromLocator(dmUtils.CompleteLoc(CurrentMyLoc),lat,long);
lat := lat*-1;
frmGrayLine.ob^.jachcucaru(true,long,lat,long,lat);
frmGrayLine.ob^.jachcucaru(true,long,lat,long+0.03,lat+0.03); //trying to make own qth dot a bit bigger
//the Grayline window zoom affects to visibility anyhow
frmGrayline.Refresh;
end;

View File

@ -38,30 +38,38 @@ type
const body_popis_max=30;
type Tcarobod=record
typ:byte; // 0 - nic;1 cara, 2 bod ctverecek , 3 bod krizek
typ:byte; // 0 - nothing, 1 square, 2 square points, 3 cross points
x1,y1,x2,y2:extended;
popis:string[body_popis_max];
barva:Tcolor;
vel_bodu:longint;
popis:string[body_popis_max]; //bodu_popis = points_list
barva:Tcolor; //barva = color
vel_bodu:longint; //vel_bodu ?? bodu = point
end;
const body_max=128;
type TGC_point=record
La1,Lo1,La2,Lo2 : double;
end;
var star_time_u:extended;
type
Tgrayline=object
const GC_Points_Max = 500;
constructor init(naz_sou:string);
destructor done;
procedure VypocitejSunClock(cas:Tdatetime);
procedure kresli(r:Trect;can:Tcanvas); {vykresli v pozadovanych rozmerech}
procedure kresli1(x1,y1:longint;can:Tcanvas); {vykresli 1:1, zadavan je "jen" levy horni roh}
procedure kresli(r:Trect;can:Tcanvas); {kresli = line draw in the required dimensions }
procedure kresli1(x1,y1:longint;can:Tcanvas); {draw 1: 1, the input is "only" the upper left corner}
procedure jachcucaru(en:boolean;x1,y1,x2,y2:extended);
procedure body_add(typ:byte;x1,y1,x2,y2:extended;popis:string;barva:tcolor;vel_bodu:longint);
procedure body_smaz;
procedure GC_line_part(x1,y1,x2,y2:double);
procedure GC_line_clear;
private
nrd:boolean; // potrebuje prekreslit (probehl novy vypocet)
nrd:boolean; //needs to redraw (a new calculation has been made)
chcipni:boolean;
ziju:boolean;
@ -76,13 +84,16 @@ type
carax1,carax2,caray1,caray2:extended;
caraen:boolean;
obrp:TLazIntfImage; // predloha... 1-z disku
obrA,obrT:TLazIntfImage; // obra - zde vse kreslit
obrp:TLazIntfImage; // template ... 1-of-disk template ... 1-of-disk
obrA,obrT:TLazIntfImage; //picture - draw everything here
obmap: TBitmap;
body:array[0..body_max] of Tcarobod;
body_poc:longint;
GC_point:array[0..GC_points_Max] of TGC_point;
GCpointer:longint;
function calc_horizontalx(var coord:t_coord; date:TDateTime; z:longint;latitude: extended):longint;
end;
Pgrayline=^Tgrayline;
@ -507,6 +518,7 @@ var e,z:longint;
end;
body_poc:=0;
GCpointer:=0;
poslednicas:=now-1000000;
nrd:=false;
@ -681,7 +693,7 @@ begin
end;
procedure Tgrayline.kresli(r:Trect;can:Tcanvas);
procedure Tgrayline.kresli(r:Trect;can:Tcanvas); //kresli =draw
var z,x,c:longint;
ze,zez,ze2,zez2,ze2s,zez2s:extended;
@ -689,7 +701,7 @@ var
xptr:^byte;
//-----------------------------------------------------------
procedure cmarniu(x1,y1,x2,y2:longint);
begin
can.pen.color:=clblack;
@ -701,7 +713,8 @@ var
can.moveto(x1,y1);
can.lineto(x2,y2);
end;
//-----------------------------------------------------------
procedure cmarni(x1,y1,x2,y2:extended;roh:boolean);
var dx,dy,ax,ay:extended;
begin
@ -726,6 +739,7 @@ var
end;
end;
//-----------------------------------------------------------
procedure bod_cmarniu(x1,y1,x2,y2:longint;b:Tcarobod);
var vb:longint;
begin
@ -775,8 +789,7 @@ var
end;
end;
//-----------------------------------------------------------
procedure bod_cmarni(b:Tcarobod);
var dx,dy,ax,ay:extended;
begin
@ -790,20 +803,20 @@ var
round(ax+round(b.x2*dx/360)),round(ay+round(b.y2*dy/180)),b);
end;
//-----------------------------------------------------------
begin
begin
if chcipni then exit;
if ((r.left-r.right<>rold.left-rold.right) or (r.top-r.bottom<>rold.top-rold.bottom))
and (r.right-r.left+1>obsi) then nrd:=true;
if nrd then
if nrd then
begin
obrA.CopyPixels(obrP);
//ze2:=0.79; //zadání jak bude tmavý obrázek - R a G
//zez2:=0.90; //zadání jak bude tmavý obrázek - modry kanal
//ze2:=0.79; // specify how the dark image will be - R and G
//zez2:=0.90; // specify how the dark image will be - blue channel
ze2 := 1.7;
zez2 := 1.0;
@ -850,31 +863,42 @@ var
obmap.LoadFromIntfImage(obrT);
end;
// r.right:=r.left;
if r.left=r.right then
begin
r.Right:=r.left+obsi-1;
r.bottom:=r.top+obvy-1;
Can.Draw(r.left,r.top,obmap);
end
else
Can.StretchDraw(r,obmap);
if caraen then
begin
cmarni(carax1,caray1,carax2,caray2,true);
// can.Font.Color:=clyellow;
// can.TextOut(10,10,inttostr(round(carax1))+':'+inttostr(round(caray1)));
// can.TextOut(10,20,inttostr(round(carax2))+':'+inttostr(round(caray2)));
end;
for z:=0 to body_poc-1 do
begin
bod_cmarni(body[z]);
end;
//r.right:=r.left;
if r.left=r.right then
begin
r.Right:=r.left+obsi-1;
r.bottom:=r.top+obvy-1;
Can.Draw(r.left,r.top,obmap);
end
else
Can.StretchDraw(r,obmap);
if caraen then
begin
cmarni(carax1,caray1,carax2,caray2,true);
// can.Font.Color:=clBlack;
// can.TextOut(10,10,' '+inttostr(round(carax1))+':'+inttostr(round(caray1))+' ');
// can.TextOut(10,30,' '+inttostr(round(carax2))+':'+inttostr(round(caray2))+' ');
end;
if GCpointer > 0 then
begin
for z:=0 to GCpointer-1 do
begin
cmarni(GC_point[z].La1, GC_point[z].Lo1, GC_point[z].La2, GC_point[z].Lo2, false);
end;
end;
for z:=0 to body_poc-1 do
begin
bod_cmarni(body[z]);
end;
nrd:=false;
end;
end;
procedure Tgrayline.kresli1(x1,y1:longint;can:Tcanvas);
procedure Tgrayline.kresli1(x1,y1:longint;can:Tcanvas); //kresli =draw
var r:Trect;
begin
if chcipni then exit;
@ -885,10 +909,10 @@ var r:Trect;
kresli(r,can);
end;
procedure Tgrayline.jachcucaru(en:boolean;x1,y1,x2,y2:extended);
procedure Tgrayline.jachcucaru(en:boolean;x1,y1,x2,y2:extended); //jachcucaru = ?????
begin
if chcipni then exit;
caraen:=en;
if chcipni then exit; //chcipni = "die"
caraen:=en; //cara = "line"
if (abs(y1)>90) or (abs(y2)>90) then
begin
caraen:=false;exit;
@ -931,9 +955,29 @@ procedure Tgrayline.body_add(typ:byte;x1,y1,x2,y2:extended;popis:string;barva:tc
end;
end;
procedure Tgrayline.body_smaz;
procedure Tgrayline.body_smaz; //smaz = delete
begin
body_poc:=0;
end;
procedure Tgrayline.GC_line_part(x1,y1,x2,y2:double);
Begin
if chcipni then exit; //chcipni = "die"
if GCpointer < GC_Points_max then
begin
GC_point[GCpointer].La1:=x1;
GC_point[GCpointer].Lo1:=y1;
GC_point[GCpointer].La2:=x2;
GC_point[GCpointer].Lo2:=y2;
inc(GCpointer);
end;
end;
procedure Tgrayline.GC_line_clear;
Begin
GCpointer:=0;
end;
end.

View File

@ -11,7 +11,7 @@ const
cBUILD = 1;
cBUILD_DATE = '2022-01-03';
cBUILD_DATE = '2022-01-20';
implementation