Enhance weather satellite UX with pass geometry, guides, and wider predictions

Pass prediction improvements:
- Widen prediction window to 48h at 5° min elevation (was 24h/15°)
- Add AOS/TCA/LOS pass geometry detail panel with times and bearings
- Fix duration display (was showing seconds labeled as minutes)
- Enhanced pass cards with AOS/LOS times, bearings, and directions
- Add REFRESH button in passes panel header
- Better empty state with clear "set your location" prompt and icon

Countdown and visual:
- Pulse animation on countdown when pass is imminent or active
- Countdown numbers scale up and change color for urgency

Sidebar getting started guide:
- New "Getting Started" section explaining what Meteor satellites are,
  polar orbits, 4-8 passes/day, step-by-step workflow
- "When to look" tips (elevation, day vs night, pass direction)
- "What you need" equipment table with costs
- Collapsed antenna guide by default to reduce initial overwhelm
- Improved offline decode section with clear instructions on where
  to get IQ recordings

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
mitchross
2026-03-25 01:13:37 -04:00
parent c3fafc87ef
commit 554bd701c8
4 changed files with 268 additions and 24 deletions
+27 -1
View File
@@ -2612,10 +2612,36 @@
<div class="wxsat-passes-header">
<span class="wxsat-passes-title">Upcoming Passes</span>
<span class="wxsat-passes-count" id="wxsatPassesCount">0</span>
<button class="wxsat-strip-btn" onclick="WeatherSat.loadPasses()" title="Refresh pass predictions" style="margin-left: auto; font-size: 9px; padding: 2px 6px;">REFRESH</button>
</div>
<!-- Pass geometry detail (shown when pass selected) -->
<div class="wxsat-pass-geometry" id="wxsatPassGeometry" style="display: none;">
<div class="wxsat-geom-event">
<span class="wxsat-geom-label">AOS</span>
<span class="wxsat-geom-time" id="wxsatGeomAosTime">--</span>
<span class="wxsat-geom-az" id="wxsatGeomAosAz">--</span>
</div>
<div class="wxsat-geom-arrow">&rarr;</div>
<div class="wxsat-geom-event wxsat-geom-tca">
<span class="wxsat-geom-label">TCA</span>
<span class="wxsat-geom-time" id="wxsatGeomTcaEl">--</span>
<span class="wxsat-geom-az" id="wxsatGeomTcaAz">--</span>
</div>
<div class="wxsat-geom-arrow">&rarr;</div>
<div class="wxsat-geom-event">
<span class="wxsat-geom-label">LOS</span>
<span class="wxsat-geom-time" id="wxsatGeomLosTime">--</span>
<span class="wxsat-geom-az" id="wxsatGeomLosAz">--</span>
</div>
<div class="wxsat-geom-meta" id="wxsatGeomMeta">--</div>
</div>
<div class="wxsat-passes-list" id="wxsatPassesList">
<div class="wxsat-gallery-empty">
<p>Set location to see pass predictions</p>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" style="width: 32px; height: 32px; margin-bottom: 8px; opacity: 0.3;">
<circle cx="12" cy="12" r="10"/><path d="M12 2v4m0 12v4M2 12h4m12 0h4"/>
</svg>
<p style="font-size: 12px; font-weight: 600; color: var(--text-secondary);">Set your location</p>
<p style="font-size: 11px; margin-top: 4px;">Enter lat/lon in the strip bar above or click the GPS button to load pass predictions</p>
</div>
</div>
</div>
@@ -11,6 +11,74 @@
</p>
</div>
<!-- Getting Started Guide -->
<div class="section">
<h3>Getting Started</h3>
<div style="font-size: 11px; color: var(--text-dim); line-height: 1.6;">
<div style="background: var(--bg-primary); border: 1px solid var(--border-color); border-radius: 4px; padding: 10px; margin-bottom: 10px;">
<strong style="color: var(--accent-cyan); font-size: 12px;">What are Meteor satellites?</strong>
<p style="margin-top: 6px;">
Russia's <strong style="color: var(--text-primary);">Meteor-M2-3</strong> and <strong style="color: var(--text-primary);">Meteor-M2-4</strong>
are polar-orbiting weather satellites that continuously transmit real-time color imagery (clouds, land, sea) at <strong style="color: var(--text-primary);">137.900 MHz</strong>
using the LRPT digital format. Unlike old analog NOAA APT, LRPT produces sharp, full-color images.
</p>
<p style="margin-top: 6px;">
They orbit ~830 km high, circling the Earth every ~100 minutes in a near-polar sun-synchronous orbit.
From any location, you'll typically get <strong style="color: var(--text-primary);">4&ndash;8 usable passes per day</strong>,
each lasting 8&ndash;15 minutes as the satellite crosses your sky.
</p>
</div>
<div style="background: var(--bg-primary); border: 1px solid var(--border-color); border-radius: 4px; padding: 10px; margin-bottom: 10px;">
<strong style="color: var(--accent-cyan); font-size: 12px;">Step-by-step</strong>
<ol style="margin: 6px 0 0 16px; padding: 0;">
<li style="margin-bottom: 4px;"><strong style="color: var(--text-primary);">Set your location</strong> &mdash; Enter your lat/lon in the strip bar above (or click GPS). This is required for pass predictions.</li>
<li style="margin-bottom: 4px;"><strong style="color: var(--text-primary);">Check upcoming passes</strong> &mdash; The pass list shows when each satellite will be overhead. Higher max elevation = better signal. Passes above 30&deg; are "good", above 60&deg; are "excellent".</li>
<li style="margin-bottom: 4px;"><strong style="color: var(--text-primary);">Prepare your antenna</strong> &mdash; You need a 137 MHz antenna outdoors with clear sky (see Antenna Guide below). A $5 V-dipole works for high passes.</li>
<li style="margin-bottom: 4px;"><strong style="color: var(--text-primary);">Click Capture</strong> on a pass card when it's about to start, or enable <strong style="color: var(--text-primary);">AUTO</strong> to let the scheduler capture automatically.</li>
<li style="margin-bottom: 4px;"><strong style="color: var(--text-primary);">Wait for images</strong> &mdash; SatDump will tune, lock the signal, and decode. Decoded images appear in the gallery after the pass completes.</li>
</ol>
</div>
<div style="background: var(--bg-primary); border: 1px solid var(--border-color); border-radius: 4px; padding: 10px; margin-bottom: 10px;">
<strong style="color: var(--accent-cyan); font-size: 12px;">When to look</strong>
<ul style="margin: 6px 0 0 14px; padding: 0;">
<li><strong style="color: var(--text-primary);">Best passes:</strong> When the satellite is high overhead (&gt;30&deg; elevation). The countdown timer shows the next one.</li>
<li><strong style="color: var(--text-primary);">Day vs night:</strong> Daytime passes produce visible-light imagery. Night passes still work but only produce infrared/thermal images.</li>
<li><strong style="color: var(--text-primary);">Both satellites share 137.9 MHz</strong> so they won't transmit at the same time. You'll see separate pass predictions for each.</li>
<li><strong style="color: var(--text-primary);">Pass direction:</strong> Meteor satellites travel roughly north&rarr;south or south&rarr;north. The pass cards show the exact rise/set direction.</li>
</ul>
</div>
<div style="background: var(--bg-primary); border: 1px solid var(--border-color); border-radius: 4px; padding: 10px;">
<strong style="color: var(--accent-cyan); font-size: 12px;">What you need</strong>
<table style="width: 100%; margin-top: 6px; font-size: 10px; border-collapse: collapse;">
<tr style="border-bottom: 1px solid var(--border-color);">
<td style="padding: 3px 4px; color: var(--text-dim);">SDR receiver</td>
<td style="padding: 3px 4px; color: var(--text-primary); text-align: right;">RTL-SDR V3/V4 ($25-35)</td>
</tr>
<tr style="border-bottom: 1px solid var(--border-color);">
<td style="padding: 3px 4px; color: var(--text-dim);">Antenna</td>
<td style="padding: 3px 4px; color: var(--text-primary); text-align: right;">137 MHz V-dipole ($5 DIY) or QFH ($20-30)</td>
</tr>
<tr style="border-bottom: 1px solid var(--border-color);">
<td style="padding: 3px 4px; color: var(--text-dim);">LNA (optional)</td>
<td style="padding: 3px 4px; color: var(--text-primary); text-align: right;">137 MHz filtered, at antenna ($15-25)</td>
</tr>
<tr style="border-bottom: 1px solid var(--border-color);">
<td style="padding: 3px 4px; color: var(--text-dim);">Location</td>
<td style="padding: 3px 4px; color: var(--text-primary); text-align: right;">Outdoors, clear sky view</td>
</tr>
<tr>
<td style="padding: 3px 4px; color: var(--text-dim);">No hardware?</td>
<td style="padding: 3px 4px; color: var(--text-primary); text-align: right;">Use <em>Load Demo Data</em> below to explore the UI</td>
</tr>
</table>
</div>
</div>
</div>
<div class="section">
<h3>Satellite</h3>
<div class="form-group">
@@ -33,10 +101,13 @@
</div>
</div>
<!-- Antenna Guide - detailed -->
<!-- Antenna Guide - detailed (collapsed by default) -->
<div class="section">
<h3>Antenna Guide</h3>
<div style="font-size: 11px; color: var(--text-dim); line-height: 1.5;">
<h3 onclick="this.parentElement.querySelector('.wxsat-antenna-body').classList.toggle('collapsed'); this.querySelector('.wxsat-collapse-icon').classList.toggle('collapsed')" style="cursor: pointer; display: flex; align-items: center; justify-content: space-between; user-select: none;">
Antenna Guide
<span class="wxsat-collapse-icon collapsed" style="font-size: 10px; transition: transform 0.2s; display: inline-block;">&#9660;</span>
</h3>
<div class="wxsat-antenna-body wxsat-test-decode-body collapsed" style="font-size: 11px; color: var(--text-dim); line-height: 1.5;">
<p style="margin-bottom: 10px; color: var(--accent-cyan); font-weight: 600;">
137 MHz band &mdash; your stock SDR antenna will NOT work.
@@ -174,14 +245,22 @@
<div class="section">
<h3 onclick="this.parentElement.querySelector('.wxsat-test-decode-body').classList.toggle('collapsed'); this.querySelector('.wxsat-collapse-icon').classList.toggle('collapsed')" style="cursor: pointer; display: flex; align-items: center; justify-content: space-between; user-select: none;">
Test Decode (File)
Offline Decode (IQ File)
<span class="wxsat-collapse-icon collapsed" style="font-size: 10px; transition: transform 0.2s; display: inline-block;">&#9660;</span>
</h3>
<div class="wxsat-test-decode-body collapsed" style="overflow: hidden;">
<p class="info-text" style="font-size: 11px; color: var(--text-dim); margin-bottom: 8px;">
Decode a pre-recorded Meteor IQ file without SDR hardware.
Shared ground-station recordings are also accepted by the backend.
Decode a pre-recorded Meteor IQ baseband file without SDR hardware.
You need an actual <code>.raw</code>, <code>.sigmf-data</code>, or <code>.wav</code> recording of a Meteor pass.
</p>
<div style="background: var(--bg-primary); border: 1px solid var(--border-color); border-radius: 4px; padding: 8px; margin-bottom: 10px; font-size: 10px; color: var(--text-dim); line-height: 1.5;">
<strong style="color: var(--text-secondary);">Where to get a test file:</strong>
<ul style="margin: 4px 0 0 14px; padding: 0;">
<li>Record one yourself with <code>rtl_sdr -f 137900000 -s 2400000 meteor.raw</code> during a pass</li>
<li>Download samples from <a href="https://www.sigidwiki.com/wiki/Meteor-M_LRPT" target="_blank" rel="noopener" style="color: var(--accent-cyan);">SigID Wiki</a> or <a href="https://www.sondehub.org/" target="_blank" rel="noopener" style="color: var(--accent-cyan);">community forums</a></li>
<li>Place the file in <code>data/weather_sat/</code> on the server</li>
</ul>
</div>
<div class="form-group">
<label>Satellite</label>
<select id="wxsatTestSatSelect" class="mode-select">
@@ -191,8 +270,8 @@
</select>
</div>
<div class="form-group">
<label>File Path (server-side)</label>
<input type="text" id="wxsatTestFilePath" value="data/weather_sat/samples/meteor_lrpt.sigmf-data" style="font-family: 'Roboto Condensed', 'Arial Narrow', sans-serif; font-size: 11px;">
<label>File Path (server-side, relative to app root)</label>
<input type="text" id="wxsatTestFilePath" placeholder="data/weather_sat/my_recording.raw" style="font-family: 'Roboto Condensed', 'Arial Narrow', sans-serif; font-size: 11px;">
</div>
<div class="form-group">
<label>Sample Rate</label>
@@ -203,7 +282,7 @@
</select>
</div>
<button class="mode-btn" onclick="WeatherSat.testDecode()" style="width: 100%; margin-top: 4px;">
Test Decode
Decode File
</button>
</div>
</div>