aboutsummaryrefslogtreecommitdiff
path: root/bridge.go
diff options
context:
space:
mode:
Diffstat (limited to 'bridge.go')
-rw-r--r--bridge.go102
1 files changed, 45 insertions, 57 deletions
diff --git a/bridge.go b/bridge.go
index 2a6fb26..c89d5f4 100644
--- a/bridge.go
+++ b/bridge.go
@@ -24,6 +24,7 @@ import (
"runtime"
"strconv"
"strings"
+ "time"
)
// Bridge struct defines hardware that is used to communicate with the lights.
@@ -51,78 +52,76 @@ type BridgeInfo struct {
} `xml:"device"`
}
-// bridge.Get sends an http GET to the bridge
+// Get sends an http GET to the bridge
func (bridge *Bridge) Get(path string) ([]byte, io.Reader, error) {
uri := fmt.Sprintf("http://" + bridge.IPAddress + path)
- resp, err := http.Get(uri)
+ client := &http.Client{Timeout: time.Second * 5}
+ resp, err := client.Get(uri)
+
if err != nil {
- err = errors.New("Error: Unable to access bridge. ")
- log.Println(err)
+ err = errors.New("unable to access bridge")
return []byte{}, nil, err
}
return HandleResponse(resp)
}
-// Bridge.Put sends an http PUT to the bridge with
+// Put sends an http PUT to the bridge with
// a body formatted with parameters (in a generic interface)
func (bridge *Bridge) Put(path string, params interface{}) ([]byte, io.Reader, error) {
uri := fmt.Sprintf("http://" + bridge.IPAddress + path)
- client := &http.Client{}
+ client := &http.Client{Timeout: time.Second * 5}
data, err := json.Marshal(params)
if err != nil {
- err = errors.New("Error: Unable marshal PUT request interface.")
- log.Println(err)
+ err = errors.New("unable to marshal PUT request interface")
return []byte{}, nil, err
}
//fmt.Println("\n\nPARAMS: ", params)
- //log.Println("\nSending PUT body: ", string(data))
- request, err := http.NewRequest("PUT", uri, bytes.NewReader(data))
+ request, _ := http.NewRequest("PUT", uri, bytes.NewReader(data))
resp, err := client.Do(request)
if err != nil {
- err = errors.New("Error: Unable to access bridge.")
- log.Println(err)
+ err = errors.New("unable to access bridge")
return []byte{}, nil, err
}
return HandleResponse(resp)
}
-// bridge.Post sends an http POST to the bridge with
+// Post sends an http POST to the bridge with
// a body formatted with parameters (in a generic interface).
// If `params` is nil then it will send an empty body with the post request.
func (bridge *Bridge) Post(path string, params interface{}) ([]byte, io.Reader, error) {
- // Add the params to the request or allow an empty body
- request := []byte{}
- if params != nil {
- reqBody, err := json.Marshal(params)
- if err != nil {
- err = errors.New("Error: Unable to add POST body parameters due to json marshal error.")
- log.Println(err)
- return []byte{}, nil, err
- }
- request = reqBody
- }
+ // Add the params to the request or allow an empty body
+ request := []byte{}
+ if params != nil {
+ reqBody, err := json.Marshal(params)
+ if err != nil {
+ err = errors.New("unable to add POST body parameters due to json marshalling error")
+ return []byte{}, nil, err
+ }
+ request = reqBody
+ }
// Send the request and handle the response
uri := fmt.Sprintf("http://" + bridge.IPAddress + path)
- resp, err := http.Post(uri, "text/json", bytes.NewReader(request))
+ client := &http.Client{Timeout: time.Second * 5}
+ resp, err := client.Post(uri, "text/json", bytes.NewReader(request))
+
if err != nil {
- err = errors.New("Error: Unable to access bridge.")
- log.Println(err)
+ err = errors.New("unable to access bridge")
return []byte{}, nil, err
}
- return HandleResponse(resp)
+ return HandleResponse(resp)
}
-// Bridge.Delete sends an http DELETE to the bridge
+// Delete sends an http DELETE to the bridge
func (bridge *Bridge) Delete(path string) error {
uri := fmt.Sprintf("http://" + bridge.IPAddress + path)
- client := &http.Client{}
- req, err := http.NewRequest("DELETE", uri, nil)
+ client := &http.Client{Timeout: time.Second * 5}
+ req, _ := http.NewRequest("DELETE", uri, nil)
resp, err := client.Do(req)
+
if err != nil {
- err = errors.New("Error: Unable to access bridge.")
- log.Println(err)
+ err = errors.New("unable to access bridge")
return err
}
_, _, err = HandleResponse(resp)
@@ -134,7 +133,7 @@ func (bridge *Bridge) Delete(path string) error {
// and invalid return types.
func HandleResponse(resp *http.Response) ([]byte, io.Reader, error) {
body, err := ioutil.ReadAll(resp.Body)
- defer resp.Body.Close()
+ defer resp.Body.Close()
if err != nil {
trace("Error parsing bridge description xml.", nil)
return []byte{}, nil, err
@@ -146,7 +145,6 @@ func HandleResponse(resp *http.Response) ([]byte, io.Reader, error) {
errDesc := errString[strings.Index(errString, "description\":\"")+14 : strings.Index(errString, "\"}}")]
errOut := fmt.Sprintf("Error type %s: %s.", errNum, errDesc)
err = errors.New(errOut)
- log.Println(err)
return []byte{}, nil, err
}
return body, reader, nil
@@ -158,15 +156,14 @@ func FindBridges() ([]Bridge, error) {
bridge := Bridge{IPAddress: "www.meethue.com"}
body, _, err := bridge.Get("/api/nupnp")
if err != nil {
- err = errors.New("Error: Unable to locate bridge.")
- log.Fatal(err)
+ err = errors.New("unable to locate bridge")
return []Bridge{}, err
}
- bridges := []Bridge{}
- err = json.Unmarshal(body, &bridges)
- if err != nil {
- return []Bridge{}, errors.New("Unable to parse FindBridges response. ")
- }
+ bridges := []Bridge{}
+ err = json.Unmarshal(body, &bridges)
+ if err != nil {
+ return []Bridge{}, errors.New("unable to parse FindBridges response")
+ }
return bridges, nil
}
@@ -181,13 +178,12 @@ func NewBridge(ip string) (*Bridge, error) {
// Test the connection by attempting to get the bridge info.
err := bridge.GetInfo()
if err != nil {
- log.Fatal("Error: Unable to access bridge. ", err)
return &Bridge{}, err
}
return &bridge, nil
}
-// GetBridgeInfo retreives the description.xml file from the bridge.
+// GetInfo retreives the description.xml file from the bridge.
// This is used as a check to see if the bridge is accessible
// and any error will be fatal as the bridge is required for nearly
// all functions.
@@ -200,27 +196,25 @@ func (bridge *Bridge) GetInfo() error {
err = xml.NewDecoder(reader).Decode(&data)
if err != nil {
err = errors.New("Error: Unable to decode XML response from bridge. ")
- log.Fatal(err)
return err
}
bridge.Info = data
return nil
}
-// Bridge.Login verifies that the username token has bridge access
+// Login verifies that the username token has bridge access
// and only assigns the bridge its Username value if verification is successful.
func (bridge *Bridge) Login(username string) error {
uri := fmt.Sprintf("/api/%s", username)
_, _, err := bridge.Get(uri)
if err != nil {
- log.Fatal(err)
return err
}
bridge.Username = username
return nil
}
-// Bridge.CreateUser adds a new user token on the whitelist.
+// CreateUser adds a new user token on the whitelist.
// The token is the first return value in this function which must
// be used with `Bridge.Login`. You cannot use a plaintext username
// like the argument provided in this function.
@@ -229,20 +223,15 @@ func (bridge *Bridge) CreateUser(deviceType string) (string, error) {
params := map[string]string{"devicetype": deviceType}
body, _, err := bridge.Post("/api", params)
if err != nil {
- log.Fatal("Error: Failed to create user. ", err)
return "", err
}
content := string(body)
username := content[strings.LastIndex(content, ":\"")+2 : strings.LastIndex(content, "\"")]
- userOut := fmt.Sprintf(
- "Created user token '%s'. Use Bridge.Login with this token from now on.",
- username)
- log.Println(userOut)
bridge.Username = username
return username, nil
}
-// Bridge.DeleteUser deletes a user given its USER KEY, not the string name.
+// DeleteUser deletes a user given its USER KEY, not the string name.
// See http://www.developers.meethue.com/documentation/configuration-api
// for description on `username` deprecation in place of the devicetype key.
func (bridge *Bridge) DeleteUser(username string) error {
@@ -307,7 +296,7 @@ func (bridge *Bridge) GetLightByIndex(index int) (Light, error) {
return light, nil
}
-// Bridge.FindNewLights makes the bridge search the zigbee spectrum for
+// FindNewLights makes the bridge search the zigbee spectrum for
// lights in the area and will add them to the list of lights available.
// If successful these new lights can be used by `Bridge.GetAllLights`
//
@@ -321,13 +310,12 @@ func (bridge *Bridge) FindNewLights() error {
uri := fmt.Sprintf("/api/%s/lights", bridge.Username)
_, _, err := bridge.Post(uri, nil)
if err != nil {
- log.Println(err)
return err
}
return nil
}
-// GetLight returns a light struct containing data on a given name.
+// GetLightByName returns a light struct containing data on a given name.
func (bridge *Bridge) GetLightByName(name string) (Light, error) {
lights, _ := bridge.GetAllLights()
for _, light := range lights {