73 lines
2.1 KiB
Go
73 lines
2.1 KiB
Go
// Package scheduler enthält den Display-Zeitplan-Scheduler.
|
|
// Er prüft jede Minute ob ein Screen ein- oder ausgeschaltet werden soll.
|
|
package scheduler
|
|
|
|
import (
|
|
"context"
|
|
"log/slog"
|
|
"time"
|
|
|
|
"git.az-it.net/az/morz-infoboard/server/backend/internal/store"
|
|
)
|
|
|
|
// DisplayCommander sendet einen Display-Befehl per MQTT.
|
|
type DisplayCommander interface {
|
|
SendDisplayCommand(screenSlug, action string) error
|
|
}
|
|
|
|
// ScreenSlugGetter lädt den Slug für eine Screen-ID.
|
|
type ScreenSlugGetter interface {
|
|
GetByID(ctx context.Context, id string) (*store.Screen, error)
|
|
}
|
|
|
|
// Run startet den Scheduler-Loop. Blockiert bis ctx abgebrochen wird.
|
|
func Run(ctx context.Context, schedules *store.ScreenScheduleStore, screens ScreenSlugGetter, notifier DisplayCommander) {
|
|
ticker := time.NewTicker(1 * time.Minute)
|
|
defer ticker.Stop()
|
|
|
|
for {
|
|
select {
|
|
case <-ticker.C:
|
|
check(ctx, schedules, screens, notifier)
|
|
case <-ctx.Done():
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// check prüft alle aktiven Zeitpläne und sendet ggf. Befehle.
|
|
func check(ctx context.Context, schedules *store.ScreenScheduleStore, screens ScreenSlugGetter, notifier DisplayCommander) {
|
|
// Uses process-local timezone — ensure TZ env var is set in the container (e.g. Europe/Berlin).
|
|
now := time.Now().Format("15:04")
|
|
|
|
enabled, err := schedules.ListEnabled(ctx)
|
|
if err != nil {
|
|
slog.Error("scheduler: list enabled schedules failed", "err", err)
|
|
return
|
|
}
|
|
|
|
for _, sc := range enabled {
|
|
screen, err := screens.GetByID(ctx, sc.ScreenID)
|
|
if err != nil {
|
|
slog.Warn("scheduler: screen not found", "screen_id", sc.ScreenID, "err", err)
|
|
continue
|
|
}
|
|
|
|
var action string
|
|
if sc.PowerOnTime != "" && sc.PowerOnTime == now {
|
|
action = "display_on"
|
|
} else if sc.PowerOffTime != "" && sc.PowerOffTime == now {
|
|
action = "display_off"
|
|
}
|
|
|
|
if action == "" {
|
|
continue
|
|
}
|
|
|
|
if err := notifier.SendDisplayCommand(screen.Slug, action); err != nil {
|
|
slog.Error("scheduler: send command failed", "screen_id", sc.ScreenID, "action", action, "err", err)
|
|
} else {
|
|
slog.Info("scheduler: display command sent", "screen_id", sc.ScreenID, "slug", screen.Slug, "action", action)
|
|
}
|
|
}
|
|
}
|