From 0ca63a5367124cd99aa33af4a16e2c43c3a90bb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesko=20Ansch=C3=BCtz?= Date: Fri, 27 Mar 2026 20:15:21 +0100 Subject: [PATCH] =?UTF-8?q?feat(scheduler):=20check()=20unterdr=C3=BCckt?= =?UTF-8?q?=20display=5Fon=20bei=20Wochenende/Override?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/internal/scheduler/scheduler.go | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/server/backend/internal/scheduler/scheduler.go b/server/backend/internal/scheduler/scheduler.go index 0de331f..02225ce 100644 --- a/server/backend/internal/scheduler/scheduler.go +++ b/server/backend/internal/scheduler/scheduler.go @@ -31,14 +31,14 @@ type AllScreensLister interface { } // Run startet den Scheduler-Loop. Blockiert bis ctx abgebrochen wird. -func Run(ctx context.Context, schedules *store.ScreenScheduleStore, screens ScreenSlugGetter, notifier DisplayCommander) { +func Run(ctx context.Context, schedules *store.ScreenScheduleStore, screens ScreenSlugGetter, globalOverrides *store.GlobalOverrideStore, notifier DisplayCommander) { ticker := time.NewTicker(1 * time.Minute) defer ticker.Stop() for { select { case <-ticker.C: - check(ctx, schedules, screens, notifier) + check(ctx, schedules, screens, globalOverrides, notifier) case <-ctx.Done(): return } @@ -153,9 +153,19 @@ func resolveDesiredState(sc store.ScreenSchedule, globalOverride *store.GlobalOv } // check prüft alle aktiven Zeitpläne und sendet ggf. Befehle. -func check(ctx context.Context, schedules *store.ScreenScheduleStore, screens ScreenSlugGetter, notifier DisplayCommander) { +func check(ctx context.Context, schedules *store.ScreenScheduleStore, screens ScreenSlugGetter, globalOverrides *store.GlobalOverrideStore, 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") + now := time.Now() + nowStr := now.Format("15:04") + + // Wochenende: keine Einschalte-Kommandos senden + isWeekend := now.Weekday() == time.Saturday || now.Weekday() == time.Sunday + + // Globaler Override "off" aktiv? + globalOverrideOff := false + if o, err := globalOverrides.Get(ctx); err == nil && o != nil && now.Before(o.Until) && o.Type == "off" { + globalOverrideOff = true + } enabled, err := schedules.ListEnabled(ctx) if err != nil { @@ -171,9 +181,9 @@ func check(ctx context.Context, schedules *store.ScreenScheduleStore, screens Sc } var action string - if sc.PowerOnTime != "" && sc.PowerOnTime == now { + if sc.PowerOnTime != "" && sc.PowerOnTime == nowStr { action = "display_on" - } else if sc.PowerOffTime != "" && sc.PowerOffTime == now { + } else if sc.PowerOffTime != "" && sc.PowerOffTime == nowStr { action = "display_off" } @@ -181,6 +191,19 @@ func check(ctx context.Context, schedules *store.ScreenScheduleStore, screens Sc continue } + // display_on unterdrücken wenn per-Screen-Override, Wochenende oder globaler Override "off" + if action == "display_on" { + if sc.OverrideOnUntil != nil && now.Before(*sc.OverrideOnUntil) { + // per-Screen Override aktiv → Kommando trotzdem senden (Override = on) + } else if isWeekend { + slog.Info("scheduler: display_on unterdrückt (Wochenende)", "screen_id", sc.ScreenID) + continue + } else if globalOverrideOff { + slog.Info("scheduler: display_on unterdrückt (globaler Override off)", "screen_id", sc.ScreenID) + 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 {