add variable system + fix bugs here and there.

This commit is contained in:
2023-01-13 01:19:34 +01:00
parent 88036cfcae
commit 842f96d8e3
22 changed files with 368 additions and 43 deletions
+27
View File
@@ -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"`
}
+17
View File
@@ -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)
}
+103
View File
@@ -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
}