73 lines
1.6 KiB
Go
73 lines
1.6 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
"time"
|
|
|
|
"example.com/mqtt5-learning/internal/config"
|
|
"example.com/mqtt5-learning/internal/mqtt"
|
|
)
|
|
|
|
func main() {
|
|
if err := run(); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func run() error {
|
|
cfg, err := config.Load(os.Args[1:])
|
|
if err != nil {
|
|
return fmt.Errorf("failed to load config: %w", err)
|
|
}
|
|
|
|
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
|
defer stop()
|
|
|
|
base := "lab/v1/devices/" + cfg.MQTT.DeviceID
|
|
inbox := make(chan mqtt.Message, 16)
|
|
|
|
manager, err := mqtt.Start(ctx, cfg, []string{base + "/telemetry", base + "/responses"}, inbox)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to start MQTT client: %w", err)
|
|
}
|
|
defer mqtt.Stop(manager)
|
|
|
|
ticker := time.NewTicker(10 * time.Second)
|
|
defer ticker.Stop()
|
|
|
|
runID := time.Now().UnixNano()
|
|
sequence := 0
|
|
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
log.Print("shutting down")
|
|
return nil
|
|
case msg := <-inbox:
|
|
log.Printf("received message on topic %s retained=%t payload=%s", msg.Topic, msg.Retain, string(msg.Payload))
|
|
|
|
case <-ticker.C:
|
|
sequence++
|
|
payload, err := json.Marshal(struct {
|
|
ID string `json:"id"`
|
|
Command string `json:"command"`
|
|
}{
|
|
ID: fmt.Sprintf("ping-%d-%d", runID, sequence), Command: "ping",
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to marshal payload: %w", err)
|
|
}
|
|
if err := mqtt.Publish(ctx, manager, base+"/commands", payload); err != nil {
|
|
log.Printf("command publication failed or outcome uncertain: %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|