You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
181 lines
4.7 KiB
181 lines
4.7 KiB
package uistate
|
|
|
|
import (
|
|
lucifer3 "git.aiterp.net/lucifer3/server"
|
|
"git.aiterp.net/lucifer3/server/commands"
|
|
"git.aiterp.net/lucifer3/server/effects"
|
|
"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/script"
|
|
"github.com/google/uuid"
|
|
"sync"
|
|
)
|
|
|
|
func NewService() lucifer3.ActiveService {
|
|
return &service{
|
|
data: Data{
|
|
Devices: map[string]Device{},
|
|
Assignments: map[uuid.UUID]Assignment{},
|
|
Scripts: map[string][]script.Line{},
|
|
Triggers: map[uuid.UUID]script.Trigger{},
|
|
},
|
|
}
|
|
}
|
|
|
|
type service struct {
|
|
mu sync.Mutex
|
|
data Data
|
|
listener []chan Patch
|
|
}
|
|
|
|
func (s *service) Active() bool {
|
|
return true
|
|
}
|
|
|
|
func (s *service) HandleCommand(bus *lucifer3.EventBus, command lucifer3.Command) {
|
|
var patches []Patch
|
|
|
|
switch command := command.(type) {
|
|
case commands.SetState:
|
|
rgb := color.Color{}
|
|
if command.State.Color != nil {
|
|
rgb, _ = command.State.Color.ToRGB()
|
|
}
|
|
|
|
patches = []Patch{{Device: &DevicePatch{
|
|
ID: command.ID,
|
|
DesiredState: &command.State,
|
|
DesiredColorRGB: rgb.RGB,
|
|
}}}
|
|
case commands.SetStateBatch:
|
|
for id, state := range command {
|
|
rgb := color.Color{}
|
|
if state.Color != nil {
|
|
rgb, _ = state.Color.ToRGB()
|
|
}
|
|
|
|
patches = append(patches, Patch{
|
|
Device: &DevicePatch{
|
|
ID: id,
|
|
DesiredState: gentools.ShallowCopy(&state),
|
|
DesiredColorRGB: rgb.RGB,
|
|
},
|
|
})
|
|
}
|
|
case script.Update:
|
|
patches = append(patches, Patch{
|
|
Script: &ScriptPatch{Name: command.Name, Lines: command.Lines},
|
|
})
|
|
case script.UpdateTrigger:
|
|
patches = append(patches, Patch{
|
|
Trigger: &TriggerPatch{Trigger: script.Trigger(command)},
|
|
})
|
|
case script.DeleteTrigger:
|
|
patches = append(patches, Patch{
|
|
Trigger: &TriggerPatch{
|
|
Trigger: script.Trigger{ID: command.ID},
|
|
Delete: true,
|
|
},
|
|
})
|
|
}
|
|
|
|
if len(patches) > 0 {
|
|
s.mu.Lock()
|
|
s.data = s.data.WithPatch(patches...)
|
|
s.mu.Unlock()
|
|
|
|
for _, patch := range patches {
|
|
bus.RunEvent(patch)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *service) HandleEvent(bus *lucifer3.EventBus, event lucifer3.Event) {
|
|
var patches []Patch
|
|
|
|
switch event := event.(type) {
|
|
case events.AliasAdded:
|
|
patches = []Patch{{Device: &DevicePatch{ID: event.ID, AddAlias: &event.Alias}}}
|
|
case events.AliasRemoved:
|
|
patches = []Patch{{Device: &DevicePatch{ID: event.ID, RemoveAlias: &event.Alias}}}
|
|
case events.HardwareState:
|
|
patches = []Patch{{Device: &DevicePatch{ID: event.ID, HWState: &event}}}
|
|
if event.State.Color != nil {
|
|
rgb, _ := event.State.Color.ToRGB()
|
|
patches = append(patches, Patch{Device: &DevicePatch{
|
|
ID: event.ID,
|
|
ActiveColorRGB: gentools.Ptr(rgb.RGB.Round()),
|
|
}})
|
|
} else {
|
|
patches = append(patches, Patch{Device: &DevicePatch{
|
|
ID: event.ID,
|
|
ClearActiveColorRGB: false,
|
|
}})
|
|
}
|
|
case events.HardwareMetadata:
|
|
patches = []Patch{{Device: &DevicePatch{ID: event.ID, HWMetadata: &event}}}
|
|
case events.AssignmentCreated:
|
|
patches = []Patch{{Assignment: &AssignmentPatch{
|
|
ID: event.ID,
|
|
Effect: &effects.Serializable{Effect: event.Effect},
|
|
}}}
|
|
case events.AssignmentRemoved:
|
|
patches = []Patch{{Assignment: &AssignmentPatch{
|
|
ID: event.ID,
|
|
Delete: true,
|
|
}}}
|
|
case events.MotionSensed:
|
|
patches = []Patch{{Device: &DevicePatch{
|
|
ID: event.ID,
|
|
Sensors: &DeviceSensors{LastMotion: gentools.Ptr(event.SecondsSince)},
|
|
}}}
|
|
case events.TemperatureChanged:
|
|
patches = []Patch{{Device: &DevicePatch{
|
|
ID: event.ID,
|
|
Sensors: &DeviceSensors{Temperature: gentools.Ptr(event.Temperature)},
|
|
}}}
|
|
case events.DeviceAssigned:
|
|
// Un-assign from current assignment (if any)
|
|
if d, ok := s.data.Devices[event.DeviceID]; ok && d.Assignment != nil {
|
|
patches = append(patches, Patch{Assignment: &AssignmentPatch{
|
|
ID: *d.Assignment,
|
|
RemoveDeviceID: &d.ID,
|
|
}})
|
|
}
|
|
|
|
// Assign to current assignment (if it's not cleared)
|
|
if event.AssignmentID != nil {
|
|
patches = append(patches, Patch{Assignment: &AssignmentPatch{
|
|
ID: *event.AssignmentID,
|
|
AddDeviceID: &event.DeviceID,
|
|
}})
|
|
}
|
|
|
|
// Always set the assignment
|
|
patches = append(patches, Patch{Device: &DevicePatch{
|
|
ID: event.DeviceID,
|
|
Assignment: gentools.ShallowCopy(event.AssignmentID),
|
|
ClearAssignment: event.AssignmentID == nil,
|
|
}})
|
|
case events.AssignmentVariables:
|
|
// Always set the assignment
|
|
if len(event.Map) > 0 {
|
|
patches = append(patches, Patch{Assignment: &AssignmentPatch{
|
|
ID: event.ID,
|
|
Variables: event.Map,
|
|
}})
|
|
}
|
|
|
|
}
|
|
|
|
if len(patches) > 0 {
|
|
s.mu.Lock()
|
|
s.data = s.data.WithPatch(patches...)
|
|
s.mu.Unlock()
|
|
|
|
for _, patch := range patches {
|
|
bus.RunEvent(patch)
|
|
}
|
|
}
|
|
}
|