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/237/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">

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",

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",

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",
@ -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",

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);
}
@ -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
);

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 */
}