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>
This commit is contained in:
parent
6dc1dff711
commit
ef90e5d337
9 changed files with 301 additions and 104 deletions
2
Makefile
2
Makefile
|
@ -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.
|
||||
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
@ -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()
|
||||
|
|
|
@ -1,7 +1,23 @@
|
|||
// 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"
|
||||
)
|
||||
|
@ -9,13 +25,9 @@ import (
|
|||
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())
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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) {
|
||||
|
|
21
examples/discover/mcu.go
Normal file
21
examples/discover/mcu.go
Normal file
|
@ -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
examples/discover/os.go
Normal file
22
examples/discover/os.go
Normal file
|
@ -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.")
|
||||
}
|
|
@ -33,12 +33,12 @@ func (d *Device) DiscoverServices(uuids []UUID) ([]DeviceService, error) {
|
|||
for _, dsvc := range d.prph.Services() {
|
||||
uuid, _ := ParseUUID(dsvc.UUID().String())
|
||||
svc := DeviceService{
|
||||
UUID: uuid,
|
||||
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:
|
||||
|
@ -46,15 +46,24 @@ func (d *Device) DiscoverServices(uuids []UUID) ([]DeviceService, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
|
@ -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:
|
||||
|
@ -99,7 +108,7 @@ func (s *DeviceService) DiscoverCharacteristics(uuids []UUID) ([]DeviceCharacter
|
|||
// DeviceCharacteristic is a BLE characteristic on a connected peripheral
|
||||
// device.
|
||||
type DeviceCharacteristic struct {
|
||||
UUID
|
||||
uuidWrapper
|
||||
|
||||
service *DeviceService
|
||||
|
||||
|
@ -107,6 +116,11 @@ type DeviceCharacteristic struct {
|
|||
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
|
||||
|
|
|
@ -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
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
140
gattc_sd.go
140
gattc_sd.go
|
@ -17,6 +17,11 @@ import (
|
|||
"runtime/volatile"
|
||||
)
|
||||
|
||||
const (
|
||||
maxDefaultServicesToDiscover = 6
|
||||
maxDefaultCharacteristicsToDiscover = 8
|
||||
)
|
||||
|
||||
var (
|
||||
errAlreadyDiscovering = errors.New("bluetooth: already discovering a service or characteristic")
|
||||
errNotFound = errors.New("bluetooth: not found")
|
||||
|
@ -29,23 +34,30 @@ var discoveringService struct {
|
|||
state volatile.Register8 // 0 means nothing happening, 1 means in progress, 2 means found something
|
||||
startHandle volatile.Register16
|
||||
endHandle volatile.Register16
|
||||
uuid C.ble_uuid_t
|
||||
}
|
||||
|
||||
// DeviceService is a BLE service on a connected peripheral device. It is only
|
||||
// valid as long as the device remains connected.
|
||||
type DeviceService struct {
|
||||
uuid shortUUID
|
||||
|
||||
connectionHandle uint16
|
||||
startHandle uint16
|
||||
endHandle uint16
|
||||
}
|
||||
|
||||
// UUID returns the UUID for this DeviceService.
|
||||
func (s *DeviceService) UUID() UUID {
|
||||
return s.uuid.UUID()
|
||||
}
|
||||
|
||||
// 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
|
||||
// order), or if some services could not be discovered an error is returned.
|
||||
//
|
||||
// Passing a nil slice of UUIDs will currently result in zero services being
|
||||
// returned, but this may be changed in the future to return a complete list of
|
||||
// Passing a nil slice of UUIDs will return a complete list of
|
||||
// services.
|
||||
//
|
||||
// On the Nordic SoftDevice, only one service discovery procedure may be done at
|
||||
|
@ -56,15 +68,46 @@ func (d *Device) DiscoverServices(uuids []UUID) ([]DeviceService, error) {
|
|||
return nil, errAlreadyDiscovering
|
||||
}
|
||||
|
||||
services := make([]DeviceService, len(uuids))
|
||||
sz := maxDefaultServicesToDiscover
|
||||
if len(uuids) > 0 {
|
||||
sz = len(uuids)
|
||||
}
|
||||
services := make([]DeviceService, 0, sz)
|
||||
|
||||
var shortUUIDs []C.ble_uuid_t
|
||||
|
||||
// Make a map of UUIDs in SoftDevice short form, for easier comparing.
|
||||
if len(uuids) > 0 {
|
||||
shortUUIDs = make([]C.ble_uuid_t, sz)
|
||||
for i, uuid := range uuids {
|
||||
// Start discovery of this service.
|
||||
shortUUID, errCode := uuid.shortUUID()
|
||||
var errCode uint32
|
||||
shortUUIDs[i], errCode = uuid.shortUUID()
|
||||
if errCode != 0 {
|
||||
return nil, Error(errCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
numFound := 0
|
||||
|
||||
var startHandle uint16 = 1
|
||||
|
||||
for i := 0; i < sz; i++ {
|
||||
var suuid C.ble_uuid_t
|
||||
if len(uuids) > 0 {
|
||||
suuid = shortUUIDs[i]
|
||||
}
|
||||
|
||||
// Start discovery of this service.
|
||||
discoveringService.state.Set(1)
|
||||
errCode = C.sd_ble_gattc_primary_services_discover(d.connectionHandle, 0, &shortUUID)
|
||||
var errCode uint32
|
||||
if len(uuids) > 0 {
|
||||
errCode = C.sd_ble_gattc_primary_services_discover(d.connectionHandle, startHandle, &suuid)
|
||||
} else {
|
||||
// calling with nil searches for all primary services.
|
||||
// TODO: need a way to set suuid from the returned data
|
||||
errCode = C.sd_ble_gattc_primary_services_discover(d.connectionHandle, startHandle, nil)
|
||||
}
|
||||
if errCode != 0 {
|
||||
discoveringService.state.Set(0)
|
||||
return nil, Error(errCode)
|
||||
|
@ -78,8 +121,9 @@ func (d *Device) DiscoverServices(uuids []UUID) ([]DeviceService, error) {
|
|||
arm.Asm("wfe")
|
||||
}
|
||||
// Retrieve values, and mark the global as unused.
|
||||
startHandle := discoveringService.startHandle.Get()
|
||||
startHandle = discoveringService.startHandle.Get()
|
||||
endHandle := discoveringService.endHandle.Get()
|
||||
suuid = discoveringService.uuid
|
||||
discoveringService.state.Set(0)
|
||||
|
||||
if startHandle == 0 {
|
||||
|
@ -89,11 +133,26 @@ func (d *Device) DiscoverServices(uuids []UUID) ([]DeviceService, error) {
|
|||
}
|
||||
|
||||
// Store the discovered service.
|
||||
services[i] = DeviceService{
|
||||
svc := DeviceService{
|
||||
uuid: suuid,
|
||||
connectionHandle: d.connectionHandle,
|
||||
startHandle: startHandle,
|
||||
endHandle: endHandle,
|
||||
}
|
||||
services = append(services, svc)
|
||||
|
||||
numFound++
|
||||
if numFound >= sz {
|
||||
break
|
||||
}
|
||||
|
||||
// last entry
|
||||
if endHandle == 0xffff {
|
||||
break
|
||||
}
|
||||
|
||||
// start with the next handle
|
||||
startHandle = endHandle + 1
|
||||
}
|
||||
|
||||
return services, nil
|
||||
|
@ -102,12 +161,19 @@ func (d *Device) DiscoverServices(uuids []UUID) ([]DeviceService, error) {
|
|||
// DeviceCharacteristic is a BLE characteristic on a connected peripheral
|
||||
// device. It is only valid as long as the device remains connected.
|
||||
type DeviceCharacteristic struct {
|
||||
uuid shortUUID
|
||||
|
||||
connectionHandle uint16
|
||||
valueHandle uint16
|
||||
cccdHandle uint16
|
||||
permissions CharacteristicPermissions
|
||||
}
|
||||
|
||||
// UUID returns the UUID for this DeviceCharacteristic.
|
||||
func (c *DeviceCharacteristic) UUID() UUID {
|
||||
return c.uuid.UUID()
|
||||
}
|
||||
|
||||
// A global used to pass information from the event handler back to the
|
||||
// DiscoverCharacteristics function below.
|
||||
var discoveringCharacteristic struct {
|
||||
|
@ -123,22 +189,24 @@ var discoveringCharacteristic struct {
|
|||
// slice has the same length as the UUID slice with characteristics in the same
|
||||
// order in the slice as in the requested UUID list.
|
||||
//
|
||||
// Passing a nil slice of UUIDs will currently result in zero characteristics
|
||||
// being returned, but this may be changed in the future to return a complete
|
||||
// Passing a nil slice of UUIDs will return a complete
|
||||
// list of characteristics.
|
||||
func (s *DeviceService) DiscoverCharacteristics(uuids []UUID) ([]DeviceCharacteristic, error) {
|
||||
if len(uuids) == 0 {
|
||||
// Nothing to do. This behavior might change in the future (if a nil
|
||||
// uuids slice is passed).
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if discoveringCharacteristic.handle_value.Get() != 0 {
|
||||
return nil, errAlreadyDiscovering
|
||||
}
|
||||
|
||||
// Make a list of UUIDs in SoftDevice short form, for easier comparing.
|
||||
shortUUIDs := make([]C.ble_uuid_t, len(uuids))
|
||||
sz := maxDefaultCharacteristicsToDiscover
|
||||
if len(uuids) > 0 {
|
||||
sz = len(uuids)
|
||||
}
|
||||
characteristics := make([]DeviceCharacteristic, 0, sz)
|
||||
|
||||
var shortUUIDs []C.ble_uuid_t
|
||||
|
||||
// Make a map of UUIDs in SoftDevice short form, for easier comparing.
|
||||
if len(uuids) > 0 {
|
||||
shortUUIDs = make([]C.ble_uuid_t, sz)
|
||||
for i, uuid := range uuids {
|
||||
var errCode uint32
|
||||
shortUUIDs[i], errCode = uuid.shortUUID()
|
||||
|
@ -146,17 +214,19 @@ func (s *DeviceService) DiscoverCharacteristics(uuids []UUID) ([]DeviceCharacter
|
|||
return nil, Error(errCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Request characteristics one by one, until all are found.
|
||||
numFound := 0
|
||||
characteristics := make([]DeviceCharacteristic, len(uuids))
|
||||
startHandle := s.startHandle
|
||||
for numFound < len(uuids) && startHandle < s.endHandle {
|
||||
|
||||
for startHandle < s.endHandle {
|
||||
// Discover the next characteristic in this service.
|
||||
handles := C.ble_gattc_handle_range_t{
|
||||
start_handle: startHandle,
|
||||
end_handle: s.endHandle,
|
||||
end_handle: startHandle + 1,
|
||||
}
|
||||
|
||||
errCode := C.sd_ble_gattc_characteristics_discover(s.connectionHandle, &handles)
|
||||
if errCode != 0 {
|
||||
return nil, Error(errCode)
|
||||
|
@ -171,12 +241,19 @@ func (s *DeviceService) DiscoverCharacteristics(uuids []UUID) ([]DeviceCharacter
|
|||
foundCharacteristicHandle := discoveringCharacteristic.handle_value.Get()
|
||||
discoveringCharacteristic.handle_value.Set(0)
|
||||
|
||||
// was it last characteristic?
|
||||
if foundCharacteristicHandle == 0xffff {
|
||||
break
|
||||
}
|
||||
|
||||
// Start the next request from the handle right after this one.
|
||||
startHandle = foundCharacteristicHandle + 1
|
||||
|
||||
// Look whether we found a requested handle.
|
||||
for i, shortUUID := range shortUUIDs {
|
||||
if discoveringCharacteristic.uuid == shortUUID {
|
||||
// not one of the characteristics we are looking for
|
||||
if len(shortUUIDs) > 0 && !shortUUID(discoveringCharacteristic.uuid).IsIn(shortUUIDs) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Found a characteristic.
|
||||
permissions := CharacteristicPermissions(0)
|
||||
rawPermissions := discoveringCharacteristic.char_props
|
||||
|
@ -198,15 +275,17 @@ func (s *DeviceService) DiscoverCharacteristics(uuids []UUID) ([]DeviceCharacter
|
|||
if rawPermissions.bitfield_indicate() != 0 {
|
||||
permissions |= CharacteristicIndicatePermission
|
||||
}
|
||||
characteristics[i].permissions = permissions
|
||||
characteristics[i].valueHandle = foundCharacteristicHandle
|
||||
|
||||
dc := DeviceCharacteristic{uuid: discoveringCharacteristic.uuid}
|
||||
dc.permissions = permissions
|
||||
dc.valueHandle = foundCharacteristicHandle
|
||||
|
||||
if permissions&CharacteristicNotifyPermission != 0 {
|
||||
// This characteristic has the notify permission, so most
|
||||
// likely it also supports notifications.
|
||||
errCode := C.sd_ble_gattc_descriptors_discover(s.connectionHandle, &C.ble_gattc_handle_range_t{
|
||||
start_handle: startHandle,
|
||||
end_handle: s.endHandle,
|
||||
end_handle: startHandle + 1,
|
||||
})
|
||||
if errCode != 0 {
|
||||
return nil, Error(errCode)
|
||||
|
@ -219,16 +298,17 @@ func (s *DeviceService) DiscoverCharacteristics(uuids []UUID) ([]DeviceCharacter
|
|||
foundDescriptorHandle := discoveringCharacteristic.handle_value.Get()
|
||||
discoveringCharacteristic.handle_value.Set(0)
|
||||
|
||||
characteristics[i].cccdHandle = foundDescriptorHandle
|
||||
dc.cccdHandle = foundDescriptorHandle
|
||||
}
|
||||
|
||||
characteristics = append(characteristics, dc)
|
||||
numFound++
|
||||
if numFound >= sz {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if numFound != len(uuids) {
|
||||
if len(uuids) > 0 && numFound != len(uuids) {
|
||||
return nil, errNotFound
|
||||
}
|
||||
|
||||
|
|
23
uuid_sd.go
23
uuid_sd.go
|
@ -12,6 +12,8 @@ package bluetooth
|
|||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
type shortUUID C.ble_uuid_t
|
||||
|
||||
func (uuid UUID) shortUUID() (C.ble_uuid_t, uint32) {
|
||||
var short C.ble_uuid_t
|
||||
short.uuid = uint16(uuid[3])
|
||||
|
@ -22,3 +24,24 @@ func (uuid UUID) shortUUID() (C.ble_uuid_t, uint32) {
|
|||
errCode := C.sd_ble_uuid_vs_add((*C.ble_uuid128_t)(unsafe.Pointer(&uuid[0])), &short._type)
|
||||
return short, errCode
|
||||
}
|
||||
|
||||
// UUID returns the full length UUID for this short UUID.
|
||||
func (s shortUUID) UUID() UUID {
|
||||
if s._type == C.BLE_UUID_TYPE_BLE {
|
||||
return New16BitUUID(s.uuid)
|
||||
}
|
||||
var outLen C.uint8_t
|
||||
var outUUID UUID
|
||||
C.sd_ble_uuid_encode(((*C.ble_uuid_t)(unsafe.Pointer(&s))), &outLen, ((*C.uint8_t)(unsafe.Pointer(&outUUID))))
|
||||
return outUUID
|
||||
}
|
||||
|
||||
// IsIn checks the passed in slice of short UUIDs to see if this uuid is in it.
|
||||
func (s shortUUID) IsIn(uuids []C.ble_uuid_t) bool {
|
||||
for _, u := range uuids {
|
||||
if u == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue