package sauna import ( "encoding/json" "log" "math/rand" "net/http" "strconv" "sync" "time" mqtt "github.com/eclipse/paho.mqtt.golang" ) type temperature struct { Value float64 `json:"value"` Unit string `json:"unit"` Time time.Time `json:"time"` Valid bool `json:"valid"` } var ( logger log.Logger = *log.Default() sauna_mutex sync.Mutex sauna_temperature = temperature{ Value: 0.0, Unit: "°C", } ) var messagePubHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { logger.Printf("Received message: %s from topic: %s\n", msg.Payload(), msg.Topic()) } var saunaHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { log.Printf("Received message: %s from topic: %s\n", msg.Payload(), msg.Topic()) sauna_mutex.Lock() err := json.Unmarshal(msg.Payload(), &sauna_temperature) sauna_temperature.Time = time.Now() if err != nil { sauna_temperature.Valid = false sauna_mutex.Unlock() logger.Print(err) return } sauna_temperature.Valid = true sauna_mutex.Unlock() } var connectHandler mqtt.OnConnectHandler = func(client mqtt.Client) { logger.Println("Connected") } var connectLostHandler mqtt.ConnectionLostHandler = func(client mqtt.Client, err error) { logger.Printf("Connect lost: %v", err) } func init() { logger.SetPrefix("apiservice/sauna: ") } func http_endpoint_sauna(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-type", "application/json; charset=utf-8;") if r.Method == http.MethodGet { sauna_mutex.Lock() data, err := json.Marshal(sauna_temperature) sauna_mutex.Unlock() if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write(json.RawMessage(`{"error": "cannot marshal object to json"}`)) } else { w.WriteHeader(http.StatusOK) w.Write(data) } } else { w.WriteHeader(http.StatusMethodNotAllowed) } } func Start() { // MQTT connection opts := mqtt.NewClientOptions() opts.AddBroker("tcp://nuc:1883") opts.SetClientID("apiservice/sauna/" + strconv.Itoa(rand.Int())) opts.SetDefaultPublishHandler(messagePubHandler) opts.OnConnect = connectHandler opts.OnConnectionLost = connectLostHandler client := mqtt.NewClient(opts) if token := client.Connect(); token.Wait() && token.Error() != nil { panic(token.Error()) } // MQTT subscribtion topic := "sauna/temperature" token := client.Subscribe(topic, 1, saunaHandler) token.Wait() logger.Printf("Subscribed to topic %s", topic) http.HandleFunc("/api/sauna", http_endpoint_sauna) }