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.

157 lines
3.9 KiB

  1. package main
  2. import (
  3. "bufio"
  4. "context"
  5. "flag"
  6. "fmt"
  7. "git.aiterp.net/lucifer/new-server/internal/drivers/nanoleaf"
  8. "git.aiterp.net/lucifer/new-server/models"
  9. "log"
  10. "os"
  11. "sort"
  12. "strconv"
  13. "strings"
  14. "time"
  15. )
  16. var flagDriver = flag.String("driver", "Nanoleaf", "The bridge driver to use")
  17. var flagAddress = flag.String("address", "127.0.0.1", "The bridge's address")
  18. var flagToken = flag.String("token", "", "The bridge's access token / api key / login")
  19. var flagPair = flag.Bool("pair", false, "Try to pair with the bridge.")
  20. var flagSearch = flag.Bool("search", false, "Search for devices first.")
  21. var flagSearchTimeout = flag.Duration("search-timeout", time.Second*3, "Timeout for device search.")
  22. func main() {
  23. flag.Parse()
  24. // TODO: Select driver
  25. driver := nanoleaf.Driver{}
  26. // Find bridge
  27. bridges, err := driver.SearchBridge(context.Background(), *flagAddress, !*flagPair)
  28. if err != nil {
  29. log.Fatalln("Failed to search bridge:", err)
  30. }
  31. if len(bridges) == 0 {
  32. log.Fatalln("No bridges found")
  33. }
  34. bridge := bridges[0]
  35. if !*flagPair {
  36. bridge.Token = *flagToken
  37. } else {
  38. log.Println("New token:", bridge.Token)
  39. }
  40. // List devices
  41. var devices []models.Device
  42. if *flagSearch {
  43. devices, err = driver.SearchDevices(context.Background(), bridge, *flagSearchTimeout)
  44. if err != nil {
  45. log.Fatalln("Failed to search devices:", err)
  46. }
  47. } else {
  48. devices, err = driver.ListDevices(context.Background(), bridge)
  49. if err != nil {
  50. log.Fatalln("Failed to list devices:", err)
  51. }
  52. }
  53. for i := range devices {
  54. devices[i].ID = i + 1
  55. }
  56. _ = driver.Publish(context.Background(), bridge, devices)
  57. ch := make(chan models.Event)
  58. go func() {
  59. err := driver.Run(context.Background(), bridge, ch)
  60. if err != nil {
  61. log.Fatalln("Run bridge stopped:", err)
  62. }
  63. }()
  64. go func() {
  65. reader := bufio.NewReader(os.Stdin)
  66. _, _ = fmt.Fprintln(os.Stderr, "Format: [id1,id2,...] [on|off] [color] [intensity]")
  67. for _, device := range devices {
  68. _, _ = fmt.Fprintf(os.Stderr, "Device: %d - %s %+v\n", device.ID, device.InternalID, device.Capabilities)
  69. }
  70. _, _ = fmt.Fprintln(os.Stderr, "Format: [id1,id2,...] [on|off] [color]")
  71. for {
  72. text, _ := reader.ReadString('\n')
  73. text = strings.Trim(text, "\t  \r\n")
  74. tokens := strings.Split(text, " ")
  75. if len(tokens) < 4 {
  76. continue
  77. }
  78. color, err := models.ParseColorValue(tokens[2])
  79. if err != nil {
  80. _, _ = fmt.Fprintln(os.Stderr, "Invalid color:", err)
  81. continue
  82. }
  83. intensity, _ := strconv.ParseFloat(tokens[3], 64)
  84. power := strings.ToLower(tokens[1]) == "on"
  85. idsStr := strings.Split(tokens[0], ",")
  86. ids := make([]int, 0, len(idsStr))
  87. for _, idStr := range idsStr {
  88. if idStr == "*" {
  89. ids = append(ids[:0], -1)
  90. break
  91. }
  92. id, err := strconv.Atoi(idStr)
  93. if err != nil {
  94. continue
  95. }
  96. ids = append(ids, id)
  97. }
  98. updatedDevices := devices[:0:0]
  99. for _, device := range devices {
  100. for _, id := range ids {
  101. if id == -1 || id == device.ID {
  102. if (color.IsKelvin() && device.HasCapability(models.DCColorKelvin)) || (color.IsHueSat() && device.HasCapability(models.DCColorHS)) {
  103. device.State.Color = color
  104. if device.HasCapability(models.DCPower) {
  105. device.State.Power = power
  106. }
  107. if device.HasCapability(models.DCIntensity) {
  108. device.State.Intensity = intensity
  109. }
  110. updatedDevices = append(updatedDevices, device)
  111. }
  112. }
  113. }
  114. }
  115. if len(updatedDevices) > 0 {
  116. err := driver.Publish(context.Background(), bridge, updatedDevices)
  117. if err != nil {
  118. log.Fatalln("Publish to bridge failed:", err)
  119. return
  120. }
  121. }
  122. }
  123. }()
  124. for event := range ch {
  125. _, _ = fmt.Fprintf(os.Stderr, "Event %s", event.Name)
  126. keys := make([]string, 0, 8)
  127. for key := range event.Payload {
  128. keys = append(keys, key)
  129. }
  130. sort.Strings(keys)
  131. for _, key := range keys {
  132. _, _ = fmt.Fprintf(os.Stderr, " %s=%#+v", key, event.Payload[key])
  133. }
  134. _, _ = fmt.Fprint(os.Stderr, "\n")
  135. }
  136. }