2008-10-21 12 views
11

Вот некоторый фон того, что я пытаюсь сделать:Как заставить метод записи последовательного порта ждать, пока строка будет очищена до отправки ее данных?

  1. Открыть последовательный порт с помощью мобильного устройства к принтеру Bluetooth.
  2. Отправьте EPL/2 форму на принтер Bluetooth, чтобы он понимал, как обрабатывать данные, которые он собирается получить.
  3. После получения формы отправьте некоторые данные на принтер, который будет напечатан на складе этикеток.
  4. Повторите шаг 3 столько раз, сколько необходимо для каждой маркируемой метки.

Шаг 2 происходит только в первый раз, так как форма не должна предшествовать каждой метке. Моя проблема в том, что когда я отправлю форму, если я отправлю данные метки слишком быстро, она не будет печататься. Иногда я получаю сообщение «Отказ Bluetooth: Радио, не действующий», напечатанный на ярлыке, а не данные, которые я отправил.

Я нашел способ обойти эту проблему, выполнив следующие действия:

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 и повторить метод записи после ожидания определенного количества времени (три секунды, кажется, работает все время, но все равно и, кажется, бросает исключение каждую попытку). После трех попыток я просто предполагаю, что у последовательного порта есть что-то неправильное и сообщит пользователю.

Этот способ, похоже, работает нормально, но я уверен, что есть лучший способ справиться с этим. В классе SerialPort есть несколько свойств, которые, я думаю, мне нужно использовать, но я не могу найти хорошую документацию или примеры того, как их использовать. Я пробовал играть с некоторыми из свойств, но никто из них, похоже, не делает то, что я пытаюсь достичь.

Вот список свойств я играл с:

  • CDHolding
  • CtsHolding
  • DsrHolding
  • DtrEnable
  • Рукопожатие
  • RtsEnable

Я уверен, что некоторые из них будут обрабатывать то, что я пытаюсь сделать более изящно.

Я использую C# (2.0 framework), принтер Bluetooth Zebra QL 220+ и портативное устройство Windows Mobile 6, если это имеет значение для решений.

Любые предложения будут оценены.

[ОБНОВЛЕНИЕ]

Следует также отметить, что мобильное устройство использует Bluetooth 2.0, в то время как принтер только в версии 1.1. Я предполагаю, что разница в скорости - это то, что заставляет принтер отставать в получении данных.

+0

Джейсон, вы связались с Зебра, и что они сказали? Мне интересно узнать, как получилась эта история ... – 2009-12-22 15:20:32

+0

Это было некоторое время назад ... Я просто помню, что они рекомендовали управление потоком программного обеспечения, которое мы уже определили как лучший подход.Я не помню, чтобы они упоминали ограничение скорости передачи или что-то в этом роде. – 2009-12-22 22:36:21

ответ

5

Управление потоком является правильным ответом здесь, и оно может отсутствовать/реализовано/применимо к вашему соединению Bluetooth.

Ознакомьтесь с спецификацией Zebra и посмотрите, реализуются ли они, или если вы можете включить управление потоком программного обеспечения (xon, xoff), что позволит вам увидеть, когда заполняются различные буферы.

Кроме того, Bluetooth-радио вряд ли сможет передавать быстрее, чем 250k. Вы могли бы искусно ограничить его до 9600 бит/с - это позволит радио в значительной степени передышку для повторных передач, исправления ошибок, обнаружения и собственного контроля потока.

Если все остальное не удается, взлом, который вы используете прямо сейчас, неплохо, но я бы назвал техническую поддержку Zebra и узнал, что они рекомендуют, прежде чем сдаться.

-Adam

2

Возможно, проблема связана не с кодом последовательного порта, а с базовым стеклом Bluetooth.Порт, который вы используете, является чисто виртуальным, и маловероятно, что какое-либо из рукопожатий даже реализовано (поскольку это было бы в значительной степени бессмысленным). CTS/RTS DTR/DSR просто неприменимы для того, над чем вы работаете.

Основная проблема заключается в том, что при создании виртуального порта под ним приходится связываться со стеклом Bluetooth и подключаться к парному последовательному устройству. Сам порт не знает, как долго это может произойти, и, вероятно, он настроен для этого асинхронно (хотя это было бы чисто до OEM-устройства, как это сделано), чтобы предотвратить блокировку звонящего в течение длительного периода, если нет сопряженное устройство или сопряженное устройство выходит за пределы допустимого диапазона.

Хотя ваш код может выглядеть как взломанный, это, вероятно, лучший, самый портативный способ сделать то, что вы делаете.

Вы можете использовать API стека bluetooth, чтобы попытаться выяснить, существует ли устройство и быть живым перед подключением, но нет стандартизации API стека, поэтому Widcom и Microsoft API отличаются тем, как вы это сделаете, и Widcom является проприетарным и дорогостоящим. То, что у вас получилось, - это беспорядок, пытаясь обнаружить тип стека, динамически загружая соответствующий класс верификатора, вызвав его вызов и поиск устройства. В свете этого ваш простой опрос кажется намного более чистым, и вам не нужно выкладывать несколько $ k для Widcom SDK.

+0

Хороший ответ. Я бы записал его в разделе «Когда взломать на самом деле не хак». – endian 2008-10-21 16:28:37

7

Ну я нашел способ сделать это на основе двух предложений уже заданных. Мне нужно настроить мой серийный объект порта со следующим:

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

Тогда мне просто нужно сделать вызов записи:

serialPort.Write(labelData); 

Поскольку принтер Zebra поддерживает программное управление потоком данных, он будет посылать Значение XOff для мобильного устройства, когда буфер почти заполнен. Это приводит к тому, что мобильное устройство ожидает, что значение XOn будет отправлено с принтера, что будет эффективно уведомлять мобильное устройство о том, что оно может продолжать передачу.

Установив свойство времени ожидания записи, я даю общее время, разрешенное для передачи, до того, как будет выбрано исключение таймаута записи. Вы все равно хотите поймать тайм-аут записи, как это было в моем примере кода в вопросе. Тем не менее, не нужно было бы зацикливать 3 (или произвольное количество) раз, пытаясь писать каждый раз, так как управление потоком программного обеспечения запустится и остановит передачу записи последовательного порта.

 Смежные вопросы

  • Нет связанных вопросов^_^