Data2025/src/main/java/de/ph87/data/weather/WeatherService.java

78 lines
2.7 KiB
Java

package de.ph87.data.weather;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import tools.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Service
@EnableScheduling
@RequiredArgsConstructor
public class WeatherService {
private List<WeatherHour> hours = new ArrayList<>();
private final WeatherConfig weatherConfig;
private final ObjectMapper objectMapper;
@NonNull
public List<WeatherHour> all() {
return new ArrayList<>(hours);
}
@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<WeatherHour> hours = new ArrayList<>();
log.debug("Updating Weather...");
for (LocalDate day = first; !day.isAfter(end); day = day.plusDays(1)) {
fetchDay(day).getWeather().stream().map(WeatherHour::new).forEach(hours::add);
}
this.hours = hours;
log.info("Weather update complete");
} catch (Exception e) {
log.error("Failed fetching Weather data: {}", 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);
}
}