Use Ambient station readings for wind/temp threshold alerts in cron
When station keys are configured and the last reading is < 15 min old, the alert cron uses windgustmph and tempf from the station instead of Open-Meteo model values. AQI still comes from Open-Meteo (no station equivalent). Alert bodies now include "(station)" or "(forecast model)" so the source is visible in the notification. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
9620c1b0cd
commit
fdc374b8bd
1 file changed
+24
-4
+24
-4
@@ -593,6 +593,20 @@ async function alertWatcherCron() {
|
||||
const currentHour = now.getHours();
|
||||
const base = `http://localhost:${PORT}`;
|
||||
|
||||
// Fetch station once per cron run — reuses the server-side cache
|
||||
let stationObs = null;
|
||||
if (ambientServerConfig.apiKey && ambientServerConfig.appKey) {
|
||||
try {
|
||||
const qs = `?apiKey=${encodeURIComponent(ambientServerConfig.apiKey)}&appKey=${encodeURIComponent(ambientServerConfig.appKey)}`;
|
||||
const sr = await fetch(`${base}/api/ambient${qs}`);
|
||||
if (sr.ok) {
|
||||
const devices = await sr.json();
|
||||
const d = devices?.[0]?.lastData;
|
||||
if (d?.dateutc && Date.now() - d.dateutc < 15 * 60 * 1000) stationObs = d;
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
for (const sub of [...pushSubscriptions]) {
|
||||
try {
|
||||
// ── NWS alerts ──────────────────────────────────────────────────────────
|
||||
@@ -634,15 +648,21 @@ async function alertWatcherCron() {
|
||||
if (wx) {
|
||||
const c = wx.current;
|
||||
const alerted = sub.lastThresholdAlerted || {};
|
||||
if (sub.thresholds.wind && c.wind_gusts_10m > sub.thresholds.wind && !alerted.wind) {
|
||||
|
||||
const gustVal = stationObs?.windgustmph ?? c.wind_gusts_10m;
|
||||
const gustSrc = stationObs ? 'station' : 'forecast model';
|
||||
if (sub.thresholds.wind && gustVal > sub.thresholds.wind && !alerted.wind) {
|
||||
alerted.wind = true;
|
||||
const body = `Gusts at ${Math.round(c.wind_gusts_10m)} mph — your threshold is ${sub.thresholds.wind} mph`;
|
||||
const body = `Gusts at ${Math.round(gustVal)} mph — your threshold is ${sub.thresholds.wind} mph (${gustSrc})`;
|
||||
await doWebPush(sub, { title: '💨 Wind Alert', body, tag: 'wind-threshold', url: '/' });
|
||||
await doNtfy(sub.ntfyTopic, '💨 Wind Alert', body, 'high');
|
||||
}
|
||||
if (sub.thresholds.tempLow && c.temperature_2m < sub.thresholds.tempLow && !alerted.tempLow) {
|
||||
|
||||
const tempVal = stationObs?.tempf ?? c.temperature_2m;
|
||||
const tempSrc = stationObs ? 'station' : 'forecast model';
|
||||
if (sub.thresholds.tempLow && tempVal < sub.thresholds.tempLow && !alerted.tempLow) {
|
||||
alerted.tempLow = true;
|
||||
const body = `Temperature at ${Math.round(c.temperature_2m)}°F — at or below your freeze threshold`;
|
||||
const body = `Temperature at ${Math.round(tempVal)}°F — at or below your freeze threshold (${tempSrc})`;
|
||||
await doWebPush(sub, { title: '🧊 Freeze Alert', body, tag: 'temp-threshold', url: '/' });
|
||||
await doNtfy(sub.ntfyTopic, '🧊 Freeze Alert', body);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user