From 08ebdc5045dff1786c9edf770a86ff7d7c8be7a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Rasmussen?= Date: Fri, 11 Mar 2022 21:06:33 +0100 Subject: [PATCH] Refactor configuration --- cmd/fermentord/config.go | 63 ---------------------- cmd/fermentord/db.go | 3 +- cmd/fermentord/main.go | 9 ++-- internal/api/http.go | 4 +- internal/configuration/config.go | 92 ++++++++++++++++++++++++++++++++ internal/controllers/chamber.go | 9 ++-- internal/controllers/config.go | 50 +++++------------ 7 files changed, 119 insertions(+), 111 deletions(-) delete mode 100644 cmd/fermentord/config.go create mode 100644 internal/configuration/config.go diff --git a/cmd/fermentord/config.go b/cmd/fermentord/config.go deleted file mode 100644 index 23e7d2d..0000000 --- a/cmd/fermentord/config.go +++ /dev/null @@ -1,63 +0,0 @@ -package main - -import ( - "log" - "time" - - "git.joco.dk/sng/fermentord/internal/controllers" - "git.joco.dk/sng/fermentord/pkg/temperature" - "github.com/getsentry/sentry-go" - "github.com/spf13/viper" -) - -func loadConfiguration() *controllers.ControllerConfig { - hub := sentry.CurrentHub().Clone() - defer hub.Flush(10 * time.Second) - - viper.SetDefault("http.port", 8000) - viper.SetDefault("main.data_path", "./data.txt") - viper.SetDefault("nats.stream", "FERMENTOR") - viper.SetDefault("nats.subject.state", "FERMENTOR.state") - viper.SetDefault("nats.subject.temp", "FERMENTOR.temp") - viper.SetDefault("nats.url", "nats.service.consul") - viper.SetDefault("pid.kd", 2.0) - viper.SetDefault("pid.ki", 0.0001) - viper.SetDefault("pid.kp", 2.0) - viper.SetDefault("limits.heater_grace_time_secs", 1800) - viper.SetDefault("limits.max_chamber_temp", 40) - viper.SetDefault("limits.max_cooler_runtime_secs", 86400) - viper.SetDefault("limits.min_chamber_temp", 5) - viper.SetDefault("limits.min_cooler_cooldown_secs", 300) - viper.SetDefault("limits.min_cooler_runtime_secs", 300) - viper.SetDefault("sensors.weight", 0.8) - - viper.AddConfigPath("/etc") - viper.AddConfigPath("/usr/local/etc") - viper.AddConfigPath(".") - viper.SetConfigName("fermentord") - viper.SetConfigType("toml") - - if err := viper.ReadInConfig(); err != nil { - log.Printf("Error loading configuration: %v", err) - } - - config := &controllers.ControllerConfig{} - if err := viper.Unmarshal(config); err != nil { - hub.CaptureException(err) - log.Fatal(err) - } - - return config -} - -func reloadConfiguration(config *controllers.ControllerConfig, ctrl *controllers.ChamberController) { - log.Printf("Reloading configuration") - - temperature.ConfigUpdates <- []string{ - config.Sensors.Ambient, - config.Sensors.Chamber, - config.Sensors.Wort, - } - - ctrl.ConfigUpdates <- *config -} diff --git a/cmd/fermentord/db.go b/cmd/fermentord/db.go index 11d55ce..c15677b 100644 --- a/cmd/fermentord/db.go +++ b/cmd/fermentord/db.go @@ -8,6 +8,7 @@ import ( "sync" "time" + "git.joco.dk/sng/fermentord/internal/configuration" "git.joco.dk/sng/fermentord/internal/controllers" "git.joco.dk/sng/fermentord/pkg/temperature" "github.com/getsentry/sentry-go" @@ -17,7 +18,7 @@ var ( f *os.File ) -func persistData(ctx context.Context, wg *sync.WaitGroup, chState <-chan controllers.ChamberState, chTemp <-chan temperature.TemperatureReading, config *controllers.ControllerConfig) { +func persistData(ctx context.Context, wg *sync.WaitGroup, chState <-chan controllers.ChamberState, chTemp <-chan temperature.TemperatureReading, config *configuration.ControllerConfig) { var err error hub := sentry.CurrentHub().Clone() diff --git a/cmd/fermentord/main.go b/cmd/fermentord/main.go index 80592b3..d2ea191 100644 --- a/cmd/fermentord/main.go +++ b/cmd/fermentord/main.go @@ -10,6 +10,7 @@ import ( "time" "git.joco.dk/sng/fermentord/internal/api" + "git.joco.dk/sng/fermentord/internal/configuration" "git.joco.dk/sng/fermentord/internal/controllers" "git.joco.dk/sng/fermentord/internal/hw" "git.joco.dk/sng/fermentord/internal/metrics" @@ -22,7 +23,7 @@ import ( "github.com/spf13/viper" ) -func mainLoop(ctx context.Context, wg *sync.WaitGroup, js nats.JetStream, config *controllers.ControllerConfig) { +func mainLoop(ctx context.Context, wg *sync.WaitGroup, js nats.JetStream, config *configuration.ControllerConfig) { hub := sentry.CurrentHub().Clone() defer hub.Flush(10 * time.Second) defer wg.Done() @@ -36,10 +37,10 @@ func mainLoop(ctx context.Context, wg *sync.WaitGroup, js nats.JetStream, config // Configuration reload viper.OnConfigChange(func(in fsnotify.Event) { - reloadConfiguration(config, ctrl) + controllers.ReloadConfiguration(config, ctrl) }) viper.WatchConfig() - reloadConfiguration(config, ctrl) + controllers.ReloadConfiguration(config, ctrl) gpio, err := hw.NewGpio() if err != nil { @@ -126,7 +127,7 @@ func main() { defer sentry.Flush(10 * time.Second) // Configuration - config := loadConfiguration() + config := configuration.LoadConfiguration() // NATS nc, err := nats.Connect(config.NATS.URL) diff --git a/internal/api/http.go b/internal/api/http.go index b62749a..4a7fafb 100644 --- a/internal/api/http.go +++ b/internal/api/http.go @@ -5,13 +5,13 @@ import ( "log" "net/http" - "git.joco.dk/sng/fermentord/internal/controllers" + "git.joco.dk/sng/fermentord/internal/configuration" "github.com/getsentry/sentry-go" "github.com/nats-io/nats.go" ) type API struct { - config *controllers.ControllerConfig + config *configuration.ControllerConfig configChangeCallback func() nc *nats.Conn } diff --git a/internal/configuration/config.go b/internal/configuration/config.go new file mode 100644 index 0000000..c1eeba5 --- /dev/null +++ b/internal/configuration/config.go @@ -0,0 +1,92 @@ +package configuration + +import ( + "log" + "time" + + "github.com/getsentry/sentry-go" + "github.com/spf13/viper" +) + +type ControllerConfig struct { + NATS struct { + URL string `mapstructure:"url"` + Stream string `mapstructure:"stream"` + Subject struct { + Temp string `mapstructure:"temp"` + State string `mapstructure:"state"` + } `mapstructure:"subject"` + } `mapstructure:"nats"` + + HTTP struct { + Port int16 `mapstructure:"port"` + } `mapstructure:"http"` + + DataPath string `mapstructure:"data_path"` + + Sensors struct { + Wort string `mapstructure:"wort"` + Chamber string `mapstructure:"chamber"` + Ambient string `mapstructure:"ambient"` + Weight float64 `mapstructure:"weight"` + } `mapstructure:"sensors"` + + FermentationTemperature float64 `mapstructure:"fermentation_temp"` + DeltaTemperatureCool float64 `mapstructure:"delta_temp_cool"` + DeltaTemperatureHeat float64 `mapstructure:"delta_temp_heat"` + + Limits struct { + MinChamberTemperature float64 `mapstructure:"min_chamber_temp"` + MaxChamberTemperature float64 `mapstructure:"max_chamber_temp"` + MinCoolerRuntimeSecs float64 `mapstructure:"min_cooler_runtime_secs"` + MaxCoolerRuntimeSecs float64 `mapstructure:"max_cooler_runtime_secs"` + MinCoolerCooldownSecs float64 `mapstructure:"min_cooler_cooldown_secs"` + HeaterGraceTimeSecs float64 `mapstructure:"heater_grace_time_secs"` + } `mapstructure:"limits"` + + PID struct { + Kp float64 `mapstructure:"kp"` // 2.0 + Ki float64 `mapstructure:"ki"` // 0.0001 + Kd float64 `mapstructure:"kd"` // 2.0 + } `mapstructure:"pid"` +} + +func LoadConfiguration() *ControllerConfig { + hub := sentry.CurrentHub().Clone() + defer hub.Flush(10 * time.Second) + + viper.SetDefault("http.port", 8000) + viper.SetDefault("main.data_path", "./data.txt") + viper.SetDefault("nats.stream", "FERMENTOR") + viper.SetDefault("nats.subject.state", "FERMENTOR.state") + viper.SetDefault("nats.subject.temp", "FERMENTOR.temp") + viper.SetDefault("nats.url", "nats.service.consul") + viper.SetDefault("pid.kd", 2.0) + viper.SetDefault("pid.ki", 0.0001) + viper.SetDefault("pid.kp", 2.0) + viper.SetDefault("limits.heater_grace_time_secs", 1800) + viper.SetDefault("limits.max_chamber_temp", 40) + viper.SetDefault("limits.max_cooler_runtime_secs", 86400) + viper.SetDefault("limits.min_chamber_temp", 5) + viper.SetDefault("limits.min_cooler_cooldown_secs", 300) + viper.SetDefault("limits.min_cooler_runtime_secs", 300) + viper.SetDefault("sensors.weight", 0.8) + + viper.AddConfigPath("/etc") + viper.AddConfigPath("/usr/local/etc") + viper.AddConfigPath(".") + viper.SetConfigName("fermentord") + viper.SetConfigType("toml") + + if err := viper.ReadInConfig(); err != nil { + log.Printf("Error loading configuration: %v", err) + } + + config := &ControllerConfig{} + if err := viper.Unmarshal(config); err != nil { + hub.CaptureException(err) + log.Fatal(err) + } + + return config +} diff --git a/internal/controllers/chamber.go b/internal/controllers/chamber.go index 2a2f57d..bab9aed 100644 --- a/internal/controllers/chamber.go +++ b/internal/controllers/chamber.go @@ -7,6 +7,7 @@ import ( "sync" "time" + "git.joco.dk/sng/fermentord/internal/configuration" "git.joco.dk/sng/fermentord/pkg/temperature" "github.com/getsentry/sentry-go" ) @@ -26,8 +27,8 @@ var ChamberStateMap = map[ChamberState]string{ } type ChamberController struct { - ConfigUpdates chan ControllerConfig - config ControllerConfig + ConfigUpdates chan configuration.ControllerConfig + config configuration.ControllerConfig // Current state. chamberState ChamberState @@ -48,7 +49,7 @@ type ChamberController struct { hub *sentry.Hub } -func NewChamberController(name string, config ControllerConfig, chTemp <-chan temperature.TemperatureReading) *ChamberController { +func NewChamberController(name string, config configuration.ControllerConfig, chTemp <-chan temperature.TemperatureReading) *ChamberController { return &ChamberController{ C: make(chan ChamberState), name: name, @@ -56,7 +57,7 @@ func NewChamberController(name string, config ControllerConfig, chTemp <-chan te pid: NewPIDController(config.PID.Kp, config.PID.Ki, config.PID.Kd), chTemp: chTemp, chamberState: ChamberStateIdle, - ConfigUpdates: make(chan ControllerConfig, 1), + ConfigUpdates: make(chan configuration.ControllerConfig, 1), hub: sentry.CurrentHub().Clone(), } } diff --git a/internal/controllers/config.go b/internal/controllers/config.go index ce2ed2e..02320b6 100644 --- a/internal/controllers/config.go +++ b/internal/controllers/config.go @@ -1,44 +1,20 @@ package controllers -type ControllerConfig struct { - NATS struct { - URL string `mapstructure:"url"` - Stream string `mapstructure:"stream"` - Subject struct { - Temp string `mapstructure:"temp"` - State string `mapstructure:"state"` - } `mapstructure:"subject"` - } `mapstructure:"nats"` +import ( + "log" - HTTP struct { - Port int16 `mapstructure:"port"` - } `mapstructure:"http"` + "git.joco.dk/sng/fermentord/internal/configuration" + "git.joco.dk/sng/fermentord/pkg/temperature" +) - DataPath string `mapstructure:"data_path"` +func ReloadConfiguration(config *configuration.ControllerConfig, ctrl *ChamberController) { + log.Printf("Reloading configuration") - Sensors struct { - Wort string `mapstructure:"wort"` - Chamber string `mapstructure:"chamber"` - Ambient string `mapstructure:"ambient"` - Weight float64 `mapstructure:"weight"` - } `mapstructure:"sensors"` + temperature.ConfigUpdates <- []string{ + config.Sensors.Ambient, + config.Sensors.Chamber, + config.Sensors.Wort, + } - FermentationTemperature float64 `mapstructure:"fermentation_temp"` - DeltaTemperatureCool float64 `mapstructure:"delta_temp_cool"` - DeltaTemperatureHeat float64 `mapstructure:"delta_temp_heat"` - - Limits struct { - MinChamberTemperature float64 `mapstructure:"min_chamber_temp"` - MaxChamberTemperature float64 `mapstructure:"max_chamber_temp"` - MinCoolerRuntimeSecs float64 `mapstructure:"min_cooler_runtime_secs"` - MaxCoolerRuntimeSecs float64 `mapstructure:"max_cooler_runtime_secs"` - MinCoolerCooldownSecs float64 `mapstructure:"min_cooler_cooldown_secs"` - HeaterGraceTimeSecs float64 `mapstructure:"heater_grace_time_secs"` - } `mapstructure:"limits"` - - PID struct { - Kp float64 `mapstructure:"kp"` // 2.0 - Ki float64 `mapstructure:"ki"` // 0.0001 - Kd float64 `mapstructure:"kd"` // 2.0 - } `mapstructure:"pid"` + ctrl.ConfigUpdates <- *config }