add variable system + fix bugs here and there.
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
package variables
|
||||
|
||||
import "git.aiterp.net/lucifer3/server/internal/gentools"
|
||||
|
||||
type Variables struct {
|
||||
Temperature map[string]AvgMinMax `json:"temperature"`
|
||||
Motion map[string]AvgMinMax `json:"motion"`
|
||||
}
|
||||
|
||||
func (v Variables) WithPropertyPatch(patch PropertyPatch) Variables {
|
||||
if patch.Motion != nil {
|
||||
v.Motion = gentools.CopyMap(v.Motion)
|
||||
v.Motion[patch.Key] = *patch.Motion
|
||||
}
|
||||
if patch.Temperature != nil {
|
||||
v.Temperature = gentools.CopyMap(v.Temperature)
|
||||
v.Temperature[patch.Key] = *patch.Temperature
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
type AvgMinMax struct {
|
||||
Avg float64 `json:"avg"`
|
||||
Min float64 `json:"min"`
|
||||
Max float64 `json:"max"`
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package variables
|
||||
|
||||
import "fmt"
|
||||
|
||||
type PropertyPatch struct {
|
||||
Key string `json:"id"`
|
||||
Temperature *AvgMinMax `json:"temperature,omitempty"`
|
||||
Motion *AvgMinMax `json:"motion,omitempty"`
|
||||
}
|
||||
|
||||
func (e PropertyPatch) VerboseKey() string {
|
||||
return "variables.PropertyPatch"
|
||||
}
|
||||
|
||||
func (e PropertyPatch) EventDescription() string {
|
||||
return fmt.Sprintf("variables.PropertyPatch(key=%s)", e.Key)
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package variables
|
||||
|
||||
import (
|
||||
lucifer3 "git.aiterp.net/lucifer3/server"
|
||||
"git.aiterp.net/lucifer3/server/events"
|
||||
"git.aiterp.net/lucifer3/server/services"
|
||||
)
|
||||
|
||||
func NewService(resolver *services.Resolver) lucifer3.Service {
|
||||
return &service{
|
||||
resolver: resolver,
|
||||
temperatures: map[string]float64{},
|
||||
motions: map[string]float64{},
|
||||
}
|
||||
}
|
||||
|
||||
type service struct {
|
||||
resolver *services.Resolver
|
||||
temperatures map[string]float64
|
||||
motions map[string]float64
|
||||
}
|
||||
|
||||
func (s *service) Active() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *service) HandleEvent(bus *lucifer3.EventBus, event lucifer3.Event) {
|
||||
var patchEvents []lucifer3.Event
|
||||
|
||||
switch event := event.(type) {
|
||||
case events.MotionSensed:
|
||||
s.motions[event.ID] = event.SecondsSince
|
||||
patchEvents = s.updateDevice(event.ID)
|
||||
case events.TemperatureChanged:
|
||||
s.temperatures[event.ID] = event.Temperature
|
||||
patchEvents = s.updateDevice(event.ID)
|
||||
case events.AliasAdded:
|
||||
patchEvents = s.updateDevice(event.ID)
|
||||
case events.AliasRemoved:
|
||||
patchEvents = s.updateDevice(event.ID)
|
||||
}
|
||||
|
||||
bus.RunEvents(patchEvents)
|
||||
}
|
||||
|
||||
func (s *service) updateDevice(id string) []lucifer3.Event {
|
||||
ptr := s.resolver.GetByID(id)
|
||||
if ptr == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
res := make([]lucifer3.Event, 0, len(ptr.Aliases)+1)
|
||||
|
||||
for _, alias := range append([]string{ptr.ID}, ptr.Aliases...) {
|
||||
patch := PropertyPatch{Key: alias}
|
||||
motionSamples := 0.0
|
||||
motionTotal := 0.0
|
||||
temperatureSamples := 0.0
|
||||
temperatureTotal := 0.0
|
||||
|
||||
for _, ptr := range s.resolver.Resolve(alias) {
|
||||
if temp, ok := s.temperatures[ptr.ID]; ok {
|
||||
if patch.Temperature == nil {
|
||||
patch.Temperature = &AvgMinMax{}
|
||||
if temp < patch.Temperature.Min || temperatureSamples == 0.0 {
|
||||
patch.Temperature.Min = temp
|
||||
}
|
||||
if temp > patch.Temperature.Max {
|
||||
patch.Temperature.Max = temp
|
||||
}
|
||||
|
||||
temperatureSamples += 1.0
|
||||
temperatureTotal += temp
|
||||
}
|
||||
}
|
||||
if motion, ok := s.motions[ptr.ID]; ok {
|
||||
if patch.Motion == nil {
|
||||
patch.Motion = &AvgMinMax{}
|
||||
if motion < patch.Motion.Min || motionSamples == 0.0 {
|
||||
patch.Motion.Min = motion
|
||||
}
|
||||
if motion > patch.Motion.Max {
|
||||
patch.Motion.Max = motion
|
||||
}
|
||||
|
||||
motionSamples += 1.0
|
||||
motionTotal += motion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if temperatureSamples > 0.5 {
|
||||
patch.Temperature.Avg = temperatureTotal / temperatureSamples
|
||||
}
|
||||
if motionSamples > 0.5 {
|
||||
patch.Motion.Avg = motionTotal / motionSamples
|
||||
}
|
||||
|
||||
res = append(res, patch)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
Reference in New Issue
Block a user