sunrise sunset working, not the cleanest solution but it works

This commit is contained in:
Sam Lewis
2022-10-24 23:03:04 -04:00
parent a2d3b46335
commit 66e179c568
4 changed files with 61 additions and 28 deletions

28
app.go
View File

@@ -36,7 +36,7 @@ type TimeString string
NewApp establishes the websocket connection and returns an object
you can use to register schedules and listeners.
*/
func NewApp(connString string) app {
func NewApp(connString string) *app {
token := os.Getenv("HA_AUTH_TOKEN")
conn, ctx, ctxCancel := ws.SetupConnection(connString, token)
@@ -45,7 +45,7 @@ func NewApp(connString string) app {
service := NewService(conn, ctx, httpClient)
state := newState(httpClient)
return app{
return &app{
conn: conn,
ctx: ctx,
ctxCancel: ctxCancel,
@@ -65,6 +65,12 @@ func (a *app) Cleanup() {
}
func (a *app) RegisterSchedule(s schedule) {
// realStartTime already set for sunset/sunrise
if s.isSunrise || s.isSunset {
a.schedules.Insert(s, float64(s.realStartTime.Unix()))
return
}
if s.frequency == 0 {
log.Fatalln("A schedule must call either Daily() or Every() when built.")
}
@@ -106,21 +112,7 @@ func (a *app) RegisterEventListener(evl eventListener) {
}
}
// Sunrise take an optional string that is passed to time.ParseDuration.
// Examples include "-1.5h", "30m", etc. See https://pkg.go.dev/time#ParseDuration
// for full list.
func (a *app) Sunrise(offset ...TimeString) string {
return getSunriseSunset(a, true, offset)
}
// Sunset take an optional string that is passed to time.ParseDuration.
// Examples include "-1.5h", "30m", etc. See https://pkg.go.dev/time#ParseDuration
// for full list.
func (a *app) Sunset(offset ...TimeString) string {
return getSunriseSunset(a, false, offset)
}
func getSunriseSunset(a *app, sunrise bool, offset []TimeString) string {
func getSunriseSunset(a *app, sunrise bool, offset []TimeString) carbon.Carbon {
printString := "Sunset"
attrKey := "next_setting"
if sunrise {
@@ -150,7 +142,7 @@ func getSunriseSunset(a *app, sunrise bool, offset []TimeString) string {
nextSetOrRise = nextSetOrRise.AddMinutes(int(t.Minutes()))
}
return carbon2TimeString(nextSetOrRise)
return nextSetOrRise
}
func carbon2TimeString(c carbon.Carbon) string {

View File

@@ -1,8 +1,5 @@
package gomeassistant
// TODO: impl eventListener. could probably create generic listener struct for
// code reuse between eventListener and eventListener
import (
"encoding/json"
"log"

View File

@@ -25,6 +25,13 @@ func main() {
At("23:00").
Build()
_30minsBeforeSunrise := ga.
ScheduleBuilder().
Call(sunriseSched).
Daily().
Sunrise(app, "-30m").
Build()
zwaveEventListener := ga.
EventListenerBuilder().
EventTypes("zwave_js_value_notification").
@@ -33,6 +40,7 @@ func main() {
app.RegisterEntityListener(pantryDoor)
app.RegisterSchedule(_11pmSched)
app.RegisterSchedule(_30minsBeforeSunrise)
app.RegisterEventListener(zwaveEventListener)
app.Start()
@@ -72,3 +80,8 @@ func lightsOut(service *ga.Service, state *ga.State) {
service.Light.TurnOff("light.main_lights")
}
}
func sunriseSched(service *ga.Service, state *ga.State) {
service.Light.TurnOn("light.living_room_lamps")
service.Light.TurnOff("light.christmas_lights")
}

View File

@@ -33,6 +33,10 @@ type schedule struct {
*/
offset time.Duration
realStartTime time.Time
isSunrise bool
isSunset bool
sunOffset TimeString
}
func (s schedule) Hash() string {
@@ -107,6 +111,24 @@ func (sb scheduleBuilderDaily) At(s string) scheduleBuilderEnd {
return scheduleBuilderEnd(sb)
}
// 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 {
sb.schedule.realStartTime = getSunriseSunset(a, true, offset).Carbon2Time()
sb.schedule.isSunrise = true
return scheduleBuilderEnd(sb)
}
// 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 {
sb.schedule.realStartTime = getSunriseSunset(a, false, offset).Carbon2Time()
sb.schedule.isSunset = true
return scheduleBuilderEnd(sb)
}
func (sb scheduleBuilderCall) Every(s TimeString) scheduleBuilderCustom {
d, err := time.ParseDuration(string(s))
if err != nil {
@@ -145,7 +167,7 @@ func runSchedules(a *app) {
for {
sched := popSchedule(a)
// log.Default().Println(sched.realStartTime)
log.Default().Println(sched.realStartTime)
// run callback for all schedules before now in case they overlap
for sched.realStartTime.Before(time.Now()) {
@@ -167,11 +189,20 @@ func popSchedule(a *app) schedule {
}
func requeueSchedule(a *app, s schedule) {
// TODO: figure out how to handle sunset/sunrise in here. Maybe just
// add sunrise bool and sunset bool to Schedule, might have to change
// API to be .Call().Sunset("1h") instead of .Call().At(ga.Sunset("1h"))
// then that function could easily set the flag. Kinda ruins the english
// language sentence structure but maybe simplest way to get it working
s.realStartTime = s.realStartTime.Add(s.frequency)
if s.isSunrise || s.isSunset {
nextSunTime := getSunriseSunset(a, s.isSunrise, []TimeString{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
// since we can't get tomorrow's sunset from HA at this point.
if nextSunTime.IsToday() {
nextSunTime = nextSunTime.AddHours(24)
}
s.realStartTime = nextSunTime.Carbon2Time()
} else {
s.realStartTime = s.realStartTime.Add(s.frequency)
}
a.schedules.Insert(s, float64(s.realStartTime.Unix()))
}