C#通用类库--短信猫操作类1(原始AT命令)
生活随笔
收集整理的這篇文章主要介紹了
C#通用类库--短信猫操作类1(原始AT命令)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一個C#資源分享平臺,專業分享學習高質量代碼,每周期布置學習任務,激發學習C#興趣!(QQ群:128874886)?
//作用:短信貓類
//作者:劉典武修正(通用于深圳百億科技GSM)
//時間:2011-03-01
//說明:來源于博客園(修正)
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.IO.Ports;
namespace myClassLibrary
{
??? public enum MsgType { AUSC2, A7Bit };//枚舉 短信類型 AUSC2 A7Bit:7位編碼 (中文用AUSC2,英文都可以 但7Bit能發送160字符,USC2僅70)
??? public class myGSM
??? {
??????? #region? 構造函數
??????? /// <summary>
??????? /// 無參數構造函數 完成有關初始化工作
??????? /// </summary>
??????? public myGSM()
??????? {
??????????? this.msgCenter = string.Empty;
??????????? this.sp = new SerialPort();
??????????? this.sp.ReadTimeout = -1;//讀超時時間 發送短信時間的需要
??????????? this.sp.RtsEnable = true;//必須為true 這樣串口才能接收到數據
??????????? this.sp.DataReceived += new SerialDataReceivedEventHandler(this.sp_DataReceived);
??????? }
??????? /// <summary>
??????? /// 構造函數
??????? /// </summary>
??????? /// <param name="comPort">串口號</param>
??????? /// <param name="baudRate">波特率</param>
??????? public myGSM(string comPort, int baudRate)
??????? {
??????????? this.msgCenter = string.Empty;
??????????? this.sp = new SerialPort();
??????????? this.sp.PortName = comPort;
??????????? this.sp.BaudRate = baudRate;
??????????? this.sp.ReadTimeout = -1;//讀超時時間 發送短信時間的需要
??????????? this.sp.RtsEnable = true;//必須為true 這樣串口才能接收到數據
??????????? this.sp.DataReceived += new SerialDataReceivedEventHandler(this.sp_DataReceived);
??????? }
??????? #endregion
??????? #region? 私有變量
??????? private SerialPort sp;
??????? private bool autoDelMsg = false;//是否自動刪除短消息
??????? private string msgCenter = string.Empty;//服務中心號碼
??????? private int newMsgIndex;//新消息序號
??????? #endregion
??????? #region 屬性
??????? /// <summary>
??????? /// 是否自動刪除短信(默認為false)
??????? /// </summary>
??????? public bool AutoDelMsg
??????? {
??????????? get { return this.autoDelMsg; }
??????????? set { this.autoDelMsg = value; }
??????? }
??????? /// <summary>
??????? /// 波特率 運行時只讀 設備打開狀態寫入將引發異常
??????? /// </summary>
??????? public int BaudRate
??????? {
??????????? get { return this.sp.BaudRate; }
??????????? set { this.sp.BaudRate = value; }
??????? }
??????? /// <summary>
??????? /// 串口號 運行時只讀 設備打開狀態寫入將引發異常
??????? /// 提供對串口端口號的訪問
??????? /// </summary>
??????? public string ComPort
??????? {
??????????? get { return this.sp.PortName; }
??????????? set { try { this.sp.PortName = value; } catch (Exception ex) { throw ex; } }
??????? }
??????? /// <summary>
??????? /// 設備是否打開
??????? /// </summary>
??????? public bool IsOpen
??????? {
??????????? get { return this.sp.IsOpen; }
??????? }
??????? #endregion
??????? #region? 方法
??????? /// <summary>
??????? /// 設置服務中心號碼
??????? /// </summary>
??????? /// <param name="msgCenterNo"></param>
??????? public void SetMsgCenterNo(string msgCenterNo)
??????? {
??????????? this.msgCenter = msgCenterNo;
??????? }
??????? /// <summary>
??????? /// 獲取機器碼
??????? /// </summary>
??????? /// <returns></returns>
??????? public string GetMachineNo()
??????? {
??????????? string temp = this.SendAT("AT+CGMI");
??????????? if (temp.Substring(temp.Length - 4, 3).Trim() == "OK")
??????????? {
??????????????? temp = temp.Split('\r')[2].Trim();
??????????? }
??????????? else
??????????? {
??????????????? throw new Exception("獲取機器碼失敗");
??????????? }
??????????? return temp;
??????? }
??????? /// <summary>
??????? /// 獲取短信中心號碼
??????? /// </summary>
??????? /// <returns></returns>
??????? public string GetMsgCenterNo()
??????? {
??????????? string temp = string.Empty;
??????????? if (msgCenter != null && msgCenter.Length != 0)
??????????? {
??????????????? return msgCenter;
??????????? }
??????????? else
??????????? {
??????????????? temp = this.SendAT("AT+CSCA?");
??????????????? if (temp.Substring(temp.Length - 4, 3).Trim() == "OK")
??????????????? {
??????????????????? return temp.Split('\"')[1].Trim();
??????????????? }
??????????????? else
??????????????? {
??????????????????? throw new Exception("獲取短信中心失敗");
??????????????? }
??????????? }
??????? }
??????? /// <summary>
??????? /// 取得未讀信息列表
??????? /// </summary>
??????? /// <returns>未讀信息列表(中心號碼,手機號碼,發送時間,短信內容)</returns>
??????? public string[] GetUnReadMsg()
??????? {
??????????? string[] result = new string[255];//存儲255條短信,一般手機上面存儲的短信少于這個數
??????????? string[] temp = null;
??????????? string tt = string.Empty;
??????????? tt = this.SendAT("AT+CMGL=0");//讀取未讀信息
??????????? if (tt.Substring(tt.Length - 4, 3).Trim() == "OK")
??????????? {
??????????????? temp = tt.Split('\r');
??????????? }
??????????? PDUEncoding pe = new PDUEncoding();
??????????? int i = 0;//計數
??????????? foreach (string str in temp)
??????????? {
??????????????? if (str != null && str.Length != 0 && str.Substring(0, 2).Trim() != "+C" && str.Substring(0, 2) != "OK" && str.Substring(0, 2) != "AT")
??????????????? {
??????????????????? result[i] = pe.PDUDecoder(str);
??????????????????? i++;
??????????????? }
??????????? }
??????????? return result;
??????? }
??????? /// <summary>
??????? /// 取得已讀信息列表
??????? /// </summary>
??????? /// <returns>已讀信息列表(中心號碼,手機號碼,發送時間,短信內容)</returns>
??????? public string[] GetIsReadMsg()
??????? {
??????????? string[] result = new string[255];//存儲255條短信,一般手機上面存儲的短信少于這個數
??????????? string[] temp = null;
??????????? string tt = string.Empty;
??????????? tt = this.SendAT("AT+CMGL=1");//讀取已讀信息
??????????? if (tt.Substring(tt.Length - 4, 3).Trim() == "OK")
??????????? {
??????????????? temp = tt.Split('\r');
??????????? }
??????????? PDUEncoding pe = new PDUEncoding();
??????????? int i = 0;//計數
??????????? foreach (string str in temp)
??????????? {
??????????????? if (str != null && str.Length != 0 && str.Substring(0, 2).Trim() != "+C" && str.Substring(0, 2) != "OK" && str.Substring(0, 2) != "AT")
??????????????? {
??????????????????? result[i] = pe.PDUDecoder(str);
??????????????????? i++;
??????????????? }
??????????? }
??????????? return result;
??????? }
??????? /// <summary>
??????? /// 取得待發信息列表
??????? /// </summary>
??????? /// <returns>待發信息列表(中心號碼,手機號碼,發送時間,短信內容)</returns>
??????? public string[] GetUnSendMsg()
??????? {
??????????? string[] result = new string[255];//存儲255條短信,一般手機上面存儲的短信少于這個數
??????????? string[] temp = null;
??????????? string tt = string.Empty;
??????????? tt = this.SendAT("AT+CMGL=2");//讀取待發信息
??????????? if (tt.Substring(tt.Length - 4, 3).Trim() == "OK")
??????????? {
??????????????? temp = tt.Split('\r');
??????????? }
??????????? PDUEncoding pe = new PDUEncoding();
??????????? int i = 0;//計數
??????????? foreach (string str in temp)
??????????? {
??????????????? if (str != null && str.Length != 0 && str.Substring(0, 2).Trim() != "+C" && str.Substring(0, 2) != "OK" && str.Substring(0, 2) != "AT")
??????????????? {
??????????????????? result[i] = pe.PDUDecoder(str);
??????????????????? i++;
??????????????? }
??????????? }
??????????? return result;
??????? }
??????? /// <summary>
??????? /// 取得已發信息列表
??????? /// </summary>
??????? /// <returns>已發信息列表(中心號碼,手機號碼,發送時間,短信內容)</returns>
??????? public string[] GetIsSendMsg()
??????? {
??????????? string[] result = new string[255];//存儲255條短信,一般手機上面存儲的短信少于這個數
??????????? string[] temp = null;
??????????? string tt = string.Empty;
??????????? tt = this.SendAT("AT+CMGL=3");//讀取已發信息
??????????? if (tt.Substring(tt.Length - 4, 3).Trim() == "OK")
??????????? {
??????????????? temp = tt.Split('\r');
??????????? }
??????????? PDUEncoding pe = new PDUEncoding();
??????????? int i = 0;//計數
??????????? foreach (string str in temp)
??????????? {
??????????????? if (str != null && str.Length != 0 && str.Substring(0, 2).Trim() != "+C" && str.Substring(0, 2) != "OK" && str.Substring(0, 2) != "AT")
??????????????? {
??????????????????? result[i] = pe.PDUDecoder(str);
??????????????????? i++;
??????????????? }
??????????? }
??????????? return result;
??????? }
??????? /// <summary>
??????? /// 獲取所有信息
??????? /// </summary>
??????? /// <returns></returns>
??????? public string[] GetAllMsg()
??????? {
??????????? string[] result = new string[255];//存儲255條短信,一般手機上面存儲的短信少于這個數
??????????? string[] temp = null;
??????????? string tt = string.Empty;
??????????? tt = this.SendAT("AT+CMGL=4");//讀取未讀信息
??????????? if (tt.Substring(tt.Length - 4, 3).Trim() == "OK")
??????????? {
??????????????? temp = tt.Split('\r');
??????????? }
??????????? PDUEncoding pe = new PDUEncoding();
??????????? int i = 0;//計數
??????????? foreach (string str in temp)
??????????? {
??????????????? if (str != null && str.Length != 0 && str.Substring(0, 2).Trim() != "+C" && str.Substring(0, 2) != "OK" && str.Substring(0, 2) != "AT")
??????????????? {
??????????????????? result[i] = pe.PDUDecoder(str);
??????????????????? i++;
??????????????? }
??????????? }
??????????? return result;
??????? }
??????? /// <summary>
??????? /// 讀取設備新收到的短消息
??????? /// </summary>
??????? /// <returns></returns>
??????? public string ReadNewMsg()
??????? {
??????????? return ReadMsgByIndex(newMsgIndex);
??????? }
??????? /// <summary>
??????? /// 發送AT命令
??????? /// </summary>
??????? /// <param name="ATCom">AT命令</param>
??????? /// <returns></returns>
??????? public string SendAT(string ATCom)
??????? {
??????????? string str = string.Empty;
??????????? //忽略接收緩沖區內容,準備發送
??????????? this.sp.DiscardInBuffer();
??????????? //注銷事件關聯,為發送做準備
??????????? this.sp.DataReceived -= this.sp_DataReceived;
??????????? try
??????????? {
??????????????? this.sp.Write(ATCom + "\r");
??????????? }
??????????? catch (Exception ex)
??????????? {
??????????????? this.sp.DataReceived += this.sp_DataReceived;
??????????????? throw ex;
??????????? }
??????????? try
??????????? {
??????????????? string temp = string.Empty;
??????????????? while ((temp.Trim() != "OK") && (temp.Trim() != "ERROR"))
??????????????? {
??????????????????? temp = this.sp.ReadLine();
??????????????????? str += temp;
??????????????? }
??????????? }
??????????? catch (Exception ex)
??????????? {
??????????????? throw ex;
??????????? }
??????????? finally
??????????? {
??????????????? this.sp.DataReceived += this.sp_DataReceived;
??????????? }
??????????? return str;
??????? }
??????? /// <summary>
??????? /// 發送短信????? ?
??????? /// </summary>
??????? /// <param name="phone">手機號碼</param>
??????? /// <param name="msg">短信內容</param>
??????? public bool SendMsg(string phone, string msg)
??????? {
??????????? string temp = "0011000D91" + this.reverserNumber(phone) + "000801" + this.contentEncoding(msg) + Convert.ToChar(26).ToString();
??????????? string len = this.getLenght(msg);//計算長度
??????????? try
??????????? {
??????????????? this.sp.DataReceived -= sp_DataReceived;
??????????????? this.sp.Write("AT+CMGS=" + len + "\r");
??????????????? this.sp.ReadTo(">");
??????????????? this.sp.DiscardInBuffer();
??????????????? //事件重新綁定 正常監視串口數據
??????????????? this.sp.DataReceived += sp_DataReceived;
??????????????? temp = this.SendAT(temp);
??????????????? if (temp.Substring(temp.Length - 4, 3).Trim() != "OK")
??????????????? {
??????????????????? return false;
??????????????? }
??????????????? else
??????????????? {
??????????????????? return true;
??????????????? }
??????????? }
??????????? catch { return false; }
??????? }
??????? #region? 自定義方法
??????? //獲取短信內容的字節數
??????? private string getLenght(string txt)
??????? {
??????????? int i = 0;
??????????? string s = "";
??????????? i = txt.Length * 2;
??????????? i += 15;
??????????? s = i.ToString();
??????????? return s;
??????? }
??????? //將手機號碼轉換為內存編碼
??????? private string reverserNumber(string phone)
??????? {
??????????? string str = "";
??????????? //檢查手機號碼是否按照標準格式寫,如果不是則補上
??????????? if (phone.Substring(0, 2) != "86")
??????????? {
??????????????? phone = string.Format("86{0}", phone);
??????????? }
??????????? char[] c = this.getChar(phone);
??????????? for (int i = 0; i <= c.Length - 2; i += 2)
??????????? {
??????????????? str += c[i + 1].ToString() + c[i].ToString();
??????????? }
??????????? return str;
??????? }
??????? //漢字解碼為16進制
??????? private string contentEncoding(string content)
??????? {
??????????? Encoding encodingUTF = System.Text.Encoding.BigEndianUnicode;
??????????? string s = "";
??????????? byte[] encodeByte = encodingUTF.GetBytes(content);
??????????? for (int i = 0; i <= encodeByte.Length - 1; i++)
??????????? {
??????????????? s += BitConverter.ToString(encodeByte, i, 1);
??????????? }
??????????? s = string.Format("{0:X2}{1}", s.Length / 2, s);
??????????? return s;
??????? }
??????? private char[] getChar(string phone)
??????? {
??????????? if (phone.Length % 2 == 0)
??????????? {
??????????????? return Convert.ToString(phone).ToCharArray();
??????????? }
??????????? else
??????????? {
??????????????? return Convert.ToString(phone + "F").ToCharArray();
??????????? }
??????? }
??????? #endregion
??????? /// <summary>
??????? /// 發送短信 (重載)
??????? /// </summary>
??????? /// <param name="phone">手機號碼</param>
??????? /// <param name="msg">短信內容</param>
??????? /// <param name="msgType">短信類型</param>
??????? public void SendMsg(string phone, string msg, MsgType msgType)
??????? {
??????????? if (msgType == MsgType.AUSC2)
??????????? {
??????????????? SendMsg(phone, msg);
??????????? }
??????????? else
??????????? {
??????????????? PDUEncoding pe = new PDUEncoding();
??????????????? pe.ServiceCenterAddress = msgCenter;??????????????????? //短信中心號碼 服務中心地址
??????????????? string temp = pe.PDU7BitEncoder(phone, msg);
??????????????? int len = (temp.Length - Convert.ToInt32(temp.Substring(0, 2), 16) * 2 - 2) / 2;? //計算長度
??????????????? try
??????????????? {
??????????????????? temp = SendAT("AT+CMGS=" + len.ToString() + "\r" + temp + (char)(26));? //26 Ctrl+Z ascii碼
??????????????? }
??????????????? catch (Exception)
??????????????? {
??????????????????? throw new Exception("短信發送失敗");
??????????????? }
??????????????? if (temp.Substring(temp.Length - 4, 3).Trim() == "OK")
??????????????? {
??????????????????? return;
??????????????? }
??????????????? throw new Exception("短信發送失敗");
??????????? }
??????? }
??????? /// <summary>
??????? /// 關閉設備
??????? /// </summary>
??????? public void CloseComm()
??????? {
??????????? try
??????????? {
??????????????? this.sp.Close();
??????????? }
??????????? catch (Exception ex)
??????????? {
??????????????? throw ex;
??????????? }
??????? }
??????? /// <summary>
??????? /// 打開設備
??????? /// </summary>
??????? public void OpenComm()
??????? {
??????????? try
??????????? {
??????????????? this.sp.Open();
??????????? }
??????????? catch (Exception ex)
??????????? {
??????????????? throw ex;
??????????? }
??????????? if (this.sp.IsOpen)
??????????? {
??????????????? //this.sp.DataReceived -= this.sp_DataReceived;
??????????????? //this.sp.Write("AT\r");
??????????????? //Thread.Sleep(100);
??????????????? //string s = this.sp.ReadExisting().Trim();
??????????????? //s = s.Substring(s.Length - 2, 2);
??????????????? //if (s != "OK")
??????????????? //{
??????????????? //??? throw new Exception("硬件連接錯誤");
??????????????? //}
??????????????? try
??????????????? {
??????????????????? this.SendAT("AT+CMGF=0");//選擇短消息格式默認為PDU
??????????????????? Thread.Sleep(100);
??????????????????? this.SendAT("AT+CNMI=2,1");//選擇當有新短消息來時提示方式
??????????????????? Thread.Sleep(100);
??????????????? }
??????????????? catch { }
??????????? }
??????? }
??????? /// <summary>
??????? /// 撥打電話
??????? /// </summary>
??????? /// <param name="telNum">電話號碼</param>
??????? public void Call(string telNum)
??????? {
??????????? try
??????????? {
??????????????? this.SendAT("ATD" + telNum + ";");
??????????? }
??????????? catch (Exception ex)
??????????? {
??????????????? throw ex;
??????????? }
??????? }
??????? /// <summary>
??????? /// 按序號讀取短信
??????? /// </summary>
??????? /// <param name="index">序號</param>
??????? /// <param name="msgCenter">短信中心</param>
??????? /// <param name="phone">發送方手機號碼</param>
??????? /// <param name="msg">短信內容</param>
??????? /// <param name="time">時間字符串</param>
??????? public void ReadMsgByIndex(int index, out string msgCenter, out string phone, out string msg, out string time)
??????? {
??????????? string temp = string.Empty;
??????????? PDUEncoding pe = new PDUEncoding();
??????????? try
??????????? {
??????????????? temp = SendAT("AT+CMGR=" + index.ToString() + "\r");
??????????? }
??????????? catch (Exception ex)
??????????? {
??????????????? throw ex;
??????????? }
??????????? if (temp.Trim() == "ERROR")
??????????? {
??????????????? throw new Exception("沒有此短信");
??????????? }
??????????? temp = temp.Split((char)(13))[2];?????? //取出PDU串(char)(13)為0x0a即\r 按\r分為多個字符串 第3個是PDU串
??????????? pe.PDUDecoder(temp, out msgCenter, out phone, out msg, out time);
??????? }
??????? /// <summary>
??????? /// 按序號讀取短信
??????? /// </summary>
??????? /// <param name="index">序號</param>
??????? /// <returns>信息字符串 (中心號碼,手機號碼,發送時間,短信內容)</returns>
??????? public string ReadMsgByIndex(int index)
??????? {
??????????? string temp = string.Empty;
??????????? string msgCenter, phone, msg, time;
??????????? PDUEncoding pe = new PDUEncoding();
??????????? try
??????????? {
??????????????? temp = SendAT("AT+CMGR=" + index.ToString());
??????????? }
??????????? catch (Exception ex)
??????????? {
??????????????? throw ex;
??????????? }
??????????? if (temp.Trim() == "ERROR")
??????????? {
??????????????? throw new Exception("沒有此短信");
??????????? }
??????????? temp = temp.Split((char)(13))[3];?????? //取出PDU串(char)(13)為0x0a即\r 按\r分為多個字符串 第3個是PDU串
??????????? pe.PDUDecoder(temp, out msgCenter, out phone, out msg, out time);
??????????? if (AutoDelMsg)//如果閱讀完短信自動刪除設置為真
??????????? {
??????????????? try
??????????????? {
??????????????????? DelMsgByIndex(index);
??????????????? }
??????????????? catch { }
??????????? }
??????????? return msgCenter + "," + phone + "," + time + "," + msg;
??????? }
??????? /// <summary>
??????? /// 刪除對應序號短信
??????? /// </summary>
??????? /// <param name="index">短信序號</param>
??????? /// <returns></returns>
??????? public bool DelMsgByIndex(int index)
??????? {
??????????? if (SendAT("AT+CMGD=" + index.ToString()).Trim() == "OK")
??????????? {
??????????????? return true;
??????????? }
??????????? else
??????????? {
??????????????? return false;
??????????? }
??????? }
??????? #endregion
??????? /// <summary>
??????? /// 創建事件收到信息的委托
??????? /// </summary>
??????? /// <param name="sender"></param>
??????? /// <param name="e"></param>
??????? public delegate void OnRecievedHandler(object sender, EventArgs e);
??????? /// <summary>
??????? /// 收到短信息事件 OnRecieved
??????? /// 收到短信將引發此事件
??????? /// </summary>
??????? public event OnRecievedHandler GetNewMsg;
??????? private void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
??????? {
??????????? string str = this.sp.ReadLine();
??????????? if ((str.Length > 8) && (str.Substring(0, 6) == "+CMTI:"))
??????????? {
??????????????? this.newMsgIndex = Convert.ToInt32(str.Split(',')[1]);
??????????????? this.GetNewMsg(this, e);
??????????? }
??????? }
??? }
??? class PDUEncoding
??? {
??????? private string serviceCenterAddress = "00";
??????? /// <summary>
??????? /// 消息服務中心(1-12個8位組)
??????? /// </summary>
??????? public string ServiceCenterAddress
??????? {
??????????? get
??????????? {
??????????????? int len = 2 * Convert.ToInt32(serviceCenterAddress.Substring(0, 2));
??????????????? string result = serviceCenterAddress.Substring(4, len - 2);
??????????????? result = ParityChange(result);
??????????????? result = result.TrimEnd('F', 'f');
??????????????? return result;
??????????? }
??????????? set???????????????? //
??????????? {
??????????????? if (value == null || value.Length == 0)????? //號碼為空
??????????????? {
??????????????????? serviceCenterAddress = "00";
??????????????? }
??????????????? else
??????????????? {
??????????????????? if (value[0] == '+')
??????????????????? {
??????????????????????? value = value.TrimStart('+');
??????????????????? }
??????????????????? if (value.Substring(0, 2) != "86")
??????????????????? {
??????????????????????? value = "86" + value;
??????????????????? }
??????????????????? value = "91" + ParityChange(value);
??????????????????? serviceCenterAddress = (value.Length / 2).ToString("X2") + value;
??????????????? }
??????????? }
??????? }
??????? private string protocolDataUnitType = "11";
??????? /// <summary>
??????? /// 協議數據單元類型(1個8位組)
??????? /// </summary>
??????? public string ProtocolDataUnitType
??????? {
??????????? set
??????????? {
??????????? }
??????????? get
??????????? {
??????????????? return "11";
??????????? }
??????? }
??????? private string messageReference = "00";
??????? /// <summary>
??????? /// 所有成功的短信發送參考數目(0..255)
??????? /// (1個8位組)
??????? /// </summary>
??????? public string MessageReference
??????? {
??????????? get
??????????? {
??????????????? return "00";
??????????? }
??????? }
??????? private string originatorAddress = "00";
??????? /// <summary>
??????? /// 發送方地址(手機號碼)(2-12個8位組)
??????? /// </summary>
??????? public string OriginatorAddress
??????? {
??????????? get
??????????? {
??????????????? int len = Convert.ToInt32(originatorAddress.Substring(0, 2), 16);??? //十六進制字符串轉為整形數據
??????????????? string result = string.Empty;
??????????????? if (len % 2 == 1)?????? //號碼長度是奇數,長度加1 編碼時加了F
??????????????? {
??????????????????? len++;
??????????????? }
??????????????? result = originatorAddress.Substring(4, len);
??????????????? result = ParityChange(result).TrimEnd('F', 'f');??? //奇偶互換,并去掉結尾F
??????????????? return result;
??????????? }
??????? }
??????? private string destinationAddress = "00";
??????? /// <summary>
??????? /// 接收方地址(手機號碼)(2-12個8位組)
??????? /// </summary>
??????? public string DestinationAddress
??????? {
??????????? set
??????????? {
??????????????? if (value == null || value.Length == 0)????? //號碼為空
??????????????? {
??????????????????? destinationAddress = "00";
??????????????? }
??????????????? else
??????????????? {
??????????????????? if (value[0] == '+')
??????????????????? {
??????????????????????? value = value.TrimStart('+');
??????????????????? }
??????????????????? if (value.Substring(0, 2) == "86")
??????????????????? {
??????????????????????? value = value.TrimStart('8', '6');
??????????????????? }
??????????????????? int len = value.Length;
??????????????????? value = ParityChange(value);
??????????????????? destinationAddress = len.ToString("X2") + "A1" + value;
??????????????? }
??????????? }
??????? }
??????? private string protocolIdentifer = "00";
??????? /// <summary>
??????? /// 參數顯示消息中心以何種方式處理消息內容
??????? /// (比如FAX,Voice)(1個8位組)
??????? /// </summary>
??????? public string ProtocolIdentifer
??????? {
??????????? get
??????????? {
??????????????? return protocolIdentifer;
??????????? }
??????????? set
??????????? {
??????????? }
??????? }
??????? private string dataCodingScheme = "08";???? //暫時僅支持國內USC2編碼
??????? /// <summary>
??????? /// 參數顯示用戶數據編碼方案(1個8位組)
??????? /// </summary>
??????? public string DataCodingScheme
??????? {
??????????? get
??????????? {
??????????????? return dataCodingScheme;
??????????? }
??????? }
??????? private string serviceCenterTimeStamp = "";
??????? /// <summary>
??????? /// 消息中心收到消息時的時間戳(7個8位組)
??????? /// </summary>
??????? public string ServiceCenterTimeStamp
??????? {
??????????? get
??????????? {
??????????????? string result = ParityChange(serviceCenterTimeStamp);
??????????????? result = "20" + result.Substring(0, 12);??????????? //年加開始的“20”
??????????????? return result;
??????????? }
??????? }
??????? private string validityPeriod = "C4";?????? //暫時固定有效期
??????? /// <summary>
??????? /// 短消息有效期(0,1,7個8位組)
??????? /// </summary>
??????? public string ValidityPeriod
??????? {
??????????? get
??????????? {
??????????????? return "C4";
??????????? }
??????? }
??????? private string userDataLenghth = "";
??????? /// <summary>
??????? /// 用戶數據長度(1個8位組)
??????? /// </summary>
??????? public string UserDataLenghth
??????? {
??????????? get
??????????? {
??????????????? return (userData.Length / 2).ToString("X2");
??????????? }
??????? }
??????? private string userData = "";
??????? /// <summary>
??????? /// 用戶數據(0-140個8位組)
??????? /// </summary>
??????? public string UserData
??????? {
??????????? get
??????????? {
??????????????? int len = Convert.ToInt32(userDataLenghth, 16) * 2;
??????????????? string result = string.Empty;
??????????????? if (dataCodingScheme == "08" || dataCodingScheme == "18")???????????? //USC2編碼
??????????????? {
??????????????????? //四個一組,每組譯為一個USC2字符
??????????????????? for (int i = 0; i < len; i += 4)
??????????????????? {
??????????????????????? string temp = userData.Substring(i, 4);
??????????????????????? int byte1 = Convert.ToInt16(temp, 16);
??????????????????????? result += ((char)byte1).ToString();
??????????????????? }
??????????????? }
??????????????? else
??????????????? {
??????????????????? result = PDU7bitDecoder(userData);
??????????????? }
??????????????? return result;
??????????? }
??????????? set
??????????? {
??????????????? userData = string.Empty;
??????????????? Encoding encodingUTF = Encoding.BigEndianUnicode;
??????????????? byte[] Bytes = encodingUTF.GetBytes(value);
??????????????? for (int i = 0; i < Bytes.Length; i++)
??????????????? {
??????????????????? userData += BitConverter.ToString(Bytes, i, 1);
??????????????? }
??????????????? userDataLenghth = (userData.Length / 2).ToString("X2");
??????????? }
??????? }
??????? /// <summary>
??????? /// 奇偶互換 (+F)
??????? /// </summary>
??????? /// <param name="str">要被轉換的字符串</param>
??????? /// <returns>轉換后的結果字符串</returns>
??????? private string ParityChange(string str)
??????? {
??????????? string result = string.Empty;
??????????? if (str.Length % 2 != 0)???????? //奇字符串 補F
??????????? {
??????????????? str += "F";
??????????? }
??????????? for (int i = 0; i < str.Length; i += 2)
??????????? {
??????????????? result += str[i + 1];
??????????????? result += str[i];
??????????? }
??????????? return result;
??????? }
??????? /// <summary>
??????? /// PDU編碼器,完成PDU編碼(USC2編碼,最多70個字)
??????? /// </summary>
??????? /// <param name="phone">目的手機號碼</param>
??????? /// <param name="Text">短信內容</param>
??????? /// <returns>編碼后的PDU字符串</returns>
??????? public string PDUEncoder(string phone, string Text)
??????? {
??????????? if (Text.Length > 70)
??????????? {
??????????????? throw (new Exception("短信字數超過70"));
??????????? }
??????????? DestinationAddress = phone;
??????????? UserData = Text;
??????????? return serviceCenterAddress + protocolDataUnitType
??????????????? + messageReference + destinationAddress + protocolIdentifer
??????????????? + dataCodingScheme + validityPeriod + userDataLenghth + userData;
??????? }
??????? /// <summary>
??????? /// 7bit 編碼
??????? /// </summary>
??????? /// <param name="phone">手機號碼</param>
??????? /// <param name="Text">短信內容</param>
??????? /// <returns>編碼后的字符串</returns>
??????? public string PDU7BitEncoder(string phone, string Text)
??????? {
??????????? if (Text.Length > 160)
??????????? {
??????????????? throw new Exception("短信字數大于160");
??????????? }
??????????? dataCodingScheme = "00";
??????????? DestinationAddress = phone;
??????????? UserData = Text;
??????????? return serviceCenterAddress + protocolDataUnitType
??????????????? + messageReference + destinationAddress + protocolIdentifer
??????????????? + dataCodingScheme + validityPeriod + userDataLenghth + userData;
??????? }
??????? /// <summary>
??????? /// 重載 解碼,返回信息字符串
??????? /// </summary>
??????? /// <param name="strPDU">短信PDU字符串</param>
??????? /// <returns>信息字符串(中心號碼,手機號碼,發送時間,短信內容)</returns>
??????? public string PDUDecoder(string strPDU)
??????? {
??????????? int length = (Convert.ToInt32(strPDU.Substring(0, 2), 0x10) * 2) + 2;
??????????? this.serviceCenterAddress = strPDU.Substring(0, length);
??????????? int num2 = Convert.ToInt32(strPDU.Substring(length + 2, 2), 0x10);
??????????? if ((num2 % 2) == 1)
??????????? {
??????????????? num2++;
??????????? }
??????????? num2 += 4;
??????????? this.originatorAddress = strPDU.Substring(length + 2, num2);
??????????? this.dataCodingScheme = strPDU.Substring((length + num2) + 4, 2);
??????????? this.serviceCenterTimeStamp = strPDU.Substring((length + num2) + 6, 14);
??????????? this.userDataLenghth = strPDU.Substring((length + num2) + 20, 2);
??????????? Convert.ToInt32(this.userDataLenghth, 0x10);
??????????? this.userData = strPDU.Substring((length + num2) + 0x16);
??????????? return (this.ServiceCenterAddress + "," + this.OriginatorAddress + "," + this.ServiceCenterTimeStamp + "," + this.UserData);
??????? }
??????? /// <summary>
??????? /// 完成手機或短信貓收到PDU格式短信的解碼 暫時僅支持中文編碼
??????? /// 未用DCS部分
??????? /// </summary>
??????? /// <param name="strPDU">短信PDU字符串</param>
??????? /// <param name="msgCenter">短消息服務中心 輸出</param>
??????? /// <param name="phone">發送方手機號碼 輸出</param>
??????? /// <param name="msg">短信內容 輸出</param>
??????? /// <param name="time">時間字符串 輸出</param>
??????? public void PDUDecoder(string strPDU, out string msgCenter, out string phone, out string msg, out string time)
??????? {
??????????? int lenSCA = Convert.ToInt32(strPDU.Substring(0, 2), 16) * 2 + 2;?????? //短消息中心占長度
??????????? serviceCenterAddress = strPDU.Substring(0, lenSCA);
??????????? int lenOA = Convert.ToInt32(strPDU.Substring(lenSCA + 2, 2), 16);?????????? //OA占用長度
??????????? if (lenOA % 2 == 1)???????????????????????????????????????????????????? //奇數則加1 F位
??????????? {
??????????????? lenOA++;
??????????? }
??????????? lenOA += 4;???????????????? //加號碼編碼的頭部長度
??????????? originatorAddress = strPDU.Substring(lenSCA + 2, lenOA);
??????????? dataCodingScheme = strPDU.Substring(lenSCA + lenOA + 4, 2);???????????? //DCS賦值,區分解碼7bit
??????????? serviceCenterTimeStamp = strPDU.Substring(lenSCA + lenOA + 6, 14);
??????????? userDataLenghth = strPDU.Substring(lenSCA + lenOA + 20, 2);
??????????? int lenUD = Convert.ToInt32(userDataLenghth, 16) * 2;
??????????? userData = strPDU.Substring(lenSCA + lenOA + 22);
??????????? msgCenter = ServiceCenterAddress;
??????????? phone = OriginatorAddress;
??????????? msg = UserData;
??????????? time = ServiceCenterTimeStamp;
??????? }
??????? /// <summary>
??????? /// PDU7bit的解碼,供UserData的get訪問器調用
??????? /// </summary>
??????? /// <param name="len">用戶數據長度</param>
??????? /// <param name="userData">數據部分PDU字符串</param>
??????? /// <returns></returns>
??????? private string PDU7bitDecoder(string userData)
??????? {
??????????? string result = string.Empty;
??????????? byte[] b = new byte[100];
??????????? string temp = string.Empty;
??????????? for (int i = 0; i < userData.Length; i += 2)
??????????? {
??????????????? b[i / 2] = (byte)Convert.ToByte((userData[i].ToString() + userData[i + 1].ToString()), 16);
??????????? }
??????????? int j = 0;??????????? //while計數
??????????? int tmp = 1;??????????? //temp中二進制字符字符個數
??????????? while (j < userData.Length / 2 - 1)
??????????? {
??????????????? string s = string.Empty;
??????????????? s = Convert.ToString(b[j], 2);
??????????????? while (s.Length < 8)??????????? //s補滿8位 byte轉化來的 有的不足8位,直接解碼將導致錯誤
??????????????? {
??????????????????? s = "0" + s;
??????????????? }
??????????????? result += (char)Convert.ToInt32(s.Substring(tmp) + temp, 2);??????? //加入一個字符 結果集 temp 上一位組剩余
??????????????? temp = s.Substring(0, tmp);???????????? //前一位組多的部分
??????????????? if (tmp > 6)??????????????????????????? //多余的部分滿7位,加入一個字符
??????????????? {
??????????????????? result += (char)Convert.ToInt32(temp, 2);
??????????????????? temp = string.Empty;
??????????????????? tmp = 0;
??????????????? }
??????????????? tmp++;
??????????????? j++;
??????????????? if (j == userData.Length / 2 - 1)?????????? //最后一個字符
??????????????? {
??????????????????? result += (char)Convert.ToInt32(Convert.ToString(b[j], 2) + temp, 2);
??????????????? }
??????????? }
??????????? return result;
??????? }
??? }
}
?
關于C#操作短信貓的文章在博客園也有很多,其中個人認為比較專業的就是 給我一杯酒 的短信貓軟件實現的系列博客了!
短信貓軟件的實現(C#)<一>熟悉串口短信貓軟件的實現(C#)<二> AT指令調試器的簡單實現短信貓軟件的實現(C#)<三>PDU格式短信解析短信貓軟件的實現(C#)<四>PDU格式編碼C#實現短信貓軟件的實現(C#)<五>PDU格式解碼C#實現短信貓軟件的實現(C#)<六>發送接收短信C#實現(API)短信貓軟件的實現(C#)<七>短信貓(簡化測試版)實現短信貓軟件的實現(C#)<八>7bitPDU的解碼短信貓軟件的實現(C#)<九>7bitPDU的編碼短信貓軟件的實現(C#)<十>類庫(API)完善短信貓軟件的實現(C#)<十一>軟件實現(完結篇)非常感謝該作者給我們無私的分享和解答,在使用的過程中,還是發現一些問題,短信發不出去,找來找去終于找到原因,我用的是深圳百億科技的GSM短信貓,他有自己的一些特殊規定,AT命令通用,但是求長度這一塊好像不一樣,下面就是我修正過來的短信貓操作類,增加了打電話,獲取所有信息等方法!
?
//類名:myGSMModem//作用:短信貓類
//作者:劉典武修正(通用于深圳百億科技GSM)
//時間:2011-03-01
//說明:來源于博客園(修正)
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.IO.Ports;
namespace myClassLibrary
{
??? public enum MsgType { AUSC2, A7Bit };//枚舉 短信類型 AUSC2 A7Bit:7位編碼 (中文用AUSC2,英文都可以 但7Bit能發送160字符,USC2僅70)
??? public class myGSM
??? {
??????? #region? 構造函數
??????? /// <summary>
??????? /// 無參數構造函數 完成有關初始化工作
??????? /// </summary>
??????? public myGSM()
??????? {
??????????? this.msgCenter = string.Empty;
??????????? this.sp = new SerialPort();
??????????? this.sp.ReadTimeout = -1;//讀超時時間 發送短信時間的需要
??????????? this.sp.RtsEnable = true;//必須為true 這樣串口才能接收到數據
??????????? this.sp.DataReceived += new SerialDataReceivedEventHandler(this.sp_DataReceived);
??????? }
??????? /// <summary>
??????? /// 構造函數
??????? /// </summary>
??????? /// <param name="comPort">串口號</param>
??????? /// <param name="baudRate">波特率</param>
??????? public myGSM(string comPort, int baudRate)
??????? {
??????????? this.msgCenter = string.Empty;
??????????? this.sp = new SerialPort();
??????????? this.sp.PortName = comPort;
??????????? this.sp.BaudRate = baudRate;
??????????? this.sp.ReadTimeout = -1;//讀超時時間 發送短信時間的需要
??????????? this.sp.RtsEnable = true;//必須為true 這樣串口才能接收到數據
??????????? this.sp.DataReceived += new SerialDataReceivedEventHandler(this.sp_DataReceived);
??????? }
??????? #endregion
??????? #region? 私有變量
??????? private SerialPort sp;
??????? private bool autoDelMsg = false;//是否自動刪除短消息
??????? private string msgCenter = string.Empty;//服務中心號碼
??????? private int newMsgIndex;//新消息序號
??????? #endregion
??????? #region 屬性
??????? /// <summary>
??????? /// 是否自動刪除短信(默認為false)
??????? /// </summary>
??????? public bool AutoDelMsg
??????? {
??????????? get { return this.autoDelMsg; }
??????????? set { this.autoDelMsg = value; }
??????? }
??????? /// <summary>
??????? /// 波特率 運行時只讀 設備打開狀態寫入將引發異常
??????? /// </summary>
??????? public int BaudRate
??????? {
??????????? get { return this.sp.BaudRate; }
??????????? set { this.sp.BaudRate = value; }
??????? }
??????? /// <summary>
??????? /// 串口號 運行時只讀 設備打開狀態寫入將引發異常
??????? /// 提供對串口端口號的訪問
??????? /// </summary>
??????? public string ComPort
??????? {
??????????? get { return this.sp.PortName; }
??????????? set { try { this.sp.PortName = value; } catch (Exception ex) { throw ex; } }
??????? }
??????? /// <summary>
??????? /// 設備是否打開
??????? /// </summary>
??????? public bool IsOpen
??????? {
??????????? get { return this.sp.IsOpen; }
??????? }
??????? #endregion
??????? #region? 方法
??????? /// <summary>
??????? /// 設置服務中心號碼
??????? /// </summary>
??????? /// <param name="msgCenterNo"></param>
??????? public void SetMsgCenterNo(string msgCenterNo)
??????? {
??????????? this.msgCenter = msgCenterNo;
??????? }
??????? /// <summary>
??????? /// 獲取機器碼
??????? /// </summary>
??????? /// <returns></returns>
??????? public string GetMachineNo()
??????? {
??????????? string temp = this.SendAT("AT+CGMI");
??????????? if (temp.Substring(temp.Length - 4, 3).Trim() == "OK")
??????????? {
??????????????? temp = temp.Split('\r')[2].Trim();
??????????? }
??????????? else
??????????? {
??????????????? throw new Exception("獲取機器碼失敗");
??????????? }
??????????? return temp;
??????? }
??????? /// <summary>
??????? /// 獲取短信中心號碼
??????? /// </summary>
??????? /// <returns></returns>
??????? public string GetMsgCenterNo()
??????? {
??????????? string temp = string.Empty;
??????????? if (msgCenter != null && msgCenter.Length != 0)
??????????? {
??????????????? return msgCenter;
??????????? }
??????????? else
??????????? {
??????????????? temp = this.SendAT("AT+CSCA?");
??????????????? if (temp.Substring(temp.Length - 4, 3).Trim() == "OK")
??????????????? {
??????????????????? return temp.Split('\"')[1].Trim();
??????????????? }
??????????????? else
??????????????? {
??????????????????? throw new Exception("獲取短信中心失敗");
??????????????? }
??????????? }
??????? }
??????? /// <summary>
??????? /// 取得未讀信息列表
??????? /// </summary>
??????? /// <returns>未讀信息列表(中心號碼,手機號碼,發送時間,短信內容)</returns>
??????? public string[] GetUnReadMsg()
??????? {
??????????? string[] result = new string[255];//存儲255條短信,一般手機上面存儲的短信少于這個數
??????????? string[] temp = null;
??????????? string tt = string.Empty;
??????????? tt = this.SendAT("AT+CMGL=0");//讀取未讀信息
??????????? if (tt.Substring(tt.Length - 4, 3).Trim() == "OK")
??????????? {
??????????????? temp = tt.Split('\r');
??????????? }
??????????? PDUEncoding pe = new PDUEncoding();
??????????? int i = 0;//計數
??????????? foreach (string str in temp)
??????????? {
??????????????? if (str != null && str.Length != 0 && str.Substring(0, 2).Trim() != "+C" && str.Substring(0, 2) != "OK" && str.Substring(0, 2) != "AT")
??????????????? {
??????????????????? result[i] = pe.PDUDecoder(str);
??????????????????? i++;
??????????????? }
??????????? }
??????????? return result;
??????? }
??????? /// <summary>
??????? /// 取得已讀信息列表
??????? /// </summary>
??????? /// <returns>已讀信息列表(中心號碼,手機號碼,發送時間,短信內容)</returns>
??????? public string[] GetIsReadMsg()
??????? {
??????????? string[] result = new string[255];//存儲255條短信,一般手機上面存儲的短信少于這個數
??????????? string[] temp = null;
??????????? string tt = string.Empty;
??????????? tt = this.SendAT("AT+CMGL=1");//讀取已讀信息
??????????? if (tt.Substring(tt.Length - 4, 3).Trim() == "OK")
??????????? {
??????????????? temp = tt.Split('\r');
??????????? }
??????????? PDUEncoding pe = new PDUEncoding();
??????????? int i = 0;//計數
??????????? foreach (string str in temp)
??????????? {
??????????????? if (str != null && str.Length != 0 && str.Substring(0, 2).Trim() != "+C" && str.Substring(0, 2) != "OK" && str.Substring(0, 2) != "AT")
??????????????? {
??????????????????? result[i] = pe.PDUDecoder(str);
??????????????????? i++;
??????????????? }
??????????? }
??????????? return result;
??????? }
??????? /// <summary>
??????? /// 取得待發信息列表
??????? /// </summary>
??????? /// <returns>待發信息列表(中心號碼,手機號碼,發送時間,短信內容)</returns>
??????? public string[] GetUnSendMsg()
??????? {
??????????? string[] result = new string[255];//存儲255條短信,一般手機上面存儲的短信少于這個數
??????????? string[] temp = null;
??????????? string tt = string.Empty;
??????????? tt = this.SendAT("AT+CMGL=2");//讀取待發信息
??????????? if (tt.Substring(tt.Length - 4, 3).Trim() == "OK")
??????????? {
??????????????? temp = tt.Split('\r');
??????????? }
??????????? PDUEncoding pe = new PDUEncoding();
??????????? int i = 0;//計數
??????????? foreach (string str in temp)
??????????? {
??????????????? if (str != null && str.Length != 0 && str.Substring(0, 2).Trim() != "+C" && str.Substring(0, 2) != "OK" && str.Substring(0, 2) != "AT")
??????????????? {
??????????????????? result[i] = pe.PDUDecoder(str);
??????????????????? i++;
??????????????? }
??????????? }
??????????? return result;
??????? }
??????? /// <summary>
??????? /// 取得已發信息列表
??????? /// </summary>
??????? /// <returns>已發信息列表(中心號碼,手機號碼,發送時間,短信內容)</returns>
??????? public string[] GetIsSendMsg()
??????? {
??????????? string[] result = new string[255];//存儲255條短信,一般手機上面存儲的短信少于這個數
??????????? string[] temp = null;
??????????? string tt = string.Empty;
??????????? tt = this.SendAT("AT+CMGL=3");//讀取已發信息
??????????? if (tt.Substring(tt.Length - 4, 3).Trim() == "OK")
??????????? {
??????????????? temp = tt.Split('\r');
??????????? }
??????????? PDUEncoding pe = new PDUEncoding();
??????????? int i = 0;//計數
??????????? foreach (string str in temp)
??????????? {
??????????????? if (str != null && str.Length != 0 && str.Substring(0, 2).Trim() != "+C" && str.Substring(0, 2) != "OK" && str.Substring(0, 2) != "AT")
??????????????? {
??????????????????? result[i] = pe.PDUDecoder(str);
??????????????????? i++;
??????????????? }
??????????? }
??????????? return result;
??????? }
??????? /// <summary>
??????? /// 獲取所有信息
??????? /// </summary>
??????? /// <returns></returns>
??????? public string[] GetAllMsg()
??????? {
??????????? string[] result = new string[255];//存儲255條短信,一般手機上面存儲的短信少于這個數
??????????? string[] temp = null;
??????????? string tt = string.Empty;
??????????? tt = this.SendAT("AT+CMGL=4");//讀取未讀信息
??????????? if (tt.Substring(tt.Length - 4, 3).Trim() == "OK")
??????????? {
??????????????? temp = tt.Split('\r');
??????????? }
??????????? PDUEncoding pe = new PDUEncoding();
??????????? int i = 0;//計數
??????????? foreach (string str in temp)
??????????? {
??????????????? if (str != null && str.Length != 0 && str.Substring(0, 2).Trim() != "+C" && str.Substring(0, 2) != "OK" && str.Substring(0, 2) != "AT")
??????????????? {
??????????????????? result[i] = pe.PDUDecoder(str);
??????????????????? i++;
??????????????? }
??????????? }
??????????? return result;
??????? }
??????? /// <summary>
??????? /// 讀取設備新收到的短消息
??????? /// </summary>
??????? /// <returns></returns>
??????? public string ReadNewMsg()
??????? {
??????????? return ReadMsgByIndex(newMsgIndex);
??????? }
??????? /// <summary>
??????? /// 發送AT命令
??????? /// </summary>
??????? /// <param name="ATCom">AT命令</param>
??????? /// <returns></returns>
??????? public string SendAT(string ATCom)
??????? {
??????????? string str = string.Empty;
??????????? //忽略接收緩沖區內容,準備發送
??????????? this.sp.DiscardInBuffer();
??????????? //注銷事件關聯,為發送做準備
??????????? this.sp.DataReceived -= this.sp_DataReceived;
??????????? try
??????????? {
??????????????? this.sp.Write(ATCom + "\r");
??????????? }
??????????? catch (Exception ex)
??????????? {
??????????????? this.sp.DataReceived += this.sp_DataReceived;
??????????????? throw ex;
??????????? }
??????????? try
??????????? {
??????????????? string temp = string.Empty;
??????????????? while ((temp.Trim() != "OK") && (temp.Trim() != "ERROR"))
??????????????? {
??????????????????? temp = this.sp.ReadLine();
??????????????????? str += temp;
??????????????? }
??????????? }
??????????? catch (Exception ex)
??????????? {
??????????????? throw ex;
??????????? }
??????????? finally
??????????? {
??????????????? this.sp.DataReceived += this.sp_DataReceived;
??????????? }
??????????? return str;
??????? }
??????? /// <summary>
??????? /// 發送短信????? ?
??????? /// </summary>
??????? /// <param name="phone">手機號碼</param>
??????? /// <param name="msg">短信內容</param>
??????? public bool SendMsg(string phone, string msg)
??????? {
??????????? string temp = "0011000D91" + this.reverserNumber(phone) + "000801" + this.contentEncoding(msg) + Convert.ToChar(26).ToString();
??????????? string len = this.getLenght(msg);//計算長度
??????????? try
??????????? {
??????????????? this.sp.DataReceived -= sp_DataReceived;
??????????????? this.sp.Write("AT+CMGS=" + len + "\r");
??????????????? this.sp.ReadTo(">");
??????????????? this.sp.DiscardInBuffer();
??????????????? //事件重新綁定 正常監視串口數據
??????????????? this.sp.DataReceived += sp_DataReceived;
??????????????? temp = this.SendAT(temp);
??????????????? if (temp.Substring(temp.Length - 4, 3).Trim() != "OK")
??????????????? {
??????????????????? return false;
??????????????? }
??????????????? else
??????????????? {
??????????????????? return true;
??????????????? }
??????????? }
??????????? catch { return false; }
??????? }
??????? #region? 自定義方法
??????? //獲取短信內容的字節數
??????? private string getLenght(string txt)
??????? {
??????????? int i = 0;
??????????? string s = "";
??????????? i = txt.Length * 2;
??????????? i += 15;
??????????? s = i.ToString();
??????????? return s;
??????? }
??????? //將手機號碼轉換為內存編碼
??????? private string reverserNumber(string phone)
??????? {
??????????? string str = "";
??????????? //檢查手機號碼是否按照標準格式寫,如果不是則補上
??????????? if (phone.Substring(0, 2) != "86")
??????????? {
??????????????? phone = string.Format("86{0}", phone);
??????????? }
??????????? char[] c = this.getChar(phone);
??????????? for (int i = 0; i <= c.Length - 2; i += 2)
??????????? {
??????????????? str += c[i + 1].ToString() + c[i].ToString();
??????????? }
??????????? return str;
??????? }
??????? //漢字解碼為16進制
??????? private string contentEncoding(string content)
??????? {
??????????? Encoding encodingUTF = System.Text.Encoding.BigEndianUnicode;
??????????? string s = "";
??????????? byte[] encodeByte = encodingUTF.GetBytes(content);
??????????? for (int i = 0; i <= encodeByte.Length - 1; i++)
??????????? {
??????????????? s += BitConverter.ToString(encodeByte, i, 1);
??????????? }
??????????? s = string.Format("{0:X2}{1}", s.Length / 2, s);
??????????? return s;
??????? }
??????? private char[] getChar(string phone)
??????? {
??????????? if (phone.Length % 2 == 0)
??????????? {
??????????????? return Convert.ToString(phone).ToCharArray();
??????????? }
??????????? else
??????????? {
??????????????? return Convert.ToString(phone + "F").ToCharArray();
??????????? }
??????? }
??????? #endregion
??????? /// <summary>
??????? /// 發送短信 (重載)
??????? /// </summary>
??????? /// <param name="phone">手機號碼</param>
??????? /// <param name="msg">短信內容</param>
??????? /// <param name="msgType">短信類型</param>
??????? public void SendMsg(string phone, string msg, MsgType msgType)
??????? {
??????????? if (msgType == MsgType.AUSC2)
??????????? {
??????????????? SendMsg(phone, msg);
??????????? }
??????????? else
??????????? {
??????????????? PDUEncoding pe = new PDUEncoding();
??????????????? pe.ServiceCenterAddress = msgCenter;??????????????????? //短信中心號碼 服務中心地址
??????????????? string temp = pe.PDU7BitEncoder(phone, msg);
??????????????? int len = (temp.Length - Convert.ToInt32(temp.Substring(0, 2), 16) * 2 - 2) / 2;? //計算長度
??????????????? try
??????????????? {
??????????????????? temp = SendAT("AT+CMGS=" + len.ToString() + "\r" + temp + (char)(26));? //26 Ctrl+Z ascii碼
??????????????? }
??????????????? catch (Exception)
??????????????? {
??????????????????? throw new Exception("短信發送失敗");
??????????????? }
??????????????? if (temp.Substring(temp.Length - 4, 3).Trim() == "OK")
??????????????? {
??????????????????? return;
??????????????? }
??????????????? throw new Exception("短信發送失敗");
??????????? }
??????? }
??????? /// <summary>
??????? /// 關閉設備
??????? /// </summary>
??????? public void CloseComm()
??????? {
??????????? try
??????????? {
??????????????? this.sp.Close();
??????????? }
??????????? catch (Exception ex)
??????????? {
??????????????? throw ex;
??????????? }
??????? }
??????? /// <summary>
??????? /// 打開設備
??????? /// </summary>
??????? public void OpenComm()
??????? {
??????????? try
??????????? {
??????????????? this.sp.Open();
??????????? }
??????????? catch (Exception ex)
??????????? {
??????????????? throw ex;
??????????? }
??????????? if (this.sp.IsOpen)
??????????? {
??????????????? //this.sp.DataReceived -= this.sp_DataReceived;
??????????????? //this.sp.Write("AT\r");
??????????????? //Thread.Sleep(100);
??????????????? //string s = this.sp.ReadExisting().Trim();
??????????????? //s = s.Substring(s.Length - 2, 2);
??????????????? //if (s != "OK")
??????????????? //{
??????????????? //??? throw new Exception("硬件連接錯誤");
??????????????? //}
??????????????? try
??????????????? {
??????????????????? this.SendAT("AT+CMGF=0");//選擇短消息格式默認為PDU
??????????????????? Thread.Sleep(100);
??????????????????? this.SendAT("AT+CNMI=2,1");//選擇當有新短消息來時提示方式
??????????????????? Thread.Sleep(100);
??????????????? }
??????????????? catch { }
??????????? }
??????? }
??????? /// <summary>
??????? /// 撥打電話
??????? /// </summary>
??????? /// <param name="telNum">電話號碼</param>
??????? public void Call(string telNum)
??????? {
??????????? try
??????????? {
??????????????? this.SendAT("ATD" + telNum + ";");
??????????? }
??????????? catch (Exception ex)
??????????? {
??????????????? throw ex;
??????????? }
??????? }
??????? /// <summary>
??????? /// 按序號讀取短信
??????? /// </summary>
??????? /// <param name="index">序號</param>
??????? /// <param name="msgCenter">短信中心</param>
??????? /// <param name="phone">發送方手機號碼</param>
??????? /// <param name="msg">短信內容</param>
??????? /// <param name="time">時間字符串</param>
??????? public void ReadMsgByIndex(int index, out string msgCenter, out string phone, out string msg, out string time)
??????? {
??????????? string temp = string.Empty;
??????????? PDUEncoding pe = new PDUEncoding();
??????????? try
??????????? {
??????????????? temp = SendAT("AT+CMGR=" + index.ToString() + "\r");
??????????? }
??????????? catch (Exception ex)
??????????? {
??????????????? throw ex;
??????????? }
??????????? if (temp.Trim() == "ERROR")
??????????? {
??????????????? throw new Exception("沒有此短信");
??????????? }
??????????? temp = temp.Split((char)(13))[2];?????? //取出PDU串(char)(13)為0x0a即\r 按\r分為多個字符串 第3個是PDU串
??????????? pe.PDUDecoder(temp, out msgCenter, out phone, out msg, out time);
??????? }
??????? /// <summary>
??????? /// 按序號讀取短信
??????? /// </summary>
??????? /// <param name="index">序號</param>
??????? /// <returns>信息字符串 (中心號碼,手機號碼,發送時間,短信內容)</returns>
??????? public string ReadMsgByIndex(int index)
??????? {
??????????? string temp = string.Empty;
??????????? string msgCenter, phone, msg, time;
??????????? PDUEncoding pe = new PDUEncoding();
??????????? try
??????????? {
??????????????? temp = SendAT("AT+CMGR=" + index.ToString());
??????????? }
??????????? catch (Exception ex)
??????????? {
??????????????? throw ex;
??????????? }
??????????? if (temp.Trim() == "ERROR")
??????????? {
??????????????? throw new Exception("沒有此短信");
??????????? }
??????????? temp = temp.Split((char)(13))[3];?????? //取出PDU串(char)(13)為0x0a即\r 按\r分為多個字符串 第3個是PDU串
??????????? pe.PDUDecoder(temp, out msgCenter, out phone, out msg, out time);
??????????? if (AutoDelMsg)//如果閱讀完短信自動刪除設置為真
??????????? {
??????????????? try
??????????????? {
??????????????????? DelMsgByIndex(index);
??????????????? }
??????????????? catch { }
??????????? }
??????????? return msgCenter + "," + phone + "," + time + "," + msg;
??????? }
??????? /// <summary>
??????? /// 刪除對應序號短信
??????? /// </summary>
??????? /// <param name="index">短信序號</param>
??????? /// <returns></returns>
??????? public bool DelMsgByIndex(int index)
??????? {
??????????? if (SendAT("AT+CMGD=" + index.ToString()).Trim() == "OK")
??????????? {
??????????????? return true;
??????????? }
??????????? else
??????????? {
??????????????? return false;
??????????? }
??????? }
??????? #endregion
??????? /// <summary>
??????? /// 創建事件收到信息的委托
??????? /// </summary>
??????? /// <param name="sender"></param>
??????? /// <param name="e"></param>
??????? public delegate void OnRecievedHandler(object sender, EventArgs e);
??????? /// <summary>
??????? /// 收到短信息事件 OnRecieved
??????? /// 收到短信將引發此事件
??????? /// </summary>
??????? public event OnRecievedHandler GetNewMsg;
??????? private void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
??????? {
??????????? string str = this.sp.ReadLine();
??????????? if ((str.Length > 8) && (str.Substring(0, 6) == "+CMTI:"))
??????????? {
??????????????? this.newMsgIndex = Convert.ToInt32(str.Split(',')[1]);
??????????????? this.GetNewMsg(this, e);
??????????? }
??????? }
??? }
??? class PDUEncoding
??? {
??????? private string serviceCenterAddress = "00";
??????? /// <summary>
??????? /// 消息服務中心(1-12個8位組)
??????? /// </summary>
??????? public string ServiceCenterAddress
??????? {
??????????? get
??????????? {
??????????????? int len = 2 * Convert.ToInt32(serviceCenterAddress.Substring(0, 2));
??????????????? string result = serviceCenterAddress.Substring(4, len - 2);
??????????????? result = ParityChange(result);
??????????????? result = result.TrimEnd('F', 'f');
??????????????? return result;
??????????? }
??????????? set???????????????? //
??????????? {
??????????????? if (value == null || value.Length == 0)????? //號碼為空
??????????????? {
??????????????????? serviceCenterAddress = "00";
??????????????? }
??????????????? else
??????????????? {
??????????????????? if (value[0] == '+')
??????????????????? {
??????????????????????? value = value.TrimStart('+');
??????????????????? }
??????????????????? if (value.Substring(0, 2) != "86")
??????????????????? {
??????????????????????? value = "86" + value;
??????????????????? }
??????????????????? value = "91" + ParityChange(value);
??????????????????? serviceCenterAddress = (value.Length / 2).ToString("X2") + value;
??????????????? }
??????????? }
??????? }
??????? private string protocolDataUnitType = "11";
??????? /// <summary>
??????? /// 協議數據單元類型(1個8位組)
??????? /// </summary>
??????? public string ProtocolDataUnitType
??????? {
??????????? set
??????????? {
??????????? }
??????????? get
??????????? {
??????????????? return "11";
??????????? }
??????? }
??????? private string messageReference = "00";
??????? /// <summary>
??????? /// 所有成功的短信發送參考數目(0..255)
??????? /// (1個8位組)
??????? /// </summary>
??????? public string MessageReference
??????? {
??????????? get
??????????? {
??????????????? return "00";
??????????? }
??????? }
??????? private string originatorAddress = "00";
??????? /// <summary>
??????? /// 發送方地址(手機號碼)(2-12個8位組)
??????? /// </summary>
??????? public string OriginatorAddress
??????? {
??????????? get
??????????? {
??????????????? int len = Convert.ToInt32(originatorAddress.Substring(0, 2), 16);??? //十六進制字符串轉為整形數據
??????????????? string result = string.Empty;
??????????????? if (len % 2 == 1)?????? //號碼長度是奇數,長度加1 編碼時加了F
??????????????? {
??????????????????? len++;
??????????????? }
??????????????? result = originatorAddress.Substring(4, len);
??????????????? result = ParityChange(result).TrimEnd('F', 'f');??? //奇偶互換,并去掉結尾F
??????????????? return result;
??????????? }
??????? }
??????? private string destinationAddress = "00";
??????? /// <summary>
??????? /// 接收方地址(手機號碼)(2-12個8位組)
??????? /// </summary>
??????? public string DestinationAddress
??????? {
??????????? set
??????????? {
??????????????? if (value == null || value.Length == 0)????? //號碼為空
??????????????? {
??????????????????? destinationAddress = "00";
??????????????? }
??????????????? else
??????????????? {
??????????????????? if (value[0] == '+')
??????????????????? {
??????????????????????? value = value.TrimStart('+');
??????????????????? }
??????????????????? if (value.Substring(0, 2) == "86")
??????????????????? {
??????????????????????? value = value.TrimStart('8', '6');
??????????????????? }
??????????????????? int len = value.Length;
??????????????????? value = ParityChange(value);
??????????????????? destinationAddress = len.ToString("X2") + "A1" + value;
??????????????? }
??????????? }
??????? }
??????? private string protocolIdentifer = "00";
??????? /// <summary>
??????? /// 參數顯示消息中心以何種方式處理消息內容
??????? /// (比如FAX,Voice)(1個8位組)
??????? /// </summary>
??????? public string ProtocolIdentifer
??????? {
??????????? get
??????????? {
??????????????? return protocolIdentifer;
??????????? }
??????????? set
??????????? {
??????????? }
??????? }
??????? private string dataCodingScheme = "08";???? //暫時僅支持國內USC2編碼
??????? /// <summary>
??????? /// 參數顯示用戶數據編碼方案(1個8位組)
??????? /// </summary>
??????? public string DataCodingScheme
??????? {
??????????? get
??????????? {
??????????????? return dataCodingScheme;
??????????? }
??????? }
??????? private string serviceCenterTimeStamp = "";
??????? /// <summary>
??????? /// 消息中心收到消息時的時間戳(7個8位組)
??????? /// </summary>
??????? public string ServiceCenterTimeStamp
??????? {
??????????? get
??????????? {
??????????????? string result = ParityChange(serviceCenterTimeStamp);
??????????????? result = "20" + result.Substring(0, 12);??????????? //年加開始的“20”
??????????????? return result;
??????????? }
??????? }
??????? private string validityPeriod = "C4";?????? //暫時固定有效期
??????? /// <summary>
??????? /// 短消息有效期(0,1,7個8位組)
??????? /// </summary>
??????? public string ValidityPeriod
??????? {
??????????? get
??????????? {
??????????????? return "C4";
??????????? }
??????? }
??????? private string userDataLenghth = "";
??????? /// <summary>
??????? /// 用戶數據長度(1個8位組)
??????? /// </summary>
??????? public string UserDataLenghth
??????? {
??????????? get
??????????? {
??????????????? return (userData.Length / 2).ToString("X2");
??????????? }
??????? }
??????? private string userData = "";
??????? /// <summary>
??????? /// 用戶數據(0-140個8位組)
??????? /// </summary>
??????? public string UserData
??????? {
??????????? get
??????????? {
??????????????? int len = Convert.ToInt32(userDataLenghth, 16) * 2;
??????????????? string result = string.Empty;
??????????????? if (dataCodingScheme == "08" || dataCodingScheme == "18")???????????? //USC2編碼
??????????????? {
??????????????????? //四個一組,每組譯為一個USC2字符
??????????????????? for (int i = 0; i < len; i += 4)
??????????????????? {
??????????????????????? string temp = userData.Substring(i, 4);
??????????????????????? int byte1 = Convert.ToInt16(temp, 16);
??????????????????????? result += ((char)byte1).ToString();
??????????????????? }
??????????????? }
??????????????? else
??????????????? {
??????????????????? result = PDU7bitDecoder(userData);
??????????????? }
??????????????? return result;
??????????? }
??????????? set
??????????? {
??????????????? userData = string.Empty;
??????????????? Encoding encodingUTF = Encoding.BigEndianUnicode;
??????????????? byte[] Bytes = encodingUTF.GetBytes(value);
??????????????? for (int i = 0; i < Bytes.Length; i++)
??????????????? {
??????????????????? userData += BitConverter.ToString(Bytes, i, 1);
??????????????? }
??????????????? userDataLenghth = (userData.Length / 2).ToString("X2");
??????????? }
??????? }
??????? /// <summary>
??????? /// 奇偶互換 (+F)
??????? /// </summary>
??????? /// <param name="str">要被轉換的字符串</param>
??????? /// <returns>轉換后的結果字符串</returns>
??????? private string ParityChange(string str)
??????? {
??????????? string result = string.Empty;
??????????? if (str.Length % 2 != 0)???????? //奇字符串 補F
??????????? {
??????????????? str += "F";
??????????? }
??????????? for (int i = 0; i < str.Length; i += 2)
??????????? {
??????????????? result += str[i + 1];
??????????????? result += str[i];
??????????? }
??????????? return result;
??????? }
??????? /// <summary>
??????? /// PDU編碼器,完成PDU編碼(USC2編碼,最多70個字)
??????? /// </summary>
??????? /// <param name="phone">目的手機號碼</param>
??????? /// <param name="Text">短信內容</param>
??????? /// <returns>編碼后的PDU字符串</returns>
??????? public string PDUEncoder(string phone, string Text)
??????? {
??????????? if (Text.Length > 70)
??????????? {
??????????????? throw (new Exception("短信字數超過70"));
??????????? }
??????????? DestinationAddress = phone;
??????????? UserData = Text;
??????????? return serviceCenterAddress + protocolDataUnitType
??????????????? + messageReference + destinationAddress + protocolIdentifer
??????????????? + dataCodingScheme + validityPeriod + userDataLenghth + userData;
??????? }
??????? /// <summary>
??????? /// 7bit 編碼
??????? /// </summary>
??????? /// <param name="phone">手機號碼</param>
??????? /// <param name="Text">短信內容</param>
??????? /// <returns>編碼后的字符串</returns>
??????? public string PDU7BitEncoder(string phone, string Text)
??????? {
??????????? if (Text.Length > 160)
??????????? {
??????????????? throw new Exception("短信字數大于160");
??????????? }
??????????? dataCodingScheme = "00";
??????????? DestinationAddress = phone;
??????????? UserData = Text;
??????????? return serviceCenterAddress + protocolDataUnitType
??????????????? + messageReference + destinationAddress + protocolIdentifer
??????????????? + dataCodingScheme + validityPeriod + userDataLenghth + userData;
??????? }
??????? /// <summary>
??????? /// 重載 解碼,返回信息字符串
??????? /// </summary>
??????? /// <param name="strPDU">短信PDU字符串</param>
??????? /// <returns>信息字符串(中心號碼,手機號碼,發送時間,短信內容)</returns>
??????? public string PDUDecoder(string strPDU)
??????? {
??????????? int length = (Convert.ToInt32(strPDU.Substring(0, 2), 0x10) * 2) + 2;
??????????? this.serviceCenterAddress = strPDU.Substring(0, length);
??????????? int num2 = Convert.ToInt32(strPDU.Substring(length + 2, 2), 0x10);
??????????? if ((num2 % 2) == 1)
??????????? {
??????????????? num2++;
??????????? }
??????????? num2 += 4;
??????????? this.originatorAddress = strPDU.Substring(length + 2, num2);
??????????? this.dataCodingScheme = strPDU.Substring((length + num2) + 4, 2);
??????????? this.serviceCenterTimeStamp = strPDU.Substring((length + num2) + 6, 14);
??????????? this.userDataLenghth = strPDU.Substring((length + num2) + 20, 2);
??????????? Convert.ToInt32(this.userDataLenghth, 0x10);
??????????? this.userData = strPDU.Substring((length + num2) + 0x16);
??????????? return (this.ServiceCenterAddress + "," + this.OriginatorAddress + "," + this.ServiceCenterTimeStamp + "," + this.UserData);
??????? }
??????? /// <summary>
??????? /// 完成手機或短信貓收到PDU格式短信的解碼 暫時僅支持中文編碼
??????? /// 未用DCS部分
??????? /// </summary>
??????? /// <param name="strPDU">短信PDU字符串</param>
??????? /// <param name="msgCenter">短消息服務中心 輸出</param>
??????? /// <param name="phone">發送方手機號碼 輸出</param>
??????? /// <param name="msg">短信內容 輸出</param>
??????? /// <param name="time">時間字符串 輸出</param>
??????? public void PDUDecoder(string strPDU, out string msgCenter, out string phone, out string msg, out string time)
??????? {
??????????? int lenSCA = Convert.ToInt32(strPDU.Substring(0, 2), 16) * 2 + 2;?????? //短消息中心占長度
??????????? serviceCenterAddress = strPDU.Substring(0, lenSCA);
??????????? int lenOA = Convert.ToInt32(strPDU.Substring(lenSCA + 2, 2), 16);?????????? //OA占用長度
??????????? if (lenOA % 2 == 1)???????????????????????????????????????????????????? //奇數則加1 F位
??????????? {
??????????????? lenOA++;
??????????? }
??????????? lenOA += 4;???????????????? //加號碼編碼的頭部長度
??????????? originatorAddress = strPDU.Substring(lenSCA + 2, lenOA);
??????????? dataCodingScheme = strPDU.Substring(lenSCA + lenOA + 4, 2);???????????? //DCS賦值,區分解碼7bit
??????????? serviceCenterTimeStamp = strPDU.Substring(lenSCA + lenOA + 6, 14);
??????????? userDataLenghth = strPDU.Substring(lenSCA + lenOA + 20, 2);
??????????? int lenUD = Convert.ToInt32(userDataLenghth, 16) * 2;
??????????? userData = strPDU.Substring(lenSCA + lenOA + 22);
??????????? msgCenter = ServiceCenterAddress;
??????????? phone = OriginatorAddress;
??????????? msg = UserData;
??????????? time = ServiceCenterTimeStamp;
??????? }
??????? /// <summary>
??????? /// PDU7bit的解碼,供UserData的get訪問器調用
??????? /// </summary>
??????? /// <param name="len">用戶數據長度</param>
??????? /// <param name="userData">數據部分PDU字符串</param>
??????? /// <returns></returns>
??????? private string PDU7bitDecoder(string userData)
??????? {
??????????? string result = string.Empty;
??????????? byte[] b = new byte[100];
??????????? string temp = string.Empty;
??????????? for (int i = 0; i < userData.Length; i += 2)
??????????? {
??????????????? b[i / 2] = (byte)Convert.ToByte((userData[i].ToString() + userData[i + 1].ToString()), 16);
??????????? }
??????????? int j = 0;??????????? //while計數
??????????? int tmp = 1;??????????? //temp中二進制字符字符個數
??????????? while (j < userData.Length / 2 - 1)
??????????? {
??????????????? string s = string.Empty;
??????????????? s = Convert.ToString(b[j], 2);
??????????????? while (s.Length < 8)??????????? //s補滿8位 byte轉化來的 有的不足8位,直接解碼將導致錯誤
??????????????? {
??????????????????? s = "0" + s;
??????????????? }
??????????????? result += (char)Convert.ToInt32(s.Substring(tmp) + temp, 2);??????? //加入一個字符 結果集 temp 上一位組剩余
??????????????? temp = s.Substring(0, tmp);???????????? //前一位組多的部分
??????????????? if (tmp > 6)??????????????????????????? //多余的部分滿7位,加入一個字符
??????????????? {
??????????????????? result += (char)Convert.ToInt32(temp, 2);
??????????????????? temp = string.Empty;
??????????????????? tmp = 0;
??????????????? }
??????????????? tmp++;
??????????????? j++;
??????????????? if (j == userData.Length / 2 - 1)?????????? //最后一個字符
??????????????? {
??????????????????? result += (char)Convert.ToInt32(Convert.ToString(b[j], 2) + temp, 2);
??????????????? }
??????????? }
??????????? return result;
??????? }
??? }
}
?
轉載于:https://www.cnblogs.com/feiyangqingyun/archive/2011/03/02/1969029.html
總結
以上是生活随笔為你收集整理的C#通用类库--短信猫操作类1(原始AT命令)的全部內容,希望文章能夠幫你解決所遇到的問題。