From 70286382b5c2ef6f8ec6165b9e16c1da00d10e2e Mon Sep 17 00:00:00 2001 From: ceotjoe Date: Fri, 3 Apr 2026 17:27:44 +0200 Subject: [PATCH 1/3] fix: Kp forecast includes 60+ past observations, hiding future predictions The noaa-planetary-k-index-forecast.json endpoint returns a mix of past observed values and future predictions in one array (roughly 7 days of history followed by 3 days of forecast). Without filtering, the server was forwarding all 81 entries; SolarPanel.slice(0, 8) therefore showed only week-old observations rather than upcoming predictions. Filter forecast rows to time_tag > now before sending so the client receives only future predictions. Co-Authored-By: Claude Sonnet 4.6 --- server/routes/space-weather.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/server/routes/space-weather.js b/server/routes/space-weather.js index aa4526fc..d1126d93 100644 --- a/server/routes/space-weather.js +++ b/server/routes/space-weather.js @@ -210,15 +210,20 @@ module.exports = function (app, ctx) { } // Kp forecast — same format change; forecast uses lowercase 'kp' field. + // The endpoint mixes past observations with future predictions; keep only + // entries whose time_tag is in the future so the chart shows predictions. if (kForecastRes.status === 'fulfilled' && kForecastRes.value.ok) { const data = await kForecastRes.value.json(); if (data?.length) { const isObj = !Array.isArray(data[0]); const rows = isObj ? data : data.slice(1); - result.kp.forecast = rows.map((d) => ({ - time: isObj ? d.time_tag : d[0], - value: Number.isFinite(isObj ? d.kp : parseFloat(d[1])) ? (isObj ? d.kp : parseFloat(d[1])) : 0, - })); + const nowIso = new Date().toISOString(); + result.kp.forecast = rows + .filter((d) => (isObj ? d.time_tag : d[0]) > nowIso) + .map((d) => ({ + time: isObj ? d.time_tag : d[0], + value: Number.isFinite(isObj ? d.kp : parseFloat(d[1])) ? (isObj ? d.kp : parseFloat(d[1])) : 0, + })); } } From 4a4e6c31a5b993657a9872b5d7b887f1e728bbe1 Mon Sep 17 00:00:00 2001 From: ceotjoe Date: Fri, 3 Apr 2026 17:32:10 +0200 Subject: [PATCH 2/3] fix: panel footer shows SFI/K from separate NOAA fetch instead of N0NBH The band conditions (GOOD/FAIR/POOR) are calculated from N0NBH data, but the SFI and K footer line was reading from solarData which comes from an independent getSolarData() NOAA fetch. These two sources can diverge, making the displayed indices inconsistent with the conditions shown above. Expose solarFlux and kIndex from useBandConditions extras (already fetched from N0NBH) and prefer those values in the PropagationPanel footer, falling back to solarData only when N0NBH data is unavailable. Co-Authored-By: Claude Sonnet 4.6 --- src/components/PropagationPanel.jsx | 3 ++- src/hooks/useBandConditions.js | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/PropagationPanel.jsx b/src/components/PropagationPanel.jsx index dc3b8457..50c7b84a 100644 --- a/src/components/PropagationPanel.jsx +++ b/src/components/PropagationPanel.jsx @@ -440,7 +440,8 @@ export const PropagationPanel = ({ {/* Geomag + Signal Noise + Source */}
- SFI {solarData?.sfi} • K {solarData?.kIndex} + SFI {bandConditions?.extras?.solarFlux ?? solarData?.sfi} • K{' '} + {bandConditions?.extras?.kIndex ?? solarData?.kIndex} {bandConditions?.extras?.geomagField && ( diff --git a/src/hooks/useBandConditions.js b/src/hooks/useBandConditions.js index 2ba76cec..e2a3a615 100644 --- a/src/hooks/useBandConditions.js +++ b/src/hooks/useBandConditions.js @@ -79,6 +79,8 @@ export const useBandConditions = () => { // Extra solar/geomag data from N0NBH setExtras({ + solarFlux: n0nbh.solarData?.solarFlux, + kIndex: n0nbh.solarData?.kIndex, aIndex: n0nbh.solarData?.aIndex, xray: n0nbh.solarData?.xray, solarWind: n0nbh.solarData?.solarWind, From 474f3b5ef468ac97ed0b216a905ed99f9be0769e Mon Sep 17 00:00:00 2001 From: accius Date: Fri, 3 Apr 2026 11:58:54 -0400 Subject: [PATCH 3/3] fix(lightning): integrate proximity alerts into audio alerts system (#861) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace hardcoded inline WAV playback with the existing audio alerts system. Lightning proximity alerts now appear in Settings > Alerts with per-feed enable/disable, tone selection, and master volume — consistent with all other feed alerts. Defaults to off. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/plugins/layers/useLightning.js | 15 +++++++-------- src/utils/audioAlerts.js | 1 + 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/plugins/layers/useLightning.js b/src/plugins/layers/useLightning.js index 7f4c3c6a..4137fb3d 100644 --- a/src/plugins/layers/useLightning.js +++ b/src/plugins/layers/useLightning.js @@ -2,6 +2,7 @@ import { useState, useEffect, useRef } from 'react'; import { useTranslation } from 'react-i18next'; import { addMinimizeToggle } from './addMinimizeToggle.js'; import { makeDraggable } from './makeDraggable.js'; +import { getAlertSettings, playTone } from '../../utils/audioAlerts'; // Lightning Detection Plugin - Real-time lightning strike visualization // Data source: Blitzortung.org WebSocket API @@ -616,14 +617,12 @@ export function useLayer({ enabled = false, opacity = 0.9, map = null, lowMemory panel.style.boxShadow = '0 0 20px rgba(255, 0, 0, 0.8)'; panel.style.transition = 'all 0.3s ease'; - // Play alert sound if available - try { - const audio = new Audio( - 'data:audio/wav;base64,UklGRnoGAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQoGAACBhYqFbF1fdJivrJBhNjVgodDbq2EcBj+a2/LDciUFLIHO8tiJNwgZaLvt559NEAxQp+PwtmMcBjiR1/LMeSwFJHfH8N2QQAoUXrTp66hVFApGn+DyvmwhBTGH0fPTgjMGHm7A7+OZRAEKT6Ln77BcGAU+ltryxnMnBSp+y/HajDkHGWi77eWdTQ0MUKfj8LZjHAY4kdfy', - ); - audio.volume = 0.3; - audio.play().catch(() => {}); // Ignore errors if audio fails - } catch (e) {} + // Play alert tone via audio alerts system (if enabled in settings) + const alertSettings = getAlertSettings(); + const lightningConf = alertSettings.lightning; + if (lightningConf?.enabled) { + playTone(lightningConf.tone, alertSettings.volume ?? 0.5); + } } else { // No nearby strikes - restore normal appearance panel.style.border = '1px solid var(--border-color)'; diff --git a/src/utils/audioAlerts.js b/src/utils/audioAlerts.js index 653204d5..2a53d0d9 100644 --- a/src/utils/audioAlerts.js +++ b/src/utils/audioAlerts.js @@ -37,6 +37,7 @@ export const ALERT_FEEDS = { dxcluster: { label: 'DX Cluster', defaultTone: 'beep' }, dxpeditions: { label: 'DXpeditions', defaultTone: 'two-tone' }, contests: { label: 'Contests', defaultTone: 'simple' }, + lightning: { label: 'Lightning Proximity', defaultTone: 'chirp' }, }; const LS_KEY = 'ohc_audio_alerts';