Как мне заставить метод записи в последовательный порт дождаться очистки строки перед отправкой ее данных?

StackOverflow https://stackoverflow.com/questions/222455

Вопрос

Вот некоторая предыстория того, что я пытаюсь сделать:

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

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

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

  • Хранение компакт - дисков
  • Кцхолдинг
  • DsrХолдинг
  • Обучаемый
  • Рукопожатие
  • Оцениваемый

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

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

Будем признательны за любые предложения.

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

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

Это было полезно?

Решение

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

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

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

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

-Адам

Другие советы

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

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

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

serialPort.Write(labelData);

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top