[feat](trx-rs): add NOAA/Meteor predictions; rename wxsat → sat
- Add NOAA-15/18/19 and Meteor-M N2-3/N2-4 to predictions list - Rename PREDICTION_SATS (was HAM_SATS) to include weather + ham sats - Rename all wxsat identifiers to sat throughout JS/HTML/CSS/Rust: wxsat.js → sat.js, WXSAT_JS → SAT_JS, /wxsat.js route → /sat.js, all #wxsat-* element IDs, .wxsat-* CSS classes, window.addWxsat* → window.addSat*, window.onServerWxsatImage → window.onServerSatImage, etc. (backend protocol strings unchanged) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
@@ -215,7 +215,7 @@ function applyAuthRestrictions() {
|
||||
"ft4-decode-toggle-btn",
|
||||
"ft2-decode-toggle-btn",
|
||||
"wspr-decode-toggle-btn",
|
||||
"wxsat-decode-toggle-btn",
|
||||
"sat-decode-toggle-btn",
|
||||
"lrpt-decode-toggle-btn",
|
||||
"hf-aprs-decode-toggle-btn",
|
||||
"cw-auto",
|
||||
@@ -228,7 +228,7 @@ function applyAuthRestrictions() {
|
||||
"settings-clear-ft4-history",
|
||||
"settings-clear-ft2-history",
|
||||
"settings-clear-wspr-history",
|
||||
"settings-clear-wxsat-history"
|
||||
"settings-clear-sat-history"
|
||||
];
|
||||
pluginToggleBtns.forEach(id => {
|
||||
const btn = document.getElementById(id);
|
||||
@@ -3231,13 +3231,13 @@ function render(update) {
|
||||
hfAprsToggleBtn.style.borderColor = hfAprsOn ? "#00d17f" : "";
|
||||
hfAprsToggleBtn.style.color = hfAprsOn ? "#00d17f" : "";
|
||||
}
|
||||
const wxsatToggleBtn = document.getElementById("wxsat-decode-toggle-btn");
|
||||
if (wxsatToggleBtn) {
|
||||
const wxsatOn = !!update.wxsat_decode_enabled;
|
||||
wxsatToggleBtn.dataset.enabled = wxsatOn ? "true" : "false";
|
||||
wxsatToggleBtn.textContent = wxsatOn ? "Disable NOAA APT" : "Enable NOAA APT";
|
||||
wxsatToggleBtn.style.borderColor = wxsatOn ? "#00d17f" : "";
|
||||
wxsatToggleBtn.style.color = wxsatOn ? "#00d17f" : "";
|
||||
const satToggleBtn = document.getElementById("sat-decode-toggle-btn");
|
||||
if (satToggleBtn) {
|
||||
const satOn = !!update.wxsat_decode_enabled;
|
||||
satToggleBtn.dataset.enabled = satOn ? "true" : "false";
|
||||
satToggleBtn.textContent = satOn ? "Disable NOAA APT" : "Enable NOAA APT";
|
||||
satToggleBtn.style.borderColor = satOn ? "#00d17f" : "";
|
||||
satToggleBtn.style.color = satOn ? "#00d17f" : "";
|
||||
}
|
||||
const lrptToggleBtn = document.getElementById("lrpt-decode-toggle-btn");
|
||||
if (lrptToggleBtn) {
|
||||
@@ -3247,7 +3247,7 @@ function render(update) {
|
||||
lrptToggleBtn.style.borderColor = lrptOn ? "#00d17f" : "";
|
||||
lrptToggleBtn.style.color = lrptOn ? "#00d17f" : "";
|
||||
}
|
||||
if (window.updateWxsatLiveState) window.updateWxsatLiveState(update);
|
||||
if (window.updateSatLiveState) window.updateSatLiveState(update);
|
||||
const cwAutoEl = document.getElementById("cw-auto");
|
||||
const cwWpmEl = document.getElementById("cw-wpm");
|
||||
const cwToneEl = document.getElementById("cw-tone");
|
||||
@@ -3423,7 +3423,7 @@ function render(update) {
|
||||
["about-dec-wspr", update.wspr_decode_enabled],
|
||||
["about-dec-cw", update.cw_decode_enabled],
|
||||
["about-dec-aprs", update.aprs_decode_enabled || update.hf_aprs_decode_enabled],
|
||||
["about-dec-wxsat", update.wxsat_decode_enabled],
|
||||
["about-dec-sat", update.wxsat_decode_enabled],
|
||||
["about-dec-lrpt", update.lrpt_decode_enabled],
|
||||
];
|
||||
for (const [id, enabled] of decMap) {
|
||||
@@ -4489,7 +4489,7 @@ const locatorMarkers = new Map();
|
||||
const decodeContactPaths = new Map();
|
||||
let selectedMapQsoKey = null;
|
||||
const mapMarkers = new Set();
|
||||
const DEFAULT_MAP_SOURCE_FILTER = { ais: true, vdes: true, aprs: true, bookmark: false, ft8: true, ft4: true, ft2: true, wspr: true, wxsat: false };
|
||||
const DEFAULT_MAP_SOURCE_FILTER = { ais: true, vdes: true, aprs: true, bookmark: false, ft8: true, ft4: true, ft2: true, wspr: true, sat: false };
|
||||
const mapFilter = { ...DEFAULT_MAP_SOURCE_FILTER };
|
||||
const mapLocatorFilter = { phase: "band", bands: new Set() };
|
||||
let mapSearchFilter = "";
|
||||
@@ -4861,7 +4861,7 @@ function locatorFilterColor(type) {
|
||||
function mapSourceColor(type) {
|
||||
if (type === "ais") return "#38bdf8";
|
||||
if (type === "vdes") return "#a78bfa";
|
||||
if (type === "wxsat") return "#f59e0b";
|
||||
if (type === "sat") return "#f59e0b";
|
||||
if (type === "aprs") return "#00d17f";
|
||||
return locatorFilterColor(type);
|
||||
}
|
||||
@@ -5676,10 +5676,10 @@ function syncAprsReceiverMarker() {
|
||||
// Weather satellite image overlays on the map
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const wxsatOverlays = new Map(); // key -> { overlay, track, msg }
|
||||
let wxsatOverlaySeq = 0;
|
||||
const satOverlays = new Map(); // key -> { overlay, track, msg }
|
||||
let satOverlaySeq = 0;
|
||||
|
||||
window.addWxsatMapOverlay = function(msg) {
|
||||
window.addSatMapOverlay = function(msg) {
|
||||
if (!msg || !msg.geo_bounds || !msg.path) return;
|
||||
const bounds = msg.geo_bounds;
|
||||
// bounds = [south, west, north, east]
|
||||
@@ -5688,14 +5688,14 @@ window.addWxsatMapOverlay = function(msg) {
|
||||
[bounds[0], bounds[1]], // SW
|
||||
[bounds[2], bounds[3]] // NE
|
||||
);
|
||||
const key = "wxsat-" + (++wxsatOverlaySeq);
|
||||
const key = "sat-" + (++satOverlaySeq);
|
||||
const overlay = L.imageOverlay(msg.path, latLngBounds, {
|
||||
opacity: 0.55,
|
||||
interactive: true,
|
||||
zIndex: 300,
|
||||
});
|
||||
overlay.__trxType = "wxsat";
|
||||
overlay.__trxWxsatKey = key;
|
||||
overlay.__trxType = "sat";
|
||||
overlay.__trxSatKey = key;
|
||||
overlay.__trxRigIds = msg.rig_id ? new Set([msg.rig_id]) : new Set();
|
||||
overlay.__trxHistoryVisible = true;
|
||||
mapMarkers.add(overlay);
|
||||
@@ -5718,13 +5718,13 @@ window.addWxsatMapOverlay = function(msg) {
|
||||
if (msg.ground_track && Array.isArray(msg.ground_track) && msg.ground_track.length >= 2) {
|
||||
const latlngs = msg.ground_track.map(function(pt) { return [pt[0], pt[1]]; });
|
||||
track = L.polyline(latlngs, {
|
||||
color: mapSourceColor("wxsat"),
|
||||
color: mapSourceColor("sat"),
|
||||
weight: 2,
|
||||
opacity: 0.7,
|
||||
dashArray: "6, 4",
|
||||
});
|
||||
track.__trxType = "wxsat";
|
||||
track.__trxWxsatKey = key;
|
||||
track.__trxType = "sat";
|
||||
track.__trxSatKey = key;
|
||||
track.__trxRigIds = overlay.__trxRigIds;
|
||||
track.__trxHistoryVisible = true;
|
||||
mapMarkers.add(track);
|
||||
@@ -5733,7 +5733,7 @@ window.addWxsatMapOverlay = function(msg) {
|
||||
}
|
||||
}
|
||||
|
||||
wxsatOverlays.set(key, { overlay: overlay, track: track, msg: msg });
|
||||
satOverlays.set(key, { overlay: overlay, track: track, msg: msg });
|
||||
|
||||
if (aprsMap) {
|
||||
overlay.addTo(aprsMap);
|
||||
@@ -5741,8 +5741,8 @@ window.addWxsatMapOverlay = function(msg) {
|
||||
applyMapFilter();
|
||||
};
|
||||
|
||||
window.removeWxsatMapOverlay = function(key) {
|
||||
const entry = wxsatOverlays.get(key);
|
||||
window.removeSatMapOverlay = function(key) {
|
||||
const entry = satOverlays.get(key);
|
||||
if (!entry) return;
|
||||
if (entry.overlay) {
|
||||
mapMarkers.delete(entry.overlay);
|
||||
@@ -5752,12 +5752,12 @@ window.removeWxsatMapOverlay = function(key) {
|
||||
mapMarkers.delete(entry.track);
|
||||
if (aprsMap && aprsMap.hasLayer(entry.track)) entry.track.removeFrom(aprsMap);
|
||||
}
|
||||
wxsatOverlays.delete(key);
|
||||
satOverlays.delete(key);
|
||||
};
|
||||
|
||||
window.clearWxsatMapOverlays = function() {
|
||||
for (const [key] of wxsatOverlays) {
|
||||
window.removeWxsatMapOverlay(key);
|
||||
window.clearSatMapOverlays = function() {
|
||||
for (const [key] of satOverlays) {
|
||||
window.removeSatMapOverlay(key);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5805,8 +5805,8 @@ window.clearMapMarkersByType = function(type) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (type === "wxsat") {
|
||||
window.clearWxsatMapOverlays();
|
||||
if (type === "sat") {
|
||||
window.clearSatMapOverlays();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -8612,7 +8612,7 @@ function dispatchDecodeMessage(msg) {
|
||||
if (msg.type === "ft4" && window.onServerFt4) window.onServerFt4(msg);
|
||||
if (msg.type === "ft2" && window.onServerFt2) window.onServerFt2(msg);
|
||||
if (msg.type === "wspr" && window.onServerWspr) window.onServerWspr(msg);
|
||||
if (msg.type === "wxsat_image" && window.onServerWxsatImage) window.onServerWxsatImage(msg);
|
||||
if (msg.type === "wxsat_image" && window.onServerSatImage) window.onServerSatImage(msg);
|
||||
if (msg.type === "lrpt_image" && window.onServerLrptImage) window.onServerLrptImage(msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -515,7 +515,7 @@
|
||||
<button class="sub-tab" data-subtab="ft2">FT2</button>
|
||||
<button class="sub-tab" data-subtab="wspr">WSPR</button>
|
||||
<button class="sub-tab" data-subtab="rds">RDS</button>
|
||||
<button class="sub-tab" data-subtab="wxsat">SAT</button>
|
||||
<button class="sub-tab" data-subtab="sat">SAT</button>
|
||||
</div>
|
||||
<div id="subtab-overview" class="sub-tab-panel">
|
||||
<div class="plugin-item">
|
||||
@@ -801,28 +801,28 @@
|
||||
</div>
|
||||
<div id="cw-output"></div>
|
||||
</div>
|
||||
<div id="subtab-wxsat" class="sub-tab-panel" style="display:none;">
|
||||
<div id="subtab-sat" class="sub-tab-panel" style="display:none;">
|
||||
<div class="ft8-controls">
|
||||
<button id="wxsat-decode-toggle-btn" type="button">Enable NOAA APT</button>
|
||||
<button id="sat-decode-toggle-btn" type="button">Enable NOAA APT</button>
|
||||
<button id="lrpt-decode-toggle-btn" type="button">Enable Meteor LRPT</button>
|
||||
<small id="wxsat-status" style="color:var(--text-muted);">Waiting for satellite pass</small>
|
||||
<small id="sat-status" style="color:var(--text-muted);">Waiting for satellite pass</small>
|
||||
</div>
|
||||
<!-- View selector -->
|
||||
<div class="wxsat-view-bar">
|
||||
<button id="wxsat-view-live" class="wxsat-view-btn wxsat-view-active" type="button">Live</button>
|
||||
<button id="wxsat-view-history" class="wxsat-view-btn" type="button">History</button>
|
||||
<button id="wxsat-view-predictions" class="wxsat-view-btn" type="button">Predictions</button>
|
||||
<div class="sat-view-bar">
|
||||
<button id="sat-view-live" class="sat-view-btn sat-view-active" type="button">Live</button>
|
||||
<button id="sat-view-history" class="sat-view-btn" type="button">History</button>
|
||||
<button id="sat-view-predictions" class="sat-view-btn" type="button">Predictions</button>
|
||||
</div>
|
||||
<!-- Live view -->
|
||||
<div id="wxsat-live-view">
|
||||
<div class="wxsat-live-grid">
|
||||
<div class="wxsat-live-card">
|
||||
<span class="wxsat-live-label">NOAA APT</span>
|
||||
<span id="wxsat-apt-state" class="wxsat-live-value wxsat-state-idle">Idle</span>
|
||||
<div id="sat-live-view">
|
||||
<div class="sat-live-grid">
|
||||
<div class="sat-live-card">
|
||||
<span class="sat-live-label">NOAA APT</span>
|
||||
<span id="sat-apt-state" class="sat-live-value sat-state-idle">Idle</span>
|
||||
</div>
|
||||
<div class="wxsat-live-card">
|
||||
<span class="wxsat-live-label">Meteor LRPT</span>
|
||||
<span id="wxsat-lrpt-state" class="wxsat-live-value wxsat-state-idle">Idle</span>
|
||||
<div class="sat-live-card">
|
||||
<span class="sat-live-label">Meteor LRPT</span>
|
||||
<span id="sat-lrpt-state" class="sat-live-value sat-state-idle">Idle</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin:0.5rem 0;">
|
||||
@@ -835,35 +835,35 @@
|
||||
Multi-channel CCSDS-framed imagery (APIDs 64–69) with RGB composite output.
|
||||
</div>
|
||||
</div>
|
||||
<div id="wxsat-live-latest" style="margin-top:0.5rem;"></div>
|
||||
<div id="sat-live-latest" style="margin-top:0.5rem;"></div>
|
||||
</div>
|
||||
<!-- History view -->
|
||||
<div id="wxsat-history-view" style="display:none;">
|
||||
<div class="wxsat-history-controls">
|
||||
<input id="wxsat-filter" class="ft8-filter" type="text" placeholder="Filter (e.g. NOAA-18, Meteor, APT)" />
|
||||
<select id="wxsat-sort" class="wxsat-sort-select">
|
||||
<div id="sat-history-view" style="display:none;">
|
||||
<div class="sat-history-controls">
|
||||
<input id="sat-filter" class="ft8-filter" type="text" placeholder="Filter (e.g. NOAA-18, Meteor, APT)" />
|
||||
<select id="sat-sort" class="sat-sort-select">
|
||||
<option value="newest">Newest first</option>
|
||||
<option value="oldest">Oldest first</option>
|
||||
</select>
|
||||
<select id="wxsat-type-filter" class="wxsat-sort-select">
|
||||
<select id="sat-type-filter" class="sat-sort-select">
|
||||
<option value="all">All types</option>
|
||||
<option value="apt">NOAA APT only</option>
|
||||
<option value="lrpt">Meteor LRPT only</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="wxsat-history-header">
|
||||
<span class="wxsat-col-time">Time</span>
|
||||
<span class="wxsat-col-type">Type</span>
|
||||
<span class="wxsat-col-sat">Satellite</span>
|
||||
<span class="wxsat-col-ch">Channels</span>
|
||||
<span class="wxsat-col-lines">Lines</span>
|
||||
<span class="wxsat-col-link">Image</span>
|
||||
<div class="sat-history-header">
|
||||
<span class="sat-col-time">Time</span>
|
||||
<span class="sat-col-type">Type</span>
|
||||
<span class="sat-col-sat">Satellite</span>
|
||||
<span class="sat-col-ch">Channels</span>
|
||||
<span class="sat-col-lines">Lines</span>
|
||||
<span class="sat-col-link">Image</span>
|
||||
</div>
|
||||
<div id="wxsat-history-list"></div>
|
||||
<small id="wxsat-history-count" style="color:var(--text-muted);font-size:0.75rem;">No images yet</small>
|
||||
<div id="sat-history-list"></div>
|
||||
<small id="sat-history-count" style="color:var(--text-muted);font-size:0.75rem;">No images yet</small>
|
||||
</div>
|
||||
<!-- Predictions view -->
|
||||
<div id="wxsat-predictions-view" style="display:none;">
|
||||
<div id="sat-predictions-view" style="display:none;">
|
||||
<div class="sat-pred-header">
|
||||
<span class="sat-pred-col-time">AOS (UTC)</span>
|
||||
<span class="sat-pred-col-sat">Satellite</span>
|
||||
@@ -1122,7 +1122,7 @@
|
||||
<button id="settings-clear-ft4-history" class="sch-write sch-reset-btn" type="button">Clear full FT4 history</button>
|
||||
<button id="settings-clear-ft2-history" class="sch-write sch-reset-btn" type="button">Clear full FT2 history</button>
|
||||
<button id="settings-clear-wspr-history" class="sch-write sch-reset-btn" type="button">Clear full WSPR history</button>
|
||||
<button id="settings-clear-wxsat-history" class="sch-write sch-reset-btn" type="button">Clear full Sat history</button>
|
||||
<button id="settings-clear-sat-history" class="sch-write sch-reset-btn" type="button">Clear full Sat history</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1195,7 +1195,7 @@
|
||||
<tr><td>WSPR</td><td id="about-dec-wspr" class="about-status-off">Off</td></tr>
|
||||
<tr><td>CW</td><td id="about-dec-cw" class="about-status-off">Off</td></tr>
|
||||
<tr><td>APRS</td><td id="about-dec-aprs" class="about-status-off">Off</td></tr>
|
||||
<tr><td>NOAA APT</td><td id="about-dec-wxsat" class="about-status-off">Off</td></tr>
|
||||
<tr><td>NOAA APT</td><td id="about-dec-sat" class="about-status-off">Off</td></tr>
|
||||
<tr><td>Meteor LRPT</td><td id="about-dec-lrpt" class="about-status-off">Off</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
@@ -1287,7 +1287,7 @@
|
||||
<script src="/ft2.js"></script>
|
||||
<script src="/wspr.js"></script>
|
||||
<script src="/cw.js"></script>
|
||||
<script src="/wxsat.js"></script>
|
||||
<script src="/sat.js"></script>
|
||||
<script src="/bookmarks.js"></script>
|
||||
<script src="/scheduler.js"></script>
|
||||
<script src="/background-decode.js"></script>
|
||||
|
||||
+109
-109
@@ -4,27 +4,27 @@
|
||||
// Predictions view: next 24 h passes for ham satellites
|
||||
|
||||
// ── DOM references ──────────────────────────────────────────────────
|
||||
const wxsatStatus = document.getElementById("wxsat-status");
|
||||
const wxsatLiveView = document.getElementById("wxsat-live-view");
|
||||
const wxsatHistoryView = document.getElementById("wxsat-history-view");
|
||||
const wxsatPredictionsView = document.getElementById("wxsat-predictions-view");
|
||||
const wxsatLiveLatest = document.getElementById("wxsat-live-latest");
|
||||
const wxsatHistoryList = document.getElementById("wxsat-history-list");
|
||||
const wxsatHistoryCount = document.getElementById("wxsat-history-count");
|
||||
const wxsatFilterInput = document.getElementById("wxsat-filter");
|
||||
const wxsatSortSelect = document.getElementById("wxsat-sort");
|
||||
const wxsatTypeFilter = document.getElementById("wxsat-type-filter");
|
||||
const wxsatAptState = document.getElementById("wxsat-apt-state");
|
||||
const wxsatLrptState = document.getElementById("wxsat-lrpt-state");
|
||||
const satStatus = document.getElementById("sat-status");
|
||||
const satLiveView = document.getElementById("sat-live-view");
|
||||
const satHistoryView = document.getElementById("sat-history-view");
|
||||
const satPredictionsView = document.getElementById("sat-predictions-view");
|
||||
const satLiveLatest = document.getElementById("sat-live-latest");
|
||||
const satHistoryList = document.getElementById("sat-history-list");
|
||||
const satHistoryCount = document.getElementById("sat-history-count");
|
||||
const satFilterInput = document.getElementById("sat-filter");
|
||||
const satSortSelect = document.getElementById("sat-sort");
|
||||
const satTypeFilter = document.getElementById("sat-type-filter");
|
||||
const satAptState = document.getElementById("sat-apt-state");
|
||||
const satLrptState = document.getElementById("sat-lrpt-state");
|
||||
|
||||
// ── State ───────────────────────────────────────────────────────────
|
||||
let wxsatImageHistory = [];
|
||||
const WXSAT_MAX_IMAGES = 100;
|
||||
let wxsatFilterText = "";
|
||||
let wxsatActiveView = "live"; // "live" | "history" | "predictions"
|
||||
let satImageHistory = [];
|
||||
const SAT_MAX_IMAGES = 100;
|
||||
let satFilterText = "";
|
||||
let satActiveView = "live"; // "live" | "history" | "predictions"
|
||||
|
||||
// ── UI scheduler helper ─────────────────────────────────────────────
|
||||
function scheduleWxsatUi(key, job) {
|
||||
function scheduleSatUi(key, job) {
|
||||
if (typeof window.trxScheduleUiFrameJob === "function") {
|
||||
window.trxScheduleUiFrameJob(key, job);
|
||||
return;
|
||||
@@ -33,51 +33,51 @@ function scheduleWxsatUi(key, job) {
|
||||
}
|
||||
|
||||
// ── View switching ──────────────────────────────────────────────────
|
||||
const wxsatViewLiveBtn = document.getElementById("wxsat-view-live");
|
||||
const wxsatViewHistoryBtn = document.getElementById("wxsat-view-history");
|
||||
const wxsatViewPredictionsBtn = document.getElementById("wxsat-view-predictions");
|
||||
const satViewLiveBtn = document.getElementById("sat-view-live");
|
||||
const satViewHistoryBtn = document.getElementById("sat-view-history");
|
||||
const satViewPredictionsBtn = document.getElementById("sat-view-predictions");
|
||||
|
||||
function switchWxsatView(view) {
|
||||
wxsatActiveView = view;
|
||||
if (wxsatLiveView) wxsatLiveView.style.display = view === "live" ? "" : "none";
|
||||
if (wxsatHistoryView) wxsatHistoryView.style.display = view === "history" ? "" : "none";
|
||||
if (wxsatPredictionsView) wxsatPredictionsView.style.display = view === "predictions" ? "" : "none";
|
||||
if (wxsatViewLiveBtn) wxsatViewLiveBtn.classList.toggle("wxsat-view-active", view === "live");
|
||||
if (wxsatViewHistoryBtn) wxsatViewHistoryBtn.classList.toggle("wxsat-view-active", view === "history");
|
||||
if (wxsatViewPredictionsBtn) wxsatViewPredictionsBtn.classList.toggle("wxsat-view-active", view === "predictions");
|
||||
function switchSatView(view) {
|
||||
satActiveView = view;
|
||||
if (satLiveView) satLiveView.style.display = view === "live" ? "" : "none";
|
||||
if (satHistoryView) satHistoryView.style.display = view === "history" ? "" : "none";
|
||||
if (satPredictionsView) satPredictionsView.style.display = view === "predictions" ? "" : "none";
|
||||
if (satViewLiveBtn) satViewLiveBtn.classList.toggle("sat-view-active", view === "live");
|
||||
if (satViewHistoryBtn) satViewHistoryBtn.classList.toggle("sat-view-active", view === "history");
|
||||
if (satViewPredictionsBtn) satViewPredictionsBtn.classList.toggle("sat-view-active", view === "predictions");
|
||||
if (view === "history") {
|
||||
renderWxsatHistoryTable();
|
||||
renderSatHistoryTable();
|
||||
} else if (view === "predictions") {
|
||||
loadSatPredictions();
|
||||
}
|
||||
}
|
||||
|
||||
wxsatViewLiveBtn?.addEventListener("click", () => switchWxsatView("live"));
|
||||
wxsatViewHistoryBtn?.addEventListener("click", () => switchWxsatView("history"));
|
||||
wxsatViewPredictionsBtn?.addEventListener("click", () => switchWxsatView("predictions"));
|
||||
satViewLiveBtn?.addEventListener("click", () => switchSatView("live"));
|
||||
satViewHistoryBtn?.addEventListener("click", () => switchSatView("history"));
|
||||
satViewPredictionsBtn?.addEventListener("click", () => switchSatView("predictions"));
|
||||
|
||||
// ── Live view: decoder state ────────────────────────────────────────
|
||||
// Updated from app.js render() via window.updateWxsatLiveState
|
||||
window.updateWxsatLiveState = function (update) {
|
||||
if (!wxsatAptState || !wxsatLrptState) return;
|
||||
// Updated from app.js render() via window.updateSatLiveState
|
||||
window.updateSatLiveState = function (update) {
|
||||
if (!satAptState || !satLrptState) return;
|
||||
const aptOn = !!update.wxsat_decode_enabled;
|
||||
const lrptOn = !!update.lrpt_decode_enabled;
|
||||
|
||||
wxsatAptState.textContent = aptOn ? "Listening" : "Idle";
|
||||
wxsatAptState.className = "wxsat-live-value " + (aptOn ? "wxsat-state-listening" : "wxsat-state-idle");
|
||||
wxsatLrptState.textContent = lrptOn ? "Listening" : "Idle";
|
||||
wxsatLrptState.className = "wxsat-live-value " + (lrptOn ? "wxsat-state-listening" : "wxsat-state-idle");
|
||||
satAptState.textContent = aptOn ? "Listening" : "Idle";
|
||||
satAptState.className = "sat-live-value " + (aptOn ? "sat-state-listening" : "sat-state-idle");
|
||||
satLrptState.textContent = lrptOn ? "Listening" : "Idle";
|
||||
satLrptState.className = "sat-live-value " + (lrptOn ? "sat-state-listening" : "sat-state-idle");
|
||||
};
|
||||
|
||||
function renderWxsatLatestCard() {
|
||||
if (!wxsatLiveLatest) return;
|
||||
if (wxsatImageHistory.length === 0) {
|
||||
wxsatLiveLatest.innerHTML =
|
||||
function renderSatLatestCard() {
|
||||
if (!satLiveLatest) return;
|
||||
if (satImageHistory.length === 0) {
|
||||
satLiveLatest.innerHTML =
|
||||
'<div style="color:var(--text-muted);font-size:0.82rem;">No images decoded yet. Enable a decoder and wait for a satellite pass.</div>';
|
||||
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 = `<div class="wxsat-latest-card">`;
|
||||
html += `<div class="wxsat-latest-title">Latest decoded image</div>`;
|
||||
html += `<div class="wxsat-latest-meta">${meta.join(" · ")}</div>`;
|
||||
let html = `<div class="sat-latest-card">`;
|
||||
html += `<div class="sat-latest-title">Latest decoded image</div>`;
|
||||
html += `<div class="sat-latest-meta">${meta.join(" · ")}</div>`;
|
||||
if (img.path) {
|
||||
html += `<a href="${img.path}" target="_blank" style="font-size:0.8rem;color:var(--accent);display:inline-block;margin-top:0.25rem;">Download PNG</a>`;
|
||||
}
|
||||
if (img.geo_bounds) {
|
||||
html += ` <button type="button" class="wxsat-map-btn" onclick="window.wxsatShowOnMap(${img.geo_bounds[0]},${img.geo_bounds[1]},${img.geo_bounds[2]},${img.geo_bounds[3]})" style="font-size:0.8rem;margin-top:0.25rem;margin-left:0.5rem;cursor:pointer;background:none;border:1px solid var(--accent);color:var(--accent);border-radius:3px;padding:1px 6px;">Show on Map</button>`;
|
||||
html += ` <button type="button" class="sat-map-btn" onclick="window.satShowOnMap(${img.geo_bounds[0]},${img.geo_bounds[1]},${img.geo_bounds[2]},${img.geo_bounds[3]})" style="font-size:0.8rem;margin-top:0.25rem;margin-left:0.5rem;cursor:pointer;background:none;border:1px solid var(--accent);color:var(--accent);border-radius:3px;padding:1px 6px;">Show on Map</button>`;
|
||||
}
|
||||
html += `</div>`;
|
||||
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) {
|
||||
? `<a href="${img.path}" target="_blank" style="color:var(--accent);">PNG</a>`
|
||||
: "--";
|
||||
if (img.geo_bounds) {
|
||||
link += ` <a href="javascript:void(0)" onclick="window.wxsatShowOnMap(${img.geo_bounds[0]},${img.geo_bounds[1]},${img.geo_bounds[2]},${img.geo_bounds[3]})" style="color:var(--accent);">Map</a>`;
|
||||
link += ` <a href="javascript:void(0)" onclick="window.satShowOnMap(${img.geo_bounds[0]},${img.geo_bounds[1]},${img.geo_bounds[2]},${img.geo_bounds[3]})" style="color:var(--accent);">Map</a>`;
|
||||
}
|
||||
|
||||
row.innerHTML = [
|
||||
`<span>${date} ${ts}</span>`,
|
||||
`<span class="wxsat-col-type ${typeClass}">${typeName}</span>`,
|
||||
`<span class="sat-col-type ${typeClass}">${typeName}</span>`,
|
||||
`<span>${satellite}</span>`,
|
||||
`<span>${channels}</span>`,
|
||||
`<span>${lines} ${unit}</span>`,
|
||||
@@ -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();
|
||||
@@ -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; }
|
||||
}
|
||||
|
||||
@@ -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")]
|
||||
|
||||
@@ -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");
|
||||
|
||||
+10
-3
@@ -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))
|
||||
|
||||
+18
-21
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user