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.

105 lines
2.1 KiB

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