-
Notifications
You must be signed in to change notification settings - Fork 24
/
bridge.go
171 lines (144 loc) · 3.94 KB
/
bridge.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package hue
import (
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
)
// Bridge is a representation of the Philips Hue bridge device.
type Bridge struct {
IpAddr string
Username string
debug bool
}
// NewBridge instantiates a bridge object. Use this method when you already
// know the ip address and username to use. Saves the trouble of a lookup.
func NewBridge(ipAddr, username string) *Bridge {
return &Bridge{IpAddr: ipAddr, Username: username}
}
func (self *Bridge) Debug() *Bridge {
self.debug = true
return self
}
func (self *Bridge) toUri(path string) string {
return fmt.Sprintf("http://%s/api/%s%s", self.IpAddr, self.Username, path)
}
func (self *Bridge) get(path string) (*http.Response, error) {
uri := self.toUri(path)
if self.debug {
log.Printf("GET %s\n", uri)
}
return client.Get(uri)
}
func (self *Bridge) post(path string, body io.Reader) (*http.Response, error) {
uri := self.toUri(path)
if self.debug {
log.Printf("POST %s\n", uri)
}
return client.Post(uri, "application/json", body)
}
func (self *Bridge) put(path string, body io.Reader) (*http.Response, error) {
uri := self.toUri(path)
if self.debug {
log.Printf("PUT %s\n", uri)
}
request, err := http.NewRequest("PUT", uri, body)
if err != nil {
return nil, err
}
return client.Do(request)
}
// GetNewLights - retrieves the list lights we've seen since
// the last scan. returns the new lights, lastseen, and any error
// that may have occured as per:
// http://developers.meethue.com/1_lightsapi.html#12_get_new_lights
func (self *Bridge) GetNewLights() ([]*Light, string, error) {
response, err := self.get("/lights/new")
if err != nil {
return nil, "", err
}
defer response.Body.Close()
data, err := ioutil.ReadAll(response.Body)
if err != nil {
return nil, "", err
}
results := make(map[string]interface{})
err = json.Unmarshal(data, &results)
if err != nil {
return nil, "", err
}
lastScan := results["lastscan"].(string)
var lights []*Light
for id, params := range results {
if id != "lastscan" {
value := params.(map[string]interface{})["name"]
light := &Light{Id: id, Name: value.(string)}
lights = append(lights, light)
}
}
return lights, lastScan, nil
}
// FindLightById allows you to easily look up light if you know it's Id
func (self *Bridge) FindLightById(id string) (*Light, error) {
lights, err := self.GetAllLights()
if err != nil {
return nil, err
}
for _, light := range lights {
if light.Id == id {
return light, nil
}
}
return nil, errors.New("unable to find light with id, " + id)
}
// FindLightByName - similar to FindLightById, this is a convenience method
// for when you already know the name of the light
func (self *Bridge) FindLightByName(name string) (*Light, error) {
lights, err := self.GetAllLights()
if err != nil {
return nil, err
}
for _, light := range lights {
if light.Name == name {
return light, nil
}
}
return nil, errors.New("unable to find light with name, " + name)
}
// Search - for new lights as per
// http://developers.meethue.com/1_lightsapi.html#13_search_for_new_lights
func (self *Bridge) Search() ([]Result, error) {
response, err := self.post("/lights", nil)
if err != nil {
return nil, err
}
defer response.Body.Close()
var results []Result
err = json.NewDecoder(response.Body).Decode(&results)
return results, err
}
// GetAllLights - retrieves all lights the Hue is aware of
func (self *Bridge) GetAllLights() ([]*Light, error) {
// fetch all the lights
response, err := self.get("/lights")
if err != nil {
return nil, err
}
defer response.Body.Close()
// deconstruct the json results
var results map[string]map[string]string
err = json.NewDecoder(response.Body).Decode(&results)
if err != nil {
return nil, err
}
// and convert them into lights
var lights []*Light
for id, params := range results {
light := Light{Id: id, Name: params["name"], bridge: self}
lights = append(lights, &light)
}
return lights, nil
}