Skip to main content
 首页 » 编程设计

c#之Xamarin IOS : BLE

2024年02月25日73zhujiabin

我正在尝试连接到我的低功耗蓝牙设备。找到设备并获取外围对象后。我无法从我的 iPhone 连接到蓝牙设备,它也没有调用 central.ConnectedPeripheral 方法。

另一个问题是我无法在方法中注册事件 central.ConnectedPeripheral += ConnectedPeripheral。

错误:System.InvalidOperationException:事件注册正在覆盖现有委托(delegate)。要么只使用事件,要么使用你自己的委托(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(); 
    } 
} 

请您参考如下方法:

要消除“错误:System.InvalidOperationException:事件注册正在覆盖现有委托(delegate)。要么只使用事件,要么使用您自己的委托(delegate)”错误,请在 SimpleCBCentralManagerDelegate 中实现 ConnectedPeripheral 方法 类。该类被用作 iOS 委托(delegate)(不要与 C# delegate 混淆)所以来自 CBCentralManager central 的所有事件都在相关方法中处理SimpleCBCentralManagerDelegate 类。

这里的想法是,您可以使用 iOS 样式委托(delegate)/协议(protocol)模式,其中实现 Obj-C/iOS 协议(protocol)的委托(delegate)类被指定为将调用这些协议(protocol)的类的 iOS/Obj-C 委托(delegate)协议(protocol)方法,或者您可以使用 C# 样式的事件订阅,但不能在同一个对象上同时使用这两种方法。

更多信息在本文档中讨论:https://learn.microsoft.com/en-us/xamarin/ios/app-fundamentals/delegates-protocols-and-events 这是一本很长的书,但如果您正在使用 Xamarin.iOS 进行开发,那么它非常值得。