[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",
|
"ft4-decode-toggle-btn",
|
||||||
"ft2-decode-toggle-btn",
|
"ft2-decode-toggle-btn",
|
||||||
"wspr-decode-toggle-btn",
|
"wspr-decode-toggle-btn",
|
||||||
"wxsat-decode-toggle-btn",
|
"sat-decode-toggle-btn",
|
||||||
"lrpt-decode-toggle-btn",
|
"lrpt-decode-toggle-btn",
|
||||||
"hf-aprs-decode-toggle-btn",
|
"hf-aprs-decode-toggle-btn",
|
||||||
"cw-auto",
|
"cw-auto",
|
||||||
@@ -228,7 +228,7 @@ function applyAuthRestrictions() {
|
|||||||
"settings-clear-ft4-history",
|
"settings-clear-ft4-history",
|
||||||
"settings-clear-ft2-history",
|
"settings-clear-ft2-history",
|
||||||
"settings-clear-wspr-history",
|
"settings-clear-wspr-history",
|
||||||
"settings-clear-wxsat-history"
|
"settings-clear-sat-history"
|
||||||
];
|
];
|
||||||
pluginToggleBtns.forEach(id => {
|
pluginToggleBtns.forEach(id => {
|
||||||
const btn = document.getElementById(id);
|
const btn = document.getElementById(id);
|
||||||
@@ -3231,13 +3231,13 @@ function render(update) {
|
|||||||
hfAprsToggleBtn.style.borderColor = hfAprsOn ? "#00d17f" : "";
|
hfAprsToggleBtn.style.borderColor = hfAprsOn ? "#00d17f" : "";
|
||||||
hfAprsToggleBtn.style.color = hfAprsOn ? "#00d17f" : "";
|
hfAprsToggleBtn.style.color = hfAprsOn ? "#00d17f" : "";
|
||||||
}
|
}
|
||||||
const wxsatToggleBtn = document.getElementById("wxsat-decode-toggle-btn");
|
const satToggleBtn = document.getElementById("sat-decode-toggle-btn");
|
||||||
if (wxsatToggleBtn) {
|
if (satToggleBtn) {
|
||||||
const wxsatOn = !!update.wxsat_decode_enabled;
|
const satOn = !!update.wxsat_decode_enabled;
|
||||||
wxsatToggleBtn.dataset.enabled = wxsatOn ? "true" : "false";
|
satToggleBtn.dataset.enabled = satOn ? "true" : "false";
|
||||||
wxsatToggleBtn.textContent = wxsatOn ? "Disable NOAA APT" : "Enable NOAA APT";
|
satToggleBtn.textContent = satOn ? "Disable NOAA APT" : "Enable NOAA APT";
|
||||||
wxsatToggleBtn.style.borderColor = wxsatOn ? "#00d17f" : "";
|
satToggleBtn.style.borderColor = satOn ? "#00d17f" : "";
|
||||||
wxsatToggleBtn.style.color = wxsatOn ? "#00d17f" : "";
|
satToggleBtn.style.color = satOn ? "#00d17f" : "";
|
||||||
}
|
}
|
||||||
const lrptToggleBtn = document.getElementById("lrpt-decode-toggle-btn");
|
const lrptToggleBtn = document.getElementById("lrpt-decode-toggle-btn");
|
||||||
if (lrptToggleBtn) {
|
if (lrptToggleBtn) {
|
||||||
@@ -3247,7 +3247,7 @@ function render(update) {
|
|||||||
lrptToggleBtn.style.borderColor = lrptOn ? "#00d17f" : "";
|
lrptToggleBtn.style.borderColor = lrptOn ? "#00d17f" : "";
|
||||||
lrptToggleBtn.style.color = 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 cwAutoEl = document.getElementById("cw-auto");
|
||||||
const cwWpmEl = document.getElementById("cw-wpm");
|
const cwWpmEl = document.getElementById("cw-wpm");
|
||||||
const cwToneEl = document.getElementById("cw-tone");
|
const cwToneEl = document.getElementById("cw-tone");
|
||||||
@@ -3423,7 +3423,7 @@ function render(update) {
|
|||||||
["about-dec-wspr", update.wspr_decode_enabled],
|
["about-dec-wspr", update.wspr_decode_enabled],
|
||||||
["about-dec-cw", update.cw_decode_enabled],
|
["about-dec-cw", update.cw_decode_enabled],
|
||||||
["about-dec-aprs", update.aprs_decode_enabled || update.hf_aprs_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],
|
["about-dec-lrpt", update.lrpt_decode_enabled],
|
||||||
];
|
];
|
||||||
for (const [id, enabled] of decMap) {
|
for (const [id, enabled] of decMap) {
|
||||||
@@ -4489,7 +4489,7 @@ const locatorMarkers = new Map();
|
|||||||
const decodeContactPaths = new Map();
|
const decodeContactPaths = new Map();
|
||||||
let selectedMapQsoKey = null;
|
let selectedMapQsoKey = null;
|
||||||
const mapMarkers = new Set();
|
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 mapFilter = { ...DEFAULT_MAP_SOURCE_FILTER };
|
||||||
const mapLocatorFilter = { phase: "band", bands: new Set() };
|
const mapLocatorFilter = { phase: "band", bands: new Set() };
|
||||||
let mapSearchFilter = "";
|
let mapSearchFilter = "";
|
||||||
@@ -4861,7 +4861,7 @@ function locatorFilterColor(type) {
|
|||||||
function mapSourceColor(type) {
|
function mapSourceColor(type) {
|
||||||
if (type === "ais") return "#38bdf8";
|
if (type === "ais") return "#38bdf8";
|
||||||
if (type === "vdes") return "#a78bfa";
|
if (type === "vdes") return "#a78bfa";
|
||||||
if (type === "wxsat") return "#f59e0b";
|
if (type === "sat") return "#f59e0b";
|
||||||
if (type === "aprs") return "#00d17f";
|
if (type === "aprs") return "#00d17f";
|
||||||
return locatorFilterColor(type);
|
return locatorFilterColor(type);
|
||||||
}
|
}
|
||||||
@@ -5676,10 +5676,10 @@ function syncAprsReceiverMarker() {
|
|||||||
// Weather satellite image overlays on the map
|
// Weather satellite image overlays on the map
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
const wxsatOverlays = new Map(); // key -> { overlay, track, msg }
|
const satOverlays = new Map(); // key -> { overlay, track, msg }
|
||||||
let wxsatOverlaySeq = 0;
|
let satOverlaySeq = 0;
|
||||||
|
|
||||||
window.addWxsatMapOverlay = function(msg) {
|
window.addSatMapOverlay = function(msg) {
|
||||||
if (!msg || !msg.geo_bounds || !msg.path) return;
|
if (!msg || !msg.geo_bounds || !msg.path) return;
|
||||||
const bounds = msg.geo_bounds;
|
const bounds = msg.geo_bounds;
|
||||||
// bounds = [south, west, north, east]
|
// bounds = [south, west, north, east]
|
||||||
@@ -5688,14 +5688,14 @@ window.addWxsatMapOverlay = function(msg) {
|
|||||||
[bounds[0], bounds[1]], // SW
|
[bounds[0], bounds[1]], // SW
|
||||||
[bounds[2], bounds[3]] // NE
|
[bounds[2], bounds[3]] // NE
|
||||||
);
|
);
|
||||||
const key = "wxsat-" + (++wxsatOverlaySeq);
|
const key = "sat-" + (++satOverlaySeq);
|
||||||
const overlay = L.imageOverlay(msg.path, latLngBounds, {
|
const overlay = L.imageOverlay(msg.path, latLngBounds, {
|
||||||
opacity: 0.55,
|
opacity: 0.55,
|
||||||
interactive: true,
|
interactive: true,
|
||||||
zIndex: 300,
|
zIndex: 300,
|
||||||
});
|
});
|
||||||
overlay.__trxType = "wxsat";
|
overlay.__trxType = "sat";
|
||||||
overlay.__trxWxsatKey = key;
|
overlay.__trxSatKey = key;
|
||||||
overlay.__trxRigIds = msg.rig_id ? new Set([msg.rig_id]) : new Set();
|
overlay.__trxRigIds = msg.rig_id ? new Set([msg.rig_id]) : new Set();
|
||||||
overlay.__trxHistoryVisible = true;
|
overlay.__trxHistoryVisible = true;
|
||||||
mapMarkers.add(overlay);
|
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) {
|
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]]; });
|
const latlngs = msg.ground_track.map(function(pt) { return [pt[0], pt[1]]; });
|
||||||
track = L.polyline(latlngs, {
|
track = L.polyline(latlngs, {
|
||||||
color: mapSourceColor("wxsat"),
|
color: mapSourceColor("sat"),
|
||||||
weight: 2,
|
weight: 2,
|
||||||
opacity: 0.7,
|
opacity: 0.7,
|
||||||
dashArray: "6, 4",
|
dashArray: "6, 4",
|
||||||
});
|
});
|
||||||
track.__trxType = "wxsat";
|
track.__trxType = "sat";
|
||||||
track.__trxWxsatKey = key;
|
track.__trxSatKey = key;
|
||||||
track.__trxRigIds = overlay.__trxRigIds;
|
track.__trxRigIds = overlay.__trxRigIds;
|
||||||
track.__trxHistoryVisible = true;
|
track.__trxHistoryVisible = true;
|
||||||
mapMarkers.add(track);
|
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) {
|
if (aprsMap) {
|
||||||
overlay.addTo(aprsMap);
|
overlay.addTo(aprsMap);
|
||||||
@@ -5741,8 +5741,8 @@ window.addWxsatMapOverlay = function(msg) {
|
|||||||
applyMapFilter();
|
applyMapFilter();
|
||||||
};
|
};
|
||||||
|
|
||||||
window.removeWxsatMapOverlay = function(key) {
|
window.removeSatMapOverlay = function(key) {
|
||||||
const entry = wxsatOverlays.get(key);
|
const entry = satOverlays.get(key);
|
||||||
if (!entry) return;
|
if (!entry) return;
|
||||||
if (entry.overlay) {
|
if (entry.overlay) {
|
||||||
mapMarkers.delete(entry.overlay);
|
mapMarkers.delete(entry.overlay);
|
||||||
@@ -5752,12 +5752,12 @@ window.removeWxsatMapOverlay = function(key) {
|
|||||||
mapMarkers.delete(entry.track);
|
mapMarkers.delete(entry.track);
|
||||||
if (aprsMap && aprsMap.hasLayer(entry.track)) entry.track.removeFrom(aprsMap);
|
if (aprsMap && aprsMap.hasLayer(entry.track)) entry.track.removeFrom(aprsMap);
|
||||||
}
|
}
|
||||||
wxsatOverlays.delete(key);
|
satOverlays.delete(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
window.clearWxsatMapOverlays = function() {
|
window.clearSatMapOverlays = function() {
|
||||||
for (const [key] of wxsatOverlays) {
|
for (const [key] of satOverlays) {
|
||||||
window.removeWxsatMapOverlay(key);
|
window.removeSatMapOverlay(key);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -5805,8 +5805,8 @@ window.clearMapMarkersByType = function(type) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === "wxsat") {
|
if (type === "sat") {
|
||||||
window.clearWxsatMapOverlays();
|
window.clearSatMapOverlays();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8612,7 +8612,7 @@ function dispatchDecodeMessage(msg) {
|
|||||||
if (msg.type === "ft4" && window.onServerFt4) window.onServerFt4(msg);
|
if (msg.type === "ft4" && window.onServerFt4) window.onServerFt4(msg);
|
||||||
if (msg.type === "ft2" && window.onServerFt2) window.onServerFt2(msg);
|
if (msg.type === "ft2" && window.onServerFt2) window.onServerFt2(msg);
|
||||||
if (msg.type === "wspr" && window.onServerWspr) window.onServerWspr(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);
|
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="ft2">FT2</button>
|
||||||
<button class="sub-tab" data-subtab="wspr">WSPR</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="rds">RDS</button>
|
||||||
<button class="sub-tab" data-subtab="wxsat">SAT</button>
|
<button class="sub-tab" data-subtab="sat">SAT</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="subtab-overview" class="sub-tab-panel">
|
<div id="subtab-overview" class="sub-tab-panel">
|
||||||
<div class="plugin-item">
|
<div class="plugin-item">
|
||||||
@@ -801,28 +801,28 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="cw-output"></div>
|
<div id="cw-output"></div>
|
||||||
</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">
|
<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>
|
<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>
|
</div>
|
||||||
<!-- View selector -->
|
<!-- View selector -->
|
||||||
<div class="wxsat-view-bar">
|
<div class="sat-view-bar">
|
||||||
<button id="wxsat-view-live" class="wxsat-view-btn wxsat-view-active" type="button">Live</button>
|
<button id="sat-view-live" class="sat-view-btn sat-view-active" type="button">Live</button>
|
||||||
<button id="wxsat-view-history" class="wxsat-view-btn" type="button">History</button>
|
<button id="sat-view-history" class="sat-view-btn" type="button">History</button>
|
||||||
<button id="wxsat-view-predictions" class="wxsat-view-btn" type="button">Predictions</button>
|
<button id="sat-view-predictions" class="sat-view-btn" type="button">Predictions</button>
|
||||||
</div>
|
</div>
|
||||||
<!-- Live view -->
|
<!-- Live view -->
|
||||||
<div id="wxsat-live-view">
|
<div id="sat-live-view">
|
||||||
<div class="wxsat-live-grid">
|
<div class="sat-live-grid">
|
||||||
<div class="wxsat-live-card">
|
<div class="sat-live-card">
|
||||||
<span class="wxsat-live-label">NOAA APT</span>
|
<span class="sat-live-label">NOAA APT</span>
|
||||||
<span id="wxsat-apt-state" class="wxsat-live-value wxsat-state-idle">Idle</span>
|
<span id="sat-apt-state" class="sat-live-value sat-state-idle">Idle</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="wxsat-live-card">
|
<div class="sat-live-card">
|
||||||
<span class="wxsat-live-label">Meteor LRPT</span>
|
<span class="sat-live-label">Meteor LRPT</span>
|
||||||
<span id="wxsat-lrpt-state" class="wxsat-live-value wxsat-state-idle">Idle</span>
|
<span id="sat-lrpt-state" class="sat-live-value sat-state-idle">Idle</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="margin:0.5rem 0;">
|
<div style="margin:0.5rem 0;">
|
||||||
@@ -835,35 +835,35 @@
|
|||||||
Multi-channel CCSDS-framed imagery (APIDs 64–69) with RGB composite output.
|
Multi-channel CCSDS-framed imagery (APIDs 64–69) with RGB composite output.
|
||||||
</div>
|
</div>
|
||||||
</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>
|
</div>
|
||||||
<!-- History view -->
|
<!-- History view -->
|
||||||
<div id="wxsat-history-view" style="display:none;">
|
<div id="sat-history-view" style="display:none;">
|
||||||
<div class="wxsat-history-controls">
|
<div class="sat-history-controls">
|
||||||
<input id="wxsat-filter" class="ft8-filter" type="text" placeholder="Filter (e.g. NOAA-18, Meteor, APT)" />
|
<input id="sat-filter" class="ft8-filter" type="text" placeholder="Filter (e.g. NOAA-18, Meteor, APT)" />
|
||||||
<select id="wxsat-sort" class="wxsat-sort-select">
|
<select id="sat-sort" class="sat-sort-select">
|
||||||
<option value="newest">Newest first</option>
|
<option value="newest">Newest first</option>
|
||||||
<option value="oldest">Oldest first</option>
|
<option value="oldest">Oldest first</option>
|
||||||
</select>
|
</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="all">All types</option>
|
||||||
<option value="apt">NOAA APT only</option>
|
<option value="apt">NOAA APT only</option>
|
||||||
<option value="lrpt">Meteor LRPT only</option>
|
<option value="lrpt">Meteor LRPT only</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="wxsat-history-header">
|
<div class="sat-history-header">
|
||||||
<span class="wxsat-col-time">Time</span>
|
<span class="sat-col-time">Time</span>
|
||||||
<span class="wxsat-col-type">Type</span>
|
<span class="sat-col-type">Type</span>
|
||||||
<span class="wxsat-col-sat">Satellite</span>
|
<span class="sat-col-sat">Satellite</span>
|
||||||
<span class="wxsat-col-ch">Channels</span>
|
<span class="sat-col-ch">Channels</span>
|
||||||
<span class="wxsat-col-lines">Lines</span>
|
<span class="sat-col-lines">Lines</span>
|
||||||
<span class="wxsat-col-link">Image</span>
|
<span class="sat-col-link">Image</span>
|
||||||
</div>
|
</div>
|
||||||
<div id="wxsat-history-list"></div>
|
<div id="sat-history-list"></div>
|
||||||
<small id="wxsat-history-count" style="color:var(--text-muted);font-size:0.75rem;">No images yet</small>
|
<small id="sat-history-count" style="color:var(--text-muted);font-size:0.75rem;">No images yet</small>
|
||||||
</div>
|
</div>
|
||||||
<!-- Predictions view -->
|
<!-- Predictions view -->
|
||||||
<div id="wxsat-predictions-view" style="display:none;">
|
<div id="sat-predictions-view" style="display:none;">
|
||||||
<div class="sat-pred-header">
|
<div class="sat-pred-header">
|
||||||
<span class="sat-pred-col-time">AOS (UTC)</span>
|
<span class="sat-pred-col-time">AOS (UTC)</span>
|
||||||
<span class="sat-pred-col-sat">Satellite</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-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-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-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>
|
</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>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>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>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>
|
<tr><td>Meteor LRPT</td><td id="about-dec-lrpt" class="about-status-off">Off</td></tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
@@ -1287,7 +1287,7 @@
|
|||||||
<script src="/ft2.js"></script>
|
<script src="/ft2.js"></script>
|
||||||
<script src="/wspr.js"></script>
|
<script src="/wspr.js"></script>
|
||||||
<script src="/cw.js"></script>
|
<script src="/cw.js"></script>
|
||||||
<script src="/wxsat.js"></script>
|
<script src="/sat.js"></script>
|
||||||
<script src="/bookmarks.js"></script>
|
<script src="/bookmarks.js"></script>
|
||||||
<script src="/scheduler.js"></script>
|
<script src="/scheduler.js"></script>
|
||||||
<script src="/background-decode.js"></script>
|
<script src="/background-decode.js"></script>
|
||||||
|
|||||||
+109
-109
@@ -4,27 +4,27 @@
|
|||||||
// Predictions view: next 24 h passes for ham satellites
|
// Predictions view: next 24 h passes for ham satellites
|
||||||
|
|
||||||
// ── DOM references ──────────────────────────────────────────────────
|
// ── DOM references ──────────────────────────────────────────────────
|
||||||
const wxsatStatus = document.getElementById("wxsat-status");
|
const satStatus = document.getElementById("sat-status");
|
||||||
const wxsatLiveView = document.getElementById("wxsat-live-view");
|
const satLiveView = document.getElementById("sat-live-view");
|
||||||
const wxsatHistoryView = document.getElementById("wxsat-history-view");
|
const satHistoryView = document.getElementById("sat-history-view");
|
||||||
const wxsatPredictionsView = document.getElementById("wxsat-predictions-view");
|
const satPredictionsView = document.getElementById("sat-predictions-view");
|
||||||
const wxsatLiveLatest = document.getElementById("wxsat-live-latest");
|
const satLiveLatest = document.getElementById("sat-live-latest");
|
||||||
const wxsatHistoryList = document.getElementById("wxsat-history-list");
|
const satHistoryList = document.getElementById("sat-history-list");
|
||||||
const wxsatHistoryCount = document.getElementById("wxsat-history-count");
|
const satHistoryCount = document.getElementById("sat-history-count");
|
||||||
const wxsatFilterInput = document.getElementById("wxsat-filter");
|
const satFilterInput = document.getElementById("sat-filter");
|
||||||
const wxsatSortSelect = document.getElementById("wxsat-sort");
|
const satSortSelect = document.getElementById("sat-sort");
|
||||||
const wxsatTypeFilter = document.getElementById("wxsat-type-filter");
|
const satTypeFilter = document.getElementById("sat-type-filter");
|
||||||
const wxsatAptState = document.getElementById("wxsat-apt-state");
|
const satAptState = document.getElementById("sat-apt-state");
|
||||||
const wxsatLrptState = document.getElementById("wxsat-lrpt-state");
|
const satLrptState = document.getElementById("sat-lrpt-state");
|
||||||
|
|
||||||
// ── State ───────────────────────────────────────────────────────────
|
// ── State ───────────────────────────────────────────────────────────
|
||||||
let wxsatImageHistory = [];
|
let satImageHistory = [];
|
||||||
const WXSAT_MAX_IMAGES = 100;
|
const SAT_MAX_IMAGES = 100;
|
||||||
let wxsatFilterText = "";
|
let satFilterText = "";
|
||||||
let wxsatActiveView = "live"; // "live" | "history" | "predictions"
|
let satActiveView = "live"; // "live" | "history" | "predictions"
|
||||||
|
|
||||||
// ── UI scheduler helper ─────────────────────────────────────────────
|
// ── UI scheduler helper ─────────────────────────────────────────────
|
||||||
function scheduleWxsatUi(key, job) {
|
function scheduleSatUi(key, job) {
|
||||||
if (typeof window.trxScheduleUiFrameJob === "function") {
|
if (typeof window.trxScheduleUiFrameJob === "function") {
|
||||||
window.trxScheduleUiFrameJob(key, job);
|
window.trxScheduleUiFrameJob(key, job);
|
||||||
return;
|
return;
|
||||||
@@ -33,51 +33,51 @@ function scheduleWxsatUi(key, job) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── View switching ──────────────────────────────────────────────────
|
// ── View switching ──────────────────────────────────────────────────
|
||||||
const wxsatViewLiveBtn = document.getElementById("wxsat-view-live");
|
const satViewLiveBtn = document.getElementById("sat-view-live");
|
||||||
const wxsatViewHistoryBtn = document.getElementById("wxsat-view-history");
|
const satViewHistoryBtn = document.getElementById("sat-view-history");
|
||||||
const wxsatViewPredictionsBtn = document.getElementById("wxsat-view-predictions");
|
const satViewPredictionsBtn = document.getElementById("sat-view-predictions");
|
||||||
|
|
||||||
function switchWxsatView(view) {
|
function switchSatView(view) {
|
||||||
wxsatActiveView = view;
|
satActiveView = view;
|
||||||
if (wxsatLiveView) wxsatLiveView.style.display = view === "live" ? "" : "none";
|
if (satLiveView) satLiveView.style.display = view === "live" ? "" : "none";
|
||||||
if (wxsatHistoryView) wxsatHistoryView.style.display = view === "history" ? "" : "none";
|
if (satHistoryView) satHistoryView.style.display = view === "history" ? "" : "none";
|
||||||
if (wxsatPredictionsView) wxsatPredictionsView.style.display = view === "predictions" ? "" : "none";
|
if (satPredictionsView) satPredictionsView.style.display = view === "predictions" ? "" : "none";
|
||||||
if (wxsatViewLiveBtn) wxsatViewLiveBtn.classList.toggle("wxsat-view-active", view === "live");
|
if (satViewLiveBtn) satViewLiveBtn.classList.toggle("sat-view-active", view === "live");
|
||||||
if (wxsatViewHistoryBtn) wxsatViewHistoryBtn.classList.toggle("wxsat-view-active", view === "history");
|
if (satViewHistoryBtn) satViewHistoryBtn.classList.toggle("sat-view-active", view === "history");
|
||||||
if (wxsatViewPredictionsBtn) wxsatViewPredictionsBtn.classList.toggle("wxsat-view-active", view === "predictions");
|
if (satViewPredictionsBtn) satViewPredictionsBtn.classList.toggle("sat-view-active", view === "predictions");
|
||||||
if (view === "history") {
|
if (view === "history") {
|
||||||
renderWxsatHistoryTable();
|
renderSatHistoryTable();
|
||||||
} else if (view === "predictions") {
|
} else if (view === "predictions") {
|
||||||
loadSatPredictions();
|
loadSatPredictions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wxsatViewLiveBtn?.addEventListener("click", () => switchWxsatView("live"));
|
satViewLiveBtn?.addEventListener("click", () => switchSatView("live"));
|
||||||
wxsatViewHistoryBtn?.addEventListener("click", () => switchWxsatView("history"));
|
satViewHistoryBtn?.addEventListener("click", () => switchSatView("history"));
|
||||||
wxsatViewPredictionsBtn?.addEventListener("click", () => switchWxsatView("predictions"));
|
satViewPredictionsBtn?.addEventListener("click", () => switchSatView("predictions"));
|
||||||
|
|
||||||
// ── Live view: decoder state ────────────────────────────────────────
|
// ── Live view: decoder state ────────────────────────────────────────
|
||||||
// Updated from app.js render() via window.updateWxsatLiveState
|
// Updated from app.js render() via window.updateSatLiveState
|
||||||
window.updateWxsatLiveState = function (update) {
|
window.updateSatLiveState = function (update) {
|
||||||
if (!wxsatAptState || !wxsatLrptState) return;
|
if (!satAptState || !satLrptState) return;
|
||||||
const aptOn = !!update.wxsat_decode_enabled;
|
const aptOn = !!update.wxsat_decode_enabled;
|
||||||
const lrptOn = !!update.lrpt_decode_enabled;
|
const lrptOn = !!update.lrpt_decode_enabled;
|
||||||
|
|
||||||
wxsatAptState.textContent = aptOn ? "Listening" : "Idle";
|
satAptState.textContent = aptOn ? "Listening" : "Idle";
|
||||||
wxsatAptState.className = "wxsat-live-value " + (aptOn ? "wxsat-state-listening" : "wxsat-state-idle");
|
satAptState.className = "sat-live-value " + (aptOn ? "sat-state-listening" : "sat-state-idle");
|
||||||
wxsatLrptState.textContent = lrptOn ? "Listening" : "Idle";
|
satLrptState.textContent = lrptOn ? "Listening" : "Idle";
|
||||||
wxsatLrptState.className = "wxsat-live-value " + (lrptOn ? "wxsat-state-listening" : "wxsat-state-idle");
|
satLrptState.className = "sat-live-value " + (lrptOn ? "sat-state-listening" : "sat-state-idle");
|
||||||
};
|
};
|
||||||
|
|
||||||
function renderWxsatLatestCard() {
|
function renderSatLatestCard() {
|
||||||
if (!wxsatLiveLatest) return;
|
if (!satLiveLatest) return;
|
||||||
if (wxsatImageHistory.length === 0) {
|
if (satImageHistory.length === 0) {
|
||||||
wxsatLiveLatest.innerHTML =
|
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>';
|
'<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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const img = wxsatImageHistory[0];
|
const img = satImageHistory[0];
|
||||||
const decoder = img._decoder || "unknown";
|
const decoder = img._decoder || "unknown";
|
||||||
const typeName = decoder === "lrpt" ? "Meteor LRPT" : "NOAA APT";
|
const typeName = decoder === "lrpt" ? "Meteor LRPT" : "NOAA APT";
|
||||||
const satellite = img.satellite || "";
|
const satellite = img.satellite || "";
|
||||||
@@ -93,30 +93,30 @@ function renderWxsatLatestCard() {
|
|||||||
meta.push(`${lines} ${unit}`);
|
meta.push(`${lines} ${unit}`);
|
||||||
meta.push(`${date} ${ts}`);
|
meta.push(`${date} ${ts}`);
|
||||||
|
|
||||||
let html = `<div class="wxsat-latest-card">`;
|
let html = `<div class="sat-latest-card">`;
|
||||||
html += `<div class="wxsat-latest-title">Latest decoded image</div>`;
|
html += `<div class="sat-latest-title">Latest decoded image</div>`;
|
||||||
html += `<div class="wxsat-latest-meta">${meta.join(" · ")}</div>`;
|
html += `<div class="sat-latest-meta">${meta.join(" · ")}</div>`;
|
||||||
if (img.path) {
|
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>`;
|
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) {
|
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>`;
|
html += `</div>`;
|
||||||
wxsatLiveLatest.innerHTML = html;
|
satLiveLatest.innerHTML = html;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── History view: table ─────────────────────────────────────────────
|
// ── History view: table ─────────────────────────────────────────────
|
||||||
function getFilteredHistory() {
|
function getSatFilteredHistory() {
|
||||||
let items = wxsatImageHistory;
|
let items = satImageHistory;
|
||||||
|
|
||||||
// Type filter
|
// Type filter
|
||||||
const typeVal = wxsatTypeFilter ? wxsatTypeFilter.value : "all";
|
const typeVal = satTypeFilter ? satTypeFilter.value : "all";
|
||||||
if (typeVal === "apt") items = items.filter((i) => i._decoder === "apt");
|
if (typeVal === "apt") items = items.filter((i) => i._decoder === "apt");
|
||||||
else if (typeVal === "lrpt") items = items.filter((i) => i._decoder === "lrpt");
|
else if (typeVal === "lrpt") items = items.filter((i) => i._decoder === "lrpt");
|
||||||
|
|
||||||
// Text filter
|
// Text filter
|
||||||
if (wxsatFilterText) {
|
if (satFilterText) {
|
||||||
items = items.filter((i) => {
|
items = items.filter((i) => {
|
||||||
const haystack = [
|
const haystack = [
|
||||||
i._decoder === "lrpt" ? "meteor lrpt" : "noaa apt",
|
i._decoder === "lrpt" ? "meteor lrpt" : "noaa apt",
|
||||||
@@ -127,12 +127,12 @@ function getFilteredHistory() {
|
|||||||
]
|
]
|
||||||
.join(" ")
|
.join(" ")
|
||||||
.toUpperCase();
|
.toUpperCase();
|
||||||
return haystack.includes(wxsatFilterText);
|
return haystack.includes(satFilterText);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort
|
// Sort
|
||||||
const sortVal = wxsatSortSelect ? wxsatSortSelect.value : "newest";
|
const sortVal = satSortSelect ? satSortSelect.value : "newest";
|
||||||
if (sortVal === "oldest") {
|
if (sortVal === "oldest") {
|
||||||
items = items.slice().reverse();
|
items = items.slice().reverse();
|
||||||
}
|
}
|
||||||
@@ -140,13 +140,13 @@ function getFilteredHistory() {
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderWxsatHistoryRow(img) {
|
function renderSatHistoryRow(img) {
|
||||||
const row = document.createElement("div");
|
const row = document.createElement("div");
|
||||||
row.className = "wxsat-history-row";
|
row.className = "sat-history-row";
|
||||||
|
|
||||||
const decoder = img._decoder || "unknown";
|
const decoder = img._decoder || "unknown";
|
||||||
const typeName = decoder === "lrpt" ? "Meteor LRPT" : "NOAA APT";
|
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 ts = img._ts || "--";
|
||||||
const date = img._tsMs ? new Date(img._tsMs).toLocaleDateString([], { month: "short", day: "numeric" }) : "";
|
const date = img._tsMs ? new Date(img._tsMs).toLocaleDateString([], { month: "short", day: "numeric" }) : "";
|
||||||
const satellite = img.satellite || "--";
|
const satellite = img.satellite || "--";
|
||||||
@@ -157,12 +157,12 @@ function renderWxsatHistoryRow(img) {
|
|||||||
? `<a href="${img.path}" target="_blank" style="color:var(--accent);">PNG</a>`
|
? `<a href="${img.path}" target="_blank" style="color:var(--accent);">PNG</a>`
|
||||||
: "--";
|
: "--";
|
||||||
if (img.geo_bounds) {
|
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 = [
|
row.innerHTML = [
|
||||||
`<span>${date} ${ts}</span>`,
|
`<span>${date} ${ts}</span>`,
|
||||||
`<span class="wxsat-col-type ${typeClass}">${typeName}</span>`,
|
`<span class="sat-col-type ${typeClass}">${typeName}</span>`,
|
||||||
`<span>${satellite}</span>`,
|
`<span>${satellite}</span>`,
|
||||||
`<span>${channels}</span>`,
|
`<span>${channels}</span>`,
|
||||||
`<span>${lines} ${unit}</span>`,
|
`<span>${lines} ${unit}</span>`,
|
||||||
@@ -172,19 +172,19 @@ function renderWxsatHistoryRow(img) {
|
|||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderWxsatHistoryTable() {
|
function renderSatHistoryTable() {
|
||||||
if (!wxsatHistoryList) return;
|
if (!satHistoryList) return;
|
||||||
const items = getFilteredHistory();
|
const items = getSatFilteredHistory();
|
||||||
const fragment = document.createDocumentFragment();
|
const fragment = document.createDocumentFragment();
|
||||||
for (let i = 0; i < items.length; i += 1) {
|
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) {
|
if (satHistoryCount) {
|
||||||
const total = wxsatImageHistory.length;
|
const total = satImageHistory.length;
|
||||||
const shown = items.length;
|
const shown = items.length;
|
||||||
wxsatHistoryCount.textContent =
|
satHistoryCount.textContent =
|
||||||
total === 0
|
total === 0
|
||||||
? "No images yet"
|
? "No images yet"
|
||||||
: shown === total
|
: shown === total
|
||||||
@@ -194,7 +194,7 @@ function renderWxsatHistoryTable() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── Add image to history ────────────────────────────────────────────
|
// ── 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();
|
const tsMs = Number.isFinite(img.ts_ms) ? Number(img.ts_ms) : Date.now();
|
||||||
img._tsMs = tsMs;
|
img._tsMs = tsMs;
|
||||||
img._ts = new Date(tsMs).toLocaleTimeString([], {
|
img._ts = new Date(tsMs).toLocaleTimeString([], {
|
||||||
@@ -204,55 +204,55 @@ function addWxsatImage(img, decoder) {
|
|||||||
});
|
});
|
||||||
img._decoder = decoder;
|
img._decoder = decoder;
|
||||||
|
|
||||||
wxsatImageHistory.unshift(img);
|
satImageHistory.unshift(img);
|
||||||
if (wxsatImageHistory.length > WXSAT_MAX_IMAGES) {
|
if (satImageHistory.length > SAT_MAX_IMAGES) {
|
||||||
wxsatImageHistory = wxsatImageHistory.slice(0, WXSAT_MAX_IMAGES);
|
satImageHistory = satImageHistory.slice(0, SAT_MAX_IMAGES);
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduleWxsatUi("wxsat-latest", () => renderWxsatLatestCard());
|
scheduleSatUi("sat-latest", () => renderSatLatestCard());
|
||||||
if (wxsatActiveView === "history") {
|
if (satActiveView === "history") {
|
||||||
scheduleWxsatUi("wxsat-history", () => renderWxsatHistoryTable());
|
scheduleSatUi("sat-history", () => renderSatHistoryTable());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Server callbacks ────────────────────────────────────────────────
|
// ── Server callbacks ────────────────────────────────────────────────
|
||||||
window.onServerWxsatImage = function (msg) {
|
window.onServerSatImage = function (msg) {
|
||||||
if (wxsatStatus) wxsatStatus.textContent = "Image received (NOAA APT)";
|
if (satStatus) satStatus.textContent = "Image received (NOAA APT)";
|
||||||
addWxsatImage(msg, "apt");
|
addSatImage(msg, "apt");
|
||||||
if (msg.geo_bounds && msg.path && window.addWxsatMapOverlay) {
|
if (msg.geo_bounds && msg.path && window.addSatMapOverlay) {
|
||||||
window.addWxsatMapOverlay(msg);
|
window.addSatMapOverlay(msg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
window.onServerLrptImage = function (msg) {
|
window.onServerLrptImage = function (msg) {
|
||||||
if (wxsatStatus) wxsatStatus.textContent = "Image received (Meteor LRPT)";
|
if (satStatus) satStatus.textContent = "Image received (Meteor LRPT)";
|
||||||
addWxsatImage(msg, "lrpt");
|
addSatImage(msg, "lrpt");
|
||||||
if (msg.geo_bounds && msg.path && window.addWxsatMapOverlay) {
|
if (msg.geo_bounds && msg.path && window.addSatMapOverlay) {
|
||||||
window.addWxsatMapOverlay(msg);
|
window.addSatMapOverlay(msg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
window.resetWxsatHistoryView = function () {
|
window.resetSatHistoryView = function () {
|
||||||
wxsatImageHistory = [];
|
satImageHistory = [];
|
||||||
if (wxsatHistoryList) wxsatHistoryList.innerHTML = "";
|
if (satHistoryList) satHistoryList.innerHTML = "";
|
||||||
renderWxsatLatestCard();
|
renderSatLatestCard();
|
||||||
renderWxsatHistoryTable();
|
renderSatHistoryTable();
|
||||||
if (window.clearWxsatMapOverlays) window.clearWxsatMapOverlays();
|
if (window.clearSatMapOverlays) window.clearSatMapOverlays();
|
||||||
};
|
};
|
||||||
|
|
||||||
window.pruneWxsatHistoryView = function () {
|
window.pruneSatHistoryView = function () {
|
||||||
renderWxsatHistoryTable();
|
renderSatHistoryTable();
|
||||||
renderWxsatLatestCard();
|
renderSatLatestCard();
|
||||||
};
|
};
|
||||||
|
|
||||||
// ── Toggle buttons ──────────────────────────────────────────────────
|
// ── Toggle buttons ──────────────────────────────────────────────────
|
||||||
const wxsatDecodeToggleBtn = document.getElementById("wxsat-decode-toggle-btn");
|
const satDecodeToggleBtn = document.getElementById("sat-decode-toggle-btn");
|
||||||
wxsatDecodeToggleBtn?.addEventListener("click", async () => {
|
satDecodeToggleBtn?.addEventListener("click", async () => {
|
||||||
try {
|
try {
|
||||||
await window.takeSchedulerControlForDecoderDisable?.(wxsatDecodeToggleBtn);
|
await window.takeSchedulerControlForDecoderDisable?.(satDecodeToggleBtn);
|
||||||
await postPath("/toggle_wxsat_decode");
|
await postPath("/toggle_wxsat_decode");
|
||||||
} catch (e) {
|
} 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 ───────────────────────────────────
|
// ── Filter / sort event listeners ───────────────────────────────────
|
||||||
wxsatFilterInput?.addEventListener("input", () => {
|
satFilterInput?.addEventListener("input", () => {
|
||||||
wxsatFilterText = wxsatFilterInput.value.trim().toUpperCase();
|
satFilterText = satFilterInput.value.trim().toUpperCase();
|
||||||
renderWxsatHistoryTable();
|
renderSatHistoryTable();
|
||||||
});
|
});
|
||||||
|
|
||||||
wxsatSortSelect?.addEventListener("change", () => renderWxsatHistoryTable());
|
satSortSelect?.addEventListener("change", () => renderSatHistoryTable());
|
||||||
wxsatTypeFilter?.addEventListener("change", () => renderWxsatHistoryTable());
|
satTypeFilter?.addEventListener("change", () => renderSatHistoryTable());
|
||||||
|
|
||||||
// ── Settings: clear history ─────────────────────────────────────────
|
// ── Settings: clear history ─────────────────────────────────────────
|
||||||
document
|
document
|
||||||
.getElementById("settings-clear-wxsat-history")
|
.getElementById("settings-clear-sat-history")
|
||||||
?.addEventListener("click", async () => {
|
?.addEventListener("click", async () => {
|
||||||
try {
|
try {
|
||||||
await postPath("/clear_wxsat_decode");
|
await postPath("/clear_wxsat_decode");
|
||||||
await postPath("/clear_lrpt_decode");
|
await postPath("/clear_lrpt_decode");
|
||||||
window.resetWxsatHistoryView();
|
window.resetSatHistoryView();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Weather satellite history clear failed", e);
|
console.error("Weather satellite history clear failed", e);
|
||||||
}
|
}
|
||||||
@@ -372,10 +372,10 @@ async function loadSatPredictions() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── Navigate to map centered on satellite image bounds ──────────────
|
// ── Navigate to map centered on satellite image bounds ──────────────
|
||||||
window.wxsatShowOnMap = function (south, west, north, east) {
|
window.satShowOnMap = function (south, west, north, east) {
|
||||||
// Enable wxsat filter if not active
|
// Enable sat filter if not active
|
||||||
if (typeof window.enableMapSourceFilter === "function") {
|
if (typeof window.enableMapSourceFilter === "function") {
|
||||||
window.enableMapSourceFilter("wxsat");
|
window.enableMapSourceFilter("sat");
|
||||||
}
|
}
|
||||||
// Navigate to the center of the image bounds
|
// Navigate to the center of the image bounds
|
||||||
const lat = (south + north) / 2;
|
const lat = (south + north) / 2;
|
||||||
@@ -386,5 +386,5 @@ window.wxsatShowOnMap = function (south, west, north, east) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// ── Initial render ──────────────────────────────────────────────────
|
// ── Initial render ──────────────────────────────────────────────────
|
||||||
renderWxsatLatestCard();
|
renderSatLatestCard();
|
||||||
renderWxsatHistoryTable();
|
renderSatHistoryTable();
|
||||||
@@ -4539,28 +4539,28 @@ button:focus-visible, input:focus-visible, select:focus-visible {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* ── SAT panel ──────────────────────────────────────────────────────── */
|
/* ── SAT panel ──────────────────────────────────────────────────────── */
|
||||||
.wxsat-view-bar { display: flex; gap: 0; margin-bottom: 0.75rem; border-bottom: 1px solid var(--border); }
|
.sat-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; }
|
.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; }
|
||||||
.wxsat-view-active { border-bottom-color: var(--accent-green); color: var(--accent-green); font-weight: 600; }
|
.sat-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); }
|
.sat-view-btn:hover:not(.sat-view-active) { color: var(--text); }
|
||||||
.wxsat-live-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; margin-bottom: 0.5rem; }
|
.sat-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; }
|
.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; }
|
||||||
.wxsat-live-label { font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; }
|
.sat-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; }
|
.sat-live-value { font-size: 0.9rem; font-weight: 600; }
|
||||||
.wxsat-state-idle { color: var(--text-muted); }
|
.sat-state-idle { color: var(--text-muted); }
|
||||||
.wxsat-state-listening { color: var(--accent-green); }
|
.sat-state-listening { color: var(--accent-green); }
|
||||||
.wxsat-state-decoding { color: #f0a020; }
|
.sat-state-decoding { color: #f0a020; }
|
||||||
.wxsat-history-controls { display: flex; gap: 0.5rem; align-items: center; margin-bottom: 0.5rem; flex-wrap: wrap; }
|
.sat-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; }
|
.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; }
|
||||||
.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); }
|
.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); }
|
||||||
.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)); }
|
.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)); }
|
||||||
.wxsat-history-row:hover { background: var(--bg-hover, rgba(255,255,255,0.02)); }
|
.sat-history-row:hover { background: var(--bg-hover, rgba(255,255,255,0.02)); }
|
||||||
.wxsat-col-type { font-weight: 500; }
|
.sat-col-type { font-weight: 500; }
|
||||||
.wxsat-type-apt { color: #6ec6ff; }
|
.sat-type-apt { color: #6ec6ff; }
|
||||||
.wxsat-type-lrpt { color: #b39ddb; }
|
.sat-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; }
|
.sat-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; }
|
.sat-latest-card .sat-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-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-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 { 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)); }
|
.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-mid { color: #f0a020; }
|
||||||
.sat-pred-el-low { color: var(--text-muted); }
|
.sat-pred-el-low { color: var(--text-muted); }
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
.wxsat-live-grid { grid-template-columns: 1fr; }
|
.sat-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-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-header, .sat-pred-row { grid-template-columns: 5.5rem 1fr 4rem 4.5rem; font-size: 0.75rem; }
|
||||||
.sat-pred-col-dir { display: none; }
|
.sat-pred-col-dir { display: none; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2174,7 +2174,7 @@ pub fn configure(cfg: &mut web::ServiceConfig) {
|
|||||||
.service(ft2_js)
|
.service(ft2_js)
|
||||||
.service(wspr_js)
|
.service(wspr_js)
|
||||||
.service(cw_js)
|
.service(cw_js)
|
||||||
.service(wxsat_js)
|
.service(sat_js)
|
||||||
.service(bookmarks_js)
|
.service(bookmarks_js)
|
||||||
.service(scheduler_js)
|
.service(scheduler_js)
|
||||||
.service(background_decode_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)
|
no_cache_response("application/javascript; charset=utf-8", status::CW_JS)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/wxsat.js")]
|
#[get("/sat.js")]
|
||||||
async fn wxsat_js() -> impl Responder {
|
async fn sat_js() -> impl Responder {
|
||||||
no_cache_response("application/javascript; charset=utf-8", status::WXSAT_JS)
|
no_cache_response("application/javascript; charset=utf-8", status::SAT_JS)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/bookmarks.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 FT2_JS: &str = include_str!("../assets/web/plugins/ft2.js");
|
||||||
pub const WSPR_JS: &str = include_str!("../assets/web/plugins/wspr.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 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 BOOKMARKS_JS: &str = include_str!("../assets/web/plugins/bookmarks.js");
|
||||||
pub const SCHEDULER_JS: &str = include_str!("../assets/web/plugins/scheduler.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");
|
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,
|
pub duration_s: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Well-known amateur satellites: (display name, NORAD ID).
|
/// Satellites included in pass predictions: weather + amateur.
|
||||||
const HAM_SATS: &[(&str, u32)] = &[
|
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),
|
("ISS (ARISS)", 25544),
|
||||||
("AO-91 (RadFxSat)", 43017),
|
("AO-91 (RadFxSat)", 43017),
|
||||||
("AO-92 (Fox-1D)", 43137),
|
("AO-92 (Fox-1D)", 43137),
|
||||||
@@ -457,7 +464,7 @@ pub fn compute_upcoming_passes(
|
|||||||
|
|
||||||
let mut all_passes = Vec::new();
|
let mut all_passes = Vec::new();
|
||||||
|
|
||||||
for &(name, norad_id) in HAM_SATS {
|
for &(name, norad_id) in PREDICTION_SATS {
|
||||||
let tle = guard
|
let tle = guard
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|s| s.get(&norad_id))
|
.and_then(|s| s.get(&norad_id))
|
||||||
|
|||||||
+18
-21
@@ -2648,14 +2648,12 @@ async fn finalize_wxsat_pass(
|
|||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
// Fallback: use station location if available
|
// Fallback: use station location if available
|
||||||
match (station_lat, station_lon) {
|
match (station_lat, station_lon) {
|
||||||
(Some(lat), Some(lon)) => Some(
|
(Some(lat), Some(lon)) => Some(trx_core::geo::estimate_pass_geo_from_station(
|
||||||
trx_core::geo::estimate_pass_geo_from_station(
|
apt_image.first_line_ms,
|
||||||
apt_image.first_line_ms,
|
pass_end_ms,
|
||||||
pass_end_ms,
|
lat,
|
||||||
lat,
|
lon,
|
||||||
lon,
|
)),
|
||||||
),
|
|
||||||
),
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -2877,18 +2875,14 @@ async fn finalize_lrpt_pass(
|
|||||||
station_lon,
|
station_lon,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.or_else(|| {
|
.or_else(|| match (station_lat, station_lon) {
|
||||||
match (station_lat, station_lon) {
|
(Some(lat), Some(lon)) => Some(trx_core::geo::estimate_pass_geo_from_station(
|
||||||
(Some(lat), Some(lon)) => Some(
|
pass_start_ms,
|
||||||
trx_core::geo::estimate_pass_geo_from_station(
|
pass_end_ms,
|
||||||
pass_start_ms,
|
lat,
|
||||||
pass_end_ms,
|
lon,
|
||||||
lat,
|
)),
|
||||||
lon,
|
_ => None,
|
||||||
),
|
|
||||||
),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
let (geo_bounds, ground_track) = match pass_geo {
|
let (geo_bounds, ground_track) = match pass_geo {
|
||||||
Some(geo) => (Some(geo.bounds), Some(geo.ground_track)),
|
Some(geo) => (Some(geo.bounds), Some(geo.ground_track)),
|
||||||
@@ -2907,7 +2901,10 @@ async fn finalize_lrpt_pass(
|
|||||||
ground_track,
|
ground_track,
|
||||||
};
|
};
|
||||||
if geo_bounds.is_some() {
|
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());
|
histories.record_lrpt_image(img.clone());
|
||||||
let _ = decode_tx.send(DecodedMessage::LrptImage(img));
|
let _ = decode_tx.send(DecodedMessage::LrptImage(img));
|
||||||
|
|||||||
Reference in New Issue
Block a user