add Duration for entityListener and rename TimeString to DurationString

This commit is contained in:
Sam Lewis
2022-10-30 23:07:54 -04:00
parent 47ba299568
commit b22b544437
4 changed files with 42 additions and 15 deletions

13
app.go
View File

@@ -2,7 +2,6 @@ package gomeassistant
import (
"context"
"fmt"
"log"
"os"
"time"
@@ -30,7 +29,11 @@ type app struct {
eventListeners map[string][]*EventListener
}
type TimeString string
/*
DurationString represents a duration, such as "2s" or "24h".
See https://pkg.go.dev/time#ParseDuration for all valid time units.
*/
type DurationString string
/*
NewApp establishes the websocket connection and returns an object
@@ -112,7 +115,7 @@ func (a *app) RegisterEventListener(evl EventListener) {
}
}
func getSunriseSunset(a *app, sunrise bool, offset []TimeString) carbon.Carbon {
func getSunriseSunset(a *app, sunrise bool, offset []DurationString) carbon.Carbon {
printString := "Sunset"
attrKey := "next_setting"
if sunrise {
@@ -145,10 +148,6 @@ func getSunriseSunset(a *app, sunrise bool, offset []TimeString) carbon.Carbon {
return nextSetOrRise
}
func carbon2TimeString(c carbon.Carbon) string {
return fmt.Sprintf("%02d:%02d", c.Hour(), c.Minute())
}
func (a *app) Start() {
// schedules
go runSchedules(a)

View File

@@ -17,6 +17,8 @@ type EntityListener struct {
betweenEnd string
throttle time.Duration
lastRan carbon.Carbon
delay time.Duration
delayTimer *time.Timer
}
type EntityListenerCallback func(*Service, EntityData)
@@ -111,7 +113,20 @@ func (b elBuilder3) ToState(s string) elBuilder3 {
return b
}
func (b elBuilder3) Throttle(s TimeString) elBuilder3 {
func (b elBuilder3) Duration(s DurationString) elBuilder3 {
// TODO: test this, should rename duration? not sure if Delay implies that state change cancels the callback
// if change name to Duration then enforce being used with ToState, should FromState be allowed?
// if FromState set to 3, then state changes to 2 and changes again to 1 halfway through delay, should the
// delay reset?
d, err := time.ParseDuration(string(s))
if err != nil {
log.Fatalf("Couldn't parse string duration passed to For(): \"%s\" see https://pkg.go.dev/time#ParseDuration for valid time units", s)
}
b.entityListener.delay = d
return b
}
func (b elBuilder3) Throttle(s DurationString) elBuilder3 {
d, err := time.ParseDuration(string(s))
if err != nil {
log.Fatalf("Couldn't parse string duration passed to Throttle(): \"%s\" see https://pkg.go.dev/time#ParseDuration for valid time units", s)
@@ -145,6 +160,9 @@ func callEntityListeners(app *app, msgBytes []byte) {
continue
}
if c := checkStatesMatch(l.toState, data.NewState.State); c.fail {
if l.delayTimer != nil {
l.delayTimer.Stop()
}
continue
}
if c := checkThrottle(l.throttle, l.lastRan); c.fail {
@@ -159,6 +177,16 @@ func callEntityListeners(app *app, msgBytes []byte) {
ToAttributes: data.NewState.Attributes,
LastChanged: data.OldState.LastChanged,
}
if l.delay != 0 {
l.delayTimer = time.AfterFunc(l.delay, func() {
go l.callback(app.service, entityData)
l.lastRan = carbon.Now()
})
return
}
// run now if no delay set
go l.callback(app.service, entityData)
l.lastRan = carbon.Now()
}

View File

@@ -71,7 +71,7 @@ func (b eventListenerBuilder3) OnlyBefore(end string) eventListenerBuilder3 {
return b
}
func (b eventListenerBuilder3) Throttle(s TimeString) eventListenerBuilder3 {
func (b eventListenerBuilder3) Throttle(s DurationString) eventListenerBuilder3 {
d, err := time.ParseDuration(string(s))
if err != nil {
log.Fatalf("Couldn't parse string duration passed to Throttle(): \"%s\" see https://pkg.go.dev/time#ParseDuration for valid time units", s)

View File

@@ -20,7 +20,7 @@ type Schedule struct {
isSunrise bool
isSunset bool
sunOffset TimeString
sunOffset DurationString
}
func (s Schedule) Hash() string {
@@ -98,7 +98,7 @@ func (sb scheduleBuilderDaily) At(s string) scheduleBuilderEnd {
// Sunrise takes an app pointer and an optional duration string that is passed to time.ParseDuration.
// Examples include "-1.5h", "30m", etc. See https://pkg.go.dev/time#ParseDuration
// for full list.
func (sb scheduleBuilderDaily) Sunrise(a *app, offset ...TimeString) scheduleBuilderEnd {
func (sb scheduleBuilderDaily) Sunrise(a *app, offset ...DurationString) scheduleBuilderEnd {
sb.schedule.realStartTime = getSunriseSunset(a, true, offset).Carbon2Time()
sb.schedule.isSunrise = true
return scheduleBuilderEnd(sb)
@@ -107,13 +107,13 @@ func (sb scheduleBuilderDaily) Sunrise(a *app, offset ...TimeString) scheduleBui
// Sunset takes an app pointer and an optional duration string that is passed to time.ParseDuration.
// Examples include "-1.5h", "30m", etc. See https://pkg.go.dev/time#ParseDuration
// for full list.
func (sb scheduleBuilderDaily) Sunset(a *app, offset ...TimeString) scheduleBuilderEnd {
func (sb scheduleBuilderDaily) Sunset(a *app, offset ...DurationString) scheduleBuilderEnd {
sb.schedule.realStartTime = getSunriseSunset(a, false, offset).Carbon2Time()
sb.schedule.isSunset = true
return scheduleBuilderEnd(sb)
}
func (sb scheduleBuilderCall) Every(s TimeString) scheduleBuilderCustom {
func (sb scheduleBuilderCall) Every(s DurationString) scheduleBuilderCustom {
d, err := time.ParseDuration(string(s))
if err != nil {
log.Fatalf("couldn't parse string duration passed to Every(): \"%s\" see https://pkg.go.dev/time#ParseDuration for valid time units", s)
@@ -122,7 +122,7 @@ func (sb scheduleBuilderCall) Every(s TimeString) scheduleBuilderCustom {
return scheduleBuilderCustom(sb)
}
func (sb scheduleBuilderCustom) Offset(s TimeString) scheduleBuilderEnd {
func (sb scheduleBuilderCustom) Offset(s DurationString) scheduleBuilderEnd {
t, err := time.ParseDuration(string(s))
if err != nil {
log.Fatalf("Couldn't parse string duration passed to Offset(): \"%s\" see https://pkg.go.dev/time#ParseDuration for valid time units", s)
@@ -174,7 +174,7 @@ func popSchedule(a *app) Schedule {
func requeueSchedule(a *app, s Schedule) {
if s.isSunrise || s.isSunset {
nextSunTime := getSunriseSunset(a, s.isSunrise, []TimeString{s.sunOffset})
nextSunTime := getSunriseSunset(a, s.isSunrise, []DurationString{s.sunOffset})
// this is true when there is a negative offset, so schedule runs before sunset/sunrise and
// HA still shows today's sunset as next sunset. Just add 24h as a default handler