Xamarin的.形成蓝牙低能量不一致

本文关键字:能量 不一致 Xamarin | 更新日期: 2023-09-27 18:17:25

我正在构建一个蓝牙低功耗应用程序:https://github.com/xabre/xamarin-bluetooth-le

这个想法是有一个应用程序,将连接到一个外围设备和设置一些属性。(用户数据)。如果在外围设备上有一些例外,我也希望通过中央应用程序进行一些日志记录。

所以我成功地连接到我的外设和按钮点击这个设备,我得到通知在我的中心设备(客户端),如果我以前按下客户端设备上的"开始更新"按钮。

连接成功后,我也可以给Firstname特性写信了。

问题是关于不一致。我关闭了两台设备的Wifi。我用的是Nexus 6P(外设)和一加一(中置)。Xamarin.Forms .

有时(经常)我在连接后得到双重服务。

断开连接时的问题(从不从await返回),经常需要重新启动设备。

连接经常丢失…

这是我的BleServer类:(凌乱)

public class BleServer 
{
    public class OfflineListener : Java.Lang.Object, IOnClickListener
    {
        private List<string> objects = new List<string>() { "Itaque his sapiens semper", "Sed tamen est aliquid", "Apparet statim", "habes enim a rhetoribus", "Non quam nostram", "Luxuriam non reprehendit" };

        public void OnClick(View v)
        {
            QueueMessages.QueueMessageHandler.Instance.Enqueue(objects.OrderBy(a => Guid.NewGuid()).First());
        }

    }
    public class MyListener : Java.Lang.Object, IOnClickListener
    {
        private BluetoothGattCharacteristic _characteristic;
        private BluetoothGattServer _bluetoothServer;
        private BluetoothDevice _device;
        private List<string> objects = new List<string>() { "Itaque his sapiens semper", "Sed tamen est aliquid", "Apparet statim", "habes enim a rhetoribus", "Non quam nostram", "Luxuriam non reprehendit" };

        public MyListener(BluetoothGattCharacteristic characteristic, BluetoothGattServer bluetoothServer, BluetoothDevice device)
        {
            _characteristic = characteristic;
            _bluetoothServer = bluetoothServer;
            _device = device;
        }
        [MethodImpl(MethodImplOptions.Synchronized)]
        public void OnClick(View v)
        {
            try
            {
                if (!QueueMessages.QueueMessageHandler.Instance.IsEmpty())
                {
                    while (!QueueMessages.QueueMessageHandler.Instance.IsEmpty())
                    {
                        var message = QueueMessages.QueueMessageHandler.Instance.Dequeue();
                        _characteristic.SetValue(message);
                        _bluetoothServer.NotifyCharacteristicChanged(_device, _characteristic, false);
                    }
                }
                _characteristic.SetValue(objects.OrderBy(a => Guid.NewGuid()).First());
                var ara = _bluetoothServer.NotifyCharacteristicChanged(_device, _characteristic, false);
            }
            catch(Exception ex)
            {
                Console.WriteLine("OnClick: {0}", ex.Message);
            }
        }
    }
    private readonly BluetoothManager _bluetoothManager;
    private BluetoothAdapter _bluetoothAdapter;
    private BleGattServerCallback _bluettothServerCallback;
    private BluetoothGattServer _bluetoothServer;
    private BluetoothGattCharacteristic _characteristic;
    private Button _button;

    private static UUID Notification_Service_UUID = UUID.FromString("00001811-0000-1000-8000-00805f9b34fb");
    private static UUID Notification_NewAlert_UUID = UUID.FromString("00002A46-0000-1000-8000-00805f9b34fb");
    //private static UUID Notification_SupportedNewAlert_UUID = UUID.FromString("00002A47-0000-1000-8000-00805f9b34fb");
    //private static UUID Notification_SupportedUnreadAlertCategory_UUID = UUID.FromString("00002A48-0000-1000-8000-00805f9b34fb");
    //private static UUID Notification_UnreadAlertStatus_UUID = UUID.FromString("00002A45-0000-1000-8000-00805f9b34fb");
    //private static UUID Notification_AlertControlPoint_UUID = UUID.FromString("00002A44-0000-1000-8000-00805f9b34fb");
    private static UUID UserData_Service_UUID = UUID.FromString("0000181c-0000-1000-8000-00805f9b34fb");
    private static UUID UserData_Fname_Level_UUID = UUID.FromString("00002a8a-0000-1000-8000-00805f9b34fb");
    private static UUID UserData_Lname_Level_UUID = UUID.FromString("00002A90-0000-1000-8000-00805f9b34fb");
    private static UUID UserData_Email_Level_UUID = UUID.FromString("00002A87-0000-1000-8000-00805f9b34fb");
    private static UUID UserData_Language_Level_UUID = UUID.FromString("00002AA2-0000-1000-8000-00805f9b34fb");

    public BleServer(Activity activity)
    {
        _button = activity.FindViewById<Button>(Resource.Id.MyButton);

        _button.SetOnClickListener(new OfflineListener());

        _bluetoothManager = (BluetoothManager)activity.ApplicationContext.GetSystemService(Context.BluetoothService);
        _bluetoothAdapter = _bluetoothManager.Adapter;
        _bluettothServerCallback = new BleGattServerCallback();
        _bluetoothServer = _bluetoothManager.OpenGattServer(activity.ApplicationContext, _bluettothServerCallback);
        var service = new BluetoothGattService(Notification_Service_UUID, GattServiceType.Primary);
        _characteristic = new BluetoothGattCharacteristic(Notification_NewAlert_UUID, GattProperty.Notify | GattProperty.Write | GattProperty.Read, GattPermission.Read | GattPermission.Write);
        service.AddCharacteristic(_characteristic);
        _bluetoothServer.AddService(service);


        //test UserData
        var userDataServie = new BluetoothGattService(UserData_Service_UUID, GattServiceType.Primary);
        ///
        var firstName = new BluetoothGattCharacteristic(UserData_Fname_Level_UUID, GattProperty.Read | GattProperty.Write, GattPermission.Read | GattPermission.Write);
        userDataServie.AddCharacteristic(firstName);
        _bluetoothServer.AddService(userDataServie);
        //

        var batteryService = new BluetoothGattService(UUID.FromString("0000180F-0000-1000-8000-00805f9b34fb"), GattServiceType.Primary);
        var batteryLevel = new BluetoothGattCharacteristic(UUID.FromString("00002A19-0000-1000-8000-00805f9b34fb"), GattProperty.Read | GattProperty.Notify, GattPermission.Read);
        batteryService.AddCharacteristic(batteryLevel);
        _bluetoothServer.AddService(batteryService);

        _bluettothServerCallback.CharacteristicReadRequest += _bluettothServerCallback_CharacteristicReadRequest;
        _bluettothServerCallback.CharacteristicWriteRequest += _bluettothServerCallback_CharacteristicWriteRequest;
        _bluettothServerCallback.NotificationSent += _bluettothServerCallback_NotificationSent;
        _bluettothServerCallback.ConnectionStateChange += _bluettothServerCallback_ConnectionStateChange;
        Console.WriteLine("Server created!");
        BluetoothLeAdvertiser myBluetoothLeAdvertiser = _bluetoothAdapter.BluetoothLeAdvertiser;
        var builder = new AdvertiseSettings.Builder();
        builder.SetAdvertiseMode(AdvertiseMode.LowLatency);
        builder.SetConnectable(true);
        builder.SetTimeout(0);
        builder.SetTxPowerLevel(AdvertiseTx.PowerHigh);
        AdvertiseData.Builder dataBuilder = new AdvertiseData.Builder();
        dataBuilder.SetIncludeDeviceName(true);
        dataBuilder.SetIncludeTxPowerLevel(true);

        myBluetoothLeAdvertiser.StartAdvertising(builder.Build(), dataBuilder.Build(), new BleAdvertiseCallback());
    }

    void _bluettothServerCallback_NotificationSent(object sender, BleEventArgs e)
    {
        Debug.WriteLine("NotificationSent to: " + e.Device);
    }

    void _bluettothServerCallback_CharacteristicReadRequest(object sender, BleEventArgs e)
    {
        _bluetoothServer.SendResponse(e.Device, e.RequestId, GattStatus.Success, e.Offset, e.Characteristic.GetValue());
        return;
    }
    void _bluettothServerCallback_CharacteristicWriteRequest(object sender, BleEventArgs e)
    {
        e.Characteristic.SetValue(e.Value);
        _bluetoothServer.SendResponse(e.Device, e.RequestId, e.GattStatus, e.Offset, e.Characteristic.GetValue());
        return;
    }
    void _bluettothServerCallback_ConnectionStateChange(object sender, BleEventArgs e)
    {
        if(e.ProfileNewState == ProfileState.Connected || e.ProfileNewState == ProfileState.Connecting)
        {
            _button.SetOnClickListener(new MyListener(_characteristic, _bluetoothServer, e.Device));
        }
        else
        {
            _button.SetOnClickListener(new OfflineListener());
        }
    }
}
public class BleAdvertiseCallback : AdvertiseCallback
{
    public override void OnStartFailure(AdvertiseFailure errorCode)
    {
        Console.WriteLine("Adevertise start failure {0}", errorCode);
        base.OnStartFailure(errorCode);
    }
    public override void OnStartSuccess(AdvertiseSettings settingsInEffect)
    {
        Console.WriteLine("Adevertise start success {0}", settingsInEffect.Mode);
        base.OnStartSuccess(settingsInEffect);
    }
}

AndroidManifest on android project(central)

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
          android:versionCode="1" 
          android:versionName="1.0" 
          package="prop.Mobile.Explorer.Droid" 
          android:installLocation="auto">
    <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="23" />
    <application android:label="Microprop" android:icon="@drawable/icon" android:theme="@style/MyTheme"></application>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
</manifest>

我做了一些阅读,BLE通常被认为是令人讨厌的东西。

<标题> 总结

Xamarin的。表单应用程序在不同的智能手机上运行。这个应用程序将连接到不同的外围设备实例。当拥有中心应用程序的人连接到一个外围设备时,他的名字(userdata设置)应该写入外围设备。

如果有什么错误,即异常,这应该排队并记录到中央应用程序,然后再到云。

<标题>
  • 这是正确的前进方向吗?
  • 当写用户名数据时,我应该使用UserData和Firstname的特征吗?(1) ? attributeXmlFile = org.bluetooth.service.user_data.xml
  • 对于日志功能,我将使用警报通知服务,这是正确的吗?(1) ? attributeXmlFile = org.bluetooth.service.alert_notification.xml
  • 我在一些文章中看到了信标,我应该调查一下吗?为什么我有这个问题?(请给出你希望看到的代码示例)

(1) bluetooth.com/specifications/gatt/viewer

Xamarin的.形成蓝牙低能量不一致

关于频繁的连接丢失:

尝试改变连接参数,特别是连接监督超时。超时定义了在主服务器将其解释为连接丢失之前,从服务器可以在多长时间内不响应主服务器。如果此值过低,如果从服务器需要很长时间才能应答,将经常发生连接丢失。

有关连接参数的更多信息,请参阅此处:

https://devzone.nordicsemi.com/question/60/what-is-connection-parameters/

对于服务的双元,通常是由于以下两种原因之一:要么是外设上的服务注册错误,要么是发现方法有问题。

目前我没有看到你的注册方法有问题,如果有的话,你总是会看到服务副本。所以我认为你的发现方法有问题。也许您不小心查询了句柄区域(从而查询了服务)两次?如果没有看到相应的方法(发送发现请求和接收发现响应),很难说。

一个好的方法是记录所有的发现请求和响应,并检查请求了哪些句柄间隔,返回了哪些结果。我们有重复的处理间隔吗?还是在两个不同的句柄区域注册服务?