|
|
package hue
import ( "context" "fmt" lucifer3 "git.aiterp.net/lucifer3/server" "git.aiterp.net/lucifer3/server/commands" "git.aiterp.net/lucifer3/server/events" "git.aiterp.net/lucifer3/server/internal/gentools" "sync" "time" )
func NewService() lucifer3.ActiveService { return &service{ bridges: map[string]*Bridge{}, } }
type service struct { mu sync.Mutex
bridges map[string]*Bridge }
func (s *service) Active() bool { return true }
func (s *service) HandleCommand(bus *lucifer3.EventBus, command lucifer3.Command) { switch command := command.(type) { case commands.PairDevice: { if hostname, ok := command.Matches("hue"); ok { go func() { timeout, cancel := context.WithTimeout(context.Background(), time.Second*30) defer cancel()
client := NewClient(hostname, "")
token, err := client.Register(timeout) if err != nil { return }
bus.RunEvent(events.DeviceAccepted{ ID: command.ID, APIKey: token, }) }() } }
case commands.SetStateBatch: for _, bridge := range s.bridges { bridge.SetStates(command) }
case commands.SetState: if sub, ok := command.Matches("hue"); ok { if s.bridges[sub] != nil { s.bridges[sub].SetStates(gentools.OneItemMap(command.ID, command.State)) } }
case commands.SearchDevices: if sub, ok := command.Matches("hue"); ok { if s.bridges[sub] != nil { go func() { err := s.bridges[sub].SearchDevices(time.Second * 30) if err != nil { bus.RunEvent(events.Log{ ID: command.ID, Level: "error", Code: "search_failed", Message: "Could not search: " + err.Error(), }) } }() } }
case commands.ConnectDevice: if sub, ok := command.Matches("hue"); ok { if s.bridges[sub] != nil { s.bridges[sub].cancel() delete(s.bridges, sub) }
ctx, cancel := context.WithCancel(context.Background()) client := NewClient(sub, command.APIKey)
bridge := NewBridge(sub, client) bridge.ctx = ctx bridge.cancel = cancel s.bridges[sub] = bridge
go func() { bus.RunEvent(events.Log{ ID: command.ID, Level: "info", Code: "connecting_device", Message: "Connecting to device...", })
for bridge.ctx.Err() == nil { ctx2, cancel2 := context.WithCancel(ctx)
err := bridge.Run(ctx2, bus) cancel2() if err != nil { bus.RunEvent(events.DeviceFailed{ ID: command.ID, Error: fmt.Sprintf("Run failed: %s", err), }) bus.RunEvent(events.Log{ ID: command.ID, Level: "error", Code: "connect_failed", Message: fmt.Sprintf("Could not connect device: %s", err), }) }
select { case <-time.After(time.Second * 5): case <-ctx.Done(): return } } }() } } }
func (s *service) HandleEvent(_ *lucifer3.EventBus, event lucifer3.Event) {}
|