1package comms
2
3import (
4 "bytes"
5 "encoding/binary"
6 "odoki/constants"
7 "odoki/ui/onelead"
8 "odoki/utils"
9 "time"
10
11 "fyne.io/fyne/v2/widget"
12 "tinygo.org/x/bluetooth"
13)
14
15var (
16 adapter = bluetooth.DefaultAdapter
17 bluetoothDevice *bluetooth.Device
18 Connected bool
19 heartRateServiceUUID = bluetooth.ServiceUUIDHeartRate
20 heartRateCharacteristicUUID = bluetooth.CharacteristicUUIDHeartRateMeasurement
21
22 rawDataServiceUUID = bluetooth.ServiceUUIDAdafruitAddressable
23 rawDataCharacteristicUUID = bluetooth.CharacteristicUUIDAdafruitRawTXRX
24
25 ReceivedHeartRate uint8
26)
27
28func Init() {
29 // Enable BLE interface.
30 utils.Must("enable BLE stack", adapter.Enable())
31}
32
33func Scan(selectWidget *widget.Select, callback func(*widget.Select, *bluetooth.Adapter, bluetooth.ScanResult)) {
34 // Start scanning.
35 selectWidget.Options = []string{}
36 time.AfterFunc(constants.BluetoothScanTimeout, func() {
37 adapter.StopScan()
38 })
39 err := adapter.Scan(func(adapter *bluetooth.Adapter, device bluetooth.ScanResult) {
40 callback(selectWidget, adapter, device)
41 })
42 utils.Must("start scan", err)
43}
44
45func Connect(connectAddress bluetooth.Address) bool {
46 device, err := adapter.Connect(connectAddress, bluetooth.ConnectionParams{})
47 if err != nil {
48 Connected = false
49 return false
50 } else {
51 bluetoothDevice = device
52 Connected = true
53 // get services
54 println("discovering services/characteristics")
55 srvcs, err := device.DiscoverServices([]bluetooth.UUID{heartRateServiceUUID})
56 utils.Must("discover services", err)
57
58 if len(srvcs) == 0 {
59 panic("could not find heart rate service")
60 }
61
62 srvc := srvcs[0]
63
64 println("found service", srvc.UUID().String())
65
66 chars, err := srvc.DiscoverCharacteristics([]bluetooth.UUID{heartRateCharacteristicUUID})
67 if err != nil {
68 println(err)
69 }
70
71 if len(chars) == 0 {
72 panic("could not find heart rate characteristic")
73 }
74
75 char := chars[0]
76 println("found characteristic", char.UUID().String())
77
78 char.EnableNotifications(func(buf []byte) {
79 println("got data!")
80 ReceivedHeartRate = uint8(buf[1])
81 onelead.UpdateHeartrate(uint8(buf[1]))
82 })
83
84 // get raw data service
85 // get services
86 println("discovering services/characteristics")
87 srvcs, err = device.DiscoverServices([]bluetooth.UUID{rawDataServiceUUID})
88 utils.Must("discover services", err)
89
90 if len(srvcs) == 0 {
91 panic("could not find raw data service")
92 }
93
94 srvc = srvcs[0]
95
96 println("found service", srvc.UUID().String())
97
98 chars, err = srvc.DiscoverCharacteristics([]bluetooth.UUID{rawDataCharacteristicUUID})
99 if err != nil {
100 println(err)
101 }
102
103 if len(chars) == 0 {
104 panic("could not find raw data characteristic")
105 }
106
107 char = chars[0]
108 println("found characteristic", char.UUID().String())
109
110 char.EnableNotifications(func(buf []byte) {
111 println("got data!")
112 for i := 0; i < constants.ChannelCount; i++ {
113 now := buf[i*4+1 : i*4+5]
114 nowBuffer := bytes.NewReader(now)
115 var nowVar int32
116 binary.Read(nowBuffer, binary.BigEndian, &nowVar)
117 println(nowVar)
118 onelead.LeadBuffer[i] = append(onelead.LeadBuffer[i], nowVar)
119 }
120 })
121
122 return true
123 }
124
125}