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/gentools" "git.aiterp.net/lucifer3/server/services/variables" "sync" ) func NewService() lucifer3.ActiveService { return &service{} } 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: patches = []Patch{{Device: &DevicePatch{ID: command.ID, DesiredState: &command.State}}} case commands.SetStateBatch: for id, state := range command { patches = append(patches, Patch{ Device: &DevicePatch{ID: id, DesiredState: gentools.ShallowCopy(&state)}, }) } } 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 variables.PropertyPatch: patches = append(patches, Patch{VariableProperty: &event}) } if len(patches) > 0 { s.mu.Lock() s.data = s.data.WithPatch(patches...) s.mu.Unlock() for _, patch := range patches { bus.RunEvent(patch) } } }