问题描述
我如何以 xamarin 形式对 BLE(低功耗蓝牙) 进行单元测试。我正在测试使用 Nunit 实现 BLE Gatt 操作 的方法。我能够对 viewmodel 进行单元测试。但是我将如何测试 BLE gatt 操作 正在进行的单例类。这是作为中间的数据传输类。
public class DataTransfer:IManager
{
public ICharacteristic _characteristicsBLE;
private static readonly object padlock = new object(); //Using Padloc to make code thread safe
private static DataTransfer instance = null;
public string _result;
public IDevice _deviceBLE; //Contains information of BLE device
private DataTransfer()
{
}
//Instance of Singeleton class
public static DataTransfer Instance
{
get
{
if (instance == null)
{
lock (padlock)
{
if (instance == null)
{
instance = new DataTransfer();
}
}
}
return instance;
}
}
public async Task connect(ScanData scanData,CancellationTokenSource token)
{
try
{
await BleManager.Instance.BleState(scanData,token);
// await getcharacteristics(scanData,token);
}
catch(Exception ex)
{
await UserDialogs.Instance.AlertAsync("The data is incomplete scan again. Datatransfer");
}
}
public async Task getcharacteristics(ScanData scanData,CancellationTokenSource token)
{
try
{
await BleManager.Instance.Getcharacteristics(scanData);
}
catch (Exception ex)
{
await UserDialogs.Instance.AlertAsync("The data is incomplete scan again. Datatransfer");
}
}
}
这是 BLE 管理器类,其中包含 BLE gatt 操作。
public class BleManager
{
private IBluetoothLE _bluetoothLe;
public IBluetoothService _bleState; //Reference for BluetoothService which has execution for turning ON bluetooth using Dependency service
public IDevice _device; //Contains information of BLE device
public IAdapter _adapter;
public static readonly Guid SERVICE_ID = Guid.Parse("00001805-0000-1000-8000-00805f9b34fb"); //Sevice ID of BLE GATT
public static readonly Guid CHaraCTERISTIC_ID_WRITE = Guid.Parse("00002B0F-0000-1000-8000-00805f9b34fb"); //Characteristic ID of BLE GATT Write
public static readonly Guid CHaraCTERISTIC_ID_READ = Guid.Parse("00002a2b-0000-1000-8000-00805f9b34fb");
public string concat { get; set; }
public string BLEresultnew { get; set; }
public ICharacteristic _characteristicsBLE;
public NativeDevice NativeDeviceAdd { get; private set; } //Class which contain name and address of BLE
public string BleDeviceName { get; private set; }
private const string SERVICE_NAME = "Current Time Service"; //Service Name of BLE GATT
private static readonly object padlock = new object(); //Using Padloc to make code thread safe
private static BleManager instance = null;
private BleManager()
{
}
//Instance of Singeleton class
public static BleManager Instance
{
get
{
if (instance == null)
{
lock (padlock)
{
if (instance == null)
{
instance = new BleManager();
}
}
}
return instance;
}
}
//Check if Bluetooth is ON or OFF. If Bluetooth is switched OFF in android then switch it ON.
public async Task BleState(ScanData scanData,CancellationTokenSource token)
{
_bluetoothLe = CrossBluetoothLE.Current;
if (_bluetoothLe.State == BluetoothState.Off)
{
if (Device.RuntimePlatform == Device.iOS)
{
await UserDialogs.Instance.AlertAsync("Switch On bluetooth");
}
else
{
_bleState = DependencyService.Get<IBluetoothService>();
_bleState.OpenBluetooth();
await ScanForDevices(scanData);
}
}
else
{
await ScanForDevices(scanData);
}
}
//Scan for BLE devices
private async Task ScanForDevices(ScanData scanData,ConnectParameters connectParameters = default,CancellationToken token = default)
{
try
{
_device = null;
_adapter = CrossBluetoothLE.Current.Adapter;
_adapter.ScanMode = ScanMode.LowLatency;
_adapter.ScanTimeout = 5000;
Device.BeginInvokeOnMainThread(async () =>
{
_adapter.Devicediscovered += async (s,a) =>
{
NativeDeviceAdd = DependencyService.Get<INativeDevice>().ConvertToNative(a.Device);
PropertyInfo propInfo = NativeDeviceAdd.GetType().GetProperty("Name");
BleDeviceName = (string)propInfo.GetValue(NativeDeviceAdd,null);
string substr = scanData.blename;
if (BleDeviceName == substr)
{
_device = a.Device;
await _adapter.StopScanningForDevicesAsync();
await ConnectForDevice(scanData);
}
};
});
await _adapter.StartScanningForDevicesAsync();
}
catch (DeviceConnectionException ex)
{
await UserDialogs.Instance.AlertAsync("Device got disconnected please scan again 1");
return;
}
catch (Exception ex)
{
await UserDialogs.Instance.AlertAsync("Device got disconnected please scan again.The CancellationTokenSource has been disposed");
return;
}
}
//If the device is selected the connection is done here
private async Task ConnectForDevice(ScanData scanData,CancellationToken token = default)
{
try
{
_adapter.DeviceConnectionLost += async (s,a) =>
{
Device.BeginInvokeOnMainThread(async () =>
{
Console.WriteLine("Device ConnectionLost : " + a.ErrorMessage);
await UserDialogs.Instance.AlertAsync("Device ConnectionLost :"+a.ErrorMessage);
var parameters2 = new ConnectParameters(forceBleTransport: true,autoConnect: true);
await _adapter.ConnectToDeviceAsync(_device,parameters2);
await Getcharacteristics(scanData);
});
};
_adapter.Devicedisconnected += async (s,a) =>
{
Console.WriteLine("Device disconnected : ");
await UserDialogs.Instance.AlertAsync("Device disconnected :");
};
var parameters = new ConnectParameters(forceBleTransport: true,autoConnect:true);
await _adapter.ConnectToDeviceAsync(_device,parameters);
await Getcharacteristics(scanData);
}
catch (DeviceConnectionException ex)
{
Console.WriteLine("Exception while connecting and registering callbacks " + ex.Message);
await UserDialogs.Instance.AlertAsync("Device got disconnected please scan again 2" + ex.Message);
}
}
public async void disconnected()
{
await Application.Current.MainPage.Navigation.PopAsync();
return;
}
public async Task Getcharacteristics(ScanData scanData,CancellationToken token = default)
{
try
{
concat = null;
var service = await _device.GetServiceAsync(SERVICE_ID);
var characteristicRead = await service.GetCharacteristicAsync(CHaraCTERISTIC_ID_READ);
await ReadConfigData(characteristicRead);
}
catch (DeviceConnectionException ex)
{
await UserDialogs.Instance.AlertAsync("Device got disconnected please scan again 3");
}
catch (TaskCanceledException tce)
{
Console.WriteLine("Scan was cancelled");
}
}
private async void OnDevicedisconnected(object sender,DeviceEventArgs e) //Is OK to use async void here
{
await UserDialogs.Instance.AlertAsync("Device got disconnected after scan");
}
private async void OnDeviceconnected(object sender,DeviceEventArgs e) //Is OK to use async void here
{
await UserDialogs.Instance.AlertAsync("Device got disconnected please scan again event");
}
public async Task WriteDataAsync(String data)
{
if (_characteristicsBLE != null)
{
try
{
byte[] senddata = Encoding.UTF8.GetBytes(data);
int start = 0;
while (start < senddata.Length)
{
int chunkLength = Math.Min(20,senddata.Length - start);
byte[] chunk = new byte[chunkLength];
Array.copy(senddata,start,chunk,chunkLength);
Device.BeginInvokeOnMainThread(async () =>
{
await _characteristicsBLE.WriteAsync(chunk);
});
start += 20;
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
public async Task ReadConfigData(ICharacteristic characteristics)
{
if (characteristics != null)
{
try
{
await _adapter.ConnectToDeviceAsync(_device);
characteristics.ValueUpdated += (o,e) =>
{
Device.BeginInvokeOnMainThread(async () =>
{
var bytes = e.Characteristic.Value;
BLEresultnew = System.Text.Encoding.UTF8.GetString(bytes);
Console.WriteLine(BLEresultnew);
concat += BLEresultnew;
});
};
await characteristics.StartUpdatesAsync();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
}
我不知道如何测试这些单一类。除了 xamarin 形式的单元测试之外,我还必须为 BLE 执行任何其他测试吗?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)