github.com/amimof/huego@v1.2.1/group.go (about) 1 package huego 2 3 import ( 4 "context" 5 "errors" 6 "image/color" 7 ) 8 9 // Group represents a bridge group https://developers.meethue.com/documentation/groups-api 10 type Group struct { 11 Name string `json:"name,omitempty"` 12 Lights []string `json:"lights,omitempty"` 13 Type string `json:"type,omitempty"` 14 GroupState *GroupState `json:"state,omitempty"` 15 Recycle bool `json:"recycle,omitempty"` 16 Class string `json:"class,omitempty"` 17 Stream *Stream `json:"stream,omitempty"` 18 Locations map[string][]float64 `json:"locations,omitempty"` 19 State *State `json:"action,omitempty"` 20 ID int `json:"-"` 21 bridge *Bridge 22 } 23 24 // GroupState defines the state on a group. 25 // Can be used to control the state of all lights in a group rather than controlling them individually 26 type GroupState struct { 27 AllOn bool `json:"all_on,omitempty"` 28 AnyOn bool `json:"any_on,omitempty"` 29 } 30 31 // Stream define the stream status of a group 32 type Stream struct { 33 ProxyMode string `json:"proxymode,omitempty"` 34 ProxyNode string `json:"proxynode,omitempty"` 35 ActiveRaw *bool `json:"active,omitempty"` 36 OwnerRaw *string `json:"owner,omitempty"` 37 } 38 39 // Active returns the stream active state, and will return false if ActiveRaw is nil 40 func (s *Stream) Active() bool { 41 if s.ActiveRaw == nil { 42 return false 43 } 44 45 return *s.ActiveRaw 46 } 47 48 // Owner returns the stream Owner, and will return an empty string if OwnerRaw is nil 49 func (s *Stream) Owner() string { 50 if s.OwnerRaw == nil { 51 return "" 52 } 53 54 return *s.OwnerRaw 55 } 56 57 // SetState sets the state of the group to s. 58 func (g *Group) SetState(s State) error { 59 return g.SetStateContext(context.Background(), s) 60 } 61 62 // SetStateContext sets the state of the group to s. 63 func (g *Group) SetStateContext(ctx context.Context, s State) error { 64 _, err := g.bridge.SetGroupStateContext(ctx, g.ID, s) 65 if err != nil { 66 return err 67 } 68 g.State = &s 69 return nil 70 } 71 72 // Rename sets the name property of the group 73 func (g *Group) Rename(new string) error { 74 return g.RenameContext(context.Background(), new) 75 } 76 77 // RenameContext sets the name property of the group 78 func (g *Group) RenameContext(ctx context.Context, new string) error { 79 update := Group{Name: new} 80 _, err := g.bridge.UpdateGroupContext(ctx, g.ID, update) 81 if err != nil { 82 return err 83 } 84 g.Name = new 85 return nil 86 } 87 88 // Off sets the On state of one group to false, turning all lights in the group off 89 func (g *Group) Off() error { 90 return g.OffContext(context.Background()) 91 } 92 93 // OffContext sets the On state of one group to false, turning all lights in the group off 94 func (g *Group) OffContext(ctx context.Context) error { 95 state := State{On: false} 96 _, err := g.bridge.SetGroupStateContext(ctx, g.ID, state) 97 if err != nil { 98 return err 99 } 100 g.State.On = false 101 return nil 102 } 103 104 // On sets the On state of one group to true, turning all lights in the group on 105 func (g *Group) On() error { 106 return g.OnContext(context.Background()) 107 } 108 109 // OnContext sets the On state of one group to true, turning all lights in the group on 110 func (g *Group) OnContext(ctx context.Context) error { 111 state := State{On: true} 112 _, err := g.bridge.SetGroupStateContext(ctx, g.ID, state) 113 if err != nil { 114 return err 115 } 116 g.State.On = true 117 return nil 118 } 119 120 // IsOn returns true if light state On property is true 121 func (g *Group) IsOn() bool { 122 return g.State.On 123 } 124 125 // Bri sets the light brightness state property 126 func (g *Group) Bri(new uint8) error { 127 return g.BriContext(context.Background(), new) 128 } 129 130 // BriContext sets the light brightness state property 131 func (g *Group) BriContext(ctx context.Context, new uint8) error { 132 update := State{On: true, Bri: new} 133 _, err := g.bridge.SetGroupStateContext(ctx, g.ID, update) 134 if err != nil { 135 return err 136 } 137 g.State.Bri = new 138 g.State.On = true 139 return nil 140 } 141 142 // Hue sets the light hue state property (0-65535) 143 func (g *Group) Hue(new uint16) error { 144 return g.HueContext(context.Background(), new) 145 } 146 147 // HueContext sets the light hue state property (0-65535) 148 func (g *Group) HueContext(ctx context.Context, new uint16) error { 149 update := State{On: true, Hue: new} 150 _, err := g.bridge.SetGroupStateContext(ctx, g.ID, update) 151 if err != nil { 152 return err 153 } 154 g.State.Hue = new 155 g.State.On = true 156 return nil 157 } 158 159 // Sat sets the light saturation state property (0-254) 160 func (g *Group) Sat(new uint8) error { 161 return g.SatContext(context.Background(), new) 162 } 163 164 // SatContext sets the light saturation state property (0-254) 165 func (g *Group) SatContext(ctx context.Context, new uint8) error { 166 update := State{On: true, Sat: new} 167 _, err := g.bridge.SetGroupStateContext(ctx, g.ID, update) 168 if err != nil { 169 return err 170 } 171 g.State.Sat = new 172 g.State.On = true 173 return nil 174 } 175 176 // Xy sets the x and y coordinates of a color in CIE color space. (0-1 per value) 177 func (g *Group) Xy(new []float32) error { 178 return g.XyContext(context.Background(), new) 179 } 180 181 // XyContext sets the x and y coordinates of a color in CIE color space. (0-1 per value) 182 func (g *Group) XyContext(ctx context.Context, new []float32) error { 183 update := State{On: true, Xy: new} 184 _, err := g.bridge.SetGroupStateContext(ctx, g.ID, update) 185 if err != nil { 186 return err 187 } 188 g.State.Xy = new 189 g.State.On = true 190 return nil 191 } 192 193 // Ct sets the light color temperature state property 194 func (g *Group) Ct(new uint16) error { 195 return g.CtContext(context.Background(), new) 196 } 197 198 // CtContext sets the light color temperature state property 199 func (g *Group) CtContext(ctx context.Context, new uint16) error { 200 update := State{On: true, Ct: new} 201 _, err := g.bridge.SetGroupStateContext(ctx, g.ID, update) 202 if err != nil { 203 return err 204 } 205 g.State.Ct = new 206 g.State.On = true 207 return nil 208 } 209 210 // Col sets the light color as RGB (will be converted to xy) 211 func (g *Group) Col(new color.Color) error { 212 return g.ColContext(context.Background(), new) 213 } 214 215 // ColContext sets the light color as RGB (will be converted to xy) 216 func (g *Group) ColContext(ctx context.Context, new color.Color) error { 217 xy, bri := ConvertRGBToXy(new) 218 219 update := State{On: true, Xy: xy, Bri: bri} 220 _, err := g.bridge.SetGroupStateContext(ctx, g.ID, update) 221 if err != nil { 222 return err 223 } 224 g.State.Xy = xy 225 g.State.Bri = bri 226 g.State.On = true 227 return nil 228 } 229 230 // Scene sets the scene by it's identifier of the scene you wish to recall 231 func (g *Group) Scene(scene string) error { 232 return g.SceneContext(context.Background(), scene) 233 } 234 235 // SceneContext sets the scene by it's identifier of the scene you wish to recall 236 func (g *Group) SceneContext(ctx context.Context, scene string) error { 237 update := State{On: true, Scene: scene} 238 _, err := g.bridge.SetGroupStateContext(ctx, g.ID, update) 239 if err != nil { 240 return err 241 } 242 g.State.Scene = scene 243 g.State.On = true 244 return nil 245 } 246 247 // TransitionTime sets the duration of the transition from the light’s current state to the new state 248 func (g *Group) TransitionTime(new uint16) error { 249 return g.TransitionTimeContext(context.Background(), new) 250 } 251 252 // TransitionTimeContext sets the duration of the transition from the light’s current state to the new state 253 func (g *Group) TransitionTimeContext(ctx context.Context, new uint16) error { 254 update := State{On: g.State.On, TransitionTime: new} 255 _, err := g.bridge.SetGroupStateContext(ctx, g.ID, update) 256 if err != nil { 257 return err 258 } 259 g.State.TransitionTime = new 260 return nil 261 } 262 263 // Effect the dynamic effect of the lights in the group, currently “none” and “colorloop” are supported 264 func (g *Group) Effect(new string) error { 265 return g.EffectContext(context.Background(), new) 266 } 267 268 // EffectContext the dynamic effect of the lights in the group, currently “none” and “colorloop” are supported 269 func (g *Group) EffectContext(ctx context.Context, new string) error { 270 update := State{On: true, Effect: new} 271 _, err := g.bridge.SetGroupStateContext(ctx, g.ID, update) 272 if err != nil { 273 return err 274 } 275 g.State.Effect = new 276 g.State.On = true 277 return nil 278 } 279 280 // Alert makes the lights in the group blink in its current color. Supported values are: 281 // “none” – The light is not performing an alert effect. 282 // “select” – The light is performing one breathe cycle. 283 // “lselect” – The light is performing breathe cycles for 15 seconds or until alert is set to "none". 284 func (g *Group) Alert(new string) error { 285 return g.AlertContext(context.Background(), new) 286 } 287 288 // AlertContext makes the lights in the group blink in its current color. Supported values are: 289 // “none” – The light is not performing an alert effect. 290 // “select” – The light is performing one breathe cycle. 291 // “lselect” – The light is performing breathe cycles for 15 seconds or until alert is set to "none". 292 func (g *Group) AlertContext(ctx context.Context, new string) error { 293 update := State{On: true, Alert: new} 294 _, err := g.bridge.SetGroupStateContext(ctx, g.ID, update) 295 if err != nil { 296 return err 297 } 298 g.State.Effect = new 299 g.State.On = true 300 return nil 301 } 302 303 // EnableStreaming enables streaming for the group by setting the Stream Active property to true 304 func (g *Group) EnableStreaming() error { 305 return g.EnableStreamingContext(context.Background()) 306 } 307 308 // EnableStreamingContext enables streaming for the group by setting the Stream Active property to true 309 func (g *Group) EnableStreamingContext(ctx context.Context) error { 310 if g.Type != "Entertainment" { 311 return errors.New("must be an entertainment group to enable streaming") 312 } 313 314 active := true 315 update := Group{ 316 Stream: &Stream{ 317 ActiveRaw: &active, 318 }, 319 } 320 _, err := g.bridge.UpdateGroupContext(ctx, g.ID, update) 321 if err != nil { 322 return err 323 } 324 325 g.Stream.ActiveRaw = &active 326 g.Stream.OwnerRaw = &g.bridge.User 327 328 return nil 329 } 330 331 // DisableStreaming disabled streaming for the group by setting the Stream Active property to false 332 func (g *Group) DisableStreaming() error { 333 return g.DisableStreamingContext(context.Background()) 334 } 335 336 // DisableStreamingContext disabled streaming for the group by setting the Stream Active property to false 337 func (g *Group) DisableStreamingContext(ctx context.Context) error { 338 if g.Type != "Entertainment" { 339 return errors.New("must be an entertainment group to disable streaming") 340 } 341 342 active := false 343 update := Group{ 344 Stream: &Stream{ 345 ActiveRaw: &active, 346 }, 347 } 348 _, err := g.bridge.UpdateGroupContext(ctx, g.ID, update) 349 if err != nil { 350 return err 351 } 352 353 g.Stream.ActiveRaw = &active 354 g.Stream.OwnerRaw = nil 355 356 return nil 357 }