Skip to content

Commit

Permalink
Sync initial state on startup
Browse files Browse the repository at this point in the history
  • Loading branch information
dansimau committed Jan 4, 2025
1 parent 3d4d060 commit fae5f74
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 3 deletions.
35 changes: 34 additions & 1 deletion connection.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package hal

import (
"fmt"
"log/slog"
"sync"
"time"
Expand Down Expand Up @@ -96,7 +97,39 @@ func (h *Connection) Start() error {
return err
}

return h.HomeAssistant().SubscribeEvents(string(hassws.MessageTypeStateChanged), h.StateChangeEvent)
if err := h.HomeAssistant().SubscribeEvents(string(hassws.MessageTypeStateChanged), h.StateChangeEvent); err != nil {
return fmt.Errorf("failed to subscribe to state changed events: %w", err)
}

if err := h.syncStates(); err != nil {
return fmt.Errorf("failed to sync initial states: %w", err)
}

return nil
}

func (h *Connection) syncStates() error {
defer perf.Timer(func(timeTaken time.Duration) {
slog.Info("Initial state sync complete", "duration", timeTaken)
})()

states, err := h.HomeAssistant().GetStates()
if err != nil {
return err
}

for _, state := range states {
entity, ok := h.entities[state.EntityID]
if !ok {
continue
}

slog.Debug("Setting initial state", "EntityID", state.EntityID, "State", state)

entity.SetState(state)
}

return nil
}

// Process incoming state change events. Dispatch state change to the relevant
Expand Down
38 changes: 37 additions & 1 deletion hassws/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"sync/atomic"
"time"

"github.com/dansimau/hal/homeassistant"
"github.com/gorilla/websocket"
)

Expand Down Expand Up @@ -116,7 +117,7 @@ func (c *Client) Connect() error {

// Listen for messages from the websocket and dispatch to listener channels.
func (c *Client) listen() {
slog.Info("Connection established, listening for state changes")
slog.Info("Connection established")

for {
_, msgBytes, err := c.conn.ReadMessage()
Expand Down Expand Up @@ -311,6 +312,8 @@ func (c *Client) SubscribeEvents(eventType string, handler func(EventMessage)) e
}
}(responseChan)

slog.Info("Listening for state changes")

return nil
}

Expand All @@ -336,3 +339,36 @@ func (c *Client) CallService(msg CallServiceRequest) (CallServiceResponse, error

return resp, nil
}

func (c *Client) GetStates() ([]homeassistant.State, error) {
msg := CommandMessage{
ID: c.nextMsgID(),
Type: MessageTypeGetStates,
}

reqBytes, err := json.Marshal(msg)
if err != nil {
return nil, err
}

resBytes, err := c.sendMessageWaitResponse(reqBytes)
if err != nil {
return nil, err
}

var resp CommandResponse
if err := json.Unmarshal(resBytes, &resp); err != nil {
return nil, err
}

if !resp.Success {
return nil, fmt.Errorf("%w: %s", ErrUnexpectedResponse, resp.Error)
}

var states []homeassistant.State
if err := json.Unmarshal(resp.Result, &states); err != nil {
return nil, err
}

return states, nil
}
14 changes: 13 additions & 1 deletion hassws/message_types.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
package hassws

import "github.com/dansimau/hal/homeassistant"
import (
"encoding/json"

"github.com/dansimau/hal/homeassistant"
)

const (
MessageTypeAuthChallenge MessageType = "auth_challenge"
MessageTypeAuthRequest MessageType = "auth_request"
MessageTypeAuthResponse MessageType = "auth_response"
MessageTypeCallService MessageType = "call_service"
MessageTypeEvent MessageType = "event"
MessageTypeGetStates MessageType = "get_states"
MessageTypeResult MessageType = "result"
MessageTypeStateChanged MessageType = "state_changed"
MessageTypeSubscribeEvents MessageType = "subscribe_events"
Expand All @@ -20,6 +25,13 @@ type CommandMessage struct {
Type MessageType `json:"type"`
}

type CommandResponse struct {
Type MessageType `json:"type"`
Success bool `json:"success"`
Result json.RawMessage `json:"result,omitempty"`
Error json.RawMessage `json:"error,omitempty"`
}

type AuthChallenge struct {
Type string `json:"type"`
HAVersion string `json:"ha_version,omitempty"`
Expand Down

0 comments on commit fae5f74

Please sign in to comment.