diff --git a/main.go b/main.go index 82e4775..2040523 100644 --- a/main.go +++ b/main.go @@ -20,23 +20,39 @@ var defaultHandler MQTT.MessageHandler = func(client MQTT.Client, msg MQTT.Messa fmt.Printf("MSG: %s\n", msg.Payload()) } -type DeviceStatus struct { - Name string - Present bool -} - // Handler got automation/presence/+ -func presenceHandler(status chan DeviceStatus) func(MQTT.Client, MQTT.Message) { +func presenceHandler(presence chan bool) func(MQTT.Client, MQTT.Message) { + devices := make(map[string]bool) + var current *bool + return func(client MQTT.Client, msg MQTT.Message) { - device := strings.Split(msg.Topic(), "/")[2] - value, err := strconv.Atoi(string(msg.Payload())) - if err != nil { - panic(err) + name := strings.Split(msg.Topic(), "/")[2] + if len(msg.Payload()) == 0 { + // @TODO What happens if we delete a device that does not exist + delete(devices, name) + } else { + value, err := strconv.Atoi(string(msg.Payload())) + if err != nil { + panic(err) + } + + devices[name] = value == 1 } - fmt.Println("presenceHandler", device, value) + present := false + fmt.Println(devices) + for _, value := range devices { + if value { + present = true + break; + } + } + + if current == nil || *current != present { + current = &present + presence <- present + } - status <- DeviceStatus{Name: device, Present: value == 1} } } @@ -67,9 +83,18 @@ func (hue *Hue) updateFlag(id int, value bool) { } } -func main() { - _ = godotenv.Load() +func connectToHue() Hue { + login, _ := os.LookupEnv("HUE_BRIDGE") + // @TODO Discover the bridge here + hue := Hue{ip: "10.0.0.146", login: login} + + // @TODO Make sure we actually are connected here + + return hue +} + +func connectMQTT() MQTT.Client { host, ok := os.LookupEnv("MQTT_HOST") if !ok { host = "localhost" @@ -90,13 +115,6 @@ func main() { if !ok { clientID = "automation" } - login, _ := os.LookupEnv("HUE_BRIDGE") - - halt := make(chan os.Signal, 1) - signal.Notify(halt, os.Interrupt, syscall.SIGTERM) - - // @TODO Discover the bridge here - hue := Hue{ip: "10.0.0.146", login: login} opts := MQTT.NewClientOptions().AddBroker(fmt.Sprintf("%s:%s", host, port)) opts.SetClientID(clientID) @@ -104,19 +122,31 @@ func main() { opts.SetUsername(user) opts.SetPassword(pass) - c := MQTT.NewClient(opts) - if token := c.Connect(); token.Wait() && token.Error() != nil { + client := MQTT.NewClient(opts) + if token := client.Connect(); token.Wait() && token.Error() != nil { panic(token.Error()) } - status := make(chan DeviceStatus, 1) - if token := c.Subscribe("automation/presence/+", 0, presenceHandler(status)); token.Wait() && token.Error() != nil { + return client +} + +func main() { + _ = godotenv.Load() + + // Signals + halt := make(chan os.Signal, 1) + signal.Notify(halt, os.Interrupt, syscall.SIGTERM) + + // MQTT + presence := make(chan bool, 1) + client := connectMQTT() + if token := client.Subscribe("automation/presence/+", 0, presenceHandler(presence)); token.Wait() && token.Error() != nil { fmt.Println(token.Error()) os.Exit(1) } - devices := make(map[string]bool) - isHome := false + // Hue + hue := connectToHue() fmt.Println("Starting event loop") @@ -124,32 +154,11 @@ func main() { events: for { select { - case state := <-status: - // Update the device state - devices[state.Name] = state.Present - - // Check if there is any device home - temp := false - for key, value := range devices { - fmt.Println(key, value) - if value { - temp = true - break; - } - } - - // Only do stuff if the state changes - if temp == isHome { - break - } - isHome = temp - - if isHome { + case present := <-presence: + if present { fmt.Println("Coming home") hue.updateFlag(41, true) } else { - fmt.Println("Leaving home") - hue.updateFlag(41, false) } fmt.Println("Done") @@ -160,10 +169,10 @@ events: } // Cleanup - if token := c.Unsubscribe("automation/presence/+"); token.Wait() && token.Error() != nil { + if token := client.Unsubscribe("automation/presence/+"); token.Wait() && token.Error() != nil { fmt.Println(token.Error()) os.Exit(1) } - c.Disconnect(250) + client.Disconnect(250) }