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.

215 lines
4.9 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. "strconv"
  9. "strings"
  10. )
  11. func fetchDevices(ctx context.Context, fetchStr string) ([]models.Device, error) {
  12. if strings.HasPrefix(fetchStr, "tag:") {
  13. return config.DeviceRepository().FetchByReference(ctx, models.RKTag, fetchStr[4:])
  14. } else if strings.HasPrefix(fetchStr, "bridge:") {
  15. return config.DeviceRepository().FetchByReference(ctx, models.RKBridgeID, fetchStr[7:])
  16. } else if strings.HasPrefix(fetchStr, "id:") {
  17. return config.DeviceRepository().FetchByReference(ctx, models.RKDeviceID, fetchStr[7:])
  18. } else if strings.HasPrefix(fetchStr, "name:") {
  19. return config.DeviceRepository().FetchByReference(ctx, models.RKName, fetchStr[7:])
  20. }else if fetchStr == "all" {
  21. return config.DeviceRepository().FetchByReference(ctx, models.RKAll, "")
  22. } else {
  23. _, err := strconv.Atoi(fetchStr)
  24. if err != nil {
  25. return config.DeviceRepository().FetchByReference(ctx, models.RKName, fetchStr)
  26. }
  27. return config.DeviceRepository().FetchByReference(ctx, models.RKDeviceID, fetchStr)
  28. }
  29. }
  30. func Devices(r gin.IRoutes) {
  31. r.GET("", handler(func(c *gin.Context) (interface{}, error) {
  32. return config.DeviceRepository().FetchByReference(ctxOf(c), models.RKAll, "")
  33. }))
  34. r.GET("/:fetch", handler(func(c *gin.Context) (interface{}, error) {
  35. return fetchDevices(ctxOf(c), c.Param("fetch"))
  36. }))
  37. r.PUT("", handler(func(c *gin.Context) (interface{}, error) {
  38. var body []struct {
  39. Fetch string `json:"fetch"`
  40. SetState models.NewDeviceState `json:"setState"`
  41. }
  42. err := parseBody(c, &body)
  43. if err != nil {
  44. return nil, err
  45. }
  46. set := make(map[int]bool)
  47. changed := make([]models.Device, 0, 64)
  48. for _, job := range body {
  49. devices, err := fetchDevices(ctxOf(c), job.Fetch)
  50. if err != nil {
  51. return nil, err
  52. }
  53. if len(devices) == 0 {
  54. return []models.Device{}, nil
  55. }
  56. for i := range devices {
  57. if set[devices[i].ID] {
  58. continue
  59. }
  60. err := devices[i].SetState(job.SetState)
  61. if err != nil {
  62. return nil, err
  63. }
  64. set[devices[i].ID] = true
  65. changed = append(changed, devices[i])
  66. }
  67. }
  68. config.PublishChannel <- changed
  69. go func() {
  70. for _, device := range changed {
  71. err := config.DeviceRepository().Save(context.Background(), &device)
  72. if err != nil {
  73. log.Println("Failed to save device for state:", err)
  74. continue
  75. }
  76. }
  77. }()
  78. return changed, nil
  79. }))
  80. r.PUT("/:fetch", handler(func(c *gin.Context) (interface{}, error) {
  81. update := models.DeviceUpdate{}
  82. err := parseBody(c, &update)
  83. if err != nil {
  84. return nil, err
  85. }
  86. devices, err := fetchDevices(ctxOf(c), c.Param("fetch"))
  87. if err != nil {
  88. return nil, err
  89. }
  90. if len(devices) == 0 {
  91. return []models.Device{}, nil
  92. }
  93. for i := range devices {
  94. devices[i].ApplyUpdate(update)
  95. err := config.DeviceRepository().Save(context.Background(), &devices[i])
  96. if err != nil {
  97. log.Println("Failed to save device for state:", err)
  98. continue
  99. }
  100. }
  101. return devices, nil
  102. }))
  103. r.PUT("/:fetch/state", handler(func(c *gin.Context) (interface{}, error) {
  104. state := models.NewDeviceState{}
  105. err := parseBody(c, &state)
  106. if err != nil {
  107. return nil, err
  108. }
  109. devices, err := fetchDevices(ctxOf(c), c.Param("fetch"))
  110. if err != nil {
  111. return nil, err
  112. }
  113. if len(devices) == 0 {
  114. return []models.Device{}, nil
  115. }
  116. for i := range devices {
  117. err := devices[i].SetState(state)
  118. if err != nil {
  119. return nil, err
  120. }
  121. }
  122. config.PublishChannel <- devices
  123. go func() {
  124. for _, device := range devices {
  125. err := config.DeviceRepository().Save(context.Background(), &device)
  126. if err != nil {
  127. log.Println("Failed to save device for state:", err)
  128. continue
  129. }
  130. }
  131. }()
  132. return devices, nil
  133. }))
  134. r.PUT("/:fetch/tags", handler(func(c *gin.Context) (interface{}, error) {
  135. var body struct {
  136. Add []string `json:"add"`
  137. Remove []string `json:"remove"`
  138. }
  139. err := parseBody(c, &body)
  140. if err != nil {
  141. return nil, err
  142. }
  143. devices, err := fetchDevices(ctxOf(c), c.Param("fetch"))
  144. if err != nil {
  145. return nil, err
  146. }
  147. if len(devices) == 0 {
  148. return []models.Device{}, nil
  149. }
  150. for i := range devices {
  151. device := &devices[i]
  152. for _, tag := range body.Add {
  153. found := false
  154. for _, tag2 := range device.Tags {
  155. if tag == tag2 {
  156. found = true
  157. break
  158. }
  159. }
  160. if !found {
  161. device.Tags = append(device.Tags, tag)
  162. }
  163. }
  164. for _, tag := range body.Remove {
  165. index := -1
  166. for i, tag2 := range device.Tags {
  167. if tag == tag2 {
  168. index = i
  169. }
  170. }
  171. if index == -1 {
  172. continue
  173. }
  174. device.Tags = append(device.Tags[:index], device.Tags[index+1:]...)
  175. }
  176. err = config.DeviceRepository().Save(ctxOf(c), device)
  177. if err != nil {
  178. return nil, err
  179. }
  180. }
  181. return devices, nil
  182. }))
  183. }