加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

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

发布时间:2020-12-16 03:58:17 所属栏目:asp.Net 来源:网络整理
导读:我正在ASP.NET网站上工作,我需要从客户端访问USB设备. 我已经看到Silverlight 5,通过使用P / Invoke,允许我们访问客户端机器上的dll.我计划在我的一个页面中添加一个silverlight控件,它将与我的USB设备进行交互.这样,使用这种设备的每个客户,只需要在我的网
我正在ASP.NET网站上工作,我需要从客户端访问USB设备.

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

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

哪个windows dll会为我提供一个与usb设备交互的好方法?

进一步的信息:

>我需要能够通过COM端口进行通信.典型的串行通信.我该如何设法做到这一点?

出于测试目的,我可以通过像“Hercules”这样的应用程序连接到我的设备,我基本上需要在我的silverlight模块中重新编写这种连接……

你们有什么例子吗?

谢谢你的帮助,

解决方法

我找到了一个包装类,它使我能够在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,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,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 'rn' 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("rn"))
        data += "rn";
      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,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,numBytes);
      string data = Encoding.UTF8.GetString(bytes,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,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));
    }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读