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.

174 lines
3.8 KiB

  1. package api
  2. import (
  3. "context"
  4. "git.aiterp.net/lucifer/new-server/app/config"
  5. "git.aiterp.net/lucifer/new-server/models"
  6. "github.com/gin-gonic/gin"
  7. "log"
  8. "strings"
  9. )
  10. func fetchDevices(ctx context.Context, fetchStr string) ([]models.Device, error) {
  11. if strings.HasPrefix(fetchStr, "tag:") {
  12. return config.DeviceRepository().FetchByReference(ctx, models.RKTag, fetchStr[4:])
  13. } else if strings.HasPrefix(fetchStr, "bridge:") {
  14. return config.DeviceRepository().FetchByReference(ctx, models.RKBridgeID, fetchStr[7:])
  15. } else if fetchStr == "all" {
  16. return config.DeviceRepository().FetchByReference(ctx, models.RKAll, "")
  17. } else {
  18. return config.DeviceRepository().FetchByReference(ctx, models.RKDeviceID, fetchStr)
  19. }
  20. }
  21. func Devices(r gin.IRoutes) {
  22. r.GET("", handler(func(c *gin.Context) (interface{}, error) {
  23. return config.DeviceRepository().FetchByReference(ctxOf(c), models.RKAll, "")
  24. }))
  25. r.GET("/:fetch", handler(func(c *gin.Context) (interface{}, error) {
  26. return fetchDevices(ctxOf(c), c.Param("fetch"))
  27. }))
  28. r.PUT("/batch", handler(func(c *gin.Context) (interface{}, error) {
  29. var body []struct {
  30. Fetch string `json:"fetch"`
  31. SetState models.NewDeviceState `json:"setState"`
  32. }
  33. err := parseBody(c, &body)
  34. if err != nil {
  35. return nil, err
  36. }
  37. set := make(map[int]bool)
  38. changed := make([]models.Device, 0, 64)
  39. for _, job := range body {
  40. devices, err := fetchDevices(ctxOf(c), job.Fetch)
  41. if err != nil {
  42. return nil, err
  43. }
  44. if len(devices) == 0 {
  45. return []models.Device{}, nil
  46. }
  47. for i := range devices {
  48. if set[devices[i].ID] {
  49. continue
  50. }
  51. err := devices[i].SetState(job.SetState)
  52. if err != nil {
  53. return nil, err
  54. }
  55. set[devices[i].ID] = true
  56. changed = append(changed, devices[i])
  57. }
  58. }
  59. config.PublishChannel <- changed
  60. go func() {
  61. for _, device := range changed {
  62. err := config.DeviceRepository().Save(context.Background(), &device)
  63. if err != nil {
  64. log.Println("Failed to save device for state:", err)
  65. continue
  66. }
  67. }
  68. }()
  69. return changed, nil
  70. }))
  71. r.PUT("/:fetch/state", handler(func(c *gin.Context) (interface{}, error) {
  72. state := models.NewDeviceState{}
  73. err := parseBody(c, &state)
  74. if err != nil {
  75. return nil, err
  76. }
  77. devices, err := fetchDevices(ctxOf(c), c.Param("fetch"))
  78. if err != nil {
  79. return nil, err
  80. }
  81. if len(devices) == 0 {
  82. return []models.Device{}, nil
  83. }
  84. for i := range devices {
  85. err := devices[i].SetState(state)
  86. if err != nil {
  87. return nil, err
  88. }
  89. }
  90. config.PublishChannel <- devices
  91. go func() {
  92. for _, device := range devices {
  93. err := config.DeviceRepository().Save(context.Background(), &device)
  94. if err != nil {
  95. log.Println("Failed to save device for state:", err)
  96. continue
  97. }
  98. }
  99. }()
  100. return devices, nil
  101. }))
  102. r.PUT("/:fetch/tags", handler(func(c *gin.Context) (interface{}, error) {
  103. var body struct {
  104. Add []string `json:"add"`
  105. Remove []string `json:"remove"`
  106. }
  107. err := parseBody(c, &body)
  108. if err != nil {
  109. return nil, err
  110. }
  111. devices, err := fetchDevices(ctxOf(c), c.Param("fetch"))
  112. if err != nil {
  113. return nil, err
  114. }
  115. if len(devices) == 0 {
  116. return []models.Device{}, nil
  117. }
  118. for i := range devices {
  119. device := &devices[i]
  120. for _, tag := range body.Add {
  121. found := false
  122. for _, tag2 := range device.Tags {
  123. if tag == tag2 {
  124. found = true
  125. break
  126. }
  127. }
  128. if !found {
  129. device.Tags = append(device.Tags, tag)
  130. }
  131. }
  132. for _, tag := range body.Remove {
  133. index := -1
  134. for i, tag2 := range device.Tags {
  135. if tag == tag2 {
  136. index = i
  137. }
  138. }
  139. device.Tags = append(device.Tags[:index], device.Tags[index+1:]...)
  140. }
  141. err = config.DeviceRepository().Save(ctxOf(c), device)
  142. if err != nil {
  143. return nil, err
  144. }
  145. }
  146. return devices, nil
  147. }))
  148. }