Refactor configuration

This commit is contained in:
Søren Rasmussen 2022-03-11 21:06:33 +01:00
parent 43241991c0
commit 08ebdc5045
7 changed files with 119 additions and 111 deletions

View file

@ -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
}

View file

@ -8,6 +8,7 @@ import (
"sync" "sync"
"time" "time"
"git.joco.dk/sng/fermentord/internal/configuration"
"git.joco.dk/sng/fermentord/internal/controllers" "git.joco.dk/sng/fermentord/internal/controllers"
"git.joco.dk/sng/fermentord/pkg/temperature" "git.joco.dk/sng/fermentord/pkg/temperature"
"github.com/getsentry/sentry-go" "github.com/getsentry/sentry-go"
@ -17,7 +18,7 @@ var (
f *os.File 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 var err error
hub := sentry.CurrentHub().Clone() hub := sentry.CurrentHub().Clone()

View file

@ -10,6 +10,7 @@ import (
"time" "time"
"git.joco.dk/sng/fermentord/internal/api" "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/controllers"
"git.joco.dk/sng/fermentord/internal/hw" "git.joco.dk/sng/fermentord/internal/hw"
"git.joco.dk/sng/fermentord/internal/metrics" "git.joco.dk/sng/fermentord/internal/metrics"
@ -22,7 +23,7 @@ import (
"github.com/spf13/viper" "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() hub := sentry.CurrentHub().Clone()
defer hub.Flush(10 * time.Second) defer hub.Flush(10 * time.Second)
defer wg.Done() defer wg.Done()
@ -36,10 +37,10 @@ func mainLoop(ctx context.Context, wg *sync.WaitGroup, js nats.JetStream, config
// Configuration reload // Configuration reload
viper.OnConfigChange(func(in fsnotify.Event) { viper.OnConfigChange(func(in fsnotify.Event) {
reloadConfiguration(config, ctrl) controllers.ReloadConfiguration(config, ctrl)
}) })
viper.WatchConfig() viper.WatchConfig()
reloadConfiguration(config, ctrl) controllers.ReloadConfiguration(config, ctrl)
gpio, err := hw.NewGpio() gpio, err := hw.NewGpio()
if err != nil { if err != nil {
@ -126,7 +127,7 @@ func main() {
defer sentry.Flush(10 * time.Second) defer sentry.Flush(10 * time.Second)
// Configuration // Configuration
config := loadConfiguration() config := configuration.LoadConfiguration()
// NATS // NATS
nc, err := nats.Connect(config.NATS.URL) nc, err := nats.Connect(config.NATS.URL)

View file

@ -5,13 +5,13 @@ import (
"log" "log"
"net/http" "net/http"
"git.joco.dk/sng/fermentord/internal/controllers" "git.joco.dk/sng/fermentord/internal/configuration"
"github.com/getsentry/sentry-go" "github.com/getsentry/sentry-go"
"github.com/nats-io/nats.go" "github.com/nats-io/nats.go"
) )
type API struct { type API struct {
config *controllers.ControllerConfig config *configuration.ControllerConfig
configChangeCallback func() configChangeCallback func()
nc *nats.Conn nc *nats.Conn
} }

View file

@ -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
}

View file

@ -7,6 +7,7 @@ import (
"sync" "sync"
"time" "time"
"git.joco.dk/sng/fermentord/internal/configuration"
"git.joco.dk/sng/fermentord/pkg/temperature" "git.joco.dk/sng/fermentord/pkg/temperature"
"github.com/getsentry/sentry-go" "github.com/getsentry/sentry-go"
) )
@ -26,8 +27,8 @@ var ChamberStateMap = map[ChamberState]string{
} }
type ChamberController struct { type ChamberController struct {
ConfigUpdates chan ControllerConfig ConfigUpdates chan configuration.ControllerConfig
config ControllerConfig config configuration.ControllerConfig
// Current state. // Current state.
chamberState ChamberState chamberState ChamberState
@ -48,7 +49,7 @@ type ChamberController struct {
hub *sentry.Hub 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{ return &ChamberController{
C: make(chan ChamberState), C: make(chan ChamberState),
name: name, 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), pid: NewPIDController(config.PID.Kp, config.PID.Ki, config.PID.Kd),
chTemp: chTemp, chTemp: chTemp,
chamberState: ChamberStateIdle, chamberState: ChamberStateIdle,
ConfigUpdates: make(chan ControllerConfig, 1), ConfigUpdates: make(chan configuration.ControllerConfig, 1),
hub: sentry.CurrentHub().Clone(), hub: sentry.CurrentHub().Clone(),
} }
} }

View file

@ -1,44 +1,20 @@
package controllers package controllers
type ControllerConfig struct { import (
NATS struct { "log"
URL string `mapstructure:"url"`
Stream string `mapstructure:"stream"`
Subject struct {
Temp string `mapstructure:"temp"`
State string `mapstructure:"state"`
} `mapstructure:"subject"`
} `mapstructure:"nats"`
HTTP struct { "git.joco.dk/sng/fermentord/internal/configuration"
Port int16 `mapstructure:"port"` "git.joco.dk/sng/fermentord/pkg/temperature"
} `mapstructure:"http"` )
DataPath string `mapstructure:"data_path"` func ReloadConfiguration(config *configuration.ControllerConfig, ctrl *ChamberController) {
log.Printf("Reloading configuration")
Sensors struct { temperature.ConfigUpdates <- []string{
Wort string `mapstructure:"wort"` config.Sensors.Ambient,
Chamber string `mapstructure:"chamber"` config.Sensors.Chamber,
Ambient string `mapstructure:"ambient"` config.Sensors.Wort,
Weight float64 `mapstructure:"weight"` }
} `mapstructure:"sensors"`
FermentationTemperature float64 `mapstructure:"fermentation_temp"` ctrl.ConfigUpdates <- *config
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"`
} }