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
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
|
|
}
|
|
|