【问题标题】:Packets swapped on BLE receive在 BLE 接收上交换的数据包
【发布时间】:2016-09-05 13:48:19
【问题描述】:

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

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

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

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

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

img1 img2

起初我认为这是一个线程问题,因为每个 Characteristic.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(byte b) 是 MessageBuffer 的一种方法,负责转义和添加到新的消息缓冲区。当它获得一个 end_char 时,它通过 MessageReceived 事件将消息传递给潜在的订阅者。

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

附带说明,该应用程序也在为 Android 和 iOS 开发,在这两个平台上都没有这样的问题。

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

【问题讨论】:

标签: c# async-await win-universal-app scheduled-tasks bluetooth-lowenergy


【解决方案1】:

Task 是在线程池上运行的协程,因此您可能实际运行在多线程上下文中,也可能不实际运行,具体取决于处理器能力和设备,但这个问题绝对看起来像是某种竞争条件。

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

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

尝试在 AddBytes 或您的事件处理程序中将字节缓冲区克隆到一个新的字节数组(.Clone() 使用对于原始类型数组很好,它将执行“深度”复制,因为字节数组中没有引用) (以与从 BLE 层读取的线程位于同一线程中的为准),然后将克隆的数组传递给新任务并查看问题是否仍然存在。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多