Compare commits
No commits in common. "31fa374c7f7d97eb211f1ea8e2dddc7221086a85" and "265caa30a29fc88c7b900687a29d02da4c7ef12e" have entirely different histories.
31fa374c7f
...
265caa30a2
2
go.mod
2
go.mod
|
@ -4,7 +4,7 @@ go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
gioui.org v0.0.0-20191126175243-2ca2e5462f16
|
gioui.org v0.0.0-20191126175243-2ca2e5462f16
|
||||||
git.wow.st/gmp/ble v0.0.0-20191127164604-2af636b9461a
|
git.wow.st/gmp/ble v0.0.0-20191205134941-3bc712870db2
|
||||||
github.com/google/go-github/v24 v24.0.1 // indirect
|
github.com/google/go-github/v24 v24.0.1 // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20191122200657-5d9234df094c // indirect
|
golang.org/x/oauth2 v0.0.0-20191122200657-5d9234df094c // indirect
|
||||||
gopkg.in/yaml.v2 v2.2.7
|
gopkg.in/yaml.v2 v2.2.7
|
||||||
|
|
255
main.go
255
main.go
|
@ -9,7 +9,6 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.wow.st/gmp/ble"
|
"git.wow.st/gmp/ble"
|
||||||
|
|
||||||
|
@ -78,25 +77,9 @@ func hrDecode(x []byte) int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Stopwatch struct {
|
|
||||||
lasttime time.Time
|
|
||||||
elapsed time.Time
|
|
||||||
running bool
|
|
||||||
startstopBtn *widget.Button
|
|
||||||
resetBtn *widget.Button
|
|
||||||
h, m, s int
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewStopwatch() Stopwatch {
|
|
||||||
return Stopwatch{
|
|
||||||
startstopBtn: &widget.Button{},
|
|
||||||
resetBtn: &widget.Button{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func eventloop() {
|
func eventloop() {
|
||||||
w := app.NewWindow(
|
w := app.NewWindow(
|
||||||
app.Size(unit.Dp(350), unit.Dp(600)),
|
app.Size(unit.Dp(400), unit.Dp(400)),
|
||||||
app.Title("HRM"),
|
app.Title("HRM"),
|
||||||
)
|
)
|
||||||
gofont.Register()
|
gofont.Register()
|
||||||
|
@ -119,7 +102,6 @@ func eventloop() {
|
||||||
state := "starting"
|
state := "starting"
|
||||||
var hr int
|
var hr int
|
||||||
var periph ble.Peripheral
|
var periph ble.Peripheral
|
||||||
var wide bool
|
|
||||||
periphs := make([]ble.Peripheral, 0)
|
periphs := make([]ble.Peripheral, 0)
|
||||||
btns := make([]*widget.Button, 0)
|
btns := make([]*widget.Button, 0)
|
||||||
backBtn := &widget.Button{}
|
backBtn := &widget.Button{}
|
||||||
|
@ -128,42 +110,22 @@ func eventloop() {
|
||||||
|
|
||||||
f := &layout.Flex{Axis: layout.Vertical}
|
f := &layout.Flex{Axis: layout.Vertical}
|
||||||
offpage = func() {
|
offpage = func() {
|
||||||
f.Layout(gtx,
|
c1 := f.Rigid(gtx, func() {
|
||||||
f.Rigid(gtx, func() {
|
|
||||||
th.Body1("Heart Rate Monitor").Layout(gtx)
|
|
||||||
}),
|
|
||||||
f.Rigid(gtx, func() {
|
|
||||||
th.Body1("Bluetooth is Powered Off").Layout(gtx)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
appname := func() {
|
|
||||||
layout.Align(layout.Center).Layout(gtx, func() {
|
|
||||||
th.Body1("Heart Rate Monitor").Layout(gtx)
|
th.Body1("Heart Rate Monitor").Layout(gtx)
|
||||||
})
|
})
|
||||||
|
c2 := f.Rigid(gtx, func() {
|
||||||
|
th.Body1("Bluetooth is Powered Off").Layout(gtx)
|
||||||
|
})
|
||||||
|
f.Layout(gtx, c1, c2)
|
||||||
}
|
}
|
||||||
appstate := func() {
|
scanpage = func() {
|
||||||
layout.Align(layout.Center).Layout(gtx, func() {
|
c1 := f.Rigid(gtx, func() {
|
||||||
|
th.Body1("Heart Rate Monitor").Layout(gtx)
|
||||||
|
})
|
||||||
|
c2 := f.Rigid(gtx, func() {
|
||||||
th.Body1(state).Layout(gtx)
|
th.Body1(state).Layout(gtx)
|
||||||
})
|
})
|
||||||
}
|
c3 := f.Rigid(gtx, func() {
|
||||||
periphname := func() {
|
|
||||||
layout.Align(layout.Center).Layout(gtx, func() {
|
|
||||||
th.Body1("COOSPO").Layout(gtx)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
leftbar := func() {
|
|
||||||
f := &layout.Flex{Axis: layout.Vertical}
|
|
||||||
f.Layout(gtx,
|
|
||||||
f.Rigid(gtx, appname),
|
|
||||||
f.Rigid(gtx, func() { th.Body1("").Layout(gtx) }),
|
|
||||||
f.Rigid(gtx, appstate),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
scanlist := func() {
|
|
||||||
lst := &layout.List{Axis: layout.Vertical}
|
lst := &layout.List{Axis: layout.Vertical}
|
||||||
lst.Layout(gtx, len(periphs), func(i int) {
|
lst.Layout(gtx, len(periphs), func(i int) {
|
||||||
gtx.Constraints.Width.Min = gtx.Constraints.Width.Max
|
gtx.Constraints.Width.Min = gtx.Constraints.Width.Max
|
||||||
|
@ -179,30 +141,21 @@ func eventloop() {
|
||||||
w.Invalidate()
|
w.Invalidate()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
})
|
||||||
|
f.Layout(gtx, c1, c2, c3)
|
||||||
scanpage = func() {
|
|
||||||
if wide {
|
|
||||||
f2 := &layout.Flex{Axis: layout.Horizontal}
|
|
||||||
f2.Layout(gtx,
|
|
||||||
f2.Flex(gtx, 0.2, leftbar),
|
|
||||||
f2.Rigid(gtx, scanlist),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
f.Layout(gtx,
|
|
||||||
f.Rigid(gtx, appname),
|
|
||||||
f.Rigid(gtx, appstate),
|
|
||||||
f.Rigid(gtx, scanlist),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
connpage = func() {
|
connpage = func() {
|
||||||
f.Layout(gtx,
|
c1 := f.Rigid(gtx, func() {
|
||||||
f.Rigid(gtx, appname),
|
th.Body1("Heart Rate Monitor").Layout(gtx)
|
||||||
f.Rigid(gtx, appstate),
|
})
|
||||||
f.Rigid(gtx, periphname),
|
c2 := f.Rigid(gtx, func() {
|
||||||
f.Rigid(gtx, func() {
|
th.Body1("Connecting").Layout(gtx)
|
||||||
|
})
|
||||||
|
c3 := f.Rigid(gtx, func() {
|
||||||
|
th.Body1(periph.Name).Layout(gtx)
|
||||||
|
})
|
||||||
|
c4 := f.Rigid(gtx, func() {
|
||||||
th.Button("Cancel").Layout(gtx, backBtn)
|
th.Button("Cancel").Layout(gtx, backBtn)
|
||||||
if backBtn.Clicked(gtx) {
|
if backBtn.Clicked(gtx) {
|
||||||
ble.CancelConnection(periph)
|
ble.CancelConnection(periph)
|
||||||
|
@ -213,16 +166,35 @@ func eventloop() {
|
||||||
state = "scanning"
|
state = "scanning"
|
||||||
page = scanpage
|
page = scanpage
|
||||||
}
|
}
|
||||||
}),
|
})
|
||||||
)
|
f.Layout(gtx, c1, c2, c3, c4)
|
||||||
}
|
}
|
||||||
|
|
||||||
hrcircle := func() int {
|
hrpage = func() {
|
||||||
var w, h1 float32
|
c1 := f.Rigid(gtx, func() {
|
||||||
layout.Align(layout.Center).Layout(gtx, func() {
|
th.Body1("Heart Rate Monitor").Layout(gtx)
|
||||||
|
})
|
||||||
|
c2 := f.Rigid(gtx, func() {
|
||||||
|
th.Body1(periph.Name).Layout(gtx)
|
||||||
|
})
|
||||||
|
c4 := f.Rigid(gtx, func() {
|
||||||
|
layout.UniformInset(unit.Dp(2)).Layout(gtx, func() {
|
||||||
|
th.Button("Stop").Layout(gtx, backBtn)
|
||||||
|
})
|
||||||
|
if backBtn.Clicked(gtx) {
|
||||||
|
ble.Disconnect(periph)
|
||||||
|
periphs = periphs[:0]
|
||||||
|
Config.Autoconnect = ""
|
||||||
|
saveConfig()
|
||||||
|
b.Scan()
|
||||||
|
state = "scanning"
|
||||||
|
page = scanpage
|
||||||
|
}
|
||||||
|
})
|
||||||
|
c3 := f.Rigid(gtx, func() {
|
||||||
blue := color.RGBA{0x3f, 0x51, 0xb5, 255}
|
blue := color.RGBA{0x3f, 0x51, 0xb5, 255}
|
||||||
white := color.RGBA{255, 255, 255, 255}
|
white := color.RGBA{255, 255, 255, 255}
|
||||||
w, h1 = float32(gtx.Constraints.Width.Max), float32(gtx.Constraints.Height.Max)
|
w, h1 := float32(gtx.Constraints.Width.Max), float32(gtx.Constraints.Height.Max)
|
||||||
if w < h1 {
|
if w < h1 {
|
||||||
h1 = w
|
h1 = w
|
||||||
}
|
}
|
||||||
|
@ -249,135 +221,13 @@ func eventloop() {
|
||||||
})
|
})
|
||||||
gtx.Dimensions.Size = image.Point{int(h1), int(h1)}
|
gtx.Dimensions.Size = image.Point{int(h1), int(h1)}
|
||||||
})
|
})
|
||||||
return int(h1)
|
f.Layout(gtx, c1, c2, c3, c4)
|
||||||
}
|
|
||||||
|
|
||||||
sw := NewStopwatch()
|
|
||||||
|
|
||||||
stopwatch := func() {
|
|
||||||
startstoptxt := "start"
|
|
||||||
if sw.running {
|
|
||||||
sw.elapsed = sw.elapsed.Add(time.Since(sw.lasttime))
|
|
||||||
startstoptxt = "stop"
|
|
||||||
}
|
|
||||||
sw.lasttime = time.Now()
|
|
||||||
f := layout.Flex{Axis: layout.Vertical}
|
|
||||||
f.Layout(gtx,
|
|
||||||
f.Rigid(gtx, func() {
|
|
||||||
layout.Align(layout.Center).Layout(gtx, func() {
|
|
||||||
gtx.Constraints.Width.Max = 1e6
|
|
||||||
th.H4(sw.elapsed.Format("15:04:05.00")).Layout(gtx)
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
f.Rigid(gtx, func() {
|
|
||||||
f2 := layout.Flex{Axis: layout.Horizontal}
|
|
||||||
gtx.Constraints.Height.Min = 100
|
|
||||||
f2.Layout(gtx,
|
|
||||||
f2.Flex(gtx, 0.5, func() {
|
|
||||||
layout.UniformInset(unit.Dp(2)).Layout(gtx, func() {
|
|
||||||
th.Button(startstoptxt).Layout(gtx, sw.startstopBtn)
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
f2.Flex(gtx, 0.5, func() {
|
|
||||||
layout.UniformInset(unit.Dp(2)).Layout(gtx, func() {
|
|
||||||
th.Button("reset").Layout(gtx, sw.resetBtn)
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
if sw.startstopBtn.Clicked(gtx) {
|
|
||||||
if sw.running {
|
|
||||||
sw.running = false
|
|
||||||
} else {
|
|
||||||
sw.running = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if sw.resetBtn.Clicked(gtx) {
|
|
||||||
sw.elapsed = time.Time{}
|
|
||||||
sw.running = false
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
swidth := new(int)
|
|
||||||
*swidth = 900
|
|
||||||
hrpage = func() {
|
|
||||||
stopbtn := func() {
|
|
||||||
gtx.Constraints.Width.Min = *swidth
|
|
||||||
gtx.Constraints.Height.Min = 100
|
|
||||||
layout.UniformInset(unit.Dp(2)).Layout(gtx, func() {
|
|
||||||
th.Button("Disconnect").Layout(gtx, backBtn)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if wide {
|
|
||||||
f2 := &layout.Flex{Axis: layout.Horizontal}
|
|
||||||
f2.Layout(gtx,
|
|
||||||
f2.Flex(gtx, 0.4, func() {
|
|
||||||
f3 := &layout.Flex{Axis: layout.Vertical}
|
|
||||||
c1 := f3.Rigid(gtx, func() {
|
|
||||||
appname()
|
|
||||||
*swidth = gtx.Dimensions.Size.X
|
|
||||||
})
|
|
||||||
c2 := f3.Rigid(gtx, func() {
|
|
||||||
periphname()
|
|
||||||
s2 := gtx.Dimensions.Size.X
|
|
||||||
if s2 > *swidth {
|
|
||||||
*swidth = s2
|
|
||||||
}
|
|
||||||
})
|
|
||||||
c3 := f3.Rigid(gtx, stopwatch)
|
|
||||||
c4 := f3.Rigid(gtx, stopbtn)
|
|
||||||
f3.Layout(gtx,
|
|
||||||
c1,
|
|
||||||
f3.Rigid(gtx, appstate),
|
|
||||||
c2,
|
|
||||||
f3.Flex(gtx, 1.0, func() { th.Body1("").Layout(gtx) }),
|
|
||||||
c3,
|
|
||||||
c4,
|
|
||||||
)
|
|
||||||
}),
|
|
||||||
f2.Flex(gtx, 0.6, func() { hrcircle() }),
|
|
||||||
)
|
|
||||||
} else { // !wide
|
|
||||||
c1 := f.Rigid(gtx, func() {
|
|
||||||
layout.Align(layout.Center).Layout(gtx, func() {
|
|
||||||
gtx.Constraints.Width.Min = *swidth
|
|
||||||
gtx.Constraints.Width.Max = *swidth
|
|
||||||
stopwatch()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
c2 := f.Rigid(gtx, func() {
|
|
||||||
layout.Align(layout.Center).Layout(gtx, stopbtn)
|
|
||||||
})
|
|
||||||
f.Layout(gtx,
|
|
||||||
f.Rigid(gtx, appname),
|
|
||||||
f.Rigid(gtx, appstate),
|
|
||||||
f.Rigid(gtx, periphname),
|
|
||||||
f.Flex(gtx, 1.0, func() {
|
|
||||||
*swidth = hrcircle()
|
|
||||||
}),
|
|
||||||
c1,
|
|
||||||
c2,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if backBtn.Clicked(gtx) {
|
|
||||||
ble.Disconnect(periph)
|
|
||||||
periphs = periphs[:0]
|
|
||||||
Config.Autoconnect = ""
|
|
||||||
saveConfig()
|
|
||||||
b.Scan()
|
|
||||||
state = "scanning"
|
|
||||||
page = scanpage
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
page = offpage
|
page = offpage
|
||||||
|
|
||||||
t := time.NewTicker(time.Second/30)
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-t.C:
|
|
||||||
w.Invalidate()
|
|
||||||
case e := <-b.Events():
|
case e := <-b.Events():
|
||||||
switch e := e.(type) {
|
switch e := e.(type) {
|
||||||
case ble.UpdateStateEvent:
|
case ble.UpdateStateEvent:
|
||||||
|
@ -447,11 +297,6 @@ func eventloop() {
|
||||||
return
|
return
|
||||||
case system.FrameEvent:
|
case system.FrameEvent:
|
||||||
gtx.Reset(e.Config, e.Size)
|
gtx.Reset(e.Config, e.Size)
|
||||||
if e.Size.X > e.Size.Y {
|
|
||||||
wide = true
|
|
||||||
} else {
|
|
||||||
wide = false
|
|
||||||
}
|
|
||||||
resetSysinset(e.Insets)
|
resetSysinset(e.Insets)
|
||||||
sysinset.Layout(gtx, func() {
|
sysinset.Layout(gtx, func() {
|
||||||
margin.Layout(gtx, page)
|
margin.Layout(gtx, page)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user