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.

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