mystreamdeck/internal/button.go
2020-10-04 15:28:04 -05:00

146 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)
}
}()
}