refactor variable system to be the responsibility of effect enforcer.
This commit is contained in:
@@ -7,9 +7,7 @@ import (
|
||||
"git.aiterp.net/lucifer3/server/events"
|
||||
"git.aiterp.net/lucifer3/server/internal/color"
|
||||
"git.aiterp.net/lucifer3/server/internal/gentools"
|
||||
"git.aiterp.net/lucifer3/server/services/variables"
|
||||
"github.com/google/uuid"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@@ -24,6 +22,8 @@ func NewService(resolver device.Resolver, sceneMap device.SceneMap) lucifer3.Act
|
||||
|
||||
supportFlags: make(map[string]device.SupportFlags),
|
||||
colorFlags: make(map[string]device.ColorFlags),
|
||||
temperatures: make(map[string]float64),
|
||||
motions: make(map[string]float64),
|
||||
}
|
||||
|
||||
return s
|
||||
@@ -36,7 +36,8 @@ type effectEnforcer struct {
|
||||
|
||||
supportFlags map[string]device.SupportFlags
|
||||
colorFlags map[string]device.ColorFlags
|
||||
variables variables.Variables
|
||||
temperatures map[string]float64
|
||||
motions map[string]float64
|
||||
|
||||
started uint32
|
||||
|
||||
@@ -48,7 +49,7 @@ func (s *effectEnforcer) Active() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *effectEnforcer) HandleEvent(_ *lucifer3.EventBus, event lucifer3.Event) {
|
||||
func (s *effectEnforcer) HandleEvent(bus *lucifer3.EventBus, event lucifer3.Event) {
|
||||
switch event := event.(type) {
|
||||
case events.HardwareState:
|
||||
s.mu.Lock()
|
||||
@@ -75,19 +76,21 @@ func (s *effectEnforcer) HandleEvent(_ *lucifer3.EventBus, event lucifer3.Event)
|
||||
}
|
||||
s.mu.Unlock()
|
||||
|
||||
case variables.PropertyPatch:
|
||||
case events.DeviceAssigned:
|
||||
s.triggerVariableEffects(bus, event.DeviceID)
|
||||
|
||||
case events.MotionSensed:
|
||||
s.mu.Lock()
|
||||
s.variables = s.variables.WithPropertyPatch(event)
|
||||
s.motions[event.ID] = event.SecondsSince
|
||||
s.mu.Unlock()
|
||||
|
||||
case events.AliasAdded:
|
||||
s.triggerVariableEffects()
|
||||
case events.AliasRemoved:
|
||||
s.triggerVariableEffects()
|
||||
case events.MotionSensed:
|
||||
s.triggerVariableEffects()
|
||||
s.triggerVariableEffects(bus, event.ID)
|
||||
case events.TemperatureChanged:
|
||||
s.triggerVariableEffects()
|
||||
s.mu.Lock()
|
||||
s.temperatures[event.ID] = event.Temperature
|
||||
s.mu.Unlock()
|
||||
|
||||
s.triggerVariableEffects(bus, event.ID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,11 +162,68 @@ func (s *effectEnforcer) HandleCommand(bus *lucifer3.EventBus, command lucifer3.
|
||||
}
|
||||
}
|
||||
|
||||
func (s *effectEnforcer) triggerVariableEffects() {
|
||||
func (s *effectEnforcer) triggerVariableEffects(bus *lucifer3.EventBus, id string) {
|
||||
now := time.Now()
|
||||
|
||||
s.mu.Lock()
|
||||
for _, run := range s.list {
|
||||
found := false
|
||||
for _, id2 := range run.ids {
|
||||
if id2 == id {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
|
||||
run.variables = map[string]float64{}
|
||||
|
||||
totalMotion := 0.0
|
||||
motionSamples := 0
|
||||
minMotion := 0.0
|
||||
maxMotion := 0.0
|
||||
totalTemperature := 0.0
|
||||
temperatureSamples := 0
|
||||
minTemperature := 0.0
|
||||
maxTemperature := 0.0
|
||||
for _, id := range run.ids {
|
||||
if motion, ok := s.motions[id]; ok {
|
||||
totalMotion += motion
|
||||
motionSamples += 1
|
||||
if motion < minMotion || motionSamples == 1 {
|
||||
minMotion = motion
|
||||
}
|
||||
if motion > maxMotion {
|
||||
maxMotion = motion
|
||||
}
|
||||
}
|
||||
if temperature, ok := s.temperatures[id]; ok {
|
||||
totalTemperature += temperature
|
||||
temperatureSamples += 1
|
||||
if temperature < minTemperature || temperatureSamples == 1 {
|
||||
minTemperature = temperature
|
||||
}
|
||||
if temperature > maxTemperature {
|
||||
maxTemperature = temperature
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if temperatureSamples > 0 {
|
||||
run.variables["temperature.avg"] = totalTemperature / float64(temperatureSamples)
|
||||
run.variables["temperature.min"] = minTemperature
|
||||
run.variables["temperature.max"] = maxTemperature
|
||||
}
|
||||
if motionSamples > 0 {
|
||||
run.variables["motion.avg"] = totalMotion / float64(motionSamples)
|
||||
run.variables["motion.min"] = minMotion
|
||||
run.variables["motion.max"] = maxMotion
|
||||
}
|
||||
|
||||
bus.RunEvent(events.AssignmentVariables{ID: run.id, Map: gentools.CopyMap(run.variables)})
|
||||
|
||||
if _, ok := run.effect.(lucifer3.VariableEffect); ok {
|
||||
run.due = now
|
||||
}
|
||||
@@ -200,37 +260,13 @@ func (s *effectEnforcer) runLoop(bus *lucifer3.EventBus) {
|
||||
|
||||
state := run.effect.State(j, len(run.ids), run.round)
|
||||
if vEff, ok := run.effect.(lucifer3.VariableEffect); ok {
|
||||
variableName := strings.Split(vEff.VariableName(), ".")
|
||||
if len(variableName) == 0 {
|
||||
variableName = append(variableName, "avg")
|
||||
}
|
||||
|
||||
var value *variables.AvgMinMax
|
||||
switch variableName[0] {
|
||||
case "temperature":
|
||||
if value2, ok := s.variables.Temperature[run.match]; ok {
|
||||
value = &value2
|
||||
}
|
||||
case "motion":
|
||||
if value2, ok := s.variables.Motion[run.match]; ok {
|
||||
value = &value2
|
||||
}
|
||||
}
|
||||
|
||||
if value != nil {
|
||||
switch variableName[1] {
|
||||
case "min":
|
||||
state = vEff.VariableState(j, len(run.ids), value.Min)
|
||||
case "max":
|
||||
state = vEff.VariableState(j, len(run.ids), value.Max)
|
||||
case "avg":
|
||||
state = vEff.VariableState(j, len(run.ids), value.Avg)
|
||||
}
|
||||
variableName := vEff.VariableName()
|
||||
if variable, ok := run.variables[variableName]; ok {
|
||||
state = vEff.VariableState(j, len(run.ids), variable)
|
||||
}
|
||||
}
|
||||
|
||||
batch[id] = state
|
||||
|
||||
}
|
||||
|
||||
if freq := run.effect.Frequency(); freq > 0 {
|
||||
@@ -312,13 +348,14 @@ func (s *effectEnforcer) runLoop(bus *lucifer3.EventBus) {
|
||||
}
|
||||
|
||||
type effectEnforcerRun struct {
|
||||
id uuid.UUID
|
||||
match string
|
||||
due time.Time
|
||||
ids []string
|
||||
effect lucifer3.Effect
|
||||
dead bool
|
||||
round int
|
||||
id uuid.UUID
|
||||
match string
|
||||
due time.Time
|
||||
ids []string
|
||||
effect lucifer3.Effect
|
||||
dead bool
|
||||
round int
|
||||
variables map[string]float64
|
||||
}
|
||||
|
||||
// remove takes out an id from the effect, and returns whether the effect is empty.
|
||||
|
||||
Reference in New Issue
Block a user