1
0
Fork 0
hats/pkg/homeassistant/rest.go

90 lines
2.2 KiB
Go

package homeassistant
import (
"errors"
"fmt"
"strings"
"sync"
"github.com/go-resty/resty/v2"
)
type RestClient struct {
client *resty.Client
}
func NewRestClient(baseUrl, token string) *RestClient {
client := resty.New().SetBaseURL(baseUrl)
client.SetHeaders(map[string]string{
"Authorization": fmt.Sprintf("Bearer %s", token),
"Accept": "application/json",
})
return &RestClient{
client: client,
}
}
func (c *RestClient) GetState(entityId string) (StateData, error) {
var data StateData
resp, err := c.client.R().SetResult(&data).Get(fmt.Sprintf("api/states/%s", entityId))
if err == nil && !resp.IsSuccess() {
err = fmt.Errorf("%d status code received: %s", resp.StatusCode(), resp.String())
}
return data, err
}
func (c *RestClient) CallService(entityId string, service string, extras ...map[string]any) error {
domain := strings.Split(entityId, ".")[0]
return c.CallServiceManual(domain, entityId, service, extras...)
}
func (c *RestClient) CallServiceManual(domain string, entityId string, service string, extras ...map[string]any) error {
data := map[string]any{
"entity_id": entityId,
}
for _, extra := range extras {
for k, v := range extra {
data[k] = v
}
}
resp, err := c.client.R().SetBody(data).Post(fmt.Sprintf("api/services/%s/%s", domain, service))
if err == nil && !resp.IsSuccess() {
err = fmt.Errorf("%d status code received: %s", resp.StatusCode(), resp.String())
}
return err
}
type CallServiceInput struct {
EntityID string
Service string
Extras map[string]any
}
func (c *RestClient) CallServices(inputs ...*CallServiceInput) error {
errorChannel := make(chan error)
var wg sync.WaitGroup
wg.Add(len(inputs))
go func() {
wg.Wait()
close(errorChannel)
}()
for _, input := range inputs {
go func(input *CallServiceInput) {
defer wg.Done()
err := c.CallService(input.EntityID, input.Service, input.Extras)
if err != nil {
errorChannel <- fmt.Errorf("error calling service %s for %s: %w", input.Service, input.EntityID, err)
}
}(input)
}
returnErrors := []error{}
for err := range errorChannel {
returnErrors = append(returnErrors, err)
}
return errors.Join(returnErrors...)
}