Skip to content

Commit

Permalink
add weather importer
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonohas committed Jul 20, 2024
1 parent 947024c commit bfa809f
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 6 deletions.
88 changes: 88 additions & 0 deletions DKSRDomain/WeatherResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using Newtonsoft.Json;

namespace DKSRDomain;

public class WeatherResponse
{
public List<WeatherSensorData> SensorData { get; set; }

Check warning on line 7 in DKSRDomain/WeatherResponse.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'SensorData' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
}

// {
// "rain": 0,
// "weather_id": 800,
// "temp": 299.37,
// "sunrise": "2024-07-19T03:24:11.000Z",
// "visibility": 10000,
// "city": "Weißdorf",
// "countrycode": "DE",
// "lon": 11.85,
// "clouds": 0,
// "pressure": 1018,
// "weather_icon": "01d",
// "feels_like": 299.37,
// "temp_max": 299.37,
// "SID": "fbc81ae8-87a2-49e7-948e-aeef30e66f71",
// "wind_deg": 190,
// "temp_min": 299.26,
// "grnd_level": 949,
// "sunset": "2024-07-19T19:13:15.000Z",
// "humidity": 53,
// "wind_speed": 2.06,
// "sea_level": 1018,
// "lat": 50.1833,
// "timestamp": "2024-07-19T15:43:50.730Z",
// "_headers": {
// "eventType": "OpenWeatherMapHofV1EventType"
// }
// }

public class WeatherSensorData
{
[JsonProperty("rain")] public int Rain { get; set; }

[JsonProperty("weather_id")] public int WeatherId { get; set; }

[JsonProperty("temp")] public double Temp { get; set; }

[JsonProperty("sunrise")] public DateTime Sunrise { get; set; }

[JsonProperty("visibility")] public int Visibility { get; set; }

[JsonProperty("city")] public string City { get; set; }

Check warning on line 51 in DKSRDomain/WeatherResponse.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'City' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

[JsonProperty("countrycode")] public string CountryCode { get; set; }

Check warning on line 53 in DKSRDomain/WeatherResponse.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'CountryCode' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

[JsonProperty("lon")] public double Lon { get; set; }

[JsonProperty("clouds")] public int Clouds { get; set; }

[JsonProperty("pressure")] public int Pressure { get; set; }

[JsonProperty("weather_icon")] public string WeatherIcon { get; set; }

Check warning on line 61 in DKSRDomain/WeatherResponse.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'WeatherIcon' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

[JsonProperty("feels_like")] public double FeelsLike { get; set; }

[JsonProperty("temp_max")] public double TempMax { get; set; }

[JsonProperty("SID")] public string SID { get; set; }

Check warning on line 67 in DKSRDomain/WeatherResponse.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'SID' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

[JsonProperty("wind_deg")] public int WindDeg { get; set; }

[JsonProperty("temp_min")] public double TempMin { get; set; }

[JsonProperty("grnd_level")] public int GrndLevel { get; set; }

[JsonProperty("sunset")] public DateTime Sunset { get; set; }

[JsonProperty("humidity")] public int Humidity { get; set; }

[JsonProperty("wind_speed")] public double WindSpeed { get; set; }

[JsonProperty("sea_level")] public int SeaLevel { get; set; }

[JsonProperty("lat")] public double Lat { get; set; }

[JsonProperty("timestamp")] public DateTime Timestamp { get; set; }

[JsonProperty("_headers")] public Dictionary<string, string> Headers { get; set; }

Check warning on line 87 in DKSRDomain/WeatherResponse.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'Headers' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
}
19 changes: 19 additions & 0 deletions Importer/Constants/Endpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@ public static class Endpoints
{
private const string Prefix = "https://";
private const string Url = "mainz-staging.dksr.city";

private const string DKSRUrl = "oup.hoferland-digital.de";

public const string TreesenseEndpoint =
"/UrbanPulseData/historic/sensordata?eventtype=fac3edb2-53fa-4319-a897-e3e3c02102cc";

public const string ParkingSpaceEndpoint =
"/UrbanPulseData/historic/sensordata?eventtype=2a4ce3e9-92db-455e-bece-0176c62fafba";

public const string WeatherEndpoint =
"/UrbanPulseData/historic/sensordata?SID=fbc81ae8-87a2-49e7-948e-aeef30e66f71";

public static string GetAuthenticatedEndpointUrl(string? username, string? password, string socket)
{
Expand All @@ -19,9 +24,23 @@ public static string GetAuthenticatedEndpointUrl(string? username, string? passw

return $"{Prefix}{username}:{password}@{Url}{socket}";
}

public static string GetAuthenticatedDKSREndpointUrl(string? username, string? password, string socket)
{
// if username or password is null, return the unauthenticated endpoint
if (username == null || password == null)
throw new ArgumentException("username or password undefined");

return $"{Prefix}{username}:{password}@{DKSRUrl}{socket}";
}

public static string GetEndpointUrl(string socket)
{
return $"{Prefix}{Url}{socket}";
}

public static string GetDKSREndpointUrl(string socket)
{
return $"{Prefix}{DKSRUrl}{socket}";
}
}
1 change: 1 addition & 0 deletions Importer/Importer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<UserSecretsId>e176392a-7a30-4b16-b02d-30acfefd587a</UserSecretsId>
</PropertyGroup>

<ItemGroup>
Expand Down
19 changes: 15 additions & 4 deletions Importer/Importers/Importer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,21 @@ public abstract class Importer

protected Importer(ILogger logger, string dataType, string dataStreamName)
{
_frostApi = new FrostApi.FrostApi(Environment.GetEnvironmentVariable("FROST_SERVER_BASE_URL") ??
throw new Exception("FROST_SERVER_BASE_URL not set"));
Username = Environment.GetEnvironmentVariable("DKSR_HISTORIC_USERNAME") ?? throw new Exception("DKSR_HISTORIC_USERNAME not set");
Password = Environment.GetEnvironmentVariable("DKSR_HISTORIC_PASSWORD") ?? throw new Exception("DKSR_HISTORIC_PASSWORD not set");
// _frostApi = new FrostApi.FrostApi(Environment.GetEnvironmentVariable("FROST_SERVER_BASE_URL") ??

This comment has been minimized.

Copy link
@Joren-vanGoethem

Joren-vanGoethem Jul 25, 2024

Member

mag weg zeker?

This comment has been minimized.

Copy link
@Jonohas

Jonohas Jul 25, 2024

Author Collaborator

nee want dat is dat van het andere script. Als de updates online komen moet dit ook wel blijven werken

// throw new Exception("FROST_SERVER_BASE_URL not set"));
//
// Username = Environment.GetEnvironmentVariable("DKSR_HISTORIC_USERNAME") ?? throw new Exception("DKSR_HISTORIC_USERNAME not set");
// Password = Environment.GetEnvironmentVariable("DKSR_HISTORIC_PASSWORD") ?? throw new Exception("DKSR_HISTORIC_PASSWORD not set");
// Client = SetupHttpClient();
// Logger = logger;
// DataType = dataType;
// _dataStreamName = dataStreamName;

_frostApi = new FrostApi.FrostApi(Environment.GetEnvironmentVariable("FROST_SERVER_BASE_URL_WEATHER") ??
throw new Exception("FROST_SERVER_BASE_URL_WEATHER not set"));

Username = Environment.GetEnvironmentVariable("DKSR_HISTORIC_USERNAME_WEATHER") ?? throw new Exception("DKSR_HISTORIC_USERNAME_WEATHER not set");
Password = Environment.GetEnvironmentVariable("DKSR_HISTORIC_PASSWORD_WEATHER") ?? throw new Exception("DKSR_HISTORIC_PASSWORD_WEATHER not set");
Client = SetupHttpClient();
Logger = logger;
DataType = dataType;
Expand Down
70 changes: 70 additions & 0 deletions Importer/Importers/WeatherImporter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using DKSRDomain;
using FrostApi.Models.Thing;
using Importer.Constants;
using Microsoft.Extensions.Logging;

namespace Importer.Importers;

public class WeatherImporter : Importer
{
private Timer _importerTimer;

public WeatherImporter(ILogger logger) : base(logger, "Weather", "weather")
{
_importerTimer = new Timer(Import, null, 0, 60 * 1000 * 60); // every hour
}

protected override async void Import(object? _)
{
try
{
Logger.LogInformation($"{DateTime.Now} - Updating {DataType} Data...");
var data = await GetDksrData();
foreach (var weather in data.SensorData)
try
{
Thing thing;
var frostThing = await GetFrostThingData(weather.SID);
if (frostThing.Value.Count == 0)
{
thing = Mappers.MapDksrResponse(weather, DataType);
await CreateNewThing(thing);
frostThing = await GetFrostThingData(weather.SID);
}

if (frostThing.Value.Count < 1)
throw new Exception($"Creating new thing with id {weather.SID} seems to have failed...");

thing = Mappers.MapDksrResponse(weather, DataType);
thing.Id = frostThing.Value.First().Id;
await Update(thing);
}
catch (Exception e)
{
Logger.LogError($"{DateTime.Now} - {e}");
}
}
catch (Exception e)
{
Logger.LogError($"{DateTime.Now} - {e}");
}
}


private async Task<WeatherResponse> GetDksrData()
{
try
{
var response =
await Client.GetAsync(
Endpoints.GetAuthenticatedDKSREndpointUrl(Username, Password, Endpoints.WeatherEndpoint));
var result = await response.Content.ReadAsAsync<WeatherResponse>();
return result;
}
catch (Exception e)
{
Logger.LogError("Getting data from DKSR failed, returning empty response");
throw new Exception($"{DateTime.Now} - {e}");
}
}
}
20 changes: 20 additions & 0 deletions Importer/Mappers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,26 @@ public static Thing MapDksrResponse(ParkingSpaceSensorData parkingSpace, string

return Thing.Create($"{dataType}-{parkingSpace.Sid}", dataType, properties, parkingSpace.Lat, parkingSpace.Lon, observation);
}

public static Thing MapDksrResponse(WeatherSensorData weather, string dataType)
{
var properties = new Dictionary<string, string>
{
{ "Id", weather.SID },
{ "Temperature", weather.Temp.ToString() },
{ "Max temperature", weather.TempMax.ToString() },
{ "Min temperature", weather.TempMin.ToString() },
{ "Pressure", weather.Pressure.ToString() },
{ "Humidity", weather.Humidity.ToString() },
{ "Wind speed", weather.WindSpeed.ToString() },
{ "Wind direction", weather.WindDeg.ToString() },
{ "Cloudiness", weather.Clouds.ToString() }
};

var observation = new Observation { Result = weather.Temp, PhenomenonTime = weather.Timestamp };

return Thing.Create($"{dataType}-{weather.SID}", dataType, properties, weather.Lat, weather.Lon, observation);
}

public static DataStream MapFrostResponseToDataStream(DataStreamResponse? response)
{
Expand Down
5 changes: 3 additions & 2 deletions Importer/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ private static void Main(string[] args)
IServiceProvider serviceProvider = services.BuildServiceProvider();
_logger = serviceProvider.GetRequiredService<ILogger<Program>>();

var treeImporter = new TreeImporter(_logger);
var parkingSpaceImporter = new ParkingSpaceImporter(_logger);
// var treeImporter = new TreeImporter(_logger);
// var parkingSpaceImporter = new ParkingSpaceImporter(_logger);
var weatherImporter = new WeatherImporter(_logger);

Process.GetCurrentProcess().WaitForExit();
}
Expand Down

0 comments on commit bfa809f

Please sign in to comment.