62,254
社区成员
发帖
与我相关
我的任务
分享
public class BLCommPort
{
[DllImport("kernel32.dll")]
private static extern bool GetCommState(
int hFile, //通信设备句柄
ref DCB lpDCB // 设备控制块DCB
);
[DllImport("kernel32.dll")]
private static extern bool BuildCommDCB(
string lpDef, // 设备控制字符串
ref DCB lpDCB // 设备控制块
);
[DllImport("kernel32.dll")]
private static extern bool SetCommState(
int hFile, // 通信设备句柄
ref DCB lpDCB // 设备控制块
);
[DllImport("kernel32.dll")]
private static extern bool GetCommTimeouts(
int hFile, // 通信设备句柄 handle to comm device
ref COMMTIMEOUTS lpCommTimeouts // 超时时间 time-out values
);
[DllImport("kernel32.dll")]
private static extern bool SetCommTimeouts(
int hFile, // 通信设备句柄 handle to comm device
ref COMMTIMEOUTS lpCommTimeouts // 超时时间 time-out values
);
[DllImport("kernel32.dll")]
private static extern bool ReadFile(
int hFile, // 通信设备句柄 handle to file
byte[] lpBuffer, // 数据缓冲区 data buffer
int nNumberOfBytesToRead, // 多少字节等待读取 number of bytes to read
ref int lpNumberOfBytesRead, // 读取多少字节 number of bytes read
ref OVERLAPPED lpOverlapped // 溢出缓冲区 overlapped buffer
);
[DllImport("kernel32.dll")]
private static extern bool WriteFile(
int hFile, // 通信设备句柄 handle to file
byte[] lpBuffer, // 数据缓冲区 data buffer
int nNumberOfBytesToWrite, // 多少字节等待写入 number of bytes to write
ref int lpNumberOfBytesWritten, // 已经写入多少字节 number of bytes written
ref OVERLAPPED lpOverlapped // 溢出缓冲区 overlapped buffer
);
[DllImport("kernel32.dll")]
private static extern bool CloseHandle(
int hObject // handle to object
);
[DllImport("kernel32.dll")]
private static extern uint GetLastError();
public void Open()
{
DCB dcbCommPort = new DCB();
COMMTIMEOUTS ctoCommPort = new COMMTIMEOUTS();
// 打开串口 OPEN THE COMM PORT.
hComm = CreateFile(PortNum, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
// 如果串口没有打开,就打开 IF THE PORT CANNOT BE OPENED, BAIL OUT.
if (hComm == INVALID_HANDLE_VALUE)
{
throw (new ApplicationException("非法操作,不能打开串口!"));
}
// 设置通信超时时间 SET THE COMM TIMEOUTS.
GetCommTimeouts(hComm, ref ctoCommPort);
ctoCommPort.ReadTotalTimeoutConstant = ReadTimeout;
ctoCommPort.ReadTotalTimeoutMultiplier = 0;
ctoCommPort.WriteTotalTimeoutMultiplier = 0;
ctoCommPort.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(hComm, ref ctoCommPort);
// 设置串口 SET BAUD RATE, PARITY, WORD SIZE, AND STOP BITS.
GetCommState(hComm, ref dcbCommPort);
dcbCommPort.BaudRate = BaudRate;
dcbCommPort.flags = 0;
//dcb.fBinary=1;
dcbCommPort.flags |= 1;
if (Parity > 0)
{
//dcb.fParity=1
dcbCommPort.flags |= 2;
}
dcbCommPort.Parity = Parity;
dcbCommPort.ByteSize = ByteSize;
dcbCommPort.StopBits = StopBits;
//if (!BuildCommDCB("9600,n,8,1 ", ref dcbCommPort))
//{
// throw (new ApplicationException("非法操作,不能打开串口! "));
//}
if (!SetCommState(hComm, ref dcbCommPort))
{
//uint ErrorNum=GetLastError();
throw (new ApplicationException("非法操作,不能打开串口!"));
}
//unremark to see if setting took correctly
//DCB dcbCommPort2 = new DCB();
//GetCommState(hComm, ref dcbCommPort2);
Opened = true;
}
public void Close()
{
if (hComm != INVALID_HANDLE_VALUE)
{
CloseHandle(hComm);
}
}
public byte[] Read(int NumBytes)
{
byte[] BufBytes;
byte[] OutBytes;
BufBytes = new byte[NumBytes];
if (hComm != INVALID_HANDLE_VALUE)
{
OVERLAPPED ovlCommPort = new OVERLAPPED();
int BytesRead = 0;
ReadFile(hComm, BufBytes, NumBytes, ref BytesRead, ref ovlCommPort);
OutBytes = new byte[BytesRead];
Array.Copy(BufBytes, OutBytes, BytesRead);
}
else
{
throw (new ApplicationException("串口未打开!"));
}
return OutBytes;
}
public void Write(byte[] WriteBytes)
{
if (hComm != INVALID_HANDLE_VALUE)
{
OVERLAPPED ovlCommPort = new OVERLAPPED();
int BytesWritten = 0;
WriteFile(hComm, WriteBytes, WriteBytes.Length, ref BytesWritten, ref ovlCommPort);
}
else
{
throw (new ApplicationException("串口未打开!"));
}
}
}
class HexCon
{
// 把十六进制字符串转换成字节型和把字节型转换成十六进制字符串 converter hex string to byte and byte to hex string
public static string ByteToString(byte[] InBytes)
{
string StringOut = "";
foreach (byte InByte in InBytes)
{
StringOut = StringOut + String.Format("{0:X2} ", InByte);
}
return StringOut;
}
public static byte[] StringToByte(string InString)
{
string[] ByteStrings;
ByteStrings = InString.Split(" ".ToCharArray());
byte[] ByteOut;
ByteOut = new byte[ByteStrings.Length - 1];
for (int i = 0; i == ByteStrings.Length - 1; i++)
{
ByteOut[i] = Convert.ToByte(("0x" + ByteStrings[i]));
}
return ByteOut;
}
}
public class BLPDUdecoding
{
public string nLength; //要发送内容的长度,由两部分组成,接收手机号加上要发送的内容
/// <summary>
/// 函数功能:短信内容编码
/// 函数名称:smsPDUEncoded(string srvContent)
/// 参 数:srvContent 要进行转换的短信内容,string类型
/// 返 回 值:编码后的短信内容,string类型
/// 函数说明:
/// 1,采用Big-Endian 字节顺序的 Unicode 格式编码,也就说把高低位的互换在这里完成了
/// 2,将转换后的短信内容存进字节数组
/// 3,去掉在进行Unicode格式编码中,两个字节中的"-",例如:00-21,变成0021
/// 4,将整条短信内容的长度除2,保留两位16进制数
/// </summary>
public string smsPDUEncoded(string srvContent)
{
Encoding encodingUTF = System.Text.Encoding.BigEndianUnicode;
string s = null;
byte[] encodedBytes = encodingUTF.GetBytes(srvContent);
for (int i = 0; i < encodedBytes.Length; i++)
{
s += BitConverter.ToString(encodedBytes, i, 1);
}
s = String.Format("{0:X2}{1}", s.Length / 2, s);
return s;
}
/// <summary>
/// 函数功能:短信中心号编码
/// 函数名称:smsDecodedCenterNumber(string srvCenterNumber)
/// 参 数:srvCenterNumber 要进行转换的短信中心号,string类型
/// 返 回 值:编码后的短信中心号,string类型
/// 函数说明:
/// 1,将奇数位和偶数位交换。
/// 2,短信中心号奇偶数交换后,看看长度是否为偶数,如果不是,最后添加F
/// 3,加上短信中心号类型,91为国际化
/// 4,计算编码后的短信中心号长度,并格化成二位的十六进制
/// </summary>
public string smsDecodedCenterNumber(string srvCenterNumber)
{
string s = null;
int nLength = srvCenterNumber.Length;
for (int i = 1; i < nLength; i += 2) //奇偶互换
{
s += srvCenterNumber[i];
s += srvCenterNumber[i - 1];
}
if (!(nLength % 2 == 0)) //是否为偶数,不是就加上F,并对最后一位与加上的F位互换
{
s += 'F';
s += srvCenterNumber[nLength - 1];
}
s = String.Format("91{0}", s); //加上91,代表短信中心类型为国际化
s = String.Format("{0:X2}{1}", s.Length / 2, s); //编码后短信中心号长度,并格式化成二位十六制
return s;
}
/// <summary>
/// 函数功能:接收短信手机号编码
/// 函数名称:smsDecodedNumber(string srvNumber)
/// 参 数:srvCenterNumber 要进行转换的短信中心号,string类型
/// 返 回 值:编码后的接收短信手机号,string类型
/// 函数说明:
/// 1,检查当前接收手机号是否按标准格式书写,不是,就补上“86”
/// 1,将奇数位和偶数位交换。
/// 2,短信中心号奇偶数交换后,看看长度是否为偶数,如果不是,最后添加F
/// </summary>
public string smsDecodedNumber(string srvNumber)
{
string s = null;
if (!(srvNumber.Substring(0, 2) == "86"))
{
srvNumber = String.Format("86{0}", srvNumber); //检查当前接收手机号是否按标准格式书写,不是,就补上“86”
}
int nLength = srvNumber.Length;
for (int i = 1; i < nLength; i += 2) //将奇数位和偶数位交换
{
s += srvNumber[i];
s += srvNumber[i - 1];
}
if (!(nLength % 2 == 0)) //是否为偶数,不是就加上F,并对最后一位与加上的F位互换
{
s += 'F';
s += srvNumber[nLength - 1];
}
return s;
}
/// <summary>
/// 函数功能:整个短信的编码
/// 函数名称:smsDecodedsms(string strCenterNumber, string strNumber, string strSMScontent)
/// 参 数:strCenterNumber 要进行转换的短信中心号,string类型
/// strNumber 接收手机号码,string类型
/// strSMScontent 短信内容
/// 返 回 值:完整的短信编码,可以在AT指令中执行,string类型
/// 函数说明:
/// 11000D91和000800 在国内,根据PDU编码原则,我们写死在此,详细解释请看我的文章
/// </summary>
public string smsDecodedsms(string strCenterNumber, string strNumber, string strSMScontent)
{
string s = String.Format("{0}11000D91{1}000800{2}", smsDecodedCenterNumber(strCenterNumber), smsDecodedNumber(strNumber), smsPDUEncoded(strSMScontent));
nLength = String.Format("{0:D2}", (s.Length - smsDecodedCenterNumber(strCenterNumber).Length) / 2); //获取短信内容加上手机号码长度
return s;
}
}