Merge branch 'sd-rotator-support' into 'master'

Rotator support

See merge request gridtracker.org/gridtracker!244

If this is changing anything in the UI or operational behavior, please prepare to update the wiki!
merge-requests/241/merge
T Loomis 2022-11-13 20:22:58 +00:00
commit 4deeacbbc3
10 zmienionych plików z 210 dodań i 30 usunięć

Wyświetl plik

@ -60,6 +60,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<script src="./lib/shadow.js" type="text/javascript"></script>
<script src="./lib/gtws.js" type="text/javascript"></script>
<script src="./lib/pota.js" type="text/javascript"></script>
<script src="./lib/services/pstrotator.js" type="text/javascript"></script>
<script src="./lib/gt.js" type="text/javascript"></script>
</head>
@ -2073,9 +2074,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</div>
</div>
<div id="logSettingsDiv" class="settingsTabcontent">
<div id="LoadAdifOnStartupDiv"
style="left: 0; padding: 1px; overflow: auto; overflow-x: hidden; display: inline-block; height: 602px"
class="roundBorder">
<table class="darkTable" align="center">
<tr>
<th data-i18n="settings.logging.tableheader.source">Source/Sync</th>
@ -2438,7 +2436,33 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<td></td>
</tr>
</table>
</div>
<h2 data-i18n="settings.logging.other.title">Other Services</h2>
<table class="darkTable" align="center">
<tr>
<th data-i18n="settings.logging.otherheader.service">Service</th>
<th data-i18n="settings.logging.otherheader.active">Active?</th>
<th data-i18n="settings.logging.otherheader.details">Details</th>
</tr>
<tr>
<td data-i18n="settings.logging.pstrotator.label">CatRotator / PstRotator</td>
<td>
<input type="checkbox" checked="false" class="inputTextValue" id="pstrotatorCheckBox"
onclick=" ValidateIPaddress(pstrotatorIpInput, this); ValidatePort(pstrotatorPortInput, this, null ); pstrotatorServiceChanged(); " />
</td>
<td>
<label data-i18n="settings.logging.pstrotator.details.IP" for="pstrotastorIpInput">IP</label>
<input id="pstrotatorIpInput" type="text" class="inputTextValue" maxlength="15" size="15"
onkeypress='return validIpKeys(event.charCode);'
oninput="ValidateIPaddress(this, pstrotatorCheckBox); pstrotatorServiceChanged(); " />
<label data-i18n="settings.logging.pstrotator.details.Port" for="pstrotatorPortInput">UDP Port</label>
<input id="pstrotatorPortInput" type="text" class="inputTextValue" maxlength="5" size="5" onkeypress='return
validNumberKeys(event.charCode);' oninput="ValidatePort(this, pstrotatorCheckBox, null );
pstrotatorServiceChanged(); " />
</td>
</tr>
</table>
</div>
<div id="callRosterDiv" class="settingsTabcontent">
<div class="mapItem">
@ -3154,4 +3178,4 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<div id="selectNodeDiv" style="-webkit-user-select: text; user-select: text; display: block; z-index: -10000"></div>
</body>
</html>
</html>

Wyświetl plik

@ -433,4 +433,4 @@
</div>
</body>
</html>
</html>

Wyświetl plik

@ -344,6 +344,13 @@
"settings.logging.HRDLogbook.source": "HRD Logbook",
"settings.logging.HRDLogbook.details.IP": "IP地址",
"settings.logging.HRDLogbook.details.Port": "埠號",
"settings.logging.other.title": "Other Services",
"settings.logging.otherheader.service": "Service",
"settings.logging.otherheader.active": "Active?",
"settings.logging.otherheader.details": "Details",
"settings.logging.pstrotator.label": "CatRotator / PstRotator",
"settings.logging.pstrotator.details.IP": "IP",
"settings.logging.pstrotator.details.Port": "UDP Port",
"settings.callroster.AlwaysOnTop.label": "視窗始終在最上層",
"settings.callroster.AlwaysOnTop.hover": "將呼叫清單置於其他視窗之上",
"settings.callroster.MaxAge.label": "呼叫清單最大時效",
@ -995,6 +1002,7 @@
"roster.menu.RosterMode": "Roster Mode",
"roster.menu.Lookup": "Lookup",
"roster.menu.GenMesg": "Gen Msgs",
"roster.menu.AimRotator": "Aim Rotator",
"roster.menu.IgnoreCall": "Ignore Call",
"roster.menu.Realtime": "Realtime",
"roster.menu.MoveLeft": "Move Column Left",
@ -1057,4 +1065,4 @@
"COMMENT_sendAlerts.js": "",
"sendAlerts.scriptEnabled": "Script Enabled",
"sendAlerts.scriptDisabled": "Script Disabled"
}
}

Wyświetl plik

@ -344,6 +344,13 @@
"settings.logging.HRDLogbook.source": "HRD Logbook",
"settings.logging.HRDLogbook.details.IP": "IP地址",
"settings.logging.HRDLogbook.details.Port": "端口",
"settings.logging.other.title": "Other Services",
"settings.logging.otherheader.service": "Service",
"settings.logging.otherheader.active": "Active?",
"settings.logging.otherheader.details": "Details",
"settings.logging.pstrotator.label": "CatRotator / PstRotator",
"settings.logging.pstrotator.details.IP": "IP",
"settings.logging.pstrotator.details.Port": "UDP Port",
"settings.callroster.AlwaysOnTop.label": "窗口始终在最上层",
"settings.callroster.AlwaysOnTop.hover": "将呼叫列表置于其他窗口之上",
"settings.callroster.MaxAge.label": "呼叫列表最大时效",
@ -995,6 +1002,7 @@
"roster.menu.RosterMode": "Roster Mode",
"roster.menu.Lookup": "Lookup",
"roster.menu.GenMesg": "Gen Msgs",
"roster.menu.AimRotator": "Aim Rotator",
"roster.menu.IgnoreCall": "Ignore Call",
"roster.menu.Realtime": "Realtime",
"roster.menu.MoveLeft": "Move Column Left",
@ -1057,4 +1065,4 @@
"COMMENT_sendAlerts.js": "",
"sendAlerts.scriptEnabled": "Script Enabled",
"sendAlerts.scriptDisabled": "Script Disabled"
}
}

Wyświetl plik

@ -343,6 +343,13 @@
"settings.logging.HRDLogbook.source": "HRD Logbook",
"settings.logging.HRDLogbook.details.IP": "IP",
"settings.logging.HRDLogbook.details.Port": "Port",
"settings.logging.other.title": "Other Services",
"settings.logging.otherheader.service": "Service",
"settings.logging.otherheader.active": "Active?",
"settings.logging.otherheader.details": "Details",
"settings.logging.pstrotator.label": "CatRotator / PstRotator",
"settings.logging.pstrotator.details.IP": "IP",
"settings.logging.pstrotator.details.Port": "UDP Port",
"settings.callroster.AlwaysOnTop.label": "Window Always On Top",
"settings.callroster.AlwaysOnTop.hover": "Keep Call Roster Above Other Windows",
"settings.callroster.MaxAge.label": "Call Roster Max Age",
@ -497,7 +504,7 @@
"roster.controls.hunting.label": "Hunting",
"roster.controls.hunting.callsign": "Callsign",
"roster.controls.hunting.grid": "Grid",
"roster.controls.hunting.dxcc": "DXCC",
"roster.controls.hunting.dxcc": "DXCC",
"roster.controls.hunting.dxccSingle": "DXCC (Single)",
"roster.controls.hunting.cqZone": "CQ Zone",
"roster.controls.hunting.ituZone": "ITU Zone",
@ -544,7 +551,7 @@
"roster.secondary.exceptions.usesOQRS": "Uses OQRS",
"roster.secondary.exceptions.wantRRCQ": "RR73 as CQ",
"roster.secondary.exceptions.allOnlyNew": "Only New Calls",
"roster.secondary.exceptions.noMsg.label": "No",
"roster.secondary.exceptions.noMsg.label": "No",
"roster.secondary.exceptions.noMsg.hover": "No Decodes Containing...",
"roster.secondary.exceptions.onlyMsg.label": "Only",
"roster.secondary.exceptions.onlyMsg.hover": "Only Decodes Containing...",
@ -995,6 +1002,7 @@
"roster.menu.RosterMode": "Roster Mode",
"roster.menu.Lookup": "Lookup",
"roster.menu.GenMesg": "Gen Msgs",
"roster.menu.AimRotator": "Aim Rotator",
"roster.menu.IgnoreCall": "Ignore Call",
"roster.menu.Realtime": "Realtime",
"roster.menu.MoveLeft": "Move Column Left",
@ -1058,4 +1066,4 @@
"COMMENT_sendAlerts.js": "",
"sendAlerts.scriptEnabled": "Script Enabled",
"sendAlerts.scriptDisabled": "Script Disabled"
}
}

Wyświetl plik

@ -27,7 +27,8 @@ var validSettings = [
"startupLogs",
"trustedQslSettings",
"screenSettings",
"legendColors"
"legendColors",
"pstrotatorSettings"
];
var def_appSettings = {
@ -234,7 +235,6 @@ var def_HRDLogbookLogSettings = {
port: 7826,
ip: "127.0.0.1"
};
var def_acLogSettings = {
enable: false,
port: 1100,
@ -277,3 +277,9 @@ var def_legendColors = {
QRZ: "#FFFF00",
QTH: "#FFA600"
};
var def_pstrotatorSettings = {
enable: false,
port: 12000,
ip: "127.0.0.1"
};

Wyświetl plik

@ -144,6 +144,10 @@ function loadAllSettings()
"HRDLogbookLogSettings",
def_HRDLogbookLogSettings
);
g_pstrotatorSettings = loadDefaultsAndMerge(
"pstrotatorSettings",
def_pstrotatorSettings
);
g_acLogSettings = loadDefaultsAndMerge("acLogSettings", def_acLogSettings);
g_trustedQslSettings = loadDefaultsAndMerge(
"trustedQslSettings",
@ -262,6 +266,7 @@ function saveLogSettings()
localStorage.log4OMSettings = JSON.stringify(g_log4OMSettings);
localStorage.dxkLogSettings = JSON.stringify(g_dxkLogSettings);
localStorage.HRDLogbookLogSettings = JSON.stringify(g_HRDLogbookLogSettings);
localStorage.pstrotatorSettings = JSON.stringify(g_pstrotatorSettings);
localStorage.acLogSettings = JSON.stringify(g_acLogSettings);
localStorage.trustedQslSettings = JSON.stringify(g_trustedQslSettings);
}
@ -1077,7 +1082,7 @@ function addDeDx(
var qsoDate = new Date(1970, 0, 1); qsoDate.setSeconds(finalTime);
var isCurrentYear = (qsoDate.getFullYear() == currentYear);
var dayAsString = String(parseInt(finalTime / 86400));
var callsign = null;
var rect = null;
var worked = false;
@ -1349,7 +1354,7 @@ function addDeDx(
g_tracker.worked.pota[dayAsString + finalDXcall + finalPOTA + band + "ph"] = true;
}
}
worked = true;
locked = true;
details.worked = worked;
@ -5531,7 +5536,7 @@ function initMap()
{
var saveSettings = false;
g_maps = Object.keys(g_maps).sort().reduce((obj, key) => { obj[key] = g_maps[key]; return obj; }, {});
if (!(g_mapSettings.mapIndex in g_maps))
{
g_mapSettings.mapIndex = def_mapSettings.mapIndex;
@ -5745,7 +5750,7 @@ function initMap()
noFeature = true;
break;
}
if (features[index].size == 6)
{
noFeature = false;
@ -10627,7 +10632,7 @@ function redrawGrids()
~~g_cqZones[cqz].confirmed_modes[mode] + 1;
}
}
if (ituz && ituz.length > 0)
{
if (g_ituZones[ituz].worked == false)
@ -10653,7 +10658,7 @@ function redrawGrids()
~~g_ituZones[ituz].confirmed_modes[mode] + 1;
}
}
if (finalGrid.length > 0)
{
var gridCheck = finalGrid.substr(0, 4);
@ -12289,7 +12294,7 @@ function toggleTimezones()
g_timezoneLayer = null;
}
}
timezoneImg.style.filter = g_timezonesEnable == 1 ? "" : "grayscale(1)";
}
@ -12735,7 +12740,7 @@ function loadMapSettings()
rosterDelayOnFocus.checked = g_appSettings.rosterDelayOnFocus;
rosterDelayTime.value = g_appSettings.rosterDelayTime;
rosterDelayTimeTd.innerHTML = rosterDelayTime.value + "ms";
setStrikesButton();
trafficDecode.checked = g_mapSettings.trafficDecode;
@ -13200,6 +13205,12 @@ function loadViewSettings()
ValidatePort(hrdLogbookPortInput, buttonHrdLogbookCheckBox, null);
ValidateIPaddress(hrdLogbookIpInput, buttonHrdLogbookCheckBox, null);
pstrotatorIpInput.value = g_pstrotatorSettings.ip;
pstrotatorPortInput.value = g_pstrotatorSettings.port;
pstrotatorCheckBox.checked = g_pstrotatorSettings.enable;
ValidatePort(pstrotatorPortInput, pstrotatorCheckBox, null);
ValidateIPaddress(pstrotatorIpInput, pstrotatorCheckBox, null);
spotHistoryTimeValue.value = parseInt(
g_receptionSettings.viewHistoryTimeSec / 60
);
@ -13506,7 +13517,7 @@ function postInit()
openCallRosterWindow(false);
openConditionsWindow(false);
showMessaging(false);
if (g_developerMode)
{
devPanel.style.display = "inline-block";
@ -15719,7 +15730,7 @@ function mediaCheck()
g_tracker.worked.px = {};
g_tracker.confirmed.px = {};
}
if (typeof g_tracker.worked.pota == "undefined")
{
g_tracker.worked.pota = {};
@ -15741,12 +15752,12 @@ function mediaCheck()
g_QSOhash[i].px = null;
}
}
if (typeof g_QSOhash[i].pota == "undefined" || g_QSOhash[i].pota == null)
{
g_QSOhash[i].pota = [];
}
g_QSOcount++;
if (g_QSOhash[i].confirmed) g_QSLcount++;
}

Wyświetl plik

@ -1725,13 +1725,28 @@ function addControls()
callGenMessage(g_targetHash, "");
}
});
g_callMenu.append(item);
item = new nw.MenuItem({ type: "separator" });
g_callMenu.append(item);
if (window.opener.g_pstrotatorSettings.enable)
{
item = new nw.MenuItem({
type: "normal",
label: $.i18n("roster.menu.AimRotator"),
click: function ()
{
let target = callRoster[g_targetHash]
window.opener.aimRotator(target, "");
}
});
g_callMenu.append(item);
item = new nw.MenuItem({ type: "separator" });
g_callMenu.append(item);
}
item = new nw.MenuItem({
type: "normal",
label: $.i18n("roster.menu.IgnoreCall"),
@ -1747,7 +1762,6 @@ function addControls()
g_callMenu.append(item);
g_callingMenu = new nw.Menu();
item = new nw.MenuItem({
type: "normal",
label: $.i18n("roster.menu.Lookup"),
@ -1773,6 +1787,23 @@ function addControls()
item = new nw.MenuItem({ type: "separator" });
g_menu.append(item);
if (window.opener.g_pstrotatorSettings.enable)
{
item = new nw.MenuItem({
type: "normal",
label: $.i18n("roster.menu.AimRotator"),
click: function ()
{
let target = callRoster[g_targetHash]
window.opener.aimRotator(target, "");
}
});
g_callingMenu.append(item);
item = new nw.MenuItem({ type: "separator" });
g_callingMenu.append(item);
}
item = new nw.MenuItem({
type: "checkbox",
label: $.i18n("roster.menu.Realtime"),

Wyświetl plik

@ -0,0 +1,82 @@
/**
* PSTRotator is a third party application (windows-only) that interfaces with dozens of antenna rotators.
* It offers a way for other apps to request rotation to a specific azimuth, or a grid square.
*
* Other rotator control apps, like [CatRotator](https://www.pianetaradio.it/blog/catrotator/) also support this API.
*
* The most comprehensive API details are in this Groups.io post:
* https://groups.io/g/PstRotator/message/5825
*
*/
var g_pstrotatorSettings = {};
function pstrotatorServiceChanged()
{
if (g_pstrotatorSettings.enabled != pstrotatorCheckBox.checked)
{
// This setting toggles the presence of a contextual menu item in the roster,
// which is constructed only during roster initialization.
//
// So when this setting is changed, we need to reload the entire roster window.
//
g_pstrotatorSettings.enable = pstrotatorCheckBox.checked;
if (g_rosterInitialized)
{
try
{
g_callRosterWindowHandle.window.location.reload();
}
catch (e)
{
console.error(e);
}
}
}
g_pstrotatorSettings.ip = pstrotatorIpInput.value;
g_pstrotatorSettings.port = pstrotatorPortInput.value;
saveLogSettings();
}
function aimRotator(info)
{
const { callObj } = info
if (
g_pstrotatorSettings.enable == true &&
g_pstrotatorSettings.port > 0 &&
g_pstrotatorSettings.ip.length > 4 &&
(callObj.distance > 0 || callObj.grid)
)
{
let payload = "<PST>"
if (callObj.distance > 0)
{
payload += `<AZIMUTH>${Math.round(callObj.heading)}</AZIMUTH>`
}
if (callObj.grid)
{
payload += `<QRA>${callObj.grid}</QRA>`
}
payload += "</PST>"
try
{
sendUdpMessage(
payload,
payload.length,
parseInt(g_pstrotatorSettings.port),
g_pstrotatorSettings.ip
);
addLastTraffic(`<font style='color:white'>Aiming rotator towards ${data.DEcall}</font>`);
}
catch (e)
{
addLastTraffic("<font style='color:red'>UDP aimRotator failed</font>");
}
}
}

Wyświetl plik

@ -619,7 +619,8 @@ a {
margin: 0;
display: none;
background-color: black;
padding: 2px;
padding: 6px;
padding-bottom: 10px;
text-align: center;
width: auto;
border: 1px solid blue;
@ -627,7 +628,8 @@ a {
vertical-align: top;
-webkit-border-radius: 6px;
white-space: normal;
max-height: 600px;
overflow: auto;
/* animation: fadeEffect .3s; Fading effect takes 1 second */
}