diff --git a/.gitignore b/.gitignore index 6095c33..65f5c4f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ cover.out -sqlite.db +sqlite.db* diff --git a/automations/sensor_lights_test.go b/automations/sensor_lights_test.go index 395c4f8..82d0ea6 100644 --- a/automations/sensor_lights_test.go +++ b/automations/sensor_lights_test.go @@ -41,7 +41,8 @@ func TestSensorTurnOnTurnOff(t *testing.T) { // Trigger motion sensor slog.Info("Test: Triggering motion sensor") - server.SendStateChangeEvent(homeassistant.Event{ + server.SendEvent(homeassistant.Event{ + EventType: "state_changed", EventData: homeassistant.EventData{ EntityID: testSensor.GetID(), NewState: &homeassistant.State{ @@ -60,7 +61,8 @@ func TestSensorTurnOnTurnOff(t *testing.T) { // Clear motion sensor slog.Info("Test: Clearing motion sensor") - server.SendStateChangeEvent(homeassistant.Event{ + server.SendEvent(homeassistant.Event{ + EventType: "state_changed", EventData: homeassistant.EventData{ EntityID: testSensor.GetID(), NewState: &homeassistant.State{ @@ -117,7 +119,8 @@ func TestSensorTurnOnTurnOffWithDimming(t *testing.T) { // Trigger motion sensor slog.Info("Test: Triggering motion sensor") - server.SendStateChangeEvent(homeassistant.Event{ + server.SendEvent(homeassistant.Event{ + EventType: "state_changed", EventData: homeassistant.EventData{ EntityID: testSensor.GetID(), NewState: &homeassistant.State{ @@ -136,7 +139,8 @@ func TestSensorTurnOnTurnOffWithDimming(t *testing.T) { // Clear motion sensor slog.Info("Test: Clearing motion sensor") - server.SendStateChangeEvent(homeassistant.Event{ + server.SendEvent(homeassistant.Event{ + EventType: "state_changed", EventData: homeassistant.EventData{ EntityID: testSensor.GetID(), NewState: &homeassistant.State{ @@ -203,7 +207,8 @@ func TestSensorLightsTurnOnAfterDimming(t *testing.T) { // Trigger motion sensor slog.Info("Test: Triggering motion sensor") - server.SendStateChangeEvent(homeassistant.Event{ + server.SendEvent(homeassistant.Event{ + EventType: "state_changed", EventData: homeassistant.EventData{ EntityID: testSensor.GetID(), NewState: &homeassistant.State{ @@ -222,7 +227,8 @@ func TestSensorLightsTurnOnAfterDimming(t *testing.T) { // Clear motion sensor slog.Info("Test: Clearing motion sensor") - server.SendStateChangeEvent(homeassistant.Event{ + server.SendEvent(homeassistant.Event{ + EventType: "state_changed", EventData: homeassistant.EventData{ EntityID: testSensor.GetID(), NewState: &homeassistant.State{ @@ -250,7 +256,8 @@ func TestSensorLightsTurnOnAfterDimming(t *testing.T) { // Trigger motion sensor again slog.Info("Test: Triggering motion sensor again") - server.SendStateChangeEvent(homeassistant.Event{ + server.SendEvent(homeassistant.Event{ + EventType: "state_changed", EventData: homeassistant.EventData{ EntityID: testSensor.GetID(), NewState: &homeassistant.State{ @@ -299,7 +306,8 @@ func TestSensorDoesntOverrideManuallySetBrightness(t *testing.T) { // Trigger motion sensor slog.Info("Test: Triggering motion sensor") - server.SendStateChangeEvent(homeassistant.Event{ + server.SendEvent(homeassistant.Event{ + EventType: "state_changed", EventData: homeassistant.EventData{ EntityID: testSensor.GetID(), NewState: &homeassistant.State{ @@ -318,7 +326,8 @@ func TestSensorDoesntOverrideManuallySetBrightness(t *testing.T) { // Light was dimmed manually slog.Info("Test: Dimming light manually") - server.SendStateChangeEvent(homeassistant.Event{ + server.SendEvent(homeassistant.Event{ + EventType: "state_changed", EventData: homeassistant.EventData{ EntityID: testLight.GetID(), NewState: &homeassistant.State{ @@ -333,7 +342,8 @@ func TestSensorDoesntOverrideManuallySetBrightness(t *testing.T) { // Trigger motion sensor slog.Info("Test: Triggering motion sensor again") - server.SendStateChangeEvent(homeassistant.Event{ + server.SendEvent(homeassistant.Event{ + EventType: "state_changed", EventData: homeassistant.EventData{ EntityID: testSensor.GetID(), NewState: &homeassistant.State{ @@ -390,7 +400,8 @@ func TestHumanOverride(t *testing.T) { // Trigger motion sensor slog.Info("Test: Triggering motion sensor") - server.SendStateChangeEvent(homeassistant.Event{ + server.SendEvent(homeassistant.Event{ + EventType: "state_changed", EventData: homeassistant.EventData{ EntityID: testSensor.GetID(), NewState: &homeassistant.State{ @@ -409,7 +420,8 @@ func TestHumanOverride(t *testing.T) { // Human presses button manually, triggering human override slog.Info("Test: Light set manually") - server.SendStateChangeEvent(homeassistant.Event{ + server.SendEvent(homeassistant.Event{ + EventType: "state_changed", EventData: homeassistant.EventData{ EntityID: testLight.GetID(), NewState: &homeassistant.State{ @@ -421,7 +433,8 @@ func TestHumanOverride(t *testing.T) { // Motion sensor is cleared, but it should be ignored because of human override slog.Info("Test: Clearing motion sensor") - server.SendStateChangeEvent(homeassistant.Event{ + server.SendEvent(homeassistant.Event{ + EventType: "state_changed", EventData: homeassistant.EventData{ EntityID: testSensor.GetID(), NewState: &homeassistant.State{ @@ -454,7 +467,8 @@ func TestHumanOverride(t *testing.T) { // Trigger motion sensor is triggered and cleared again slog.Info("Test: Triggering motion sensor") - server.SendStateChangeEvent(homeassistant.Event{ + server.SendEvent(homeassistant.Event{ + EventType: "state_changed", EventData: homeassistant.EventData{ EntityID: testSensor.GetID(), NewState: &homeassistant.State{ @@ -471,7 +485,8 @@ func TestHumanOverride(t *testing.T) { }) slog.Info("Test: Clearing motion sensor") - server.SendStateChangeEvent(homeassistant.Event{ + server.SendEvent(homeassistant.Event{ + EventType: "state_changed", EventData: homeassistant.EventData{ EntityID: testSensor.GetID(), NewState: &homeassistant.State{ diff --git a/connection.go b/connection.go index 6d4f713..5f62e53 100644 --- a/connection.go +++ b/connection.go @@ -176,8 +176,8 @@ func (h *Connection) StateChangeEvent(event hassws.EventMessage) { }) // Prevent loops by not running automations that originate from hal - if event.Context.UserID == h.config.HomeAssistant.UserID { - slog.Debug("Skipping automation to prevent loop", "EntityID", event.Event.EventData.EntityID) + if event.Event.Context.UserID == h.config.HomeAssistant.UserID { + slog.Debug("Skipping automation from own action", "EntityID", event.Event.EventData.EntityID) return } diff --git a/connection_test.go b/connection_test.go index 4285d1a..bd66c17 100644 --- a/connection_test.go +++ b/connection_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/dansimau/hal" - "github.com/dansimau/hal/hassws" "github.com/dansimau/hal/homeassistant" "github.com/dansimau/hal/testutil" "github.com/davecgh/go-spew/spew" @@ -22,7 +21,8 @@ func TestConnection(t *testing.T) { conn.RegisterEntities(entity) // Send state change event - server.SendStateChangeEvent(homeassistant.Event{ + server.SendEvent(homeassistant.Event{ + EventType: "state_changed", EventData: homeassistant.EventData{ EntityID: "test.entity", NewState: &homeassistant.State{State: "on"}, @@ -57,17 +57,20 @@ func TestLoopProtection(t *testing.T) { ) // This one should be ignored because it is from the same user - server.SendStateChangeEventWithContext(homeassistant.Event{ + server.SendEvent(homeassistant.Event{ + EventType: "state_changed", EventData: homeassistant.EventData{ EntityID: "test.entity", NewState: &homeassistant.State{State: "off"}, }, - }, hassws.EventMessageContext{ - UserID: testutil.TestUserID, + Context: homeassistant.EventMessageContext{ + UserID: testutil.TestUserID, + }, }) // This one should cause the automation to be triggered - server.SendStateChangeEvent(homeassistant.Event{ + server.SendEvent(homeassistant.Event{ + EventType: "state_changed", EventData: homeassistant.EventData{ EntityID: "test.entity", NewState: &homeassistant.State{State: "on"}, diff --git a/hassws/message_types.go b/hassws/message_types.go index 79a53e1..eb3d881 100644 --- a/hassws/message_types.go +++ b/hassws/message_types.go @@ -50,19 +50,9 @@ type AuthResponse struct { } type EventMessage struct { - ID int `json:"id"` - Type MessageType `json:"type"` // "event" - Event homeassistant.Event `json:"event"` - EventType MessageType `json:"event_type"` - TimeFired string `json:"time_fired"` - Origin string `json:"origin"` - Context EventMessageContext `json:"context"` -} - -type EventMessageContext struct { - ID string `json:"id"` - ParentID string `json:"parent_id"` - UserID string `json:"user_id"` + ID int `json:"id"` + Type MessageType `json:"type"` // "event" + Event homeassistant.Event `json:"event"` } type subscribeEventsRequest struct { diff --git a/hassws/server.go b/hassws/server.go index 35f8690..21461f4 100644 --- a/hassws/server.go +++ b/hassws/server.go @@ -146,7 +146,7 @@ func (s *Server) listen() { // Generate state updates for _, entityID := range entityIDs { - s.SendStateChangeEvent(homeassistant.Event{ + s.SendEvent(homeassistant.Event{ EventData: homeassistant.EventData{ EntityID: entityID, NewState: &homeassistant.State{ @@ -265,27 +265,13 @@ func (s *Server) MessagesSent() [][]byte { return s.messagesSent } -// SendStateChangeEvent sends a state change event to the server. -func (s *Server) SendStateChangeEvent(event homeassistant.Event) { +// SendEvent sends a state change event to the server. +func (s *Server) SendEvent(event homeassistant.Event) { for _, id := range s.subscribers { s.SendMessage(EventMessage{ - ID: id, - Type: MessageTypeEvent, - EventType: MessageTypeStateChanged, - Event: event, - }) - } -} - -// SendStateChangeEventWithContext sends a state change event to the server. -func (s *Server) SendStateChangeEventWithContext(event homeassistant.Event, context EventMessageContext) { - for _, id := range s.subscribers { - s.SendMessage(EventMessage{ - ID: id, - Type: MessageTypeEvent, - EventType: MessageTypeStateChanged, - Event: event, - Context: context, + ID: id, + Type: MessageTypeEvent, + Event: event, }) } } diff --git a/homeassistant/events.go b/homeassistant/events.go index 1da0aba..33ae519 100644 --- a/homeassistant/events.go +++ b/homeassistant/events.go @@ -1,7 +1,17 @@ package homeassistant type Event struct { - EventData EventData `json:"data"` + EventData EventData `json:"data"` + EventType string `json:"event_type"` + TimeFired string `json:"time_fired"` + Origin string `json:"origin"` + Context EventMessageContext `json:"context"` +} + +type EventMessageContext struct { + ID string `json:"id"` + ParentID string `json:"parent_id"` + UserID string `json:"user_id"` } type EventData struct {