mirror of
https://github.com/Xevion/go-ha.git
synced 2025-12-06 09:15:12 -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
|
NewApp 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 NewApp(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)
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ func NewApp(connString string) app {
|
|||||||
service := NewService(conn, ctx, httpClient)
|
service := NewService(conn, ctx, httpClient)
|
||||||
state := newState(httpClient)
|
state := newState(httpClient)
|
||||||
|
|
||||||
return app{
|
return &app{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
ctxCancel: ctxCancel,
|
ctxCancel: ctxCancel,
|
||||||
@@ -65,6 +65,12 @@ func (a *app) Cleanup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *app) RegisterSchedule(s schedule) {
|
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 {
|
if s.frequency == 0 {
|
||||||
log.Fatalln("A schedule must call either Daily() or Every() when built.")
|
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.
|
func getSunriseSunset(a *app, sunrise bool, offset []TimeString) carbon.Carbon {
|
||||||
// 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 {
|
|
||||||
printString := "Sunset"
|
printString := "Sunset"
|
||||||
attrKey := "next_setting"
|
attrKey := "next_setting"
|
||||||
if sunrise {
|
if sunrise {
|
||||||
@@ -150,7 +142,7 @@ func getSunriseSunset(a *app, sunrise bool, offset []TimeString) string {
|
|||||||
nextSetOrRise = nextSetOrRise.AddMinutes(int(t.Minutes()))
|
nextSetOrRise = nextSetOrRise.AddMinutes(int(t.Minutes()))
|
||||||
}
|
}
|
||||||
|
|
||||||
return carbon2TimeString(nextSetOrRise)
|
return nextSetOrRise
|
||||||
}
|
}
|
||||||
|
|
||||||
func carbon2TimeString(c carbon.Carbon) string {
|
func carbon2TimeString(c carbon.Carbon) string {
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
package gomeassistant
|
package gomeassistant
|
||||||
|
|
||||||
// TODO: impl eventListener. could probably create generic listener struct for
|
|
||||||
// code reuse between eventListener and eventListener
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log"
|
"log"
|
||||||
|
|||||||
@@ -25,6 +25,13 @@ func main() {
|
|||||||
At("23:00").
|
At("23:00").
|
||||||
Build()
|
Build()
|
||||||
|
|
||||||
|
_30minsBeforeSunrise := ga.
|
||||||
|
ScheduleBuilder().
|
||||||
|
Call(sunriseSched).
|
||||||
|
Daily().
|
||||||
|
Sunrise(app, "-30m").
|
||||||
|
Build()
|
||||||
|
|
||||||
zwaveEventListener := ga.
|
zwaveEventListener := ga.
|
||||||
EventListenerBuilder().
|
EventListenerBuilder().
|
||||||
EventTypes("zwave_js_value_notification").
|
EventTypes("zwave_js_value_notification").
|
||||||
@@ -33,6 +40,7 @@ func main() {
|
|||||||
|
|
||||||
app.RegisterEntityListener(pantryDoor)
|
app.RegisterEntityListener(pantryDoor)
|
||||||
app.RegisterSchedule(_11pmSched)
|
app.RegisterSchedule(_11pmSched)
|
||||||
|
app.RegisterSchedule(_30minsBeforeSunrise)
|
||||||
app.RegisterEventListener(zwaveEventListener)
|
app.RegisterEventListener(zwaveEventListener)
|
||||||
|
|
||||||
app.Start()
|
app.Start()
|
||||||
@@ -72,3 +80,8 @@ func lightsOut(service *ga.Service, state *ga.State) {
|
|||||||
service.Light.TurnOff("light.main_lights")
|
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
|
offset time.Duration
|
||||||
realStartTime time.Time
|
realStartTime time.Time
|
||||||
|
|
||||||
|
isSunrise bool
|
||||||
|
isSunset bool
|
||||||
|
sunOffset TimeString
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s schedule) Hash() string {
|
func (s schedule) Hash() string {
|
||||||
@@ -107,6 +111,24 @@ func (sb scheduleBuilderDaily) At(s string) scheduleBuilderEnd {
|
|||||||
return scheduleBuilderEnd(sb)
|
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 {
|
func (sb scheduleBuilderCall) Every(s TimeString) scheduleBuilderCustom {
|
||||||
d, err := time.ParseDuration(string(s))
|
d, err := time.ParseDuration(string(s))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -145,7 +167,7 @@ func runSchedules(a *app) {
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
sched := popSchedule(a)
|
sched := popSchedule(a)
|
||||||
// log.Default().Println(sched.realStartTime)
|
log.Default().Println(sched.realStartTime)
|
||||||
|
|
||||||
// run callback for all schedules before now in case they overlap
|
// run callback for all schedules before now in case they overlap
|
||||||
for sched.realStartTime.Before(time.Now()) {
|
for sched.realStartTime.Before(time.Now()) {
|
||||||
@@ -167,11 +189,20 @@ func popSchedule(a *app) schedule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func requeueSchedule(a *app, s schedule) {
|
func requeueSchedule(a *app, s schedule) {
|
||||||
// TODO: figure out how to handle sunset/sunrise in here. Maybe just
|
if s.isSunrise || s.isSunset {
|
||||||
// add sunrise bool and sunset bool to Schedule, might have to change
|
nextSunTime := getSunriseSunset(a, s.isSunrise, []TimeString{s.sunOffset})
|
||||||
// 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
|
// this is true when there is a negative offset, so schedule runs before sunset/sunrise and
|
||||||
// language sentence structure but maybe simplest way to get it working
|
// HA still shows today's sunset as next sunset. Just add 24h as a default handler
|
||||||
s.realStartTime = s.realStartTime.Add(s.frequency)
|
// 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()))
|
a.schedules.Insert(s, float64(s.realStartTime.Unix()))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user