Skip to content

Commit

Permalink
Add support for hal.yaml config file
Browse files Browse the repository at this point in the history
  • Loading branch information
dansimau committed Dec 9, 2024
1 parent 1eab652 commit d183b6c
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 9 deletions.
7 changes: 7 additions & 0 deletions automations.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
package hal

type Automation interface {
// Name is a friendly name for the automation, used in logs and stats.
Name() string

// Entities should return a list of entities that this automation should
// listen on. For every state change to one of these entities, the
// automation will be trigged.
Entities() Entities

// Action is called when the automation is triggered.
Action()
}
4 changes: 2 additions & 2 deletions automations/sensor_lights.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"github.com/dansimau/hal"
)

// SensorsTriggerLights is an automation that combines one or more sensors (
// motion or presence sensors) and a set of lights. Lights are turned on when
// SensorsTriggerLights is an automation that combines one or more sensors
// (motion or presence sensors) and a set of lights. Lights are turned on when
// any of the sensors are triggered and turned off after a given duration.
type SensorsTriggerLights struct {
name string
Expand Down
77 changes: 77 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package hal

import (
"os"
"path/filepath"

"gopkg.in/yaml.v3"
)

const configFilename = "hal.yaml"

type Config struct {
HomeAssistant HomeAssistantConfig `yaml:"homeAssistant"`
}

type HomeAssistantConfig struct {
Host string `yaml:"host"`
Token string `yaml:"token"`
}

func LoadConfig() (*Config, error) {
configPath, err := searchParentsForFileFromCwd(configFilename)
if err != nil {
return nil, err
}

yamlBytes, err := os.ReadFile(configPath)
if err != nil {
return nil, err
}

config := Config{}
if err := yaml.Unmarshal(yamlBytes, &config); err != nil {
return nil, err
}

return &config, nil
}

func searchParentsForFile(filename, searchPath string) (path string, err error) {
for _, path := range getParents(searchPath) {
f := filepath.Join(path, filename)
if fileExists(f) {
return f, nil
}
}

return "", nil
}

func searchParentsForFileFromCwd(filename string) (path string, err error) {
wd, err := os.Getwd()
if err != nil {
return "", err
}

return searchParentsForFile(filename, wd)
}

func getParents(basePath string) (paths []string) {
root := basePath

for root != "/" {
paths = append(paths, root)
root = filepath.Dir(root)
}

paths = append(paths, "/")

return paths
}

func fileExists(path string) bool {
_, err := os.Stat(path)

return !os.IsNotExist(err)
}
12 changes: 10 additions & 2 deletions connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ import (
// listens for state updates and invokes automations when state changes are detected.
// TODO: Rename "Connection" to something more descriptive.
type Connection struct {
homeAssistant *hassws.Client
config Config

automations map[string][]Automation
entities map[string]EntityLike

// Lock to serialize state updates and ensure automations fire in order.
mutex sync.RWMutex

homeAssistant *hassws.Client
}

// ConnectionBinder is an interface that can be implemented by entities to bind
Expand All @@ -29,8 +31,14 @@ type ConnectionBinder interface {
BindConnection(connection *Connection)
}

func NewConnection(api *hassws.Client) *Connection {
func NewConnection(cfg Config) *Connection {
api := hassws.NewClient(hassws.ClientConfig{
Host: cfg.HomeAssistant.Host,
Token: cfg.HomeAssistant.Token,
})

return &Connection{
config: cfg,
homeAssistant: api,

automations: make(map[string][]Automation),
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require github.com/davecgh/go-spew v1.1.1

require (
github.com/gorilla/websocket v1.5.3
gopkg.in/yaml.v3 v3.0.1
gotest.tools/v3 v3.5.1
)

Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,9 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
2 changes: 1 addition & 1 deletion hassws/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ type ClientConfig struct {
Token string
}

func NewWebsocketAPI(config ClientConfig) *Client {
func NewClient(config ClientConfig) *Client {
return &Client{
cfg: config,
responses: make(map[int]chan []byte),
Expand Down
9 changes: 5 additions & 4 deletions testutil/testutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ func NewClientServer(t *testing.T) (*hal.Connection, *hassws.Server, func()) {
assert.NilError(t, err)

// Create client and connection
client := hassws.NewWebsocketAPI(hassws.ClientConfig{
Host: server.ListenAddress(),
Token: "test-token",
conn := hal.NewConnection(hal.Config{
HomeAssistant: hal.HomeAssistantConfig{
Host: server.ListenAddress(),
Token: "test-token",
},
})
conn := hal.NewConnection(client)

// Create test entity and register it
entity := hal.NewEntity("test.entity")
Expand Down

0 comments on commit d183b6c

Please sign in to comment.