all: use Addresser interface to handle fact that macOS uses UUID instead of MAC as the BLE address for a peripheral

Signed-off-by: Ron Evans <ron@hybridgroup.com>
This commit is contained in:
Ron Evans 2020-08-28 12:40:03 +02:00
parent a620bacdb8
commit c1114ad708
8 changed files with 144 additions and 19 deletions

View file

@ -36,6 +36,7 @@ func (a *Adapter) Enable() error {
// CentralManager delegate functions
// CentralManagerDidUpdateState when central manager state updated.
func (a *Adapter) CentralManagerDidUpdateState(cmgr cbgo.CentralManager) {
}
@ -88,15 +89,16 @@ func (a *Adapter) CentralDidUnsubscribe(pmgr cbgo.PeripheralManager, cent cbgo.C
// makeScanResult creates a ScanResult when peripheral is found.
func makeScanResult(prph cbgo.Peripheral, advFields cbgo.AdvFields, rssi int) ScanResult {
// TODO: figure out the peripheral info.
var u [16]byte
copy(u[:], prph.Identifier())
uuid := NewUUID(u)
// TODO: create a list of serviceUUIDs.
return ScanResult{
RSSI: int16(rssi),
RSSI: int16(rssi),
Address: Address{
// TODO: fill in this info
//MAC: prph.Identifier(),
UUID: uuid,
//IsRandom: prph.Identifier == "random",
},
AdvertisementPayload: &advertisementFields{

View file

@ -102,8 +102,8 @@ func handleEvent() {
// callback.
scanReportBuffer.len = byte(advReport.data.len)
globalScanResult.RSSI = int16(advReport.rssi)
globalScanResult.Address.MAC = advReport.peer_addr.addr
globalScanResult.Address.IsRandom = advReport.peer_addr.bitfield_addr_type() != 0
globalScanResult.Address.Set(advReport.peer_addr.addr)
globalScanResult.Address.SetRandom(advReport.peer_addr.bitfield_addr_type() != 0)
globalScanResult.AdvertisementPayload = &scanReportBuffer
// Signal to the main thread that there was a scan report.
// Scanning will be resumed (from the main thread) once the scan

17
gap.go
View file

@ -41,11 +41,14 @@ func NewDuration(interval time.Duration) Duration {
// Connection is a numeric identifier that indicates a connection handle.
type Connection uint16
// Address contains a Bluetooth address, which is a MAC address plus some extra
// Addresser contains a Bluetooth address, which is a MAC address plus some extra
// information.
type Address struct {
// The MAC address of a Bluetooth device.
MAC
type Addresser interface {
// String of the address
String() string
// Set the address
Set(val interface{})
// Is this address a random address?
// Bluetooth addresses are roughly split in two kinds: public
@ -54,14 +57,16 @@ type Address struct {
// random. Sometimes, it contains a hash.
// For more information:
// https://www.novelbits.io/bluetooth-address-privacy-ble/
IsRandom bool
// Set the address
SetRandom(bool)
IsRandom() bool
}
// ScanResult contains information from when an advertisement packet was
// received. It is passed as a parameter to the callback of the Scan method.
type ScanResult struct {
// Bluetooth address of the scanned device.
Address Address
Address Addresser
// RSSI the last time a packet from this device has been received.
RSSI int16

View file

@ -6,6 +6,30 @@ import (
"github.com/JuulLabs-OSS/cbgo"
)
// Address contains a Bluetooth address, which is a MAC address plus some extra
// information.
type Address struct {
// UUID if this is macOS.
UUID
isRandom bool
}
// IsRandom if the address is randomly created.
func (ad Address) IsRandom() bool {
return ad.isRandom
}
// SetRandom if is a random address.
func (ad Address) SetRandom(val bool) {
ad.isRandom = val
}
// Set the address
func (ad Address) Set(val interface{}) {
ad.UUID = val.(UUID)
}
// Scan starts a BLE scan. It is stopped by a call to StopScan. A common pattern
// is to cancel the scan when a particular device has been found.
func (a *Adapter) Scan(callback func(*Adapter, ScanResult)) (err error) {

View file

@ -11,6 +11,29 @@ import (
"github.com/muka/go-bluetooth/bluez/profile/device"
)
// Address contains a Bluetooth address, which is a MAC address plus some extra
// information.
type Address struct {
// The MAC address of a Bluetooth device.
MAC
isRandom bool
}
// IsRandom if the address is randomly created.
func (ad Address) IsRandom() bool {
return ad.isRandom
}
// SetRandom if is a random address.
func (ad Address) SetRandom(val bool) {
ad.isRandom = val
}
// Set the address
func (ad Address) Set(val interface{}) {
ad.MAC = val.(MAC)
}
// Advertisement encapsulates a single advertisement instance.
type Advertisement struct {
adapter *Adapter
@ -218,7 +241,7 @@ func makeScanResult(props *device.Device1Properties) ScanResult {
RSSI: props.RSSI,
Address: Address{
MAC: addr,
IsRandom: props.AddressType == "random",
isRandom: props.AddressType == "random",
},
AdvertisementPayload: &advertisementFields{
AdvertisementFields{
@ -237,8 +260,9 @@ type Device struct {
// Connect starts a connection attempt to the given peripheral device address.
//
// On Linux and Windows, the IsRandom part of the address is ignored.
func (a *Adapter) Connect(address Address, params ConnectionParams) (*Device, error) {
devicePath := dbus.ObjectPath(string(a.adapter.Path()) + "/dev_" + strings.Replace(address.MAC.String(), ":", "_", -1))
func (a *Adapter) Connect(address Addresser, params ConnectionParams) (*Device, error) {
adr := address.(Address)
devicePath := dbus.ObjectPath(string(a.adapter.Path()) + "/dev_" + strings.Replace(adr.MAC.String(), ":", "_", -1))
dev, err := device.NewDevice1(devicePath)
if err != nil {
return nil, err

View file

@ -16,6 +16,29 @@ import (
"time"
)
// Address contains a Bluetooth address, which is a MAC address plus some extra
// information.
type Address struct {
// The MAC address of a Bluetooth device.
MAC
isRandom bool
}
// IsRandom if the address is randomly created.
func (ad Address) IsRandom() bool {
return ad.isRandom
}
// SetRandom if is a random address.
func (ad Address) SetRandom(val bool) {
ad.isRandom = val
}
// Set the address
func (ad Address) Set(val interface{}) {
ad.MAC = val.(MAC)
}
// Advertisement encapsulates a single advertisement instance.
type Advertisement struct {
interval Duration

View file

@ -27,6 +27,29 @@ var (
globalScanResult ScanResult
)
// Address contains a Bluetooth address, which is a MAC address plus some extra
// information.
type Address struct {
// The MAC address of a Bluetooth device.
MAC
isRandom bool
}
// IsRandom if the address is randomly created.
func (ad Address) IsRandom() bool {
return ad.isRandom
}
// SetRandom if is a random address.
func (ad Address) SetRandom(val bool) {
ad.isRandom = val
}
// Set the address
func (ad Address) Set(val interface{}) {
ad.MAC = val.(MAC)
}
// Advertisement encapsulates a single advertisement instance.
type Advertisement struct {
handle uint8
@ -169,12 +192,13 @@ var connectionAttempt struct {
// connection attempt at once and that the address parameter must have the
// IsRandom bit set correctly. This bit is set correctly for scan results, so
// you can reuse that address directly.
func (a *Adapter) Connect(address Address, params ConnectionParams) (*Device, error) {
func (a *Adapter) Connect(address Addresser, params ConnectionParams) (*Device, error) {
adr := address.(Address)
// Construct an address object as used in the SoftDevice.
var addr C.ble_gap_addr_t
addr.addr = address.MAC
if address.IsRandom {
switch address.MAC[5] >> 6 {
addr.addr = adr.MAC
if address.IsRandom() {
switch adr.MAC[5] >> 6 {
case 0b11:
addr.set_bitfield_addr_type(C.BLE_GAP_ADDR_TYPE_RANDOM_STATIC)
case 0b01:

View file

@ -4,6 +4,29 @@ import (
"github.com/tinygo-org/bluetooth/winbt"
)
// Address contains a Bluetooth address, which is a MAC address plus some extra
// information.
type Address struct {
// The MAC address of a Bluetooth device.
MAC
isRandom bool
}
// IsRandom if the address is randomly created.
func (ad Address) IsRandom() bool {
return ad.isRandom
}
// SetRandom if is a random address.
func (ad Address) SetRandom(val bool) {
ad.isRandom = val
}
// Set the address
func (ad Address) Set(val interface{}) {
ad.MAC = val.(MAC)
}
// Scan starts a BLE scan. It is stopped by a call to StopScan. A common pattern
// is to cancel the scan when a particular device has been found.
func (a *Adapter) Scan(callback func(*Adapter, ScanResult)) (err error) {