Files
weerscherm/src/OpenMeteoClient.php
T
theoandClaude Sonnet 5 8e90eb1129 feat: uuroverzicht per dag (temperatuur, regen, wind)
Tik op een dag in de verwachtingsstrook voor een uuroverzicht van
temperatuur, regen en wind (richting + snelheid), om de 2 uur, 12
punten per dag. Sluit na 20 seconden vanzelf of bij een tik op de
overlay zelf.

Backend: Open-Meteo levert hourly-data in dezelfde call als daily
(geen extra verzoek, dezelfde 60min-cache). Nieuwe HourlyForecastMapper
groepeert per kalenderdatum en bemonstert om het andere uur, robuust
voor de zomertijddag (23/25 uur). OpenMeteoClient::dailyForecast()
hernoemd naar forecast(), geeft nu {daily, hourly} terug. Elke dag in
de forecast-array krijgt een hourly-lijst.

Frontend: temperatuurlijn hergebruikt sparklinePath (nu ook als
sparklinePoints voor exacte uitlijning met de 12-koloms grid), regen
als kleine staafjes, windpijl (nieuw icoon) wijst waarheen de wind
waait. 20s-balk via CSS transition met reflow-restart. Servicewerker
naar v5.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-13 10:18:11 +02:00

40 lines
1.3 KiB
PHP

<?php
declare(strict_types=1);
namespace Weerscherm;
/** Open-Meteo dagverwachting. Gratis voor niet-commercieel gebruik, geen API-key. */
final class OpenMeteoClient
{
private const URL = 'https://api.open-meteo.com/v1/forecast';
public function __construct(private readonly HttpClient $http)
{
}
/** @return array{daily: array<string, mixed>, hourly: array<string, mixed>} */
public function forecast(float $lat, float $lon, string $timezone): array
{
$res = $this->http->get(self::URL, [
'latitude' => $lat,
'longitude' => $lon,
'daily' => 'weather_code,temperature_2m_max,temperature_2m_min,precipitation_sum,precipitation_probability_max',
'hourly' => 'temperature_2m,precipitation,wind_speed_10m,wind_direction_10m',
'timezone' => $timezone,
'forecast_days' => 6,
]);
if ($res->status !== 200) {
throw new UpstreamException("Open-Meteo: HTTP {$res->status}");
}
$json = $res->json();
if (!is_array($json['daily'] ?? null)) {
throw new UpstreamException('Open-Meteo: geen daily-blok in antwoord');
}
return [
'daily' => $json['daily'],
'hourly' => is_array($json['hourly'] ?? null) ? $json['hourly'] : [],
];
}
}