|
|
package tradfri
import ( "fmt" lucifer3 "git.aiterp.net/lucifer3/server" "git.aiterp.net/lucifer3/server/commands" "git.aiterp.net/lucifer3/server/events" "github.com/sirupsen/logrus" "io" "strings" "sync" )
func NewService() lucifer3.ActiveService { logrus.StandardLogger().Out = io.Discard logrus.StandardLogger().ExitFunc = func(i int) { panic(fmt.Sprintf("tradfri: exit code %d", i)) }
return &service{ bridges: make(map[string]*Bridge, 4), } }
type service struct { mu sync.Mutex
bridges map[string]*Bridge }
func (s *service) Active() bool { return true }
func (s *service) HandleEvent(*lucifer3.EventBus, lucifer3.Event) { // NOP
}
func (s *service) HandleCommand(bus *lucifer3.EventBus, command lucifer3.Command) { defer s.mu.Unlock() s.mu.Lock()
switch command := command.(type) { case commands.PairDevice: if sub, ok := command.Matches("tradfri"); ok { bridge, err := connect(sub, command.APIKey) if err != nil { bus.RunEvent(events.DeviceFailed{ ID: command.ID, Error: err.Error(), }) return }
s.bridges[bridge.id] = bridge
bus.RunEvent(events.DeviceAccepted{ ID: bridge.id, APIKey: bridge.newCredentials, }) } case commands.SearchDevices: if _, ok := command.Matches("tradfri"); ok { bus.RunEvent(events.DeviceFailed{ ID: command.ID, Error: "Please follow instructions in IKEA app; they will appear here after pairing.", }) } case commands.SetState: if _, ok := command.Matches("tradfri"); ok { bridge, ok := s.findBridge(command.ID) if !ok { return }
bridge.writeState(command.ID, command.State, bus) } case commands.SetStateBatch: for id, state := range command { if strings.HasPrefix(id, "tradfri") { bridge, ok := s.findBridge(id) if !ok { return }
bridge.writeState(id, state, bus) } } case commands.ConnectDevice: if sub, ok := command.Matches("tradfri"); ok { if s.bridges[command.ID] == nil { bridge, err := connect(sub, command.APIKey) if err != nil { bus.RunEvent(events.DeviceFailed{ ID: command.ID, Error: err.Error(), }) return }
s.bridges[command.ID] = bridge }
bus.RunEvent(events.DeviceConnected{Prefix: s.bridges[command.ID].id}) s.bridges[command.ID].listen(bus) } } }
func (s *service) findBridge(id string) (*Bridge, bool) { bits := strings.Split(id, ":") for i := 2; i < len(bits); i++ { prefix := strings.Join(bits[0:i], ":") if s.bridges[prefix] != nil { return s.bridges[prefix], true } }
return nil, false }
|