/
config.go
140 lines (121 loc) · 3.3 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Copyright (c) 2023 Joshua Rich <joshua.rich@gmail.com>
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
package hass
import (
"bytes"
"context"
"encoding/json"
"fmt"
"sync"
"github.com/joshuar/go-hass-agent/internal/request"
"github.com/perimeterx/marshmallow"
"github.com/rs/zerolog/log"
)
const (
websocketPath = "/api/websocket"
webHookPath = "/api/webhook/"
)
type HassConfig struct {
rawConfigProps map[string]interface{}
hassConfigProps
mu sync.Mutex
}
type hassConfigProps struct {
Entities map[string]map[string]interface{} `json:"entities"`
UnitSystem struct {
Length string `json:"length"`
Mass string `json:"mass"`
Temperature string `json:"temperature"`
Volume string `json:"volume"`
} `json:"unit_system"`
ConfigDir string `json:"config_dir"`
LocationName string `json:"location_name"`
TimeZone string `json:"time_zone"`
Version string `json:"version"`
Components []string `json:"components"`
WhitelistExternalDirs []string `json:"whitelist_external_dirs"`
Elevation int `json:"elevation"`
Latitude float64 `json:"latitude"`
Longitude float64 `json:"longitude"`
}
func NewHassConfig(ctx context.Context) *HassConfig {
c := &HassConfig{}
if err := c.Refresh(ctx); err != nil {
log.Debug().Err(err).
Msg("Could not fetch config from Home Assistant.")
return nil
}
return c
}
func (h *HassConfig) GetEntityState(entity string) map[string]interface{} {
h.mu.Lock()
defer h.mu.Unlock()
if v, ok := h.Entities[entity]; ok {
return v
}
return nil
}
func (h *HassConfig) IsEntityDisabled(entity string) bool {
h.mu.Lock()
defer h.mu.Unlock()
if v, ok := h.Entities[entity]["disabled"]; ok {
if disabledState, ok := v.(bool); !ok {
return false
} else {
return disabledState
}
}
return false
}
// HassConfig implements hass.Request so that it can be sent as a request to HA
// to get its data.
func (h *HassConfig) RequestType() request.RequestType {
return request.RequestTypeGetConfig
}
func (h *HassConfig) RequestData() json.RawMessage {
return nil
}
func (h *HassConfig) ResponseHandler(resp bytes.Buffer) {
if resp.Bytes() == nil {
log.Debug().
Msg("No response returned.")
return
}
h.mu.Lock()
result, err := marshmallow.Unmarshal(resp.Bytes(), &h.hassConfigProps)
if err != nil {
log.Debug().Err(err).
Msg("Couldn't unmarshal Hass config.")
return
}
h.rawConfigProps = result
h.mu.Unlock()
}
// HassConfig implements config.Config
func (c *HassConfig) Get(property string) (interface{}, error) {
c.mu.Lock()
defer c.mu.Unlock()
if value, ok := c.rawConfigProps[property]; ok {
return value, nil
} else {
return nil, fmt.Errorf("config does not have an option %s", property)
}
}
func (c *HassConfig) Set(property string, value interface{}) error {
log.Debug().Caller().Msg("Hass configuration is not settable.")
return nil
}
func (c *HassConfig) Validate() error {
log.Debug().Caller().Msg("Hass configuration has no validation.")
return nil
}
func (h *HassConfig) Refresh(ctx context.Context) error {
request.APIRequest(ctx, h)
return nil
}
func (h *HassConfig) Upgrade() error {
log.Debug().Caller().Msg("Hass configuration has no upgrades.")
return nil
}