package config import ( "encoding/json" "fmt" "os" ) type Config struct { ScreenID string `json:"screen_id"` ServerBaseURL string `json:"server_base_url"` MQTTBroker string `json:"mqtt_broker"` HeartbeatEvery int `json:"heartbeat_every_seconds"` } const defaultConfigPath = "/etc/signage/config.json" func Load() (Config, error) { cfg := defaultConfig() configPath := getenv("MORZ_INFOBOARD_CONFIG", defaultConfigPath) if err := loadFromFile(configPath, &cfg); err != nil { if !os.IsNotExist(err) { return Config{}, fmt.Errorf("load config file: %w", err) } } overrideFromEnv(&cfg) if cfg.ScreenID == "" { return Config{}, fmt.Errorf("screen id is required") } if cfg.HeartbeatEvery <= 0 { cfg.HeartbeatEvery = defaultConfig().HeartbeatEvery } return cfg, nil } func defaultConfig() Config { return Config{ ScreenID: "unset-screen", ServerBaseURL: "http://127.0.0.1:8080", MQTTBroker: "tcp://127.0.0.1:1883", HeartbeatEvery: 30, } } func loadFromFile(path string, cfg *Config) error { data, err := os.ReadFile(path) if err != nil { return err } return json.Unmarshal(data, cfg) } func overrideFromEnv(cfg *Config) { cfg.ScreenID = getenv("MORZ_INFOBOARD_SCREEN_ID", cfg.ScreenID) cfg.ServerBaseURL = getenv("MORZ_INFOBOARD_SERVER_URL", cfg.ServerBaseURL) cfg.MQTTBroker = getenv("MORZ_INFOBOARD_MQTT_BROKER", cfg.MQTTBroker) } func getenv(key, fallback string) string { value := os.Getenv(key) if value == "" { return fallback } return value }