Files
go-weatherstation/internal/config/config.go

131 lines
2.9 KiB
Go

package config
import (
"errors"
"os"
"strings"
"time"
"gopkg.in/yaml.v3"
)
type Config struct {
LogLevel string `yaml:"log_level"`
MQTT struct {
Broker string `yaml:"broker"`
ClientID string `yaml:"client_id"`
Username string `yaml:"username"`
Password string `yaml:"password"`
Topic string `yaml:"topic"`
QoS byte `yaml:"qos"`
Topics []MQTTTopic `yaml:"topics"`
} `yaml:"mqtt"`
DB struct {
ConnString string `yaml:"conn_string"`
} `yaml:"db"`
Site struct {
Name string `yaml:"name"`
Latitude float64 `yaml:"latitude"`
Longitude float64 `yaml:"longitude"`
ElevationM float64 `yaml:"elevation_m"`
} `yaml:"site"`
Pollers struct {
OpenMeteo struct {
Enabled bool `yaml:"enabled"`
Interval time.Duration `yaml:"interval"`
Model string `yaml:"model"`
} `yaml:"open_meteo"`
} `yaml:"pollers"`
Web struct {
Enabled *bool `yaml:"enabled"`
Listen string `yaml:"listen"`
} `yaml:"web"`
Wunderground struct {
Enabled bool `yaml:"enabled"`
StationID string `yaml:"station_id"`
StationKey string `yaml:"station_key"`
Interval time.Duration `yaml:"interval"`
} `yaml:"wunderground"`
}
type MQTTTopic struct {
Name string `yaml:"name"`
Topic string `yaml:"topic"`
Type string `yaml:"type"`
QoS *byte `yaml:"qos"`
}
func Load(path string) (*Config, error) {
b, err := os.ReadFile(path)
if err != nil {
return nil, err
}
var c Config
if err := yaml.Unmarshal(b, &c); err != nil {
return nil, err
}
// Minimal validation
if c.MQTT.Broker == "" {
return nil, errors.New("mqtt broker is required")
}
if len(c.MQTT.Topics) == 0 && c.MQTT.Topic != "" {
qos := c.MQTT.QoS
c.MQTT.Topics = []MQTTTopic{{
Name: "ws90",
Topic: c.MQTT.Topic,
Type: "ws90",
QoS: &qos,
}}
}
if len(c.MQTT.Topics) == 0 {
return nil, errors.New("mqtt topic(s) are required")
}
for i := range c.MQTT.Topics {
t := c.MQTT.Topics[i]
if t.Topic == "" {
return nil, errors.New("mqtt topics must include topic")
}
if t.Type == "" {
t.Type = "ws90"
}
t.Type = strings.ToLower(t.Type)
c.MQTT.Topics[i] = t
}
if c.DB.ConnString == "" {
return nil, errors.New("db conn_string is required")
}
if c.Site.Name == "" {
c.Site.Name = "default"
}
if c.Pollers.OpenMeteo.Model == "" {
c.Pollers.OpenMeteo.Model = "ecmwf"
}
if c.Pollers.OpenMeteo.Interval == 0 {
c.Pollers.OpenMeteo.Interval = 30 * time.Minute
}
if c.Wunderground.Interval == 0 {
c.Wunderground.Interval = 60 * time.Second
}
if c.Web.Listen == "" {
c.Web.Listen = ":8080"
}
if c.Web.Enabled == nil {
enabled := true
c.Web.Enabled = &enabled
}
// If enabled, require creds
if c.Wunderground.Enabled && (c.Wunderground.StationID == "" || c.Wunderground.StationKey == "") {
return nil, errors.New("wunderground enabled but station_id/station_key not set")
}
return &c, nil
}