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.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() { 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), }) } select { case <-time.After(time.Second * 5): case <-ctx.Done(): return } } }() } } } func (s *service) HandleEvent(_ *lucifer3.EventBus, event lucifer3.Event) {}