BLE接收交换的数据包

本文关键字:数据包 交换 BLE | 更新日期: 2025-03-17 20:23:21

首先简单介绍一下应用程序。我们正在开发一种无线传感器,该传感器使用单一特性(硬件限制)通过BLE向客户端UWP应用程序发送数据。消息的大小从20字节以下到512字节不等。消息由开始字符(start_char)、前导码、数据、用于检测错误的CRC和结束字符(end_char)组成。如果这些特殊字符出现在消息中,则对其进行转义。

客户端的消息处理包括以下内容:

  1. 倾听特征。GattCharacteristic上的ValueChanged事件
  2. 将生成的字节数组传递给构建消息的解析器
  3. 将生成的消息传递给设备对象以进行解释

如果消息大于20个字节,BLE层会自动将其拆分为多个较小的字节数组,每个数组都会触发Characteristic。ValueChanged事件。解析器由AddBytes(byte[]data)方法组成,该方法在接收到start_char时启动新消息,并存储后续数据,直到接收到end_char,然后计算消息的CRC并将其传递

当接收到大于20字节的消息时,就会出现问题,并且看起来20字节长的数组中的一些正在被交换。以下图片显示了一个512字节的消息,出于调试目的,该消息被设置为表示三角波(2个上升)。我已经标出了数据被破坏的地方。

img1img2

起初我认为这是一个线程问题,因为每个Characteristics。ValueChanged事件在一个单独的线程上触发(我可能错了),所以我尝试使用这个:

public class ScheduledBuffer : MessageBuffer
{
    #region Fields / Properties
    TaskScheduler scheduler;
    TaskFactory taskFactory;
    #endregion
    #region Methods
    #region Constructors        
    public ScheduledBuffer() : base()
    {
        scheduler = TaskScheduler.FromCurrentSynchronizationContext();
        taskFactory = new TaskFactory(scheduler);
    }
    #endregion
    #region Private Methods
    void ProcessByteArray(byte[] buffer)
    {
        foreach (byte b in buffer)
        {
            ProcessByte(b);
        }
    }
    #endregion
    #region Public Methods
    public override void AddBytes(byte[] newData)
    {
        taskFactory
            .StartNew(() => { ProcessByteArray(newData); })
            .ContinueWith(t => { });
    }
    #endregion
    #endregion
    #region Events        
    #endregion
    #region Commands        
    #endregion
}

目标是对20字节长的数组进行排队处理,这样我就不会在前一个数组完成之前开始处理新的数组。ProcessByte(字节b)是MessageBuffer的一个方法,负责转义和添加到新的消息缓冲区。当它获得end_char时,它会通过MessageReceived事件将消息传递给潜在的订阅者。

这个实现有什么问题吗?或者BLE层可能在给我ValueChanged通知之前交换了字节数组吗?这种行为还有哪些可能的来源?

顺便说一句,该应用程序也正在为Android和iOS开发,这两个平台都没有这样的问题。

另一件值得一提的事情是,当在功能更强大的机器上运行应用程序时,这些错误的频率会降低,而在我的Lumia 640上,我很少收到正确的消息。

BLE接收交换的数据包

Task是在线程池上运行的协同程序,因此根据处理器功率和设备的不同,您可能会也可能不会在多线程上下文中运行,但这个问题看起来肯定是某种竞争条件。

BLE层在给我ValueChanged通知之前是否可能正在交换字节数组?

它必须这样做,除非ValueChanged通知还包括对字节数组的引用。在不了解更多信息的情况下,我猜BLE端有一个可重复使用的缓冲区,它正在一遍又一遍地读取同一组字节,而你只是在它用下一组覆盖它之前争着读取它们。

尝试将字节缓冲区克隆到AddBytes或事件处理程序(与从BLE层读取的字节在同一线程上)内的一个新字节数组(.Clone()对于基元类型的数组来说是可以使用的,它会进行"深度"复制,因为字节数组内没有引用),然后将克隆的数组传递给新的Task,看看问题是否仍然存在。