go-hue-interface/bridge.go
2020-05-14 22:16:54 +02:00

176 lines
4.5 KiB
Go

package hue
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"io/ioutil"
)
// -------------------------------------------------------------
// Interfaces
// -------------------------------------------------------------
// Bridge is the hue bridge interface
type Bridge struct {
Config *Config
}
// BridgeUserConfig is the config provided for hue for a user
type BridgeUserConfig struct {
Name string `json:"name"`
APIVersion string `json:"apiversion"`
IPAddress string `json:"ipaddress"`
MAC string `json:"mac"`
BridgeID string `json:"bridgeid"`
DataStoreVersion string `json:"datastoreversion"`
StarterKitID string `json:"starterkitid"`
ReplacesBridgeID string `json:"replacesbridgeid"`
}
// BridgeResponse is the response object returned to a bridge command
type BridgeResponse struct {
Success map[string]interface{} `json:"success"`
Error *BridgeResponseError `json:"error"`
}
// BridgeResponseError provides info about a bridge api error
type BridgeResponseError struct {
Type uint `json:"type"`
Address string `json:"address"`
Description string `json:"description"`
}
func (err *BridgeResponseError) String() string {
return fmt.Sprintf("Type=\"%d\" Addr=\"%s\" Desc=\"%s\" \n", err.Type, err.Address, err.Description)
}
// -------------------------------------------------------------
// Methods
// -------------------------------------------------------------
// NewBridge creates a new bridge api instance
func NewBridge(conf *Config) *Bridge {
return &Bridge{
Config: conf,
}
}
func (b *Bridge) postToBridge(endpoint string, payload interface{}) (*http.Response, error) {
return b.sendToBridge(endpoint, http.MethodPost, payload)
}
func (b *Bridge) putToBridge(endpoint string, payload interface{}) (*http.Response, error) {
return b.sendToBridge(endpoint, http.MethodPut, payload)
}
func (b *Bridge) deleteFromBridge(endpoint string, payload interface{}) (*http.Response, error) {
return b.sendToBridge(endpoint, http.MethodDelete, payload)
}
func (b *Bridge) sendToBridge(endpoint string, method string, payload interface{}) (*http.Response, error) {
data, errMarhshal := json.Marshal(payload)
if errMarhshal != nil {
return nil, errMarhshal
}
uri := b.getBridgeAPIURI() + endpoint
req, err := http.NewRequest(method, uri, bytes.NewBuffer(data))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
res, err := client.Do(req)
if err != nil {
return nil, err
}
return res, nil
}
func (b *Bridge) getRawResponse(endpoint string) ([]byte, error) {
res, errCom := b.getFromBridge(endpoint)
if errCom != nil {
return nil, errCom
}
defer res.Body.Close()
respBytes, errRead := ioutil.ReadAll(res.Body)
if errRead != nil {
return nil, errRead
}
return respBytes, nil
}
func (b *Bridge) getFromBridge(endpoint string) (*http.Response, error) {
uri := b.getBridgeAPIURI() + endpoint
req, err := http.NewRequest("GET", uri, nil)
if err != nil {
return nil, err
}
client := &http.Client{}
res, err := client.Do(req)
if err != nil {
return nil, err
}
// check http responses
if res.StatusCode != http.StatusOK {
return nil, errors.New("Hue responded with error" + res.Status + fmt.Sprint(res.StatusCode))
}
return res, nil
}
// getAndDecode performs a get request and unmarshals the result into target
func (b *Bridge) getAndDecode(endpoint string, target interface{}) error {
res, errCom := b.getFromBridge(endpoint)
if errCom != nil {
return errCom
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
return errors.New("Hue responded with error" + res.Status + fmt.Sprint(res.StatusCode))
}
// Unmarshal data
errDecode := json.NewDecoder(res.Body).Decode(target)
if errDecode != nil {
return errDecode
}
return nil
}
func (b *Bridge) getBridgeAPIURI() string {
return b.Config.BridgeAddrScheme + "://" + b.Config.BridgeAddr + "/api/" + b.Config.Username
}
// func decodeResponse(r *htpp.Response, target interface{}) {
// defer r.Body.Close()
// // TODO: remove
// fmt.Println("response Status:", res.Status)
// fmt.Println("response Headers:", res.Header)
// body, _ := ioutil.ReadAll(res.Body)
// fmt.Println("response Body:", string(body))
// if res.StatusCode != http.StatusOK {
// return errors.New("Hue responded with error" + res.Status + fmt.Sprint(res.StatusCode))
// }
// // Unmarshal data
// if respData != nil {
// errDecode := json.NewDecoder(res.Body).Decode(respData)
// if errDecode != nil {
// return nil, errDecode
// }
// }
// }