Refactor and complete providers

This commit is contained in:
2025-01-04 17:51:55 -05:00
parent 9094cb3d3e
commit 398cfdb77c
12 changed files with 401 additions and 109 deletions

54
pkg/weather/enrich.go Normal file
View File

@ -0,0 +1,54 @@
package weather
import "math"
// Attempts to complete missing fields that may not
// be set by a specific provider, such as DewPoint and WindChill
//
// If enrich is called repeated with the same station ID, measurements
// will be recorded to produce averages. This will be more stable
// and support scaling if Redis is available
// TODO: Implement average tracker
func (u *WeatherUpdate) Enrich() {
if u.WindChillF == 0 {
u.WindChillF = CalculateWindChill(u.TempF, u.WindSpeedMPH)
}
if u.DewPointF == 0 {
u.DewPointF = CalculateDewPoint(u.TempF, float32(u.Humidity))
}
if u.BaromAbsoluteIn == 0 {
u.BaromAbsoluteIn = u.BaromRelativeIn
}
}
func CalculateDewPoint(tempF, humidity float32) float32 {
// Convert temperature from Fahrenheit to Celsius
tempC := (tempF - 32) * 5 / 9
// Calculate the dew point using the Magnus-Tetens approximation
a := float32(17.27)
b := float32(237.7)
alpha := (a*tempC)/(b+tempC) + float32(math.Log(float64(humidity)/100))
dewPointC := (b * alpha) / (a - alpha)
// Convert dew point back to Fahrenheit
dewPointF := (dewPointC * 9 / 5) + 32
return dewPointF
}
func CalculateWindChill(tempF float32, windSpeedMPH float32) float32 {
if windSpeedMPH <= 3 {
// Wind chill calculation doesn't apply for very low wind speeds
return tempF
}
// Formula for calculating wind chill
return float32(
35.74 + 0.6215*float64(tempF) -
35.75*math.Pow(float64(windSpeedMPH), 0.16) +
0.4275*float64(tempF)*
math.Pow(float64(windSpeedMPH), 0.16))
}

3
pkg/weather/metrics.go Normal file
View File

@ -0,0 +1,3 @@
package weather
// TODO: Add OTEL Metrics

39
pkg/weather/types.go Normal file
View File

@ -0,0 +1,39 @@
package weather
import (
"time"
)
// Stable intermediate struct containing superset of fields
// between AWN and Wunderground style updates from Ambient devices
type WeatherUpdate struct {
DateUTC *time.Time
StationType string
TempF float32
TempInsideF float32
Humidity int
HumidityInside int
WindSpeedMPH float32
WindGustMPH float32
MaxDailyGust float32
WindDir int
WindDirAVG10m int
UV int
SolarRadiation float32
HourlyRainIn float32
EventRainIn float32
DailyRainIn float32
WeeklyRainIn float32
MonthlyRainIn float32
YearlyRainIn float32
TotalRainIn float32
BattOutdoorSensor int
BattIndoorSensor int
BattRainSensor int
BaromRelativeIn float32
BaromAbsoluteIn float32
// These fields may be calculated
// if not otherwise set
DewPointF float32
WindChillF float32
}