mirror of
https://github.com/Xevion/go-ha.git
synced 2025-12-05 23:15:07 -06:00
sunrise sunset working, not the cleanest solution but it works
This commit is contained in:
28
app.go
28
app.go
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
45
schedule.go
45
schedule.go
@@ -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()))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user