No images decoded yet. Enable a decoder and wait for a satellite pass.
';
return;
}
- const img = wxsatImageHistory[0];
+ const img = satImageHistory[0];
const decoder = img._decoder || "unknown";
const typeName = decoder === "lrpt" ? "Meteor LRPT" : "NOAA APT";
const satellite = img.satellite || "";
@@ -93,30 +93,30 @@ function renderWxsatLatestCard() {
meta.push(`${lines} ${unit}`);
meta.push(`${date} ${ts}`);
- let html = ``;
- html += `
Latest decoded image
`;
- html += `
${meta.join(" · ")}
`;
+ let html = `
`;
+ html += `
Latest decoded image
`;
+ html += `
${meta.join(" · ")}
`;
if (img.path) {
html += `
Download PNG`;
}
if (img.geo_bounds) {
- html += `
`;
+ html += `
`;
}
html += `
`;
- wxsatLiveLatest.innerHTML = html;
+ satLiveLatest.innerHTML = html;
}
// ── History view: table ─────────────────────────────────────────────
-function getFilteredHistory() {
- let items = wxsatImageHistory;
+function getSatFilteredHistory() {
+ let items = satImageHistory;
// Type filter
- const typeVal = wxsatTypeFilter ? wxsatTypeFilter.value : "all";
+ const typeVal = satTypeFilter ? satTypeFilter.value : "all";
if (typeVal === "apt") items = items.filter((i) => i._decoder === "apt");
else if (typeVal === "lrpt") items = items.filter((i) => i._decoder === "lrpt");
// Text filter
- if (wxsatFilterText) {
+ if (satFilterText) {
items = items.filter((i) => {
const haystack = [
i._decoder === "lrpt" ? "meteor lrpt" : "noaa apt",
@@ -127,12 +127,12 @@ function getFilteredHistory() {
]
.join(" ")
.toUpperCase();
- return haystack.includes(wxsatFilterText);
+ return haystack.includes(satFilterText);
});
}
// Sort
- const sortVal = wxsatSortSelect ? wxsatSortSelect.value : "newest";
+ const sortVal = satSortSelect ? satSortSelect.value : "newest";
if (sortVal === "oldest") {
items = items.slice().reverse();
}
@@ -140,13 +140,13 @@ function getFilteredHistory() {
return items;
}
-function renderWxsatHistoryRow(img) {
+function renderSatHistoryRow(img) {
const row = document.createElement("div");
- row.className = "wxsat-history-row";
+ row.className = "sat-history-row";
const decoder = img._decoder || "unknown";
const typeName = decoder === "lrpt" ? "Meteor LRPT" : "NOAA APT";
- const typeClass = decoder === "lrpt" ? "wxsat-type-lrpt" : "wxsat-type-apt";
+ const typeClass = decoder === "lrpt" ? "sat-type-lrpt" : "sat-type-apt";
const ts = img._ts || "--";
const date = img._tsMs ? new Date(img._tsMs).toLocaleDateString([], { month: "short", day: "numeric" }) : "";
const satellite = img.satellite || "--";
@@ -157,12 +157,12 @@ function renderWxsatHistoryRow(img) {
? `
PNG`
: "--";
if (img.geo_bounds) {
- link += `
Map`;
+ link += `
Map`;
}
row.innerHTML = [
`
${date} ${ts}`,
- `
${typeName}`,
+ `
${typeName}`,
`
${satellite}`,
`
${channels}`,
`
${lines} ${unit}`,
@@ -172,19 +172,19 @@ function renderWxsatHistoryRow(img) {
return row;
}
-function renderWxsatHistoryTable() {
- if (!wxsatHistoryList) return;
- const items = getFilteredHistory();
+function renderSatHistoryTable() {
+ if (!satHistoryList) return;
+ const items = getSatFilteredHistory();
const fragment = document.createDocumentFragment();
for (let i = 0; i < items.length; i += 1) {
- fragment.appendChild(renderWxsatHistoryRow(items[i]));
+ fragment.appendChild(renderSatHistoryRow(items[i]));
}
- wxsatHistoryList.replaceChildren(fragment);
+ satHistoryList.replaceChildren(fragment);
- if (wxsatHistoryCount) {
- const total = wxsatImageHistory.length;
+ if (satHistoryCount) {
+ const total = satImageHistory.length;
const shown = items.length;
- wxsatHistoryCount.textContent =
+ satHistoryCount.textContent =
total === 0
? "No images yet"
: shown === total
@@ -194,7 +194,7 @@ function renderWxsatHistoryTable() {
}
// ── Add image to history ────────────────────────────────────────────
-function addWxsatImage(img, decoder) {
+function addSatImage(img, decoder) {
const tsMs = Number.isFinite(img.ts_ms) ? Number(img.ts_ms) : Date.now();
img._tsMs = tsMs;
img._ts = new Date(tsMs).toLocaleTimeString([], {
@@ -204,55 +204,55 @@ function addWxsatImage(img, decoder) {
});
img._decoder = decoder;
- wxsatImageHistory.unshift(img);
- if (wxsatImageHistory.length > WXSAT_MAX_IMAGES) {
- wxsatImageHistory = wxsatImageHistory.slice(0, WXSAT_MAX_IMAGES);
+ satImageHistory.unshift(img);
+ if (satImageHistory.length > SAT_MAX_IMAGES) {
+ satImageHistory = satImageHistory.slice(0, SAT_MAX_IMAGES);
}
- scheduleWxsatUi("wxsat-latest", () => renderWxsatLatestCard());
- if (wxsatActiveView === "history") {
- scheduleWxsatUi("wxsat-history", () => renderWxsatHistoryTable());
+ scheduleSatUi("sat-latest", () => renderSatLatestCard());
+ if (satActiveView === "history") {
+ scheduleSatUi("sat-history", () => renderSatHistoryTable());
}
}
// ── Server callbacks ────────────────────────────────────────────────
-window.onServerWxsatImage = function (msg) {
- if (wxsatStatus) wxsatStatus.textContent = "Image received (NOAA APT)";
- addWxsatImage(msg, "apt");
- if (msg.geo_bounds && msg.path && window.addWxsatMapOverlay) {
- window.addWxsatMapOverlay(msg);
+window.onServerSatImage = function (msg) {
+ if (satStatus) satStatus.textContent = "Image received (NOAA APT)";
+ addSatImage(msg, "apt");
+ if (msg.geo_bounds && msg.path && window.addSatMapOverlay) {
+ window.addSatMapOverlay(msg);
}
};
window.onServerLrptImage = function (msg) {
- if (wxsatStatus) wxsatStatus.textContent = "Image received (Meteor LRPT)";
- addWxsatImage(msg, "lrpt");
- if (msg.geo_bounds && msg.path && window.addWxsatMapOverlay) {
- window.addWxsatMapOverlay(msg);
+ if (satStatus) satStatus.textContent = "Image received (Meteor LRPT)";
+ addSatImage(msg, "lrpt");
+ if (msg.geo_bounds && msg.path && window.addSatMapOverlay) {
+ window.addSatMapOverlay(msg);
}
};
-window.resetWxsatHistoryView = function () {
- wxsatImageHistory = [];
- if (wxsatHistoryList) wxsatHistoryList.innerHTML = "";
- renderWxsatLatestCard();
- renderWxsatHistoryTable();
- if (window.clearWxsatMapOverlays) window.clearWxsatMapOverlays();
+window.resetSatHistoryView = function () {
+ satImageHistory = [];
+ if (satHistoryList) satHistoryList.innerHTML = "";
+ renderSatLatestCard();
+ renderSatHistoryTable();
+ if (window.clearSatMapOverlays) window.clearSatMapOverlays();
};
-window.pruneWxsatHistoryView = function () {
- renderWxsatHistoryTable();
- renderWxsatLatestCard();
+window.pruneSatHistoryView = function () {
+ renderSatHistoryTable();
+ renderSatLatestCard();
};
// ── Toggle buttons ──────────────────────────────────────────────────
-const wxsatDecodeToggleBtn = document.getElementById("wxsat-decode-toggle-btn");
-wxsatDecodeToggleBtn?.addEventListener("click", async () => {
+const satDecodeToggleBtn = document.getElementById("sat-decode-toggle-btn");
+satDecodeToggleBtn?.addEventListener("click", async () => {
try {
- await window.takeSchedulerControlForDecoderDisable?.(wxsatDecodeToggleBtn);
+ await window.takeSchedulerControlForDecoderDisable?.(satDecodeToggleBtn);
await postPath("/toggle_wxsat_decode");
} catch (e) {
- console.error("WXSAT toggle failed", e);
+ console.error("SAT toggle failed", e);
}
});
@@ -267,22 +267,22 @@ lrptDecodeToggleBtn?.addEventListener("click", async () => {
});
// ── Filter / sort event listeners ───────────────────────────────────
-wxsatFilterInput?.addEventListener("input", () => {
- wxsatFilterText = wxsatFilterInput.value.trim().toUpperCase();
- renderWxsatHistoryTable();
+satFilterInput?.addEventListener("input", () => {
+ satFilterText = satFilterInput.value.trim().toUpperCase();
+ renderSatHistoryTable();
});
-wxsatSortSelect?.addEventListener("change", () => renderWxsatHistoryTable());
-wxsatTypeFilter?.addEventListener("change", () => renderWxsatHistoryTable());
+satSortSelect?.addEventListener("change", () => renderSatHistoryTable());
+satTypeFilter?.addEventListener("change", () => renderSatHistoryTable());
// ── Settings: clear history ─────────────────────────────────────────
document
- .getElementById("settings-clear-wxsat-history")
+ .getElementById("settings-clear-sat-history")
?.addEventListener("click", async () => {
try {
await postPath("/clear_wxsat_decode");
await postPath("/clear_lrpt_decode");
- window.resetWxsatHistoryView();
+ window.resetSatHistoryView();
} catch (e) {
console.error("Weather satellite history clear failed", e);
}
@@ -372,10 +372,10 @@ async function loadSatPredictions() {
}
// ── Navigate to map centered on satellite image bounds ──────────────
-window.wxsatShowOnMap = function (south, west, north, east) {
- // Enable wxsat filter if not active
+window.satShowOnMap = function (south, west, north, east) {
+ // Enable sat filter if not active
if (typeof window.enableMapSourceFilter === "function") {
- window.enableMapSourceFilter("wxsat");
+ window.enableMapSourceFilter("sat");
}
// Navigate to the center of the image bounds
const lat = (south + north) / 2;
@@ -386,5 +386,5 @@ window.wxsatShowOnMap = function (south, west, north, east) {
};
// ── Initial render ──────────────────────────────────────────────────
-renderWxsatLatestCard();
-renderWxsatHistoryTable();
+renderSatLatestCard();
+renderSatHistoryTable();
diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css
index 17e8cad..5c6ae8d 100644
--- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css
+++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css
@@ -4539,28 +4539,28 @@ button:focus-visible, input:focus-visible, select:focus-visible {
}
}
/* ── SAT panel ──────────────────────────────────────────────────────── */
-.wxsat-view-bar { display: flex; gap: 0; margin-bottom: 0.75rem; border-bottom: 1px solid var(--border); }
-.wxsat-view-btn { flex-shrink: 0; background: transparent; border: none; border-bottom: 2px solid transparent; border-radius: 0; padding: 0.3rem 0.9rem; color: var(--text-muted); cursor: pointer; font-size: 0.82rem; }
-.wxsat-view-active { border-bottom-color: var(--accent-green); color: var(--accent-green); font-weight: 600; }
-.wxsat-view-btn:hover:not(.wxsat-view-active) { color: var(--text); }
-.wxsat-live-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; margin-bottom: 0.5rem; }
-.wxsat-live-card { background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 0.35rem; padding: 0.5rem 0.75rem; display: flex; flex-direction: column; gap: 0.15rem; }
-.wxsat-live-label { font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; }
-.wxsat-live-value { font-size: 0.9rem; font-weight: 600; }
-.wxsat-state-idle { color: var(--text-muted); }
-.wxsat-state-listening { color: var(--accent-green); }
-.wxsat-state-decoding { color: #f0a020; }
-.wxsat-history-controls { display: flex; gap: 0.5rem; align-items: center; margin-bottom: 0.5rem; flex-wrap: wrap; }
-.wxsat-sort-select { background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 0.25rem; color: var(--text); padding: 0.25rem 0.4rem; font-size: 0.82rem; }
-.wxsat-history-header { display: grid; grid-template-columns: 7rem 5.5rem 9rem 6rem 4.5rem 1fr; gap: 0.25rem; padding: 0.25rem 0.4rem; font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.03em; border-bottom: 1px solid var(--border); }
-.wxsat-history-row { display: grid; grid-template-columns: 7rem 5.5rem 9rem 6rem 4.5rem 1fr; gap: 0.25rem; padding: 0.35rem 0.4rem; font-size: 0.82rem; border-bottom: 1px solid var(--border-faint, rgba(255,255,255,0.04)); }
-.wxsat-history-row:hover { background: var(--bg-hover, rgba(255,255,255,0.02)); }
-.wxsat-col-type { font-weight: 500; }
-.wxsat-type-apt { color: #6ec6ff; }
-.wxsat-type-lrpt { color: #b39ddb; }
-.wxsat-latest-card { background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 0.4rem; padding: 0.6rem 0.75rem; }
-.wxsat-latest-card .wxsat-latest-title { font-size: 0.82rem; font-weight: 600; margin-bottom: 0.25rem; }
-.wxsat-latest-card .wxsat-latest-meta { font-size: 0.78rem; color: var(--text-muted); }
+.sat-view-bar { display: flex; gap: 0; margin-bottom: 0.75rem; border-bottom: 1px solid var(--border); }
+.sat-view-btn { flex-shrink: 0; background: transparent; border: none; border-bottom: 2px solid transparent; border-radius: 0; padding: 0.3rem 0.9rem; color: var(--text-muted); cursor: pointer; font-size: 0.82rem; }
+.sat-view-active { border-bottom-color: var(--accent-green); color: var(--accent-green); font-weight: 600; }
+.sat-view-btn:hover:not(.sat-view-active) { color: var(--text); }
+.sat-live-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; margin-bottom: 0.5rem; }
+.sat-live-card { background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 0.35rem; padding: 0.5rem 0.75rem; display: flex; flex-direction: column; gap: 0.15rem; }
+.sat-live-label { font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; }
+.sat-live-value { font-size: 0.9rem; font-weight: 600; }
+.sat-state-idle { color: var(--text-muted); }
+.sat-state-listening { color: var(--accent-green); }
+.sat-state-decoding { color: #f0a020; }
+.sat-history-controls { display: flex; gap: 0.5rem; align-items: center; margin-bottom: 0.5rem; flex-wrap: wrap; }
+.sat-sort-select { background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 0.25rem; color: var(--text); padding: 0.25rem 0.4rem; font-size: 0.82rem; }
+.sat-history-header { display: grid; grid-template-columns: 7rem 5.5rem 9rem 6rem 4.5rem 1fr; gap: 0.25rem; padding: 0.25rem 0.4rem; font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.03em; border-bottom: 1px solid var(--border); }
+.sat-history-row { display: grid; grid-template-columns: 7rem 5.5rem 9rem 6rem 4.5rem 1fr; gap: 0.25rem; padding: 0.35rem 0.4rem; font-size: 0.82rem; border-bottom: 1px solid var(--border-faint, rgba(255,255,255,0.04)); }
+.sat-history-row:hover { background: var(--bg-hover, rgba(255,255,255,0.02)); }
+.sat-col-type { font-weight: 500; }
+.sat-type-apt { color: #6ec6ff; }
+.sat-type-lrpt { color: #b39ddb; }
+.sat-latest-card { background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 0.4rem; padding: 0.6rem 0.75rem; }
+.sat-latest-card .sat-latest-title { font-size: 0.82rem; font-weight: 600; margin-bottom: 0.25rem; }
+.sat-latest-card .sat-latest-meta { font-size: 0.78rem; color: var(--text-muted); }
.sat-pred-header { display: grid; grid-template-columns: 6rem 1fr 4.5rem 5rem 6rem; gap: 0.25rem; padding: 0.25rem 0.4rem; font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.03em; border-bottom: 1px solid var(--border); }
.sat-pred-row { display: grid; grid-template-columns: 6rem 1fr 4.5rem 5rem 6rem; gap: 0.25rem; padding: 0.35rem 0.4rem; font-size: 0.82rem; border-bottom: 1px solid var(--border-faint, rgba(255,255,255,0.04)); }
.sat-pred-row:hover { background: var(--bg-hover, rgba(255,255,255,0.02)); }
@@ -4573,8 +4573,8 @@ button:focus-visible, input:focus-visible, select:focus-visible {
.sat-pred-el-mid { color: #f0a020; }
.sat-pred-el-low { color: var(--text-muted); }
@media (max-width: 600px) {
- .wxsat-live-grid { grid-template-columns: 1fr; }
- .wxsat-history-header, .wxsat-history-row { grid-template-columns: 5rem 4rem 6rem 4rem 3.5rem 1fr; font-size: 0.75rem; }
+ .sat-live-grid { grid-template-columns: 1fr; }
+ .sat-history-header, .sat-history-row { grid-template-columns: 5rem 4rem 6rem 4rem 3.5rem 1fr; font-size: 0.75rem; }
.sat-pred-header, .sat-pred-row { grid-template-columns: 5.5rem 1fr 4rem 4.5rem; font-size: 0.75rem; }
.sat-pred-col-dir { display: none; }
}
diff --git a/src/trx-client/trx-frontend/trx-frontend-http/src/api.rs b/src/trx-client/trx-frontend/trx-frontend-http/src/api.rs
index 7000e2f..9fbd07f 100644
--- a/src/trx-client/trx-frontend/trx-frontend-http/src/api.rs
+++ b/src/trx-client/trx-frontend/trx-frontend-http/src/api.rs
@@ -2174,7 +2174,7 @@ pub fn configure(cfg: &mut web::ServiceConfig) {
.service(ft2_js)
.service(wspr_js)
.service(cw_js)
- .service(wxsat_js)
+ .service(sat_js)
.service(bookmarks_js)
.service(scheduler_js)
.service(background_decode_js)
@@ -2318,9 +2318,9 @@ async fn cw_js() -> impl Responder {
no_cache_response("application/javascript; charset=utf-8", status::CW_JS)
}
-#[get("/wxsat.js")]
-async fn wxsat_js() -> impl Responder {
- no_cache_response("application/javascript; charset=utf-8", status::WXSAT_JS)
+#[get("/sat.js")]
+async fn sat_js() -> impl Responder {
+ no_cache_response("application/javascript; charset=utf-8", status::SAT_JS)
}
#[get("/bookmarks.js")]
diff --git a/src/trx-client/trx-frontend/trx-frontend-http/src/status.rs b/src/trx-client/trx-frontend/trx-frontend-http/src/status.rs
index 999532c..da2f913 100644
--- a/src/trx-client/trx-frontend/trx-frontend-http/src/status.rs
+++ b/src/trx-client/trx-frontend/trx-frontend-http/src/status.rs
@@ -22,7 +22,7 @@ pub const FT4_JS: &str = include_str!("../assets/web/plugins/ft4.js");
pub const FT2_JS: &str = include_str!("../assets/web/plugins/ft2.js");
pub const WSPR_JS: &str = include_str!("../assets/web/plugins/wspr.js");
pub const CW_JS: &str = include_str!("../assets/web/plugins/cw.js");
-pub const WXSAT_JS: &str = include_str!("../assets/web/plugins/wxsat.js");
+pub const SAT_JS: &str = include_str!("../assets/web/plugins/sat.js");
pub const BOOKMARKS_JS: &str = include_str!("../assets/web/plugins/bookmarks.js");
pub const SCHEDULER_JS: &str = include_str!("../assets/web/plugins/scheduler.js");
pub const BACKGROUND_DECODE_JS: &str = include_str!("../assets/web/plugins/background-decode.js");
diff --git a/src/trx-core/src/geo.rs b/src/trx-core/src/geo.rs
index b4fdc02..1180520 100644
--- a/src/trx-core/src/geo.rs
+++ b/src/trx-core/src/geo.rs
@@ -72,8 +72,15 @@ pub struct PassPrediction {
pub duration_s: u64,
}
-/// Well-known amateur satellites: (display name, NORAD ID).
-const HAM_SATS: &[(&str, u32)] = &[
+/// Satellites included in pass predictions: weather + amateur.
+const PREDICTION_SATS: &[(&str, u32)] = &[
+ // Weather satellites (TLEs from CelesTrak weather group)
+ ("NOAA-15", 25338),
+ ("NOAA-18", 28654),
+ ("NOAA-19", 33591),
+ ("Meteor-M N2-3", 57166),
+ ("Meteor-M N2-4", 59051),
+ // Amateur satellites (TLEs from CelesTrak amateur group)
("ISS (ARISS)", 25544),
("AO-91 (RadFxSat)", 43017),
("AO-92 (Fox-1D)", 43137),
@@ -457,7 +464,7 @@ pub fn compute_upcoming_passes(
let mut all_passes = Vec::new();
- for &(name, norad_id) in HAM_SATS {
+ for &(name, norad_id) in PREDICTION_SATS {
let tle = guard
.as_ref()
.and_then(|s| s.get(&norad_id))
diff --git a/src/trx-server/src/audio.rs b/src/trx-server/src/audio.rs
index fb837a0..f1cafec 100644
--- a/src/trx-server/src/audio.rs
+++ b/src/trx-server/src/audio.rs
@@ -2648,14 +2648,12 @@ async fn finalize_wxsat_pass(
.or_else(|| {
// Fallback: use station location if available
match (station_lat, station_lon) {
- (Some(lat), Some(lon)) => Some(
- trx_core::geo::estimate_pass_geo_from_station(
- apt_image.first_line_ms,
- pass_end_ms,
- lat,
- lon,
- ),
- ),
+ (Some(lat), Some(lon)) => Some(trx_core::geo::estimate_pass_geo_from_station(
+ apt_image.first_line_ms,
+ pass_end_ms,
+ lat,
+ lon,
+ )),
_ => None,
}
});
@@ -2877,18 +2875,14 @@ async fn finalize_lrpt_pass(
station_lon,
)
})
- .or_else(|| {
- match (station_lat, station_lon) {
- (Some(lat), Some(lon)) => Some(
- trx_core::geo::estimate_pass_geo_from_station(
- pass_start_ms,
- pass_end_ms,
- lat,
- lon,
- ),
- ),
- _ => None,
- }
+ .or_else(|| match (station_lat, station_lon) {
+ (Some(lat), Some(lon)) => Some(trx_core::geo::estimate_pass_geo_from_station(
+ pass_start_ms,
+ pass_end_ms,
+ lat,
+ lon,
+ )),
+ _ => None,
});
let (geo_bounds, ground_track) = match pass_geo {
Some(geo) => (Some(geo.bounds), Some(geo.ground_track)),
@@ -2907,7 +2901,10 @@ async fn finalize_lrpt_pass(
ground_track,
};
if geo_bounds.is_some() {
- info!("LRPT: geo-referenced {} image overlay", sat_name.as_deref().unwrap_or("unknown"));
+ info!(
+ "LRPT: geo-referenced {} image overlay",
+ sat_name.as_deref().unwrap_or("unknown")
+ );
}
histories.record_lrpt_image(img.clone());
let _ = decode_tx.send(DecodedMessage::LrptImage(img));