📄 commbase.cs
字号:
//JH 1.1: Avoid use of GetHandleInformation for W98 compatability.
if (hPort != (System.IntPtr)Win32Com.INVALID_HANDLE_VALUE) return true;
ThrowException("Offline");
return false;
}
else
{
if (auto)
{
if (Open()) return true;
}
ThrowException("Offline");
return false;
}
}
}
/// <summary>
/// Overlays CommBase to provide line or packet oriented communications to derived classes. Strings
/// are sent and received and the Transact method is added which transmits a string and then blocks until
/// a reply string has been received (subject to a timeout).
/// </summary>
public abstract class CommLine : CommBase {
private byte[] RxBuffer;
private uint RxBufferP = 0;
private ASCII RxTerm;
private ASCII[] TxTerm;
private ASCII[] RxFilter;
private string RxString = "";
private ManualResetEvent TransFlag = new ManualResetEvent(true);
private uint TransTimeout;
/// <summary>
/// Extends CommBaseSettings to add the settings used by CommLine.
/// </summary>
public class CommLineSettings : CommBase.CommBaseSettings
{
/// <summary>
/// Maximum size of received string (default: 256)
/// </summary>
public int rxStringBufferSize = 256;
/// <summary>
/// ASCII code that terminates a received string (default: CR)
/// </summary>
public ASCII rxTerminator = ASCII.CR;
/// <summary>
/// ASCII codes that will be ignored in received string (default: null)
/// </summary>
public ASCII[] rxFilter;
/// <summary>
/// Maximum time (ms) for the Transact method to complete (default: 500)
/// </summary>
public int transactTimeout = 500;
/// <summary>
/// ASCII codes transmitted after each Send string (default: null)
/// </summary>
public ASCII[] txTerminator;
public static new CommLineSettings LoadFromXML(Stream s)
{
return (CommLineSettings)LoadFromXML(s, typeof(CommLineSettings));
}
}
/// <summary>
/// Queue the ASCII representation of a string and then the set terminator bytes for sending.
/// </summary>
/// <param name="toSend">String to be sent.</param>
protected void Send(string toSend)
{
//JH 1.1: Use static encoder for efficiency. Thanks to Prof. Dr. Peter Jesorsky!
uint l = (uint)Encoding.ASCII.GetByteCount(toSend);
if (TxTerm != null) l += (uint)TxTerm.GetLength(0);
byte[] b = new byte[l];
byte[] s = Encoding.ASCII.GetBytes(toSend);
int i;
for (i = 0; (i <= s.GetUpperBound(0)); i++) b[i] = s[i];
if (TxTerm != null) for (int j = 0; (j <= TxTerm.GetUpperBound(0)); j++, i++) b[i] = (byte)TxTerm[j];
Send(b);
}
/// <summary>
/// Transmits the ASCII representation of a string followed by the set terminator bytes and then
/// awaits a response string.
/// </summary>
/// <param name="toSend">The string to be sent.</param>
/// <returns>The response string.</returns>
protected string Transact(string toSend) {
Send(toSend);
TransFlag.Reset();
if (!TransFlag.WaitOne((int)TransTimeout, false)) ThrowException("Timeout");
string s;
lock(RxString) {s = RxString;}
return s;
}
/// <summary>
/// If a derived class overrides ComSettings(), it must call this prior to returning the settings to
/// the base class.
/// </summary>
/// <param name="s">Class containing the appropriate settings.</param>
protected void Setup(CommLineSettings s) {
RxBuffer = new byte[s.rxStringBufferSize];
RxTerm = s.rxTerminator;
RxFilter = s.rxFilter;
TransTimeout = (uint)s.transactTimeout;
TxTerm = s.txTerminator;
}
/// <summary>
/// Override this to process unsolicited input lines (not a result of Transact).
/// </summary>
/// <param name="s">String containing the received ASCII text.</param>
protected virtual void OnRxLine(string s) {}
protected override void OnRxChar(byte ch) {
ASCII ca = (ASCII)ch;
if ((ca == RxTerm) || (RxBufferP > RxBuffer.GetUpperBound(0))) {
//JH 1.1: Use static encoder for efficiency. Thanks to Prof. Dr. Peter Jesorsky!
lock(RxString) {RxString = Encoding.ASCII.GetString(RxBuffer, 0, (int)RxBufferP);}
RxBufferP = 0;
if (TransFlag.WaitOne(0,false)) {
OnRxLine(RxString);
} else {
TransFlag.Set();
}
} else {
bool wr = true;
if (RxFilter != null) {
for (int i=0; i <= RxFilter.GetUpperBound(0); i++) if (RxFilter[i] == ca) wr = false;
}
if (wr) {
RxBuffer[RxBufferP] = ch;
RxBufferP++;
}
}
}
}
/// <summary>
/// Exception used for all errors.
/// </summary>
public class CommPortException : ApplicationException
{
/// <summary>
/// Constructor for raising direct exceptions
/// </summary>
/// <param name="desc">Description of error</param>
public CommPortException(string desc) : base(desc) {}
/// <summary>
/// Constructor for re-raising exceptions from receive thread
/// </summary>
/// <param name="e">Inner exception raised on receive thread</param>
public CommPortException(Exception e) : base("Receive Thread Exception", e) {}
}
internal class Win32Com {
/// <summary>
/// Opening Testing and Closing the Port Handle.
/// </summary>
[DllImport("kernel32.dll", SetLastError=true)]
internal static extern IntPtr CreateFile(String lpFileName, UInt32 dwDesiredAccess, UInt32 dwShareMode,
IntPtr lpSecurityAttributes, UInt32 dwCreationDisposition, UInt32 dwFlagsAndAttributes,
IntPtr hTemplateFile);
//Constants for errors:
internal const UInt32 ERROR_FILE_NOT_FOUND = 2;
internal const UInt32 ERROR_INVALID_NAME = 123;
internal const UInt32 ERROR_ACCESS_DENIED = 5;
internal const UInt32 ERROR_IO_PENDING = 997;
internal const UInt32 ERROR_IO_INCOMPLETE = 996;
//Constants for return value:
internal const Int32 INVALID_HANDLE_VALUE = -1;
//Constants for dwFlagsAndAttributes:
internal const UInt32 FILE_FLAG_OVERLAPPED = 0x40000000;
//Constants for dwCreationDisposition:
internal const UInt32 OPEN_EXISTING = 3;
//Constants for dwDesiredAccess:
internal const UInt32 GENERIC_READ = 0x80000000;
internal const UInt32 GENERIC_WRITE = 0x40000000;
[DllImport("kernel32.dll")]
internal static extern Boolean CloseHandle(IntPtr hObject);
/// <summary>
/// Manipulating the communications settings.
/// </summary>
[DllImport("kernel32.dll")]
internal static extern Boolean GetCommState(IntPtr hFile, ref DCB lpDCB);
[DllImport("kernel32.dll")]
internal static extern Boolean GetCommTimeouts(IntPtr hFile, out COMMTIMEOUTS lpCommTimeouts);
[DllImport("kernel32.dll")]
internal static extern Boolean BuildCommDCBAndTimeouts(String lpDef, ref DCB lpDCB, ref COMMTIMEOUTS lpCommTimeouts);
[DllImport("kernel32.dll")]
internal static extern Boolean SetCommState(IntPtr hFile, [In] ref DCB lpDCB);
[DllImport("kernel32.dll")]
internal static extern Boolean SetCommTimeouts(IntPtr hFile, [In] ref COMMTIMEOUTS lpCommTimeouts);
[DllImport("kernel32.dll")]
internal static extern Boolean SetupComm(IntPtr hFile, UInt32 dwInQueue, UInt32 dwOutQueue);
[StructLayout( LayoutKind.Sequential )] internal struct COMMTIMEOUTS
{
//JH 1.1: Changed Int32 to UInt32 to allow setting to MAXDWORD
internal UInt32 ReadIntervalTimeout;
internal UInt32 ReadTotalTimeoutMultiplier;
internal UInt32 ReadTotalTimeoutConstant;
internal UInt32 WriteTotalTimeoutMultiplier;
internal UInt32 WriteTotalTimeoutConstant;
}
//JH 1.1: Added to enable use of "return immediately" timeout.
internal const UInt32 MAXDWORD = 0xffffffff;
[StructLayout( LayoutKind.Sequential )] internal struct DCB
{
internal Int32 DCBlength;
internal Int32 BaudRate;
internal Int32 PackedValues;
internal Int16 wReserved;
internal Int16 XonLim;
internal Int16 XoffLim;
internal Byte ByteSize;
internal Byte Parity;
internal Byte StopBits;
internal Byte XonChar;
internal Byte XoffChar;
internal Byte ErrorChar;
internal Byte EofChar;
internal Byte EvtChar;
internal Int16 wReserved1;
internal void init(bool parity, bool outCTS, bool outDSR, int dtr, bool inDSR, bool txc, bool xOut,
bool xIn, int rts)
{
//JH 1.3: Was 0x8001 ans so not setting fAbortOnError - Thanks Larry Delby!
DCBlength = 28; PackedValues = 0x4001;
if (parity) PackedValues |= 0x0002;
if (outCTS) PackedValues |= 0x0004;
if (outDSR) PackedValues |= 0x0008;
PackedValues |= ((dtr & 0x0003) << 4);
if (inDSR) PackedValues |= 0x0040;
if (txc) PackedValues |= 0x0080;
if (xOut) PackedValues |= 0x0100;
if (xIn) PackedValues |= 0x0200;
PackedValues |= ((rts & 0x0003) << 12);
}
}
/// <summary>
/// Reading and writing.
/// </summary>
[DllImport("kernel32.dll", SetLastError=true)]
internal static extern Boolean WriteFile(IntPtr fFile, Byte[] lpBuffer, UInt32 nNumberOfBytesToWrite,
out UInt32 lpNumberOfBytesWritten, IntPtr lpOverlapped);
[StructLayout( LayoutKind.Sequential )] internal struct OVERLAPPED
{
internal UIntPtr Internal;
internal UIntPtr InternalHigh;
internal UInt32 Offset;
internal UInt32 OffsetHigh;
internal IntPtr hEvent;
}
[DllImport("kernel32.dll")]
internal static extern Boolean SetCommMask(IntPtr hFile, UInt32 dwEvtMask);
// Constants for dwEvtMask:
internal const UInt32 EV_RXCHAR = 0x0001;
internal const UInt32 EV_RXFLAG = 0x0002;
internal const UInt32 EV_TXEMPTY = 0x0004;
internal const UInt32 EV_CTS = 0x0008;
internal const UInt32 EV_DSR = 0x0010;
internal const UInt32 EV_RLSD = 0x0020;
internal const UInt32 EV_BREAK = 0x0040;
internal const UInt32 EV_ERR = 0x0080;
internal const UInt32 EV_RING = 0x0100;
internal const UInt32 EV_PERR = 0x0200;
internal const UInt32 EV_RX80FULL = 0x0400;
internal const UInt32 EV_EVENT1 = 0x0800;
internal const UInt32 EV_EVENT2 = 0x1000;
[DllImport("kernel32.dll", SetLastError=true)]
internal static extern Boolean WaitCommEvent(IntPtr hFile, IntPtr lpEvtMask, IntPtr lpOverlapped);
[DllImport("kernel32.dll")]
internal static extern Boolean CancelIo(IntPtr hFile);
[DllImport("kernel32.dll", SetLastError=true)]
internal static extern Boolean ReadFile(IntPtr hFile, [Out] Byte[] lpBuffer, UInt32 nNumberOfBytesToRead,
out UInt32 nNumberOfBytesRead, IntPtr lpOverlapped);
[DllImport("kernel32.dll")]
internal static extern Boolean TransmitCommChar(IntPtr hFile, Byte cChar);
/// <summary>
/// Control port functions.
/// </summary>
[DllImport("kernel32.dll")]
internal static extern Boolean EscapeCommFunction(IntPtr hFile, UInt32 dwFunc);
// Constants for dwFunc:
internal const UInt32 SETXOFF = 1;
internal const UInt32 SETXON = 2;
internal const UInt32 SETRTS = 3;
internal const UInt32 CLRRTS = 4;
internal const UInt32 SETDTR = 5;
internal const UInt32 CLRDTR = 6;
internal const UInt32 RESETDEV = 7;
internal const UInt32 SETBREAK = 8;
internal const UInt32 CLRBREAK = 9;
[DllImport("kernel32.dll")]
internal static extern Boolean GetCommModemStatus(IntPtr hFile, out UInt32 lpModemStat);
// Constants for lpModemStat:
internal const UInt32 MS_CTS_ON = 0x0010;
internal const UInt32 MS_DSR_ON = 0x0020;
internal const UInt32 MS_RING_ON = 0x0040;
internal const UInt32 MS_RLSD_ON = 0x0080;
/// <summary>
/// Status Functions.
/// </summary>
[DllImport("kernel32.dll", SetLastError=true)]
internal static extern Boolean GetOverlappedResult(IntPtr hFile, IntPtr lpOverlapped,
out UInt32 nNumberOfBytesTransferred, Boolean bWait);
[DllImport("kernel32.dll")]
internal static extern Boolean ClearCommError(IntPtr hFile, out UInt32 lpErrors, IntPtr lpStat);
[DllImport("kernel32.dll")]
internal static extern Boolean ClearCommError(IntPtr hFile, out UInt32 lpErrors, out COMSTAT cs);
//Constants for lpErrors:
internal const UInt32 CE_RXOVER = 0x0001;
internal const UInt32 CE_OVERRUN = 0x0002;
internal const UInt32 CE_RXPARITY = 0x0004;
internal const UInt32 CE_FRAME = 0x0008;
internal const UInt32 CE_BREAK = 0x0010;
internal const UInt32 CE_TXFULL = 0x0100;
internal const UInt32 CE_PTO = 0x0200;
internal const UInt32 CE_IOE = 0x0400;
internal const UInt32 CE_DNS = 0x0800;
internal const UInt32 CE_OOP = 0x1000;
internal const UInt32 CE_MODE = 0x8000;
[StructLayout( LayoutKind.Sequential )] internal struct COMSTAT
{
internal const uint fCtsHold = 0x1;
internal const uint fDsrHold = 0x2;
internal const uint fRlsdHold = 0x4;
internal const uint fXoffHold = 0x8;
internal const uint fXoffSent = 0x10;
internal const uint fEof = 0x20;
internal const uint fTxim = 0x40;
internal UInt32 Flags;
internal UInt32 cbInQue;
internal UInt32 cbOutQue;
}
[DllImport("kernel32.dll")]
internal static extern Boolean GetCommProperties(IntPtr hFile, out COMMPROP cp);
[StructLayout( LayoutKind.Sequential )] internal struct COMMPROP
{
internal UInt16 wPacketLength;
internal UInt16 wPacketVersion;
internal UInt32 dwServiceMask;
internal UInt32 dwReserved1;
internal UInt32 dwMaxTxQueue;
internal UInt32 dwMaxRxQueue;
internal UInt32 dwMaxBaud;
internal UInt32 dwProvSubType;
internal UInt32 dwProvCapabilities;
internal UInt32 dwSettableParams;
internal UInt32 dwSettableBaud;
internal UInt16 wSettableData;
internal UInt16 wSettableStopParity;
internal UInt32 dwCurrentTxQueue;
internal UInt32 dwCurrentRxQueue;
internal UInt32 dwProvSpec1;
internal UInt32 dwProvSpec2;
internal Byte wcProvChar;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -