データを送信する前に、ラインがクリアされるのを待つようにシリアルポート書き込みメソッドを強制するにはどうすればよいですか?

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

質問

ここで、私がやろうとしていることの背景を説明します。

  1. モバイルデバイスからBluetoothプリンターへのシリアルポートを開きます。
  2. EPL / 2フォームをBluetoothプリンターに送信し、受信しようとしているデータの処理方法を理解します。
  3. フォームを受け取ったら、ラベルストックに印刷されるデータをプリンターに送信します。
  4. 各ラベルを印刷するのに必要な回数だけステップ3を繰り返します。

ステップ2は、フォームが各ラベルの前にある必要がないため、最初にのみ発生します。私の問題は、フォームを送信するときに、ラベルデータをすばやく送信すると印刷されないことです。 「Bluetooth Failure:Radio Non-Operational」というメッセージが表示されることがあります。送信したデータではなく、ラベルに印刷されています。

次のことを行うことで問題を回避する方法を見つけました:

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をキャッチし、一定の時間待機した後、書き込みメソッドを再試行できます(3秒は常に機能するようですが、それ以下の場合は試行ごとに例外をスローするようです)。 3回試行した後、シリアルポートに何か問題があると思い、ユーザーに知らせます。

この方法はうまくいくようですが、これを処理するより良い方法があると確信しています。 SerialPortクラスには、使用する必要があると思われるいくつかのプロパティがありますが、それらの使用方法に関する優れたドキュメントや例は実際には見つかりません。私はいくつかのプロパティをいじってみましたが、どれも私が達成しようとしていることをしているようには見えません。

これまでに使ったプロパティのリストは次のとおりです。

  • CDHolding
  • CtsHolding
  • DsrHolding
  • DtrEnable
  • ハンドシェイク
  • RtsEnable

これらのいくつかの組み合わせが、私がもっと優雅にやろうとしていることを処理すると確信しています。

C#(2.0フレームワーク)、Zebra QL 220+ Bluetoothプリンター、およびWindows Mobile 6ハンドヘルドデバイスを使用しています(ソリューションに違いがある場合)。

ご意見をお寄せください。

[更新]

また、モバイルデバイスはBluetooth 2.0を使用していますが、プリンターはバージョン1.1のみです。速度の違いが、プリンターがデータを受信する際に遅れを生じさせる原因であると考えています。

役に立ちましたか?

解決

ここでのフロー制御は正解であり、Bluetooth接続に存在/実装/適用できない場合があります。

Zebraの仕様をチェックして、実装されているかどうか、またはさまざまなバッファがいっぱいになったときに確認できるソフトウェアフロー制御(xon、xoff)をオンにできるかどうかを確認します。

さらに、Bluetooth無線は最大で250kを超える速度で送信することはできません。 9,600bpsに人為的に制限することを検討するかもしれません-これにより、無線は、再送信、エラー修正、検出、および独自のフロー制御のための大きな余地を得ることができます。

他のすべてが失敗した場合、あなたが今使用しているハックは悪くありませんが、Zebraの技術サポートに電話して、あきらめる前に彼らが推奨するものを見つけます。

-アダム

他のヒント

さて、すでに与えられた2つの提案に基づいてこれを行う方法を見つけました。次のようにシリアルポートオブジェクトを設定する必要があります。

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

その後、書き込み呼び出しを行う必要があります:

serialPort.Write(labelData);

Zebraプリンターはソフトウェアフロー制御をサポートしているため、バッファーがほぼいっぱいになるとXOff値をモバイルデバイスに送信します。これにより、モバイルデバイスはXOn値がプリンターから送信されるのを待ち、送信を継続できることをモバイルデバイスに効果的に通知します。

書き込みタイムアウトプロパティを設定することにより、書き込みタイムアウト例外がスローされるまでの送信に許可される合計時間を指定しています。質問のサンプルコードで行ったように、書き込みタイムアウトをキャッチする必要があります。ただし、ソフトウェアフロー制御がシリアルポートの書き込み送信を開始および停止するため、毎回書き込みを試行して3回(または任意の回数)ループする必要はありません。

問題は、シリアルポートコードではなく、基盤となるbluetoothスタックにある可能性があります。使用しているポートは純粋に仮想であり、ハンドシェイクが実装されていることはほとんどありません(ほとんど意味がないため)。 CTS / RTS DTR / DSRは、作業中のものには適用されません。

根本的な問題は、仮想ポートを作成するときに、その下でbluetoothスタックにバインドし、ペアのシリアルデバイスに接続する必要があることです。ポート自体には、どれくらい時間がかかるかわからないため、おそらく非同期でこれを行うように設定されています(ただし、純粋にデバイスOEMが行う方法です)。ペアリングされたデバイスまたはペアリングされたデバイスが範囲外です。

コードはハックのように感じるかもしれませんが、おそらくあなたがしていることを行うための最良で最も移植性の高い方法です。

BluetoothスタックAPIを使用して、デバイスが存在するかどうかを確認してから接続することができますが、スタックAPIの標準化はありません。そのため、WidcomとMicrosoft APIはその方法が異なります。独自仕様で高価です。最終的には、スタックの種類を見つけようとすること、適切な検証クラスを動的にロードすること、スタックを呼び出してデバイスを探すことの混乱に終わります。それに照らして、あなたの単純な世論調査はずっときれいに見え、Widcom SDKのために数ドルを払う必要はありません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top