[refactor](trx-frontend-http): rename rig_id API fields to remote
Rename HTTP query params, JSON fields, and scheduler payloads to use remote names consistently while still accepting legacy `rig_id` inputs through serde aliases. Co-authored-by: OpenAI Codex <noreply@openai.com> Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
@@ -1001,19 +1001,19 @@ async function refreshRigList() {
|
|||||||
if (!resp.ok) return;
|
if (!resp.ok) return;
|
||||||
const data = await resp.json();
|
const data = await resp.json();
|
||||||
const rigs = Array.isArray(data.rigs) ? data.rigs : [];
|
const rigs = Array.isArray(data.rigs) ? data.rigs : [];
|
||||||
const rigIds = rigs.map((r) => r && r.rig_id).filter(Boolean);
|
const rigIds = rigs.map((r) => r && r.remote).filter(Boolean);
|
||||||
const displayNames = {};
|
const displayNames = {};
|
||||||
rigs.forEach((r) => {
|
rigs.forEach((r) => {
|
||||||
if (!r || !r.rig_id) return;
|
if (!r || !r.remote) return;
|
||||||
if (typeof r.display_name === "string" && r.display_name.length > 0) {
|
if (typeof r.display_name === "string" && r.display_name.length > 0) {
|
||||||
displayNames[r.rig_id] = r.display_name;
|
displayNames[r.remote] = r.display_name;
|
||||||
} else {
|
} else {
|
||||||
displayNames[r.rig_id] = r.rig_id;
|
displayNames[r.remote] = r.remote;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
serverRigs = rigs;
|
serverRigs = rigs;
|
||||||
serverActiveRigId = data.active_rig_id || null;
|
serverActiveRigId = data.active_remote || null;
|
||||||
applyRigList(data.active_rig_id, rigIds, displayNames);
|
applyRigList(data.active_remote, rigIds, displayNames);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Non-fatal: SSE/status path still drives main UI.
|
// Non-fatal: SSE/status path still drives main UI.
|
||||||
}
|
}
|
||||||
@@ -3248,8 +3248,8 @@ function render(update) {
|
|||||||
if (lastActiveRigId) {
|
if (lastActiveRigId) {
|
||||||
document.getElementById("about-active-rig").textContent = lastActiveRigId;
|
document.getElementById("about-active-rig").textContent = lastActiveRigId;
|
||||||
}
|
}
|
||||||
if (Array.isArray(update.rig_ids)) {
|
if (Array.isArray(update.remotes)) {
|
||||||
applyRigList(update.active_rig_id, update.rig_ids);
|
applyRigList(update.active_remote, update.remotes);
|
||||||
}
|
}
|
||||||
if (typeof update.rigctl_clients === "number") {
|
if (typeof update.rigctl_clients === "number") {
|
||||||
document.getElementById("about-rigctl-clients").textContent = update.rigctl_clients;
|
document.getElementById("about-rigctl-clients").textContent = update.rigctl_clients;
|
||||||
@@ -3293,7 +3293,7 @@ function scheduleReconnect(delayMs = 1000) {
|
|||||||
async function pollFreshSnapshot() {
|
async function pollFreshSnapshot() {
|
||||||
try {
|
try {
|
||||||
const statusUrl = lastActiveRigId
|
const statusUrl = lastActiveRigId
|
||||||
? `/status?rig_id=${encodeURIComponent(lastActiveRigId)}`
|
? `/status?remote=${encodeURIComponent(lastActiveRigId)}`
|
||||||
: "/status";
|
: "/status";
|
||||||
const resp = await fetch(statusUrl, { cache: "no-store" });
|
const resp = await fetch(statusUrl, { cache: "no-store" });
|
||||||
if (!resp.ok) return;
|
if (!resp.ok) return;
|
||||||
@@ -3316,7 +3316,7 @@ function connect() {
|
|||||||
}
|
}
|
||||||
pollFreshSnapshot();
|
pollFreshSnapshot();
|
||||||
const eventsUrl = lastActiveRigId
|
const eventsUrl = lastActiveRigId
|
||||||
? `/events?rig_id=${encodeURIComponent(lastActiveRigId)}`
|
? `/events?remote=${encodeURIComponent(lastActiveRigId)}`
|
||||||
: "/events";
|
: "/events";
|
||||||
es = new EventSource(eventsUrl);
|
es = new EventSource(eventsUrl);
|
||||||
lastEventAt = Date.now();
|
lastEventAt = Date.now();
|
||||||
@@ -3442,11 +3442,11 @@ function scheduleUiFrameJob(key, job) {
|
|||||||
window.trxScheduleUiFrameJob = scheduleUiFrameJob;
|
window.trxScheduleUiFrameJob = scheduleUiFrameJob;
|
||||||
|
|
||||||
async function postPath(path) {
|
async function postPath(path) {
|
||||||
// Auto-append rig_id so each tab targets its own rig.
|
// Auto-append remote so each tab targets its own rig.
|
||||||
// Skip when the caller already included rig_id (e.g. /select_rig).
|
// Skip when the caller already included remote (e.g. /select_rig).
|
||||||
if (lastActiveRigId && !path.includes("rig_id=")) {
|
if (lastActiveRigId && !path.includes("remote=")) {
|
||||||
const sep = path.includes("?") ? "&" : "?";
|
const sep = path.includes("?") ? "&" : "?";
|
||||||
path = `${path}${sep}rig_id=${encodeURIComponent(lastActiveRigId)}`;
|
path = `${path}${sep}remote=${encodeURIComponent(lastActiveRigId)}`;
|
||||||
}
|
}
|
||||||
const resp = await fetch(path, { method: "POST" });
|
const resp = await fetch(path, { method: "POST" });
|
||||||
if (authEnabled && resp.status === 401) {
|
if (authEnabled && resp.status === 401) {
|
||||||
@@ -3502,7 +3502,7 @@ async function switchRigFromSelect(selectEl) {
|
|||||||
// state channel.
|
// state channel.
|
||||||
try {
|
try {
|
||||||
const sidParam = sseSessionId ? `&session_id=${encodeURIComponent(sseSessionId)}` : "";
|
const sidParam = sseSessionId ? `&session_id=${encodeURIComponent(sseSessionId)}` : "";
|
||||||
await postPath(`/select_rig?rig_id=${encodeURIComponent(selectEl.value)}${sidParam}`);
|
await postPath(`/select_rig?remote=${encodeURIComponent(selectEl.value)}${sidParam}`);
|
||||||
connect();
|
connect();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("select_rig failed:", err);
|
console.error("select_rig failed:", err);
|
||||||
@@ -6061,7 +6061,7 @@ function buildReceiverPopupHtml() {
|
|||||||
}
|
}
|
||||||
for (const rig of serverRigs) {
|
for (const rig of serverRigs) {
|
||||||
const name = rig.display_name || `${rig.manufacturer} ${rig.model}`.trim();
|
const name = rig.display_name || `${rig.manufacturer} ${rig.model}`.trim();
|
||||||
const active = rig.rig_id === serverActiveRigId
|
const active = rig.remote === serverActiveRigId
|
||||||
? ` <span class="receiver-popup-active">active</span>` : "";
|
? ` <span class="receiver-popup-active">active</span>` : "";
|
||||||
rows += `<tr><td class="aprs-popup-label">Rig</td><td>${escapeMapHtml(name)}${active}</td></tr>`;
|
rows += `<tr><td class="aprs-popup-label">Rig</td><td>${escapeMapHtml(name)}${active}</td></tr>`;
|
||||||
}
|
}
|
||||||
@@ -7137,7 +7137,7 @@ window.mapAddLocator = function(message, grids, type = "ft8", station = null, de
|
|||||||
dt_s: Number.isFinite(details?.dt_s) ? Number(details.dt_s) : null,
|
dt_s: Number.isFinite(details?.dt_s) ? Number(details.dt_s) : null,
|
||||||
freq_hz: Number.isFinite(details?.freq_hz) ? Number(details.freq_hz) : null,
|
freq_hz: Number.isFinite(details?.freq_hz) ? Number(details.freq_hz) : null,
|
||||||
message: String(details?.message || message || "").trim() || null,
|
message: String(details?.message || message || "").trim() || null,
|
||||||
rig_id: lastActiveRigId || null,
|
remote: lastActiveRigId || null,
|
||||||
};
|
};
|
||||||
const detailKey = detailStationId || `${targetId || "decode"}:${detailEntry.message || "decode"}:${detailEntry.ts_ms || Date.now()}`;
|
const detailKey = detailStationId || `${targetId || "decode"}:${detailEntry.message || "decode"}:${detailEntry.ts_ms || Date.now()}`;
|
||||||
const key = `${markerType}:${grid}`;
|
const key = `${markerType}:${grid}`;
|
||||||
@@ -7667,7 +7667,7 @@ function startRxAudio() {
|
|||||||
if (_audioChannelOverride) {
|
if (_audioChannelOverride) {
|
||||||
audioPath = `/audio?channel_id=${encodeURIComponent(_audioChannelOverride)}`;
|
audioPath = `/audio?channel_id=${encodeURIComponent(_audioChannelOverride)}`;
|
||||||
} else if (lastActiveRigId) {
|
} else if (lastActiveRigId) {
|
||||||
audioPath = `/audio?rig_id=${encodeURIComponent(lastActiveRigId)}`;
|
audioPath = `/audio?remote=${encodeURIComponent(lastActiveRigId)}`;
|
||||||
} else {
|
} else {
|
||||||
audioPath = "/audio";
|
audioPath = "/audio";
|
||||||
}
|
}
|
||||||
@@ -8705,7 +8705,7 @@ function scheduleSpectrumReconnect() {
|
|||||||
function startSpectrumStreaming() {
|
function startSpectrumStreaming() {
|
||||||
if (spectrumSource !== null) return;
|
if (spectrumSource !== null) return;
|
||||||
const spectrumUrl = lastActiveRigId
|
const spectrumUrl = lastActiveRigId
|
||||||
? `/spectrum?rig_id=${encodeURIComponent(lastActiveRigId)}`
|
? `/spectrum?remote=${encodeURIComponent(lastActiveRigId)}`
|
||||||
: "/spectrum";
|
: "/spectrum";
|
||||||
spectrumSource = new EventSource(spectrumUrl);
|
spectrumSource = new EventSource(spectrumUrl);
|
||||||
// Unnamed event = reset signal.
|
// Unnamed event = reset signal.
|
||||||
|
|||||||
+4
-4
@@ -74,7 +74,7 @@
|
|||||||
if (!rigId) return;
|
if (!rigId) return;
|
||||||
Promise.all([apiGetConfig(rigId), apiGetBookmarks()])
|
Promise.all([apiGetConfig(rigId), apiGetBookmarks()])
|
||||||
.then(function ([config, bookmarks]) {
|
.then(function ([config, bookmarks]) {
|
||||||
currentConfig = config || { rig_id: rigId, enabled: false, bookmark_ids: [] };
|
currentConfig = config || { remote: rigId, enabled: false, bookmark_ids: [] };
|
||||||
bookmarkList = Array.isArray(bookmarks) ? bookmarks : [];
|
bookmarkList = Array.isArray(bookmarks) ? bookmarks : [];
|
||||||
renderBookmarkPick();
|
renderBookmarkPick();
|
||||||
renderBackgroundDecode();
|
renderBackgroundDecode();
|
||||||
@@ -121,7 +121,7 @@
|
|||||||
|
|
||||||
function renderBackgroundDecode() {
|
function renderBackgroundDecode() {
|
||||||
if (!currentConfig) {
|
if (!currentConfig) {
|
||||||
currentConfig = { rig_id: currentRigId, enabled: false, bookmark_ids: [] };
|
currentConfig = { remote: currentRigId, enabled: false, bookmark_ids: [] };
|
||||||
}
|
}
|
||||||
setCheckbox("background-decode-enabled", !!currentConfig.enabled);
|
setCheckbox("background-decode-enabled", !!currentConfig.enabled);
|
||||||
renderBookmarkList();
|
renderBookmarkList();
|
||||||
@@ -178,7 +178,7 @@
|
|||||||
const sel = document.getElementById("background-decode-bookmark-pick");
|
const sel = document.getElementById("background-decode-bookmark-pick");
|
||||||
if (!sel || !sel.value) return;
|
if (!sel || !sel.value) return;
|
||||||
if (!currentConfig) {
|
if (!currentConfig) {
|
||||||
currentConfig = { rig_id: currentRigId, enabled: false, bookmark_ids: [] };
|
currentConfig = { remote: currentRigId, enabled: false, bookmark_ids: [] };
|
||||||
}
|
}
|
||||||
if (!Array.isArray(currentConfig.bookmark_ids)) currentConfig.bookmark_ids = [];
|
if (!Array.isArray(currentConfig.bookmark_ids)) currentConfig.bookmark_ids = [];
|
||||||
if (!currentConfig.bookmark_ids.includes(sel.value)) currentConfig.bookmark_ids.push(sel.value);
|
if (!currentConfig.bookmark_ids.includes(sel.value)) currentConfig.bookmark_ids.push(sel.value);
|
||||||
@@ -191,7 +191,7 @@
|
|||||||
const rigId = currentRigId;
|
const rigId = currentRigId;
|
||||||
if (!rigId) return;
|
if (!rigId) return;
|
||||||
const payload = {
|
const payload = {
|
||||||
rig_id: rigId,
|
remote: rigId,
|
||||||
enabled: !!document.getElementById("background-decode-enabled").checked,
|
enabled: !!document.getElementById("background-decode-enabled").checked,
|
||||||
bookmark_ids: Array.isArray(currentConfig && currentConfig.bookmark_ids) ? currentConfig.bookmark_ids.slice() : [],
|
bookmark_ids: Array.isArray(currentConfig && currentConfig.bookmark_ids) ? currentConfig.bookmark_ids.slice() : [],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -511,7 +511,7 @@
|
|||||||
const extraBmIds = pendingExtraBmIds.slice();
|
const extraBmIds = pendingExtraBmIds.slice();
|
||||||
|
|
||||||
if (!currentConfig) {
|
if (!currentConfig) {
|
||||||
currentConfig = { rig_id: currentRigId, mode: "time_span", entries: [] };
|
currentConfig = { remote: currentRigId, mode: "time_span", entries: [] };
|
||||||
}
|
}
|
||||||
if (!currentConfig.entries) currentConfig.entries = [];
|
if (!currentConfig.entries) currentConfig.entries = [];
|
||||||
|
|
||||||
@@ -666,7 +666,7 @@
|
|||||||
const mode = modeEl ? modeEl.value : "disabled";
|
const mode = modeEl ? modeEl.value : "disabled";
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
rig_id: rig,
|
remote: rig,
|
||||||
mode,
|
mode,
|
||||||
grayline: null,
|
grayline: null,
|
||||||
entries: [],
|
entries: [],
|
||||||
@@ -722,7 +722,7 @@
|
|||||||
apiDeleteScheduler(rig)
|
apiDeleteScheduler(rig)
|
||||||
.then(function () {
|
.then(function () {
|
||||||
currentConfig = {
|
currentConfig = {
|
||||||
rig_id: rig,
|
remote: rig,
|
||||||
mode: "disabled",
|
mode: "disabled",
|
||||||
grayline: null,
|
grayline: null,
|
||||||
entries: [],
|
entries: [],
|
||||||
@@ -756,7 +756,7 @@
|
|||||||
const modeEl = document.getElementById("scheduler-mode-select");
|
const modeEl = document.getElementById("scheduler-mode-select");
|
||||||
if (modeEl) {
|
if (modeEl) {
|
||||||
modeEl.addEventListener("change", function () {
|
modeEl.addEventListener("change", function () {
|
||||||
if (!currentConfig) currentConfig = { rig_id: currentRigId, mode: modeEl.value, entries: [] };
|
if (!currentConfig) currentConfig = { remote: currentRigId, mode: modeEl.value, entries: [] };
|
||||||
currentConfig.mode = modeEl.value;
|
currentConfig.mode = modeEl.value;
|
||||||
renderScheduler();
|
renderScheduler();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ async function vchanToggleSchedulerRelease() {
|
|||||||
const resp = await fetch("/scheduler-control", {
|
const resp = await fetch("/scheduler-control", {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ session_id: vchanSessionId, released: true, rig_id: rigId }),
|
body: JSON.stringify({ session_id: vchanSessionId, released: true, remote: rigId }),
|
||||||
});
|
});
|
||||||
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
|
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
|
||||||
schedulerReleaseState = await resp.json();
|
schedulerReleaseState = await resp.json();
|
||||||
@@ -128,7 +128,7 @@ function vchanHandleSession(data) {
|
|||||||
function vchanHandleChannels(data) {
|
function vchanHandleChannels(data) {
|
||||||
try {
|
try {
|
||||||
const d = JSON.parse(data);
|
const d = JSON.parse(data);
|
||||||
vchanRigId = d.rig_id || null;
|
vchanRigId = d.remote || null;
|
||||||
vchanChannels = d.channels || [];
|
vchanChannels = d.channels || [];
|
||||||
const ids = new Set(vchanChannels.map(c => c.id));
|
const ids = new Set(vchanChannels.map(c => c.id));
|
||||||
if (!vchanActiveId && vchanChannels.length > 0 && vchanSessionId) {
|
if (!vchanActiveId && vchanChannels.length > 0 && vchanSessionId) {
|
||||||
|
|||||||
@@ -84,8 +84,8 @@ struct FrontendMeta {
|
|||||||
http_clients: usize,
|
http_clients: usize,
|
||||||
rigctl_clients: usize,
|
rigctl_clients: usize,
|
||||||
rigctl_addr: Option<String>,
|
rigctl_addr: Option<String>,
|
||||||
active_rig_id: Option<String>,
|
active_remote: Option<String>,
|
||||||
rig_ids: Vec<String>,
|
remotes: Vec<String>,
|
||||||
owner_callsign: Option<String>,
|
owner_callsign: Option<String>,
|
||||||
owner_website_url: Option<String>,
|
owner_website_url: Option<String>,
|
||||||
owner_website_name: Option<String>,
|
owner_website_name: Option<String>,
|
||||||
@@ -137,7 +137,8 @@ pub type SharedSessionRigManager = Arc<SessionRigManager>;
|
|||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct StatusQuery {
|
pub struct StatusQuery {
|
||||||
pub rig_id: Option<String>,
|
#[serde(alias = "rig_id")]
|
||||||
|
pub remote: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/status")]
|
#[get("/status")]
|
||||||
@@ -147,10 +148,10 @@ pub async fn status_api(
|
|||||||
clients: web::Data<Arc<AtomicUsize>>,
|
clients: web::Data<Arc<AtomicUsize>>,
|
||||||
context: web::Data<Arc<FrontendRuntimeContext>>,
|
context: web::Data<Arc<FrontendRuntimeContext>>,
|
||||||
) -> Result<impl Responder, Error> {
|
) -> Result<impl Responder, Error> {
|
||||||
// Prefer the per-rig watch channel when a rig_id is specified,
|
// Prefer the per-rig watch channel when a remote is specified,
|
||||||
// falling back to the global state watch.
|
// falling back to the global state watch.
|
||||||
let rx = query
|
let rx = query
|
||||||
.rig_id
|
.remote
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.filter(|s| !s.is_empty())
|
.filter(|s| !s.is_empty())
|
||||||
.and_then(|rid| context.rig_state_rx(rid))
|
.and_then(|rid| context.rig_state_rx(rid))
|
||||||
@@ -187,10 +188,10 @@ fn inject_frontend_meta(json: &str, meta: FrontendMeta) -> String {
|
|||||||
if let Some(v) = meta.rigctl_addr {
|
if let Some(v) = meta.rigctl_addr {
|
||||||
extra.insert("rigctl_addr".into(), serde_json::json!(v));
|
extra.insert("rigctl_addr".into(), serde_json::json!(v));
|
||||||
}
|
}
|
||||||
if let Some(v) = meta.active_rig_id {
|
if let Some(v) = meta.active_remote {
|
||||||
extra.insert("active_rig_id".into(), serde_json::json!(v));
|
extra.insert("active_remote".into(), serde_json::json!(v));
|
||||||
}
|
}
|
||||||
extra.insert("rig_ids".into(), serde_json::json!(meta.rig_ids));
|
extra.insert("remotes".into(), serde_json::json!(meta.remotes));
|
||||||
if let Some(v) = meta.owner_callsign {
|
if let Some(v) = meta.owner_callsign {
|
||||||
extra.insert("owner_callsign".into(), serde_json::json!(v));
|
extra.insert("owner_callsign".into(), serde_json::json!(v));
|
||||||
}
|
}
|
||||||
@@ -246,8 +247,8 @@ fn frontend_meta_from_context(
|
|||||||
http_clients,
|
http_clients,
|
||||||
rigctl_clients: context.rigctl_clients.load(Ordering::Relaxed),
|
rigctl_clients: context.rigctl_clients.load(Ordering::Relaxed),
|
||||||
rigctl_addr: rigctl_addr_from_context(context),
|
rigctl_addr: rigctl_addr_from_context(context),
|
||||||
active_rig_id: active_rig_id_from_context(context),
|
active_remote: active_rig_id_from_context(context),
|
||||||
rig_ids: rig_ids_from_context(context),
|
remotes: rig_ids_from_context(context),
|
||||||
owner_callsign: owner_callsign_from_context(context),
|
owner_callsign: owner_callsign_from_context(context),
|
||||||
owner_website_url: owner_website_url_from_context(context),
|
owner_website_url: owner_website_url_from_context(context),
|
||||||
owner_website_name: owner_website_name_from_context(context),
|
owner_website_name: owner_website_name_from_context(context),
|
||||||
@@ -339,7 +340,8 @@ fn decode_history_retention_min_from_context(context: &FrontendRuntimeContext) -
|
|||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct EventsQuery {
|
pub struct EventsQuery {
|
||||||
pub rig_id: Option<String>,
|
#[serde(alias = "rig_id")]
|
||||||
|
pub remote: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/events")]
|
#[get("/events")]
|
||||||
@@ -362,10 +364,10 @@ pub async fn events(
|
|||||||
let session_id = Uuid::new_v4();
|
let session_id = Uuid::new_v4();
|
||||||
scheduler_control.register_session(session_id);
|
scheduler_control.register_session(session_id);
|
||||||
|
|
||||||
// Use the client-requested rig_id if provided, otherwise fall back to
|
// Use the client-requested remote if provided, otherwise fall back to
|
||||||
// the global default. This allows each tab to reconnect SSE for the
|
// the global default. This allows each tab to reconnect SSE for the
|
||||||
// rig it has selected without mutating global state.
|
// rig it has selected without mutating global state.
|
||||||
let active_rig_id = query.rig_id.clone().filter(|s| !s.is_empty()).or_else(|| {
|
let active_rig_id = query.remote.clone().filter(|s| !s.is_empty()).or_else(|| {
|
||||||
context
|
context
|
||||||
.remote_active_rig_id
|
.remote_active_rig_id
|
||||||
.lock()
|
.lock()
|
||||||
@@ -413,7 +415,7 @@ pub async fn events(
|
|||||||
let chans = vchan_mgr.channels(rid);
|
let chans = vchan_mgr.channels(rid);
|
||||||
if let Ok(json) = serde_json::to_string(&chans) {
|
if let Ok(json) = serde_json::to_string(&chans) {
|
||||||
prefix.push(Ok(Bytes::from(format!(
|
prefix.push(Ok(Bytes::from(format!(
|
||||||
"event: channels\ndata: {{\"rig_id\":\"{rid}\",\"channels\":{json}}}\n\n"
|
"event: channels\ndata: {{\"remote\":\"{rid}\",\"channels\":{json}}}\n\n"
|
||||||
))));
|
))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -493,7 +495,7 @@ pub async fn events(
|
|||||||
}
|
}
|
||||||
let channels_json = &msg[colon + 1..];
|
let channels_json = &msg[colon + 1..];
|
||||||
let payload =
|
let payload =
|
||||||
format!("{{\"rig_id\":\"{rig_id}\",\"channels\":{channels_json}}}");
|
format!("{{\"remote\":\"{rig_id}\",\"channels\":{channels_json}}}");
|
||||||
return Some((
|
return Some((
|
||||||
Ok::<Bytes, Error>(Bytes::from(format!(
|
Ok::<Bytes, Error>(Bytes::from(format!(
|
||||||
"event: channels\ndata: {payload}\n\n"
|
"event: channels\ndata: {payload}\n\n"
|
||||||
@@ -812,13 +814,13 @@ impl<I> futures_util::Stream for DropStream<I> {
|
|||||||
/// Emits an unnamed `data: null` event when spectrum data becomes unavailable.
|
/// Emits an unnamed `data: null` event when spectrum data becomes unavailable.
|
||||||
#[get("/spectrum")]
|
#[get("/spectrum")]
|
||||||
pub async fn spectrum(
|
pub async fn spectrum(
|
||||||
query: web::Query<RigIdQuery>,
|
query: web::Query<RemoteQuery>,
|
||||||
context: web::Data<Arc<FrontendRuntimeContext>>,
|
context: web::Data<Arc<FrontendRuntimeContext>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
// Subscribe to a per-rig spectrum channel when rig_id is specified,
|
// Subscribe to a per-rig spectrum channel when remote is specified,
|
||||||
// otherwise fall back to the global channel for backward compat.
|
// otherwise fall back to the global channel for backward compat.
|
||||||
let rx = if let Some(ref rig_id) = query.rig_id {
|
let rx = if let Some(ref remote) = query.remote {
|
||||||
context.rig_spectrum_rx(rig_id)
|
context.rig_spectrum_rx(remote)
|
||||||
} else {
|
} else {
|
||||||
context.spectrum.subscribe()
|
context.spectrum.subscribe()
|
||||||
};
|
};
|
||||||
@@ -866,7 +868,7 @@ pub async fn spectrum(
|
|||||||
|
|
||||||
#[post("/toggle_power")]
|
#[post("/toggle_power")]
|
||||||
pub async fn toggle_power(
|
pub async fn toggle_power(
|
||||||
query: web::Query<RigIdQuery>,
|
query: web::Query<RemoteQuery>,
|
||||||
state: web::Data<watch::Receiver<RigState>>,
|
state: web::Data<watch::Receiver<RigState>>,
|
||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
@@ -876,37 +878,38 @@ pub async fn toggle_power(
|
|||||||
} else {
|
} else {
|
||||||
RigCommand::PowerOff
|
RigCommand::PowerOff
|
||||||
};
|
};
|
||||||
send_command(&rig_tx, cmd, query.into_inner().rig_id).await
|
send_command(&rig_tx, cmd, query.into_inner().remote).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/toggle_vfo")]
|
#[post("/toggle_vfo")]
|
||||||
pub async fn toggle_vfo(
|
pub async fn toggle_vfo(
|
||||||
query: web::Query<RigIdQuery>,
|
query: web::Query<RemoteQuery>,
|
||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
send_command(&rig_tx, RigCommand::ToggleVfo, query.into_inner().rig_id).await
|
send_command(&rig_tx, RigCommand::ToggleVfo, query.into_inner().remote).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/lock")]
|
#[post("/lock")]
|
||||||
pub async fn lock_panel(
|
pub async fn lock_panel(
|
||||||
query: web::Query<RigIdQuery>,
|
query: web::Query<RemoteQuery>,
|
||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
send_command(&rig_tx, RigCommand::Lock, query.into_inner().rig_id).await
|
send_command(&rig_tx, RigCommand::Lock, query.into_inner().remote).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/unlock")]
|
#[post("/unlock")]
|
||||||
pub async fn unlock_panel(
|
pub async fn unlock_panel(
|
||||||
query: web::Query<RigIdQuery>,
|
query: web::Query<RemoteQuery>,
|
||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
send_command(&rig_tx, RigCommand::Unlock, query.into_inner().rig_id).await
|
send_command(&rig_tx, RigCommand::Unlock, query.into_inner().remote).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct FreqQuery {
|
pub struct FreqQuery {
|
||||||
pub hz: u64,
|
pub hz: u64,
|
||||||
pub rig_id: Option<String>,
|
#[serde(alias = "rig_id")]
|
||||||
|
pub remote: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/set_freq")]
|
#[post("/set_freq")]
|
||||||
@@ -915,7 +918,7 @@ pub async fn set_freq(
|
|||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let q = query.into_inner();
|
let q = query.into_inner();
|
||||||
send_command(&rig_tx, RigCommand::SetFreq(Freq { hz: q.hz }), q.rig_id).await
|
send_command(&rig_tx, RigCommand::SetFreq(Freq { hz: q.hz }), q.remote).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/set_center_freq")]
|
#[post("/set_center_freq")]
|
||||||
@@ -927,7 +930,7 @@ pub async fn set_center_freq(
|
|||||||
send_command(
|
send_command(
|
||||||
&rig_tx,
|
&rig_tx,
|
||||||
RigCommand::SetCenterFreq(Freq { hz: q.hz }),
|
RigCommand::SetCenterFreq(Freq { hz: q.hz }),
|
||||||
q.rig_id,
|
q.remote,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@@ -935,7 +938,8 @@ pub async fn set_center_freq(
|
|||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct ModeQuery {
|
pub struct ModeQuery {
|
||||||
pub mode: String,
|
pub mode: String,
|
||||||
pub rig_id: Option<String>,
|
#[serde(alias = "rig_id")]
|
||||||
|
pub remote: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/set_mode")]
|
#[post("/set_mode")]
|
||||||
@@ -945,13 +949,14 @@ pub async fn set_mode(
|
|||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let q = query.into_inner();
|
let q = query.into_inner();
|
||||||
let mode = parse_mode(&q.mode);
|
let mode = parse_mode(&q.mode);
|
||||||
send_command(&rig_tx, RigCommand::SetMode(mode), q.rig_id).await
|
send_command(&rig_tx, RigCommand::SetMode(mode), q.remote).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct PttQuery {
|
pub struct PttQuery {
|
||||||
pub ptt: String,
|
pub ptt: String,
|
||||||
pub rig_id: Option<String>,
|
#[serde(alias = "rig_id")]
|
||||||
|
pub remote: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/set_ptt")]
|
#[post("/set_ptt")]
|
||||||
@@ -967,13 +972,14 @@ pub async fn set_ptt(
|
|||||||
"invalid ptt parameter: {other}"
|
"invalid ptt parameter: {other}"
|
||||||
))),
|
))),
|
||||||
}?;
|
}?;
|
||||||
send_command(&rig_tx, RigCommand::SetPtt(ptt), q.rig_id).await
|
send_command(&rig_tx, RigCommand::SetPtt(ptt), q.remote).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct TxLimitQuery {
|
pub struct TxLimitQuery {
|
||||||
pub limit: u8,
|
pub limit: u8,
|
||||||
pub rig_id: Option<String>,
|
#[serde(alias = "rig_id")]
|
||||||
|
pub remote: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/set_tx_limit")]
|
#[post("/set_tx_limit")]
|
||||||
@@ -982,13 +988,14 @@ pub async fn set_tx_limit(
|
|||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let q = query.into_inner();
|
let q = query.into_inner();
|
||||||
send_command(&rig_tx, RigCommand::SetTxLimit(q.limit), q.rig_id).await
|
send_command(&rig_tx, RigCommand::SetTxLimit(q.limit), q.remote).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct BandwidthQuery {
|
pub struct BandwidthQuery {
|
||||||
pub hz: u32,
|
pub hz: u32,
|
||||||
pub rig_id: Option<String>,
|
#[serde(alias = "rig_id")]
|
||||||
|
pub remote: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/set_bandwidth")]
|
#[post("/set_bandwidth")]
|
||||||
@@ -997,13 +1004,14 @@ pub async fn set_bandwidth(
|
|||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let q = query.into_inner();
|
let q = query.into_inner();
|
||||||
send_command(&rig_tx, RigCommand::SetBandwidth(q.hz), q.rig_id).await
|
send_command(&rig_tx, RigCommand::SetBandwidth(q.hz), q.remote).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct SdrGainQuery {
|
pub struct SdrGainQuery {
|
||||||
pub db: f64,
|
pub db: f64,
|
||||||
pub rig_id: Option<String>,
|
#[serde(alias = "rig_id")]
|
||||||
|
pub remote: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/set_sdr_gain")]
|
#[post("/set_sdr_gain")]
|
||||||
@@ -1012,13 +1020,14 @@ pub async fn set_sdr_gain(
|
|||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let q = query.into_inner();
|
let q = query.into_inner();
|
||||||
send_command(&rig_tx, RigCommand::SetSdrGain(q.db), q.rig_id).await
|
send_command(&rig_tx, RigCommand::SetSdrGain(q.db), q.remote).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct SdrLnaGainQuery {
|
pub struct SdrLnaGainQuery {
|
||||||
pub db: f64,
|
pub db: f64,
|
||||||
pub rig_id: Option<String>,
|
#[serde(alias = "rig_id")]
|
||||||
|
pub remote: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/set_sdr_lna_gain")]
|
#[post("/set_sdr_lna_gain")]
|
||||||
@@ -1027,13 +1036,14 @@ pub async fn set_sdr_lna_gain(
|
|||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let q = query.into_inner();
|
let q = query.into_inner();
|
||||||
send_command(&rig_tx, RigCommand::SetSdrLnaGain(q.db), q.rig_id).await
|
send_command(&rig_tx, RigCommand::SetSdrLnaGain(q.db), q.remote).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct SdrAgcQuery {
|
pub struct SdrAgcQuery {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub rig_id: Option<String>,
|
#[serde(alias = "rig_id")]
|
||||||
|
pub remote: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/set_sdr_agc")]
|
#[post("/set_sdr_agc")]
|
||||||
@@ -1042,14 +1052,15 @@ pub async fn set_sdr_agc(
|
|||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let q = query.into_inner();
|
let q = query.into_inner();
|
||||||
send_command(&rig_tx, RigCommand::SetSdrAgc(q.enabled), q.rig_id).await
|
send_command(&rig_tx, RigCommand::SetSdrAgc(q.enabled), q.remote).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct SdrSquelchQuery {
|
pub struct SdrSquelchQuery {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub threshold_db: f64,
|
pub threshold_db: f64,
|
||||||
pub rig_id: Option<String>,
|
#[serde(alias = "rig_id")]
|
||||||
|
pub remote: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/set_sdr_squelch")]
|
#[post("/set_sdr_squelch")]
|
||||||
@@ -1064,7 +1075,7 @@ pub async fn set_sdr_squelch(
|
|||||||
enabled: q.enabled,
|
enabled: q.enabled,
|
||||||
threshold_db: q.threshold_db,
|
threshold_db: q.threshold_db,
|
||||||
},
|
},
|
||||||
q.rig_id,
|
q.remote,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@@ -1073,7 +1084,8 @@ pub async fn set_sdr_squelch(
|
|||||||
pub struct SdrNoiseBlankerQuery {
|
pub struct SdrNoiseBlankerQuery {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub threshold: f64,
|
pub threshold: f64,
|
||||||
pub rig_id: Option<String>,
|
#[serde(alias = "rig_id")]
|
||||||
|
pub remote: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/set_sdr_noise_blanker")]
|
#[post("/set_sdr_noise_blanker")]
|
||||||
@@ -1088,7 +1100,7 @@ pub async fn set_sdr_noise_blanker(
|
|||||||
enabled: q.enabled,
|
enabled: q.enabled,
|
||||||
threshold: q.threshold,
|
threshold: q.threshold,
|
||||||
},
|
},
|
||||||
q.rig_id,
|
q.remote,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@@ -1096,7 +1108,8 @@ pub async fn set_sdr_noise_blanker(
|
|||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct WfmDeemphasisQuery {
|
pub struct WfmDeemphasisQuery {
|
||||||
pub us: u32,
|
pub us: u32,
|
||||||
pub rig_id: Option<String>,
|
#[serde(alias = "rig_id")]
|
||||||
|
pub remote: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/set_wfm_deemphasis")]
|
#[post("/set_wfm_deemphasis")]
|
||||||
@@ -1105,13 +1118,14 @@ pub async fn set_wfm_deemphasis(
|
|||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let q = query.into_inner();
|
let q = query.into_inner();
|
||||||
send_command(&rig_tx, RigCommand::SetWfmDeemphasis(q.us), q.rig_id).await
|
send_command(&rig_tx, RigCommand::SetWfmDeemphasis(q.us), q.remote).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct WfmStereoQuery {
|
pub struct WfmStereoQuery {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub rig_id: Option<String>,
|
#[serde(alias = "rig_id")]
|
||||||
|
pub remote: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/set_wfm_stereo")]
|
#[post("/set_wfm_stereo")]
|
||||||
@@ -1120,13 +1134,14 @@ pub async fn set_wfm_stereo(
|
|||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let q = query.into_inner();
|
let q = query.into_inner();
|
||||||
send_command(&rig_tx, RigCommand::SetWfmStereo(q.enabled), q.rig_id).await
|
send_command(&rig_tx, RigCommand::SetWfmStereo(q.enabled), q.remote).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct WfmDenoiseQuery {
|
pub struct WfmDenoiseQuery {
|
||||||
pub level: WfmDenoiseLevel,
|
pub level: WfmDenoiseLevel,
|
||||||
pub rig_id: Option<String>,
|
#[serde(alias = "rig_id")]
|
||||||
|
pub remote: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/set_wfm_denoise")]
|
#[post("/set_wfm_denoise")]
|
||||||
@@ -1135,12 +1150,12 @@ pub async fn set_wfm_denoise(
|
|||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let q = query.into_inner();
|
let q = query.into_inner();
|
||||||
send_command(&rig_tx, RigCommand::SetWfmDenoise(q.level), q.rig_id).await
|
send_command(&rig_tx, RigCommand::SetWfmDenoise(q.level), q.remote).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/toggle_aprs_decode")]
|
#[post("/toggle_aprs_decode")]
|
||||||
pub async fn toggle_aprs_decode(
|
pub async fn toggle_aprs_decode(
|
||||||
query: web::Query<RigIdQuery>,
|
query: web::Query<RemoteQuery>,
|
||||||
state: web::Data<watch::Receiver<RigState>>,
|
state: web::Data<watch::Receiver<RigState>>,
|
||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
@@ -1148,14 +1163,14 @@ pub async fn toggle_aprs_decode(
|
|||||||
send_command(
|
send_command(
|
||||||
&rig_tx,
|
&rig_tx,
|
||||||
RigCommand::SetAprsDecodeEnabled(!enabled),
|
RigCommand::SetAprsDecodeEnabled(!enabled),
|
||||||
query.into_inner().rig_id,
|
query.into_inner().remote,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/toggle_hf_aprs_decode")]
|
#[post("/toggle_hf_aprs_decode")]
|
||||||
pub async fn toggle_hf_aprs_decode(
|
pub async fn toggle_hf_aprs_decode(
|
||||||
query: web::Query<RigIdQuery>,
|
query: web::Query<RemoteQuery>,
|
||||||
state: web::Data<watch::Receiver<RigState>>,
|
state: web::Data<watch::Receiver<RigState>>,
|
||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
@@ -1163,14 +1178,14 @@ pub async fn toggle_hf_aprs_decode(
|
|||||||
send_command(
|
send_command(
|
||||||
&rig_tx,
|
&rig_tx,
|
||||||
RigCommand::SetHfAprsDecodeEnabled(!enabled),
|
RigCommand::SetHfAprsDecodeEnabled(!enabled),
|
||||||
query.into_inner().rig_id,
|
query.into_inner().remote,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/toggle_cw_decode")]
|
#[post("/toggle_cw_decode")]
|
||||||
pub async fn toggle_cw_decode(
|
pub async fn toggle_cw_decode(
|
||||||
query: web::Query<RigIdQuery>,
|
query: web::Query<RemoteQuery>,
|
||||||
state: web::Data<watch::Receiver<RigState>>,
|
state: web::Data<watch::Receiver<RigState>>,
|
||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
@@ -1178,7 +1193,7 @@ pub async fn toggle_cw_decode(
|
|||||||
send_command(
|
send_command(
|
||||||
&rig_tx,
|
&rig_tx,
|
||||||
RigCommand::SetCwDecodeEnabled(!enabled),
|
RigCommand::SetCwDecodeEnabled(!enabled),
|
||||||
query.into_inner().rig_id,
|
query.into_inner().remote,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@@ -1186,7 +1201,8 @@ pub async fn toggle_cw_decode(
|
|||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct CwAutoQuery {
|
pub struct CwAutoQuery {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub rig_id: Option<String>,
|
#[serde(alias = "rig_id")]
|
||||||
|
pub remote: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/set_cw_auto")]
|
#[post("/set_cw_auto")]
|
||||||
@@ -1195,13 +1211,14 @@ pub async fn set_cw_auto(
|
|||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let q = query.into_inner();
|
let q = query.into_inner();
|
||||||
send_command(&rig_tx, RigCommand::SetCwAuto(q.enabled), q.rig_id).await
|
send_command(&rig_tx, RigCommand::SetCwAuto(q.enabled), q.remote).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct CwWpmQuery {
|
pub struct CwWpmQuery {
|
||||||
pub wpm: u32,
|
pub wpm: u32,
|
||||||
pub rig_id: Option<String>,
|
#[serde(alias = "rig_id")]
|
||||||
|
pub remote: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/set_cw_wpm")]
|
#[post("/set_cw_wpm")]
|
||||||
@@ -1210,13 +1227,14 @@ pub async fn set_cw_wpm(
|
|||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let q = query.into_inner();
|
let q = query.into_inner();
|
||||||
send_command(&rig_tx, RigCommand::SetCwWpm(q.wpm), q.rig_id).await
|
send_command(&rig_tx, RigCommand::SetCwWpm(q.wpm), q.remote).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct CwToneQuery {
|
pub struct CwToneQuery {
|
||||||
pub tone_hz: u32,
|
pub tone_hz: u32,
|
||||||
pub rig_id: Option<String>,
|
#[serde(alias = "rig_id")]
|
||||||
|
pub remote: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/set_cw_tone")]
|
#[post("/set_cw_tone")]
|
||||||
@@ -1225,12 +1243,12 @@ pub async fn set_cw_tone(
|
|||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let q = query.into_inner();
|
let q = query.into_inner();
|
||||||
send_command(&rig_tx, RigCommand::SetCwToneHz(q.tone_hz), q.rig_id).await
|
send_command(&rig_tx, RigCommand::SetCwToneHz(q.tone_hz), q.remote).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/toggle_ft8_decode")]
|
#[post("/toggle_ft8_decode")]
|
||||||
pub async fn toggle_ft8_decode(
|
pub async fn toggle_ft8_decode(
|
||||||
query: web::Query<RigIdQuery>,
|
query: web::Query<RemoteQuery>,
|
||||||
state: web::Data<watch::Receiver<RigState>>,
|
state: web::Data<watch::Receiver<RigState>>,
|
||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
@@ -1238,14 +1256,14 @@ pub async fn toggle_ft8_decode(
|
|||||||
send_command(
|
send_command(
|
||||||
&rig_tx,
|
&rig_tx,
|
||||||
RigCommand::SetFt8DecodeEnabled(!enabled),
|
RigCommand::SetFt8DecodeEnabled(!enabled),
|
||||||
query.into_inner().rig_id,
|
query.into_inner().remote,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/toggle_ft4_decode")]
|
#[post("/toggle_ft4_decode")]
|
||||||
pub async fn toggle_ft4_decode(
|
pub async fn toggle_ft4_decode(
|
||||||
query: web::Query<RigIdQuery>,
|
query: web::Query<RemoteQuery>,
|
||||||
state: web::Data<watch::Receiver<RigState>>,
|
state: web::Data<watch::Receiver<RigState>>,
|
||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
@@ -1253,14 +1271,14 @@ pub async fn toggle_ft4_decode(
|
|||||||
send_command(
|
send_command(
|
||||||
&rig_tx,
|
&rig_tx,
|
||||||
RigCommand::SetFt4DecodeEnabled(!enabled),
|
RigCommand::SetFt4DecodeEnabled(!enabled),
|
||||||
query.into_inner().rig_id,
|
query.into_inner().remote,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/toggle_ft2_decode")]
|
#[post("/toggle_ft2_decode")]
|
||||||
pub async fn toggle_ft2_decode(
|
pub async fn toggle_ft2_decode(
|
||||||
query: web::Query<RigIdQuery>,
|
query: web::Query<RemoteQuery>,
|
||||||
state: web::Data<watch::Receiver<RigState>>,
|
state: web::Data<watch::Receiver<RigState>>,
|
||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
@@ -1268,14 +1286,14 @@ pub async fn toggle_ft2_decode(
|
|||||||
send_command(
|
send_command(
|
||||||
&rig_tx,
|
&rig_tx,
|
||||||
RigCommand::SetFt2DecodeEnabled(!enabled),
|
RigCommand::SetFt2DecodeEnabled(!enabled),
|
||||||
query.into_inner().rig_id,
|
query.into_inner().remote,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/toggle_wspr_decode")]
|
#[post("/toggle_wspr_decode")]
|
||||||
pub async fn toggle_wspr_decode(
|
pub async fn toggle_wspr_decode(
|
||||||
query: web::Query<RigIdQuery>,
|
query: web::Query<RemoteQuery>,
|
||||||
state: web::Data<watch::Receiver<RigState>>,
|
state: web::Data<watch::Receiver<RigState>>,
|
||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
@@ -1283,14 +1301,14 @@ pub async fn toggle_wspr_decode(
|
|||||||
send_command(
|
send_command(
|
||||||
&rig_tx,
|
&rig_tx,
|
||||||
RigCommand::SetWsprDecodeEnabled(!enabled),
|
RigCommand::SetWsprDecodeEnabled(!enabled),
|
||||||
query.into_inner().rig_id,
|
query.into_inner().remote,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/clear_ft8_decode")]
|
#[post("/clear_ft8_decode")]
|
||||||
pub async fn clear_ft8_decode(
|
pub async fn clear_ft8_decode(
|
||||||
query: web::Query<RigIdQuery>,
|
query: web::Query<RemoteQuery>,
|
||||||
context: web::Data<Arc<FrontendRuntimeContext>>,
|
context: web::Data<Arc<FrontendRuntimeContext>>,
|
||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
@@ -1298,14 +1316,14 @@ pub async fn clear_ft8_decode(
|
|||||||
send_command(
|
send_command(
|
||||||
&rig_tx,
|
&rig_tx,
|
||||||
RigCommand::ResetFt8Decoder,
|
RigCommand::ResetFt8Decoder,
|
||||||
query.into_inner().rig_id,
|
query.into_inner().remote,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/clear_ft4_decode")]
|
#[post("/clear_ft4_decode")]
|
||||||
pub async fn clear_ft4_decode(
|
pub async fn clear_ft4_decode(
|
||||||
query: web::Query<RigIdQuery>,
|
query: web::Query<RemoteQuery>,
|
||||||
context: web::Data<Arc<FrontendRuntimeContext>>,
|
context: web::Data<Arc<FrontendRuntimeContext>>,
|
||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
@@ -1313,14 +1331,14 @@ pub async fn clear_ft4_decode(
|
|||||||
send_command(
|
send_command(
|
||||||
&rig_tx,
|
&rig_tx,
|
||||||
RigCommand::ResetFt4Decoder,
|
RigCommand::ResetFt4Decoder,
|
||||||
query.into_inner().rig_id,
|
query.into_inner().remote,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/clear_ft2_decode")]
|
#[post("/clear_ft2_decode")]
|
||||||
pub async fn clear_ft2_decode(
|
pub async fn clear_ft2_decode(
|
||||||
query: web::Query<RigIdQuery>,
|
query: web::Query<RemoteQuery>,
|
||||||
context: web::Data<Arc<FrontendRuntimeContext>>,
|
context: web::Data<Arc<FrontendRuntimeContext>>,
|
||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
@@ -1328,14 +1346,14 @@ pub async fn clear_ft2_decode(
|
|||||||
send_command(
|
send_command(
|
||||||
&rig_tx,
|
&rig_tx,
|
||||||
RigCommand::ResetFt2Decoder,
|
RigCommand::ResetFt2Decoder,
|
||||||
query.into_inner().rig_id,
|
query.into_inner().remote,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/clear_wspr_decode")]
|
#[post("/clear_wspr_decode")]
|
||||||
pub async fn clear_wspr_decode(
|
pub async fn clear_wspr_decode(
|
||||||
query: web::Query<RigIdQuery>,
|
query: web::Query<RemoteQuery>,
|
||||||
context: web::Data<Arc<FrontendRuntimeContext>>,
|
context: web::Data<Arc<FrontendRuntimeContext>>,
|
||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
@@ -1343,14 +1361,14 @@ pub async fn clear_wspr_decode(
|
|||||||
send_command(
|
send_command(
|
||||||
&rig_tx,
|
&rig_tx,
|
||||||
RigCommand::ResetWsprDecoder,
|
RigCommand::ResetWsprDecoder,
|
||||||
query.into_inner().rig_id,
|
query.into_inner().remote,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/clear_aprs_decode")]
|
#[post("/clear_aprs_decode")]
|
||||||
pub async fn clear_aprs_decode(
|
pub async fn clear_aprs_decode(
|
||||||
query: web::Query<RigIdQuery>,
|
query: web::Query<RemoteQuery>,
|
||||||
context: web::Data<Arc<FrontendRuntimeContext>>,
|
context: web::Data<Arc<FrontendRuntimeContext>>,
|
||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
@@ -1358,14 +1376,14 @@ pub async fn clear_aprs_decode(
|
|||||||
send_command(
|
send_command(
|
||||||
&rig_tx,
|
&rig_tx,
|
||||||
RigCommand::ResetAprsDecoder,
|
RigCommand::ResetAprsDecoder,
|
||||||
query.into_inner().rig_id,
|
query.into_inner().remote,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/clear_hf_aprs_decode")]
|
#[post("/clear_hf_aprs_decode")]
|
||||||
pub async fn clear_hf_aprs_decode(
|
pub async fn clear_hf_aprs_decode(
|
||||||
query: web::Query<RigIdQuery>,
|
query: web::Query<RemoteQuery>,
|
||||||
context: web::Data<Arc<FrontendRuntimeContext>>,
|
context: web::Data<Arc<FrontendRuntimeContext>>,
|
||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
@@ -1373,7 +1391,7 @@ pub async fn clear_hf_aprs_decode(
|
|||||||
send_command(
|
send_command(
|
||||||
&rig_tx,
|
&rig_tx,
|
||||||
RigCommand::ResetHfAprsDecoder,
|
RigCommand::ResetHfAprsDecoder,
|
||||||
query.into_inner().rig_id,
|
query.into_inner().remote,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@@ -1396,7 +1414,7 @@ pub async fn clear_vdes_decode(
|
|||||||
|
|
||||||
#[post("/clear_cw_decode")]
|
#[post("/clear_cw_decode")]
|
||||||
pub async fn clear_cw_decode(
|
pub async fn clear_cw_decode(
|
||||||
query: web::Query<RigIdQuery>,
|
query: web::Query<RemoteQuery>,
|
||||||
context: web::Data<Arc<FrontendRuntimeContext>>,
|
context: web::Data<Arc<FrontendRuntimeContext>>,
|
||||||
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
rig_tx: web::Data<mpsc::Sender<RigRequest>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
@@ -1404,7 +1422,7 @@ pub async fn clear_cw_decode(
|
|||||||
send_command(
|
send_command(
|
||||||
&rig_tx,
|
&rig_tx,
|
||||||
RigCommand::ResetCwDecoder,
|
RigCommand::ResetCwDecoder,
|
||||||
query.into_inner().rig_id,
|
query.into_inner().remote,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@@ -1594,7 +1612,7 @@ pub async fn batch_delete_bookmarks(
|
|||||||
|
|
||||||
#[derive(serde::Serialize)]
|
#[derive(serde::Serialize)]
|
||||||
struct RigListItem {
|
struct RigListItem {
|
||||||
rig_id: String,
|
remote: String,
|
||||||
display_name: Option<String>,
|
display_name: Option<String>,
|
||||||
manufacturer: String,
|
manufacturer: String,
|
||||||
model: String,
|
model: String,
|
||||||
@@ -1603,12 +1621,12 @@ struct RigListItem {
|
|||||||
|
|
||||||
#[derive(serde::Serialize)]
|
#[derive(serde::Serialize)]
|
||||||
struct RigListResponse {
|
struct RigListResponse {
|
||||||
active_rig_id: Option<String>,
|
active_remote: Option<String>,
|
||||||
rigs: Vec<RigListItem>,
|
rigs: Vec<RigListItem>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_rig_list_payload(context: &FrontendRuntimeContext) -> RigListResponse {
|
fn build_rig_list_payload(context: &FrontendRuntimeContext) -> RigListResponse {
|
||||||
let active_rig_id = active_rig_id_from_context(context);
|
let active_remote = active_rig_id_from_context(context);
|
||||||
let rigs = context
|
let rigs = context
|
||||||
.remote_rigs
|
.remote_rigs
|
||||||
.lock()
|
.lock()
|
||||||
@@ -1616,14 +1634,14 @@ fn build_rig_list_payload(context: &FrontendRuntimeContext) -> RigListResponse {
|
|||||||
.map(|entries| entries.iter().map(map_rig_entry).collect())
|
.map(|entries| entries.iter().map(map_rig_entry).collect())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
RigListResponse {
|
RigListResponse {
|
||||||
active_rig_id,
|
active_remote,
|
||||||
rigs,
|
rigs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_rig_entry(entry: &RemoteRigEntry) -> RigListItem {
|
fn map_rig_entry(entry: &RemoteRigEntry) -> RigListItem {
|
||||||
RigListItem {
|
RigListItem {
|
||||||
rig_id: entry.rig_id.clone(),
|
remote: entry.rig_id.clone(),
|
||||||
display_name: entry.display_name.clone(),
|
display_name: entry.display_name.clone(),
|
||||||
manufacturer: entry.state.info.manufacturer.clone(),
|
manufacturer: entry.state.info.manufacturer.clone(),
|
||||||
model: entry.state.info.model.clone(),
|
model: entry.state.info.model.clone(),
|
||||||
@@ -1640,7 +1658,8 @@ pub async fn list_rigs(
|
|||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct SelectRigQuery {
|
pub struct SelectRigQuery {
|
||||||
pub rig_id: String,
|
#[serde(alias = "rig_id")]
|
||||||
|
pub remote: String,
|
||||||
pub session_id: Option<String>,
|
pub session_id: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1651,10 +1670,10 @@ pub async fn select_rig(
|
|||||||
vchan_mgr: web::Data<Arc<ClientChannelManager>>,
|
vchan_mgr: web::Data<Arc<ClientChannelManager>>,
|
||||||
session_rig_mgr: web::Data<Arc<SessionRigManager>>,
|
session_rig_mgr: web::Data<Arc<SessionRigManager>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let rig_id = query.rig_id.trim();
|
let remote = query.remote.trim();
|
||||||
if rig_id.is_empty() {
|
if remote.is_empty() {
|
||||||
return Err(actix_web::error::ErrorBadRequest(
|
return Err(actix_web::error::ErrorBadRequest(
|
||||||
"rig_id must not be empty",
|
"remote must not be empty",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1662,11 +1681,11 @@ pub async fn select_rig(
|
|||||||
.remote_rigs
|
.remote_rigs
|
||||||
.lock()
|
.lock()
|
||||||
.ok()
|
.ok()
|
||||||
.map(|entries| entries.iter().any(|entry| entry.rig_id == rig_id))
|
.map(|entries| entries.iter().any(|entry| entry.rig_id == remote))
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
if !known {
|
if !known {
|
||||||
return Err(actix_web::error::ErrorBadRequest(format!(
|
return Err(actix_web::error::ErrorBadRequest(format!(
|
||||||
"unknown rig_id: {rig_id}"
|
"unknown remote: {remote}"
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1674,15 +1693,15 @@ pub async fn select_rig(
|
|||||||
// active rig so that other tabs/sessions are unaffected.
|
// active rig so that other tabs/sessions are unaffected.
|
||||||
if let Some(ref sid) = query.session_id {
|
if let Some(ref sid) = query.session_id {
|
||||||
if let Ok(uuid) = Uuid::parse_str(sid) {
|
if let Ok(uuid) = Uuid::parse_str(sid) {
|
||||||
session_rig_mgr.set_rig(uuid, rig_id.to_string());
|
session_rig_mgr.set_rig(uuid, remote.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Broadcast the channel list for the newly selected rig so all SSE
|
// Broadcast the channel list for the newly selected rig so all SSE
|
||||||
// clients receive the correct virtual channels immediately.
|
// clients receive the correct virtual channels immediately.
|
||||||
let chans = vchan_mgr.channels(rig_id);
|
let chans = vchan_mgr.channels(remote);
|
||||||
if let Ok(json) = serde_json::to_string(&chans) {
|
if let Ok(json) = serde_json::to_string(&chans) {
|
||||||
let _ = vchan_mgr.change_tx.send(format!("{rig_id}:{json}"));
|
let _ = vchan_mgr.change_tx.send(format!("{remote}:{json}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().json(build_rig_list_payload(context.get_ref().as_ref())))
|
Ok(HttpResponse::Ok().json(build_rig_list_payload(context.get_ref().as_ref())))
|
||||||
@@ -1692,13 +1711,13 @@ pub async fn select_rig(
|
|||||||
// Virtual channel CRUD
|
// Virtual channel CRUD
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
#[get("/channels/{rig_id}")]
|
#[get("/channels/{remote}")]
|
||||||
pub async fn list_channels(
|
pub async fn list_channels(
|
||||||
path: web::Path<String>,
|
path: web::Path<String>,
|
||||||
vchan_mgr: web::Data<Arc<ClientChannelManager>>,
|
vchan_mgr: web::Data<Arc<ClientChannelManager>>,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let rig_id = path.into_inner();
|
let remote = path.into_inner();
|
||||||
HttpResponse::Ok().json(vchan_mgr.channels(&rig_id))
|
HttpResponse::Ok().json(vchan_mgr.channels(&remote))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
@@ -1708,26 +1727,26 @@ struct AllocateChannelBody {
|
|||||||
mode: String,
|
mode: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/channels/{rig_id}")]
|
#[post("/channels/{remote}")]
|
||||||
pub async fn allocate_channel(
|
pub async fn allocate_channel(
|
||||||
path: web::Path<String>,
|
path: web::Path<String>,
|
||||||
body: web::Json<AllocateChannelBody>,
|
body: web::Json<AllocateChannelBody>,
|
||||||
vchan_mgr: web::Data<Arc<ClientChannelManager>>,
|
vchan_mgr: web::Data<Arc<ClientChannelManager>>,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let rig_id = path.into_inner();
|
let remote = path.into_inner();
|
||||||
match vchan_mgr.allocate(body.session_id, &rig_id, body.freq_hz, &body.mode) {
|
match vchan_mgr.allocate(body.session_id, &remote, body.freq_hz, &body.mode) {
|
||||||
Ok(ch) => HttpResponse::Ok().json(ch),
|
Ok(ch) => HttpResponse::Ok().json(ch),
|
||||||
Err(e) => HttpResponse::BadRequest().body(e.to_string()),
|
Err(e) => HttpResponse::BadRequest().body(e.to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[delete("/channels/{rig_id}/{channel_id}")]
|
#[delete("/channels/{remote}/{channel_id}")]
|
||||||
pub async fn delete_channel_route(
|
pub async fn delete_channel_route(
|
||||||
path: web::Path<(String, Uuid)>,
|
path: web::Path<(String, Uuid)>,
|
||||||
vchan_mgr: web::Data<Arc<ClientChannelManager>>,
|
vchan_mgr: web::Data<Arc<ClientChannelManager>>,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let (rig_id, channel_id) = path.into_inner();
|
let (remote, channel_id) = path.into_inner();
|
||||||
match vchan_mgr.delete_channel(&rig_id, channel_id) {
|
match vchan_mgr.delete_channel(&remote, channel_id) {
|
||||||
Ok(()) => HttpResponse::Ok().finish(),
|
Ok(()) => HttpResponse::Ok().finish(),
|
||||||
Err(crate::server::vchan::VChanClientError::NotFound) => HttpResponse::NotFound().finish(),
|
Err(crate::server::vchan::VChanClientError::NotFound) => HttpResponse::NotFound().finish(),
|
||||||
Err(crate::server::vchan::VChanClientError::Permanent) => {
|
Err(crate::server::vchan::VChanClientError::Permanent) => {
|
||||||
@@ -1742,7 +1761,7 @@ struct SubscribeBody {
|
|||||||
session_id: Uuid,
|
session_id: Uuid,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/channels/{rig_id}/{channel_id}/subscribe")]
|
#[post("/channels/{remote}/{channel_id}/subscribe")]
|
||||||
pub async fn subscribe_channel(
|
pub async fn subscribe_channel(
|
||||||
path: web::Path<(String, Uuid)>,
|
path: web::Path<(String, Uuid)>,
|
||||||
body: web::Json<SubscribeBody>,
|
body: web::Json<SubscribeBody>,
|
||||||
@@ -1752,16 +1771,16 @@ pub async fn subscribe_channel(
|
|||||||
scheduler_control: web::Data<crate::server::scheduler::SharedSchedulerControlManager>,
|
scheduler_control: web::Data<crate::server::scheduler::SharedSchedulerControlManager>,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let body = body.into_inner();
|
let body = body.into_inner();
|
||||||
let (rig_id, channel_id) = path.into_inner();
|
let (remote, channel_id) = path.into_inner();
|
||||||
match vchan_mgr.subscribe_session(body.session_id, &rig_id, channel_id) {
|
match vchan_mgr.subscribe_session(body.session_id, &remote, channel_id) {
|
||||||
Some(ch) => {
|
Some(ch) => {
|
||||||
scheduler_control.set_released(body.session_id, false);
|
scheduler_control.set_released(body.session_id, false);
|
||||||
let Some(selected) = vchan_mgr.selected_channel(&rig_id, channel_id) else {
|
let Some(selected) = vchan_mgr.selected_channel(&remote, channel_id) else {
|
||||||
return HttpResponse::InternalServerError().body("subscribed channel missing");
|
return HttpResponse::InternalServerError().body("subscribed channel missing");
|
||||||
};
|
};
|
||||||
if let Err(err) = apply_selected_channel(
|
if let Err(err) = apply_selected_channel(
|
||||||
rig_tx.get_ref(),
|
rig_tx.get_ref(),
|
||||||
&rig_id,
|
&remote,
|
||||||
&selected,
|
&selected,
|
||||||
bookmark_store.get_ref().as_ref(),
|
bookmark_store.get_ref().as_ref(),
|
||||||
)
|
)
|
||||||
@@ -1780,14 +1799,14 @@ struct SetChanFreqBody {
|
|||||||
freq_hz: u64,
|
freq_hz: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[put("/channels/{rig_id}/{channel_id}/freq")]
|
#[put("/channels/{remote}/{channel_id}/freq")]
|
||||||
pub async fn set_vchan_freq(
|
pub async fn set_vchan_freq(
|
||||||
path: web::Path<(String, Uuid)>,
|
path: web::Path<(String, Uuid)>,
|
||||||
body: web::Json<SetChanFreqBody>,
|
body: web::Json<SetChanFreqBody>,
|
||||||
vchan_mgr: web::Data<Arc<ClientChannelManager>>,
|
vchan_mgr: web::Data<Arc<ClientChannelManager>>,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let (rig_id, channel_id) = path.into_inner();
|
let (remote, channel_id) = path.into_inner();
|
||||||
match vchan_mgr.set_channel_freq(&rig_id, channel_id, body.freq_hz) {
|
match vchan_mgr.set_channel_freq(&remote, channel_id, body.freq_hz) {
|
||||||
Ok(()) => HttpResponse::Ok().finish(),
|
Ok(()) => HttpResponse::Ok().finish(),
|
||||||
Err(crate::server::vchan::VChanClientError::NotFound) => HttpResponse::NotFound().finish(),
|
Err(crate::server::vchan::VChanClientError::NotFound) => HttpResponse::NotFound().finish(),
|
||||||
Err(e) => HttpResponse::BadRequest().body(e.to_string()),
|
Err(e) => HttpResponse::BadRequest().body(e.to_string()),
|
||||||
@@ -1799,14 +1818,14 @@ struct SetChanBwBody {
|
|||||||
bandwidth_hz: u32,
|
bandwidth_hz: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[put("/channels/{rig_id}/{channel_id}/bw")]
|
#[put("/channels/{remote}/{channel_id}/bw")]
|
||||||
pub async fn set_vchan_bw(
|
pub async fn set_vchan_bw(
|
||||||
path: web::Path<(String, Uuid)>,
|
path: web::Path<(String, Uuid)>,
|
||||||
body: web::Json<SetChanBwBody>,
|
body: web::Json<SetChanBwBody>,
|
||||||
vchan_mgr: web::Data<Arc<ClientChannelManager>>,
|
vchan_mgr: web::Data<Arc<ClientChannelManager>>,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let (rig_id, channel_id) = path.into_inner();
|
let (remote, channel_id) = path.into_inner();
|
||||||
match vchan_mgr.set_channel_bandwidth(&rig_id, channel_id, body.bandwidth_hz) {
|
match vchan_mgr.set_channel_bandwidth(&remote, channel_id, body.bandwidth_hz) {
|
||||||
Ok(()) => HttpResponse::Ok().finish(),
|
Ok(()) => HttpResponse::Ok().finish(),
|
||||||
Err(crate::server::vchan::VChanClientError::NotFound) => HttpResponse::NotFound().finish(),
|
Err(crate::server::vchan::VChanClientError::NotFound) => HttpResponse::NotFound().finish(),
|
||||||
Err(e) => HttpResponse::BadRequest().body(e.to_string()),
|
Err(e) => HttpResponse::BadRequest().body(e.to_string()),
|
||||||
@@ -1818,14 +1837,14 @@ struct SetChanModeBody {
|
|||||||
mode: String,
|
mode: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[put("/channels/{rig_id}/{channel_id}/mode")]
|
#[put("/channels/{remote}/{channel_id}/mode")]
|
||||||
pub async fn set_vchan_mode(
|
pub async fn set_vchan_mode(
|
||||||
path: web::Path<(String, Uuid)>,
|
path: web::Path<(String, Uuid)>,
|
||||||
body: web::Json<SetChanModeBody>,
|
body: web::Json<SetChanModeBody>,
|
||||||
vchan_mgr: web::Data<Arc<ClientChannelManager>>,
|
vchan_mgr: web::Data<Arc<ClientChannelManager>>,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let (rig_id, channel_id) = path.into_inner();
|
let (remote, channel_id) = path.into_inner();
|
||||||
match vchan_mgr.set_channel_mode(&rig_id, channel_id, &body.mode) {
|
match vchan_mgr.set_channel_mode(&remote, channel_id, &body.mode) {
|
||||||
Ok(()) => HttpResponse::Ok().finish(),
|
Ok(()) => HttpResponse::Ok().finish(),
|
||||||
Err(crate::server::vchan::VChanClientError::NotFound) => HttpResponse::NotFound().finish(),
|
Err(crate::server::vchan::VChanClientError::NotFound) => HttpResponse::NotFound().finish(),
|
||||||
Err(e) => HttpResponse::BadRequest().body(e.to_string()),
|
Err(e) => HttpResponse::BadRequest().body(e.to_string()),
|
||||||
@@ -2169,23 +2188,24 @@ async fn vchan_js() -> impl Responder {
|
|||||||
.body(status::VCHAN_JS)
|
.body(status::VCHAN_JS)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generic query extractor for endpoints that only need the optional rig_id.
|
/// Generic query extractor for endpoints that only need the optional remote.
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct RigIdQuery {
|
pub struct RemoteQuery {
|
||||||
pub rig_id: Option<String>,
|
#[serde(alias = "rig_id")]
|
||||||
|
pub remote: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_command(
|
async fn send_command(
|
||||||
rig_tx: &mpsc::Sender<RigRequest>,
|
rig_tx: &mpsc::Sender<RigRequest>,
|
||||||
cmd: RigCommand,
|
cmd: RigCommand,
|
||||||
rig_id: Option<String>,
|
remote: Option<String>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let (resp_tx, resp_rx) = oneshot::channel();
|
let (resp_tx, resp_rx) = oneshot::channel();
|
||||||
rig_tx
|
rig_tx
|
||||||
.send(RigRequest {
|
.send(RigRequest {
|
||||||
cmd,
|
cmd,
|
||||||
respond_to: resp_tx,
|
respond_to: resp_tx,
|
||||||
rig_id_override: rig_id,
|
rig_id_override: remote,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
@@ -2219,7 +2239,7 @@ async fn send_command(
|
|||||||
|
|
||||||
async fn send_command_to_rig(
|
async fn send_command_to_rig(
|
||||||
rig_tx: &mpsc::Sender<RigRequest>,
|
rig_tx: &mpsc::Sender<RigRequest>,
|
||||||
rig_id: &str,
|
remote: &str,
|
||||||
cmd: RigCommand,
|
cmd: RigCommand,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let (resp_tx, resp_rx) = oneshot::channel();
|
let (resp_tx, resp_rx) = oneshot::channel();
|
||||||
@@ -2227,7 +2247,7 @@ async fn send_command_to_rig(
|
|||||||
.send(RigRequest {
|
.send(RigRequest {
|
||||||
cmd,
|
cmd,
|
||||||
respond_to: resp_tx,
|
respond_to: resp_tx,
|
||||||
rig_id_override: Some(rig_id.to_string()),
|
rig_id_override: Some(remote.to_string()),
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
@@ -2312,13 +2332,13 @@ fn bookmark_decoder_kinds(bookmark: &crate::server::bookmarks::Bookmark) -> Vec<
|
|||||||
|
|
||||||
async fn apply_selected_channel(
|
async fn apply_selected_channel(
|
||||||
rig_tx: &mpsc::Sender<RigRequest>,
|
rig_tx: &mpsc::Sender<RigRequest>,
|
||||||
rig_id: &str,
|
remote: &str,
|
||||||
channel: &crate::server::vchan::SelectedChannel,
|
channel: &crate::server::vchan::SelectedChannel,
|
||||||
bookmark_store: &crate::server::bookmarks::BookmarkStore,
|
bookmark_store: &crate::server::bookmarks::BookmarkStore,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
send_command_to_rig(
|
send_command_to_rig(
|
||||||
rig_tx,
|
rig_tx,
|
||||||
rig_id,
|
remote,
|
||||||
RigCommand::SetMode(parse_mode(&channel.mode)),
|
RigCommand::SetMode(parse_mode(&channel.mode)),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -2326,7 +2346,7 @@ async fn apply_selected_channel(
|
|||||||
if channel.bandwidth_hz > 0 {
|
if channel.bandwidth_hz > 0 {
|
||||||
send_command_to_rig(
|
send_command_to_rig(
|
||||||
rig_tx,
|
rig_tx,
|
||||||
rig_id,
|
remote,
|
||||||
RigCommand::SetBandwidth(channel.bandwidth_hz),
|
RigCommand::SetBandwidth(channel.bandwidth_hz),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -2334,7 +2354,7 @@ async fn apply_selected_channel(
|
|||||||
|
|
||||||
send_command_to_rig(
|
send_command_to_rig(
|
||||||
rig_tx,
|
rig_tx,
|
||||||
rig_id,
|
remote,
|
||||||
RigCommand::SetFreq(Freq {
|
RigCommand::SetFreq(Freq {
|
||||||
hz: channel.freq_hz,
|
hz: channel.freq_hz,
|
||||||
}),
|
}),
|
||||||
@@ -2358,7 +2378,7 @@ async fn apply_selected_channel(
|
|||||||
RigCommand::SetWsprDecodeEnabled(want_wspr),
|
RigCommand::SetWsprDecodeEnabled(want_wspr),
|
||||||
];
|
];
|
||||||
for cmd in desired {
|
for cmd in desired {
|
||||||
send_command_to_rig(rig_tx, rig_id, cmd).await?;
|
send_command_to_rig(rig_tx, remote, cmd).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -90,7 +90,8 @@ pub struct ScheduleEntry {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
pub struct SchedulerConfig {
|
pub struct SchedulerConfig {
|
||||||
pub rig_id: String,
|
#[serde(alias = "rig_id")]
|
||||||
|
pub remote: String,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub mode: SchedulerMode,
|
pub mode: SchedulerMode,
|
||||||
pub grayline: Option<GraylineConfig>,
|
pub grayline: Option<GraylineConfig>,
|
||||||
@@ -147,19 +148,19 @@ impl SchedulerStore {
|
|||||||
.unwrap_or_else(|| PathBuf::from("scheduler.db"))
|
.unwrap_or_else(|| PathBuf::from("scheduler.db"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, rig_id: &str) -> Option<SchedulerConfig> {
|
pub fn get(&self, remote: &str) -> Option<SchedulerConfig> {
|
||||||
let db = self.db.read().unwrap_or_else(|e| e.into_inner());
|
let db = self.db.read().unwrap_or_else(|e| e.into_inner());
|
||||||
db.get::<SchedulerConfig>(&format!("sch:{rig_id}"))
|
db.get::<SchedulerConfig>(&format!("sch:{remote}"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn upsert(&self, config: &SchedulerConfig) -> bool {
|
pub fn upsert(&self, config: &SchedulerConfig) -> bool {
|
||||||
let mut db = self.db.write().unwrap_or_else(|e| e.into_inner());
|
let mut db = self.db.write().unwrap_or_else(|e| e.into_inner());
|
||||||
db.set(&format!("sch:{}", config.rig_id), config).is_ok()
|
db.set(&format!("sch:{}", config.remote), config).is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove(&self, rig_id: &str) -> bool {
|
pub fn remove(&self, remote: &str) -> bool {
|
||||||
let mut db = self.db.write().unwrap_or_else(|e| e.into_inner());
|
let mut db = self.db.write().unwrap_or_else(|e| e.into_inner());
|
||||||
db.rem(&format!("sch:{rig_id}")).unwrap_or(false)
|
db.rem(&format!("sch:{remote}")).unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_all(&self) -> Vec<SchedulerConfig> {
|
pub fn list_all(&self) -> Vec<SchedulerConfig> {
|
||||||
@@ -422,7 +423,7 @@ pub struct SchedulerStatus {
|
|||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
async fn apply_scheduler_target(
|
async fn apply_scheduler_target(
|
||||||
rig_tx: &mpsc::Sender<RigRequest>,
|
rig_tx: &mpsc::Sender<RigRequest>,
|
||||||
rig_id: &str,
|
remote: &str,
|
||||||
status_map: &SchedulerStatusMap,
|
status_map: &SchedulerStatusMap,
|
||||||
bookmarks: &BookmarkStore,
|
bookmarks: &BookmarkStore,
|
||||||
entry_id: Option<&str>,
|
entry_id: Option<&str>,
|
||||||
@@ -432,7 +433,7 @@ async fn apply_scheduler_target(
|
|||||||
) -> Result<SchedulerStatus, String> {
|
) -> Result<SchedulerStatus, String> {
|
||||||
let bookmark = bookmarks
|
let bookmark = bookmarks
|
||||||
.get(bookmark_id)
|
.get(bookmark_id)
|
||||||
.ok_or_else(|| format!("bookmark '{bookmark_id}' not found for rig '{rig_id}'"))?;
|
.ok_or_else(|| format!("bookmark '{bookmark_id}' not found for remote '{remote}'"))?;
|
||||||
|
|
||||||
let extra_bookmarks: Vec<_> = extra_bm_ids
|
let extra_bookmarks: Vec<_> = extra_bm_ids
|
||||||
.iter()
|
.iter()
|
||||||
@@ -443,7 +444,7 @@ async fn apply_scheduler_target(
|
|||||||
scheduler_send(
|
scheduler_send(
|
||||||
rig_tx,
|
rig_tx,
|
||||||
RigCommand::SetCenterFreq(Freq { hz: chz }),
|
RigCommand::SetCenterFreq(Freq { hz: chz }),
|
||||||
rig_id.to_string(),
|
remote.to_string(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
@@ -453,18 +454,18 @@ async fn apply_scheduler_target(
|
|||||||
RigCommand::SetFreq(Freq {
|
RigCommand::SetFreq(Freq {
|
||||||
hz: bookmark.freq_hz,
|
hz: bookmark.freq_hz,
|
||||||
}),
|
}),
|
||||||
rig_id.to_string(),
|
remote.to_string(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
scheduler_send(
|
scheduler_send(
|
||||||
rig_tx,
|
rig_tx,
|
||||||
RigCommand::SetMode(trx_protocol::parse_mode(&bookmark.mode)),
|
RigCommand::SetMode(trx_protocol::parse_mode(&bookmark.mode)),
|
||||||
rig_id.to_string(),
|
remote.to_string(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
apply_scheduler_decoders(rig_tx, rig_id, &bookmark, &extra_bookmarks).await;
|
apply_scheduler_decoders(rig_tx, remote, &bookmark, &extra_bookmarks).await;
|
||||||
|
|
||||||
let status = SchedulerStatus {
|
let status = SchedulerStatus {
|
||||||
active: true,
|
active: true,
|
||||||
@@ -483,7 +484,7 @@ async fn apply_scheduler_target(
|
|||||||
|
|
||||||
{
|
{
|
||||||
let mut map = status_map.write().unwrap_or_else(|e| e.into_inner());
|
let mut map = status_map.write().unwrap_or_else(|e| e.into_inner());
|
||||||
map.insert(rig_id.to_string(), status.clone());
|
map.insert(remote.to_string(), status.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(status)
|
Ok(status)
|
||||||
@@ -633,26 +634,26 @@ pub fn spawn_scheduler_task(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Already at this exact scheduled target — skip.
|
// Already at this exact scheduled target — skip.
|
||||||
if last_applied.get(&config.rig_id) == Some(&target) {
|
if last_applied.get(&config.remote) == Some(&target) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(bm) = bookmarks.get(&bm_id) else {
|
let Some(bm) = bookmarks.get(&bm_id) else {
|
||||||
warn!(
|
warn!(
|
||||||
"scheduler: bookmark '{}' not found for rig '{}'",
|
"scheduler: bookmark '{}' not found for remote '{}'",
|
||||||
bm_id, config.rig_id
|
bm_id, config.remote
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
"scheduler: rig '{}' → bookmark '{}' ({} Hz {})",
|
"scheduler: remote '{}' → bookmark '{}' ({} Hz {})",
|
||||||
config.rig_id, bm.name, bm.freq_hz, bm.mode
|
config.remote, bm.name, bm.freq_hz, bm.mode
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Err(e) = apply_scheduler_target(
|
if let Err(e) = apply_scheduler_target(
|
||||||
&rig_tx,
|
&rig_tx,
|
||||||
&config.rig_id,
|
&config.remote,
|
||||||
&status_map,
|
&status_map,
|
||||||
&bookmarks,
|
&bookmarks,
|
||||||
entry_id.as_deref(),
|
entry_id.as_deref(),
|
||||||
@@ -664,12 +665,12 @@ pub fn spawn_scheduler_task(
|
|||||||
{
|
{
|
||||||
warn!(
|
warn!(
|
||||||
"scheduler: failed to apply target for '{}': {e}",
|
"scheduler: failed to apply target for '{}': {e}",
|
||||||
config.rig_id
|
config.remote
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
last_applied.insert(config.rig_id.clone(), target);
|
last_applied.insert(config.remote.clone(), target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -677,7 +678,7 @@ pub fn spawn_scheduler_task(
|
|||||||
|
|
||||||
async fn apply_scheduler_decoders(
|
async fn apply_scheduler_decoders(
|
||||||
rig_tx: &mpsc::Sender<RigRequest>,
|
rig_tx: &mpsc::Sender<RigRequest>,
|
||||||
rig_id: &str,
|
remote: &str,
|
||||||
bookmark: &crate::server::bookmarks::Bookmark,
|
bookmark: &crate::server::bookmarks::Bookmark,
|
||||||
extra_bookmarks: &[crate::server::bookmarks::Bookmark],
|
extra_bookmarks: &[crate::server::bookmarks::Bookmark],
|
||||||
) {
|
) {
|
||||||
@@ -721,10 +722,10 @@ async fn apply_scheduler_decoders(
|
|||||||
];
|
];
|
||||||
|
|
||||||
for (label, cmd) in desired {
|
for (label, cmd) in desired {
|
||||||
if let Err(e) = scheduler_send(rig_tx, cmd, rig_id.to_string()).await {
|
if let Err(e) = scheduler_send(rig_tx, cmd, remote.to_string()).await {
|
||||||
warn!(
|
warn!(
|
||||||
"scheduler: Set{label}DecodeEnabled failed for '{}': {:?}",
|
"scheduler: Set{label}DecodeEnabled failed for '{}': {:?}",
|
||||||
rig_id, e
|
remote, e
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -732,7 +733,7 @@ async fn apply_scheduler_decoders(
|
|||||||
|
|
||||||
async fn apply_last_scheduler_cycle(
|
async fn apply_last_scheduler_cycle(
|
||||||
rig_tx: &mpsc::Sender<RigRequest>,
|
rig_tx: &mpsc::Sender<RigRequest>,
|
||||||
rig_id: &str,
|
remote: &str,
|
||||||
status_map: &SchedulerStatusMap,
|
status_map: &SchedulerStatusMap,
|
||||||
bookmarks: &BookmarkStore,
|
bookmarks: &BookmarkStore,
|
||||||
) {
|
) {
|
||||||
@@ -740,7 +741,7 @@ async fn apply_last_scheduler_cycle(
|
|||||||
let Ok(map) = status_map.read() else {
|
let Ok(map) = status_map.read() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
map.get(rig_id).cloned()
|
map.get(remote).cloned()
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(status) = status else {
|
let Some(status) = status else {
|
||||||
@@ -751,15 +752,15 @@ async fn apply_last_scheduler_cycle(
|
|||||||
};
|
};
|
||||||
if bookmarks.get(&bookmark_id).is_none() {
|
if bookmarks.get(&bookmark_id).is_none() {
|
||||||
warn!(
|
warn!(
|
||||||
"scheduler: last bookmark '{}' not found for rig '{}'",
|
"scheduler: last bookmark '{}' not found for remote '{}'",
|
||||||
bookmark_id, rig_id
|
bookmark_id, remote
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(e) = apply_scheduler_target(
|
if let Err(e) = apply_scheduler_target(
|
||||||
rig_tx,
|
rig_tx,
|
||||||
rig_id,
|
remote,
|
||||||
status_map,
|
status_map,
|
||||||
bookmarks,
|
bookmarks,
|
||||||
status.last_entry_id.as_deref(),
|
status.last_entry_id.as_deref(),
|
||||||
@@ -769,7 +770,7 @@ async fn apply_last_scheduler_cycle(
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
warn!("scheduler: restore failed for '{}': {e}", rig_id);
|
warn!("scheduler: restore failed for '{}': {e}", remote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -777,14 +778,14 @@ async fn apply_last_scheduler_cycle(
|
|||||||
async fn scheduler_send(
|
async fn scheduler_send(
|
||||||
rig_tx: &mpsc::Sender<RigRequest>,
|
rig_tx: &mpsc::Sender<RigRequest>,
|
||||||
cmd: RigCommand,
|
cmd: RigCommand,
|
||||||
rig_id: String,
|
remote: String,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let (resp_tx, resp_rx) = oneshot::channel();
|
let (resp_tx, resp_rx) = oneshot::channel();
|
||||||
rig_tx
|
rig_tx
|
||||||
.send(RigRequest {
|
.send(RigRequest {
|
||||||
cmd,
|
cmd,
|
||||||
respond_to: resp_tx,
|
respond_to: resp_tx,
|
||||||
rig_id_override: Some(rig_id),
|
rig_id_override: Some(remote),
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.map_err(|e| format!("send error: {e:?}"))?;
|
.map_err(|e| format!("send error: {e:?}"))?;
|
||||||
@@ -797,15 +798,15 @@ async fn scheduler_send(
|
|||||||
// HTTP handlers
|
// HTTP handlers
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
/// GET /scheduler/{rig_id}
|
/// GET /scheduler/{remote}
|
||||||
#[get("/scheduler/{rig_id}")]
|
#[get("/scheduler/{remote}")]
|
||||||
pub async fn get_scheduler(
|
pub async fn get_scheduler(
|
||||||
path: web::Path<String>,
|
path: web::Path<String>,
|
||||||
store: web::Data<Arc<SchedulerStore>>,
|
store: web::Data<Arc<SchedulerStore>>,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let rig_id = path.into_inner();
|
let remote = path.into_inner();
|
||||||
let config = store.get(&rig_id).unwrap_or(SchedulerConfig {
|
let config = store.get(&remote).unwrap_or(SchedulerConfig {
|
||||||
rig_id: rig_id.clone(),
|
remote: remote.clone(),
|
||||||
mode: SchedulerMode::Disabled,
|
mode: SchedulerMode::Disabled,
|
||||||
grayline: None,
|
grayline: None,
|
||||||
entries: vec![],
|
entries: vec![],
|
||||||
@@ -814,16 +815,16 @@ pub async fn get_scheduler(
|
|||||||
HttpResponse::Ok().json(config)
|
HttpResponse::Ok().json(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PUT /scheduler/{rig_id}
|
/// PUT /scheduler/{remote}
|
||||||
#[put("/scheduler/{rig_id}")]
|
#[put("/scheduler/{remote}")]
|
||||||
pub async fn put_scheduler(
|
pub async fn put_scheduler(
|
||||||
path: web::Path<String>,
|
path: web::Path<String>,
|
||||||
body: web::Json<SchedulerConfig>,
|
body: web::Json<SchedulerConfig>,
|
||||||
store: web::Data<Arc<SchedulerStore>>,
|
store: web::Data<Arc<SchedulerStore>>,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let rig_id = path.into_inner();
|
let remote = path.into_inner();
|
||||||
let mut config = body.into_inner();
|
let mut config = body.into_inner();
|
||||||
config.rig_id = rig_id;
|
config.remote = remote;
|
||||||
if store.upsert(&config) {
|
if store.upsert(&config) {
|
||||||
HttpResponse::Ok().json(config)
|
HttpResponse::Ok().json(config)
|
||||||
} else {
|
} else {
|
||||||
@@ -831,26 +832,26 @@ pub async fn put_scheduler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// DELETE /scheduler/{rig_id}
|
/// DELETE /scheduler/{remote}
|
||||||
#[delete("/scheduler/{rig_id}")]
|
#[delete("/scheduler/{remote}")]
|
||||||
pub async fn delete_scheduler(
|
pub async fn delete_scheduler(
|
||||||
path: web::Path<String>,
|
path: web::Path<String>,
|
||||||
store: web::Data<Arc<SchedulerStore>>,
|
store: web::Data<Arc<SchedulerStore>>,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let rig_id = path.into_inner();
|
let remote = path.into_inner();
|
||||||
store.remove(&rig_id);
|
store.remove(&remote);
|
||||||
HttpResponse::Ok().json(serde_json::json!({ "deleted": true }))
|
HttpResponse::Ok().json(serde_json::json!({ "deleted": true }))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// GET /scheduler/{rig_id}/status
|
/// GET /scheduler/{remote}/status
|
||||||
#[get("/scheduler/{rig_id}/status")]
|
#[get("/scheduler/{remote}/status")]
|
||||||
pub async fn get_scheduler_status(
|
pub async fn get_scheduler_status(
|
||||||
path: web::Path<String>,
|
path: web::Path<String>,
|
||||||
status_map: web::Data<SchedulerStatusMap>,
|
status_map: web::Data<SchedulerStatusMap>,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let rig_id = path.into_inner();
|
let remote = path.into_inner();
|
||||||
let map = status_map.read().unwrap_or_else(|e| e.into_inner());
|
let map = status_map.read().unwrap_or_else(|e| e.into_inner());
|
||||||
let status = map.get(&rig_id).cloned().unwrap_or_default();
|
let status = map.get(&remote).cloned().unwrap_or_default();
|
||||||
HttpResponse::Ok().json(status)
|
HttpResponse::Ok().json(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -860,7 +861,7 @@ pub struct SchedulerActivateEntryRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// PUT /scheduler/{rig_id}/activate
|
/// PUT /scheduler/{rig_id}/activate
|
||||||
#[put("/scheduler/{rig_id}/activate")]
|
#[put("/scheduler/{remote}/activate")]
|
||||||
pub async fn put_scheduler_activate_entry(
|
pub async fn put_scheduler_activate_entry(
|
||||||
path: web::Path<String>,
|
path: web::Path<String>,
|
||||||
body: web::Json<SchedulerActivateEntryRequest>,
|
body: web::Json<SchedulerActivateEntryRequest>,
|
||||||
|
|||||||
Reference in New Issue
Block a user