I program (first time :P) AT-09 module with Xamarin Forms. From the module I send "Hello", it's work - I have chcecked with "Serial Bluetooth Terminal" app. I have wrote this simply code, which should be reading data from the module (I suppose):
using Android.App;
using Android.OS;
using Android.Runtime;
using Android.Widget;
using Android.Bluetooth;
using AndroidX.AppCompat.App;
using Plugin.BLE;
using Plugin.BLE.Abstractions.Contracts;
using Plugin.BLE.Abstractions.Exceptions;
using Plugin.BLE.Abstractions.EventArgs;
using Plugin.BLE.Android;
using IAdapter = Plugin.BLE.Abstractions.Contracts.IAdapter;
using IBluetoothLE = Plugin.BLE.Abstractions.Contracts.IBluetoothLE;
using IDevice = Plugin.BLE.Abstractions.Contracts.IDevice;
using System.Collections.ObjectModel;
using System.Text;
using System;
namespace BTT1
{
[Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
TextView tekst;
IBluetoothLE ble;
IAdapter adapter;
ObservableCollection<IDevice> deviceList;
IDevice _device;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
tekst = FindViewById<TextView>(Resource.Id.textView1);
tekst.Text = "ok dziala";
ble = CrossBluetoothLE.Current;
adapter = CrossBluetoothLE.Current.Adapter;
deviceList = new ObservableCollection<IDevice>();
btnConnect_Clicked();
}
private async void btnConnect_Clicked()
{
tekst.Text = "ok";
deviceList.Clear();
adapter.DeviceDiscovered = (s, a) =>
{
deviceList.Add(a.Device);
};
//We have to test if the device is scanning
if (!ble.Adapter.IsScanning)
{
await adapter.StartScanningForDevicesAsync();
tekst.Text = "ok2";
foreach (IDevice d in deviceList)
{
if (d.Id == Guid.Parse("00000000-0000-0000-0000-907065fb48ae"))
{
_device = d;
break;
}
}
await adapter.StopScanningForDevicesAsync();
}
try
{
if (_device != null)
{
await adapter.ConnectToDeviceAsync(_device);
Plugin.BLE.Abstractions.DeviceState status = Plugin.BLE.Abstractions.DeviceState.Connected;
if (_device.State == status)
{
tekst.Text = "ok3";
//var services = await device.GetServicesAsync();
var service = await _device.GetServiceAsync(Guid.Parse("0000ffe0-0000-1000-8000-00805f9b34fb"));
if (service != null)
{
//GattCharacteristicIdentifiers.ManufacturerName);
var characteristic = await service.GetCharacteristicAsync(Guid.Parse("0000ffe1-0000-1000-8000-00805f9b34fb"));
if (characteristic != null)
{
var bytes = await characteristic.ReadAsync();
var datas = Encoding.UTF8.GetString(bytes);
tekst.Text = datas.ToString(); //WHY datas.ToString() = "J"?
}
}
}
}
else
{
tekst.Text = "Notice No Device selected !";
}
}
catch (DeviceConnectionException ex)
{
//Could not connect to the device
tekst.Text = "Notice " ex.Message.ToString();
}
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
The string should be read in this fragment:
if (characteristic != null)
{
var bytes = await characteristic.ReadAsync();
var datas = Encoding.UTF8.GetString(bytes);
tekst.Text = datas.ToString(); //WHY datas.ToString() = "J"?
}
But there is a problem - my received text (tekst.Text = datas.ToString();
) is only "J", not "Hello". I don't have an idea why... Could you help me?
CodePudding user response:
Make sure to read the documentation of the BLE plugin and also check out the sample project provided there.
You need to subscribe to the ValueUpdated
event of the BLE characteristics of the connected device in order to receive characteristic notifications instead of manually reading the characteristic:
if (characteristic != null)
{
//subscribe to updates
characteristic.ValueUpdated = (s,e) =>
{
//read value here
var readBytes = e.Characteristic.Value;
var data = Encoding.UTF8.GetString(readBytes);
}
//start updates
await characteristic.StartUpdatesAsync();
}
Note: There is a platform-specific limit on the length of the BLE data per package. The BLE default is 20 bytes. So, if your text is longer, multiple events will be triggered, which means you need to collect the bytes in a byte array and then convert it to string once all bytes have been read.
That is how I have been using the BLE plugin so far. This code is only to demonstrate the general usage, you should of course adjust it to your needs.
Also, make sure to always wrap the BLE code in try-catch
blocks to avoid unhandled exceptions, especially on Android: https://github.com/xabre/xamarin-bluetooth-le#best-practice.