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.

160 lines
4.0 KiB

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