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.

118 lines
2.4 KiB

2 years ago
2 years ago
2 years ago
  1. package hue
  2. import (
  3. "context"
  4. "fmt"
  5. lucifer3 "git.aiterp.net/lucifer3/server"
  6. "git.aiterp.net/lucifer3/server/commands"
  7. "git.aiterp.net/lucifer3/server/events"
  8. "git.aiterp.net/lucifer3/server/internal/gentools"
  9. "log"
  10. "sync"
  11. "time"
  12. )
  13. func NewService() lucifer3.ActiveService {
  14. return &service{
  15. bridges: map[string]*Bridge{},
  16. }
  17. }
  18. type service struct {
  19. mu sync.Mutex
  20. bridges map[string]*Bridge
  21. }
  22. func (s *service) Active() bool {
  23. return true
  24. }
  25. func (s *service) HandleCommand(bus *lucifer3.EventBus, command lucifer3.Command) {
  26. switch command := command.(type) {
  27. case commands.PairDevice:
  28. {
  29. if hostname, ok := command.Matches("hue"); ok {
  30. go func() {
  31. timeout, cancel := context.WithTimeout(context.Background(), time.Second*30)
  32. defer cancel()
  33. client := NewClient(hostname, "")
  34. token, err := client.Register(timeout)
  35. if err != nil {
  36. return
  37. }
  38. bus.RunEvent(events.DeviceAccepted{
  39. ID: command.ID,
  40. APIKey: token,
  41. })
  42. }()
  43. }
  44. }
  45. case commands.SetStateBatch:
  46. for _, bridge := range s.bridges {
  47. bridge.SetStates(command)
  48. }
  49. case commands.SetState:
  50. if sub, ok := command.Matches("hue"); ok {
  51. if s.bridges[sub] != nil {
  52. s.bridges[sub].SetStates(gentools.OneItemMap(command.ID, command.State))
  53. }
  54. }
  55. case commands.SearchDevices:
  56. if sub, ok := command.Matches("hue"); ok {
  57. if s.bridges[sub] != nil {
  58. go func() {
  59. err := s.bridges[sub].SearchDevices(time.Second * 30)
  60. if err != nil {
  61. log.Println("Search failed:", err)
  62. }
  63. }()
  64. }
  65. }
  66. case commands.ConnectDevice:
  67. if sub, ok := command.Matches("hue"); ok {
  68. if s.bridges[sub] != nil {
  69. s.bridges[sub].cancel()
  70. delete(s.bridges, sub)
  71. }
  72. ctx, cancel := context.WithCancel(context.Background())
  73. client := NewClient(sub, command.APIKey)
  74. bridge := NewBridge(sub, client)
  75. bridge.ctx = ctx
  76. bridge.cancel = cancel
  77. s.bridges[sub] = bridge
  78. go func() {
  79. for bridge.ctx.Err() == nil {
  80. ctx2, cancel2 := context.WithCancel(ctx)
  81. err := bridge.Run(ctx2, bus)
  82. cancel2()
  83. if err != nil {
  84. bus.RunEvent(events.DeviceFailed{
  85. ID: command.ID,
  86. Error: fmt.Sprintf("Run failed: %s", err),
  87. })
  88. }
  89. select {
  90. case <-time.After(time.Second * 5):
  91. case <-ctx.Done():
  92. return
  93. }
  94. }
  95. }()
  96. }
  97. }
  98. }
  99. func (s *service) HandleEvent(_ *lucifer3.EventBus, event lucifer3.Event) {}