mirror of
https://github.com/Xevion/go-ha.git
synced 2025-12-06 15:15:14 -06:00
documented general use cases
This commit is contained in:
109
README.md
109
README.md
@@ -1,9 +1,11 @@
|
||||
# Gome-Assistant
|
||||
|
||||
Golang ↔️ Home Assistant
|
||||
|
||||
Write your [Home Assistant](https://www.home-assistant.io/) automations with a strongly-typed Golang library!
|
||||
|
||||
## Disclaimer
|
||||
|
||||
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
|
||||
@@ -24,26 +26,37 @@ Keeping with the simplicity that Go is famous for, you don't need a specific env
|
||||
|
||||
> _❗ 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._
|
||||
|
||||
## Disclaimer
|
||||
## gome-assistant Concepts
|
||||
|
||||
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 — maybe likely — that breaking changes will happen before v1.0.0!
|
||||
### Overview
|
||||
|
||||
## gome-assistant Concepts (TODO)
|
||||
The general flow is
|
||||
|
||||
First, you'll need to create your app.
|
||||
1. Create your app
|
||||
2. Register automations
|
||||
3. Start app
|
||||
|
||||
```go
|
||||
import ga "github.com/saml-dev/gome-assistant"
|
||||
|
||||
// replace with IP and port of your Home Assistant installation if needed
|
||||
// replace with IP and port of your Home Assistant installation
|
||||
app := ga.App("0.0.0.0:8123")
|
||||
|
||||
// create automations here (see next sections)
|
||||
|
||||
// register automations
|
||||
app.RegisterSchedules(...)
|
||||
app.RegisterEntityListeners(...)
|
||||
app.RegisterEventListeners(...)
|
||||
|
||||
app.Start()
|
||||
```
|
||||
|
||||
A full reference is available on [pkg.go.dev](https://pkg.go.dev/github.com/saml-dev/gome-assistant), but all you need to know to get started are the three types of automations in gome-assistant.
|
||||
|
||||
### Schedules
|
||||
|
||||
Schedules are as you expect, a way to run a function on a schedule. The most common schedule will be once a day.
|
||||
Schedules are simply a way to run a function on a schedule. The most common schedule is once a day at a certain time.
|
||||
|
||||
```go
|
||||
_7pm := ga.NewSchedule().Call(myFunc).Daily().At("19:00").Build()
|
||||
@@ -56,19 +69,13 @@ Schedules can also be run at sunrise or sunset, with an optional [offset](https:
|
||||
sunrise := ga.NewSchedule().Call(myFunc).Daily().Sunrise(app, "-30m").Build()
|
||||
```
|
||||
|
||||
Schedules are also used to run a function on a certain interval. Offset is used to offset the first run of a schedule from midnight.
|
||||
Schedules are also used to run a function on an interval. Offset is used to offset the first run of a schedule from midnight.
|
||||
|
||||
```go
|
||||
// run every hour at the 30-minute mark
|
||||
interval := ga.NewSchedule().Call(a).Every("1h").Offset("30m").Build()
|
||||
```
|
||||
|
||||
All schedules must be registered with your app. This will panic if there are any issues with the schedule.
|
||||
|
||||
```go
|
||||
app.RegisterSchedules(_7pm, sunrise, interval)
|
||||
```
|
||||
|
||||
#### Schedule Callback function
|
||||
|
||||
The function passed to `.Call()` must take
|
||||
@@ -76,6 +83,78 @@ The function passed to `.Call()` must take
|
||||
- `*ga.Service` used to call home assistant services
|
||||
- `*ga.State` used to retrieve state from home assistant
|
||||
|
||||
```go
|
||||
func myFunc(se *ga.Service, st *ga.State) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### Entity Listeners
|
||||
|
||||
Entity Listeners are used to respond to entities changing state. The simplest entity listener looks like:
|
||||
|
||||
```go
|
||||
etl := ga.NewEntityListener().EntityIds("binary_sensor.front_door").Call(myFunc).Build()
|
||||
```
|
||||
|
||||
Entity listeners have other functions to change the behavior.
|
||||
|
||||
| Function | Info |
|
||||
| ------------------------------------ | ------------------------------------------------------------------------------------------------- |
|
||||
| ToState("on") | Function only called if new state matches argument. |
|
||||
| FromState("on") | Function only called if old state matches argument. |
|
||||
| Throttle("30s") | Minimum time between function calls. |
|
||||
| Duration("30s") | Requires ToState(). Sets how long the entity should be in the state before running your function. |
|
||||
| OnlyAfter("03:00") | Only run your function after a specified time of day. |
|
||||
| OnlyBefore("03:00") | Only run your function before a specified time of day. |
|
||||
| OnlyBetween("03:00", "14:00") | Only run your function between two specified times of day. |
|
||||
| ExceptionDay(time.Time) | A one time exception on the given date. Time is ignored, applies to whole day. |
|
||||
| ExceptionRange(time.Time, time.Time) | A one time exception between the two date/times. Both date and time are considered. |
|
||||
|
||||
#### Entity Listener Callback function
|
||||
|
||||
The function passed to `.Call()` must take
|
||||
|
||||
- `*ga.Service` used to call home assistant services
|
||||
- `*ga.State` used to retrieve state from home assistant
|
||||
- `ga.EntityData` which is the entity that triggered the listener
|
||||
|
||||
```go
|
||||
func myFunc(se *ga.Service, st *ga.State, e ga.EntityData) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### Event Listeners
|
||||
|
||||
Event Listeners are used to respond to entities changing state. The simplest event listener looks like:
|
||||
|
||||
```go
|
||||
evl := ga.NewEntityListener().EntityIds("binary_sensor.front_door").Call(myFunc).Build()
|
||||
```
|
||||
|
||||
Event listeners have other functions to change the behavior.
|
||||
|
||||
| Function | Info |
|
||||
| ------------------------------------ | ----------------------------------------------------------------------------------- |
|
||||
| Throttle("30s") | Minimum time between function calls. |
|
||||
| OnlyAfter("03:00") | Only run your function after a specified time of day. |
|
||||
| OnlyBefore("03:00") | Only run your function before a specified time of day. |
|
||||
| OnlyBetween("03:00", "14:00") | Only run your function between two specified times of day. |
|
||||
| ExceptionDay(time.Time) | A one time exception on the given date. Time is ignored, applies to whole day. |
|
||||
| ExceptionRange(time.Time, time.Time) | A one time exception between the two date/times. Both date and time are considered. |
|
||||
|
||||
#### Event Listener Callback function
|
||||
|
||||
The function passed to `.Call()` must take
|
||||
|
||||
- `*ga.Service` used to call home assistant services
|
||||
- `*ga.State` used to retrieve state from home assistant
|
||||
|
||||
```go
|
||||
func myFunc(se *ga.Service, st *ga.State) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
<!-- TODO: add doc for State and Service, prolly don't need it for EntityData/EntityState -->
|
||||
|
||||
@@ -27,7 +27,7 @@ type EntityListener struct {
|
||||
}
|
||||
|
||||
// TODO: add state object as second arg
|
||||
type EntityListenerCallback func(*Service, EntityData)
|
||||
type EntityListenerCallback func(*Service, *State, EntityData)
|
||||
|
||||
type EntityData struct {
|
||||
TriggerEntityId string
|
||||
@@ -192,14 +192,14 @@ func callEntityListeners(app *app, msgBytes []byte) {
|
||||
|
||||
if l.delay != 0 {
|
||||
l.delayTimer = time.AfterFunc(l.delay, func() {
|
||||
go l.callback(app.service, entityData)
|
||||
go l.callback(app.service, app.state, entityData)
|
||||
l.lastRan = carbon.Now()
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// run now if no delay set
|
||||
go l.callback(app.service, entityData)
|
||||
go l.callback(app.service, app.state, entityData)
|
||||
l.lastRan = carbon.Now()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ func main() {
|
||||
|
||||
}
|
||||
|
||||
func pantryLights(service *ga.Service, sensor ga.EntityData) {
|
||||
func pantryLights(service *ga.Service, state *ga.State, sensor ga.EntityData) {
|
||||
l := "light.pantry"
|
||||
if sensor.ToState == "on" {
|
||||
service.HomeAssistant.TurnOn(l)
|
||||
@@ -68,6 +68,7 @@ func onEvent(service *ga.Service, data ga.EventData) {
|
||||
}
|
||||
|
||||
func lightsOut(service *ga.Service, state *ga.State) {
|
||||
// always turn off outside lights
|
||||
service.Light.TurnOff("light.outside_lights")
|
||||
s, err := state.Get("binary_sensor.living_room_motion")
|
||||
if err != nil {
|
||||
@@ -76,7 +77,7 @@ func lightsOut(service *ga.Service, state *ga.State) {
|
||||
}
|
||||
|
||||
// if no motion detected in living room for 30mins
|
||||
if s.State == "off" && time.Now().Sub(s.LastChanged).Minutes() > 30 {
|
||||
if s.State == "off" && time.Since(s.LastChanged).Minutes() > 30 {
|
||||
service.Light.TurnOff("light.main_lights")
|
||||
}
|
||||
}
|
||||
|
||||
8
state.go
8
state.go
@@ -32,3 +32,11 @@ func (s *State) Get(entityId string) (EntityState, error) {
|
||||
json.Unmarshal(resp, &es)
|
||||
return es, nil
|
||||
}
|
||||
|
||||
func (s *State) Equals(entityId string, expectedState string) (bool, error) {
|
||||
currentState, err := s.Get(entityId)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return currentState.State == expectedState, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user