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.

169 lines
4.4 KiB

  1. package uistate
  2. import (
  3. lucifer3 "git.aiterp.net/lucifer3/server"
  4. "git.aiterp.net/lucifer3/server/commands"
  5. "git.aiterp.net/lucifer3/server/effects"
  6. "git.aiterp.net/lucifer3/server/events"
  7. "git.aiterp.net/lucifer3/server/internal/color"
  8. "git.aiterp.net/lucifer3/server/internal/gentools"
  9. "git.aiterp.net/lucifer3/server/services/script"
  10. "github.com/google/uuid"
  11. "sync"
  12. )
  13. func NewService() lucifer3.ActiveService {
  14. return &service{
  15. data: Data{
  16. Devices: map[string]Device{},
  17. Assignments: map[uuid.UUID]Assignment{},
  18. Scripts: map[string][]script.Line{},
  19. },
  20. }
  21. }
  22. type service struct {
  23. mu sync.Mutex
  24. data Data
  25. listener []chan Patch
  26. }
  27. func (s *service) Active() bool {
  28. return true
  29. }
  30. func (s *service) HandleCommand(bus *lucifer3.EventBus, command lucifer3.Command) {
  31. var patches []Patch
  32. switch command := command.(type) {
  33. case commands.SetState:
  34. rgb := color.Color{}
  35. if command.State.Color != nil {
  36. rgb, _ = command.State.Color.ToRGB()
  37. }
  38. patches = []Patch{{Device: &DevicePatch{
  39. ID: command.ID,
  40. DesiredState: &command.State,
  41. DesiredColorRGB: rgb.RGB,
  42. }}}
  43. case commands.SetStateBatch:
  44. for id, state := range command {
  45. rgb := color.Color{}
  46. if state.Color != nil {
  47. rgb, _ = state.Color.ToRGB()
  48. }
  49. patches = append(patches, Patch{
  50. Device: &DevicePatch{
  51. ID: id,
  52. DesiredState: gentools.ShallowCopy(&state),
  53. DesiredColorRGB: rgb.RGB,
  54. },
  55. })
  56. }
  57. case script.Update:
  58. patches = append(patches, Patch{
  59. Script: &ScriptPatch{Name: command.Name, Lines: command.Lines},
  60. })
  61. }
  62. if len(patches) > 0 {
  63. s.mu.Lock()
  64. s.data = s.data.WithPatch(patches...)
  65. s.mu.Unlock()
  66. for _, patch := range patches {
  67. bus.RunEvent(patch)
  68. }
  69. }
  70. }
  71. func (s *service) HandleEvent(bus *lucifer3.EventBus, event lucifer3.Event) {
  72. var patches []Patch
  73. switch event := event.(type) {
  74. case events.AliasAdded:
  75. patches = []Patch{{Device: &DevicePatch{ID: event.ID, AddAlias: &event.Alias}}}
  76. case events.AliasRemoved:
  77. patches = []Patch{{Device: &DevicePatch{ID: event.ID, RemoveAlias: &event.Alias}}}
  78. case events.HardwareState:
  79. patches = []Patch{{Device: &DevicePatch{ID: event.ID, HWState: &event}}}
  80. if event.State.Color != nil {
  81. rgb, _ := event.State.Color.ToRGB()
  82. patches = append(patches, Patch{Device: &DevicePatch{
  83. ID: event.ID,
  84. ActiveColorRGB: gentools.Ptr(rgb.RGB.Round()),
  85. }})
  86. } else {
  87. patches = append(patches, Patch{Device: &DevicePatch{
  88. ID: event.ID,
  89. ClearActiveColorRGB: false,
  90. }})
  91. }
  92. case events.HardwareMetadata:
  93. patches = []Patch{{Device: &DevicePatch{ID: event.ID, HWMetadata: &event}}}
  94. case events.AssignmentCreated:
  95. patches = []Patch{{Assignment: &AssignmentPatch{
  96. ID: event.ID,
  97. Effect: &effects.Serializable{Effect: event.Effect},
  98. }}}
  99. case events.AssignmentRemoved:
  100. patches = []Patch{{Assignment: &AssignmentPatch{
  101. ID: event.ID,
  102. Delete: true,
  103. }}}
  104. case events.MotionSensed:
  105. patches = []Patch{{Device: &DevicePatch{
  106. ID: event.ID,
  107. Sensors: &DeviceSensors{LastMotion: gentools.Ptr(event.SecondsSince)},
  108. }}}
  109. case events.TemperatureChanged:
  110. patches = []Patch{{Device: &DevicePatch{
  111. ID: event.ID,
  112. Sensors: &DeviceSensors{Temperature: gentools.Ptr(event.Temperature)},
  113. }}}
  114. case events.DeviceAssigned:
  115. // Un-assign from current assignment (if any)
  116. if d, ok := s.data.Devices[event.DeviceID]; ok && d.Assignment != nil {
  117. patches = append(patches, Patch{Assignment: &AssignmentPatch{
  118. ID: *d.Assignment,
  119. RemoveDeviceID: &d.ID,
  120. }})
  121. }
  122. // Assign to current assignment (if it's not cleared)
  123. if event.AssignmentID != nil {
  124. patches = append(patches, Patch{Assignment: &AssignmentPatch{
  125. ID: *event.AssignmentID,
  126. AddDeviceID: &event.DeviceID,
  127. }})
  128. }
  129. // Always set the assignment
  130. patches = append(patches, Patch{Device: &DevicePatch{
  131. ID: event.DeviceID,
  132. Assignment: gentools.ShallowCopy(event.AssignmentID),
  133. ClearAssignment: event.AssignmentID == nil,
  134. }})
  135. case events.AssignmentVariables:
  136. // Always set the assignment
  137. if len(event.Map) > 0 {
  138. patches = append(patches, Patch{Assignment: &AssignmentPatch{
  139. ID: event.ID,
  140. Variables: event.Map,
  141. }})
  142. }
  143. }
  144. if len(patches) > 0 {
  145. s.mu.Lock()
  146. s.data = s.data.WithPatch(patches...)
  147. s.mu.Unlock()
  148. for _, patch := range patches {
  149. bus.RunEvent(patch)
  150. }
  151. }
  152. }