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.
 
 
 
 
 
 

135 lines
2.9 KiB

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) {}