mirror of
https://github.com/smittix/intercept.git
synced 2026-04-24 06:40:00 -07:00
Merge upstream/main and resolve weather-satellite.js conflict
Resolved conflict in static/js/modes/weather-satellite.js: - Kept allPasses state variable and applyPassFilter() for satellite pass filtering - Kept satellite select dropdown listener for filter feature - Adopted upstream's optimistic stop() UI pattern for better responsiveness - Kept optional chaining (pass?.trajectory) since drawPolarPlot can receive null Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
98
templates/partials/modes/morse.html
Normal file
98
templates/partials/modes/morse.html
Normal file
@@ -0,0 +1,98 @@
|
||||
<!-- MORSE CODE MODE -->
|
||||
<div id="morseMode" class="mode-content">
|
||||
<div class="section">
|
||||
<h3>CW/Morse Decoder</h3>
|
||||
<p class="info-text" style="font-size: 11px; color: var(--text-dim); margin-bottom: 12px;">
|
||||
Decode CW (continuous wave) Morse code from amateur radio HF bands using USB demodulation
|
||||
and Goertzel tone detection.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h3>Frequency</h3>
|
||||
<div class="form-group">
|
||||
<label>Frequency (MHz)</label>
|
||||
<input type="number" id="morseFrequency" value="14.060" step="0.001" min="1" max="30">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Band Presets</label>
|
||||
<div class="morse-presets" style="display: flex; flex-wrap: wrap; gap: 4px;">
|
||||
<button class="preset-btn" onclick="MorseMode.setFreq(3.560)">80m</button>
|
||||
<button class="preset-btn" onclick="MorseMode.setFreq(7.030)">40m</button>
|
||||
<button class="preset-btn" onclick="MorseMode.setFreq(10.116)">30m</button>
|
||||
<button class="preset-btn" onclick="MorseMode.setFreq(14.060)">20m</button>
|
||||
<button class="preset-btn" onclick="MorseMode.setFreq(18.080)">17m</button>
|
||||
<button class="preset-btn" onclick="MorseMode.setFreq(21.060)">15m</button>
|
||||
<button class="preset-btn" onclick="MorseMode.setFreq(24.910)">12m</button>
|
||||
<button class="preset-btn" onclick="MorseMode.setFreq(28.060)">10m</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h3>Settings</h3>
|
||||
<div class="form-group">
|
||||
<label>Gain (dB)</label>
|
||||
<input type="number" id="morseGain" value="40" step="1" min="0" max="50">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>PPM Correction</label>
|
||||
<input type="number" id="morsePPM" value="0" step="1" min="-100" max="100">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h3>CW Settings</h3>
|
||||
<div class="form-group">
|
||||
<label>Tone Frequency: <span id="morseToneFreqLabel">700</span> Hz</label>
|
||||
<input type="range" id="morseToneFreq" value="700" min="300" max="1200" step="10"
|
||||
oninput="document.getElementById('morseToneFreqLabel').textContent = this.value">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Speed: <span id="morseWpmLabel">15</span> WPM</label>
|
||||
<input type="range" id="morseWpm" value="15" min="5" max="50" step="1"
|
||||
oninput="document.getElementById('morseWpmLabel').textContent = this.value">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Morse Reference -->
|
||||
<div class="section">
|
||||
<h3 style="cursor: pointer;" onclick="this.parentElement.querySelector('.morse-ref-grid').classList.toggle('collapsed')">
|
||||
Morse Reference <span style="font-size: 10px; color: var(--text-dim);">(click to toggle)</span>
|
||||
</h3>
|
||||
<div class="morse-ref-grid collapsed" style="font-family: var(--font-mono); font-size: 10px; line-height: 1.8; columns: 2; column-gap: 12px; color: var(--text-dim);">
|
||||
<div>A .-</div><div>B -...</div><div>C -.-.</div><div>D -..</div>
|
||||
<div>E .</div><div>F ..-.</div><div>G --.</div><div>H ....</div>
|
||||
<div>I ..</div><div>J .---</div><div>K -.-</div><div>L .-..</div>
|
||||
<div>M --</div><div>N -.</div><div>O ---</div><div>P .--.</div>
|
||||
<div>Q --.-</div><div>R .-.</div><div>S ...</div><div>T -</div>
|
||||
<div>U ..-</div><div>V ...-</div><div>W .--</div><div>X -..-</div>
|
||||
<div>Y -.--</div><div>Z --..</div>
|
||||
<div style="margin-top: 4px; border-top: 1px solid var(--border-color); padding-top: 4px;">0 -----</div>
|
||||
<div style="margin-top: 4px; border-top: 1px solid var(--border-color); padding-top: 4px;">1 .----</div>
|
||||
<div>2 ..---</div><div>3 ...--</div><div>4 ....-</div>
|
||||
<div>5 .....</div><div>6 -....</div><div>7 --...</div>
|
||||
<div>8 ---..</div><div>9 ----.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Status -->
|
||||
<div class="section">
|
||||
<div class="morse-status" style="display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--text-dim);">
|
||||
<span id="morseStatusIndicator" class="status-dot" style="width: 8px; height: 8px; border-radius: 50%; background: var(--text-dim);"></span>
|
||||
<span id="morseStatusText">Standby</span>
|
||||
<span style="margin-left: auto;" id="morseCharCount">0 chars</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- HF Antenna Note -->
|
||||
<div class="section">
|
||||
<p class="info-text" style="font-size: 11px; color: #ffaa00; line-height: 1.5;">
|
||||
CW operates on HF bands (1-30 MHz). Requires an HF-capable SDR with direct sampling
|
||||
or an upconverter, plus an appropriate HF antenna (dipole, end-fed, or random wire).
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button class="run-btn" id="morseStartBtn" onclick="MorseMode.start()">Start Decoder</button>
|
||||
<button class="stop-btn" id="morseStopBtn" onclick="MorseMode.stop()" style="display: none;">Stop Decoder</button>
|
||||
</div>
|
||||
@@ -169,20 +169,32 @@
|
||||
.catch(err => alert('Error: ' + err.message));
|
||||
}
|
||||
|
||||
function stopVdl2Mode() {
|
||||
fetch('/vdl2/stop', { method: 'POST' })
|
||||
.then(r => r.json())
|
||||
.then(() => {
|
||||
document.getElementById('startVdl2Btn').style.display = 'block';
|
||||
document.getElementById('stopVdl2Btn').style.display = 'none';
|
||||
document.getElementById('vdl2StatusText').textContent = 'Standby';
|
||||
document.getElementById('vdl2StatusText').style.color = 'var(--accent-yellow)';
|
||||
if (vdl2MainEventSource) {
|
||||
vdl2MainEventSource.close();
|
||||
vdl2MainEventSource = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
function stopVdl2Mode() {
|
||||
fetch('/vdl2/stop', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ source: 'vdl2_mode' })
|
||||
})
|
||||
.then(async (r) => {
|
||||
const text = await r.text();
|
||||
const data = text ? JSON.parse(text) : {};
|
||||
if (!r.ok || (data.status !== 'stopped' && data.status !== 'success')) {
|
||||
throw new Error(data.message || `HTTP ${r.status}`);
|
||||
}
|
||||
return data;
|
||||
})
|
||||
.then(() => {
|
||||
document.getElementById('startVdl2Btn').style.display = 'block';
|
||||
document.getElementById('stopVdl2Btn').style.display = 'none';
|
||||
document.getElementById('vdl2StatusText').textContent = 'Standby';
|
||||
document.getElementById('vdl2StatusText').style.color = 'var(--accent-yellow)';
|
||||
if (vdl2MainEventSource) {
|
||||
vdl2MainEventSource.close();
|
||||
vdl2MainEventSource = null;
|
||||
}
|
||||
})
|
||||
.catch(err => alert('Failed to stop VDL2: ' + err.message));
|
||||
}
|
||||
|
||||
function startVdl2MainSSE() {
|
||||
if (vdl2MainEventSource) vdl2MainEventSource.close();
|
||||
|
||||
129
templates/partials/modes/wefax.html
Normal file
129
templates/partials/modes/wefax.html
Normal file
@@ -0,0 +1,129 @@
|
||||
<!-- WEFAX MODE -->
|
||||
<div id="wefaxMode" class="mode-content">
|
||||
<div class="section">
|
||||
<h3>WeFax Decoder</h3>
|
||||
<p class="info-text" style="font-size: 11px; color: var(--text-dim); margin-bottom: 12px;">
|
||||
Decode HF weather fax (radiofax) from maritime and aviation weather services.
|
||||
Stations broadcast weather charts on fixed schedules via HF radio.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h3>Station</h3>
|
||||
<div class="form-group">
|
||||
<label>Station</label>
|
||||
<select id="wefaxStation" onchange="WeFax.onStationChange()">
|
||||
<option value="">Select a station...</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Frequency (kHz)</label>
|
||||
<select id="wefaxFrequency">
|
||||
<option value="">Select station first</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h3>Settings</h3>
|
||||
<div class="form-group">
|
||||
<label>IOC (Index of Cooperation)</label>
|
||||
<select id="wefaxIOC">
|
||||
<option value="576" selected>576 (Standard)</option>
|
||||
<option value="288">288 (Half)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>LPM (Lines Per Minute)</label>
|
||||
<select id="wefaxLPM">
|
||||
<option value="120" selected>120 (Standard)</option>
|
||||
<option value="60">60 (Slow)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Gain (dB)</label>
|
||||
<input type="number" id="wefaxGain" value="40" step="1" min="0" max="50">
|
||||
</div>
|
||||
<div class="form-group" style="display: flex; align-items: center; gap: 8px;">
|
||||
<input type="checkbox" id="wefaxDirectSampling" checked>
|
||||
<label for="wefaxDirectSampling" style="margin: 0; cursor: pointer;">Direct Sampling (Q-branch, required for HF)</label>
|
||||
</div>
|
||||
<div class="form-group" style="display: flex; align-items: center; gap: 8px;">
|
||||
<input type="checkbox" id="wefaxAutoUsbAlign" checked>
|
||||
<label for="wefaxAutoUsbAlign" style="margin: 0; cursor: pointer;">Auto USB align listed carrier frequencies (-1.9 kHz)</label>
|
||||
</div>
|
||||
<p class="info-text" style="font-size: 11px; color: var(--text-dim); margin-top: -4px;">
|
||||
Disable this if your source already provides USB dial frequencies.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h3>Auto Capture</h3>
|
||||
<div class="form-group" style="display: flex; align-items: center; gap: 8px;">
|
||||
<input type="checkbox" id="wefaxSidebarAutoSchedule"
|
||||
onchange="WeFax.toggleScheduler(this)">
|
||||
<label for="wefaxSidebarAutoSchedule" style="margin: 0; cursor: pointer;">Auto-capture scheduled broadcasts</label>
|
||||
</div>
|
||||
<p class="info-text" style="font-size: 11px; color: var(--text-dim); margin-top: 4px;">
|
||||
Automatically decode at scheduled broadcast times.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Antenna Guide -->
|
||||
<div class="section">
|
||||
<h3>HF Antenna Guide</h3>
|
||||
<div style="font-size: 11px; color: var(--text-dim); line-height: 1.5;">
|
||||
<p style="margin-bottom: 8px; color: #ffaa00; font-weight: 600;">
|
||||
HF band (2–30 MHz) — requires HF antenna + direct sampling SDR
|
||||
</p>
|
||||
|
||||
<div style="background: var(--bg-primary); border: 1px solid var(--border-color); border-radius: 4px; padding: 10px; margin-bottom: 10px;">
|
||||
<strong style="color: #ffaa00; font-size: 12px;">Requirements</strong>
|
||||
<ul style="margin: 6px 0 0 14px; padding: 0;">
|
||||
<li><strong style="color: var(--text-primary);">SDR:</strong> RTL-SDR (direct sampling), HackRF, LimeSDR, Airspy, or SDRPlay</li>
|
||||
<li><strong style="color: var(--text-primary);">Antenna:</strong> Long wire (10m+), random wire, or dipole for target band</li>
|
||||
<li><strong style="color: var(--text-primary);">Mode:</strong> USB (Upper Sideband) demodulation</li>
|
||||
<li><strong style="color: var(--text-primary);">Signals:</strong> Moderate — HF propagation varies by time of day</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div style="background: var(--bg-primary); border: 1px solid var(--border-color); border-radius: 4px; padding: 10px;">
|
||||
<strong style="color: #ffaa00; font-size: 12px;">Quick Reference</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);">Protocol</td>
|
||||
<td style="padding: 3px 4px; color: var(--text-primary); text-align: right;">AM Facsimile (ITU-T T.4)</td>
|
||||
</tr>
|
||||
<tr style="border-bottom: 1px solid var(--border-color);">
|
||||
<td style="padding: 3px 4px; color: var(--text-dim);">Carrier</td>
|
||||
<td style="padding: 3px 4px; color: var(--text-primary); text-align: right;">1900 Hz</td>
|
||||
</tr>
|
||||
<tr style="border-bottom: 1px solid var(--border-color);">
|
||||
<td style="padding: 3px 4px; color: var(--text-dim);">Deviation</td>
|
||||
<td style="padding: 3px 4px; color: var(--text-primary); text-align: right;">±400 Hz</td>
|
||||
</tr>
|
||||
<tr style="border-bottom: 1px solid var(--border-color);">
|
||||
<td style="padding: 3px 4px; color: var(--text-dim);">Black / White</td>
|
||||
<td style="padding: 3px 4px; color: var(--text-primary); text-align: right;">1500 / 2300 Hz</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 3px 4px; color: var(--text-dim);">Start / Stop tone</td>
|
||||
<td style="padding: 3px 4px; color: var(--text-primary); text-align: right;">300 / 450 Hz</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h3>Resources</h3>
|
||||
<div style="display: flex; flex-direction: column; gap: 6px;">
|
||||
<a href="https://www.weather.gov/marine/radiofax_charts" target="_blank" rel="noopener" class="preset-btn" style="text-decoration: none; text-align: center;">
|
||||
NWS Radiofax Charts
|
||||
</a>
|
||||
<a href="https://www.nws.noaa.gov/os/marine/rfax.pdf" target="_blank" rel="noopener" class="preset-btn" style="text-decoration: none; text-align: center;">
|
||||
NOAA Radiofax Schedule (PDF)
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user