puerta/internal/door/hue.go

134 lines
2.5 KiB
Go

// SPDX-License-Identifier: Apache-2.0
// Copyright © 2022 Roberto Hidalgo <nidito@un.rob.mx>
package door
import (
"context"
"time"
"github.com/amimof/huego"
hue "github.com/amimof/huego"
"github.com/sirupsen/logrus"
)
type HueConfig struct {
ip string
username string
device int
}
type Hue struct {
bridge *hue.Bridge
device *hue.Light
config *HueConfig
}
func init() {
_register("hue", NewHue)
}
func NewHue(config map[string]any) (Door, error) {
cfg := &HueConfig{
ip: config["ip"].(string),
username: config["username"].(string),
device: -1,
}
if config["device"] != nil {
cfg.device = config["device"].(int)
}
h := &Hue{
bridge: huego.New(cfg.ip, cfg.username),
config: cfg,
}
logrus.Infof("Hue client for %s starting", cfg.ip)
if cfg.username != "" && cfg.device > -1 {
device, err := h.bridge.GetLight(cfg.device)
if err != nil {
return nil, err
}
h.device = device
}
return h, nil
}
func (h *Hue) Setup(domain string) error {
if h.config.username == "" {
logrus.Info("Pairing with bridge, please press the button")
user, err := h.bridge.CreateUser(domain)
if err != nil {
return err
}
logrus.Infof("Created user id: %s", user)
h.bridge = h.bridge.Login(user)
}
if h.config.device == -1 {
logrus.Info("Looking for devices...")
lights, err := h.bridge.GetLights()
if err != nil {
return err
}
for _, l := range lights {
if l.Type == "On/Off plug-in unit" {
logrus.Infof("Found %s named %s with ID: %d", l.ProductName, l.Name, l.ID)
} else {
logrus.Debugf("Found %s (%s) named %s with ID: %d", l.Type, l.ProductName, l.Name, l.ID)
}
}
}
logrus.Info("Setup complete")
return nil
}
func (h *Hue) IsOpen() (bool, error) {
return h.device.IsOn(), nil
}
func (h *Hue) Open(errors chan<- error, done chan<- bool) {
defer close(errors)
defer close(done)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
err := h.device.SetStateContext(ctx, hue.State{On: true})
if err != nil {
errors <- err
return
}
errors <- nil
time.Sleep(4 * time.Second)
ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
err = h.device.SetStateContext(ctx, hue.State{On: false})
if err != nil {
errors <- err
return
}
done <- true
}
func (h *Hue) Close(errors chan error) {
err, ok := <-errors
if ok && err != nil {
logrus.Errorf("Failed during power off: %s", err)
return
} else if ok {
logrus.Info("Door power shut off correctly")
}
}