commit bda132266de8914681d4fb7e6f495377e77b8287 Author: Greg Date: Wed Oct 23 18:29:13 2019 -0400 Initial commit. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f063deb --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +hrm diff --git a/main.go b/main.go new file mode 100644 index 0000000..cf7f16c --- /dev/null +++ b/main.go @@ -0,0 +1,175 @@ +package main + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "path" + "time" + + "git.wow.st/gmp/ble" + + "gopkg.in/yaml.v2" + + "gioui.org/app" + "gioui.org/io/system" + "gioui.org/layout" + "gioui.org/unit" + "gioui.org/text" + "gioui.org/widget" + "gioui.org/widget/material" + + _ "gioui.org/font/gofont" +) + +type conf struct { +} + +var Config conf + +func main() { + conffile := path.Join(confDir, "config.yml") + if _, err := os.Stat(conffile); os.IsNotExist(err) { + fd, err := os.Create(conffile) + if err != nil { + log.Fatal("Cannot create configuration file: ", err) + } + fd.Close() + } + + confbytes, err := ioutil.ReadFile(conffile) + if err != nil { + log.Fatal("Cannot read configuration file: ", err) + } + if err = yaml.UnmarshalStrict(confbytes, &Config); err != nil { + log.Fatal("Cannot parse configuration file: ", err) + } + go eventloop() + app.Main() +} + +func eventloop() { + w := app.NewWindow( + app.Size(unit.Dp(400), unit.Dp(400)), + app.Title("HRM"), + ) + th := material.NewTheme() + gtx := &layout.Context{Queue: w.Queue()} + + sysinset := &layout.Inset{} + resetSysinset := func(x system.Insets) { + sysinset.Top = x.Top + sysinset.Bottom = x.Bottom + sysinset.Left = x.Left + sysinset.Right = x.Right + } + margin := layout.UniformInset(unit.Dp(10)) + + b := ble.NewBLE() + b.Scan() + + state := "starting" + var periph ble.Peripheral + periphs := make([]ble.Peripheral,0) + btns := make([]*widget.Button,0) + + var autoconnectID string + + var page, scanpage, connpage, hrpage func() + + f := &layout.Flex{Axis: layout.Vertical} + scanpage = func() { + c1 := f.Rigid(gtx, func() { + th.Body1("Heart Rate Monitor").Layout(gtx) + }) + c2 := f.Rigid(gtx, func() { + th.Body1(state).Layout(gtx) + }) + c3 := f.Rigid(gtx, func() { + lst := &layout.List{Axis: layout.Vertical} + lst.Layout(gtx, len(periphs), func(i int) { + th.Button(periphs[i].Name).Layout(gtx, btns[i]) + if btns[i].Clicked(gtx) { + periph = periphs[i] + page = connpage + b.StopScan() + b.Connect(periph) + } + }) + }) + lst := &layout.List{Axis: layout.Vertical} + lst.Layout(gtx, 1, func(i int) { + f.Layout(gtx, c1, c2, c3) + }) + } + + connpage = func() { + c1 := f.Rigid(gtx, func() { + th.Body1("Heart Rate Monitor").Layout(gtx) + }) + c2 := f.Rigid(gtx, func() { + th.Body1("Connecting").Layout(gtx) + }) + c3 := f.Rigid(gtx, func() { + th.Body1(periph.Name).Layout(gtx) + }) + f.Layout(gtx, c1, c2, c3) + } + + hrpage = func() { + c1 := f.Rigid(gtx, func() { + th.Body1("Heart Rate Monitor").Layout(gtx) + }) + c2 := f.Rigid(gtx, func() { + th.Body1(periph.Name).Layout(gtx) + }) + c3 := f.Rigid(gtx, func() { + l := th.H1(fmt.Sprintf("%d",b.HR())) + l.Alignment = text.Middle + l.Layout(gtx) + }) + f.Layout(gtx, c1, c2, c3) + } + + page = scanpage + + tick := time.NewTicker(time.Second / 30) + events := b.Events() + + for { + select { + case e := <-events: + switch e := e.(type) { + case ble.UpdateStateEvent: + state = e.State + case ble.DiscoverEvent: + fmt.Printf("found %s\n", e.Peripheral.Identifier()) + periphs = append(periphs, e.Peripheral) + //btns = append(btns, th.Button(e.Peripheral.Name)) + btns = append(btns, &widget.Button{}) + fmt.Printf("len(periphs) = %d\n", len(periphs)) + if e.Peripheral.Identifier() == autoconnectID { + b.Connect(e.Peripheral) + } + case ble.ConnectEvent: + state = "connected" + page = hrpage + } + case <- tick.C: + w.Invalidate() + case e := <-w.Events(): + switch e := e.(type) { + case system.DestroyEvent: + return + case system.FrameEvent: + gtx.Reset(e.Config, e.Size) + resetSysinset(e.Insets) + sysinset.Layout(gtx, func() { + margin.Layout(gtx, page) + }) + e.Frame(gtx.Ops) + } + } + } +} diff --git a/os_darwin.go b/os_darwin.go new file mode 100644 index 0000000..fad4fdb --- /dev/null +++ b/os_darwin.go @@ -0,0 +1,26 @@ +package main + +import ( + "log" + "os" + "os/user" + "path" +) + +var confDir string + +func init() { + usr, err := user.Current() + if err != nil { + log.Fatal("Cannot get current user: ", err) + } + confDir = path.Join(usr.HomeDir, ".config/gohrm") + if _, err := os.Stat(confDir); os.IsNotExist(err) { + err = os.MkdirAll(confDir, 0700) + if err != nil { + log.Fatal("Cannot create configuration directory %s: %s", confDir, err) + } else { + log.Print("Configuration directory created") + } + } +}