Move initial configuration to separate loadConfig function. Add support for HA options.json.
All checks were successful
Build Docker image / build (push) Successful in 1m8s
Build Golang packages / release (push) Has been skipped

This commit is contained in:
Pieter Hollander 2024-07-25 23:00:09 +02:00
parent 285dfd90f6
commit 7b01faa277
Signed by: pieter
SSH key fingerprint: SHA256:HbX+9cBXsop9SuvL+mELd29sK+7DehFfdVweFVDtMSg

99
main.go
View file

@ -7,6 +7,7 @@ import (
"log" "log"
"log/slog" "log/slog"
"os" "os"
"strconv"
"time" "time"
_ "time/tzdata" _ "time/tzdata"
@ -107,17 +108,91 @@ type Payload struct {
R3 *int `json:"r3"` // Returning / exporting L3 (W) 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 db *sql.DB
var logger = slog.New(slog.NewJSONHandler(os.Stdout, nil)) 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() { func main() {
// Initial logger setup // Initial logger setup
slog.SetDefault(logger) slog.SetDefault(logger)
// Load environment variables from .env file if it exists loadConfig()
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)
}
// Update the logger based on the LOG_LEVEL environment variable // Update the logger based on the LOG_LEVEL environment variable
logLevel := getLogLevelFromEnv(slog.LevelInfo) // Default to info level logLevel := getLogLevelFromEnv(slog.LevelInfo) // Default to info level
@ -127,22 +202,22 @@ func main() {
logger.Info("Logger initialized with dynamic log level") logger.Info("Logger initialized with dynamic log level")
// Connect to PostgreSQL // Connect to PostgreSQL
pgConnStr := os.Getenv("PG_DB") pgConnStr := config.DB
if err := connectToPostgreSQL(pgConnStr); err != nil { if err := connectToPostgreSQL(pgConnStr); err != nil {
log.Fatal("Error connecting to PostgreSQL", "error", err) log.Fatal("Error connecting to PostgreSQL", "error", err)
} }
// Initialize MQTT options // Initialize MQTT options
opts := mqtt.NewClientOptions() opts := mqtt.NewClientOptions()
opts.AddBroker(os.Getenv("MQTT_BROKER")) opts.AddBroker(config.MQTTBroker)
opts.SetUsername(os.Getenv("MQTT_USERNAME")) opts.SetUsername(config.MQTTUser)
opts.SetPassword(os.Getenv("MQTT_PASSWORD")) opts.SetPassword(config.MQTTPassword)
opts.SetAutoReconnect(true) opts.SetAutoReconnect(true)
opts.SetConnectionLostHandler(func(client mqtt.Client, err error) { opts.SetConnectionLostHandler(func(client mqtt.Client, err error) {
logger.Error("Connection lost", "error", err) logger.Error("Connection lost", "error", err)
}) })
opts.SetOnConnectHandler(func(client mqtt.Client) { 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) logger.Info("Connected to MQTT broker, subscribing to topic...", "topic", topic)
if token := client.Subscribe(topic, 0, mqttMessageHandler); token.Wait() && token.Error() != nil { if token := client.Subscribe(topic, 0, mqttMessageHandler); token.Wait() && token.Error() != nil {
logger.Error("Error subscribing to MQTT topic", "topic", topic, "error", token.Error()) 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 // Helper function to map environment variable to slog.Level
func getLogLevelFromEnv(defaultLevel slog.Level) slog.Level { func getLogLevelFromEnv(defaultLevel slog.Level) slog.Level {
logLevelStr := os.Getenv("LOG_LEVEL") logLevelStr := config.LogLevel
switch logLevelStr { switch logLevelStr {
case "DEBUG": case "DEBUG":
return slog.LevelDebug return slog.LevelDebug
@ -428,9 +503,7 @@ func connectToPostgreSQL(pgConnStr string) error {
log.Fatal("Error creating table:", err) log.Fatal("Error creating table:", err)
} }
timescaleDBEnabled := os.Getenv("TIMESCALEDB_ENABLED") if config.TimescaleDB {
if timescaleDBEnabled == "true" {
// Enable TimescaleDB // Enable TimescaleDB
_, err = db.Exec(` _, err = db.Exec(`
SELECT create_hypertable('p1', 'timestamp', if_not_exists => TRUE, migrate_data => TRUE); SELECT create_hypertable('p1', 'timestamp', if_not_exists => TRUE, migrate_data => TRUE);