Data/src/main/java/de/ph87/data/weather/WeatherService.java
2025-02-28 12:06:17 +01:00

77 lines
2.6 KiB
Java

package de.ph87.data.weather;
import com.fasterxml.jackson.databind.*;
import lombok.*;
import lombok.extern.slf4j.*;
import org.springframework.boot.context.event.*;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.*;
import org.springframework.stereotype.*;
import java.io.*;
import java.net.*;
import java.nio.charset.*;
import java.time.*;
import java.time.format.*;
import java.util.*;
@Slf4j
@Service
@EnableScheduling
@RequiredArgsConstructor
public class WeatherService {
private List<WeatherDay> days = new ArrayList<>();
private final WeatherConfig weatherConfig;
private final ObjectMapper objectMapper;
@NonNull
public List<WeatherDay> all() {
return new ArrayList<>(days);
}
@Scheduled(cron = "0 0 * * * *")
@EventListener(ApplicationStartedEvent.class)
public void update() {
try {
final LocalDate today = LocalDate.now();
final LocalDate first = today.minusDays(weatherConfig.getPastDays());
final LocalDate end = today.plusDays(weatherConfig.getFutureDays());
final List<WeatherDay> newDays = new ArrayList<>();
log.debug("Updating Weather...");
for (LocalDate day = first; !day.isAfter(end); day = day.plusDays(1)) {
final WeatherDay weatherDay = new WeatherDay(fetchDay(day));
newDays.add(weatherDay);
if (log.isDebugEnabled()) {
log.debug(" {}:", weatherDay);
for (WeatherDay.Hour hour : weatherDay.getHours()) {
log.debug(" %s: %4s clouds, %9s, %4s".formatted(hour.date.toLocalTime(), hour.getClouds(), hour.getIrradiation(), hour.getPrecipitation()));
}
}
}
days = newDays;
log.info("Weather update complete");
} catch (IOException e) {
log.error(e.toString());
}
}
@NonNull
public BrightSkyDto fetchDay(@NonNull final LocalDate day) throws IOException {
final String url = weatherConfig.getUrlPattern()
.replace("{date}", ZonedDateTime.of(day, LocalTime.MIDNIGHT, ZoneId.systemDefault()).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME))
.replace("{latitude}", weatherConfig.getLatitude() + "")
.replace("{longitude}", weatherConfig.getLongitude() + "");
final HttpURLConnection connection = (HttpURLConnection) URI.create(url).toURL().openConnection();
final int responseCode = connection.getResponseCode();
final byte[] bytes = connection.getInputStream().readAllBytes();
if (responseCode / 100 != 2) {
throw new IOException("responseCode=%d, message: %s".formatted(responseCode, new String(bytes, StandardCharsets.UTF_8)));
}
return objectMapper.readValue(bytes, BrightSkyDto.class);
}
}