some tweaks/renames, schedule documentation

This commit is contained in:
Sam Lewis
2022-11-01 01:20:15 -04:00
parent cbfce76897
commit b0804e39d0
6 changed files with 61 additions and 53 deletions

86
app.go
View File

@@ -41,16 +41,16 @@ type timeRange struct {
} }
/* /*
NewApp establishes the websocket connection and returns an object App establishes the websocket connection and returns an object
you can use to register schedules and listeners. you can use to register schedules and listeners.
*/ */
func NewApp(connString string) *app { func App(connString string) *app {
token := os.Getenv("HA_AUTH_TOKEN") token := os.Getenv("HA_AUTH_TOKEN")
conn, ctx, ctxCancel := ws.SetupConnection(connString, token) conn, ctx, ctxCancel := ws.SetupConnection(connString, token)
httpClient := http.NewHttpClient(connString, token) httpClient := http.NewHttpClient(connString, token)
service := NewService(conn, ctx, httpClient) service := newService(conn, ctx, httpClient)
state := newState(httpClient) state := newState(httpClient)
return &app{ return &app{
@@ -72,54 +72,60 @@ func (a *app) Cleanup() {
} }
} }
func (a *app) RegisterSchedule(s Schedule) { func (a *app) RegisterSchedules(schedules ...Schedule) {
// realStartTime already set for sunset/sunrise for _, s := range schedules {
if s.isSunrise || s.isSunset { // realStartTime already set for sunset/sunrise
a.schedules.Insert(s, float64(s.realStartTime.Unix())) if s.isSunrise || s.isSunset {
return a.schedules.Insert(s, float64(s.realStartTime.Unix()))
} return
}
if s.frequency == 0 { if s.frequency == 0 {
panic("A schedule must use either Daily() or Every() when built.") panic("A schedule must use either Daily() or Every() when built.")
} }
now := time.Now() now := time.Now()
startTime := carbon.Now().StartOfDay().Carbon2Time() startTime := carbon.Now().StartOfDay().Carbon2Time()
// apply offset if set // apply offset if set
if s.offset.Minutes() > 0 { if s.offset.Minutes() > 0 {
startTime = startTime.Add(s.offset) startTime = startTime.Add(s.offset)
} }
// advance first scheduled time by frequency until it is in the future // advance first scheduled time by frequency until it is in the future
for startTime.Before(now) { for startTime.Before(now) {
startTime = startTime.Add(s.frequency) startTime = startTime.Add(s.frequency)
} }
s.realStartTime = startTime s.realStartTime = startTime
a.schedules.Insert(s, float64(startTime.Unix())) a.schedules.Insert(s, float64(startTime.Unix()))
}
} }
func (a *app) RegisterEntityListener(etl EntityListener) { func (a *app) RegisterEntityListeners(etls ...EntityListener) {
if etl.delay != 0 && etl.toState == "" { for _, etl := range etls {
panic("EntityListener error: you have to use ToState() when using Duration()") if etl.delay != 0 && etl.toState == "" {
} panic("EntityListener error: you have to use ToState() when using Duration()")
}
for _, entity := range etl.entityIds { for _, entity := range etl.entityIds {
if elList, ok := a.entityListeners[entity]; ok { if elList, ok := a.entityListeners[entity]; ok {
a.entityListeners[entity] = append(elList, &etl) a.entityListeners[entity] = append(elList, &etl)
} else { } else {
a.entityListeners[entity] = []*EntityListener{&etl} a.entityListeners[entity] = []*EntityListener{&etl}
}
} }
} }
} }
func (a *app) RegisterEventListener(evl EventListener) { func (a *app) RegisterEventListeners(evls ...EventListener) {
for _, eventType := range evl.eventTypes { for _, evl := range evls {
if elList, ok := a.eventListeners[eventType]; ok { for _, eventType := range evl.eventTypes {
a.eventListeners[eventType] = append(elList, &evl) if elList, ok := a.eventListeners[eventType]; ok {
} else { a.eventListeners[eventType] = append(elList, &evl)
ws.SubscribeToEventType(eventType, a.conn, a.ctx) } else {
a.eventListeners[eventType] = []*EventListener{&evl} ws.SubscribeToEventType(eventType, a.conn, a.ctx)
a.eventListeners[eventType] = []*EventListener{&evl}
}
} }
} }
} }

View File

@@ -26,6 +26,7 @@ type EntityListener struct {
exceptionRanges []timeRange exceptionRanges []timeRange
} }
// TODO: add state object as second arg
type EntityListenerCallback func(*Service, EntityData) type EntityListenerCallback func(*Service, EntityData)
type EntityData struct { type EntityData struct {
@@ -60,7 +61,7 @@ type msgState struct {
/* Methods */ /* Methods */
func EntityListenerBuilder() elBuilder1 { func NewEntityListener() elBuilder1 {
return elBuilder1{EntityListener{ return elBuilder1{EntityListener{
lastRan: carbon.Now().StartOfCentury(), lastRan: carbon.Now().StartOfCentury(),
}} }}

View File

@@ -21,6 +21,7 @@ type EventListener struct {
exceptionRanges []timeRange exceptionRanges []timeRange
} }
// TODO: add state object as second arg
type EventListenerCallback func(*Service, EventData) type EventListenerCallback func(*Service, EventData)
type EventData struct { type EventData struct {
@@ -30,7 +31,7 @@ type EventData struct {
/* Methods */ /* Methods */
func EventListenerBuilder() eventListenerBuilder1 { func NewEventListener() eventListenerBuilder1 {
return eventListenerBuilder1{EventListener{ return eventListenerBuilder1{EventListener{
lastRan: carbon.Now().StartOfCentury(), lastRan: carbon.Now().StartOfCentury(),
}} }}

View File

@@ -9,39 +9,39 @@ import (
) )
func main() { func main() {
app := ga.NewApp("0.0.0.0:8123") // Replace with your Home Assistant IP Address app := ga.App("0.0.0.0:8123") // Replace with your Home Assistant IP Address
defer app.Cleanup() defer app.Cleanup()
pantryDoor := ga. pantryDoor := ga.
EntityListenerBuilder(). NewEntityListener().
EntityIds("binary_sensor.pantry_door"). EntityIds("binary_sensor.pantry_door").
Call(pantryLights). Call(pantryLights).
Build() Build()
_11pmSched := ga. _11pmSched := ga.
ScheduleBuilder(). NewSchedule().
Call(lightsOut). Call(lightsOut).
Daily(). Daily().
At("23:00"). At("23:00").
Build() Build()
_30minsBeforeSunrise := ga. _30minsBeforeSunrise := ga.
ScheduleBuilder(). NewSchedule().
Call(sunriseSched). Call(sunriseSched).
Daily(). Daily().
Sunrise(app, "-30m"). Sunrise(app, "-30m").
Build() Build()
zwaveEventListener := ga. zwaveEventListener := ga.
EventListenerBuilder(). NewEventListener().
EventTypes("zwave_js_value_notification"). EventTypes("zwave_js_value_notification").
Call(onEvent). Call(onEvent).
Build() Build()
app.RegisterEntityListener(pantryDoor) app.RegisterEntityListeners(pantryDoor)
app.RegisterSchedule(_11pmSched) app.RegisterSchedules(_11pmSched)
app.RegisterSchedule(_30minsBeforeSunrise) app.RegisterSchedules(_30minsBeforeSunrise)
app.RegisterEventListener(zwaveEventListener) app.RegisterEventListeners(zwaveEventListener)
app.Start() app.Start()

View File

@@ -50,7 +50,7 @@ type scheduleBuilderEnd struct {
schedule Schedule schedule Schedule
} }
func ScheduleBuilder() scheduleBuilder { func NewSchedule() scheduleBuilder {
return scheduleBuilder{ return scheduleBuilder{
Schedule{ Schedule{
frequency: 0, frequency: 0,

View File

@@ -20,7 +20,7 @@ type Service struct {
InputNumber *services.InputNumber InputNumber *services.InputNumber
} }
func NewService(conn *websocket.Conn, ctx context.Context, httpClient *http.HttpClient) *Service { func newService(conn *websocket.Conn, ctx context.Context, httpClient *http.HttpClient) *Service {
return &Service{ return &Service{
Light: services.BuildService[services.Light](conn, ctx), Light: services.BuildService[services.Light](conn, ctx),
HomeAssistant: services.BuildService[services.HomeAssistant](conn, ctx), HomeAssistant: services.BuildService[services.HomeAssistant](conn, ctx),