2

.NET サービス オブジェクトのプラグ アンド プレイ バージョンの POS に取り組んでいます。2 つのデバイスを搭載した FTDI デバイスがあります。1 つは MSR で、もう 1 つは RFID です。ハードウェア ID を指定すると、POS for .NET はプラグイン プレイをサポートします。FTDI デバイスのハードウェア ID はQUADPORT\QUAD_SERIAL_INTERFACEです。だから私のサービスオブジェクト(SO)では、これで始めます

[HardwareId("QUADPORT\\QUAD_SERIAL_INTERFACE")]
[ServiceObject(DeviceType.Msr, "FTDI Device", "MSR FTDI Device", 1, 8)]
public class FTDIDevice : Msr
{
...
}

open メソッドでは、DevicePath プロパティを照会できます。これは正しい DevicePath です。デバイス パスを介して実際にシリアル ポートと通信していることを確認するための簡単なテストとして、このデバイス パスへの FileStream を開き、両方の仮想 COM ポートを開いて、そのうちの 1 つが「アクセスが拒否されました」であることを確認しました。素晴らしい!次に行ったテストは、RFID デバイスへの書き込みでした。ほとんどすべてのコマンドと、RFID デバイスと通信するためのバイト配列のフォーマット方法を知っているからです。実際、ここに私が使用するコードがあります。

    public override void Open()
    {
        string str = this.DevicePath;
        handle_read = Kernel32.CreateExistingRWFile(str);
        FS_read = new FileStream(handle_read, FileAccess.ReadWrite, 9);

        Console.WriteLine("File Stream Created, Writing Open Sequence");
        byte[] open = { 0xAA, 0xBB, 0x04, 0xFB, 0x00, 0x00, 0x03, 0xF8 };
        FS_read.Write(open, 0, open.Length);

        //byte[] receive = new byte[11];
        //var something = FS_read.Read(receive, 0, receive.Length);
        //Console.WriteLine(BitConverter.ToString(receive, 0, something));
        //Close the FileStream and the SafeFileHandle
        close();
    }
    private SafeFileHandle handle_read;
    private FileStream FS_read;

このコードを初めて実行したとき、MSR を選択し (デバイス マネージャーと Microsoft テスト アプリの両方に正確な名前のデバイスが 2 つあるので、とにかく推測していました)、そのコマンドを送信しても MSR から応答がありませんでした (明らかな理由であり、RFID デバイスではありません)。MSDN サイトによると、Read コマンドは、ストリームから少なくとも 1 バイトが読み取られるまでブロックされます。MSR は RFID コマンドに応答しないため、これは問題です。したがって、本質的に私のプログラムはデッドロックです。プログラムを強制終了してから再度起動し、RFID を選択すると、Read メソッドは実際に RFID からの正常な応答を返しました。

だから私の質問は、どのようにストリームにクエリを実行して、デバイスからの応答があったかどうかを確認できるかということです。CanRead プロパティを使用してみました (常に true を返します)。ReadByte を使用して、ドキュメントが想定されているように -1 を返すかどうかを確認してみましたが、ハングします。Length プロパティを使用してみましたが、Stream がシークをサポートしていないという例外がスローされます。選択肢がなくなったような気がするので、ここで質問しています。助言がありますか?

編集

ハンスは、私がハンドルをどのように作成したかを見たいと思っています

internal class Kernel32
{
    internal static SafeFileHandle CreateExistingRWFile(string devicePath)
    {
        return CreateFile(devicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
    }

    internal const short FILE_ATTRIBUTE_NORMAL = 0x80;
    internal const short INVALID_HANDLE_VALUE = -1;
    internal const uint GENERIC_READ = 0x80000000;
    internal const uint GENERIC_WRITE = 0x40000000;
    internal const uint FILE_SHARE_READ = 0x00000001;
    internal const uint FILE_SHARE_WRITE = 0x00000002;
    internal const uint CREATE_NEW = 1;
    internal const uint CREATE_ALWAYS = 2;
    internal const uint OPEN_EXISTING = 3;

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool ReadFile(SafeFileHandle hFile, byte[] lpBuffer, uint nNumberOfBytesToRead, ref uint lpNumberOfBytesRead, IntPtr lpOverlapped);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool WriteFile(SafeFileHandle hFile, byte[] lpBuffer, uint nNumberOfBytesToWrite, ref uint lpNumberOfBytesWritten, IntPtr lpOverlapped);
}

ハンスが何かを提案しているのを見たとき、私は BeginRead で作業していましたが、これまでのところ EndRead は常に 0 を返します:/

これがそのコードです。

        byte[] receive = new byte[11];
        IAsyncResult iAR = FS_read.BeginRead(receive, 0, receive.Length, ASyncFileCallBack, receive);

        byte[] wildGuess = (byte[])iAR.AsyncState;
        Console.WriteLine("Guessing:{0}", BitConverter.ToString(wildGuess));
    }
    private void ASyncFileCallBack(IAsyncResult result)
    {
        byte[] buffer = (byte[])result.AsyncState;
        int length = FS_read.EndRead(result);

        if (length > 0)
            Console.WriteLine("Response:{0}", BitConverter.ToString(buffer, 0, length));
        else
            Console.WriteLine("No Resposne");
    }

guessing常に 11 個の 0 をほぼ即座に吐き​​出します。「応答なし」がコンソールに表示された直後。

4

0 に答える 0