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 <noreply@anthropic.com>
This commit is contained in:
Jesko Anschütz 2026-03-22 21:00:15 +01:00
parent d0137179e5
commit 1dbebc0a2b
3 changed files with 12 additions and 2 deletions

View file

@ -75,7 +75,7 @@ func New() (*App, error) {
var mqttPub mqttSender var mqttPub mqttSender
if cfg.MQTTBroker != "" { 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) logger.Printf("event=mqtt_enabled broker=%s", cfg.MQTTBroker)
} else { } else {
logger.Printf("event=mqtt_disabled reason=no_broker_configured") logger.Printf("event=mqtt_disabled reason=no_broker_configured")

View file

@ -10,6 +10,8 @@ type Config struct {
ScreenID string `json:"screen_id"` ScreenID string `json:"screen_id"`
ServerBaseURL string `json:"server_base_url"` ServerBaseURL string `json:"server_base_url"`
MQTTBroker string `json:"mqtt_broker"` MQTTBroker string `json:"mqtt_broker"`
MQTTUsername string `json:"mqtt_username"`
MQTTPassword string `json:"mqtt_password"`
HeartbeatEvery int `json:"heartbeat_every_seconds"` HeartbeatEvery int `json:"heartbeat_every_seconds"`
StatusReportEvery int `json:"status_report_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.ScreenID = getenv("MORZ_INFOBOARD_SCREEN_ID", cfg.ScreenID)
cfg.ServerBaseURL = getenv("MORZ_INFOBOARD_SERVER_URL", cfg.ServerBaseURL) cfg.ServerBaseURL = getenv("MORZ_INFOBOARD_SERVER_URL", cfg.ServerBaseURL)
cfg.MQTTBroker = getenv("MORZ_INFOBOARD_MQTT_BROKER", cfg.MQTTBroker) 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 != "" { if value := getenv("MORZ_INFOBOARD_STATUS_REPORT_EVERY", ""); value != "" {
var parsed int var parsed int
_, _ = fmt.Sscanf(value, "%d", &parsed) _, _ = fmt.Sscanf(value, "%d", &parsed)

View file

@ -25,10 +25,11 @@ type Publisher struct {
} }
// New creates a Publisher and initiates a non-blocking connection to broker. // 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 // paho retries the connection in the background if the broker is unreachable
// at startup, so New always succeeds. Publish calls will return errors until // at startup, so New always succeeds. Publish calls will return errors until
// the connection is established. // the connection is established.
func New(broker, screenID string) *Publisher { func New(broker, screenID, username, password string) *Publisher {
opts := mqtt.NewClientOptions(). opts := mqtt.NewClientOptions().
AddBroker(broker). AddBroker(broker).
SetClientID("morz-agent-" + screenID). SetClientID("morz-agent-" + screenID).
@ -37,6 +38,11 @@ func New(broker, screenID string) *Publisher {
SetConnectRetry(true). SetConnectRetry(true).
SetConnectRetryInterval(10 * time.Second) SetConnectRetryInterval(10 * time.Second)
if username != "" {
opts.SetUsername(username)
opts.SetPassword(password)
}
client := mqtt.NewClient(opts) client := mqtt.NewClient(opts)
client.Connect() // non-blocking; paho retries in background client.Connect() // non-blocking; paho retries in background
return &Publisher{client: client, screenID: screenID} return &Publisher{client: client, screenID: screenID}