feat(wavelog): push station frequency/mode to Wavelog per operator
Add a CAT integration so the station's current frequency and mode are
reported to each operator's personal Wavelog logbook via Wavelog's radio
API (POST <baseUrl>/index.php/api/radio).
- New plugin rms.wavelog.cat (capability logging.cat.publish): posts
{key, radio, frequency, mode}. Base URL / radio name come from plugin
settings or env (WAVELOG_BASE_URL, WAVELOG_RADIO_NAME); no secrets in repo.
- Core hook in the OpenWebRX band-select flow pushes centerFreqHz + startMod
for the active operator, best-effort (never breaks the band change).
- Per-user Wavelog API key stored on the user record; PUT /v1/me/wavelog-key
to set it, returned by GET /v1/me and the OpenWebRX session issue response.
- UI: Wavelog API key field in the OpenWebRX panel (visible when generating
the session link), with i18n (de/en).
- Docs, .env.example entries, and a unit test for the mode mapping.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -135,6 +135,9 @@ const els = {
|
||||
openwebrxSessionLink: document.getElementById("openwebrxSessionLink"),
|
||||
openwebrxCopyLinkBtn: document.getElementById("openwebrxCopyLinkBtn"),
|
||||
openwebrxSessionTicket: document.getElementById("openwebrxSessionTicket"),
|
||||
wavelogKeyInput: document.getElementById("wavelogKeyInput"),
|
||||
wavelogKeySaveBtn: document.getElementById("wavelogKeySaveBtn"),
|
||||
wavelogKeyMessage: document.getElementById("wavelogKeyMessage"),
|
||||
openwebrxTxStatePill: document.getElementById("openwebrxTxStatePill"),
|
||||
rotorCurrent: document.getElementById("rotorCurrent"),
|
||||
rotorCompass: document.getElementById("rotorCompass"),
|
||||
@@ -690,6 +693,11 @@ function bindEvents() {
|
||||
await copyOpenWebRxLink();
|
||||
});
|
||||
}
|
||||
if (els.wavelogKeySaveBtn) {
|
||||
els.wavelogKeySaveBtn.addEventListener("click", async () => {
|
||||
await saveWavelogKey();
|
||||
});
|
||||
}
|
||||
if (els.openwebrxEnableTxBtn) {
|
||||
els.openwebrxEnableTxBtn.addEventListener("click", async (event) => {
|
||||
if (event) {
|
||||
@@ -1496,6 +1504,8 @@ async function refreshCurrentUser() {
|
||||
try {
|
||||
const result = await api("/v1/me", { authRequired: true });
|
||||
state.user = result.user;
|
||||
state.wavelogApiKey = typeof result.wavelogApiKey === "string" ? result.wavelogApiKey : "";
|
||||
applyWavelogKeyToInput();
|
||||
renderUserSettingsAuthMethods();
|
||||
await ensureLanguageFromUserPreference();
|
||||
} catch {
|
||||
@@ -1684,12 +1694,37 @@ async function cancelReservationByUserId(userId) {
|
||||
}
|
||||
}
|
||||
|
||||
function applyWavelogKeyToInput() {
|
||||
if (els.wavelogKeyInput) {
|
||||
els.wavelogKeyInput.value = String(state.wavelogApiKey || "");
|
||||
}
|
||||
}
|
||||
|
||||
async function saveWavelogKey() {
|
||||
if (!els.wavelogKeyInput) {
|
||||
return;
|
||||
}
|
||||
const apiKey = String(els.wavelogKeyInput.value || "").trim();
|
||||
try {
|
||||
const result = await api("/v1/me/wavelog-key", { method: "PUT", body: { apiKey } });
|
||||
state.wavelogApiKey = result && typeof result.wavelogApiKey === "string" ? result.wavelogApiKey : apiKey;
|
||||
applyWavelogKeyToInput();
|
||||
renderMessage(els.wavelogKeyMessage, translateLiteral("Wavelog API Key gespeichert."), false);
|
||||
} catch (error) {
|
||||
renderMessage(els.wavelogKeyMessage, error.message, true);
|
||||
}
|
||||
}
|
||||
|
||||
async function openOpenWebRxSession() {
|
||||
clearMessages("status");
|
||||
setOpenWebRxBusy(true);
|
||||
try {
|
||||
const result = await requestOpenWebRxSessionWithRetry();
|
||||
const session = result && result.session ? result.session : null;
|
||||
if (result && typeof result.wavelogApiKey === "string") {
|
||||
state.wavelogApiKey = result.wavelogApiKey;
|
||||
applyWavelogKeyToInput();
|
||||
}
|
||||
const sessionTicket = session && session.ticket ? String(session.ticket) : "";
|
||||
state.openWebRx.sessionUrl = buildOpenWebRxSessionUrl(session && session.iframeUrl ? session.iframeUrl : "", sessionTicket);
|
||||
state.openWebRx.sessionTicket = sessionTicket;
|
||||
@@ -1715,6 +1750,10 @@ async function openOpenWebRxExternal() {
|
||||
try {
|
||||
const result = await requestOpenWebRxSessionWithRetry();
|
||||
const session = result && result.session ? result.session : null;
|
||||
if (result && typeof result.wavelogApiKey === "string") {
|
||||
state.wavelogApiKey = result.wavelogApiKey;
|
||||
applyWavelogKeyToInput();
|
||||
}
|
||||
const sessionTicket = session && session.ticket ? String(session.ticket) : "";
|
||||
const sessionUrl = buildOpenWebRxSessionUrl(session && session.iframeUrl ? String(session.iframeUrl) : "", sessionTicket);
|
||||
if (!sessionUrl) {
|
||||
|
||||
@@ -52,6 +52,10 @@
|
||||
"OpenWebRX laden": "OpenWebRX laden",
|
||||
"SDR oeffnen": "SDR oeffnen",
|
||||
"Session Key (Ticket):": "Session Key (Ticket):",
|
||||
"Wavelog API Key (Rig-Key)": "Wavelog API Key (Rig-Key)",
|
||||
"Key speichern": "Key speichern",
|
||||
"Frequenz und Mode der Station werden beim Bandwechsel an dein Wavelog-Logbuch gesendet.": "Frequenz und Mode der Station werden beim Bandwechsel an dein Wavelog-Logbuch gesendet.",
|
||||
"Wavelog API Key gespeichert.": "Wavelog API Key gespeichert.",
|
||||
"Reservierungen": "Reservierungen",
|
||||
"Naechsten Slot reservieren": "Naechsten Slot reservieren",
|
||||
"SWR Uebersicht": "SWR Uebersicht",
|
||||
|
||||
@@ -52,6 +52,10 @@
|
||||
"OpenWebRX laden": "Load OpenWebRX",
|
||||
"SDR oeffnen": "Open SDR",
|
||||
"Session Key (Ticket):": "Session key (ticket):",
|
||||
"Wavelog API Key (Rig-Key)": "Wavelog API Key (Rig Key)",
|
||||
"Key speichern": "Save key",
|
||||
"Frequenz und Mode der Station werden beim Bandwechsel an dein Wavelog-Logbuch gesendet.": "The station's frequency and mode are sent to your Wavelog logbook on band change.",
|
||||
"Wavelog API Key gespeichert.": "Wavelog API key saved.",
|
||||
"Reservierungen": "Reservations",
|
||||
"Naechsten Slot reservieren": "Reserve next slot",
|
||||
"SWR Uebersicht": "SWR Overview",
|
||||
|
||||
@@ -166,6 +166,15 @@
|
||||
<div id="openwebrxSessionAccess" class="stack" hidden>
|
||||
<p class="muted">Session Key (Ticket): <code id="openwebrxSessionTicket">-</code></p>
|
||||
</div>
|
||||
<div id="wavelogKeyBox" class="stack">
|
||||
<label for="wavelogKeyInput">Wavelog API Key (Rig-Key)</label>
|
||||
<input id="wavelogKeyInput" type="text" autocomplete="off" spellcheck="false" placeholder="Wavelog API Key" />
|
||||
<div class="actions">
|
||||
<button id="wavelogKeySaveBtn" type="button" class="ghost-btn">Key speichern</button>
|
||||
</div>
|
||||
<p id="wavelogKeyMessage" class="message"></p>
|
||||
<p class="muted">Frequenz und Mode der Station werden beim Bandwechsel an dein Wavelog-Logbuch gesendet.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="reservationPanel" class="links-wrap" hidden>
|
||||
|
||||
Reference in New Issue
Block a user