mirror of
https://github.com/ckaczor/HomeMonitor.git
synced 2026-02-16 10:58:32 -05:00
Implement weather calculations in the service
This commit is contained in:
38
Power/Service/.vscode/launch.json
vendored
38
Power/Service/.vscode/launch.json
vendored
@@ -1,30 +1,30 @@
|
|||||||
{
|
{
|
||||||
// Use IntelliSense to find out which attributes exist for C# debugging
|
// Use IntelliSense to learn about possible attributes.
|
||||||
// Use hover for the description of the existing attributes
|
// Hover to view descriptions of existing attributes.
|
||||||
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": ".NET Core Launch (remote console)",
|
"name": ".NET Core Launch (web)",
|
||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"preLaunchTask": "publish",
|
"preLaunchTask": "build",
|
||||||
"program": "dotnet",
|
"program": "${workspaceFolder}/bin/Debug/netcoreapp3.0/ChrisKaczor.HomeMonitor.Power.Service.dll",
|
||||||
"args": [
|
"args": [],
|
||||||
"/home/ckaczor/Power/Service/Power.Service.dll"
|
"cwd": "${workspaceFolder}",
|
||||||
],
|
|
||||||
"cwd": "/home/ckaczor/Power/Service",
|
|
||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
"console": "internalConsole",
|
"env": {
|
||||||
"pipeTransport": {
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
"pipeCwd": "${workspaceFolder}",
|
|
||||||
"pipeProgram": "C:\\Program Files (x86)\\PuTTY\\PLINK.EXE",
|
|
||||||
"pipeArgs": [
|
|
||||||
"root@172.23.10.6"
|
|
||||||
],
|
|
||||||
"debuggerPath": "/home/ckaczor/vsdbg/vsdbg"
|
|
||||||
},
|
},
|
||||||
"internalConsoleOptions": "openOnSessionStart"
|
"sourceFileMap": {
|
||||||
|
"/Views": "${workspaceFolder}/Views"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": ".NET Core Attach",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "attach",
|
||||||
|
"processId": "${command:pickProcess}"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
57
Power/Service/.vscode/tasks.json
vendored
57
Power/Service/.vscode/tasks.json
vendored
@@ -7,29 +7,54 @@
|
|||||||
"type": "process",
|
"type": "process",
|
||||||
"args": [
|
"args": [
|
||||||
"build",
|
"build",
|
||||||
"${workspaceFolder}/Service.csproj"
|
"${workspaceFolder}/Service.csproj",
|
||||||
|
"/property:GenerateFullPaths=true",
|
||||||
|
"/consoleloggerparameters:NoSummary"
|
||||||
],
|
],
|
||||||
"problemMatcher": "$msCompile",
|
"problemMatcher": "$msCompile"
|
||||||
"group": {
|
|
||||||
"kind": "build",
|
|
||||||
"isDefault": true
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "publish",
|
"label": "publish",
|
||||||
|
"command": "dotnet",
|
||||||
|
"type": "process",
|
||||||
|
"args": [
|
||||||
|
"publish",
|
||||||
|
"${workspaceFolder}/Service.csproj",
|
||||||
|
"/property:GenerateFullPaths=true",
|
||||||
|
"/consoleloggerparameters:NoSummary"
|
||||||
|
],
|
||||||
|
"problemMatcher": "$msCompile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "watch",
|
||||||
|
"command": "dotnet",
|
||||||
|
"type": "process",
|
||||||
|
"args": [
|
||||||
|
"watch",
|
||||||
|
"run",
|
||||||
|
"${workspaceFolder}/Service.csproj",
|
||||||
|
"/property:GenerateFullPaths=true",
|
||||||
|
"/consoleloggerparameters:NoSummary"
|
||||||
|
],
|
||||||
|
"problemMatcher": "$msCompile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "build",
|
||||||
|
"command": "dotnet",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
|
"args": [
|
||||||
|
"build",
|
||||||
|
"/property:GenerateFullPaths=true",
|
||||||
|
"/consoleloggerparameters:NoSummary"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
"presentation": {
|
"presentation": {
|
||||||
"reveal": "always",
|
"reveal": "silent"
|
||||||
"panel": "shared"
|
|
||||||
},
|
},
|
||||||
"options": {
|
"problemMatcher": "$msCompile"
|
||||||
"cwd": "${workspaceFolder}"
|
|
||||||
},
|
|
||||||
"windows": {
|
|
||||||
"command": "${cwd}\\publish.bat"
|
|
||||||
},
|
|
||||||
"problemMatcher": [],
|
|
||||||
"group": "build"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
43
Weather/Service/.vscode/launch.json
vendored
43
Weather/Service/.vscode/launch.json
vendored
@@ -1,30 +1,31 @@
|
|||||||
{
|
{
|
||||||
// Use IntelliSense to find out which attributes exist for C# debugging
|
// Use IntelliSense to find out which attributes exist for C# debugging
|
||||||
// Use hover for the description of the existing attributes
|
// Use hover for the description of the existing attributes
|
||||||
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
|
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": ".NET Core Launch (remote console)",
|
"name": ".NET Core Launch (web)",
|
||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"preLaunchTask": "publish",
|
"preLaunchTask": "build",
|
||||||
"program": "dotnet",
|
// If you have changed target frameworks, make sure to update the program path.
|
||||||
"args": [
|
"program": "${workspaceFolder}/bin/Debug/netcoreapp3.0/ChrisKaczor.HomeMonitor.Weather.Service.dll",
|
||||||
"/home/ckaczor/Weather/Service/Weather.Service.dll"
|
"args": [],
|
||||||
],
|
"cwd": "${workspaceFolder}",
|
||||||
"cwd": "/home/ckaczor/Weather/Service",
|
|
||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
"console": "internalConsole",
|
"env": {
|
||||||
"pipeTransport": {
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
"pipeCwd": "${workspaceFolder}",
|
|
||||||
"pipeProgram": "C:\\Program Files (x86)\\PuTTY\\PLINK.EXE",
|
|
||||||
"pipeArgs": [
|
|
||||||
"root@172.23.10.6"
|
|
||||||
],
|
|
||||||
"debuggerPath": "/home/ckaczor/vsdbg/vsdbg"
|
|
||||||
},
|
},
|
||||||
"internalConsoleOptions": "openOnSessionStart"
|
"sourceFileMap": {
|
||||||
|
"/Views": "${workspaceFolder}/Views"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": ".NET Core Attach",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "attach",
|
||||||
|
"processId": "${command:pickProcess}"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
5
Weather/Service/.vscode/settings.json
vendored
Normal file
5
Weather/Service/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"Kaczor"
|
||||||
|
]
|
||||||
|
}
|
||||||
57
Weather/Service/.vscode/tasks.json
vendored
57
Weather/Service/.vscode/tasks.json
vendored
@@ -7,29 +7,54 @@
|
|||||||
"type": "process",
|
"type": "process",
|
||||||
"args": [
|
"args": [
|
||||||
"build",
|
"build",
|
||||||
"${workspaceFolder}/Service.csproj"
|
"${workspaceFolder}/Service.csproj",
|
||||||
|
"/property:GenerateFullPaths=true",
|
||||||
|
"/consoleloggerparameters:NoSummary"
|
||||||
],
|
],
|
||||||
"problemMatcher": "$msCompile",
|
"problemMatcher": "$msCompile"
|
||||||
"group": {
|
|
||||||
"kind": "build",
|
|
||||||
"isDefault": true
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "publish",
|
"label": "publish",
|
||||||
|
"command": "dotnet",
|
||||||
|
"type": "process",
|
||||||
|
"args": [
|
||||||
|
"publish",
|
||||||
|
"${workspaceFolder}/Service.csproj",
|
||||||
|
"/property:GenerateFullPaths=true",
|
||||||
|
"/consoleloggerparameters:NoSummary"
|
||||||
|
],
|
||||||
|
"problemMatcher": "$msCompile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "watch",
|
||||||
|
"command": "dotnet",
|
||||||
|
"type": "process",
|
||||||
|
"args": [
|
||||||
|
"watch",
|
||||||
|
"run",
|
||||||
|
"${workspaceFolder}/Service.csproj",
|
||||||
|
"/property:GenerateFullPaths=true",
|
||||||
|
"/consoleloggerparameters:NoSummary"
|
||||||
|
],
|
||||||
|
"problemMatcher": "$msCompile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "build",
|
||||||
|
"command": "dotnet",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
|
"args": [
|
||||||
|
"build",
|
||||||
|
"/property:GenerateFullPaths=true",
|
||||||
|
"/consoleloggerparameters:NoSummary"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
"presentation": {
|
"presentation": {
|
||||||
"reveal": "always",
|
"reveal": "silent"
|
||||||
"panel": "shared"
|
|
||||||
},
|
},
|
||||||
"options": {
|
"problemMatcher": "$msCompile"
|
||||||
"cwd": "${workspaceFolder}"
|
|
||||||
},
|
|
||||||
"windows": {
|
|
||||||
"command": "${cwd}\\publish.bat"
|
|
||||||
},
|
|
||||||
"problemMatcher": [],
|
|
||||||
"group": "build"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -2,3 +2,4 @@ SELECT Timestamp,
|
|||||||
@Value AS Value
|
@Value AS Value
|
||||||
FROM Reading
|
FROM Reading
|
||||||
WHERE Timestamp BETWEEN @Start AND @End
|
WHERE Timestamp BETWEEN @Start AND @End
|
||||||
|
ORDER BY Timestamp ASC
|
||||||
|
|||||||
12
Weather/Service/Extensions.cs
Normal file
12
Weather/Service/Extensions.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ChrisKaczor.HomeMonitor.Weather.Service
|
||||||
|
{
|
||||||
|
public static class Extensions
|
||||||
|
{
|
||||||
|
public static bool IsBetween<T>(this T item, T start, T end) where T : IComparable
|
||||||
|
{
|
||||||
|
return item.CompareTo(start) >= 0 && item.CompareTo(end) <= 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using ChrisKaczor.HomeMonitor.Weather.Models;
|
using ChrisKaczor.HomeMonitor.Weather.Models;
|
||||||
using ChrisKaczor.HomeMonitor.Weather.Service.Data;
|
using ChrisKaczor.HomeMonitor.Weather.Service.Data;
|
||||||
|
using ChrisKaczor.HomeMonitor.Weather.Service.Models;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Microsoft.AspNetCore.SignalR.Client;
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
@@ -8,11 +9,9 @@ using Newtonsoft.Json;
|
|||||||
using RabbitMQ.Client;
|
using RabbitMQ.Client;
|
||||||
using RabbitMQ.Client.Events;
|
using RabbitMQ.Client.Events;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using ChrisKaczor.HomeMonitor.Weather.Service.Models;
|
|
||||||
|
|
||||||
namespace ChrisKaczor.HomeMonitor.Weather.Service
|
namespace ChrisKaczor.HomeMonitor.Weather.Service
|
||||||
{
|
{
|
||||||
@@ -97,17 +96,19 @@ namespace ChrisKaczor.HomeMonitor.Weather.Service
|
|||||||
|
|
||||||
_database.StoreWeatherData(weatherMessage);
|
_database.StoreWeatherData(weatherMessage);
|
||||||
|
|
||||||
weatherMessage.Rain = _database.GetReadingValueSum(WeatherValueType.Rain, weatherMessage.Timestamp.AddHours(-1), weatherMessage.Timestamp).Result;
|
|
||||||
|
|
||||||
if (_hubConnection == null)
|
if (_hubConnection == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var weatherUpdate = new WeatherUpdate(weatherMessage, _database);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (_hubConnection.State == HubConnectionState.Disconnected)
|
if (_hubConnection.State == HubConnectionState.Disconnected)
|
||||||
_hubConnection.StartAsync().Wait();
|
_hubConnection.StartAsync().Wait();
|
||||||
|
|
||||||
_hubConnection.InvokeAsync("SendLatestReading", JsonConvert.SerializeObject(weatherMessage)).Wait();
|
var json = JsonConvert.SerializeObject(weatherUpdate);
|
||||||
|
|
||||||
|
_hubConnection.InvokeAsync("SendLatestReading", json).Wait();
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
|
|||||||
114
Weather/Service/Models/WeatherUpdate.cs
Normal file
114
Weather/Service/Models/WeatherUpdate.cs
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using ChrisKaczor.HomeMonitor.Weather.Models;
|
||||||
|
using ChrisKaczor.HomeMonitor.Weather.Service.Data;
|
||||||
|
using DecimalMath;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using MathNet.Numerics;
|
||||||
|
|
||||||
|
namespace ChrisKaczor.HomeMonitor.Weather.Service.Models
|
||||||
|
{
|
||||||
|
[PublicAPI]
|
||||||
|
public class WeatherUpdate : WeatherMessage
|
||||||
|
{
|
||||||
|
private Database _database;
|
||||||
|
|
||||||
|
public decimal? WindChill { get; set; }
|
||||||
|
|
||||||
|
public decimal? HeatIndex { get; set; }
|
||||||
|
|
||||||
|
public decimal DewPoint { get; set; }
|
||||||
|
|
||||||
|
public decimal PressureTrend { get; set; }
|
||||||
|
|
||||||
|
public WeatherUpdate(WeatherMessage weatherMessage, Database database)
|
||||||
|
{
|
||||||
|
_database = database;
|
||||||
|
|
||||||
|
Type = weatherMessage.Type;
|
||||||
|
Message = weatherMessage.Message;
|
||||||
|
Timestamp = weatherMessage.Timestamp;
|
||||||
|
WindDirection = weatherMessage.WindDirection;
|
||||||
|
WindSpeed = weatherMessage.WindSpeed;
|
||||||
|
Humidity = weatherMessage.Humidity;
|
||||||
|
HumidityTemperature = weatherMessage.HumidityTemperature;
|
||||||
|
Rain = weatherMessage.Rain;
|
||||||
|
Pressure = weatherMessage.Pressure;
|
||||||
|
PressureTemperature = weatherMessage.PressureTemperature;
|
||||||
|
BatteryLevel = weatherMessage.BatteryLevel;
|
||||||
|
LightLevel = weatherMessage.LightLevel;
|
||||||
|
Latitude = weatherMessage.Latitude;
|
||||||
|
Longitude = weatherMessage.Longitude;
|
||||||
|
Altitude = weatherMessage.Altitude;
|
||||||
|
SatelliteCount = weatherMessage.SatelliteCount;
|
||||||
|
GpsTimestamp = weatherMessage.GpsTimestamp;
|
||||||
|
|
||||||
|
HeatIndex = CalculateHeatIndex();
|
||||||
|
WindChill = CalculateWindChill();
|
||||||
|
DewPoint = CalculateDewPoint();
|
||||||
|
PressureTrend = CalculatePressureTrend();
|
||||||
|
|
||||||
|
Rain = database.GetReadingValueSum(WeatherValueType.Rain, Timestamp.AddHours(-1), Timestamp).Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private decimal CalculatePressureTrend()
|
||||||
|
{
|
||||||
|
var pressureData = _database.GetReadingValueHistory(WeatherValueType.Pressure, Timestamp.AddHours(-3), Timestamp).Result;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
var difference = (decimal) (lineFunction(yData.Length - 1) - lineFunction(0));
|
||||||
|
|
||||||
|
return difference;
|
||||||
|
}
|
||||||
|
|
||||||
|
private decimal? CalculateHeatIndex()
|
||||||
|
{
|
||||||
|
var temperature = PressureTemperature;
|
||||||
|
var humidity = Humidity;
|
||||||
|
|
||||||
|
if (temperature.IsBetween(80, 100) && humidity.IsBetween(40, 100))
|
||||||
|
{
|
||||||
|
var 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;
|
||||||
|
|
||||||
|
return heatIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private decimal? CalculateWindChill()
|
||||||
|
{
|
||||||
|
var temperatureInF = PressureTemperature;
|
||||||
|
var windSpeedInMph = WindSpeed;
|
||||||
|
|
||||||
|
if (temperatureInF.IsBetween(-45, 45) && windSpeedInMph.IsBetween(3, 60))
|
||||||
|
{
|
||||||
|
var windChill = 35.74m + 0.6215m * temperatureInF - 35.75m * DecimalEx.Pow(windSpeedInMph, 0.16m) + 0.4275m * temperatureInF * DecimalEx.Pow(windSpeedInMph, 0.16m);
|
||||||
|
|
||||||
|
return windChill;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private decimal CalculateDewPoint()
|
||||||
|
{
|
||||||
|
var relativeHumidity = Humidity;
|
||||||
|
var temperatureInF = PressureTemperature;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
return dewPointInC * 9.0m / 5.0m + 32.0m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,6 +34,8 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ChrisKaczor.HomeMonitor.Weather.Models" Version="1.0.1" />
|
<PackageReference Include="ChrisKaczor.HomeMonitor.Weather.Models" Version="1.0.1" />
|
||||||
<PackageReference Include="Dapper" Version="2.0.30" />
|
<PackageReference Include="Dapper" Version="2.0.30" />
|
||||||
|
<PackageReference Include="DecimalMath.DecimalEx" Version="1.0.2" />
|
||||||
|
<PackageReference Include="MathNet.Numerics" Version="4.11.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="3.0.0" />
|
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="3.0.0" />
|
||||||
<PackageReference Include="RabbitMQ.Client" Version="5.1.2" />
|
<PackageReference Include="RabbitMQ.Client" Version="5.1.2" />
|
||||||
<PackageReference Include="System.Data.SqlClient" Version="4.7.0" />
|
<PackageReference Include="System.Data.SqlClient" Version="4.7.0" />
|
||||||
|
|||||||
Reference in New Issue
Block a user