unify weather data fetching

This commit is contained in:
terraputix
2026-02-15 20:29:39 +01:00
parent 92e38efebb
commit 71c8a57515
5 changed files with 845 additions and 181 deletions
+29 -98
View File
@@ -7,13 +7,7 @@
import { storedLocation } from '$lib/stores/settings';
import {
buildCurrentTimeSeries,
buildDaylightMarkAreas,
buildDaylightSeries,
convertTimestamps,
getThemeColors
} from '$lib/utils/echarts';
import { buildCurrentTimeSeries, buildDaylightSeries, getThemeColors } from '$lib/utils/echarts';
import { pad } from '$lib/utils/index';
import { ChartContainer, ChartToolbar, EChart } from '$lib/components/charts';
@@ -21,6 +15,14 @@
import { Label } from '$lib/components/ui/label';
import * as Select from '$lib/components/ui/select';
import {
type MarkArea,
type WeekDailyData,
type WeekForecastResult,
type WeekHourlyData,
fetchWeekForecast
} from '$lib/services/weather';
import { defaultParameters, models } from '../../options';
import { getColor } from '../../utils/colors';
import weatherCodes from '../../utils/weather-codes';
@@ -61,42 +63,16 @@
// ─── Fetched Data ───────────────────────────────────────────────────────────
interface HourlyData {
time: number[];
temperature_2m: number[];
precipitation: number[];
precipitation_probability: number[];
weather_code: number[];
windspeed_10m: number[];
winddirection_10m: number[];
cloud_cover: number[];
relative_humidity_2m: number[];
}
interface DailyData {
time: string[];
weather_code: number[];
temperature_2m_max: number[];
temperature_2m_min: number[];
sunrise: number[];
sunset: number[];
sunshine_duration: number[];
precipitation_sum: number[];
windspeed_10m_max: number[];
windgusts_10m_max: number[];
winddirection_10m_dominant: number[];
}
interface FetchedHourly {
hourly: HourlyData;
hourly: WeekHourlyData;
utc_offset_seconds: number;
timestamps: number[];
hourlyDates: Date[];
markAreas: Array<[{ xAxis: number; itemStyle: { color: string } }, { xAxis: number }]>;
markAreas: MarkArea[];
}
interface FetchedDaily {
daily: DailyData;
daily: WeekDailyData;
dailyDates: Date[];
}
@@ -276,73 +252,28 @@
chartInstances = [];
chartComponents = [];
const model = modelList[0];
const hourlyVars = [
'temperature_2m',
'precipitation',
'precipitation_probability',
'weather_code',
'windspeed_10m',
'winddirection_10m',
'cloud_cover',
'relative_humidity_2m'
].join(',');
const dailyVars = [
'weather_code',
'temperature_2m_max',
'temperature_2m_min',
'sunrise',
'sunset',
'sunshine_duration',
'precipitation_sum',
'windspeed_10m_max',
'windgusts_10m_max',
'winddirection_10m_dominant'
].join(',');
const baseParams = `latitude=${loc.latitude}&longitude=${loc.longitude}&temperature_unit=${params.temperature_unit}&wind_speed_unit=${params.wind_speed_unit}&precipitation_unit=${params.precipitation_unit}`;
const modelParam = model === 'best_match' ? '' : `&models=${model}`;
const [hourlyResp, dailyResp] = await Promise.all([
fetch(
`https://api.open-meteo.com/v1/forecast?${baseParams}&hourly=${hourlyVars}${modelParam}&timeformat=unixtime&forecast_days=6&past_days=1&daily=sunrise,sunset`
),
fetch(
`https://api.open-meteo.com/v1/forecast?${baseParams}&daily=${dailyVars}${modelParam}&timeformat=unixtime&forecast_days=6&past_days=1`
)
]);
const [hourlyJson, dailyJson] = await Promise.all([hourlyResp.json(), dailyResp.json()]);
const utcOffset = hourlyJson.utc_offset_seconds ?? 0;
const timestamps = convertTimestamps(hourlyJson.hourly.time, utcOffset);
const hourlyDates = timestamps.map((t: number) => new Date(t));
let markAreas: FetchedHourly['markAreas'] = [];
if (hourlyJson.daily?.sunrise && hourlyJson.daily?.sunset) {
markAreas = buildDaylightMarkAreas(
hourlyJson.daily.sunrise,
hourlyJson.daily.sunset,
utcOffset
);
}
const result: WeekForecastResult = await fetchWeekForecast({
latitude: loc.latitude!,
longitude: loc.longitude!,
model: modelList[0],
temperature_unit: params.temperature_unit as 'celsius' | 'fahrenheit',
wind_speed_unit: params.wind_speed_unit as 'kmh' | 'ms' | 'mph' | 'kn',
precipitation_unit: params.precipitation_unit as 'mm' | 'inch',
forecast_days: 6,
past_days: 1
});
fetchedHourly = {
hourly: hourlyJson.hourly,
utc_offset_seconds: utcOffset,
timestamps,
hourlyDates,
markAreas
hourly: result.hourly,
utc_offset_seconds: result.utcOffsetSeconds,
timestamps: result.hourlyTimestamps,
hourlyDates: result.hourlyDates,
markAreas: result.markAreas
};
const dailyDates = (dailyJson.daily.time as number[]).map(
(t: number) => new Date((t + (dailyJson.utc_offset_seconds ?? 0)) * 1000)
);
fetchedDaily = {
daily: dailyJson.daily,
dailyDates
daily: result.daily,
dailyDates: result.dailyDates
};
loading = false;