110 lines
3.3 KiB
C#
110 lines
3.3 KiB
C#
using System.Text.Json;
|
|
|
|
namespace Backend.ServiceHandler
|
|
{
|
|
public sealed class WeatherService
|
|
{
|
|
private static readonly HttpClient Http = new()
|
|
{
|
|
DefaultRequestHeaders = { { "User-Agent", "SoftTrader/1.0" } }
|
|
};
|
|
|
|
public async Task<(string City, double Latitude, double Longitude)?> GeocodeAsync(
|
|
string city,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
string encoded = Uri.EscapeDataString(city.Trim());
|
|
string url = $"https://geocoding-api.open-meteo.com/v1/search?name={encoded}&count=1&language=en";
|
|
|
|
string json = await Http.GetStringAsync(url, cancellationToken);
|
|
using var doc = JsonDocument.Parse(json);
|
|
|
|
if (!doc.RootElement.TryGetProperty("results", out var results) ||
|
|
results.GetArrayLength() == 0)
|
|
return null;
|
|
|
|
var first = results[0];
|
|
string name = first.GetProperty("name").GetString() ?? city;
|
|
double lat = first.GetProperty("latitude").GetDouble();
|
|
double lng = first.GetProperty("longitude").GetDouble();
|
|
|
|
return (name, lat, lng);
|
|
}
|
|
|
|
public async Task<WeatherResult?> GetCurrentWeatherAsync(
|
|
double latitude,
|
|
double longitude,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
string url =
|
|
$"https://api.open-meteo.com/v1/forecast" +
|
|
$"?latitude={latitude}&longitude={longitude}" +
|
|
$"¤t=temperature_2m,relative_humidity_2m,weather_code,wind_speed_10m" +
|
|
$"&temperature_unit=fahrenheit" +
|
|
$"&wind_speed_unit=mph";
|
|
|
|
string json = await Http.GetStringAsync(url, cancellationToken);
|
|
using var doc = JsonDocument.Parse(json);
|
|
|
|
if (!doc.RootElement.TryGetProperty("current", out var current))
|
|
return null;
|
|
|
|
return new WeatherResult
|
|
{
|
|
TemperatureF = current.GetProperty("temperature_2m").GetDouble(),
|
|
HumidityPercent = current.GetProperty("relative_humidity_2m").GetDouble(),
|
|
WeatherCode = current.GetProperty("weather_code").GetInt32(),
|
|
WindSpeedMph = current.GetProperty("wind_speed_10m").GetDouble()
|
|
};
|
|
}
|
|
}
|
|
|
|
public sealed class WeatherResult
|
|
{
|
|
public double TemperatureF { get; init; }
|
|
public double HumidityPercent { get; init; }
|
|
public int WeatherCode { get; init; }
|
|
public double WindSpeedMph { get; init; }
|
|
|
|
public string Description => WeatherCode switch
|
|
{
|
|
0 => "Clear sky",
|
|
1 => "Mainly clear",
|
|
2 => "Partly cloudy",
|
|
3 => "Overcast",
|
|
45 or 48 => "Foggy",
|
|
51 or 53 or 55 => "Drizzle",
|
|
61 or 63 or 65 => "Rain",
|
|
66 or 67 => "Freezing rain",
|
|
71 or 73 or 75 => "Snowfall",
|
|
77 => "Snow grains",
|
|
80 or 81 or 82 => "Rain showers",
|
|
85 or 86 => "Snow showers",
|
|
95 => "Thunderstorm",
|
|
96 or 99 => "Thunderstorm with hail",
|
|
_ => "Unknown"
|
|
};
|
|
}
|
|
|
|
public sealed class CurrentWeatherResponse
|
|
{
|
|
public string City { get; init; } = string.Empty;
|
|
public double TemperatureF { get; init; }
|
|
public double HumidityPercent { get; init; }
|
|
public double WindSpeedMph { get; init; }
|
|
public int WeatherCode { get; init; }
|
|
public string Description { get; init; } = string.Empty;
|
|
|
|
public static CurrentWeatherResponse From(
|
|
Backend.DatabaseHandler.UserLocationRecord location, WeatherResult weather) => new()
|
|
{
|
|
City = location.City,
|
|
TemperatureF = weather.TemperatureF,
|
|
HumidityPercent = weather.HumidityPercent,
|
|
WindSpeedMph = weather.WindSpeedMph,
|
|
WeatherCode = weather.WeatherCode,
|
|
Description = weather.Description
|
|
};
|
|
}
|
|
}
|