Browse Source
it has the trappings of a driver now, but essential features are missing: discovery and forgetting
feature-colorvalue2
it has the trappings of a driver now, but essential features are missing: discovery and forgetting
feature-colorvalue2
Gisle Aune
3 years ago
8 changed files with 729 additions and 45 deletions
-
2app/config/driver.go
-
22cmd/xy/main.go
-
296internal/drivers/hue2/bridge.go
-
156internal/drivers/hue2/client.go
-
125internal/drivers/hue2/data.go
-
116internal/drivers/hue2/driver.go
-
1models/bridge.go
-
8models/colorxy.go
@ -0,0 +1,116 @@ |
|||
package hue2 |
|||
|
|||
import ( |
|||
"context" |
|||
"encoding/json" |
|||
"encoding/xml" |
|||
"fmt" |
|||
"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, models.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 nil, nil |
|||
} |
|||
|
|||
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) 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 |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue