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}