145 lines
3.4 KiB
Go
145 lines
3.4 KiB
Go
package internal
|
|
|
|
import (
|
|
"encoding/json"
|
|
"log"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/cenkalti/backoff/v4"
|
|
"github.com/jcollie/go-homeassistant"
|
|
"github.com/jcollie/go-streamdeck"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// Button .
|
|
type Button interface {
|
|
InitializeButton()
|
|
StateChange(entityID string, state string)
|
|
ButtonPressed(sd *streamdeck.StreamDeck, x int, y int, timestamp time.Time)
|
|
ButtonReleased(sd *streamdeck.StreamDeck, x int, y int, timestamp time.Time)
|
|
}
|
|
|
|
// ButtonInfo .
|
|
type ButtonInfo struct {
|
|
X int
|
|
Y int
|
|
}
|
|
|
|
var myButtons []Button
|
|
|
|
type eventWatcher struct {
|
|
sync.Mutex
|
|
id uint64
|
|
}
|
|
|
|
var theEventWatcher eventWatcher
|
|
|
|
// StartWatchingEvents .
|
|
func StartWatchingEvents(ha *homeassistant.Connection) error {
|
|
var err error
|
|
|
|
theEventWatcher.Lock()
|
|
defer theEventWatcher.Unlock()
|
|
|
|
if theEventWatcher.id != 0 {
|
|
return errors.Errorf("we already seem to be watching events!")
|
|
}
|
|
|
|
theEventWatcher.id, err = ha.SubscribeToEvents("state_changed", &theEventWatcher)
|
|
if err != nil {
|
|
return errors.Wrap(err, "unable to subscribe to state changed events")
|
|
}
|
|
log.Printf("subscribe to state changed events command sent")
|
|
return nil
|
|
}
|
|
|
|
func (e *eventWatcher) HandleResult(ha *homeassistant.Connection, subscriptionID uint64, success bool, result json.RawMessage) {
|
|
log.Printf("eventwatcher result: %v %s\n", success, string(result))
|
|
}
|
|
|
|
func (e *eventWatcher) HandleEvent(ha *homeassistant.Connection, subscriptionID uint64, origin string, timeFired time.Time, event *homeassistant.Event) {
|
|
// fmt.Printf("%s %s %s\n", origin, event.Data.NewState.EntityID, event.Data.NewState.State)
|
|
for _, m := range myButtons {
|
|
m.StateChange(event.Data.NewState.EntityID, event.Data.NewState.State)
|
|
}
|
|
}
|
|
|
|
func (e *eventWatcher) HandleClose(ha *homeassistant.Connection, id uint64) {
|
|
log.Printf("home assistant closed")
|
|
time.Sleep(5 * time.Second)
|
|
e.id = 0
|
|
go func() {
|
|
err := backoff.Retry(
|
|
func() error {
|
|
log.Printf("attempting to watch events")
|
|
return StartWatchingEvents(ha)
|
|
},
|
|
backoff.NewExponentialBackOff(),
|
|
)
|
|
if err != nil {
|
|
log.Printf("unable to start watching events: %+v", err)
|
|
}
|
|
}()
|
|
}
|
|
|
|
type initializeState struct {
|
|
id uint64
|
|
result chan bool
|
|
}
|
|
|
|
// InitializeState .
|
|
func InitializeState(ha *homeassistant.Connection) error {
|
|
var err error
|
|
var i initializeState
|
|
i.result = make(chan bool)
|
|
i.id, err = ha.GetStates(&i)
|
|
if err != nil {
|
|
return errors.Wrap(err, "unable to initialize state")
|
|
}
|
|
result := <-i.result
|
|
if !result {
|
|
return errors.Errorf("problem intiaizlizing states")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// HandleResult .
|
|
func (i *initializeState) HandleResult(ha *homeassistant.Connection, id uint64, success bool, result json.RawMessage) {
|
|
if !success {
|
|
i.result <- false
|
|
close(i.result)
|
|
return
|
|
}
|
|
var states []homeassistant.State
|
|
err := json.Unmarshal(result, &states)
|
|
if err != nil {
|
|
log.Printf("unable to unmarshall states: %+v", err)
|
|
return
|
|
}
|
|
for _, state := range states {
|
|
for _, m := range myButtons {
|
|
m.StateChange(state.EntityID, state.State)
|
|
}
|
|
}
|
|
i.result <- true
|
|
close(i.result)
|
|
}
|
|
|
|
func (i *initializeState) HandleClose(ha *homeassistant.Connection, id uint64) {
|
|
log.Printf("home assistant closed")
|
|
time.Sleep(5 * time.Second)
|
|
i.id = 0
|
|
go func() {
|
|
err := backoff.Retry(
|
|
func() error {
|
|
log.Printf("attempting to initialize state")
|
|
return InitializeState(ha)
|
|
},
|
|
backoff.NewExponentialBackOff(),
|
|
)
|
|
if err != nil {
|
|
log.Printf("unable to initalize state: %+v", err)
|
|
}
|
|
}()
|
|
}
|