diff --git a/automation/automation.go b/automation/automation.go index d6d3d9c..363c830 100644 --- a/automation/automation.go +++ b/automation/automation.go @@ -4,6 +4,7 @@ import ( "automation/home" "automation/integration/hue" "automation/integration/ntfy" + "automation/presence" "encoding/json" "log" @@ -35,9 +36,10 @@ func on[M any](client paho.Client, topic string, onMessage func(message M)) { } } -func RegisterAutomations(client paho.Client, prefix string, hue *hue.Hue, notify *ntfy.Notify, home *home.Home) { +func RegisterAutomations(client paho.Client, prefix string, hue *hue.Hue, notify *ntfy.Notify, home *home.Home, presence *presence.Presence) { presenceAutomation(client, hue, notify, home) mixerAutomation(client, prefix, home) kettleAutomation(client, prefix, home) darknessAutomation(client, hue) + frontdoorAutomation(client, prefix, presence) } diff --git a/automation/frontdoor.go b/automation/frontdoor.go new file mode 100644 index 0000000..7e052c3 --- /dev/null +++ b/automation/frontdoor.go @@ -0,0 +1,56 @@ +package automation + +import ( + "automation/presence" + "encoding/json" + "fmt" + "log" + "time" + + paho "github.com/eclipse/paho.mqtt.golang" +) + +type Message struct { + Contact bool `json:"contact"` +} + +func frontdoorAutomation(client paho.Client, prefix string, p *presence.Presence) { + const length = 15 * time.Minute + + timer := time.NewTimer(length) + timer.Stop() + + on(client, fmt.Sprintf("%s/hallway/frontdoor", prefix), func(message Message) { + // Always reset the timer if the door is opened + if !message.Contact { + timer.Reset(length) + } + + // If the door opens an there is no one home + if !message.Contact && !p.Current() { + payload, err := json.Marshal(presence.Message{ + State: true, + Updated: time.Now().UnixMilli(), + }) + if err != nil { + log.Println(err) + } + + token := client.Publish("automation/presence/frontdoor", 1, false, payload) + if token.Wait() && token.Error() != nil { + log.Println(token.Error()) + } + } + }) + + go func() { + for { + <-timer.C + // Clear out the value + token := client.Publish("automation/presence/frontdoor", 1, false, "") + if token.Wait() && token.Error() != nil { + log.Println(token.Error()) + } + } + }() +} diff --git a/automation/kettle.go b/automation/kettle.go index 36fefdd..dac6007 100644 --- a/automation/kettle.go +++ b/automation/kettle.go @@ -16,6 +16,7 @@ func kettleAutomation(client paho.Client, prefix string, home *home.Home) { const length = 5 * time.Minute timer := time.NewTimer(length) + timer.Stop() on(client, fmt.Sprintf("%s/%s", prefix, name), func(message zigbee.OnOffState) { if message.State { diff --git a/automation/presence.go b/automation/presence.go index 06e02d0..0fff779 100644 --- a/automation/presence.go +++ b/automation/presence.go @@ -6,7 +6,6 @@ import ( "automation/integration/hue" "automation/integration/ntfy" "automation/presence" - "fmt" "log" paho "github.com/eclipse/paho.mqtt.golang" @@ -14,7 +13,7 @@ import ( func presenceAutomation(client paho.Client, hue *hue.Hue, notify *ntfy.Notify, home *home.Home) { on(client, "automation/presence", func(message presence.Message) { - fmt.Printf("Presence: %t\n", message.State) + log.Printf("Presence changed: %t\n", message.State) // Set presence on the hue bridge hue.SetFlag(41, message.State) diff --git a/main.go b/main.go index 02ce89f..8077ed4 100644 --- a/main.go +++ b/main.go @@ -65,7 +65,7 @@ func main() { } defer automationClient.Disconnect(250) - automation.RegisterAutomations(automationClient, cfg.Zigbee.MQTTPrefix, hue, notify, home) + automation.RegisterAutomations(automationClient, cfg.Zigbee.MQTTPrefix, hue, notify, home, p) addr := ":8090" srv := http.Server{ diff --git a/presence/presence.go b/presence/presence.go index 96619ff..47346dd 100644 --- a/presence/presence.go +++ b/presence/presence.go @@ -23,6 +23,10 @@ type Message struct { Updated int64 `json:"updated"` } +func (p *Presence) Current() bool { + return p.presence +} + func (p *Presence) devicePresenceHandler(client paho.Client, msg paho.Message) { name := strings.Split(msg.Topic(), "/")[2] @@ -48,8 +52,6 @@ func (p *Presence) devicePresenceHandler(client paho.Client, msg paho.Message) { } } - log.Printf("Setting overall presence: %t\n", present) - if p.presence != present { p.presence = present