11

这是我正在尝试做的一些背景:

  1. 打开从移动设备到蓝牙打印机的串行端口。
  2. 向蓝牙打印机发送 EPL/2 表格,以便它了解如何处理即将接收的数据。
  3. 收到表格后,将一些数据发送到打印机,这些数据将打印在标签纸上。
  4. 根据需要对要打印的每个标签重复步骤 3。

第 2 步只发生在第一次,因为表单不需要在每个标签之前。我的问题是,当我发送表格时,如果我发送标签数据太快,它将无法打印。有时我会在标签上打印“蓝牙故障:无线电无法运行”,而不是我发送的数据。

通过执行以下操作,我找到了解决此问题的方法:

for (int attempt = 0; attempt < 3; attempt++)
{
    try
    {
        serialPort.Write(labelData);
        break;
    }
    catch (TimeoutException ex)
    {
        // Log info or display info based on ex.Message
        Thread.Sleep(3000);
    }
}

所以基本上,我可以捕获一个 TimeoutException 并在等待一段时间后重试 write 方法(三秒似乎一直有效,但更少,似乎每次尝试都会抛出异常)。经过三次尝试,我只是假设串行端口有问题并让用户知道。

这种方式似乎工作正常,但我确信有更好的方法来处理这个问题。我认为我需要使用 SerialPort 类中的一些属性,但我真的找不到任何好的文档或如何使用它们的示例。我尝试过使用一些属性,但它们似乎都没有达到我想要达到的效果。

这是我玩过的属性列表:

  • CD控股
  • 中通控股
  • Dsr控股
  • 启用 Dtr
  • 握手
  • RtsEnable

我确信这些的一些组合将处理我正在尝试做的更优雅的事情。

我正在使用 C#(2.0 框架)、Zebra QL 220+ 蓝牙打印机和 windows Mobile 6 手持设备,如果这对解决方案有任何影响的话。

任何建议,将不胜感激。

[更新]

我还应该注意到,移动设备使用的是蓝牙 2.0,而打印机只有 1.1 版。我假设速度差异是导致打印机在接收数据方面落后的原因。

4

3 回答 3

7

好吧,我已经根据已经给出的两个建议找到了一种方法。我需要使用以下内容设置我的串行端口对象:

serialPort.Handshake = Handshake.RequestToSendXOnXOff;
serialPort.WriteTimeout = 10000; // Could use a lower value here.

然后我只需要进行写调用:

serialPort.Write(labelData);

由于 Zebra 打印机支持软件流控制,它会在缓冲区快满时向移动设备发送 XOff 值。这会导致移动设备等待打印机发送 XOn 值,从而有效地通知移动设备它可以继续传输。

通过设置写入超时属性,我给出了在抛出写入超时异常之前允许传输的总时间。您仍然希望捕获写入超时,就像我在问题的示例代码中所做的那样。但是,没有必要循环 3 次(或任意数量),每次都尝试写入,因为软件流控制会启动和停止串行端口写入传输。

于 2008-10-31T15:57:47.373 回答
5

流量控制在这里是正确的答案,它可能不存在/实现/适用于您的蓝牙连接。

查看 Zebra 规范,看看它们是否实现了,或者您是否可以打开软件流控制(xon、xoff),这将允许您查看各种缓冲区何时已满。

此外,蓝牙无线电的最大传输速度不太可能超过 250k。您可能会考虑人为地将其限制为 9,600bps - 这将为无线电提供很大的喘息空间,用于重传、纠错、检测和自身的流量控制。

如果一切都失败了,那么您现在使用的 hack 还不错,但我会打电话给 Zebra 技术支持,并在放弃之前找出他们的建议。

-亚当

于 2008-10-21T16:33:54.477 回答
2

问题可能不在于串行端口代码,而在于底层蓝牙堆栈。您使用的端口是纯虚拟的,甚至不太可能实现任何握手(因为它在很大程度上没有意义)。CTS/RTS DTR/DSR 根本不适用于您的工作。

根本问题是,当您创建虚拟端口时,它必须绑定到蓝牙堆栈并连接到配对的串行设备。端口本身不知道这可能需要多长时间,并且它可能已设置为异步执行此操作(尽管这完全取决于设备 OEM 如何完成)以防止调用者在没有时间的情况下长时间锁定配对设备或配对设备超出范围。

虽然您的代码可能感觉像是 hack,但它可能是完成您正在做的事情的最佳、最便携的方式。

您可以使用蓝牙堆栈 API 来尝试在连接之前查看设备是否存在并处于活动状态,但堆栈 API 没有标准化,因此 Widcom 和 Microsoft API 在您如何执行此操作方面有所不同,并且 Widcom 是专有的,并且昂贵的。你最终会遇到一堆尝试发现堆栈类型,动态加载适当的验证器类,让它调用堆栈并查找设备的混乱。鉴于此,您的简单民意调查似乎更清晰,您不必为 Widcom SDK 支付几美元。

于 2008-10-21T16:21:27.950 回答