Added timestamp to presence state and use mqtt instead of channel for overall presence
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
07fa5fc986
commit
c49ee841fd
|
@ -23,6 +23,7 @@ func Connect(config Config) MQTT {
|
||||||
opts.SetDefaultPublishHandler(defaultHandler)
|
opts.SetDefaultPublishHandler(defaultHandler)
|
||||||
opts.SetUsername(config.Username)
|
opts.SetUsername(config.Username)
|
||||||
opts.SetPassword(config.Password)
|
opts.SetPassword(config.Password)
|
||||||
|
opts.SetOrderMatters(false)
|
||||||
|
|
||||||
client := mqtt.NewClient(opts)
|
client := mqtt.NewClient(opts)
|
||||||
if token := client.Connect(); token.Wait() && token.Error() != nil {
|
if token := client.Connect(); token.Wait() && token.Error() != nil {
|
||||||
|
|
46
main.go
46
main.go
|
@ -7,6 +7,7 @@ import (
|
||||||
"automation/integration/mqtt"
|
"automation/integration/mqtt"
|
||||||
"automation/integration/ntfy"
|
"automation/integration/ntfy"
|
||||||
"automation/presence"
|
"automation/presence"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -16,6 +17,8 @@ import (
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
"github.com/kelseyhightower/envconfig"
|
"github.com/kelseyhightower/envconfig"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
|
paho "github.com/eclipse/paho.mqtt.golang"
|
||||||
)
|
)
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
|
@ -138,11 +141,7 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ntfy.sh
|
// ntfy.sh
|
||||||
n := ntfy.Connect(config.NTFY)
|
// n := ntfy.Connect(config.NTFY)
|
||||||
|
|
||||||
// Presence
|
|
||||||
p := presence.New()
|
|
||||||
m.AddHandler("automation/presence/+", p.PresenceHandler)
|
|
||||||
|
|
||||||
// Devices that we control and expose to google home
|
// Devices that we control and expose to google home
|
||||||
provider := device.NewProvider(config.Google, &m)
|
provider := device.NewProvider(config.Google, &m)
|
||||||
|
@ -154,20 +153,30 @@ func main() {
|
||||||
provider.AddDevice(device.NewComputer(info.MACAddress, name, info.Room, info.Url))
|
provider.AddDevice(device.NewComputer(info.MACAddress, name, info.Room, info.Url))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event loop
|
// Presence
|
||||||
go func() {
|
p := presence.New()
|
||||||
fmt.Println("Starting event loop")
|
m.AddHandler("automation/presence/+", p.PresenceHandler)
|
||||||
for {
|
|
||||||
select {
|
m.AddHandler("automation/presence", func(client paho.Client, msg paho.Message) {
|
||||||
case present := <-p.Presence:
|
if len(msg.Payload()) == 0 {
|
||||||
fmt.Printf("Presence: %t\n", present)
|
// In this case we clear the persistent message
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var message presence.Message
|
||||||
|
err := json.Unmarshal(msg.Payload(), &message)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Presence: %t\n", message.State)
|
||||||
// Notify users of presence update
|
// Notify users of presence update
|
||||||
n.Presence(present)
|
// n.Presence(present)
|
||||||
|
|
||||||
// Set presence on the hue bridge
|
// Set presence on the hue bridge
|
||||||
h.SetFlag(41, present)
|
h.SetFlag(41, message.State)
|
||||||
|
|
||||||
if !present {
|
if !message.State {
|
||||||
// Turn off all the devices that we manage ourselves
|
// Turn off all the devices that we manage ourselves
|
||||||
provider.TurnAllOff()
|
provider.TurnAllOff()
|
||||||
|
|
||||||
|
@ -185,12 +194,7 @@ func main() {
|
||||||
} else {
|
} else {
|
||||||
// @TODO Turn on the nest thermostat again
|
// @TODO Turn on the nest thermostat again
|
||||||
}
|
}
|
||||||
|
})
|
||||||
case <-h.Events:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
addr := ":8090"
|
addr := ":8090"
|
||||||
srv := http.Server{
|
srv := http.Server{
|
||||||
|
|
|
@ -1,40 +1,48 @@
|
||||||
package presence
|
package presence
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"encoding/json"
|
||||||
"strconv"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
mqtt "github.com/eclipse/paho.mqtt.golang"
|
mqtt "github.com/eclipse/paho.mqtt.golang"
|
||||||
|
"github.com/kr/pretty"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Presence struct {
|
type Presence struct {
|
||||||
Presence chan bool
|
|
||||||
devices map[string]bool
|
devices map[string]bool
|
||||||
current *bool
|
current *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Message struct {
|
||||||
|
State bool `json:"state"`
|
||||||
|
Updated int64 `json:"updated"`
|
||||||
|
}
|
||||||
|
|
||||||
func New() Presence {
|
func New() Presence {
|
||||||
return Presence{Presence: make(chan bool), devices: make(map[string]bool), current: nil}
|
return Presence{devices: make(map[string]bool), current: nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler got automation/presence/+
|
// Handler got automation/presence/+
|
||||||
func (p *Presence) PresenceHandler(client mqtt.Client, msg mqtt.Message) {
|
func (p *Presence) PresenceHandler(client mqtt.Client, msg mqtt.Message) {
|
||||||
name := strings.Split(msg.Topic(), "/")[2]
|
name := strings.Split(msg.Topic(), "/")[2]
|
||||||
|
|
||||||
if len(msg.Payload()) == 0 {
|
if len(msg.Payload()) == 0 {
|
||||||
// @TODO What happens if we delete a device that does not exist
|
|
||||||
delete(p.devices, name)
|
delete(p.devices, name)
|
||||||
} else {
|
} else {
|
||||||
value, err := strconv.Atoi(string(msg.Payload()))
|
var message Message
|
||||||
|
err := json.Unmarshal(msg.Payload(), &message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
log.Println(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
p.devices[name] = value == 1
|
p.devices[name] = message.State
|
||||||
}
|
}
|
||||||
|
|
||||||
present := false
|
present := false
|
||||||
fmt.Println(p.devices)
|
pretty.Println(p.devices)
|
||||||
for _, value := range p.devices {
|
for _, value := range p.devices {
|
||||||
if value {
|
if value {
|
||||||
present = true
|
present = true
|
||||||
|
@ -42,9 +50,23 @@ func (p *Presence) PresenceHandler(client mqtt.Client, msg mqtt.Message) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Println(present)
|
||||||
|
|
||||||
if p.current == nil || *p.current != present {
|
if p.current == nil || *p.current != present {
|
||||||
p.current = &present
|
p.current = &present
|
||||||
p.Presence <- present
|
|
||||||
|
msg, err := json.Marshal(Message{
|
||||||
|
State: present,
|
||||||
|
Updated: time.Now().UnixMilli(),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
token := client.Publish("automation/presence", 1, true, msg)
|
||||||
|
if token.Wait() && token.Error() != nil {
|
||||||
|
log.Println(token.Error())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in New Issue
Block a user