|
|
package hue2
import ( "context" "encoding/json" "encoding/xml" "fmt" "git.aiterp.net/lucifer/new-server/internal/lerrors" "git.aiterp.net/lucifer/new-server/models" "net/http" "sync" "time" )
type Driver struct { mu sync.Mutex bridges []*Bridge }
func (d *Driver) SearchBridge(ctx context.Context, address, token string, dryRun bool) ([]models.Bridge, error) { if address == "" { if !dryRun { return nil, lerrors.ErrAddressOnlyDryRunnable }
res, err := http.Get("https://discovery.meethue.com") if err != nil { return nil, err } defer res.Body.Close()
entries := make([]DiscoveryEntry, 0, 8) err = json.NewDecoder(res.Body).Decode(&entries) if err != nil { return nil, err }
bridges := make([]models.Bridge, 0, len(entries)) for _, entry := range entries { bridges = append(bridges, models.Bridge{ ID: -1, Name: entry.Id, Driver: models.DTHue2, Address: entry.InternalIPAddress, Token: "", }) }
return bridges, nil }
deviceInfo := BridgeDeviceInfo{} res, err := http.Get(fmt.Sprintf("http://%s/description.xml", address)) if err != nil { return nil, err } defer res.Body.Close() err = xml.NewDecoder(res.Body).Decode(&deviceInfo) if err != nil { return nil, err }
bridge := models.Bridge{ ID: -1, Name: deviceInfo.Device.FriendlyName, Driver: models.DTHue2, Address: address, Token: "", }
if !dryRun { client := NewClient(address, "")
timeout, cancel := context.WithTimeout(ctx, time.Second*30) defer cancel()
bridge.Token, err = client.Register(timeout) if err != nil { return nil, err } }
return []models.Bridge{bridge}, nil }
func (d *Driver) SearchDevices(ctx context.Context, bridge models.Bridge, timeout time.Duration) ([]models.Device, error) { return d.ensureBridge(bridge).SearchDevices(ctx, timeout) }
func (d *Driver) ListDevices(_ context.Context, bridge models.Bridge) ([]models.Device, error) { return d.ensureBridge(bridge).GenerateDevices(), nil }
func (d *Driver) Publish(_ context.Context, bridge models.Bridge, devices []models.Device) error { d.ensureBridge(bridge).Update(devices...) return nil }
func (d *Driver) Run(ctx context.Context, bridge models.Bridge, ch chan<- models.Event) error { return d.ensureBridge(bridge).Run(ctx, ch) }
func (d *Driver) ForgetDevice(ctx context.Context, bridge models.Bridge, device models.Device) error { return d.ensureBridge(bridge).Forget(ctx, device) }
func (d *Driver) ensureBridge(info models.Bridge) *Bridge { d.mu.Lock() for _, bridge := range d.bridges { if bridge.client.host == info.Address { d.mu.Unlock() return bridge } } bridge := NewBridge(NewClient(info.Address, info.Token)) bridge.externalID = info.ID d.bridges = append(d.bridges, bridge) d.mu.Unlock()
return bridge }
|