Reputation: 81
I am trying to connect to my Bluetooth Low Energy Device. After finding the device and getting the peripheral object. I cannot connect to the Bluetooth Device from my iPhone and it does not call central.ConnectedPeripheral method.
Another issue is that i cannot register the event central.ConnectedPeripheral += ConnectedPeripheral in the method.
Error: System.InvalidOperationException: Event registration is overwriting existing delegate. Either just use events or your own delegate:
class IOSBluetooth : IBluetooth
{
private readonly CBCentralManager central;
private CBPeripheral activePeripheral;
SimpleCBCentralManagerDelegate myCentralDelegate;
public bool IsScanning { get; private set; }
List<CBPeripheral> connectedDevices = new List<CBPeripheral>();
//List<CBPeripheral> discoveredDevices = new List<CBPeripheral>();
/// <summary>
/// Gets the current Bluetooth instance
/// </summary>
/// <value>The Bluetooth Adapter instance</value>
public IOSBluetooth(SimpleCBCentralManagerDelegate myCenDel)
{
myCentralDelegate = myCenDel;
central = new CBCentralManager(myCentralDelegate, DispatchQueue.CurrentQueue);
InitializeEvents();
// central.DiscoveredPeripheral += DiscoveredPeripheral; // Called when peripheral is discovered (Working)
// central.UpdatedState += UpdatedState; // Method Implemented - Tells us about the bluetooth powered state (On or Off). (Working)
// central.ConnectedPeripheral += ConnectedPeripheral; // Devices that are connected to Iphone -> Services and Characteristics discovery start from here
// central.DisconnectedPeripheral += DisconnectedPeripheral; // Disconnect the device from the iphone
// central.FailedToConnectPeripheral += FailedToConnectPeripheral; // Failed to connect to Bluetooth Device
}
void InitializeEvents()
{
try
{
// central.ConnectedPeripheral += ConnectedPeripheral;
central.FailedToConnectPeripheral += FailedToConnectPeripheral;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message, "Intialization Failes");
Console.WriteLine("Bluetooth.Connect " + ex.Message);
}
}
public void FailedToConnectPeripheral(object sender, CBPeripheralErrorEventArgs e)
{
Console.WriteLine("Failed to Connect to Peripheral");
}
private void DisconnectedPeripheral(object sender, CBPeripheralErrorEventArgs e)
{
// when a peripheral disconnects, remove it from our running list.
if (connectedDevices.Contains(e.Peripheral))
{
connectedDevices.Remove(e.Peripheral);
}
}
public void ConnectToPeripheral(CBPeripheral peripheral)
{
central.ConnectPeripheral(peripheral, new PeripheralConnectionOptions { NotifyOnConnection = true, NotifyOnDisconnection = true, NotifyOnNotification = true });
}
private void UpdatedState(object sender, EventArgs e)
{
throw new NotImplementedException();
}
//public override void DiscoveredPeripheral(object sender, CBDiscoveredPeripheralEventArgs e)
//{
// Console.WriteLine("DiscoveredPeripheral: {0}", e.Peripheral.Name);
// discoveredDevices.Add(e.Peripheral);
//}
public void ConnectedPeripheral(object sender, CBPeripheralEventArgs e)
{
if (!connectedDevices.Contains(e.Peripheral))
{
connectedDevices.Add(e.Peripheral);
}
activePeripheral = e.Peripheral;
Console.WriteLine("Connected to " + activePeripheral.Name);
if (activePeripheral.Delegate == null)
{
activePeripheral.Delegate = new SimplePeripheralDelegate();
//Begins asynchronous discovery of services
activePeripheral.DiscoverServices();
}
}
public async void BeginScanningForDevices()
{
Console.WriteLine("BluetoothLEManager: Starting a scan for devices.");
// start scanning
IsScanning = true;
central.ScanForPeripherals((CBUUID[])null); // Discover all the devices and Initiates async calls of DiscoveredPeripheral
// in 10 seconds, stop the scan
await Task.Delay(10000);
// if we're still scanning
if (IsScanning)
{
Console.WriteLine("BluetoothLEManager: Scan timeout has elapsed.");
StopScanningForDevices();
}
}
/// <summary>
/// Stops the Central Bluetooth Manager from scanning for more devices. Automatically
/// called after 10 seconds to prevent battery drain.
/// </summary>
public void StopScanningForDevices()
{
Console.WriteLine("BluetoothLEManager: Stopping the scan for devices.");
IsScanning = false;
central.StopScan();
}
public IEnumerable<string> ListDevices()
{
return myCentralDelegate.DiscoveredDevices.Keys;
}
public bool Connect(string DeviceName)
{
StopScanningForDevices();
if (!myCentralDelegate.DiscoveredDevices.ContainsKey(DeviceName))
return false;
var device = myCentralDelegate.DiscoveredDevices[DeviceName];
// central.ConnectPeripheral(device, new PeripheralConnectionOptions { NotifyOnConnection = true, NotifyOnDisconnection = true, NotifyOnNotification = true });
central.ConnectPeripheral(device);
return true;
}
public void StartScanning()
{
if(central.State == (CBCentralManagerState.PoweredOn))
BeginScanningForDevices();
}
public void StopScanning()
{
StopScanningForDevices();
}
}
Upvotes: 1
Views: 2026
Reputation: 6088
To get rid of the "Error: System.InvalidOperationException: Event registration is overwriting existing delegate. Either just use events or your own delegate" error, implement the ConnectedPeripheral
method in the SimpleCBCentralManagerDelegate
class. That class is being used as the iOS delegate (not to be confused with a C# delegate
) so all of the events from CBCentralManager central
are being handled in the relevant methods in the SimpleCBCentralManagerDelegate
class.
The idea here is that you can either use the iOS style delegate/protocol pattern, where a delegate class that implements an Obj-C/iOS protocol is assigned as the iOS/Obj-C delegate for the class that will call those protocol methods, or you can use C# style event subscriptions, but you can't use both on the same object.
More info on this is discussed on this document: https://learn.microsoft.com/en-us/xamarin/ios/app-fundamentals/delegates-protocols-and-events It's a long read but well worth it if you are developing using Xamarin.iOS.
Upvotes: 3