gpt4 book ai didi

asp.net - 与 Silverlight 5 的串行通信(COM 端口)

转载 作者:行者123 更新时间:2023-12-04 22:24:00 25 4
gpt4 key购买 nike

我正在一个 ASP.NET 网站上工作,我需要从客户端访问 USB 设备。

我已经看到 Silverlight 5 通过使用 P/Invoke 允许我们访问客户端计算机上的 dll。我计划在我的一个页面中添加一个 Silverlight 控件,该控件将与我的 USB 设备交互。这样,每个使用这种设备的客户只需要连接到我的网站并开始使用它。

尽管如此,作为与 USB 设备进行这种交互的初学者,我该如何做到这一点?

哪个 windows dll 将为我提供与 USB 设备交互的好方法?

更多信息:

  • 我需要能够通过 COM 端口进行通信。典型的串行通信。我怎样才能做到这一点?

  • 出于测试目的,我可以通过“Hercules”之类的应用程序连接到我的设备,我基本上需要在我的 silverlight 模块中重现这种连接......

    你们有什么例子吗?

    谢谢你的帮助,

    最佳答案

    我找到了一个包装类,它使我能够创建到 的连接。串口 内银光 5 .我现在可以通过串行通信访问我的 USB 设备。

    由于我花了很多时间试图让它发挥作用,我将与你分享这门课:

    using System;
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Text;

    namespace TestSerialDLL
    {
    public class SerialWrapper : IDisposable
    {
    #region Enum
    public enum StopBits
    {
    None,
    One,
    Two,
    OnePointFive,
    }

    public enum Parity
    {
    None,
    Odd,
    Even,
    Mark,
    Space,
    }
    #endregion
    #region Fields
    /// <summary>
    /// The baud rate at which the communications device operates.
    /// </summary>
    private readonly int iBaudRate;

    /// <summary>
    /// The number of bits in the bytes to be transmitted and received.
    /// </summary>
    private readonly byte byteSize;

    /// <summary>
    /// The system handle to the serial port connection ('file' handle).
    /// </summary>
    private IntPtr pHandle = IntPtr.Zero;

    /// <summary>
    /// The parity scheme to be used.
    /// </summary>
    private readonly Parity parity;

    /// <summary>
    /// The name of the serial port to connect to.
    /// </summary>
    private readonly string sPortName;

    /// <summary>
    /// The number of bits in the bytes to be transmitted and received.
    /// </summary>
    private readonly StopBits stopBits;
    #endregion

    #region Constructor
    /// <summary>
    /// Creates a new instance of SerialCom.
    /// </summary>
    /// <param>The name of the serial port to connect to</param>
    /// <param>The baud rate at which the communications device operates</param>
    /// <param>The number of stop bits to be used</param>
    /// <param>The parity scheme to be used</param>
    /// <param>The number of bits in the bytes to be transmitted and received</param>
    public SerialWrapper(string portName, int baudRate, StopBits stopBits, Parity parity, byte byteSize)
    {
    if (stopBits == StopBits.None)
    throw new ArgumentException("stopBits cannot be StopBits.None", "stopBits");
    if (byteSize < 5 || byteSize > 8)
    throw new ArgumentOutOfRangeException("The number of data bits must be 5 to 8 bits.", "byteSize");
    if (baudRate < 110 || baudRate > 256000)
    throw new ArgumentOutOfRangeException("Invalid baud rate specified.", "baudRate");
    if ((byteSize == 5 && stopBits == StopBits.Two) || (stopBits == StopBits.OnePointFive && byteSize > 5))
    throw new ArgumentException("The use of 5 data bits with 2 stop bits is an invalid combination, " +
    "as is 6, 7, or 8 data bits with 1.5 stop bits.");

    this.sPortName = portName;
    this.iBaudRate = baudRate;
    this.byteSize = byteSize;
    this.stopBits = stopBits;
    this.parity = parity;
    }

    /// <summary>
    /// Creates a new instance of SerialCom.
    /// </summary>
    /// <param>The name of the serial port to connect to</param>
    /// <param>The baud rate at which the communications device operates</param>
    /// <param>The number of stop bits to be used</param>
    /// <param>The parity scheme to be used</param>
    public SerialWrapper(string portName, int baudRate, StopBits stopBits, Parity parity)
    : this(portName, baudRate, stopBits, parity, 8)
    {

    }
    #endregion

    #region Open
    /// <summary>
    /// Opens and initializes the serial connection.
    /// </summary>
    /// <returns>Whether or not the operation succeeded</returns>
    public bool Open()
    {
    pHandle = CreateFile(this.sPortName, FileAccess.ReadWrite, FileShare.None,
    IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
    if (pHandle == IntPtr.Zero) return false;

    if (ConfigureSerialPort()) return true;
    else
    {
    Dispose();
    return false;
    }
    }
    #endregion

    #region Write
    /// <summary>
    /// Transmits the specified array of bytes.
    /// </summary>
    /// <param>The bytes to write</param>
    /// <returns>The number of bytes written (-1 if error)</returns>
    public int Write(byte[] data)
    {
    FailIfNotConnected();
    if (data == null) return 0;

    int bytesWritten;
    if (WriteFile(pHandle, data, data.Length, out bytesWritten, 0))
    return bytesWritten;
    return -1;
    }

    /// <summary>
    /// Transmits the specified string.
    /// </summary>
    /// <param>The string to write</param>
    /// <returns>The number of bytes written (-1 if error)</returns>
    public int Write(string data)
    {
    FailIfNotConnected();

    // convert the string to bytes
    byte[] bytes;
    if (data == null)
    {
    bytes = null;
    }
    else
    {
    bytes = Encoding.UTF8.GetBytes(data);
    }

    return Write(bytes);
    }

    /// <summary>
    /// Transmits the specified string and appends the carriage return to the end
    /// if it does not exist.
    /// </summary>
    /// <remarks>
    /// Note that the string must end in '\r\n' before any serial device will interpret the data
    /// sent. For ease of programmability, this method should be used instead of Write() when you
    /// want to automatically execute the specified command string.
    /// </remarks>
    /// <param>The string to write</param>
    /// <returns>The number of bytes written (-1 if error)</returns>
    public int WriteLine(string data)
    {
    if (data != null && !data.EndsWith("\r\n"))
    data += "\r\n";
    return Write(data);
    }
    #endregion

    #region Read
    /// <summary>
    /// Reads any bytes that have been received and writes them to the specified array.
    /// </summary>
    /// <param>The array to write the read data to</param>
    /// <returns>The number of bytes read (-1 if error)</returns>
    public int Read(byte[] data)
    {
    FailIfNotConnected();
    if (data == null) return 0;

    int bytesRead;
    if (ReadFile(pHandle, data, data.Length, out bytesRead, 0))
    return bytesRead;
    return -1;
    }

    /// <summary>
    /// Reads any data that has been received as a string.
    /// </summary>
    /// <param>The maximum number of bytes to read</param>
    /// <returns>The data received (null if no data)</returns>
    public string ReadString(int maxBytesToRead)
    {
    if (maxBytesToRead < 1) throw new ArgumentOutOfRangeException("maxBytesToRead");

    byte[] bytes = new byte[maxBytesToRead];
    int numBytes = Read(bytes);
    //string data = ASCIIEncoding.ASCII.GetString(bytes, 0, numBytes);
    string data = Encoding.UTF8.GetString(bytes, 0, numBytes);
    return data;
    }
    #endregion

    #region Dispose Utils
    /// <summary>
    /// Disconnects and disposes of the SerialCom instance.
    /// </summary>
    public void Dispose()
    {
    if (pHandle != IntPtr.Zero)
    {
    CloseHandle(pHandle);
    pHandle = IntPtr.Zero;
    }
    }

    /// <summary>
    /// Flushes the serial I/O buffers.
    /// </summary>
    /// <returns>Whether or not the operation succeeded</returns>
    public bool Flush()
    {
    FailIfNotConnected();

    const int PURGE_RXCLEAR = 0x0008; // input buffer
    const int PURGE_TXCLEAR = 0x0004; // output buffer
    return PurgeComm(pHandle, PURGE_RXCLEAR | PURGE_TXCLEAR);
    }
    #endregion

    #region Private Helpers
    /// <summary>
    /// Configures the serial device based on the connection parameters pased in by the user.
    /// </summary>
    /// <returns>Whether or not the operation succeeded</returns>
    private bool ConfigureSerialPort()
    {
    DCB serialConfig = new DCB();
    if (GetCommState(pHandle, ref serialConfig))
    {
    // setup the DCB struct with the serial settings we need
    serialConfig.BaudRate = (uint)this.iBaudRate;
    serialConfig.ByteSize = this.byteSize;
    serialConfig.fBinary = 1; // must be true
    serialConfig.fDtrControl = 1; // DTR_CONTROL_ENABLE "Enables the DTR line when the device is opened and leaves it on."
    serialConfig.fAbortOnError = 0; // false
    serialConfig.fTXContinueOnXoff = 0; // false

    serialConfig.fParity = 1; // true so that the Parity member is looked at
    switch (this.parity)
    {
    case Parity.Even:
    serialConfig.Parity = 2;
    break;
    case Parity.Mark:
    serialConfig.Parity = 3;
    break;
    case Parity.Odd:
    serialConfig.Parity = 1;
    break;
    case Parity.Space:
    serialConfig.Parity = 4;
    break;
    case Parity.None:
    default:
    serialConfig.Parity = 0;
    break;
    }
    switch (this.stopBits)
    {
    case StopBits.One:
    serialConfig.StopBits = 0;
    break;
    case StopBits.OnePointFive:
    serialConfig.StopBits = 1;
    break;
    case StopBits.Two:
    serialConfig.StopBits = 2;
    break;
    case StopBits.None:
    default:
    throw new ArgumentException("stopBits cannot be StopBits.None");
    }

    if (SetCommState(pHandle, ref serialConfig))
    {
    // set the serial connection timeouts
    COMMTIMEOUTS timeouts = new COMMTIMEOUTS();
    timeouts.ReadIntervalTimeout = 1;
    timeouts.ReadTotalTimeoutMultiplier = 0;
    timeouts.ReadTotalTimeoutConstant = 0;
    timeouts.WriteTotalTimeoutMultiplier = 0;
    timeouts.WriteTotalTimeoutConstant = 0;
    if (SetCommTimeouts(pHandle, ref timeouts))
    {
    return true;
    }
    else
    {
    return false;
    }
    }
    else
    {
    return false;
    }
    }
    else
    {
    return false;
    }
    }

    /// <summary>
    /// Helper that throws a InvalidOperationException if we don't have a serial connection.
    /// </summary>
    private void FailIfNotConnected()
    {
    if (pHandle == IntPtr.Zero)
    throw new InvalidOperationException("You must be connected to the serial port before performing this operation.");
    }
    #endregion

    #region Native Helpers
    #region Native structures
    /// <summary>
    /// Contains the time-out parameters for a communications device.
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    struct COMMTIMEOUTS
    {
    public uint ReadIntervalTimeout;
    public uint ReadTotalTimeoutMultiplier;
    public uint ReadTotalTimeoutConstant;
    public uint WriteTotalTimeoutMultiplier;
    public uint WriteTotalTimeoutConstant;
    }

    /// <summary>
    /// Defines the control setting for a serial communications device.
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    struct DCB
    {
    public int DCBlength;
    public uint BaudRate;
    public uint Flags;
    public ushort wReserved;
    public ushort XonLim;
    public ushort XoffLim;
    public byte ByteSize;
    public byte Parity;
    public byte StopBits;
    public sbyte XonChar;
    public sbyte XoffChar;
    public sbyte ErrorChar;
    public sbyte EofChar;
    public sbyte EvtChar;
    public ushort wReserved1;
    public uint fBinary;
    public uint fParity;
    public uint fOutxCtsFlow;
    public uint fOutxDsrFlow;
    public uint fDtrControl;
    public uint fDsrSensitivity;
    public uint fTXContinueOnXoff;
    public uint fOutX;
    public uint fInX;
    public uint fErrorChar;
    public uint fNull;
    public uint fRtsControl;
    public uint fAbortOnError;
    }
    #endregion

    #region Native Methods
    // Used to get a handle to the serial port so that we can read/write to it.
    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern IntPtr CreateFile(string fileName,
    [MarshalAs(UnmanagedType.U4)] FileAccess fileAccess,
    [MarshalAs(UnmanagedType.U4)] FileShare fileShare,
    IntPtr securityAttributes,
    [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
    int flags,
    IntPtr template);

    // Used to close the handle to the serial port.
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool CloseHandle(IntPtr hObject);

    // Used to get the state of the serial port so that we can configure it.
    [DllImport("kernel32.dll")]
    static extern bool GetCommState(IntPtr hFile, ref DCB lpDCB);

    // Used to configure the serial port.
    [DllImport("kernel32.dll")]
    static extern bool SetCommState(IntPtr hFile, [In] ref DCB lpDCB);

    // Used to set the connection timeouts on our serial connection.
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool SetCommTimeouts(IntPtr hFile, ref COMMTIMEOUTS lpCommTimeouts);

    // Used to read bytes from the serial connection.
    [DllImport("kernel32.dll")]
    static extern bool ReadFile(IntPtr hFile, byte[] lpBuffer,
    int nNumberOfBytesToRead, out int lpNumberOfBytesRead, int lpOverlapped);

    // Used to write bytes to the serial connection.
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool WriteFile(IntPtr hFile, byte[] lpBuffer,
    int nNumberOfBytesToWrite, out int lpNumberOfBytesWritten, int lpOverlapped);

    // Used to flush the I/O buffers.
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool PurgeComm(IntPtr hFile, int dwFlags);
    #endregion
    #endregion
    }
    }

    下面是一个正在运行的 SerialWrapper 示例:
    using (var p = new SerialWrapper(@"\\.\COM12", 9600, SerialWrapper.StopBits.One, SerialWrapper.Parity.None))
    {
    if (!p.Open())
    {
    Console.WriteLine("Unable to connect.");
    return;
    }
    while (true)
    {
    Console.Write(p.ReadString(1024));
    }
    }

    关于asp.net - 与 Silverlight 5 的串行通信(COM 端口),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8989538/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com