Update Weather to .NET 8 and add telemetry

This commit is contained in:
2024-01-25 16:25:59 -05:00
parent 2394f613d2
commit 5d0bc2c31c
28 changed files with 856 additions and 775 deletions

View File

@@ -1,25 +1,17 @@
using ChrisKaczor.HomeMonitor.Weather.Models;
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.Linq;
using ChrisKaczor.HomeMonitor.Weather.Models;
using JetBrains.Annotations;
namespace ChrisKaczor.HomeMonitor.Weather.Service.Models
namespace ChrisKaczor.HomeMonitor.Weather.Service.Models;
[PublicAPI]
public class ReadingAggregate(IEnumerable<WeatherReading> readings, Func<WeatherReading, decimal> selector, int decimalPlaces)
{
[PublicAPI]
public class ReadingAggregate
{
public decimal Min { get; set; }
public decimal Min { get; set; } = readings.Min(selector);
public decimal Max { get; set; }
public decimal Max { get; set; } = readings.Max(selector);
public decimal Average { get; set; }
public ReadingAggregate(IEnumerable<WeatherReading> readings, Func<WeatherReading, decimal> selector, int decimalPlaces)
{
Min = readings.Min(selector);
Max = readings.Max(selector);
Average = readings.Average(selector).Truncate(decimalPlaces);
}
}
public decimal Average { get; set; } = readings.Average(selector).Truncate(decimalPlaces);
}

View File

@@ -1,49 +1,48 @@
using ChrisKaczor.HomeMonitor.Weather.Models;
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.Linq;
using ChrisKaczor.HomeMonitor.Weather.Models;
using JetBrains.Annotations;
namespace ChrisKaczor.HomeMonitor.Weather.Service.Models
namespace ChrisKaczor.HomeMonitor.Weather.Service.Models;
[PublicAPI]
public class WeatherAggregate
{
[PublicAPI]
public class WeatherAggregate
public ReadingAggregate Humidity { get; set; }
public ReadingAggregate Temperature { get; set; }
public ReadingAggregate Pressure { get; set; }
public ReadingAggregate Light { get; set; }
public ReadingAggregate WindSpeed { get; set; }
public WindDirection WindDirectionAverage { get; set; }
public decimal RainTotal { get; set; }
private static readonly List<int> WindDirectionValues = ((WindDirection[])Enum.GetValues(typeof(WindDirection))).Select(e => (int)e).ToList();
public WeatherAggregate(List<WeatherReading> readings)
{
public ReadingAggregate Humidity { get; set; }
if (!readings.Any())
return;
public ReadingAggregate Temperature { get; set; }
Humidity = new ReadingAggregate(readings, r => r.Humidity, 1);
public ReadingAggregate Pressure { get; set; }
Temperature = new ReadingAggregate(readings, r => r.HumidityTemperature, 1);
public ReadingAggregate Light { get; set; }
Pressure = new ReadingAggregate(readings, r => r.Pressure, 2);
public ReadingAggregate WindSpeed { get; set; }
Light = new ReadingAggregate(readings, r => r.LightLevel, 2);
public WindDirection WindDirectionAverage { get; set; }
WindSpeed = new ReadingAggregate(readings, r => r.WindSpeed, 1);
public decimal RainTotal { get; set; }
var windDirectionAverage = readings.Average(r => (decimal)r.WindDirection);
WindDirectionAverage = (WindDirection)WindDirectionValues.Aggregate((x, y) => Math.Abs(x - windDirectionAverage) < Math.Abs(y - windDirectionAverage) ? x : y);
private static readonly List<int> WindDirectionValues = ((WindDirection[])Enum.GetValues(typeof(WindDirection))).Select(e => (int)e).ToList();
public WeatherAggregate(List<WeatherReading> readings)
{
if (!readings.Any())
return;
Humidity = new ReadingAggregate(readings, r => r.Humidity, 1);
Temperature = new ReadingAggregate(readings, r => r.HumidityTemperature, 1);
Pressure = new ReadingAggregate(readings, r => r.Pressure, 2);
Light = new ReadingAggregate(readings, r => r.LightLevel, 2);
WindSpeed = new ReadingAggregate(readings, r => r.WindSpeed, 1);
var windDirectionAverage = readings.Average(r => (decimal)r.WindDirection);
WindDirectionAverage = (WindDirection)WindDirectionValues.Aggregate((x, y) => Math.Abs(x - windDirectionAverage) < Math.Abs(y - windDirectionAverage) ? x : y);
RainTotal = readings.Sum(r => r.Rain);
}
RainTotal = readings.Sum(r => r.Rain);
}
}

View File

@@ -1,21 +1,20 @@
using JetBrains.Annotations;
using System;
namespace ChrisKaczor.HomeMonitor.Weather.Service.Models
namespace ChrisKaczor.HomeMonitor.Weather.Service.Models;
[PublicAPI]
public class WeatherReadingGrouped
{
[PublicAPI]
public class WeatherReadingGrouped
{
public DateTimeOffset Bucket { get; set; }
public DateTimeOffset Bucket { get; set; }
public decimal AverageHumidity { get; set; }
public decimal AverageHumidity { get; set; }
public decimal AverageTemperature { get; set; }
public decimal AverageTemperature { get; set; }
public decimal AveragePressure { get; set; }
public decimal AveragePressure { get; set; }
public decimal AverageLightLevel { get; set; }
public decimal AverageLightLevel { get; set; }
public decimal RainTotal { get; set; }
}
public decimal RainTotal { get; set; }
}

View File

@@ -5,97 +5,96 @@ using JetBrains.Annotations;
using MathNet.Numerics;
using System.Linq;
namespace ChrisKaczor.HomeMonitor.Weather.Service.Models
namespace ChrisKaczor.HomeMonitor.Weather.Service.Models;
[PublicAPI]
public class WeatherUpdate : WeatherUpdateBase
{
[PublicAPI]
public class WeatherUpdate : WeatherUpdateBase
private readonly Database _database;
public WeatherUpdate(WeatherMessage weatherMessage, Database database)
{
private readonly Database _database;
_database = database;
public WeatherUpdate(WeatherMessage weatherMessage, Database database)
Type = weatherMessage.Type;
Message = weatherMessage.Message;
Timestamp = weatherMessage.Timestamp;
WindDirection = weatherMessage.WindDirection;
WindSpeed = weatherMessage.WindSpeed;
Humidity = weatherMessage.Humidity;
Rain = weatherMessage.Rain;
Pressure = weatherMessage.Pressure;
Temperature = weatherMessage.HumidityTemperature;
LightLevel = weatherMessage.LightLevel;
Latitude = weatherMessage.Latitude;
Longitude = weatherMessage.Longitude;
Altitude = weatherMessage.Altitude;
SatelliteCount = weatherMessage.SatelliteCount;
GpsTimestamp = weatherMessage.GpsTimestamp;
CalculateHeatIndex();
CalculateWindChill();
CalculateDewPoint();
CalculatePressureTrend();
CalculateRainLastHour();
}
private void CalculateRainLastHour()
{
RainLastHour = _database.GetReadingValueSum(WeatherValueType.Rain, Timestamp.AddHours(-1), Timestamp).Result;
}
private void CalculateWindChill()
{
var temperatureInF = Temperature;
var windSpeedInMph = WindSpeed;
if (temperatureInF.IsBetween(-45, 45) && windSpeedInMph.IsBetween(3, 60))
{
_database = database;
Type = weatherMessage.Type;
Message = weatherMessage.Message;
Timestamp = weatherMessage.Timestamp;
WindDirection = weatherMessage.WindDirection;
WindSpeed = weatherMessage.WindSpeed;
Humidity = weatherMessage.Humidity;
Rain = weatherMessage.Rain;
Pressure = weatherMessage.Pressure;
Temperature = weatherMessage.HumidityTemperature;
LightLevel = weatherMessage.LightLevel;
Latitude = weatherMessage.Latitude;
Longitude = weatherMessage.Longitude;
Altitude = weatherMessage.Altitude;
SatelliteCount = weatherMessage.SatelliteCount;
GpsTimestamp = weatherMessage.GpsTimestamp;
CalculateHeatIndex();
CalculateWindChill();
CalculateDewPoint();
CalculatePressureTrend();
CalculateRainLastHour();
}
private void CalculateRainLastHour()
{
RainLastHour = _database.GetReadingValueSum(WeatherValueType.Rain, Timestamp.AddHours(-1), Timestamp).Result;
}
private void CalculateWindChill()
{
var temperatureInF = Temperature;
var windSpeedInMph = WindSpeed;
if (temperatureInF.IsBetween(-45, 45) && windSpeedInMph.IsBetween(3, 60))
{
WindChill = 35.74m + 0.6215m * temperatureInF - 35.75m * DecimalEx.Pow(windSpeedInMph, 0.16m) + 0.4275m * temperatureInF * DecimalEx.Pow(windSpeedInMph, 0.16m);
}
}
private void CalculateDewPoint()
{
var relativeHumidity = Humidity;
var temperatureInF = Temperature;
var temperatureInC = (temperatureInF - 32.0m) * 5.0m / 9.0m;
var vaporPressure = relativeHumidity * 0.01m * 6.112m * DecimalEx.Exp(17.62m * temperatureInC / (temperatureInC + 243.12m));
var numerator = 243.12m * DecimalEx.Log(vaporPressure) - 440.1m;
var denominator = 19.43m - DecimalEx.Log(vaporPressure);
var dewPointInC = numerator / denominator;
DewPoint = dewPointInC * 9.0m / 5.0m + 32.0m;
}
private void CalculatePressureTrend()
{
var pressureData = _database
.GetReadingValueHistory(WeatherValueType.Pressure, Timestamp.AddHours(-3), Timestamp).Result.ToList();
var xData = pressureData.Select(p => (double)p.Timestamp.ToUnixTimeSeconds()).ToArray();
var yData = pressureData.Select(p => (double)p.Value / 100.0).ToArray();
var lineFunction = Fit.LineFunc(xData, yData);
PressureDifferenceThreeHour = (decimal)(lineFunction(xData.Last()) - lineFunction(xData[0]));
}
private void CalculateHeatIndex()
{
var temperature = Temperature;
var humidity = Humidity;
if (temperature.IsBetween(80, 100) && humidity.IsBetween(40, 100))
{
HeatIndex = -42.379m + 2.04901523m * temperature + 10.14333127m * humidity -
.22475541m * temperature * humidity - .00683783m * temperature * temperature -
.05481717m * humidity * humidity + .00122874m * temperature * temperature * humidity +
.00085282m * temperature * humidity * humidity -
.00000199m * temperature * temperature * humidity * humidity;
}
WindChill = 35.74m + 0.6215m * temperatureInF - 35.75m * DecimalEx.Pow(windSpeedInMph, 0.16m) + 0.4275m * temperatureInF * DecimalEx.Pow(windSpeedInMph, 0.16m);
}
}
}
private void CalculateDewPoint()
{
var relativeHumidity = Humidity;
var temperatureInF = Temperature;
var temperatureInC = (temperatureInF - 32.0m) * 5.0m / 9.0m;
var vaporPressure = relativeHumidity * 0.01m * 6.112m * DecimalEx.Exp(17.62m * temperatureInC / (temperatureInC + 243.12m));
var numerator = 243.12m * DecimalEx.Log(vaporPressure) - 440.1m;
var denominator = 19.43m - DecimalEx.Log(vaporPressure);
var dewPointInC = numerator / denominator;
DewPoint = dewPointInC * 9.0m / 5.0m + 32.0m;
}
private void CalculatePressureTrend()
{
var pressureData = _database
.GetReadingValueHistory(WeatherValueType.Pressure, Timestamp.AddHours(-3), Timestamp).Result.ToList();
var xData = pressureData.Select(p => (double)p.Timestamp.ToUnixTimeSeconds()).ToArray();
var yData = pressureData.Select(p => (double)p.Value / 100.0).ToArray();
var lineFunction = Fit.LineFunc(xData, yData);
PressureDifferenceThreeHour = (decimal)(lineFunction(xData.Last()) - lineFunction(xData[0]));
}
private void CalculateHeatIndex()
{
var temperature = Temperature;
var humidity = Humidity;
if (temperature.IsBetween(80, 100) && humidity.IsBetween(40, 100))
{
HeatIndex = -42.379m + 2.04901523m * temperature + 10.14333127m * humidity -
.22475541m * temperature * humidity - .00683783m * temperature * temperature -
.05481717m * humidity * humidity + .00122874m * temperature * temperature * humidity +
.00085282m * temperature * humidity * humidity -
.00000199m * temperature * temperature * humidity * humidity;
}
}
}

View File

@@ -1,13 +1,12 @@
using JetBrains.Annotations;
using System;
namespace ChrisKaczor.HomeMonitor.Weather.Service.Models
{
[PublicAPI]
public class WeatherValue
{
public DateTimeOffset Timestamp { get; set; }
namespace ChrisKaczor.HomeMonitor.Weather.Service.Models;
public decimal Value { get; set; }
}
}
[PublicAPI]
public class WeatherValue
{
public DateTimeOffset Timestamp { get; set; }
public decimal Value { get; set; }
}

View File

@@ -1,13 +1,12 @@
using JetBrains.Annotations;
using System;
namespace ChrisKaczor.HomeMonitor.Weather.Service.Models
{
[PublicAPI]
public class WeatherValueGrouped
{
public DateTimeOffset Bucket { get; set; }
namespace ChrisKaczor.HomeMonitor.Weather.Service.Models;
public decimal AverageValue { get; set; }
}
[PublicAPI]
public class WeatherValueGrouped
{
public DateTimeOffset Bucket { get; set; }
public decimal AverageValue { get; set; }
}

View File

@@ -1,18 +1,17 @@
using JetBrains.Annotations;
namespace ChrisKaczor.HomeMonitor.Weather.Service.Models
namespace ChrisKaczor.HomeMonitor.Weather.Service.Models;
[PublicAPI]
public enum WeatherValueType
{
[PublicAPI]
public enum WeatherValueType
{
WindSpeed,
Humidity,
HumidityTemperature,
Rain,
Pressure,
PressureTemperature,
LightLevel,
Altitude,
SatelliteCount
}
}
WindSpeed,
Humidity,
HumidityTemperature,
Rain,
Pressure,
PressureTemperature,
LightLevel,
Altitude,
SatelliteCount
}

View File

@@ -1,19 +1,18 @@
using JetBrains.Annotations;
using System;
namespace ChrisKaczor.HomeMonitor.Weather.Service.Models
namespace ChrisKaczor.HomeMonitor.Weather.Service.Models;
[PublicAPI]
public class WindHistoryGrouped
{
[PublicAPI]
public class WindHistoryGrouped
{
public DateTimeOffset Bucket { get; set; }
public DateTimeOffset Bucket { get; set; }
public decimal MinimumSpeed { get; set; }
public decimal MinimumSpeed { get; set; }
public decimal AverageSpeed { get; set; }
public decimal AverageSpeed { get; set; }
public decimal MaximumSpeed { get; set; }
public decimal MaximumSpeed { get; set; }
public decimal AverageDirection { get; set; }
}
public decimal AverageDirection { get; set; }
}