commit c62aa93ae0d6dd77a7b667e6580159e016415e82 Author: Barak Michener Date: Tue Dec 4 20:31:56 2018 -0800 experiments diff --git a/discovery/main.go b/discovery/main.go new file mode 100644 index 0000000..a66782e --- /dev/null +++ b/discovery/main.go @@ -0,0 +1,114 @@ +package discovery + +import ( + "encoding/json" + "fmt" + "os" + "os/user" + "path/filepath" + + "github.com/amimof/huego" +) + +// UserInfo is the saved data struture of a Hue app connection +type UserInfo struct { + User string +} + +func DiscoverAndConnectFromConfig(appName string) (*huego.Bridge, error) { + data := make(map[string]UserInfo) + u, err := user.Current() + if err != nil { + return nil, err + } + + filename := filepath.Join(u.HomeDir, ".config/hue-barak") + _, err = os.Stat(filename) + if err == nil { + f, err := os.Open(filename) + if err != nil { + return nil, err + } + err = json.NewDecoder(f).Decode(&data) + if err != nil { + return nil, err + } + f.Close() + } + + ui, ok := data[appName] + if !ok { + ui = UserInfo{} + } + b, err := huego.Discover() + if err != nil { + return nil, err + } + if ui.User != "" { + newb := b.Login(ui.User) + return newb, nil + } + fmt.Println("Please press the Hue Bridge button, then press Enter") + fmt.Scanln() + user, err := b.CreateUser(appName) + if err != nil { + return nil, err + } + data[appName] = UserInfo{User: user} + + b = b.Login(user) + + f, err := os.Create(filename) + defer f.Close() + if err != nil { + return nil, err + } + err = json.NewEncoder(f).Encode(data) + return b, err +} + +func main() { + fmt.Println("vim-go") + b, err := DiscoverAndConnectFromConfig("barak-hue-test") + if err != nil { + panic(err) + } + + rules, err := b.GetRules() + if err != nil { + panic(err) + } + for i, r := range rules { + fmt.Println(i, r.ID, r.Name) + //for _, act := range r.Actions { + //fmt.Printf("\t%#v\n", act) + //} + } + + testRule := huego.Rule{Actions: rules[0].Actions} + t, _ := json.Marshal(testRule) + fmt.Println(string(t)) + + l, err := b.GetGroups() + if err != nil { + panic(err) + } + for i, r := range l { + fmt.Println(i, r.ID, r.Name, r.IsOn()) + //for _, s := range r.Lights { + //fmt.Printf("\t%s\n", s) + //} + } + + s, err := b.GetSensors() + if err != nil { + panic(err) + } + for i, r := range s { + fmt.Println(i, r.ID, r.Name) + //for _, s := range r.Lights { + //fmt.Printf("\t%s\n", s) + //} + } + +} diff --git a/gui/main.go b/gui/main.go new file mode 100644 index 0000000..b0cbb6a --- /dev/null +++ b/gui/main.go @@ -0,0 +1,142 @@ +package main + +import ( + "fmt" + "sort" + "time" + + "git.barakmich.com/barak/hue/discovery" + "github.com/amimof/huego" + "github.com/andlabs/ui" + "github.com/lucasb-eyer/go-colorful" + "github.com/maruel/temperature" +) + +type groupList struct { + box *ui.Box + groups []*group +} + +type group struct { + group huego.Group + box *ui.Box + cb *ui.Checkbox + color *ui.ColorButton +} + +type uiModel struct { + gl *groupList +} + +var bridge *huego.Bridge + +func (u *uiModel) update() { + var err error + if bridge == nil { + bridge, err = discovery.DiscoverAndConnectFromConfig("barak-hue-test") + if err != nil { + ui.QueueMain(func() { + ui.Quit() + }) + } + } + groups, err := bridge.GetGroups() + if err != nil { + panic(err) + } + ui.QueueMain(func() { u.gl.update(groups) }) +} + +func newGroup() *group { + g := &group{} + g.box = ui.NewHorizontalBox() + g.cb = ui.NewCheckbox("") + g.color = ui.NewColorButton() + g.box.Append(g.color, false) + g.box.Append(g.cb, false) + g.cb.OnToggled(g.onToggle) + return g +} + +func (gl *groupList) update(groups []huego.Group) { + sort.Slice(groups, func(i, j int) bool { + return groups[i].ID < groups[j].ID + }) + for len(gl.groups) < len(groups) { + g := newGroup() + gl.groups = append(gl.groups, g) + gl.box.Append(g.box, false) + } + for i, g := range gl.groups { + g.group = groups[i] + g.update() + } +} + +func (g *group) update() { + g.cb.SetText(fmt.Sprintf("%d %s : %s", g.group.ID, g.group.Name, fmt.Sprint(g.group.State.Xy, g.group.State.Bri, g.group.State.Hue, g.group.State.Sat))) + if g.group.State.ColorMode == "xy" { + c := colorful.Xyy(float64(g.group.State.Xy[0]), float64(g.group.State.Xy[1]), (float64(g.group.State.Bri)/(255.0*1.5))+0.33) + r, gr, b := c.LinearRgb() + g.color.SetColor(r, gr, b, 1.0) + } else if g.group.State.ColorMode == "ct" { + r, gr, b := temperature.ToRGB(uint16(1000000.0 / float64(g.group.State.Ct))) + g.color.SetColor(float64(r)/255.0, float64(gr)/255.0, float64(b)/255.0, 1.0) + } else { + b := float64(g.group.State.Bri) / 255.0 + g.color.SetColor(b, b, b, 1.0) + } + g.cb.SetChecked(g.group.IsOn()) +} + +func (g *group) onToggle(c *ui.Checkbox) { + fmt.Println("toggling", g.group.ID) + var err error + if c.Checked() { + err = g.group.On() + } else { + err = g.group.Off() + } + if err != nil { + panic(err) + } +} + +func main() { + closer := make(chan bool) + err := ui.Main(func() { + gl := &groupList{} + uiModel := &uiModel{ + gl: gl, + } + gl.box = ui.NewVerticalBox() + window := ui.NewWindow("Hue UI", 200, 100, false) + window.SetMargined(true) + window.SetChild(gl.box) + window.OnClosing(func(*ui.Window) bool { + ui.Quit() + return true + }) + fmt.Println("whatup") + go updater(closer, uiModel) + window.Show() + }) + fmt.Println("outside") + if err != nil { + panic(err) + } + close(closer) +} + +func updater(closer chan bool, um *uiModel) { + um.update() + for { + select { + case <-closer: + return + case <-time.After(2 * time.Second): + fmt.Println("tick") + um.update() + } + } +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..d89abb3 --- /dev/null +++ b/main.go @@ -0,0 +1,154 @@ +package main + +import ( + "fmt" + "math/rand" + "strconv" + "time" + + "git.barakmich.com/barak/hue/discovery" + "github.com/amimof/huego" + "github.com/lucasb-eyer/go-colorful" +) + +func setLightToHex(l *huego.Light, hex string, tTenths int) error { + return setLightToHexBright(l, hex, -1, tTenths) +} + +func setLightToHexBright(l *huego.Light, hex string, bright int, tTenths int) error { + c, _ := colorful.Hex(hex) + xc, yc, yz := c.Xyy() + var bout uint8 + if bright < 0 { + bout = uint8(255 * yz) + } else { + bout = uint8(bright) + } + return l.SetState(huego.State{ + On: true, + TransitionTime: uint16(tTenths), + ColorMode: "xy", + Xy: []float32{float32(xc), float32(yc)}, + Bri: bout, + }) +} + +func runTransition(l *huego.Light, ret chan *huego.Light) { + setLightToHex(l, "#aaaaaa", 7) + time.Sleep(800 * time.Millisecond) + setLightToHex(l, "#5555ff", 7) + time.Sleep(700 * time.Millisecond) + ret <- l +} + +func runSnowAmbiance(lights []*huego.Light) { + for _, x := range lights { + setLightToHex(x, "#5555ff", 0) + } + var ready []*huego.Light + ret := make(chan *huego.Light, 100) + ready = lights + for { + select { + case l := <-ret: + ready = append(ready, l) + case <-time.Tick(100 * time.Millisecond): + if rand.Float32() < 0.03 { + if len(ready) == 0 { + continue + } + i := rand.Intn(len(ready)) + l := ready[i] + ready = append(ready[:i], ready[i+1:]...) + go runTransition(l, ret) + } + } + } +} + +func runRedTransition(l *huego.Light, c chan *huego.Light) { + setLightToHex(l, "#ff0000", 0) + c <- l +} + +func runGreenTransition(l *huego.Light, c chan *huego.Light) { + setLightToHex(l, "#009900", 0) + c <- l +} + +func runChristmas(lights []*huego.Light) { + var red []*huego.Light + var green []*huego.Light + redc := make(chan *huego.Light, 100) + greenc := make(chan *huego.Light, 100) + for _, x := range lights { + if rand.Float32() < 0.5 { + setLightToHex(x, "#ff0000", 0) + red = append(red, x) + } else { + setLightToHex(x, "#009900", 0) + green = append(green, x) + } + } + for { + select { + case x := <-redc: + red = append(red, x) + case x := <-greenc: + green = append(green, x) + case <-time.Tick(1000 * time.Millisecond): + if len(red)+len(green) == 0 { + continue + } + var selector = red + toRed := false + i := rand.Intn(len(red) + len(green)) + if i >= len(red) { + i = i - len(red) + selector = green + toRed = true + } + l := selector[i] + selector = append(selector[:i], selector[i+1:]...) + if toRed { + go runRedTransition(l, redc) + } else { + go runGreenTransition(l, greenc) + } + } + } +} + +func main() { + bridge, err := discovery.DiscoverAndConnectFromConfig("barak-hue-test") + if err != nil { + panic(err) + } + groups, err := bridge.GetGroups() + if err != nil { + panic(err) + } + var all huego.Group + found := false + for _, x := range groups { + if x.Name == "All Colors" { + found = true + all = x + break + } + } + fmt.Println(all) + + if !found { + panic("couldn't find it") + } + lightaddr := make([]*huego.Light, len(all.Lights)) + for i, x := range all.Lights { + n, _ := strconv.Atoi(x) + lightaddr[i], err = bridge.GetLight(n) + if err != nil { + panic(err) + } + } + runChristmas(lightaddr) +}