Skip to content

Commit ef90e5d

Browse files
authored
gattc: use GetUUID() to allow for bare metal use of short UUID. (#14)
* gattc: use UUID() to allow for bare metal to permit clean use of short UUIDs Signed-off-by: deadprogram <ron@hybridgroup.com> * gattc/macos: correct usage of UUID wrapper type alias Signed-off-by: Ron Evans <ron@hybridgroup.com> * gattc/sd: correct usage of UUID wrapper type alias Signed-off-by: Ron Evans <ron@hybridgroup.com> * gattc/sd, uuid/sd: changes intended to reduce memory allocations for service and characteristic discovery Signed-off-by: deadprogram <ron@hybridgroup.com> * gattc/sd: partial improvements to DiscoverServices/DiscoverCharacteristics Signed-off-by: deadprogram <ron@hybridgroup.com> * gattc/sd: mostly getting uuid back for services in DiscoverServices Signed-off-by: deadprogram <ron@hybridgroup.com> * uuid/sd: correct way to calculate UUID from shortUUID Signed-off-by: deadprogram <ron@hybridgroup.com> * gattc/sd: able to discover services and characteristics Signed-off-by: deadprogram <ron@hybridgroup.com> * examples: updated discover example that can run with OS or bare metal Signed-off-by: deadprogram <ron@hybridgroup.com> * gattc/sd: ensure safe casts for length of returned struct when converting short UUID Signed-off-by: deadprogram <ron@hybridgroup.com>
1 parent 6dc1dff commit ef90e5d

File tree

9 files changed

+302
-105
lines changed

9 files changed

+302
-105
lines changed

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ smoketest-linux:
3333
GOOS=linux go build -o /tmp/go-build-discard ./examples/heartrate
3434
GOOS=linux go build -o /tmp/go-build-discard ./examples/nusserver
3535
GOOS=linux go build -o /tmp/go-build-discard ./examples/scanner
36+
GOOS=linux go build -o /tmp/go-build-discard ./examples/discover
3637

3738
smoketest-windows:
3839
# Test on Windows.
@@ -41,3 +42,4 @@ smoketest-windows:
4142
smoketest-macos:
4243
# Test on macos.
4344
GOOS=darwin CGO_ENABLED=1 go build -o /tmp/go-build-discard ./examples/scanner
45+
GOOS=darwin CGO_ENABLED=1 go build -o /tmp/go-build-discard ./examples/discover

adapter_nrf528xx.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ func handleEvent() {
177177
// one discovered service. Use the first as a sensible fallback.
178178
discoveringService.startHandle.Set(discoveryEvent.services[0].handle_range.start_handle)
179179
discoveringService.endHandle.Set(discoveryEvent.services[0].handle_range.end_handle)
180+
discoveringService.uuid = discoveryEvent.services[0].uuid
180181
} else {
181182
// No service found.
182183
discoveringService.startHandle.Set(0)
@@ -192,6 +193,9 @@ func handleEvent() {
192193
discoveringCharacteristic.handle_value.Set(discoveryEvent.chars[0].handle_value)
193194
discoveringCharacteristic.char_props = discoveryEvent.chars[0].char_props
194195
discoveringCharacteristic.uuid = discoveryEvent.chars[0].uuid
196+
} else {
197+
// zero indicates we received no characteristic, set handle_value to last
198+
discoveringCharacteristic.handle_value.Set(0xffff)
195199
}
196200
case C.BLE_GATTC_EVT_DESC_DISC_RSP:
197201
discoveryEvent := gattcEvent.params.unionfield_desc_disc_rsp()

examples/discover/main.go

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,33 @@
1+
// This example scans and then connects to a specific Bluetooth peripheral
2+
// and then displays all of the services and characteristics.
3+
//
4+
// To run this on a desktop system:
5+
//
6+
// go run ./examples/discover EE:74:7D:C9:2A:68
7+
//
8+
// To run this on a microcontroller, change the constant value in the file
9+
// "mcu.go" to set the MAC address of the device you want to discover.
10+
// Then, flash to the microcontroller board like this:
11+
//
12+
// tinygo flash -o circuitplay-bluefruit ./examples/discover
13+
//
14+
// Once the program is flashed to the board, connect to the USB port
15+
// via serial to view the output.
16+
//
117
package main
218

319
import (
4-
"os"
20+
"time"
521

622
"tinygo.org/x/bluetooth"
723
)
824

925
var adapter = bluetooth.DefaultAdapter
1026

1127
func main() {
12-
if len(os.Args) < 2 {
13-
println("usage: discover [local name]")
14-
os.Exit(1)
15-
}
28+
time.Sleep(3 * time.Second)
1629

17-
// look for device with specific name
18-
name := os.Args[1]
30+
println("enabling")
1931

2032
// Enable BLE interface.
2133
must("enable BLE stack", adapter.Enable())
@@ -26,7 +38,7 @@ func main() {
2638
println("scanning...")
2739
err := adapter.Scan(func(adapter *bluetooth.Adapter, result bluetooth.ScanResult) {
2840
println("found device:", result.Address.String(), result.RSSI, result.LocalName())
29-
if result.LocalName() == name {
41+
if result.Address.String() == connectAddress() {
3042
adapter.StopScan()
3143
ch <- result
3244
}
@@ -38,25 +50,30 @@ func main() {
3850
device, err = adapter.Connect(result.Address, bluetooth.ConnectionParams{})
3951
if err != nil {
4052
println(err.Error())
41-
os.Exit(1)
53+
return
4254
}
4355

44-
println("connected to ", result.LocalName())
56+
println("connected to ", result.Address.String())
4557
}
4658

4759
// get services
4860
println("discovering services/characteristics")
4961
srvcs, err := device.DiscoverServices(nil)
62+
must("discover services", err)
63+
5064
for _, srvc := range srvcs {
51-
println("- service", srvc.UUID.String())
65+
println("- service", srvc.UUID().String())
5266

53-
chars, _ := srvc.DiscoverCharacteristics(nil)
67+
chars, err := srvc.DiscoverCharacteristics(nil)
68+
if err != nil {
69+
println(err)
70+
}
5471
for _, char := range chars {
55-
println("-- characteristic", char.UUID.String())
72+
println("-- characteristic", char.UUID().String())
5673
}
5774
}
5875

59-
must("start scan", err)
76+
done()
6077
}
6178

6279
func must(action string, err error) {

examples/discover/mcu.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// +build baremetal
2+
3+
package main
4+
5+
import (
6+
"time"
7+
)
8+
9+
// replace this with the MAC address of the Bluetooth peripheral you want to connect to.
10+
const deviceAddress = "E4:B7:F4:11:8D:33"
11+
12+
func connectAddress() string {
13+
return deviceAddress
14+
}
15+
16+
// done just blocks forever, allows USB CDC reset for flashing new software.
17+
func done() {
18+
println("Done.")
19+
20+
time.Sleep(1 * time.Hour)
21+
}

examples/discover/os.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// +build !baremetal
2+
3+
package main
4+
5+
import "os"
6+
7+
func connectAddress() string {
8+
if len(os.Args) < 2 {
9+
println("usage: discover [address]")
10+
os.Exit(1)
11+
}
12+
13+
// look for device with specific name
14+
address := os.Args[1]
15+
16+
return address
17+
}
18+
19+
// done just prints a message and allows program to exit.
20+
func done() {
21+
println("Done.")
22+
}

gattc_darwin.go

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,28 +33,37 @@ func (d *Device) DiscoverServices(uuids []UUID) ([]DeviceService, error) {
3333
for _, dsvc := range d.prph.Services() {
3434
uuid, _ := ParseUUID(dsvc.UUID().String())
3535
svc := DeviceService{
36-
UUID: uuid,
37-
device: d,
38-
service: dsvc,
36+
uuidWrapper: uuid,
37+
device: d,
38+
service: dsvc,
3939
}
4040
svcs = append(svcs, svc)
41-
d.services[svc.UUID] = &svc
41+
d.services[svc.uuidWrapper] = &svc
4242
}
4343
return svcs, nil
4444
case <-time.NewTimer(10 * time.Second).C:
4545
return nil, errors.New("timeout on DiscoverServices")
4646
}
4747
}
4848

49+
// uuidWrapper is a type alias for UUID so we ensure no conflicts with
50+
// struct method of the same name.
51+
type uuidWrapper = UUID
52+
4953
// DeviceService is a BLE service on a connected peripheral device.
5054
type DeviceService struct {
51-
UUID
55+
uuidWrapper
5256

5357
device *Device
5458

5559
service cbgo.Service
5660
}
5761

62+
// UUID returns the UUID for this DeviceService.
63+
func (s *DeviceService) UUID() UUID {
64+
return s.uuidWrapper
65+
}
66+
5867
// DiscoverCharacteristics discovers characteristics in this service. Pass a
5968
// list of characteristic UUIDs you are interested in to this function. Either a
6069
// list of all requested services is returned, or if some services could not be
@@ -83,12 +92,12 @@ func (s *DeviceService) DiscoverCharacteristics(uuids []UUID) ([]DeviceCharacter
8392
for _, dchar := range s.service.Characteristics() {
8493
uuid, _ := ParseUUID(dchar.UUID().String())
8594
char := DeviceCharacteristic{
86-
UUID: uuid,
95+
uuidWrapper: uuid,
8796
service: s,
8897
characteristic: dchar,
8998
}
9099
chars = append(chars, char)
91-
s.device.characteristics[char.UUID] = &char
100+
s.device.characteristics[char.uuidWrapper] = &char
92101
}
93102
return chars, nil
94103
case <-time.NewTimer(10 * time.Second).C:
@@ -99,14 +108,19 @@ func (s *DeviceService) DiscoverCharacteristics(uuids []UUID) ([]DeviceCharacter
99108
// DeviceCharacteristic is a BLE characteristic on a connected peripheral
100109
// device.
101110
type DeviceCharacteristic struct {
102-
UUID
111+
uuidWrapper
103112

104113
service *DeviceService
105114

106115
characteristic cbgo.Characteristic
107116
callback func(buf []byte)
108117
}
109118

119+
// UUID returns the UUID for this DeviceCharacteristic.
120+
func (c *DeviceCharacteristic) UUID() UUID {
121+
return c.uuidWrapper
122+
}
123+
110124
// WriteWithoutResponse replaces the characteristic value with a new value. The
111125
// call will return before all data has been written. A limited number of such
112126
// writes can be in flight at any given time. This call is also known as a

gattc_linux.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,22 @@ import (
1111
"github.com/muka/go-bluetooth/bluez/profile/gatt"
1212
)
1313

14+
// UUIDWrapper is a type alias for UUID so we ensure no conflicts with
15+
// struct method of the same name.
16+
type uuidWrapper = UUID
17+
1418
// DeviceService is a BLE service on a connected peripheral device.
1519
type DeviceService struct {
16-
UUID
20+
uuidWrapper
1721

1822
service *gatt.GattService1
1923
}
2024

25+
// UUID returns the UUID for this DeviceService.
26+
func (s *DeviceService) UUID() UUID {
27+
return s.uuidWrapper
28+
}
29+
2130
// DiscoverServices starts a service discovery procedure. Pass a list of service
2231
// UUIDs you are interested in to this function. Either a slice of all services
2332
// is returned (of the same length as the requested UUIDs and in the same
@@ -89,7 +98,7 @@ func (d *Device) DiscoverServices(uuids []UUID) ([]DeviceService, error) {
8998
}
9099

91100
uuid, _ := ParseUUID(service.Properties.UUID)
92-
ds := DeviceService{UUID: uuid,
101+
ds := DeviceService{uuidWrapper: uuid,
93102
service: service,
94103
}
95104

@@ -108,11 +117,16 @@ func (d *Device) DiscoverServices(uuids []UUID) ([]DeviceService, error) {
108117
// DeviceCharacteristic is a BLE characteristic on a connected peripheral
109118
// device.
110119
type DeviceCharacteristic struct {
111-
UUID
120+
uuidWrapper
112121

113122
characteristic *gatt.GattCharacteristic1
114123
}
115124

125+
// UUID returns the UUID for this DeviceCharacteristic.
126+
func (c *DeviceCharacteristic) UUID() UUID {
127+
return c.uuidWrapper
128+
}
129+
116130
// DiscoverCharacteristics discovers characteristics in this service. Pass a
117131
// list of characteristic UUIDs you are interested in to this function. Either a
118132
// list of all requested services is returned, or if some services could not be
@@ -171,7 +185,7 @@ func (s *DeviceService) DiscoverCharacteristics(uuids []UUID) ([]DeviceCharacter
171185
}
172186

173187
uuid, _ := ParseUUID(char.Properties.UUID)
174-
dc := DeviceCharacteristic{UUID: uuid,
188+
dc := DeviceCharacteristic{uuidWrapper: uuid,
175189
characteristic: char,
176190
}
177191

0 commit comments

Comments
 (0)