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.

165 lines
4.1 KiB

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