aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.go58
-rw-r--r--main.go65
2 files changed, 101 insertions, 22 deletions
diff --git a/config.go b/config.go
index a12a240..1402c17 100644
--- a/config.go
+++ b/config.go
@@ -1,8 +1,10 @@
package main
import (
+ "errors"
"io/ioutil"
"log"
+ "strings"
"github.com/BurntSushi/xdg"
"gopkg.in/yaml.v2"
@@ -10,13 +12,15 @@ import (
const XDG_CONFIG_NAME = "phlux"
+type BridgeConfig struct {
+ BridgeID string `yaml:"id"`
+ Token string `yaml:"token"`
+}
+
type PhluxConfig struct {
- Latitude float64 `yaml:"latitude"`
- Longitude float64 `yaml:"longitude"`
- Bridges []struct {
- BridgeID string `yaml:"id"`
- Token string `yaml:"token"`
- } `yaml:"bridges"`
+ Latitude float64 `yaml:"latitude"`
+ Longitude float64 `yaml:"longitude"`
+ Bridges []BridgeConfig `yaml:"bridges"`
}
func (c *PhluxConfig) Read() {
@@ -37,3 +41,45 @@ func (c *PhluxConfig) Read() {
return
}
}
+
+func (c *PhluxConfig) GetBridgeToken(id string) (string, error) {
+ lc := strings.ToLower(id)
+ for _, bridge := range c.Bridges {
+ if strings.ToLower(bridge.BridgeID) == lc {
+ return bridge.Token, nil
+ }
+ }
+ return "", errors.New("No token found for bridge " + id)
+}
+
+func (c *PhluxConfig) SetBridgeToken(id, token string) {
+ for _, bridge := range c.Bridges {
+ if bridge.BridgeID == id {
+ bridge.Token = token
+ return
+ }
+ }
+ c.Bridges = append(c.Bridges, BridgeConfig{
+ BridgeID: id,
+ Token: token,
+ })
+}
+
+func (c *PhluxConfig) Save() (err error) {
+ out, err := yaml.Marshal(c)
+ if err != nil {
+ log.Printf("Error marshalling config: %s\n", err.Error())
+ }
+ var paths xdg.Paths
+ configFile, err := paths.ConfigFile(XDG_CONFIG_NAME)
+ if err != nil {
+ log.Printf("No config file found: %s\n", err.Error())
+ return
+ }
+ err = ioutil.WriteFile(configFile, out, 0600)
+ if err != nil {
+ log.Printf("Error writing config file %s: %s\n", configFile, err.Error())
+ return
+ }
+ return
+}
diff --git a/main.go b/main.go
index 6253cbb..00850db 100644
--- a/main.go
+++ b/main.go
@@ -1,14 +1,15 @@
package main
import (
+ "errors"
+ "fmt"
"log"
- "os"
"time"
hue "github.com/benburwell/gohue"
)
-const username = "phlux"
+const USERNAME = "phlux"
func main() {
var config PhluxConfig
@@ -23,29 +24,61 @@ func main() {
desiredColorTemp := getDesiredColorTemperature(time.Now(), config.Latitude, config.Longitude)
for _, bridge := range bridges {
log.Printf("Bridge: %s\n", bridge.IPAddress)
- updateBridge(bridge, desiredColorTemp)
+ updateBridge(&bridge, desiredColorTemp, &config)
}
}
-func updateBridge(bridge hue.Bridge, ct ColorTemperature) {
- //username, err := bridge.CreateUser(username)
- //if err != nil {
- // panic("Could not create user on bridge")
- //}
- //fmt.Printf("Made user %s for bridge %s\n", username, bridge.IPAddress)
- err := bridge.Login(os.Getenv("HUE_LOGIN"))
+// In case we don't know the bridge's serial number for some reason, we won't
+// be able to look up the token, nor will we be able to save it. There is still
+// a chance we will be able to successfully log in though: if the link button
+// has been pressed, we should be able to create ourselves a temporary token.
+func authenticateOnce(bridge *hue.Bridge) error {
+ token, err := bridge.CreateUser(USERNAME)
if err != nil {
- log.Fatalf("Could not log in to bridge: %s\n", err.Error())
+ return errors.New(fmt.Sprintf("Could not create temporary token: %s", err.Error()))
}
- log.Println("Logged in to bridge")
+ log.Printf("Made token %s for bridge %s\n", token, bridge.IPAddress)
+ err = bridge.Login(token)
+ if err != nil {
+ return errors.New(fmt.Sprintf("Failed to log in with temporary token: %s", err.Error()))
+ }
+ log.Printf("Logged in to bridge %s\n", bridge.IPAddress)
+ return nil
+}
+
+func createToken(bridge *hue.Bridge, config *PhluxConfig) error {
+ if err := authenticateOnce(bridge); err != nil {
+ return err
+ }
+ config.SetBridgeToken(bridge.Info.Device.SerialNumber, bridge.Username)
+ config.Save()
+ return nil
+}
- config, err := bridge.GetConfig()
+// Attempt to authenticate to the bridge using a variety of techniques,
+// including looking up a saved token for the bridge's serial number and
+// attempting to generate a new token for the bridge assuming the link button
+// has been pressed.
+func authenticate(bridge *hue.Bridge, config *PhluxConfig) error {
+ // get bridge info, which contains serial number
+ err := bridge.GetInfo()
if err != nil {
- log.Fatalf("Could not get bridge info: %s\n", err.Error())
+ return authenticateOnce(bridge)
}
- log.Printf("Bridge name: %s\n", config.Name)
- log.Printf("Bridge ID: %s\n", config.BridgeID)
+ token, err := config.GetBridgeToken(bridge.Info.Device.SerialNumber)
+ if err != nil {
+ return createToken(bridge, config)
+ }
+ err = bridge.Login(token)
+ if err != nil {
+ log.Fatalf("Could not log in to bridge: %s\n", err.Error())
+ }
+ log.Println("Logged in to bridge")
+ return nil
+}
+func updateBridge(bridge *hue.Bridge, ct ColorTemperature, config *PhluxConfig) {
+ authenticate(bridge, config)
lights, err := bridge.GetAllLights()
if err != nil {
log.Fatalf("Error getting lights: %s\n", err.Error())