all: make Device a value instead of a pointer
This is a refactor that is necessary to make it easier to work with connected central devices on a SoftDevice.
This commit is contained in:
parent
6e0df0ec3c
commit
c9eafaff20
12 changed files with 75 additions and 62 deletions
|
@ -21,7 +21,7 @@ type Adapter struct {
|
||||||
|
|
||||||
connectHandler func(device Address, connected bool)
|
connectHandler func(device Address, connected bool)
|
||||||
|
|
||||||
connectedDevices []*Device
|
connectedDevices []Device
|
||||||
notificationsStarted bool
|
notificationsStarted bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ var DefaultAdapter = &Adapter{
|
||||||
connectHandler: func(device Address, connected bool) {
|
connectHandler: func(device Address, connected bool) {
|
||||||
return
|
return
|
||||||
},
|
},
|
||||||
connectedDevices: make([]*Device, 0, maxConnections),
|
connectedDevices: make([]Device, 0, maxConnections),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable configures the BLE stack. It must be called before any
|
// Enable configures the BLE stack. It must be called before any
|
||||||
|
@ -185,7 +185,7 @@ func (a *Adapter) startNotifications() {
|
||||||
}
|
}
|
||||||
|
|
||||||
d := a.findDevice(not.connectionHandle)
|
d := a.findDevice(not.connectionHandle)
|
||||||
if d == nil {
|
if d.deviceInternal == nil {
|
||||||
if _debug {
|
if _debug {
|
||||||
println("no device found for handle", not.connectionHandle)
|
println("no device found for handle", not.connectionHandle)
|
||||||
}
|
}
|
||||||
|
@ -212,7 +212,7 @@ func (a *Adapter) startNotifications() {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Adapter) findDevice(handle uint16) *Device {
|
func (a *Adapter) findDevice(handle uint16) Device {
|
||||||
for _, d := range a.connectedDevices {
|
for _, d := range a.connectedDevices {
|
||||||
if d.handle == handle {
|
if d.handle == handle {
|
||||||
if _debug {
|
if _debug {
|
||||||
|
@ -223,5 +223,5 @@ func (a *Adapter) findDevice(handle uint16) *Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return Device{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ func main() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
var device *bluetooth.Device
|
var device bluetooth.Device
|
||||||
select {
|
select {
|
||||||
case result := <-ch:
|
case result := <-ch:
|
||||||
device, err = adapter.Connect(result.Address, bluetooth.ConnectionParams{})
|
device, err = adapter.Connect(result.Address, bluetooth.ConnectionParams{})
|
||||||
|
|
|
@ -52,7 +52,7 @@ func main() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
var device *bluetooth.Device
|
var device bluetooth.Device
|
||||||
select {
|
select {
|
||||||
case result := <-ch:
|
case result := <-ch:
|
||||||
device, err = adapter.Connect(result.Address, bluetooth.ConnectionParams{})
|
device, err = adapter.Connect(result.Address, bluetooth.ConnectionParams{})
|
||||||
|
|
|
@ -85,6 +85,10 @@ func (a *Adapter) StopScan() error {
|
||||||
|
|
||||||
// Device is a connection to a remote peripheral.
|
// Device is a connection to a remote peripheral.
|
||||||
type Device struct {
|
type Device struct {
|
||||||
|
*deviceInternal
|
||||||
|
}
|
||||||
|
|
||||||
|
type deviceInternal struct {
|
||||||
delegate *peripheralDelegate
|
delegate *peripheralDelegate
|
||||||
|
|
||||||
cm cbgo.CentralManager
|
cm cbgo.CentralManager
|
||||||
|
@ -97,14 +101,14 @@ type Device struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect starts a connection attempt to the given peripheral device address.
|
// Connect starts a connection attempt to the given peripheral device address.
|
||||||
func (a *Adapter) Connect(address Address, params ConnectionParams) (*Device, error) {
|
func (a *Adapter) Connect(address Address, params ConnectionParams) (Device, error) {
|
||||||
uuid, err := cbgo.ParseUUID(address.UUID.String())
|
uuid, err := cbgo.ParseUUID(address.UUID.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return Device{}, err
|
||||||
}
|
}
|
||||||
prphs := a.cm.RetrievePeripheralsWithIdentifiers([]cbgo.UUID{uuid})
|
prphs := a.cm.RetrievePeripheralsWithIdentifiers([]cbgo.UUID{uuid})
|
||||||
if len(prphs) == 0 {
|
if len(prphs) == 0 {
|
||||||
return nil, fmt.Errorf("Connect failed: no peer with address: %s", address.UUID.String())
|
return Device{}, fmt.Errorf("Connect failed: no peer with address: %s", address.UUID.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout := defaultConnectionTimeout
|
timeout := defaultConnectionTimeout
|
||||||
|
@ -129,14 +133,16 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (*Device, er
|
||||||
|
|
||||||
// check if we have received a disconnected peripheral
|
// check if we have received a disconnected peripheral
|
||||||
if p.State() == cbgo.PeripheralStateDisconnected {
|
if p.State() == cbgo.PeripheralStateDisconnected {
|
||||||
return nil, connectionError
|
return Device{}, connectionError
|
||||||
}
|
}
|
||||||
|
|
||||||
d := &Device{
|
d := Device{
|
||||||
cm: a.cm,
|
&deviceInternal{
|
||||||
prph: p,
|
cm: a.cm,
|
||||||
servicesChan: make(chan error),
|
prph: p,
|
||||||
charsChan: make(chan error),
|
servicesChan: make(chan error),
|
||||||
|
charsChan: make(chan error),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
d.delegate = &peripheralDelegate{d: d}
|
d.delegate = &peripheralDelegate{d: d}
|
||||||
|
@ -162,7 +168,7 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (*Device, er
|
||||||
|
|
||||||
// Disconnect from the BLE device. This method is non-blocking and does not
|
// Disconnect from the BLE device. This method is non-blocking and does not
|
||||||
// wait until the connection is fully gone.
|
// wait until the connection is fully gone.
|
||||||
func (d *Device) Disconnect() error {
|
func (d Device) Disconnect() error {
|
||||||
d.cm.CancelConnect(d.prph)
|
d.cm.CancelConnect(d.prph)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -172,7 +178,7 @@ func (d *Device) Disconnect() error {
|
||||||
type peripheralDelegate struct {
|
type peripheralDelegate struct {
|
||||||
cbgo.PeripheralDelegateBase
|
cbgo.PeripheralDelegateBase
|
||||||
|
|
||||||
d *Device
|
d Device
|
||||||
}
|
}
|
||||||
|
|
||||||
// DidDiscoverServices is called when the services for a Peripheral
|
// DidDiscoverServices is called when the services for a Peripheral
|
||||||
|
|
10
gap_linux.go
10
gap_linux.go
|
@ -300,9 +300,9 @@ type Device struct {
|
||||||
// Connect starts a connection attempt to the given peripheral device address.
|
// Connect starts a connection attempt to the given peripheral device address.
|
||||||
//
|
//
|
||||||
// On Linux and Windows, the IsRandom part of the address is ignored.
|
// On Linux and Windows, the IsRandom part of the address is ignored.
|
||||||
func (a *Adapter) Connect(address Address, params ConnectionParams) (*Device, error) {
|
func (a *Adapter) Connect(address Address, params ConnectionParams) (Device, error) {
|
||||||
devicePath := dbus.ObjectPath(string(a.adapter.Path()) + "/dev_" + strings.Replace(address.MAC.String(), ":", "_", -1))
|
devicePath := dbus.ObjectPath(string(a.adapter.Path()) + "/dev_" + strings.Replace(address.MAC.String(), ":", "_", -1))
|
||||||
device := &Device{
|
device := Device{
|
||||||
device: a.bus.Object("org.bluez", devicePath),
|
device: a.bus.Object("org.bluez", devicePath),
|
||||||
adapter: a,
|
adapter: a,
|
||||||
address: address,
|
address: address,
|
||||||
|
@ -321,7 +321,7 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (*Device, er
|
||||||
// Read whether this device is already connected.
|
// Read whether this device is already connected.
|
||||||
connected, err := device.device.GetProperty("org.bluez.Device1.Connected")
|
connected, err := device.device.GetProperty("org.bluez.Device1.Connected")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return Device{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect to the device, if not already connected.
|
// Connect to the device, if not already connected.
|
||||||
|
@ -329,7 +329,7 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (*Device, er
|
||||||
// Start connecting (async).
|
// Start connecting (async).
|
||||||
err := device.device.Call("org.bluez.Device1.Connect", 0).Err
|
err := device.device.Call("org.bluez.Device1.Connect", 0).Err
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("bluetooth: failed to connect: %w", err)
|
return Device{}, fmt.Errorf("bluetooth: failed to connect: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait until the device has connected.
|
// Wait until the device has connected.
|
||||||
|
@ -360,7 +360,7 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (*Device, er
|
||||||
|
|
||||||
// Disconnect from the BLE device. This method is non-blocking and does not
|
// Disconnect from the BLE device. This method is non-blocking and does not
|
||||||
// wait until the connection is fully gone.
|
// wait until the connection is fully gone.
|
||||||
func (d *Device) Disconnect() error {
|
func (d Device) Disconnect() error {
|
||||||
// we don't call our cancel function here, instead we wait for the
|
// we don't call our cancel function here, instead we wait for the
|
||||||
// property change in `watchForConnect` and cancel things then
|
// property change in `watchForConnect` and cancel things then
|
||||||
return d.device.Call("org.bluez.Device1.Disconnect", 0).Err
|
return d.device.Call("org.bluez.Device1.Disconnect", 0).Err
|
||||||
|
|
|
@ -133,7 +133,7 @@ type Address struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect starts a connection attempt to the given peripheral device address.
|
// Connect starts a connection attempt to the given peripheral device address.
|
||||||
func (a *Adapter) Connect(address Address, params ConnectionParams) (*Device, error) {
|
func (a *Adapter) Connect(address Address, params ConnectionParams) (Device, error) {
|
||||||
if _debug {
|
if _debug {
|
||||||
println("Connect")
|
println("Connect")
|
||||||
}
|
}
|
||||||
|
@ -145,14 +145,14 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (*Device, er
|
||||||
if err := a.hci.leCreateConn(0x0060, 0x0030, 0x00,
|
if err := a.hci.leCreateConn(0x0060, 0x0030, 0x00,
|
||||||
random, makeNINAAddress(address.MAC),
|
random, makeNINAAddress(address.MAC),
|
||||||
0x00, 0x0006, 0x000c, 0x0000, 0x00c8, 0x0004, 0x0006); err != nil {
|
0x00, 0x0006, 0x000c, 0x0000, 0x00c8, 0x0004, 0x0006); err != nil {
|
||||||
return nil, err
|
return Device{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// are we connected?
|
// are we connected?
|
||||||
start := time.Now().UnixNano()
|
start := time.Now().UnixNano()
|
||||||
for {
|
for {
|
||||||
if err := a.hci.poll(); err != nil {
|
if err := a.hci.poll(); err != nil {
|
||||||
return nil, err
|
return Device{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.hci.connectData.connected {
|
if a.hci.connectData.connected {
|
||||||
|
@ -163,15 +163,18 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (*Device, er
|
||||||
random = true
|
random = true
|
||||||
}
|
}
|
||||||
|
|
||||||
d := &Device{adapter: a,
|
d := Device{
|
||||||
handle: a.hci.connectData.handle,
|
|
||||||
Address: Address{
|
Address: Address{
|
||||||
MACAddress{
|
MACAddress{
|
||||||
MAC: makeAddress(a.hci.connectData.peerBdaddr),
|
MAC: makeAddress(a.hci.connectData.peerBdaddr),
|
||||||
isRandom: random},
|
isRandom: random},
|
||||||
},
|
},
|
||||||
mtu: defaultMTU,
|
deviceInternal: &deviceInternal{
|
||||||
notificationRegistrations: make([]notificationRegistration, 0),
|
adapter: a,
|
||||||
|
handle: a.hci.connectData.handle,
|
||||||
|
mtu: defaultMTU,
|
||||||
|
notificationRegistrations: make([]notificationRegistration, 0),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
a.connectedDevices = append(a.connectedDevices, d)
|
a.connectedDevices = append(a.connectedDevices, d)
|
||||||
|
|
||||||
|
@ -189,10 +192,10 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (*Device, er
|
||||||
|
|
||||||
// cancel connection attempt that failed
|
// cancel connection attempt that failed
|
||||||
if err := a.hci.leCancelConn(); err != nil {
|
if err := a.hci.leCancelConn(); err != nil {
|
||||||
return nil, err
|
return Device{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, ErrConnect
|
return Device{}, ErrConnect
|
||||||
}
|
}
|
||||||
|
|
||||||
type notificationRegistration struct {
|
type notificationRegistration struct {
|
||||||
|
@ -202,8 +205,12 @@ type notificationRegistration struct {
|
||||||
|
|
||||||
// Device is a connection to a remote peripheral.
|
// Device is a connection to a remote peripheral.
|
||||||
type Device struct {
|
type Device struct {
|
||||||
adapter *Adapter
|
|
||||||
Address Address
|
Address Address
|
||||||
|
*deviceInternal
|
||||||
|
}
|
||||||
|
|
||||||
|
type deviceInternal struct {
|
||||||
|
adapter *Adapter
|
||||||
handle uint16
|
handle uint16
|
||||||
mtu uint16
|
mtu uint16
|
||||||
|
|
||||||
|
@ -211,7 +218,7 @@ type Device struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disconnect from the BLE device.
|
// Disconnect from the BLE device.
|
||||||
func (d *Device) Disconnect() error {
|
func (d Device) Disconnect() error {
|
||||||
if _debug {
|
if _debug {
|
||||||
println("Disconnect")
|
println("Disconnect")
|
||||||
}
|
}
|
||||||
|
@ -219,11 +226,11 @@ func (d *Device) Disconnect() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
d.adapter.connectedDevices = []*Device{}
|
d.adapter.connectedDevices = []Device{}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Device) findNotificationRegistration(handle uint16) *notificationRegistration {
|
func (d Device) findNotificationRegistration(handle uint16) *notificationRegistration {
|
||||||
for _, n := range d.notificationRegistrations {
|
for _, n := range d.notificationRegistrations {
|
||||||
if n.handle == handle {
|
if n.handle == handle {
|
||||||
return &n
|
return &n
|
||||||
|
@ -233,7 +240,7 @@ func (d *Device) findNotificationRegistration(handle uint16) *notificationRegist
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Device) addNotificationRegistration(handle uint16, callback func([]byte)) {
|
func (d Device) addNotificationRegistration(handle uint16, callback func([]byte)) {
|
||||||
d.notificationRegistrations = append(d.notificationRegistrations,
|
d.notificationRegistrations = append(d.notificationRegistrations,
|
||||||
notificationRegistration{
|
notificationRegistration{
|
||||||
handle: handle,
|
handle: handle,
|
||||||
|
@ -241,6 +248,6 @@ func (d *Device) addNotificationRegistration(handle uint16, callback func([]byte
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Device) startNotifications() {
|
func (d Device) startNotifications() {
|
||||||
d.adapter.startNotifications()
|
d.adapter.startNotifications()
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@ var connectionAttempt struct {
|
||||||
// connection attempt at once and that the address parameter must have the
|
// 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
|
// IsRandom bit set correctly. This bit is set correctly for scan results, so
|
||||||
// you can reuse that address directly.
|
// you can reuse that address directly.
|
||||||
func (a *Adapter) Connect(address Address, params ConnectionParams) (*Device, error) {
|
func (a *Adapter) Connect(address Address, params ConnectionParams) (Device, error) {
|
||||||
// Construct an address object as used in the SoftDevice.
|
// Construct an address object as used in the SoftDevice.
|
||||||
var addr C.ble_gap_addr_t
|
var addr C.ble_gap_addr_t
|
||||||
addr.addr = makeSDAddress(address.MAC)
|
addr.addr = makeSDAddress(address.MAC)
|
||||||
|
@ -158,7 +158,7 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (*Device, er
|
||||||
// This should be safe as long as Connect is not called concurrently. And
|
// This should be safe as long as Connect is not called concurrently. And
|
||||||
// even then, it should catch most such race conditions.
|
// even then, it should catch most such race conditions.
|
||||||
if connectionAttempt.state.Get() != 0 {
|
if connectionAttempt.state.Get() != 0 {
|
||||||
return nil, errAlreadyConnecting
|
return Device{}, errAlreadyConnecting
|
||||||
}
|
}
|
||||||
connectionAttempt.state.Set(1)
|
connectionAttempt.state.Set(1)
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (*Device, er
|
||||||
errCode := C.sd_ble_gap_connect(&addr, &scanParams, &connectionParams, C.BLE_CONN_CFG_TAG_DEFAULT)
|
errCode := C.sd_ble_gap_connect(&addr, &scanParams, &connectionParams, C.BLE_CONN_CFG_TAG_DEFAULT)
|
||||||
if errCode != 0 {
|
if errCode != 0 {
|
||||||
connectionAttempt.state.Set(0)
|
connectionAttempt.state.Set(0)
|
||||||
return nil, Error(errCode)
|
return Device{}, Error(errCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait until the connection is established.
|
// Wait until the connection is established.
|
||||||
|
@ -179,13 +179,13 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (*Device, er
|
||||||
connectionAttempt.state.Set(0)
|
connectionAttempt.state.Set(0)
|
||||||
|
|
||||||
// Connection has been established.
|
// Connection has been established.
|
||||||
return &Device{
|
return Device{
|
||||||
connectionHandle: connectionHandle,
|
connectionHandle: connectionHandle,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disconnect from the BLE device.
|
// Disconnect from the BLE device.
|
||||||
func (d *Device) Disconnect() error {
|
func (d Device) Disconnect() error {
|
||||||
errCode := C.sd_ble_gap_disconnect(d.connectionHandle, C.BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION)
|
errCode := C.sd_ble_gap_disconnect(d.connectionHandle, C.BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION)
|
||||||
if errCode != 0 {
|
if errCode != 0 {
|
||||||
return Error(errCode)
|
return Error(errCode)
|
||||||
|
|
|
@ -170,7 +170,7 @@ type Device struct {
|
||||||
// Connect starts a connection attempt to the given peripheral device address.
|
// Connect starts a connection attempt to the given peripheral device address.
|
||||||
//
|
//
|
||||||
// On Linux and Windows, the IsRandom part of the address is ignored.
|
// On Linux and Windows, the IsRandom part of the address is ignored.
|
||||||
func (a *Adapter) Connect(address Address, params ConnectionParams) (*Device, error) {
|
func (a *Adapter) Connect(address Address, params ConnectionParams) (Device, error) {
|
||||||
var winAddr uint64
|
var winAddr uint64
|
||||||
for i := range address.MAC {
|
for i := range address.MAC {
|
||||||
winAddr += uint64(address.MAC[i]) << (8 * i)
|
winAddr += uint64(address.MAC[i]) << (8 * i)
|
||||||
|
@ -179,23 +179,23 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (*Device, er
|
||||||
// IAsyncOperation<BluetoothLEDevice>
|
// IAsyncOperation<BluetoothLEDevice>
|
||||||
bleDeviceOp, err := bluetooth.FromBluetoothAddressAsync(winAddr)
|
bleDeviceOp, err := bluetooth.FromBluetoothAddressAsync(winAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return Device{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to pass the signature of the parameter returned by the async operation:
|
// We need to pass the signature of the parameter returned by the async operation:
|
||||||
// IAsyncOperation<BluetoothLEDevice>
|
// IAsyncOperation<BluetoothLEDevice>
|
||||||
if err := awaitAsyncOperation(bleDeviceOp, bluetooth.SignatureBluetoothLEDevice); err != nil {
|
if err := awaitAsyncOperation(bleDeviceOp, bluetooth.SignatureBluetoothLEDevice); err != nil {
|
||||||
return nil, fmt.Errorf("error connecting to device: %w", err)
|
return Device{}, fmt.Errorf("error connecting to device: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := bleDeviceOp.GetResults()
|
res, err := bleDeviceOp.GetResults()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return Device{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// The returned BluetoothLEDevice is set to null if FromBluetoothAddressAsync can't find the device identified by bluetoothAddress
|
// The returned BluetoothLEDevice is set to null if FromBluetoothAddressAsync can't find the device identified by bluetoothAddress
|
||||||
if uintptr(res) == 0x0 {
|
if uintptr(res) == 0x0 {
|
||||||
return nil, fmt.Errorf("device with the given address was not found")
|
return Device{}, fmt.Errorf("device with the given address was not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
bleDevice := (*bluetooth.BluetoothLEDevice)(res)
|
bleDevice := (*bluetooth.BluetoothLEDevice)(res)
|
||||||
|
@ -204,7 +204,7 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (*Device, er
|
||||||
// To initiate a connection, we need to set GattSession.MaintainConnection to true.
|
// To initiate a connection, we need to set GattSession.MaintainConnection to true.
|
||||||
dID, err := bleDevice.GetBluetoothDeviceId()
|
dID, err := bleDevice.GetBluetoothDeviceId()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return Device{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Windows does not support explicitly connecting to a device.
|
// Windows does not support explicitly connecting to a device.
|
||||||
|
@ -212,29 +212,29 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (*Device, er
|
||||||
// by the calling program.
|
// by the calling program.
|
||||||
gattSessionOp, err := genericattributeprofile.FromDeviceIdAsync(dID) // IAsyncOperation<GattSession>
|
gattSessionOp, err := genericattributeprofile.FromDeviceIdAsync(dID) // IAsyncOperation<GattSession>
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return Device{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := awaitAsyncOperation(gattSessionOp, genericattributeprofile.SignatureGattSession); err != nil {
|
if err := awaitAsyncOperation(gattSessionOp, genericattributeprofile.SignatureGattSession); err != nil {
|
||||||
return nil, fmt.Errorf("error getting gatt session: %w", err)
|
return Device{}, fmt.Errorf("error getting gatt session: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
gattRes, err := gattSessionOp.GetResults()
|
gattRes, err := gattSessionOp.GetResults()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return Device{}, err
|
||||||
}
|
}
|
||||||
newSession := (*genericattributeprofile.GattSession)(gattRes)
|
newSession := (*genericattributeprofile.GattSession)(gattRes)
|
||||||
// This keeps the device connected until we set maintain_connection = False.
|
// This keeps the device connected until we set maintain_connection = False.
|
||||||
if err := newSession.SetMaintainConnection(true); err != nil {
|
if err := newSession.SetMaintainConnection(true); err != nil {
|
||||||
return nil, err
|
return Device{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Device{bleDevice, newSession}, nil
|
return Device{bleDevice, newSession}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disconnect from the BLE device. This method is non-blocking and does not
|
// Disconnect from the BLE device. This method is non-blocking and does not
|
||||||
// wait until the connection is fully gone.
|
// wait until the connection is fully gone.
|
||||||
func (d *Device) Disconnect() error {
|
func (d Device) Disconnect() error {
|
||||||
defer d.device.Release()
|
defer d.device.Release()
|
||||||
defer d.session.Release()
|
defer d.session.Release()
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
//
|
//
|
||||||
// Passing a nil slice of UUIDs will return a complete list of
|
// Passing a nil slice of UUIDs will return a complete list of
|
||||||
// services.
|
// services.
|
||||||
func (d *Device) DiscoverServices(uuids []UUID) ([]DeviceService, error) {
|
func (d Device) DiscoverServices(uuids []UUID) ([]DeviceService, error) {
|
||||||
d.prph.DiscoverServices([]cbgo.UUID{})
|
d.prph.DiscoverServices([]cbgo.UUID{})
|
||||||
|
|
||||||
// clear cache of services
|
// clear cache of services
|
||||||
|
@ -69,7 +69,7 @@ type DeviceService struct {
|
||||||
type deviceService struct {
|
type deviceService struct {
|
||||||
uuidWrapper
|
uuidWrapper
|
||||||
|
|
||||||
device *Device
|
device Device
|
||||||
|
|
||||||
service cbgo.Service
|
service cbgo.Service
|
||||||
characteristics []DeviceCharacteristic
|
characteristics []DeviceCharacteristic
|
||||||
|
|
|
@ -35,7 +35,7 @@ const (
|
||||||
type DeviceService struct {
|
type DeviceService struct {
|
||||||
uuid UUID
|
uuid UUID
|
||||||
|
|
||||||
device *Device
|
device Device
|
||||||
startHandle, endHandle uint16
|
startHandle, endHandle uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ func (s DeviceService) UUID() UUID {
|
||||||
//
|
//
|
||||||
// Passing a nil slice of UUIDs will return a complete list of
|
// Passing a nil slice of UUIDs will return a complete list of
|
||||||
// services.
|
// services.
|
||||||
func (d *Device) DiscoverServices(uuids []UUID) ([]DeviceService, error) {
|
func (d Device) DiscoverServices(uuids []UUID) ([]DeviceService, error) {
|
||||||
if _debug {
|
if _debug {
|
||||||
println("DiscoverServices")
|
println("DiscoverServices")
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ func (s DeviceService) UUID() UUID {
|
||||||
//
|
//
|
||||||
// On the Nordic SoftDevice, only one service discovery procedure may be done at
|
// On the Nordic SoftDevice, only one service discovery procedure may be done at
|
||||||
// a time.
|
// a time.
|
||||||
func (d *Device) DiscoverServices(uuids []UUID) ([]DeviceService, error) {
|
func (d Device) DiscoverServices(uuids []UUID) ([]DeviceService, error) {
|
||||||
if discoveringService.state.Get() != 0 {
|
if discoveringService.state.Get() != 0 {
|
||||||
// Not concurrency safe, but should catch most concurrency misuses.
|
// Not concurrency safe, but should catch most concurrency misuses.
|
||||||
return nil, errAlreadyDiscovering
|
return nil, errAlreadyDiscovering
|
||||||
|
|
|
@ -30,7 +30,7 @@ var (
|
||||||
//
|
//
|
||||||
// Passing a nil slice of UUIDs will return a complete list of
|
// Passing a nil slice of UUIDs will return a complete list of
|
||||||
// services.
|
// services.
|
||||||
func (d *Device) DiscoverServices(filterUUIDs []UUID) ([]DeviceService, error) {
|
func (d Device) DiscoverServices(filterUUIDs []UUID) ([]DeviceService, error) {
|
||||||
// IAsyncOperation<GattDeviceServicesResult>
|
// IAsyncOperation<GattDeviceServicesResult>
|
||||||
getServicesOperation, err := d.device.GetGattServicesWithCacheModeAsync(bluetooth.BluetoothCacheModeUncached)
|
getServicesOperation, err := d.device.GetGattServicesWithCacheModeAsync(bluetooth.BluetoothCacheModeUncached)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -133,7 +133,7 @@ type DeviceService struct {
|
||||||
uuidWrapper
|
uuidWrapper
|
||||||
|
|
||||||
service *genericattributeprofile.GattDeviceService
|
service *genericattributeprofile.GattDeviceService
|
||||||
device *Device
|
device Device
|
||||||
}
|
}
|
||||||
|
|
||||||
// UUID returns the UUID for this DeviceService.
|
// UUID returns the UUID for this DeviceService.
|
||||||
|
|
Loading…
Reference in a new issue