hrm/main.go

180 lines
3.7 KiB
Go

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]
b.StopScan()
b.Connect(periph)
page = connpage
w.Invalidate()
}
})
})
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:
fmt.Printf("Connect event\n")
state = "connected"
ble.DiscoverServices(e.Peripheral)
page = hrpage
w.Invalidate()
}
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)
}
}
}
}