From 1dbebc0a2b70b856eda161877dabbd74646375da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesko=20Ansch=C3=BCtz?= Date: Sun, 22 Mar 2026 21:00:15 +0100 Subject: [PATCH] Ergaenze MQTT-Authentifizierung mit Username und Password - Config: mqtt_username / mqtt_password (JSON + Env MORZ_INFOBOARD_MQTT_USERNAME/PASSWORD) - mqttheartbeat.New() nimmt username und password entgegen, setzt Credentials nur wenn username nicht leer ist (kein-Auth-Broker bleibt kompatibel) Co-Authored-By: Claude Sonnet 4.6 --- player/agent/internal/app/app.go | 2 +- player/agent/internal/config/config.go | 4 ++++ player/agent/internal/mqttheartbeat/heartbeat.go | 8 +++++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/player/agent/internal/app/app.go b/player/agent/internal/app/app.go index 828dcb1..03bed3e 100644 --- a/player/agent/internal/app/app.go +++ b/player/agent/internal/app/app.go @@ -75,7 +75,7 @@ func New() (*App, error) { var mqttPub mqttSender if cfg.MQTTBroker != "" { - mqttPub = mqttheartbeat.New(cfg.MQTTBroker, cfg.ScreenID) + mqttPub = mqttheartbeat.New(cfg.MQTTBroker, cfg.ScreenID, cfg.MQTTUsername, cfg.MQTTPassword) logger.Printf("event=mqtt_enabled broker=%s", cfg.MQTTBroker) } else { logger.Printf("event=mqtt_disabled reason=no_broker_configured") diff --git a/player/agent/internal/config/config.go b/player/agent/internal/config/config.go index bb45d3e..bc5e5f0 100644 --- a/player/agent/internal/config/config.go +++ b/player/agent/internal/config/config.go @@ -10,6 +10,8 @@ type Config struct { ScreenID string `json:"screen_id"` ServerBaseURL string `json:"server_base_url"` MQTTBroker string `json:"mqtt_broker"` + MQTTUsername string `json:"mqtt_username"` + MQTTPassword string `json:"mqtt_password"` HeartbeatEvery int `json:"heartbeat_every_seconds"` StatusReportEvery int `json:"status_report_every_seconds"` } @@ -66,6 +68,8 @@ 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) + cfg.MQTTUsername = getenv("MORZ_INFOBOARD_MQTT_USERNAME", cfg.MQTTUsername) + cfg.MQTTPassword = getenv("MORZ_INFOBOARD_MQTT_PASSWORD", cfg.MQTTPassword) if value := getenv("MORZ_INFOBOARD_STATUS_REPORT_EVERY", ""); value != "" { var parsed int _, _ = fmt.Sscanf(value, "%d", &parsed) diff --git a/player/agent/internal/mqttheartbeat/heartbeat.go b/player/agent/internal/mqttheartbeat/heartbeat.go index 65a16f8..abb58c3 100644 --- a/player/agent/internal/mqttheartbeat/heartbeat.go +++ b/player/agent/internal/mqttheartbeat/heartbeat.go @@ -25,10 +25,11 @@ type Publisher struct { } // New creates a Publisher and initiates a non-blocking connection to broker. +// username and password may be empty if the broker requires no authentication. // paho retries the connection in the background if the broker is unreachable // at startup, so New always succeeds. Publish calls will return errors until // the connection is established. -func New(broker, screenID string) *Publisher { +func New(broker, screenID, username, password string) *Publisher { opts := mqtt.NewClientOptions(). AddBroker(broker). SetClientID("morz-agent-" + screenID). @@ -37,6 +38,11 @@ func New(broker, screenID string) *Publisher { SetConnectRetry(true). SetConnectRetryInterval(10 * time.Second) + if username != "" { + opts.SetUsername(username) + opts.SetPassword(password) + } + client := mqtt.NewClient(opts) client.Connect() // non-blocking; paho retries in background return &Publisher{client: client, screenID: screenID}