import { service } from '../service' import { ForecastData, TimeseriesData } from './weather/types' type WeatherItem = DetailedWeatherItem | SummaryWeatherItem interface SummaryWeatherItem { date: string temperature: { min: number; max: number } summary: null | string precipitationAmount: number } interface DetailedWeatherItem { date: string summary: null | string precipitationAmount: null | number temperature: number windDirection: number windSpeed: number relativeHumidity: number airPressure: number } const API_URL = 'https://api.met.no/weatherapi' const API_USER_AGENT = 'KamenWatch 1.0 jan@zipek.cz' const API_PARAMS = { lat: '50.070219', lon: '14.414034', } const getSummaryItem = (date: string, item: TimeseriesData) => { if (item.next_6_hours) { return { date, temperature: { min: item.next_6_hours.details.air_temperature_min, max: item.next_6_hours.details.air_temperature_max, }, summary: item.next_6_hours.summary.symbol_code, precipitationAmount: item.next_6_hours.details.precipitation_amount, } as SummaryWeatherItem } } const getDetailedItem = (date: string, item: TimeseriesData) => { const detail = item.instant?.details if (!detail) { return } const result: DetailedWeatherItem = { date, temperature: detail.air_temperature, airPressure: detail.air_pressure_at_sea_level, relativeHumidity: detail.relative_humidity, windDirection: detail.wind_from_direction, windSpeed: detail.wind_speed, precipitationAmount: null, summary: null, } if (item.next_1_hours) { result.summary = item.next_1_hours.summary.symbol_code result.precipitationAmount = item.next_1_hours.details.precipitation_amount } else if (item.next_6_hours) { result.summary = item.next_6_hours.summary.symbol_code } else if (item.next_12_hours) { result.summary = item.next_12_hours.summary.symbol_code } return result } export const weatherService = service(({ fetch }) => { return async () => { const forecast: ForecastData = JSON.parse( await fetch( `${API_URL}/locationforecast/2.0/complete?lat=${API_PARAMS.lat}&lon=${API_PARAMS.lon}`, { headers: { 'User-agent': API_USER_AGENT, }, }, ), ) const result = { now: null as WeatherItem | null, hours: {} as Record, days: {} as Record, } let recordedHours = 0 const nowDays = Math.floor(Date.now() / 1000 / 3600 / 24) const nowHours = Math.floor(Date.now() / 1000 / 3600) forecast.properties.timeseries.forEach((item, index) => { const date = new Date(item['time']) const converted = getDetailedItem(item.time, item.data) if (!converted) { return } if (index === 0) { result.now = converted } if (date.getHours() === 14) { const dayData = getSummaryItem(item.time, item.data) if (dayData) { const daysDiff = Math.floor(date.getTime() / 1000 / 3600 / 24) - nowDays result.days[daysDiff] = dayData } } if (recordedHours < 23) { const hoursDiff = Math.floor(date.getTime() / 1000 / 3600) - nowHours result.hours[hoursDiff] = converted recordedHours += 1 } }) return result } })