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.

252 lines
5.5 KiB

  1. package api
  2. import (
  3. "context"
  4. "git.aiterp.net/lucifer/new-server/app/config"
  5. "git.aiterp.net/lucifer/new-server/app/services/scene"
  6. "git.aiterp.net/lucifer/new-server/models"
  7. "github.com/gin-gonic/gin"
  8. "golang.org/x/sync/errgroup"
  9. "log"
  10. "time"
  11. )
  12. func fetchDevices(ctx context.Context, fetchStr string) ([]models.Device, error) {
  13. kind, value := models.ParseFetchString(fetchStr)
  14. return config.DeviceRepository().FetchByReference(ctx, kind, value)
  15. }
  16. func Devices(r gin.IRoutes) {
  17. r.GET("", handler(func(c *gin.Context) (interface{}, error) {
  18. return config.DeviceRepository().FetchByReference(ctxOf(c), models.RKAll, "")
  19. }))
  20. r.GET("/:fetch", handler(func(c *gin.Context) (interface{}, error) {
  21. return fetchDevices(ctxOf(c), c.Param("fetch"))
  22. }))
  23. r.PUT("", handler(func(c *gin.Context) (interface{}, error) {
  24. var body []struct {
  25. Fetch string `json:"fetch"`
  26. SetState models.NewDeviceState `json:"setState"`
  27. }
  28. err := parseBody(c, &body)
  29. if err != nil {
  30. return nil, err
  31. }
  32. set := make(map[int]bool)
  33. changed := make([]models.Device, 0, 64)
  34. for _, job := range body {
  35. devices, err := fetchDevices(ctxOf(c), job.Fetch)
  36. if err != nil {
  37. return nil, err
  38. }
  39. if len(devices) == 0 {
  40. return []models.Device{}, nil
  41. }
  42. for i := range devices {
  43. if set[devices[i].ID] {
  44. continue
  45. }
  46. err := devices[i].SetState(job.SetState)
  47. if err != nil {
  48. return nil, err
  49. }
  50. _ = scene.GlobalManager().UpdateDevice(ctxOf(c), &devices[i], nil)
  51. set[devices[i].ID] = true
  52. changed = append(changed, devices[i])
  53. }
  54. }
  55. config.PublishChannel <- scene.GlobalManager().FilterUnassigned(changed)
  56. go func() {
  57. for _, device := range changed {
  58. err := config.DeviceRepository().Save(context.Background(), &device, models.SMState)
  59. if err != nil {
  60. log.Println("Failed to save device for state:", err)
  61. continue
  62. }
  63. }
  64. }()
  65. return changed, nil
  66. }))
  67. r.PUT("/:fetch", handler(func(c *gin.Context) (interface{}, error) {
  68. update := models.DeviceUpdate{}
  69. err := parseBody(c, &update)
  70. if err != nil {
  71. return nil, err
  72. }
  73. devices, err := fetchDevices(ctxOf(c), c.Param("fetch"))
  74. if err != nil {
  75. return nil, err
  76. }
  77. if len(devices) == 0 {
  78. return []models.Device{}, nil
  79. }
  80. for i := range devices {
  81. devices[i].ApplyUpdate(update)
  82. err := config.DeviceRepository().Save(context.Background(), &devices[i], models.SMProperties)
  83. if err != nil {
  84. log.Println("Failed to save device for state:", err)
  85. continue
  86. }
  87. }
  88. return devices, nil
  89. }))
  90. r.PUT("/:fetch/state", handler(func(c *gin.Context) (interface{}, error) {
  91. state := models.NewDeviceState{}
  92. err := parseBody(c, &state)
  93. if err != nil {
  94. return nil, err
  95. }
  96. devices, err := fetchDevices(ctxOf(c), c.Param("fetch"))
  97. if err != nil {
  98. return nil, err
  99. }
  100. if len(devices) == 0 {
  101. return []models.Device{}, nil
  102. }
  103. for i := range devices {
  104. err := devices[i].SetState(state)
  105. if err != nil {
  106. return nil, err
  107. }
  108. _ = scene.GlobalManager().UpdateDevice(ctxOf(c), &devices[i], nil)
  109. }
  110. config.PublishChannel <- scene.GlobalManager().FilterUnassigned(devices)
  111. go func() {
  112. for _, device := range devices {
  113. err := config.DeviceRepository().Save(context.Background(), &device, models.SMState)
  114. if err != nil {
  115. log.Println("Failed to save device for state:", err)
  116. continue
  117. }
  118. }
  119. }()
  120. return devices, nil
  121. }))
  122. r.PUT("/:fetch/tags", handler(func(c *gin.Context) (interface{}, error) {
  123. var body struct {
  124. Add []string `json:"add"`
  125. Remove []string `json:"remove"`
  126. }
  127. err := parseBody(c, &body)
  128. if err != nil {
  129. return nil, err
  130. }
  131. devices, err := fetchDevices(ctxOf(c), c.Param("fetch"))
  132. if err != nil {
  133. return nil, err
  134. }
  135. if len(devices) == 0 {
  136. return []models.Device{}, nil
  137. }
  138. for i := range devices {
  139. device := &devices[i]
  140. for _, tag := range body.Add {
  141. found := false
  142. for _, tag2 := range device.Tags {
  143. if tag == tag2 {
  144. found = true
  145. break
  146. }
  147. }
  148. if !found {
  149. device.Tags = append(device.Tags, tag)
  150. }
  151. }
  152. for _, tag := range body.Remove {
  153. index := -1
  154. for i, tag2 := range device.Tags {
  155. if tag == tag2 {
  156. index = i
  157. }
  158. }
  159. if index == -1 {
  160. continue
  161. }
  162. device.Tags = append(device.Tags[:index], device.Tags[index+1:]...)
  163. }
  164. err = config.DeviceRepository().Save(ctxOf(c), device, models.SMTags)
  165. if err != nil {
  166. return nil, err
  167. }
  168. }
  169. return devices, nil
  170. }))
  171. r.PUT("/:fetch/scene", handler(func(c *gin.Context) (interface{}, error) {
  172. var body models.DeviceSceneAssignment
  173. err := parseBody(c, &body)
  174. if err != nil {
  175. return nil, err
  176. }
  177. devices, err := fetchDevices(ctxOf(c), c.Param("fetch"))
  178. if err != nil {
  179. return nil, err
  180. }
  181. if len(devices) == 0 {
  182. return []models.Device{}, nil
  183. }
  184. assignedScene, err := config.SceneRepository().Find(ctxOf(c), body.SceneID)
  185. if err != nil {
  186. return nil, err
  187. }
  188. if body.DurationMS < 0 {
  189. body.DurationMS = 0
  190. }
  191. body.StartTime = time.Now()
  192. for i := range devices {
  193. devices[i].SceneAssignments = []models.DeviceSceneAssignment{body}
  194. err := scene.GlobalManager().UpdateDevice(ctxOf(c), &devices[i], assignedScene)
  195. if err != nil {
  196. return nil, err
  197. }
  198. }
  199. eg := errgroup.Group{}
  200. for i := range devices {
  201. eg.Go(func() error {
  202. return config.DeviceRepository().Save(ctxOf(c), &devices[i], 0)
  203. })
  204. }
  205. err = eg.Wait()
  206. if err != nil {
  207. return nil, err
  208. }
  209. return devices, nil
  210. }))
  211. }