115 lines
5.2 KiB
C#
115 lines
5.2 KiB
C#
using System.IO.Compression;
|
|
using System.Text;
|
|
using Xunit;
|
|
|
|
namespace LehrerApp.Api.Tests;
|
|
|
|
public sealed class DwdWeatherServiceTests
|
|
{
|
|
[Fact]
|
|
public void ParseStationCatalog_LiestFestbreitenformatUndFindetNaechsteStation()
|
|
{
|
|
const string catalog = """
|
|
ID ICAO NAME LAT LON ELEV
|
|
----- ---- -------------------- ----- ------- -----
|
|
10641 EDDF OFFENBACH-WETTERPARK 50.08 8.78 119
|
|
10382 EDDT BERLIN-TEGEL 52.56 13.31 37
|
|
""";
|
|
|
|
var stations = DwdWeatherService.ParseStationCatalog(catalog);
|
|
var nearest = DwdWeatherService.FindNearestStation(stations, 50.1, 8.7);
|
|
|
|
Assert.Equal(2, stations.Count);
|
|
Assert.Equal("10641", nearest!.Id);
|
|
Assert.Equal("OFFENBACH-WETTERPARK", nearest.Name);
|
|
}
|
|
|
|
[Fact]
|
|
public void ParseMosmix_KonvertiertEinheitenUndBehaeltFehlwerteAlsNull()
|
|
{
|
|
var now = DateTime.UtcNow.AddHours(1).ToString("yyyy-MM-dd'T'HH:00:00.000'Z'");
|
|
var kml = $$"""
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<kml:kml xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:dwd="https://opendata.dwd.de/weather/lib/pointforecast_dwd_extension_V1_0.xsd">
|
|
<kml:Document><kml:ExtendedData><dwd:ProductDefinition>
|
|
<dwd:IssueTime>2026-08-23T15:00:00Z</dwd:IssueTime>
|
|
<dwd:ForecastTimeSteps><dwd:TimeStep>{{now}}</dwd:TimeStep></dwd:ForecastTimeSteps>
|
|
</dwd:ProductDefinition></kml:ExtendedData><kml:Placemark><kml:ExtendedData>
|
|
<dwd:Forecast dwd:elementName="TTT"><dwd:value>293.15</dwd:value></dwd:Forecast>
|
|
<dwd:Forecast dwd:elementName="FF"><dwd:value>5</dwd:value></dwd:Forecast>
|
|
<dwd:Forecast dwd:elementName="FX1"><dwd:value>-</dwd:value></dwd:Forecast>
|
|
<dwd:Forecast dwd:elementName="RR1c"><dwd:value>1.25</dwd:value></dwd:Forecast>
|
|
<dwd:Forecast dwd:elementName="Neff"><dwd:value>75</dwd:value></dwd:Forecast>
|
|
<dwd:Forecast dwd:elementName="ww"><dwd:value>61</dwd:value></dwd:Forecast>
|
|
</kml:ExtendedData></kml:Placemark></kml:Document>
|
|
</kml:kml>
|
|
""";
|
|
|
|
var parsed = DwdWeatherService.ParseMosmix(Zip("forecast.kml", kml));
|
|
var hour = Assert.Single(parsed.Hours);
|
|
|
|
Assert.Equal(20, hour.TemperatureC);
|
|
Assert.Equal(18, hour.WindSpeedKmh);
|
|
Assert.Null(hour.WindGustKmh);
|
|
Assert.Equal(1.3, hour.PrecipitationMm);
|
|
Assert.Equal(61, hour.WeatherCode);
|
|
}
|
|
|
|
[Fact]
|
|
public void ParseMosmix_LiefertMehrAlsDreiTageFuerFolgewoche()
|
|
{
|
|
var start = DateTime.UtcNow.AddHours(1);
|
|
var timeSteps = string.Join("", Enumerable.Range(0, 100)
|
|
.Select(i => $"<dwd:TimeStep>{start.AddHours(i):yyyy-MM-dd'T'HH:mm:ss'Z'}</dwd:TimeStep>"));
|
|
var values = string.Join(' ', Enumerable.Repeat("293.15", 100));
|
|
var kml = $$"""
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<kml:kml xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:dwd="https://opendata.dwd.de/weather/lib/pointforecast_dwd_extension_V1_0.xsd">
|
|
<kml:Document><kml:ExtendedData><dwd:ProductDefinition>
|
|
<dwd:ForecastTimeSteps>{{timeSteps}}</dwd:ForecastTimeSteps>
|
|
</dwd:ProductDefinition></kml:ExtendedData><kml:Placemark><kml:ExtendedData>
|
|
<dwd:Forecast dwd:elementName="TTT"><dwd:value>{{values}}</dwd:value></dwd:Forecast>
|
|
</kml:ExtendedData></kml:Placemark></kml:Document>
|
|
</kml:kml>
|
|
""";
|
|
|
|
var parsed = DwdWeatherService.ParseMosmix(Zip("forecast.kml", kml));
|
|
|
|
Assert.Equal(100, parsed.Hours.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void ParseCapArchive_OrdnetWarnpolygonGeografischZu()
|
|
{
|
|
var xml = """
|
|
<alert xmlns="urn:oasis:names:tc:emergency:cap:1.2">
|
|
<identifier>warnung-1</identifier><status>Actual</status>
|
|
<info><language>de-DE</language><event>GEWITTER</event><severity>Severe</severity>
|
|
<onset>2026-08-23T18:00:00Z</onset><expires>2099-08-23T20:00:00Z</expires>
|
|
<headline>Amtliche Warnung</headline><description>Test</description>
|
|
<area><polygon>50.0,8.0 50.0,9.0 51.0,9.0 51.0,8.0 50.0,8.0</polygon></area>
|
|
</info>
|
|
</alert>
|
|
""";
|
|
|
|
var warning = Assert.Single(DwdWeatherService.ParseCapArchive(
|
|
Zip("warning.xml", xml), DateTime.UtcNow));
|
|
|
|
Assert.True(DwdWeatherService.PointInPolygon(warning.Polygons[0], 50.5, 8.5));
|
|
Assert.False(DwdWeatherService.PointInPolygon(warning.Polygons[0], 52.0, 8.5));
|
|
Assert.Equal("GEWITTER", warning.Warning.Event);
|
|
}
|
|
|
|
private static byte[] Zip(string fileName, string content)
|
|
{
|
|
using var memory = new MemoryStream();
|
|
using (var archive = new ZipArchive(memory, ZipArchiveMode.Create, leaveOpen: true))
|
|
{
|
|
var entry = archive.CreateEntry(fileName);
|
|
using var writer = new StreamWriter(entry.Open(), new UTF8Encoding(false));
|
|
writer.Write(content);
|
|
}
|
|
return memory.ToArray();
|
|
}
|
|
}
|