Use station data for current conditions; persist keys server-side
Station overlay:
- When Ambient Weather station data is present and fresh (<15 min),
its readings replace the model's current conditions: temp, feels-like,
humidity, dewpoint, wind speed/direction, gusts, pressure (inHg→hPa),
UV index, rain today, wind peek summary, and data-panel readouts
- A small "📡 My Station" badge appears in the hero when active
- applyStationOverlay() is called at the end of renderWeather (instant
if station data already loaded) and again whenever station data
refreshes (so the display stays live every 60 s)
- Hourly/daily forecasts continue to use Open-Meteo
Server-side key persistence:
- POST /api/ambient-config saves keys to data/ambient-config.json
(same persistent volume as VAPID and subscriptions)
- GET /api/ambient-config returns {configured: bool} without exposing keys
- /api/ambient checks query params → saved config → env vars in order
- Settings Save button posts keys to server after a successful test;
confirms "saved for all devices" in the status line
- On page load, if no localStorage keys but server is configured,
the station loads automatically on any device
This commit is contained in:
4 files changed
+151
-4
No files matched your search
+32
-3
@@ -441,10 +441,39 @@ app.get('/api/spc/reports', async (_req, res) => {
|
||||
});
|
||||
|
||||
// ── Ambient Weather personal station ─────────────────────────────────────────
|
||||
const ambientCaches = new Map(); // keyed by apiKey so each user's cache is independent
|
||||
const AMBIENT_CONFIG_FILE = path.join(DATA_DIR, 'ambient-config.json');
|
||||
let ambientServerConfig = { apiKey: '', appKey: '' };
|
||||
try {
|
||||
if (fs.existsSync(AMBIENT_CONFIG_FILE)) {
|
||||
ambientServerConfig = JSON.parse(fs.readFileSync(AMBIENT_CONFIG_FILE, 'utf8'));
|
||||
}
|
||||
} catch {}
|
||||
|
||||
function saveAmbientConfig() {
|
||||
try { fs.writeFileSync(AMBIENT_CONFIG_FILE, JSON.stringify(ambientServerConfig)); } catch {}
|
||||
}
|
||||
|
||||
const ambientCaches = new Map();
|
||||
|
||||
// Save keys server-side so all devices share them
|
||||
app.post('/api/ambient-config', (req, res) => {
|
||||
const { apiKey, appKey } = req.body || {};
|
||||
if (!apiKey || !appKey) return res.status(400).json({ error: 'apiKey and appKey required' });
|
||||
ambientServerConfig = { apiKey, appKey };
|
||||
saveAmbientConfig();
|
||||
res.json({ ok: true });
|
||||
});
|
||||
|
||||
// Return whether server-side keys exist (never expose the actual keys)
|
||||
app.get('/api/ambient-config', (_req, res) => {
|
||||
const hasKeys = !!(ambientServerConfig.apiKey && ambientServerConfig.appKey);
|
||||
res.json({ configured: hasKeys });
|
||||
});
|
||||
|
||||
app.get('/api/ambient', async (req, res) => {
|
||||
const apiKey = req.query.apiKey || process.env.AMBIENT_API_KEY;
|
||||
const appKey = req.query.appKey || process.env.AMBIENT_APP_KEY;
|
||||
// Priority: query params (client override) → server-saved → env vars
|
||||
const apiKey = req.query.apiKey || ambientServerConfig.apiKey || process.env.AMBIENT_API_KEY;
|
||||
const appKey = req.query.appKey || ambientServerConfig.appKey || process.env.AMBIENT_APP_KEY;
|
||||
if (!apiKey || !appKey) return res.status(503).json({ error: 'Ambient Weather keys not configured' });
|
||||
|
||||
const cacheKey = apiKey;
|
||||
|
||||
Reference in new issue
Block a user