Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ smoketest-linux:
GOOS=linux go build -o /tmp/go-build-discard ./examples/heartrate
GOOS=linux go build -o /tmp/go-build-discard ./examples/nusserver
GOOS=linux go build -o /tmp/go-build-discard ./examples/scanner
GOOS=linux go build -o /tmp/go-build-discard ./examples/discover

smoketest-windows:
# Test on Windows.
Expand All @@ -41,3 +42,4 @@ smoketest-windows:
smoketest-macos:
# Test on macos.
GOOS=darwin CGO_ENABLED=1 go build -o /tmp/go-build-discard ./examples/scanner
GOOS=darwin CGO_ENABLED=1 go build -o /tmp/go-build-discard ./examples/discover
4 changes: 4 additions & 0 deletions adapter_nrf528xx.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ func handleEvent() {
// one discovered service. Use the first as a sensible fallback.
discoveringService.startHandle.Set(discoveryEvent.services[0].handle_range.start_handle)
discoveringService.endHandle.Set(discoveryEvent.services[0].handle_range.end_handle)
discoveringService.uuid = discoveryEvent.services[0].uuid
} else {
// No service found.
discoveringService.startHandle.Set(0)
Expand All @@ -192,6 +193,9 @@ func handleEvent() {
discoveringCharacteristic.handle_value.Set(discoveryEvent.chars[0].handle_value)
discoveringCharacteristic.char_props = discoveryEvent.chars[0].char_props
discoveringCharacteristic.uuid = discoveryEvent.chars[0].uuid
} else {
// zero indicates we received no characteristic, set handle_value to last
discoveringCharacteristic.handle_value.Set(0xffff)
}
case C.BLE_GATTC_EVT_DESC_DISC_RSP:
discoveryEvent := gattcEvent.params.unionfield_desc_disc_rsp()
Expand Down
45 changes: 31 additions & 14 deletions examples/discover/main.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
// This example scans and then connects to a specific Bluetooth peripheral
// and then displays all of the services and characteristics.
//
// To run this on a desktop system:
//
// go run ./examples/discover EE:74:7D:C9:2A:68
//
// To run this on a microcontroller, change the constant value in the file
// "mcu.go" to set the MAC address of the device you want to discover.
// Then, flash to the microcontroller board like this:
//
// tinygo flash -o circuitplay-bluefruit ./examples/discover
//
// Once the program is flashed to the board, connect to the USB port
// via serial to view the output.
//
package main

import (
"os"
"time"

"tinygo.org/x/bluetooth"
)

var adapter = bluetooth.DefaultAdapter

func main() {
if len(os.Args) < 2 {
println("usage: discover [local name]")
os.Exit(1)
}
time.Sleep(3 * time.Second)

// look for device with specific name
name := os.Args[1]
println("enabling")

// Enable BLE interface.
must("enable BLE stack", adapter.Enable())
Expand All @@ -26,7 +38,7 @@ func main() {
println("scanning...")
err := adapter.Scan(func(adapter *bluetooth.Adapter, result bluetooth.ScanResult) {
println("found device:", result.Address.String(), result.RSSI, result.LocalName())
if result.LocalName() == name {
if result.Address.String() == connectAddress() {
adapter.StopScan()
ch <- result
}
Expand All @@ -38,25 +50,30 @@ func main() {
device, err = adapter.Connect(result.Address, bluetooth.ConnectionParams{})
if err != nil {
println(err.Error())
os.Exit(1)
return
}

println("connected to ", result.LocalName())
println("connected to ", result.Address.String())
}

// get services
println("discovering services/characteristics")
srvcs, err := device.DiscoverServices(nil)
must("discover services", err)

for _, srvc := range srvcs {
println("- service", srvc.UUID.String())
println("- service", srvc.UUID().String())

chars, _ := srvc.DiscoverCharacteristics(nil)
chars, err := srvc.DiscoverCharacteristics(nil)
if err != nil {
println(err)
}
for _, char := range chars {
println("-- characteristic", char.UUID.String())
println("-- characteristic", char.UUID().String())
}
}

must("start scan", err)
done()
}

func must(action string, err error) {
Expand Down
21 changes: 21 additions & 0 deletions examples/discover/mcu.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// +build baremetal

package main

import (
"time"
)

// replace this with the MAC address of the Bluetooth peripheral you want to connect to.
const deviceAddress = "E4:B7:F4:11:8D:33"

func connectAddress() string {
return deviceAddress
}

// done just blocks forever, allows USB CDC reset for flashing new software.
func done() {
println("Done.")

time.Sleep(1 * time.Hour)
}
22 changes: 22 additions & 0 deletions examples/discover/os.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// +build !baremetal

package main

import "os"

func connectAddress() string {
if len(os.Args) < 2 {
println("usage: discover [address]")
os.Exit(1)
}

// look for device with specific name
address := os.Args[1]

return address
}

// done just prints a message and allows program to exit.
func done() {
println("Done.")
}
30 changes: 22 additions & 8 deletions gattc_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,37 @@ func (d *Device) DiscoverServices(uuids []UUID) ([]DeviceService, error) {
for _, dsvc := range d.prph.Services() {
uuid, _ := ParseUUID(dsvc.UUID().String())
svc := DeviceService{
UUID: uuid,
device: d,
service: dsvc,
uuidWrapper: uuid,
device: d,
service: dsvc,
}
svcs = append(svcs, svc)
d.services[svc.UUID] = &svc
d.services[svc.uuidWrapper] = &svc
}
return svcs, nil
case <-time.NewTimer(10 * time.Second).C:
return nil, errors.New("timeout on DiscoverServices")
}
}

// uuidWrapper is a type alias for UUID so we ensure no conflicts with
// struct method of the same name.
type uuidWrapper = UUID

// DeviceService is a BLE service on a connected peripheral device.
type DeviceService struct {
UUID
uuidWrapper

device *Device

service cbgo.Service
}

// UUID returns the UUID for this DeviceService.
func (s *DeviceService) UUID() UUID {
return s.uuidWrapper
}

// DiscoverCharacteristics discovers characteristics in this service. Pass a
// list of characteristic UUIDs you are interested in to this function. Either a
// list of all requested services is returned, or if some services could not be
Expand Down Expand Up @@ -83,12 +92,12 @@ func (s *DeviceService) DiscoverCharacteristics(uuids []UUID) ([]DeviceCharacter
for _, dchar := range s.service.Characteristics() {
uuid, _ := ParseUUID(dchar.UUID().String())
char := DeviceCharacteristic{
UUID: uuid,
uuidWrapper: uuid,
service: s,
characteristic: dchar,
}
chars = append(chars, char)
s.device.characteristics[char.UUID] = &char
s.device.characteristics[char.uuidWrapper] = &char
}
return chars, nil
case <-time.NewTimer(10 * time.Second).C:
Expand All @@ -99,14 +108,19 @@ func (s *DeviceService) DiscoverCharacteristics(uuids []UUID) ([]DeviceCharacter
// DeviceCharacteristic is a BLE characteristic on a connected peripheral
// device.
type DeviceCharacteristic struct {
UUID
uuidWrapper

service *DeviceService

characteristic cbgo.Characteristic
callback func(buf []byte)
}

// UUID returns the UUID for this DeviceCharacteristic.
func (c *DeviceCharacteristic) UUID() UUID {
return c.uuidWrapper
}

// WriteWithoutResponse replaces the characteristic value with a new value. The
// call will return before all data has been written. A limited number of such
// writes can be in flight at any given time. This call is also known as a
Expand Down
22 changes: 18 additions & 4 deletions gattc_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,22 @@ import (
"github.com/muka/go-bluetooth/bluez/profile/gatt"
)

// UUIDWrapper is a type alias for UUID so we ensure no conflicts with
// struct method of the same name.
type uuidWrapper = UUID

// DeviceService is a BLE service on a connected peripheral device.
type DeviceService struct {
UUID
uuidWrapper

service *gatt.GattService1
}

// UUID returns the UUID for this DeviceService.
func (s *DeviceService) UUID() UUID {
return s.uuidWrapper
}

// DiscoverServices starts a service discovery procedure. Pass a list of service
// UUIDs you are interested in to this function. Either a slice of all services
// is returned (of the same length as the requested UUIDs and in the same
Expand Down Expand Up @@ -89,7 +98,7 @@ func (d *Device) DiscoverServices(uuids []UUID) ([]DeviceService, error) {
}

uuid, _ := ParseUUID(service.Properties.UUID)
ds := DeviceService{UUID: uuid,
ds := DeviceService{uuidWrapper: uuid,
service: service,
}

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

characteristic *gatt.GattCharacteristic1
}

// UUID returns the UUID for this DeviceCharacteristic.
func (c *DeviceCharacteristic) UUID() UUID {
return c.uuidWrapper
}

// DiscoverCharacteristics discovers characteristics in this service. Pass a
// list of characteristic UUIDs you are interested in to this function. Either a
// list of all requested services is returned, or if some services could not be
Expand Down Expand Up @@ -171,7 +185,7 @@ func (s *DeviceService) DiscoverCharacteristics(uuids []UUID) ([]DeviceCharacter
}

uuid, _ := ParseUUID(char.Properties.UUID)
dc := DeviceCharacteristic{UUID: uuid,
dc := DeviceCharacteristic{uuidWrapper: uuid,
characteristic: char,
}

Expand Down
Loading