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

View File

@ -0,0 +1,79 @@
package awn
import (
"context"
"net/http"
"net/url"
"time"
"github.com/gorilla/schema"
"gitea.libretechconsulting.com/rmcguire/ambient-weather-local-exporter/pkg/weather"
)
type AWNProvider struct{}
const providerName = "awn"
func (awn *AWNProvider) Name() string {
return providerName
}
// Takes an inbound request from the ambient device and maps
// to a stable struct for weather updates
func (awn *AWNProvider) ReqToWeather(_ context.Context, r *http.Request) (
*weather.WeatherUpdate, error,
) {
awnUpdate, err := UnmarshalQueryParams(r.URL.Query())
if err != nil {
return nil, err
}
return MapAwnUpdate(awnUpdate), nil
}
func MapAwnUpdate(awnUpdate *AmbientWeatherUpdate) *weather.WeatherUpdate {
updateTime, err := time.Parse(time.DateTime, awnUpdate.DateUTC)
if err != nil {
updateTime = time.Now()
}
return &weather.WeatherUpdate{
StationType: awnUpdate.StationType,
DateUTC: &updateTime,
TempF: awnUpdate.TempF,
Humidity: awnUpdate.Humidity,
WindSpeedMPH: awnUpdate.WindGustMPH,
WindGustMPH: awnUpdate.WindGustMPH,
MaxDailyGust: awnUpdate.MaxDailyGust,
WindDir: awnUpdate.WindDir,
WindDirAVG10m: awnUpdate.WindDirAVG10m,
UV: awnUpdate.UV,
SolarRadiation: awnUpdate.SolarRadiation,
HourlyRainIn: awnUpdate.HourlyRainIn,
EventRainIn: awnUpdate.EventRainIn,
DailyRainIn: awnUpdate.DailyRainIn,
WeeklyRainIn: awnUpdate.WeeklyRainIn,
MonthlyRainIn: awnUpdate.MonthlyRainIn,
YearlyRainIn: awnUpdate.YearlyRainIn,
TotalRainIn: awnUpdate.TotalRainIn,
BattOutdoorSensor: awnUpdate.BattOut,
BattIndoorSensor: awnUpdate.BattIn,
BattRainSensor: awnUpdate.BattRain,
TempInsideF: awnUpdate.TempInF,
HumidityInside: awnUpdate.HumidityIn,
BaromRelativeIn: awnUpdate.BaromRelIn,
BaromAbsoluteIn: awnUpdate.BaromAbsIn,
}
}
func UnmarshalQueryParams(query url.Values) (*AmbientWeatherUpdate, error) {
update := new(AmbientWeatherUpdate)
decoder := schema.NewDecoder()
if err := decoder.Decode(update, query); err != nil {
return nil, err
}
return update, nil
}

30
pkg/provider/awn/types.go Normal file
View File

@ -0,0 +1,30 @@
package awn
type AmbientWeatherUpdate struct {
PassKey string `json:"PASSKEY,omitempty" schema:"PASSKEY"`
StationType string `json:"stationtype,omitempty" schema:"stationtype"`
DateUTC string `json:"dateutc,omitempty" schema:"dateutc"`
TempF float32 `json:"tempf,omitempty" schema:"tempf"`
Humidity int `json:"humidity,omitempty" schema:"humidity"`
WindSpeedMPH float32 `json:"windspeedmph,omitempty" schema:"windspeedmph"`
WindGustMPH float32 `json:"windgustmph,omitempty" schema:"windgustmph"`
MaxDailyGust float32 `json:"maxdailygust,omitempty" schema:"maxdailygust"`
WindDir int `json:"winddir,omitempty" schema:"winddir"`
WindDirAVG10m int `json:"winddir_avg10m,omitempty" schema:"winddir_avg10m"`
UV int `json:"uv,omitempty" schema:"uv"`
SolarRadiation float32 `json:"solarradiation,omitempty" schema:"solarradiation"`
HourlyRainIn float32 `json:"hourlyrainin,omitempty" schema:"hourlyrainin"`
EventRainIn float32 `json:"eventrainin,omitempty" schema:"eventrainin"`
DailyRainIn float32 `json:"dailyrainin,omitempty" schema:"dailyrainin"`
WeeklyRainIn float32 `json:"weeklyrainin,omitempty" schema:"weeklyrainin"`
MonthlyRainIn float32 `json:"monthlyrainin,omitempty" schema:"monthlyrainin"`
YearlyRainIn float32 `json:"yearlyrainin,omitempty" schema:"yearlyrainin"`
TotalRainIn float32 `json:"totalrainin,omitempty" schema:"totalrainin"`
BattOut int `json:"battout,omitempty" schema:"battout"`
BattRain int `json:"battrain,omitempty" schema:"battrain"`
TempInF float32 `json:"tempinf,omitempty" schema:"tempinf"`
HumidityIn int `json:"humidityin,omitempty" schema:"humidityin"`
BaromRelIn float32 `json:"baromrelin,omitempty" schema:"baromrelin"`
BaromAbsIn float32 `json:"baromabsin,omitempty" schema:"baromabsin"`
BattIn int `json:"battin,omitempty" schema:"battin"`
}

15
pkg/provider/provider.go Normal file
View File

@ -0,0 +1,15 @@
package provider
import (
"context"
"net/http"
"gitea.libretechconsulting.com/rmcguire/ambient-weather-local-exporter/pkg/weather"
)
// Simple interface used for converting Wunderground and
// Ambient Weather Network HTTP requests to a stable struct
type AmbientProvider interface {
ReqToWeather(context.Context, *http.Request) (*weather.WeatherUpdate, error)
Name() string
}

View File

@ -0,0 +1,70 @@
package wunderground
import (
"context"
"net/http"
"net/url"
"time"
"github.com/gorilla/schema"
"gitea.libretechconsulting.com/rmcguire/ambient-weather-local-exporter/pkg/weather"
)
type WUProvider struct{}
const providerName = "weatherunderground"
func (wu *WUProvider) Name() string {
return providerName
}
// Takes an inbound request from the ambient device and maps
// to a stable struct for weather updates
func (wu *WUProvider) ReqToWeather(_ context.Context, r *http.Request) (
*weather.WeatherUpdate, error,
) {
wuUpdate, err := UnmarshalQueryParams(r.URL.Query())
if err != nil {
return nil, err
}
return MapWUUpdate(wuUpdate), nil
}
func MapWUUpdate(wuUpdate *WundergroundUpdate) *weather.WeatherUpdate {
updateTime, err := time.Parse(time.DateTime, wuUpdate.DateUTC)
if err != nil {
updateTime = time.Now()
}
return &weather.WeatherUpdate{
StationType: wuUpdate.SoftwareType,
DateUTC: &updateTime,
TempF: wuUpdate.Tempf,
Humidity: wuUpdate.Humidity,
WindSpeedMPH: wuUpdate.WindGustMPH,
WindGustMPH: wuUpdate.WindGustMPH,
WindDir: wuUpdate.WindDir,
UV: wuUpdate.UV,
SolarRadiation: wuUpdate.SolarRadiation,
HourlyRainIn: wuUpdate.RainIn,
DailyRainIn: wuUpdate.DailyRainIn,
WeeklyRainIn: wuUpdate.WeeklyRainIn,
MonthlyRainIn: wuUpdate.MonthlyRainIn,
YearlyRainIn: wuUpdate.YearlyRainIn,
TempInsideF: wuUpdate.IndoorTempF,
HumidityInside: wuUpdate.IndoorHumidity,
BaromRelativeIn: wuUpdate.BaromIn,
}
}
func UnmarshalQueryParams(query url.Values) (*WundergroundUpdate, error) {
update := new(WundergroundUpdate)
if err := schema.NewDecoder().Decode(update, query); err != nil {
return nil, err
}
return update, nil
}

View File

@ -0,0 +1,29 @@
package wunderground
type WundergroundUpdate struct {
ID string `json:"ID,omitempty" schema:"ID"`
Password string `json:"PASSWORD,omitempty" schema:"PASSWORD"`
UV int `json:"UV,omitempty" schema:"UV"`
Action string `json:"action,omitempty" schema:"action"`
BaromIn float32 `json:"baromin,omitempty" schema:"baromin"`
DailyRainIn float32 `json:"dailyrainin,omitempty" schema:"dailyrainin"`
DateUTC string `json:"dateutc,omitempty" schema:"dateutc"`
DewPtF float32 `json:"dewptf,omitempty" schema:"dewptf"`
Humidity int `json:"humidity,omitempty" schema:"humidity"`
IndoorHumidity int `json:"indoorhumidity,omitempty" schema:"indoorhumidity"`
IndoorTempF float32 `json:"indoortempf,omitempty" schema:"indoortempf"`
LowBatt bool `json:"lowbatt,omitempty" schema:"lowbatt"`
MonthlyRainIn float32 `json:"monthlyrainin,omitempty" schema:"monthlyrainin"`
RainIn float32 `json:"rainin,omitempty" schema:"rainin"`
Realtime bool `json:"realtime,omitempty" schema:"realtime"`
Rtfreq int `json:"rtfreq,omitempty" schema:"rtfreq"`
SoftwareType string `json:"softwaretype,omitempty" schema:"softwaretype"`
SolarRadiation float32 `json:"solarradiation,omitempty" schema:"solarradiation"`
Tempf float32 `json:"tempf,omitempty" schema:"tempf"`
WeeklyRainIn float32 `json:"weeklyrainin,omitempty" schema:"weeklyrainin"`
WindChillF float32 `json:"windchillf,omitempty" schema:"windchillf"`
WindDir int `json:"winddir,omitempty" schema:"winddir"`
WindGustMPH float32 `json:"windgustmph,omitempty" schema:"windgustmph"`
WindSpeedMPH float32 `json:"windspeedmph,omitempty" schema:"windspeedmph"`
YearlyRainIn float32 `json:"yearlyrainin,omitempty" schema:"yearlyrainin"`
}