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.

149 lines
4.4 KiB

  1. package uistate
  2. import (
  3. "git.aiterp.net/lucifer3/server/device"
  4. "git.aiterp.net/lucifer3/server/effects"
  5. "git.aiterp.net/lucifer3/server/events"
  6. "git.aiterp.net/lucifer3/server/internal/color"
  7. "git.aiterp.net/lucifer3/server/internal/gentools"
  8. "git.aiterp.net/lucifer3/server/services/script"
  9. "github.com/google/uuid"
  10. )
  11. type Data struct {
  12. Devices map[string]Device `json:"devices"`
  13. Assignments map[uuid.UUID]Assignment `json:"assignments"`
  14. Scripts map[string][]script.Line `json:"scripts"`
  15. }
  16. func (d *Data) WithPatch(patches ...Patch) Data {
  17. newData := d.Copy()
  18. for _, patch := range patches {
  19. if patch.Device != nil {
  20. pd := d.ensureDevice(patch.Device.ID)
  21. gentools.ApplyUpdateSlice(&pd.Aliases, patch.Device.SetAliases)
  22. gentools.ApplyUpdate(&pd.Name, patch.Device.Name)
  23. gentools.ApplyUpdatePtr(&pd.HWState, patch.Device.HWState)
  24. gentools.ApplyUpdatePtr(&pd.HWMetadata, patch.Device.HWMetadata)
  25. gentools.ApplyUpdatePtr(&pd.DesiredState, patch.Device.DesiredState)
  26. gentools.ApplyUpdatePtr(&pd.Assignment, patch.Device.Assignment)
  27. gentools.ApplyUpdatePtr(&pd.ActiveColorRGB, patch.Device.ActiveColorRGB)
  28. if patch.Device.AddAlias != nil {
  29. pd.Aliases = append(pd.Aliases[:0:0], pd.Aliases...)
  30. pd.Aliases = append(pd.Aliases, *patch.Device.AddAlias)
  31. }
  32. if patch.Device.RemoveAlias != nil {
  33. for i, alias := range pd.Aliases {
  34. if alias == *patch.Device.RemoveAlias {
  35. pd.Aliases = append(pd.Aliases[:0:0], pd.Aliases...)
  36. pd.Aliases = append(pd.Aliases[:i], pd.Aliases[i+1:]...)
  37. break
  38. }
  39. }
  40. }
  41. if patch.Device.ClearAssignment {
  42. pd.Assignment = nil
  43. }
  44. if patch.Device.ClearActiveColorRGB {
  45. pd.ActiveColorRGB = nil
  46. }
  47. if patch.Device.Sensors != nil {
  48. if patch.Device.Sensors.LastMotion != nil {
  49. pd.Sensors.LastMotion = gentools.ShallowCopy(patch.Device.Sensors.LastMotion)
  50. }
  51. if patch.Device.Sensors.Temperature != nil {
  52. pd.Sensors.Temperature = gentools.ShallowCopy(patch.Device.Sensors.Temperature)
  53. }
  54. }
  55. if patch.Device.Delete {
  56. delete(newData.Devices, pd.ID)
  57. } else {
  58. newData.Devices[pd.ID] = pd
  59. }
  60. }
  61. if patch.Assignment != nil {
  62. pa := d.ensureAssignment(patch.Assignment.ID)
  63. gentools.ApplyUpdatePtr(&pa.Effect, patch.Assignment.Effect)
  64. if patch.Assignment.AddDeviceID != nil {
  65. pa.DeviceIDs = append(pa.DeviceIDs[:0:0], pa.DeviceIDs...)
  66. pa.DeviceIDs = append(pa.DeviceIDs, *patch.Assignment.AddDeviceID)
  67. }
  68. if patch.Assignment.RemoveDeviceID != nil {
  69. for i, id := range pa.DeviceIDs {
  70. if id == *patch.Assignment.RemoveDeviceID {
  71. pa.DeviceIDs = append(pa.DeviceIDs[:0:0], pa.DeviceIDs...)
  72. pa.DeviceIDs[i] = ""
  73. break
  74. }
  75. }
  76. }
  77. if patch.Assignment.Variables != nil {
  78. pa.Variables = gentools.CopyMap(patch.Assignment.Variables)
  79. }
  80. if patch.Assignment.Delete {
  81. delete(newData.Assignments, pa.ID)
  82. } else {
  83. newData.Assignments[pa.ID] = pa
  84. }
  85. }
  86. if patch.Script != nil {
  87. newData.Scripts[patch.Script.Name] = patch.Script.Lines
  88. }
  89. }
  90. return newData
  91. }
  92. func (d *Data) Copy() Data {
  93. return Data{
  94. Devices: gentools.CopyMap(d.Devices),
  95. Assignments: gentools.CopyMap(d.Assignments),
  96. Scripts: gentools.CopyMap(d.Scripts),
  97. }
  98. }
  99. func (d *Data) ensureDevice(id string) Device {
  100. if device, ok := d.Devices[id]; ok {
  101. return device
  102. } else {
  103. return Device{ID: id}
  104. }
  105. }
  106. func (d *Data) ensureAssignment(id uuid.UUID) Assignment {
  107. if assignment, ok := d.Assignments[id]; ok {
  108. return assignment
  109. } else {
  110. return Assignment{ID: id}
  111. }
  112. }
  113. type Device struct {
  114. ID string `json:"id"`
  115. Name string `json:"name"`
  116. HWMetadata *events.HardwareMetadata `json:"hwMetadata"`
  117. HWState *events.HardwareState `json:"hwState"`
  118. ActiveColorRGB *color.RGB `json:"activeColorRgb"`
  119. DesiredState *device.State `json:"desiredState"`
  120. Aliases []string `json:"aliases"`
  121. Assignment *uuid.UUID `json:"assignment"`
  122. Sensors DeviceSensors `json:"sensors"`
  123. }
  124. type DeviceSensors struct {
  125. LastMotion *float64 `json:"lastMotion,omitempty"`
  126. Temperature *float64 `json:"temperature,omitempty"`
  127. }
  128. type Assignment struct {
  129. ID uuid.UUID `json:"id"`
  130. DeviceIDs []string `json:"deviceIds"`
  131. Effect *effects.Serializable `json:"effect"`
  132. Variables map[string]float64 `json:"variables"`
  133. }