daemon: pause work on device disconnect to save battery
This commit is contained in:
parent
3eaf9dc0c4
commit
20c46e18b3
@ -9,6 +9,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"streamdeck-lets-go/internal/config"
|
"streamdeck-lets-go/internal/config"
|
||||||
@ -357,6 +358,7 @@ type AutoSwitchManager struct {
|
|||||||
lastManualPage string
|
lastManualPage string
|
||||||
autoPage string
|
autoPage string
|
||||||
autoStay bool
|
autoStay bool
|
||||||
|
paused atomic.Bool // disables auto-switch when device is disconnected
|
||||||
}
|
}
|
||||||
|
|
||||||
type compiledRule struct {
|
type compiledRule struct {
|
||||||
@ -410,6 +412,25 @@ func (m *AutoSwitchManager) NotifyManualPage(name string) {
|
|||||||
slog.Debug("auto-switch: manual page set", "page", name)
|
slog.Debug("auto-switch: manual page set", "page", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pause disables auto-switch evaluation — use when the device is disconnected
|
||||||
|
// to prevent unnecessary page switches on a closed deck.
|
||||||
|
func (m *AutoSwitchManager) Pause() {
|
||||||
|
m.paused.Store(true)
|
||||||
|
slog.Debug("auto-switch: paused")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resume re-enables auto-switch evaluation after reconnect.
|
||||||
|
// Stale window events should be drained from the channel before resuming.
|
||||||
|
func (m *AutoSwitchManager) Resume() {
|
||||||
|
m.paused.Store(false)
|
||||||
|
slog.Debug("auto-switch: resumed")
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPaused returns true when auto-switch evaluation is paused.
|
||||||
|
func (m *AutoSwitchManager) IsPaused() bool {
|
||||||
|
return m.paused.Load()
|
||||||
|
}
|
||||||
|
|
||||||
func (m *AutoSwitchManager) Evaluate(win Window, currentPage string) (page string, shouldSwitch bool) {
|
func (m *AutoSwitchManager) Evaluate(win Window, currentPage string) (page string, shouldSwitch bool) {
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
|
|||||||
38
daemon.go
38
daemon.go
@ -143,15 +143,27 @@ func Run(ctx context.Context, cfg *config.Config, opts RunOptions) error {
|
|||||||
case evt, ok := <-primaryDeck.Events():
|
case evt, ok := <-primaryDeck.Events():
|
||||||
if !ok {
|
if !ok {
|
||||||
slog.Warn("deck event channel closed, attempting reconnect...")
|
slog.Warn("deck event channel closed, attempting reconnect...")
|
||||||
|
|
||||||
|
// Stop all periodic scripts to avoid wasting cycles on a closed device.
|
||||||
|
primaryPM.stopPeriodicKeys()
|
||||||
|
asm.Pause()
|
||||||
|
|
||||||
primaryDeck.Close()
|
primaryDeck.Close()
|
||||||
newDeck := reconnectDeck(ctx, cfg, &primaryPM, asm)
|
newDeck := reconnectDeck(ctx, cfg, &primaryPM)
|
||||||
if newDeck == nil {
|
if newDeck == nil {
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update all references to the new device and page manager.
|
||||||
|
pageMgrs[0] = primaryPM
|
||||||
decks[0] = newDeck
|
decks[0] = newDeck
|
||||||
primaryDeck = newDeck
|
primaryDeck = newDeck
|
||||||
web.SetDecks(decks)
|
web.SetDecks(decks)
|
||||||
|
web.SetPageManager(primaryPM)
|
||||||
|
|
||||||
newDeck.SetBrightness(deviceBrightness(cfg, newDeck.Serial()))
|
newDeck.SetBrightness(deviceBrightness(cfg, newDeck.Serial()))
|
||||||
|
asm.NotifyManualPage(cfg.DefaultPage)
|
||||||
|
asm.Resume()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,6 +206,13 @@ func Run(ctx context.Context, cfg *config.Config, opts RunOptions) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case win := <-windowCh:
|
case win := <-windowCh:
|
||||||
|
if asm.IsPaused() {
|
||||||
|
// Drain buffered window events accumulated while disconnected.
|
||||||
|
for len(windowCh) > 0 {
|
||||||
|
<-windowCh
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
if page, ok := asm.Evaluate(win, primaryPM.ActivePageName()); ok {
|
if page, ok := asm.Evaluate(win, primaryPM.ActivePageName()); ok {
|
||||||
for _, pm := range pageMgrs {
|
for _, pm := range pageMgrs {
|
||||||
if err := pm.ActivatePage(page); err != nil {
|
if err := pm.ActivatePage(page); err != nil {
|
||||||
@ -263,15 +282,27 @@ func Run(ctx context.Context, cfg *config.Config, opts RunOptions) error {
|
|||||||
case <-reconnectTicker.C:
|
case <-reconnectTicker.C:
|
||||||
if err := primaryDeck.SetBrightness(primaryDeck.Brightness()); err != nil {
|
if err := primaryDeck.SetBrightness(primaryDeck.Brightness()); err != nil {
|
||||||
slog.Warn("deck connection lost, reconnecting...", "error", err)
|
slog.Warn("deck connection lost, reconnecting...", "error", err)
|
||||||
|
|
||||||
|
// Stop all periodic scripts to avoid wasting cycles on a closed device.
|
||||||
|
primaryPM.stopPeriodicKeys()
|
||||||
|
asm.Pause()
|
||||||
|
|
||||||
primaryDeck.Close()
|
primaryDeck.Close()
|
||||||
newDeck := reconnectDeck(ctx, cfg, &primaryPM, asm)
|
newDeck := reconnectDeck(ctx, cfg, &primaryPM)
|
||||||
if newDeck == nil {
|
if newDeck == nil {
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update all references to the new device and page manager.
|
||||||
|
pageMgrs[0] = primaryPM
|
||||||
decks[0] = newDeck
|
decks[0] = newDeck
|
||||||
primaryDeck = newDeck
|
primaryDeck = newDeck
|
||||||
web.SetDecks(decks)
|
web.SetDecks(decks)
|
||||||
|
web.SetPageManager(primaryPM)
|
||||||
|
|
||||||
newDeck.SetBrightness(deviceBrightness(cfg, newDeck.Serial()))
|
newDeck.SetBrightness(deviceBrightness(cfg, newDeck.Serial()))
|
||||||
|
asm.NotifyManualPage(cfg.DefaultPage)
|
||||||
|
asm.Resume()
|
||||||
}
|
}
|
||||||
|
|
||||||
case <-ssTicker.C:
|
case <-ssTicker.C:
|
||||||
@ -322,7 +353,7 @@ func deviceBrightness(cfg *config.Config, serial string) int {
|
|||||||
return 75
|
return 75
|
||||||
}
|
}
|
||||||
|
|
||||||
func reconnectDeck(ctx context.Context, cfg *config.Config, pm **PageManager, asm *AutoSwitchManager) *Deck {
|
func reconnectDeck(ctx context.Context, cfg *config.Config, pm **PageManager) *Deck {
|
||||||
for {
|
for {
|
||||||
newDeck, err := OpenDeck("")
|
newDeck, err := OpenDeck("")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -332,7 +363,6 @@ func reconnectDeck(ctx context.Context, cfg *config.Config, pm **PageManager, as
|
|||||||
(*pm).LoadPages(cfg.Pages)
|
(*pm).LoadPages(cfg.Pages)
|
||||||
(*pm).ActivatePage(cfg.DefaultPage)
|
(*pm).ActivatePage(cfg.DefaultPage)
|
||||||
(*pm).startPeriodicKeys()
|
(*pm).startPeriodicKeys()
|
||||||
asm.NotifyManualPage(cfg.DefaultPage)
|
|
||||||
return newDeck
|
return newDeck
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user