Xamarin IOS: BLE - PullRequest
       10

Xamarin IOS: BLE

0 голосов
/ 15 января 2019

Я пытаюсь подключиться к своему устройству с низким энергопотреблением Bluetooth. После нахождения устройства и получения периферийного объекта. Я не могу подключиться к устройству Bluetooth с моего iPhone, и он не вызывает central.ConnectedPeripheral метод.

Другая проблема заключается в том, что я не могу зарегистрировать событие central.ConnectedPeripheral + = ConnectedPeripheral в методе.

Ошибка : System.InvalidOperationException: регистрация события перезаписывает существующего делегата. Либо просто используйте события, либо свой собственный делегат:

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();
    }
}

1 Ответ

0 голосов
/ 16 января 2019

Чтобы избавиться от ошибки «Ошибка: System.InvalidOperationException: регистрация события перезаписывает существующего делегата. Либо просто используйте события, либо свой собственный делегат», реализуйте метод ConnectedPeripheral в классе SimpleCBCentralManagerDelegate. Этот класс используется в качестве делегата iOS (не путать с C # delegate), поэтому все события из CBCentralManager central обрабатываются соответствующими методами в классе SimpleCBCentralManagerDelegate.

Идея заключается в том, что вы можете использовать шаблон делегата / протокола в стиле iOS, где класс делегата, который реализует протокол Obj-C / iOS, назначается как делегат iOS / Obj-C для класса, который будет вызывать их. протокольные методы, или вы можете использовать подписки на события в стиле C #, но вы не можете использовать оба для одного и того же объекта.

Более подробная информация об этом обсуждается в этом документе: https://docs.microsoft.com/en-us/xamarin/ios/app-fundamentals/delegates-protocols-and-events Это долгое чтение, но оно того стоит, если вы разрабатываете с использованием Xamarin.iOS.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...