Log official NWS observations for a reference ZIP and overlay them on the dashboard
Publish Container / publish (push) Successful in 2m33s
Publish Container / publish (push) Successful in 2m33s
- Resolves ZIP (default 24550) to the nearest NWS observation station; logs every observation (normalised imperial values + raw METAR), back-fills ~7 days, snapshots the hourly forecast every 3h, and logs alerts for that point - Chart overlay (temp, humidity/dew point, wind, pressure) with an NWS toggle in the History bar - 'Official NWS observation' card on the Now tab comparing against your station - Settings: change the reference ZIP and see logging status - Exact-unit conversions for NWS values (verified against known conversions) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5ed673bacc
commit
acdcd6a2c5
5 files changed
+364
-20
No files matched your search
@@ -162,6 +162,18 @@ button.primary:disabled { opacity: 0.5; cursor: not-allowed; }
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- NWS reference station -->
|
||||
<div class="section">
|
||||
<div class="section-hdr">NWS Reference Station</div>
|
||||
<p class="hint" style="margin:0 0 0.85rem">Logs every official observation from the National Weather Service station nearest this ZIP code (plus hourly forecast snapshots and alerts) and overlays it on your charts.</p>
|
||||
<div class="threshold-row">
|
||||
<div><label>ZIP code</label><input id="nwsZip" type="text" inputmode="numeric" maxlength="5" placeholder="24550" autocomplete="off"></div>
|
||||
<div style="align-self:end"><button class="primary" id="saveNwsBtn">Save & look up</button></div>
|
||||
</div>
|
||||
<div class="settings-actions"><span id="nwsMsg" class="save-msg"></span></div>
|
||||
<div id="nwsInfo" class="hint"></div>
|
||||
</div>
|
||||
|
||||
<!-- Export / Import -->
|
||||
<div class="section">
|
||||
<div class="section-hdr">Data</div>
|
||||
@@ -423,6 +435,35 @@ checkKeyStatus();
|
||||
loadThresholds();
|
||||
loadStationName();
|
||||
loadLocation();
|
||||
|
||||
// ── NWS reference station ──────────────────────────────────────────────
|
||||
async function loadNwsInfo() {
|
||||
try {
|
||||
const r = await fetch('/api/nws/config');
|
||||
if (!r.ok) return;
|
||||
const c = await r.json();
|
||||
const zipEl = document.getElementById('nwsZip');
|
||||
if (zipEl && !zipEl.value) zipEl.value = c.zip || '';
|
||||
const res = c.resolved;
|
||||
const when = (t) => t ? new Date(t).toLocaleString([], { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }) : '—';
|
||||
document.getElementById('nwsInfo').innerHTML = res
|
||||
? `Station <b>${res.stationId}</b> — ${res.stationName} · ${res.distanceMi ?? '?'} mi from ZIP ${res.zip}${res.place ? ' (' + res.place + ')' : ''}${res.approx ? ' · <i>approximate ZIP location</i>' : ''}<br>${c.observations.toLocaleString()} observations logged · first ${when(c.firstObservation)} · latest ${when(c.lastObservation)}${c.lastError ? '<br><span style="color:var(--accent)">Last error: ' + c.lastError + '</span>' : ''}`
|
||||
: (c.lastError ? `<span style="color:var(--accent)">${c.lastError}</span>` : 'Looking up the station for this ZIP…');
|
||||
} catch {}
|
||||
}
|
||||
document.getElementById('saveNwsBtn')?.addEventListener('click', async () => {
|
||||
const msg = document.getElementById('nwsMsg'), zip = document.getElementById('nwsZip').value.trim();
|
||||
msg.textContent = 'Looking up…'; msg.className = 'save-msg';
|
||||
try {
|
||||
const r = await fetch('/api/nws/config', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ zip }) });
|
||||
const d = await r.json();
|
||||
if (!r.ok) throw new Error(d.error || 'Failed');
|
||||
msg.textContent = 'Saved — logging has started'; await loadNwsInfo();
|
||||
setTimeout(loadNwsInfo, 4000);
|
||||
} catch (e) { msg.textContent = e.message; msg.className = 'save-msg err'; }
|
||||
setTimeout(() => { msg.textContent = ''; }, 6000);
|
||||
});
|
||||
loadNwsInfo();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user