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

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