如何以Xamarin形式为BLE分割并发送大于20字节的数据? [英] How to split and send data >20 bytes for BLE in Xamarin forms?
问题描述
我正在尝试以Xamarin形式实现 BLE .我要发送数据大于20个字节.我已经看到使用Java在原生android中的实现.如下图
I'm trying to implement BLE in Xamarin forms. I want to send data larger than 20 bytes. I have seen the implementations in the native android using java. It looks like below
private void sendMessage(BluetoothGattCharacteristic characteristic, String CHARACTERS){
byte[] initial_packet = new byte[3];
/**
* Indicate byte
*/
initial_packet[0] = BLE.INITIAL_MESSAGE_PACKET;
if (Long.valueOf(
String.valueOf(CHARACTERS.length() + initial_packet.length))
> BLE.DEFAULT_BYTES_VIA_BLE) {
sendingContinuePacket(characteristic, initial_packet, CHARACTERS);
} else {
sendingLastPacket(characteristic, initial_packet, CHARACTERS);
}
}
private void sendingContinuePacket(BluetoothGattCharacteristic characteristic,
byte[] initial_packet, String CHARACTERS){
/**
* TODO If data length > Default data can sent via BLE : 20 bytes
*/
// Check the data length is large how many times with Default Data (BLE)
int times = Byte.valueOf(String.valueOf(
CHARACTERS.length() / BLE.DEFAULT_BYTES_IN_CONTINUE_PACKET));
Log.i(TAG, "CHARACTERS.length() " + CHARACTERS.length());
Log.i(TAG, "times " + times);
// TODO
// 100 : Success
// 101 : Error
byte[] sending_continue_hex = new byte[BLE.DEFAULT_BYTES_IN_CONTINUE_PACKET];
for (int time = 0; time <= times; time++) {
/**
* Wait second before sending continue packet
*/
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (time == times) {
Log.i(TAG, "LAST PACKET ");
/**
* If you do not have enough characters to send continue packet,
* This is the last packet that will be sent to the band
*/
/**
* Packet length byte :
*/
/**
* Length of last packet
*/
int character_length = CHARACTERS.length()
- BLE.DEFAULT_BYTES_IN_CONTINUE_PACKET*times;
initial_packet[1] = Byte.valueOf(String.valueOf(character_length
+ BLE.INITIAL_MESSAGE_PACKET_LENGTH));
initial_packet[2] = BLE.SENDING_LAST_PACKET;
Log.i(TAG, "character_length " + character_length);
/**
* Message
*/
// Hex file
byte[] sending_last_hex = new byte[character_length];
// Hex file : Get next bytes
for (int i = 0; i < sending_last_hex.length; i++) {
sending_last_hex[i] =
CHARACTERS.getBytes()[sending_continue_hex.length*time + i];
}
// Merge byte[]
byte[] last_packet =
new byte[character_length + BLE.INITIAL_MESSAGE_PACKET_LENGTH];
System.arraycopy(initial_packet, 0, last_packet,
0, initial_packet.length);
System.arraycopy(sending_last_hex, 0, last_packet,
initial_packet.length, sending_last_hex.length);
// Set value for characteristic
characteristic.setValue(last_packet);
} else {
Log.i(TAG, "CONTINUE PACKET ");
/**
* If you have enough characters to send continue packet,
* This is the continue packet that will be sent to the band
*/
/**
* Packet length byte
*/
int character_length = sending_continue_hex.length;
/**
* TODO Default Length : 20 Bytes
*/
initial_packet[1] = Byte.valueOf(String.valueOf(
character_length + BLE.INITIAL_MESSAGE_PACKET_LENGTH));
/**
* If sent data length > 20 bytes (Default : BLE allow send 20 bytes one time)
* -> set 01 : continue sending next packet
* else or if after sent until data length < 20 bytes
* -> set 00 : last packet
*/
initial_packet[2] = BLE.SENDING_CONTINUE_PACKET;
/**
* Message
*/
// Hex file : Get first 17 bytes
for (int i = 0; i < sending_continue_hex.length; i++) {
Log.i(TAG, "Send stt : "
+ (sending_continue_hex.length*time + i));
// Get next bytes
sending_continue_hex[i] =
CHARACTERS.getBytes()[sending_continue_hex.length*time + i];
}
// Merge byte[]
byte[] sending_continue_packet =
new byte[character_length + BLE.INITIAL_MESSAGE_PACKET_LENGTH];
System.arraycopy(initial_packet, 0, sending_continue_packet,
0, initial_packet.length);
System.arraycopy(sending_continue_hex, 0, sending_continue_packet,
initial_packet.length, sending_continue_hex.length);
// Set value for characteristic
characteristic.setValue(sending_continue_packet);
}
// Write characteristic via BLE
mBluetoothGatt.writeCharacteristic(characteristic);
}
}
public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic,
String data) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return false;
}
if (ActivityBLEController.IS_FIRST_TIME) {
/**
* In the first time,
* should send the Title
*/
byte[] merge_title = sendTitle(data);
// Set value for characteristic
characteristic.setValue(merge_title);
// Write characteristic via BLE
mBluetoothGatt.writeCharacteristic(characteristic);
// Reset
ActivityBLEController.IS_FIRST_TIME = false;
return true;
} else {
/**
* In the second time,
* should send the Message
*/
if (data.length() <= BLE.LIMIT_CHARACTERS) {
sendMessage(characteristic, data);
// Reset
ActivityBLEController.IS_FIRST_TIME = true;
return true;
} else {
// Typed character
typed_character = data.length();
return false;
}
}
}
这是我的 Xamarin代码,我在其中进行写操作
This is my Xamarin code where I do write operation
private async Task<string> ReadAndWriteCharacterisicsValue(ICharacteristic _characteristics)
{
if (_characteristics != null)
{
var sbnew = new StringBuilder("BLE Characteristics\n");
byte[] senddata = Encoding.UTF8.GetBytes(string.IsNullOrEmpty("") ? "Hi1290004847846767627723676" : "");
if (MainThread.IsMainThread)
{
string writeTypes = _characteristics.WriteType.ToString();
await _characteristics.WriteAsync(senddata);
}
//_characteristics.ReadAsync();
var charVal = _characteristics.Value;
var str = Encoding.UTF8.GetString(charVal);
sbnew.AppendLine($"Characteristics found on this device: {string.Join(", ", str.ToString())}");
return sbnew.ToString();
}
return null;
}
当我尝试发送字符串 Hi1290004847846767627723676(27字节)时,我在外围设备中收到了 Hi129000484784676762(20字节)而没有崩溃.我正在使用 plugin.ble 最新版本,并且我的蓝牙设备版本是 5.0 .我什至尝试请求Mtu .如您在以下代码中看到的
When I try to send String Hi1290004847846767627723676(27 Bytes) but I get Hi129000484784676762(20 Bytes) in peripheral without crashing. I'm using plugin.ble latest version and also my bluetooth device version is 5.0. I even tried requesting Mtu. As you can see in the following code
if (_characteristics != null)
{
try
{
var sbnew = new StringBuilder("BLE Characteristics\n");
byte[] senddata = Encoding.UTF8.GetBytes(string.IsNullOrEmpty("") ? "Start{'command':'UnSelectEnhancement','data':[{'UnSelectEnhancement':'VitaminC'},{'UnSelectEnhancement':'CitricAcid'}, {'UnSelectEnhancement':'Electolytes'},{'UnSelectEnhancement':'Sweetener'}]}End":"");
await _device.RequestMtuAsync(2000);
if (MainThread.IsMainThread)
{
string writeTypes = _characteristics.WriteType.ToString();
await _characteristics.WriteAsync(senddata);
}
我要发送的数据最大为 200字节.我还尝试使用此代码分割字符串.
I want to send data maximum of 200 bytes. I also tried splitting string using this code.
IEnumerable<string> s = str.Split();
IEnumerable<string> Split( )
{
while (!string.IsNullOrWhiteSpace(str))
{
var chunk = str.Take(size).ToArray();
str = str.Substring(chunk.Length);
yield return new string(chunk);
}
}
Console.WriteLine("Error of split");
Console.WriteLine(String.Join(Environment.NewLine, str));
Console.WriteLine(String.Join(Environment.NewLine, str));
但是它没有用,对我来说看起来很复杂.是否有任何简便的方法使用Xamarin形式的c#对大于 20字节的数据进行写操作?
But it didn't work.It looks quite complicated for me. Is there any easy way to do the write operation for data larger than 20 bytes using c# in xamarin forms?
推荐答案
您可以尝试以多个块发送数据,每个块的最大大小为20.此示例发送第一个20字节的块,然后发送剩下的7字节的另一个块.
You can try and send the data in multiple chunks each having a maximum size of 20. This example sends the first chunk of 20 bytes, then another one with the remaining 7.
byte[] senddata = Encoding.ASCII.GetBytes("Hi1290004847846767627723676");
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, 0, chunkLength);
await writeBuf.WriteAsync(chunk);
start += 20;
}
- 已删除为副本&的评论粘贴
这篇关于如何以Xamarin形式为BLE分割并发送大于20字节的数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!