import { fetchJson, maybe } from "../http"; import type { AirQuality } from "../types"; /** * Air quality from Open-Meteo's free air-quality API (CAMS data), used for * every provider so the AQI always means the same thing. * Docs: https://open-meteo.com/en/docs/air-quality-api * * The same call also tells us the location's IANA time zone, which some * providers (Tomorrow.io, OpenWeather free) don't give us. */ interface AirQualityResponse { timezone: string; current: { us_aqi: number | null; pm2_5: number | null; pm10: number | null; ozone: number | null; nitrogen_dioxide: number | null; }; } export interface LocalContext { timeZone: string; airQuality: AirQuality | null; } export async function getLocalContext(lat: number, lon: number): Promise { const params = new URLSearchParams({ latitude: String(lat), longitude: String(lon), current: "us_aqi,pm2_5,pm10,ozone,nitrogen_dioxide", timezone: "auto", }); const data = await fetchJson( `https://air-quality-api.open-meteo.com/v1/air-quality?${params}`, "Open-Meteo air quality", { cacheSeconds: 1800 }, // air quality updates hourly at most ); const c = data.current; return { timeZone: data.timezone, airQuality: c.us_aqi === null ? null : { usAqi: Math.round(c.us_aqi), pm25: maybe(c.pm2_5), pm10: maybe(c.pm10), ozone: maybe(c.ozone), no2: maybe(c.nitrogen_dioxide) }, }; }