From 7b01faa2776addd86019864568eea6c554ee4e69 Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Thu, 25 Jul 2024 23:00:09 +0200 Subject: [PATCH] Move initial configuration to separate loadConfig function. Add support for HA options.json. --- main.go | 99 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 86 insertions(+), 13 deletions(-) diff --git a/main.go b/main.go index 2c7a5b5..1e9c8b0 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "log" "log/slog" "os" + "strconv" "time" _ "time/tzdata" @@ -107,17 +108,91 @@ type Payload struct { R3 *int `json:"r3"` // Returning / exporting L3 (W) } +type Config struct { + MQTTBroker string `json:"mqtt_broker"` + MQTTTopic string `json:"mqtt_topic"` + MQTTUser string `json:"mqtt_user"` + MQTTPassword string `json:"mqtt_password"` + DB string `json:"DB"` + TimescaleDB bool `json:"timescaledb"` + LogLevel string `json:"log_level"` + TZ string `json:"timezone"` +} + var db *sql.DB var logger = slog.New(slog.NewJSONHandler(os.Stdout, nil)) +var config Config + +func loadConfig() Config { + configFilePath := os.Getenv("CONFIG_FILE") + if configFilePath == "" { + configFilePath = "/data/options.json" + } + + data, err := os.ReadFile(configFilePath) + if err == nil { + // Successfully read the file, parse the JSON + err = json.Unmarshal(data, &config) + if err != nil { + log.Fatalf("Error parsing config file: %v", err) + } + } else { + // Load environment variables from .env file if it exists + if err := godotenv.Load(); err != nil { + logger.Info("No .env file found or error loading .env file (ignore this message when using container)", "error", err) + } + + // Fallback to environment variables + config.MQTTBroker = os.Getenv("MQTT_BROKER") + if config.MQTTBroker == "" { + log.Fatal("MQTT_BROKER environment variable is not set.") + } + config.MQTTTopic = os.Getenv("MQTT_TOPIC") + if config.MQTTTopic == "" { + log.Fatal("MQTT_TOPIC environment variable is not set.") + } + config.MQTTUser = os.Getenv("MQTT_USERNAME") + if config.MQTTUser == "" { + log.Fatal("MQTT_USERNAME environment variable is not set.") + } + config.MQTTPassword = os.Getenv("MQTT_PASSWORD") + if config.MQTTPassword == "" { + log.Fatal("MQTT_PASSWORD environment variable is not set.") + } + config.DB = os.Getenv("PG_DB") + if config.DB == "" { + log.Fatal("PG_DB environment variable is not set.") + } + + timescaleDBStr := os.Getenv("TIMESCALEDB_ENABLED") + if timescaleDBStr != "" { + timescaleDB, err := strconv.ParseBool(timescaleDBStr) + if err != nil { + log.Fatalf("Error parsing TIMESCALEDB_ENABLED: %v", err) + } + config.TimescaleDB = timescaleDB + } + config.LogLevel = os.Getenv("LOG_LEVEL") + if config.DB == "" { + log.Fatal("LOG_LEVEL environment variable is not set.") + } + + config.TZ = os.Getenv("TZ") + if config.DB == "" { + log.Fatal("TZ environment variable is not set.") + } + + } + + return config + +} func main() { // Initial logger setup slog.SetDefault(logger) - // Load environment variables from .env file if it exists - if err := godotenv.Load(); err != nil { - logger.Info("No .env file found or error loading .env file (ignore this message when using container)", "error", err) - } + loadConfig() // Update the logger based on the LOG_LEVEL environment variable logLevel := getLogLevelFromEnv(slog.LevelInfo) // Default to info level @@ -127,22 +202,22 @@ func main() { logger.Info("Logger initialized with dynamic log level") // Connect to PostgreSQL - pgConnStr := os.Getenv("PG_DB") + pgConnStr := config.DB if err := connectToPostgreSQL(pgConnStr); err != nil { log.Fatal("Error connecting to PostgreSQL", "error", err) } // Initialize MQTT options opts := mqtt.NewClientOptions() - opts.AddBroker(os.Getenv("MQTT_BROKER")) - opts.SetUsername(os.Getenv("MQTT_USERNAME")) - opts.SetPassword(os.Getenv("MQTT_PASSWORD")) + opts.AddBroker(config.MQTTBroker) + opts.SetUsername(config.MQTTUser) + opts.SetPassword(config.MQTTPassword) opts.SetAutoReconnect(true) opts.SetConnectionLostHandler(func(client mqtt.Client, err error) { logger.Error("Connection lost", "error", err) }) opts.SetOnConnectHandler(func(client mqtt.Client) { - topic := os.Getenv("MQTT_TOPIC") + topic := config.MQTTTopic logger.Info("Connected to MQTT broker, subscribing to topic...", "topic", topic) if token := client.Subscribe(topic, 0, mqttMessageHandler); token.Wait() && token.Error() != nil { logger.Error("Error subscribing to MQTT topic", "topic", topic, "error", token.Error()) @@ -161,7 +236,7 @@ func main() { // Helper function to map environment variable to slog.Level func getLogLevelFromEnv(defaultLevel slog.Level) slog.Level { - logLevelStr := os.Getenv("LOG_LEVEL") + logLevelStr := config.LogLevel switch logLevelStr { case "DEBUG": return slog.LevelDebug @@ -428,9 +503,7 @@ func connectToPostgreSQL(pgConnStr string) error { log.Fatal("Error creating table:", err) } - timescaleDBEnabled := os.Getenv("TIMESCALEDB_ENABLED") - - if timescaleDBEnabled == "true" { + if config.TimescaleDB { // Enable TimescaleDB _, err = db.Exec(` SELECT create_hypertable('p1', 'timestamp', if_not_exists => TRUE, migrate_data => TRUE);