You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

52 lines
1.6 KiB

package sensor
import (
"crypto/rand"
"log/slog"
"time"
mqtt "github.com/eclipse/paho.mqtt.golang"
)
// MQTTConfig selects the broker, sensor topic, and optional broker credentials.
type MQTTConfig struct {
Broker string
Topic string
Username string
Password string
}
// StartMQTT connects in the background, retrying initial failures and reconnecting
// after outages. Every connection subscribes again because sessions are clean.
// The caller must Disconnect the returned client during shutdown.
func StartMQTT(config MQTTConfig, sampler *Sampler, logger *slog.Logger) mqtt.Client {
options := mqtt.NewClientOptions().
AddBroker(config.Broker).
SetClientID("laundry-" + rand.Text()[:12]).
SetUsername(config.Username).
SetPassword(config.Password).
SetAutoReconnect(true).
SetConnectRetry(true).
SetConnectRetryInterval(5 * time.Second).
SetConnectTimeout(5 * time.Second)
options.SetOnConnectHandler(func(client mqtt.Client) {
token := client.Subscribe(config.Topic, 0, func(_ mqtt.Client, message mqtt.Message) {
if err := sampler.Receive(message.Payload()); err != nil {
logger.Warn("Ignoring invalid sensor payload", "error", err)
}
})
if !token.WaitTimeout(10 * time.Second) {
logger.Error("MQTT subscription timed out")
} else if err := token.Error(); err != nil {
logger.Error("MQTT subscription failed", "error", err)
} else {
logger.Info("MQTT sensor subscription ready", "topic", config.Topic)
}
})
options.SetConnectionLostHandler(func(_ mqtt.Client, err error) {
logger.Warn("MQTT connection lost; reconnecting", "error", err)
})
client := mqtt.NewClient(options)
client.Connect()
return client
}