package main import ( "encoding/json" "log" "mime" "net/http" "sync" mqtt "github.com/eclipse/paho.mqtt.golang" ) type temperature struct { Value float64 `json:"value"` Unit string `json:"unit"` } 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_mutex.Unlock() if err != nil { logger.Print(err) return } } 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("Homeservice: ") } 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 main() { logger.Println("starting") // MQTT connection opts := mqtt.NewClientOptions() opts.AddBroker("tcp://nuc:1883") opts.SetClientID("homeservice") 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) mime.AddExtensionType(".js", "text/javascript; charset=utf-8") mime.AddExtensionType(".css", "text/css; charset=utf-8") // API routes // Serve files from static folder http.Handle("/", http.FileServer(http.Dir("./webui/build"))) http.HandleFunc("/sauna/sample", http_endpoint_sauna) port := ":5000" logger.Println("Server is running on port" + port) // Start server on port specified above logger.Fatal(http.ListenAndServe(port, nil)) }