mirror of
https://github.com/Xevion/go-ha.git
synced 2025-12-11 14:07:27 -06:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c91c4f85c3 | |||
| 5698a30b37 | |||
| a8d4cefaab | |||
| 7081d06001 | |||
| 55a390e69c | |||
| 378bc29e7e | |||
| 393191ccb5 | |||
| e35f296d70 |
36
README.md
36
README.md
@@ -1,20 +1,18 @@
|
|||||||
# Gome-Assistant
|
# go-ha
|
||||||
|
|
||||||
Write strongly typed [Home Assistant](https://www.home-assistant.io/) automations in Go!
|
Write strongly typed [Home Assistant](https://www.home-assistant.io/) automations in Go!
|
||||||
|
|
||||||
## Disclaimer
|
```bash
|
||||||
|
go get github.com/Xevion/go-ha
|
||||||
Gome-Assistant is a new library, and I'm opening it up early to get some user feedback on the API and help shape the direction. I plan for it to grow to cover all Home Assistant use cases, services, and event types. So it's possible that breaking changes will happen before v1.0.0!
|
|
||||||
|
|
||||||
## Quick Start
|
|
||||||
|
|
||||||
### Installation
|
|
||||||
|
|
||||||
```
|
|
||||||
go get github.com/Xevion/gome-assistant
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Generate Entity Constants
|
or in `go.mod`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
require github.com/Xevion/go-ha
|
||||||
|
```
|
||||||
|
|
||||||
|
## Generate Entity Constants
|
||||||
|
|
||||||
You can generate type-safe constants for all your Home Assistant entities using `go generate`. This makes it easier to reference entities in your code.
|
You can generate type-safe constants for all your Home Assistant entities using `go generate`. This makes it easier to reference entities in your code.
|
||||||
|
|
||||||
@@ -37,7 +35,7 @@ exclude_domains: ["device_tracker", "person"]
|
|||||||
2. Add a `//go:generate` comment in your project:
|
2. Add a `//go:generate` comment in your project:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
//go:generate go run github.com/Xevion/gome-assistant/cmd/generate
|
//go:generate go run github.com/Xevion/go-ha/cmd/generate
|
||||||
```
|
```
|
||||||
|
|
||||||
Optionally use the `-config` flag to customize the file path of the config file.
|
Optionally use the `-config` flag to customize the file path of the config file.
|
||||||
@@ -72,11 +70,11 @@ Check out [`example/example.go`](./example/example.go) for an example of the 3 t
|
|||||||
|
|
||||||
### Run your code
|
### Run your code
|
||||||
|
|
||||||
Keeping with the simplicity that Go is famous for, you don't need a specific environment or docker container to run Gome-Assistant. You just write and run your code like any other Go binary. So once you build your code, you can run it however you like — using `screen` or `tmux`, a cron job, a linux service, or wrap it up in a docker container if you like!
|
Keeping with the simplicity that Go is famous for, you don't need a specific environment or docker container to run go-ha. You just write and run your code like any other Go binary. So once you build your code, you can run it however you like — using `screen` or `tmux`, a cron job, a linux service, or wrap it up in a docker container if you like!
|
||||||
|
|
||||||
> _❗ No promises, but I may provide a Docker image with file watching to automatically restart gome-assistant, to make it easier to use gome-assistant on a fully managed Home Assistant installation._
|
> _❗ No promises, but I may provide a Docker image with file watching to automatically restart go-ha, to make it easier to use go-ha on a fully managed Home Assistant installation._
|
||||||
|
|
||||||
## gome-assistant Concepts
|
## go-ha Concepts
|
||||||
|
|
||||||
### Overview
|
### Overview
|
||||||
|
|
||||||
@@ -87,7 +85,7 @@ The general flow is
|
|||||||
3. Start app
|
3. Start app
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import ga "github.com/Xevion/gome-assistant"
|
import ga "github.com/Xevion/go-ha"
|
||||||
|
|
||||||
// replace with IP and port of your Home Assistant installation
|
// replace with IP and port of your Home Assistant installation
|
||||||
app, err := ga.NewApp(ga.NewAppRequest{
|
app, err := ga.NewApp(ga.NewAppRequest{
|
||||||
@@ -107,7 +105,7 @@ app.RegisterIntervals(...)
|
|||||||
app.Start()
|
app.Start()
|
||||||
```
|
```
|
||||||
|
|
||||||
A full reference is available on [pkg.go.dev](https://pkg.go.dev/github.com/Xevion/gome-assistant), but all you need to know to get started are the four types of automations in gome-assistant.
|
A full reference is available on [pkg.go.dev](https://pkg.go.dev/github.com/Xevion/go-ha), but all you need to know to get started are the four types of automations in go-ha.
|
||||||
|
|
||||||
- [Daily Schedules](#daily-schedule)
|
- [Daily Schedules](#daily-schedule)
|
||||||
- [Entity Listeners](#entity-listener)
|
- [Entity Listeners](#entity-listener)
|
||||||
@@ -226,7 +224,7 @@ func myCallback(service *ga.Service, state ga.State, data ga.EventData) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
> 💡 Check `eventTypes.go` for pre-defined event types, or create your own struct type for custom events and contribute them back to gome-assistant with a PR.
|
> 💡 Check `eventTypes.go` for pre-defined event types, or create your own struct type for custom events and contribute them back to go-ha with a PR.
|
||||||
|
|
||||||
### Interval
|
### Interval
|
||||||
|
|
||||||
|
|||||||
63
app.go
63
app.go
@@ -13,10 +13,10 @@ import (
|
|||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
sunriseLib "github.com/nathan-osman/go-sunrise"
|
sunriseLib "github.com/nathan-osman/go-sunrise"
|
||||||
|
|
||||||
"github.com/Xevion/gome-assistant/internal"
|
"github.com/Workiva/go-datastructures/queue"
|
||||||
"github.com/Xevion/gome-assistant/internal/http"
|
internal "github.com/Xevion/go-ha/internal"
|
||||||
pq "github.com/Xevion/gome-assistant/internal/priority_queue"
|
"github.com/Xevion/go-ha/internal/parse"
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrInvalidArgs = errors.New("invalid arguments provided")
|
var ErrInvalidArgs = errors.New("invalid arguments provided")
|
||||||
@@ -29,18 +29,32 @@ type App struct {
|
|||||||
// Wraps the ws connection with added mutex locking
|
// Wraps the ws connection with added mutex locking
|
||||||
wsWriter *ws.WebsocketWriter
|
wsWriter *ws.WebsocketWriter
|
||||||
|
|
||||||
httpClient *http.HttpClient
|
httpClient *internal.HttpClient
|
||||||
|
|
||||||
service *Service
|
service *Service
|
||||||
state *StateImpl
|
state *StateImpl
|
||||||
|
|
||||||
schedules pq.PriorityQueue
|
schedules *queue.PriorityQueue
|
||||||
intervals pq.PriorityQueue
|
intervals *queue.PriorityQueue
|
||||||
entityListeners map[string][]*EntityListener
|
entityListeners map[string][]*EntityListener
|
||||||
entityListenersId int64
|
entityListenersId int64
|
||||||
eventListeners map[string][]*EventListener
|
eventListeners map[string][]*EventListener
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Item struct {
|
||||||
|
Value interface{}
|
||||||
|
Priority float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mi Item) Compare(other queue.Item) int {
|
||||||
|
if mi.Priority > other.(Item).Priority {
|
||||||
|
return 1
|
||||||
|
} else if mi.Priority == other.(Item).Priority {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
// DurationString represents a duration, such as "2s" or "24h".
|
// DurationString represents a duration, such as "2s" or "24h".
|
||||||
// See https://pkg.go.dev/time#ParseDuration for all valid time units.
|
// See https://pkg.go.dev/time#ParseDuration for all valid time units.
|
||||||
type DurationString string
|
type DurationString string
|
||||||
@@ -133,19 +147,8 @@ func NewApp(request NewAppRequest) (*App, error) {
|
|||||||
var err error
|
var err error
|
||||||
baseURL, err = url.Parse(request.URL)
|
baseURL, err = url.Parse(request.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ErrInvalidArgs
|
return nil, fmt.Errorf("failed to parse URL: %w", err)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// This is deprecated and will be removed in a future release
|
|
||||||
port := request.Port
|
|
||||||
if port == "" {
|
|
||||||
port = "8123"
|
|
||||||
}
|
|
||||||
baseURL.Scheme = "http"
|
|
||||||
if request.Secure {
|
|
||||||
baseURL.Scheme = "https"
|
|
||||||
}
|
|
||||||
baseURL.Host = request.IpAddress + ":" + port
|
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, ctx, ctxCancel, err := ws.ConnectionFromUri(baseURL, request.HAAuthToken)
|
conn, ctx, ctxCancel, err := ws.ConnectionFromUri(baseURL, request.HAAuthToken)
|
||||||
@@ -156,7 +159,7 @@ func NewApp(request NewAppRequest) (*App, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
httpClient := http.NewHttpClient(baseURL, request.HAAuthToken)
|
httpClient := internal.NewHttpClient(baseURL, request.HAAuthToken)
|
||||||
|
|
||||||
wsWriter := &ws.WebsocketWriter{Conn: conn}
|
wsWriter := &ws.WebsocketWriter{Conn: conn}
|
||||||
service := newService(wsWriter)
|
service := newService(wsWriter)
|
||||||
@@ -178,8 +181,8 @@ func NewApp(request NewAppRequest) (*App, error) {
|
|||||||
httpClient: httpClient,
|
httpClient: httpClient,
|
||||||
service: service,
|
service: service,
|
||||||
state: state,
|
state: state,
|
||||||
schedules: pq.New(),
|
schedules: queue.NewPriorityQueue(100, false),
|
||||||
intervals: pq.New(),
|
intervals: queue.NewPriorityQueue(100, false),
|
||||||
entityListeners: map[string][]*EntityListener{},
|
entityListeners: map[string][]*EntityListener{},
|
||||||
eventListeners: map[string][]*EventListener{},
|
eventListeners: map[string][]*EventListener{},
|
||||||
}, nil
|
}, nil
|
||||||
@@ -232,7 +235,7 @@ func (a *App) RegisterSchedules(schedules ...DailySchedule) {
|
|||||||
// realStartTime already set for sunset/sunrise
|
// realStartTime already set for sunset/sunrise
|
||||||
if s.isSunrise || s.isSunset {
|
if s.isSunrise || s.isSunset {
|
||||||
s.nextRunTime = getNextSunRiseOrSet(a, s.isSunrise, s.sunOffset).Carbon2Time()
|
s.nextRunTime = getNextSunRiseOrSet(a, s.isSunrise, s.sunOffset).Carbon2Time()
|
||||||
a.schedules.Insert(s, float64(s.nextRunTime.Unix()))
|
a.schedules.Put()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,7 +248,10 @@ func (a *App) RegisterSchedules(schedules ...DailySchedule) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s.nextRunTime = startTime.Carbon2Time()
|
s.nextRunTime = startTime.Carbon2Time()
|
||||||
a.schedules.Insert(s, float64(startTime.Carbon2Time().Unix()))
|
a.schedules.Put(Item{
|
||||||
|
Value: s,
|
||||||
|
Priority: float64(startTime.Carbon2Time().Unix()),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,12 +262,15 @@ func (a *App) RegisterIntervals(intervals ...Interval) {
|
|||||||
panic(ErrInvalidArgs)
|
panic(ErrInvalidArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
i.nextRunTime = internal.ParseTime(string(i.startTime)).Carbon2Time()
|
i.nextRunTime = parse.ParseTime(string(i.startTime)).Carbon2Time()
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
for i.nextRunTime.Before(now) {
|
for i.nextRunTime.Before(now) {
|
||||||
i.nextRunTime = i.nextRunTime.Add(i.frequency)
|
i.nextRunTime = i.nextRunTime.Add(i.frequency)
|
||||||
}
|
}
|
||||||
a.intervals.Insert(i, float64(i.nextRunTime.Unix()))
|
a.intervals.Put(Item{
|
||||||
|
Value: i,
|
||||||
|
Priority: float64(i.nextRunTime.Unix()),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,7 +358,7 @@ func (a *App) Start() {
|
|||||||
go runIntervals(a)
|
go runIntervals(a)
|
||||||
|
|
||||||
// subscribe to state_changed events
|
// subscribe to state_changed events
|
||||||
id := internal.GetId()
|
id := internal.NextId()
|
||||||
ws.SubscribeToStateChangedEvents(id, a.wsWriter, a.ctx)
|
ws.SubscribeToStateChangedEvents(id, a.wsWriter, a.ctx)
|
||||||
a.entityListenersId = id
|
a.entityListenersId = id
|
||||||
|
|
||||||
|
|||||||
13
checkers.go
13
checkers.go
@@ -3,7 +3,8 @@ package gomeassistant
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Xevion/gome-assistant/internal"
|
"github.com/Xevion/go-ha/internal"
|
||||||
|
"github.com/Xevion/go-ha/internal/parse"
|
||||||
"github.com/golang-module/carbon"
|
"github.com/golang-module/carbon"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -16,8 +17,8 @@ func checkWithinTimeRange(startTime, endTime string) conditionCheck {
|
|||||||
// if betweenStart and betweenEnd both set, first account for midnight
|
// if betweenStart and betweenEnd both set, first account for midnight
|
||||||
// overlap, then check if between those times.
|
// overlap, then check if between those times.
|
||||||
if startTime != "" && endTime != "" {
|
if startTime != "" && endTime != "" {
|
||||||
parsedStart := internal.ParseTime(startTime)
|
parsedStart := parse.ParseTime(startTime)
|
||||||
parsedEnd := internal.ParseTime(endTime)
|
parsedEnd := parse.ParseTime(endTime)
|
||||||
|
|
||||||
// check for midnight overlap
|
// check for midnight overlap
|
||||||
if parsedEnd.Lt(parsedStart) { // example turn on night lights when motion from 23:00 to 07:00
|
if parsedEnd.Lt(parsedStart) { // example turn on night lights when motion from 23:00 to 07:00
|
||||||
@@ -34,9 +35,9 @@ func checkWithinTimeRange(startTime, endTime string) conditionCheck {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// otherwise just check individual before/after
|
// otherwise just check individual before/after
|
||||||
} else if startTime != "" && internal.ParseTime(startTime).IsFuture() {
|
} else if startTime != "" && parse.ParseTime(startTime).IsFuture() {
|
||||||
cc.fail = true
|
cc.fail = true
|
||||||
} else if endTime != "" && internal.ParseTime(endTime).IsPast() {
|
} else if endTime != "" && parse.ParseTime(endTime).IsPast() {
|
||||||
cc.fail = true
|
cc.fail = true
|
||||||
}
|
}
|
||||||
return cc
|
return cc
|
||||||
@@ -168,7 +169,7 @@ func checkStartEndTime(s TimeString, isStart bool) conditionCheck {
|
|||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
parsedTime := internal.ParseTime(string(s)).Carbon2Time()
|
parsedTime := parse.ParseTime(string(s)).Carbon2Time()
|
||||||
if isStart {
|
if isStart {
|
||||||
if parsedTime.After(now) {
|
if parsedTime.After(now) {
|
||||||
cc.fail = true
|
cc.fail = true
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/Xevion/gome-assistant/internal"
|
"github.com/Xevion/go-ha/internal"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
ga "github.com/Xevion/gome-assistant"
|
ga "github.com/Xevion/go-ha"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ import (
|
|||||||
|
|
||||||
"github.com/golang-module/carbon"
|
"github.com/golang-module/carbon"
|
||||||
|
|
||||||
"github.com/Xevion/gome-assistant/internal"
|
"github.com/Xevion/go-ha/internal"
|
||||||
|
"github.com/Xevion/go-ha/internal/parse"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EntityListener struct {
|
type EntityListener struct {
|
||||||
@@ -127,13 +128,13 @@ func (b elBuilder3) ToState(s string) elBuilder3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b elBuilder3) Duration(s DurationString) elBuilder3 {
|
func (b elBuilder3) Duration(s DurationString) elBuilder3 {
|
||||||
d := internal.ParseDuration(string(s))
|
d := parse.ParseDuration(string(s))
|
||||||
b.entityListener.delay = d
|
b.entityListener.delay = d
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b elBuilder3) Throttle(s DurationString) elBuilder3 {
|
func (b elBuilder3) Throttle(s DurationString) elBuilder3 {
|
||||||
d := internal.ParseDuration(string(s))
|
d := parse.ParseDuration(string(s))
|
||||||
b.entityListener.throttle = d
|
b.entityListener.throttle = d
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
@@ -7,8 +7,9 @@ import (
|
|||||||
|
|
||||||
"github.com/golang-module/carbon"
|
"github.com/golang-module/carbon"
|
||||||
|
|
||||||
"github.com/Xevion/gome-assistant/internal"
|
"github.com/Xevion/go-ha/internal"
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
"github.com/Xevion/go-ha/internal/parse"
|
||||||
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EventListener struct {
|
type EventListener struct {
|
||||||
@@ -80,7 +81,7 @@ func (b eventListenerBuilder3) OnlyBefore(end string) eventListenerBuilder3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b eventListenerBuilder3) Throttle(s DurationString) eventListenerBuilder3 {
|
func (b eventListenerBuilder3) Throttle(s DurationString) eventListenerBuilder3 {
|
||||||
d := internal.ParseDuration(string(s))
|
d := parse.ParseDuration(string(s))
|
||||||
b.eventListener.throttle = d
|
b.eventListener.throttle = d
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
@@ -8,10 +8,10 @@ import (
|
|||||||
|
|
||||||
// "example/entities" // Optional import generated entities
|
// "example/entities" // Optional import generated entities
|
||||||
|
|
||||||
ga "github.com/Xevion/gome-assistant"
|
ga "github.com/Xevion/go-ha"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate go run github.com/Xevion/gome-assistant/cmd/generate
|
//go:generate go run github.com/Xevion/go-ha/cmd/generate
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app, err := ga.NewApp(ga.NewAppRequest{
|
app, err := ga.NewApp(ga.NewAppRequest{
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
ga "github.com/Xevion/gome-assistant"
|
ga "github.com/Xevion/go-ha"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
|||||||
7
go.mod
7
go.mod
@@ -1,13 +1,15 @@
|
|||||||
module github.com/Xevion/gome-assistant
|
module github.com/Xevion/go-ha
|
||||||
|
|
||||||
go 1.21
|
go 1.21
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/Workiva/go-datastructures v1.1.5
|
||||||
github.com/golang-module/carbon v1.7.1
|
github.com/golang-module/carbon v1.7.1
|
||||||
github.com/gorilla/websocket v1.5.0
|
github.com/gorilla/websocket v1.5.0
|
||||||
github.com/nathan-osman/go-sunrise v1.1.0
|
github.com/nathan-osman/go-sunrise v1.1.0
|
||||||
github.com/stretchr/testify v1.8.4
|
github.com/stretchr/testify v1.10.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
|
resty.dev/v3 v3.0.0-beta.3
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -18,4 +20,5 @@ require (
|
|||||||
github.com/joho/godotenv v1.4.0 // indirect
|
github.com/joho/godotenv v1.4.0 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.9.0 // indirect
|
github.com/rogpeppe/go-internal v1.9.0 // indirect
|
||||||
|
golang.org/x/net v0.33.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
28
go.sum
28
go.sum
@@ -1,4 +1,6 @@
|
|||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/Workiva/go-datastructures v1.1.5 h1:5YfhQ4ry7bZc2Mc7R0YZyYwpf5c6t1cEFvdAhd6Mkf4=
|
||||||
|
github.com/Workiva/go-datastructures v1.1.5/go.mod h1:1yZL+zfsztete+ePzZz/Zb1/t5BnDuE2Ya2MMGhzP6A=
|
||||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||||
@@ -41,6 +43,7 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
|
|||||||
github.com/nathan-osman/go-sunrise v1.1.0 h1:ZqZmtmtzs8Os/DGQYi0YMHpuUqR/iRoJK+wDO0wTCw8=
|
github.com/nathan-osman/go-sunrise v1.1.0 h1:ZqZmtmtzs8Os/DGQYi0YMHpuUqR/iRoJK+wDO0wTCw8=
|
||||||
github.com/nathan-osman/go-sunrise v1.1.0/go.mod h1:RcWqhT+5ShCZDev79GuWLayetpJp78RSjSWxiDowmlM=
|
github.com/nathan-osman/go-sunrise v1.1.0/go.mod h1:RcWqhT+5ShCZDev79GuWLayetpJp78RSjSWxiDowmlM=
|
||||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
|
github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
|
||||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
@@ -64,23 +67,42 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
|||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg=
|
||||||
|
github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q=
|
||||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||||
|
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
@@ -89,3 +111,5 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
resty.dev/v3 v3.0.0-beta.3 h1:3kEwzEgCnnS6Ob4Emlk94t+I/gClyoah7SnNi67lt+E=
|
||||||
|
resty.dev/v3 v3.0.0-beta.3/go.mod h1:OgkqiPvTDtOuV4MGZuUDhwOpkY8enjOsjjMzeOHefy4=
|
||||||
|
|||||||
74
internal/http.go
Normal file
74
internal/http.go
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
// http is used to interact with the home assistant
|
||||||
|
// REST API. Currently only used to retrieve state for
|
||||||
|
// a single entity_id
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"resty.dev/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HttpClient struct {
|
||||||
|
client *resty.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHttpClient(url *url.URL, token string) *HttpClient {
|
||||||
|
// Shallow copy the URL to avoid modifying the original
|
||||||
|
u := *url
|
||||||
|
u.Path = "/api"
|
||||||
|
if u.Scheme == "ws" {
|
||||||
|
u.Scheme = "http"
|
||||||
|
}
|
||||||
|
if u.Scheme == "wss" {
|
||||||
|
u.Scheme = "https"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create resty client with configuration
|
||||||
|
client := resty.New().
|
||||||
|
SetBaseURL(u.String()).
|
||||||
|
SetHeader("Authorization", "Bearer "+token).
|
||||||
|
SetTimeout(30 * time.Second).
|
||||||
|
SetRetryCount(3).
|
||||||
|
SetRetryWaitTime(1 * time.Second).
|
||||||
|
SetRetryMaxWaitTime(5 * time.Second).
|
||||||
|
AddRetryConditions(func(r *resty.Response, err error) bool {
|
||||||
|
return err != nil || r.StatusCode() >= 500
|
||||||
|
})
|
||||||
|
|
||||||
|
return &HttpClient{
|
||||||
|
client: client,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *HttpClient) GetState(entityId string) ([]byte, error) {
|
||||||
|
resp, err := c.client.R().
|
||||||
|
Get("/states/" + entityId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Error making HTTP request: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode() >= 400 {
|
||||||
|
return nil, errors.New("HTTP error: " + resp.Status() + " - " + string(resp.Bytes()))
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *HttpClient) States() ([]byte, error) {
|
||||||
|
resp, err := c.client.R().
|
||||||
|
Get("/states")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Error making HTTP request: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode() >= 400 {
|
||||||
|
return nil, errors.New("HTTP error: " + resp.Status() + " - " + string(resp.Bytes()))
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp.Bytes(), nil
|
||||||
|
}
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
// http is used to interact with the home assistant
|
|
||||||
// REST API. Currently only used to retrieve state for
|
|
||||||
// a single entity_id
|
|
||||||
package http
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
)
|
|
||||||
|
|
||||||
type HttpClient struct {
|
|
||||||
url string
|
|
||||||
token string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewHttpClient(url *url.URL, token string) *HttpClient {
|
|
||||||
// Shallow copy the URL to avoid modifying the original
|
|
||||||
u := *url
|
|
||||||
u.Path = "/api"
|
|
||||||
if u.Scheme == "ws" {
|
|
||||||
u.Scheme = "http"
|
|
||||||
}
|
|
||||||
if u.Scheme == "wss" {
|
|
||||||
u.Scheme = "https"
|
|
||||||
}
|
|
||||||
|
|
||||||
return &HttpClient{
|
|
||||||
url: u.String(),
|
|
||||||
token: token,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *HttpClient) GetState(entityId string) ([]byte, error) {
|
|
||||||
resp, err := get(c.url+"/states/"+entityId, c.token)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *HttpClient) States() ([]byte, error) {
|
|
||||||
resp, err := get(c.url+"/states", c.token)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func get(url, token string) ([]byte, error) {
|
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("Error creating HTTP request: " + err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Header.Add("Authorization", "Bearer "+token)
|
|
||||||
|
|
||||||
client := &http.Client{}
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("Error on response.\n[ERROR] -" + err.Error())
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
body, err := io.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("Error while reading the response bytes:" + err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return body, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// func post(url string, token string, data any) ([]byte, error) {
|
|
||||||
// postBody, err := json.Marshal(data)
|
|
||||||
// if err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
// req, err := http.NewRequest("GET", url, bytes.NewBuffer(postBody))
|
|
||||||
// if err != nil {
|
|
||||||
// return nil, errors.New("Error building post request: " + err.Error())
|
|
||||||
// }
|
|
||||||
|
|
||||||
// req.Header.Add("Authorization", "Bearer "+token)
|
|
||||||
|
|
||||||
// client := &http.Client{}
|
|
||||||
// resp, err := client.Do(req)
|
|
||||||
// if err != nil {
|
|
||||||
// return nil, errors.New("Error in post response: " + err.Error())
|
|
||||||
// }
|
|
||||||
// defer resp.Body.Close()
|
|
||||||
|
|
||||||
// if resp.StatusCode == 401 {
|
|
||||||
// panic("ERROR: Auth token is invalid. Please double check it or create a new token in your Home Assistant profile")
|
|
||||||
// }
|
|
||||||
|
|
||||||
// body, err := io.ReadAll(resp.Body)
|
|
||||||
// if err != nil {
|
|
||||||
// panic(err)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return body, nil
|
|
||||||
// }
|
|
||||||
28
internal/misc.go
Normal file
28
internal/misc.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EnabledDisabledInfo struct {
|
||||||
|
Entity string
|
||||||
|
State string
|
||||||
|
RunOnError bool
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
id atomic.Int64 // default value is 0
|
||||||
|
)
|
||||||
|
|
||||||
|
// NextId returns a unique integer (for the given process), often used for providing a uniquely identifiable
|
||||||
|
// id for a request. This function is thread-safe.
|
||||||
|
func NextId() int64 {
|
||||||
|
return id.Add(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFunctionName returns the name of the function that the interface is a pointer to.
|
||||||
|
func GetFunctionName(i interface{}) string {
|
||||||
|
return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
|
||||||
|
}
|
||||||
@@ -1,28 +1,13 @@
|
|||||||
package internal
|
package parse
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"reflect"
|
|
||||||
"runtime"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang-module/carbon"
|
"github.com/golang-module/carbon"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EnabledDisabledInfo struct {
|
|
||||||
Entity string
|
|
||||||
State string
|
|
||||||
RunOnError bool
|
|
||||||
}
|
|
||||||
|
|
||||||
var id int64 = 0
|
|
||||||
|
|
||||||
func GetId() int64 {
|
|
||||||
id += 1
|
|
||||||
return id
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parses a HH:MM string.
|
// Parses a HH:MM string.
|
||||||
func ParseTime(s string) carbon.Carbon {
|
func ParseTime(s string) carbon.Carbon {
|
||||||
t, err := time.Parse("15:04", s)
|
t, err := time.Parse("15:04", s)
|
||||||
@@ -43,7 +28,3 @@ func ParseDuration(s string) time.Duration {
|
|||||||
}
|
}
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetFunctionName(i interface{}) string {
|
|
||||||
return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
package priority_queue
|
|
||||||
|
|
||||||
import (
|
|
||||||
"container/heap"
|
|
||||||
"errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PriorityQueue represents the queue
|
|
||||||
type PriorityQueue struct {
|
|
||||||
itemHeap *itemHeap
|
|
||||||
lookup map[interface{}]*item
|
|
||||||
}
|
|
||||||
|
|
||||||
// New initializes an empty priority queue.
|
|
||||||
func New() PriorityQueue {
|
|
||||||
return PriorityQueue{
|
|
||||||
itemHeap: &itemHeap{},
|
|
||||||
lookup: make(map[interface{}]*item),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Len returns the number of elements in the queue.
|
|
||||||
func (p *PriorityQueue) Len() int {
|
|
||||||
return p.itemHeap.Len()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert inserts a new element into the queue. No action is performed on duplicate elements.
|
|
||||||
func (p *PriorityQueue) Insert(v interface{ Hash() string }, priority float64) {
|
|
||||||
_, ok := p.lookup[v.Hash()]
|
|
||||||
if ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
newItem := &item{
|
|
||||||
value: v,
|
|
||||||
priority: priority,
|
|
||||||
}
|
|
||||||
heap.Push(p.itemHeap, newItem)
|
|
||||||
p.lookup[v.Hash()] = newItem
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pop removes the element with the highest priority from the queue and returns it.
|
|
||||||
// In case of an empty queue, an error is returned.
|
|
||||||
func (p *PriorityQueue) Pop() (interface{}, error) {
|
|
||||||
if len(*p.itemHeap) == 0 {
|
|
||||||
return nil, errors.New("empty queue")
|
|
||||||
}
|
|
||||||
|
|
||||||
item := heap.Pop(p.itemHeap).(*item)
|
|
||||||
delete(p.lookup, item.value.(interface{ Hash() string }).Hash())
|
|
||||||
return item.value, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type itemHeap []*item
|
|
||||||
|
|
||||||
type item struct {
|
|
||||||
value interface{}
|
|
||||||
priority float64
|
|
||||||
index int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ih *itemHeap) Len() int {
|
|
||||||
return len(*ih)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ih *itemHeap) Less(i, j int) bool {
|
|
||||||
return (*ih)[i].priority < (*ih)[j].priority
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ih *itemHeap) Swap(i, j int) {
|
|
||||||
(*ih)[i], (*ih)[j] = (*ih)[j], (*ih)[i]
|
|
||||||
(*ih)[i].index = i
|
|
||||||
(*ih)[j].index = j
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ih *itemHeap) Push(x interface{}) {
|
|
||||||
it := x.(*item)
|
|
||||||
it.index = len(*ih)
|
|
||||||
*ih = append(*ih, it)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ih *itemHeap) Pop() interface{} {
|
|
||||||
old := *ih
|
|
||||||
item := old[len(old)-1]
|
|
||||||
*ih = old[0 : len(old)-1]
|
|
||||||
return item
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Structs */
|
/* Structs */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Structs */
|
/* Structs */
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
"github.com/Xevion/gome-assistant/types"
|
"github.com/Xevion/go-ha/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Structs */
|
/* Structs */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Structs */
|
/* Structs */
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/Xevion/gome-assistant/internal"
|
"github.com/Xevion/go-ha/internal"
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Event struct {
|
type Event struct {
|
||||||
@@ -23,7 +23,7 @@ type FireEventRequest struct {
|
|||||||
// as `event_data`.
|
// as `event_data`.
|
||||||
func (e Event) Fire(eventType string, eventData ...map[string]any) error {
|
func (e Event) Fire(eventType string, eventData ...map[string]any) error {
|
||||||
req := FireEventRequest{
|
req := FireEventRequest{
|
||||||
Id: internal.GetId(),
|
Id: internal.NextId(),
|
||||||
Type: "fire_event",
|
Type: "fire_event",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HomeAssistant struct {
|
type HomeAssistant struct {
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Structs */
|
/* Structs */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Structs */
|
/* Structs */
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Structs */
|
/* Structs */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Structs */
|
/* Structs */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Structs */
|
/* Structs */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Structs */
|
/* Structs */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Structs */
|
/* Structs */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Structs */
|
/* Structs */
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
"github.com/Xevion/gome-assistant/types"
|
"github.com/Xevion/go-ha/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Notify struct {
|
type Notify struct {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Number struct {
|
type Number struct {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Structs */
|
/* Structs */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Structs */
|
/* Structs */
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/Xevion/gome-assistant/internal"
|
"github.com/Xevion/go-ha/internal"
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BuildService[
|
func BuildService[
|
||||||
@@ -45,13 +45,15 @@ type BaseServiceRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewBaseServiceRequest(entityId string) BaseServiceRequest {
|
func NewBaseServiceRequest(entityId string) BaseServiceRequest {
|
||||||
id := internal.GetId()
|
id := internal.NextId()
|
||||||
bsr := BaseServiceRequest{
|
request := BaseServiceRequest{
|
||||||
Id: id,
|
Id: id,
|
||||||
RequestType: "call_service",
|
RequestType: "call_service",
|
||||||
}
|
}
|
||||||
|
|
||||||
if entityId != "" {
|
if entityId != "" {
|
||||||
bsr.Target.EntityId = entityId
|
request.Target.EntityId = entityId
|
||||||
}
|
}
|
||||||
return bsr
|
|
||||||
|
return request
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Structs */
|
/* Structs */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Structs */
|
/* Structs */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Structs */
|
/* Structs */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Structs */
|
/* Structs */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Structs */
|
/* Structs */
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
|
|
||||||
"github.com/Xevion/gome-assistant/internal"
|
"github.com/Xevion/go-ha/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrInvalidToken = errors.New("invalid authentication token")
|
var ErrInvalidToken = errors.New("invalid authentication token")
|
||||||
@@ -140,7 +140,7 @@ func SubscribeToStateChangedEvents(id int64, conn *WebsocketWriter, ctx context.
|
|||||||
func SubscribeToEventType(eventType string, conn *WebsocketWriter, ctx context.Context, id ...int64) {
|
func SubscribeToEventType(eventType string, conn *WebsocketWriter, ctx context.Context, id ...int64) {
|
||||||
var finalId int64
|
var finalId int64
|
||||||
if len(id) == 0 {
|
if len(id) == 0 {
|
||||||
finalId = internal.GetId()
|
finalId = internal.NextId()
|
||||||
} else {
|
} else {
|
||||||
finalId = id[0]
|
finalId = id[0]
|
||||||
}
|
}
|
||||||
|
|||||||
14
interval.go
14
interval.go
@@ -5,7 +5,8 @@ import (
|
|||||||
"log/slog"
|
"log/slog"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Xevion/gome-assistant/internal"
|
"github.com/Xevion/go-ha/internal"
|
||||||
|
"github.com/Xevion/go-ha/internal/parse"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IntervalCallback func(*Service, State)
|
type IntervalCallback func(*Service, State)
|
||||||
@@ -80,7 +81,7 @@ func (ib intervalBuilder) Call(callback IntervalCallback) intervalBuilderCall {
|
|||||||
|
|
||||||
// Takes a DurationString ("2h", "5m", etc) to set the frequency of the interval.
|
// Takes a DurationString ("2h", "5m", etc) to set the frequency of the interval.
|
||||||
func (ib intervalBuilderCall) Every(s DurationString) intervalBuilderEnd {
|
func (ib intervalBuilderCall) Every(s DurationString) intervalBuilderEnd {
|
||||||
d := internal.ParseDuration(string(s))
|
d := parse.ParseDuration(string(s))
|
||||||
ib.interval.frequency = d
|
ib.interval.frequency = d
|
||||||
return intervalBuilderEnd(ib)
|
return intervalBuilderEnd(ib)
|
||||||
}
|
}
|
||||||
@@ -206,12 +207,15 @@ func (i Interval) maybeRunCallback(a *App) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func popInterval(a *App) Interval {
|
func popInterval(a *App) Interval {
|
||||||
i, _ := a.intervals.Pop()
|
i, _ := a.intervals.Get(1)
|
||||||
return i.(Interval)
|
return i[0].(Item).Value.(Interval)
|
||||||
}
|
}
|
||||||
|
|
||||||
func requeueInterval(a *App, i Interval) {
|
func requeueInterval(a *App, i Interval) {
|
||||||
i.nextRunTime = i.nextRunTime.Add(i.frequency)
|
i.nextRunTime = i.nextRunTime.Add(i.frequency)
|
||||||
|
|
||||||
a.intervals.Insert(i, float64(i.nextRunTime.Unix()))
|
a.intervals.Put(Item{
|
||||||
|
Value: i,
|
||||||
|
Priority: float64(i.nextRunTime.Unix()),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
14
schedule.go
14
schedule.go
@@ -5,7 +5,8 @@ import (
|
|||||||
"log/slog"
|
"log/slog"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Xevion/gome-assistant/internal"
|
"github.com/Xevion/go-ha/internal"
|
||||||
|
"github.com/Xevion/go-ha/internal/parse"
|
||||||
"github.com/golang-module/carbon"
|
"github.com/golang-module/carbon"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -75,7 +76,7 @@ func (sb scheduleBuilder) Call(callback ScheduleCallback) scheduleBuilderCall {
|
|||||||
|
|
||||||
// At takes a string in 24hr format time like "15:30".
|
// At takes a string in 24hr format time like "15:30".
|
||||||
func (sb scheduleBuilderCall) At(s string) scheduleBuilderEnd {
|
func (sb scheduleBuilderCall) At(s string) scheduleBuilderEnd {
|
||||||
t := internal.ParseTime(s)
|
t := parse.ParseTime(s)
|
||||||
sb.schedule.hour = t.Hour()
|
sb.schedule.hour = t.Hour()
|
||||||
sb.schedule.minute = t.Minute()
|
sb.schedule.minute = t.Minute()
|
||||||
return scheduleBuilderEnd(sb)
|
return scheduleBuilderEnd(sb)
|
||||||
@@ -208,8 +209,8 @@ func (s DailySchedule) maybeRunCallback(a *App) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func popSchedule(a *App) DailySchedule {
|
func popSchedule(a *App) DailySchedule {
|
||||||
_sched, _ := a.schedules.Pop()
|
_sched, _ := a.schedules.Get(1)
|
||||||
return _sched.(DailySchedule)
|
return _sched[0].(Item).Value.(DailySchedule)
|
||||||
}
|
}
|
||||||
|
|
||||||
func requeueSchedule(a *App, s DailySchedule) {
|
func requeueSchedule(a *App, s DailySchedule) {
|
||||||
@@ -227,5 +228,8 @@ func requeueSchedule(a *App, s DailySchedule) {
|
|||||||
s.nextRunTime = carbon.Time2Carbon(s.nextRunTime).AddDay().Carbon2Time()
|
s.nextRunTime = carbon.Time2Carbon(s.nextRunTime).AddDay().Carbon2Time()
|
||||||
}
|
}
|
||||||
|
|
||||||
a.schedules.Insert(s, float64(s.nextRunTime.Unix()))
|
a.schedules.Put(Item{
|
||||||
|
Value: s,
|
||||||
|
Priority: float64(s.nextRunTime.Unix()),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package gomeassistant
|
package gomeassistant
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/Xevion/gome-assistant/internal/services"
|
"github.com/Xevion/go-ha/internal/services"
|
||||||
ws "github.com/Xevion/gome-assistant/internal/websocket"
|
ws "github.com/Xevion/go-ha/internal/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Service struct {
|
type Service struct {
|
||||||
|
|||||||
6
state.go
6
state.go
@@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/golang-module/carbon"
|
"github.com/golang-module/carbon"
|
||||||
|
|
||||||
"github.com/Xevion/gome-assistant/internal/http"
|
internal "github.com/Xevion/go-ha/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
type State interface {
|
type State interface {
|
||||||
@@ -23,7 +23,7 @@ type State interface {
|
|||||||
|
|
||||||
// State is used to retrieve state from Home Assistant.
|
// State is used to retrieve state from Home Assistant.
|
||||||
type StateImpl struct {
|
type StateImpl struct {
|
||||||
httpClient *http.HttpClient
|
httpClient *internal.HttpClient
|
||||||
latitude float64
|
latitude float64
|
||||||
longitude float64
|
longitude float64
|
||||||
}
|
}
|
||||||
@@ -35,7 +35,7 @@ type EntityState struct {
|
|||||||
LastChanged time.Time `json:"last_changed"`
|
LastChanged time.Time `json:"last_changed"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func newState(c *http.HttpClient, homeZoneEntityId string) (*StateImpl, error) {
|
func newState(c *internal.HttpClient, homeZoneEntityId string) (*StateImpl, error) {
|
||||||
state := &StateImpl{httpClient: c}
|
state := &StateImpl{httpClient: c}
|
||||||
|
|
||||||
// Ensure the zone exists and has required attributes
|
// Ensure the zone exists and has required attributes
|
||||||
|
|||||||
Reference in New Issue
Block a user