From 88036cfcae5956ae2c914d70c151cbe6ce25f6ec Mon Sep 17 00:00:00 2001 From: Gisle Aune Date: Sun, 8 Jan 2023 17:07:53 +0100 Subject: [PATCH] add state filtering to effect enforcer. --- commands/state.go | 12 ++++++- services/effectenforcer.go | 71 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/commands/state.go b/commands/state.go index b508800..32ff3bb 100644 --- a/commands/state.go +++ b/commands/state.go @@ -30,7 +30,17 @@ func (c SetState) VerboseKey() string { type SetStateBatch map[string]device.State func (c SetStateBatch) CommandDescription() string { - return fmt.Sprintf("SetStateBatch(%d devices)", len(c)) + b := strings.Builder{} + b.WriteByte('\n') + for key, value := range c { + b.WriteString(" ") + b.WriteString(key) + b.WriteString(": ") + b.WriteString(value.String()) + b.WriteRune('\n') + } + + return fmt.Sprintf("SetStateBatch(%s)", b.String()) } func (c SetStateBatch) VerboseKey() string { diff --git a/services/effectenforcer.go b/services/effectenforcer.go index e505e20..22a5bda 100644 --- a/services/effectenforcer.go +++ b/services/effectenforcer.go @@ -5,6 +5,7 @@ import ( "git.aiterp.net/lucifer3/server/commands" "git.aiterp.net/lucifer3/server/device" "git.aiterp.net/lucifer3/server/events" + "git.aiterp.net/lucifer3/server/internal/color" "git.aiterp.net/lucifer3/server/internal/gentools" "github.com/google/uuid" "sync" @@ -18,6 +19,9 @@ func NewEffectEnforcer(resolver device.Resolver, sceneMap device.SceneMap) lucif sceneMap: sceneMap, list: make([]*effectEnforcerRun, 0, 16), index: make(map[string]*effectEnforcerRun, 8), + + supportFlags: make(map[string]device.SupportFlags), + colorFlags: make(map[string]device.ColorFlags), } return s @@ -28,6 +32,9 @@ type effectEnforcer struct { resolver device.Resolver sceneMap device.SceneMap + supportFlags map[string]device.SupportFlags + colorFlags map[string]device.ColorFlags + started uint32 list []*effectEnforcerRun @@ -40,6 +47,22 @@ func (s *effectEnforcer) Active() bool { func (s *effectEnforcer) HandleEvent(_ *lucifer3.EventBus, event lucifer3.Event) { switch event := event.(type) { + case events.HardwareState: + s.mu.Lock() + colorFlags := s.colorFlags + supportFlags := s.supportFlags + s.mu.Unlock() + + colorFlags = gentools.CopyMap(colorFlags) + supportFlags = gentools.CopyMap(supportFlags) + colorFlags[event.ID] = event.ColorFlags + supportFlags[event.ID] = event.SupportFlags + + s.mu.Lock() + s.colorFlags = colorFlags + s.supportFlags = supportFlags + s.mu.Unlock() + case events.DeviceReady: // If the device is managed by the effect enforcer, cause the effect to be // re-ran. @@ -127,6 +150,9 @@ func (s *effectEnforcer) runLoop(bus *lucifer3.EventBus) { deleteIDs = deleteIDs[:0] s.mu.Lock() + colorFlags := s.colorFlags + supportFlags := s.supportFlags + for i, run := range s.list { if run.dead { deleteIDs = append(deleteIDs, run.id) @@ -173,6 +199,51 @@ func (s *effectEnforcer) runLoop(bus *lucifer3.EventBus) { } if len(batch) > 0 { + for id, state := range batch { + sf := supportFlags[id] + + if state.Power != nil && !sf.HasAny(device.SFlagPower) { + state.Power = nil + } + if state.Temperature != nil && !sf.HasAny(device.SFlagTemperature) { + state.Temperature = nil + } + if state.Intensity != nil && !sf.HasAny(device.SFlagIntensity) { + state.Intensity = nil + } + if state.Color != nil && !sf.HasAny(device.SFlagColor) { + state.Color = nil + } else { + cf := colorFlags[id] + invalid := (state.Color.K != nil && !cf.HasAll(device.CFlagKelvin)) || + (state.Color.XY != nil && !cf.HasAll(device.CFlagXY)) || + (state.Color.RGB != nil && !cf.HasAll(device.CFlagRGB)) || + (state.Color.HS != nil && !cf.HasAll(device.CFlagHS)) + + if invalid { + var converted color.Color + var ok bool + + switch { + case cf.HasAny(device.CFlagXY): + converted, ok = state.Color.ToXY() + case cf.HasAny(device.CFlagRGB): + converted, ok = state.Color.ToRGB() + case cf.HasAny(device.CFlagHS): + converted, ok = state.Color.ToHS() + } + + if !ok { + state.Color = nil + } else { + state.Color = &converted + } + } + } + + batch[id] = state + } + bus.RunCommand(batch) batch = make(commands.SetStateBatch, 64) }