SerialPort實現modem的來電顯示

來源:互聯網
上載者:User

一個朋友接了個case,但是卻臨時有事要出差,所以就把部分的功能叫我來做。以前一直注重於web編程,對於串口編程還是比較陌生的,還好網上的文章不少。當然比較好的文章,有直接協助的文章還是要數cnblogs裡面的文章。把這寫到部落格裡便於以後自己查閱,希望也能夠幫到需要協助的人。
這裡主要是講用serailPort來實現modem的來電顯示。
來電顯示要依賴於具體的modem,不同的modem,可能AT指令不一樣,所以需要定義一個介面,將應用程式與硬體的耦合進行解耦。

Code
public interface IModem
    {
        void Open();
        void Close();
        bool SupportAT
        {
            get;
        }
        bool SupportCID
        {
            get;
        }
        event EventHandler<RingEventArgs> Ring;
    }
這個介面定義了open,close方法,還有是否支援AT指令,是否支援來電顯示,還有一個響鈴事件。RingEventArgs裡麵包含了來電的電話號碼。
在寫這個IModem的實作類別時,使用的是筆記本的modem,也不知道是什麼型號的,就直接用modem來命名。
Code
public class Modem : IModem
    {
        public event EventHandler<RingEventArgs> Ring;
        System.IO.Ports.SerialPort port = null;

        public Modem()
        {
            port = new System.IO.Ports.SerialPort();
            port.PortName = Settings.Instance.GetValue("PortName", "COM3");
            port.BaudRate = Settings.Instance.GetValue("BaudRate", 460800);
            port.DataBits = 8;
            port.Parity = Parity.None;
            port.StopBits = StopBits.One;
            port.ReadTimeout =
                port.WriteTimeout = 1000;//1S

            port.ReadBufferSize =
                port.WriteBufferSize = 1024;//1K

            port.Handshake = Handshake.None;
            port.ReceivedBytesThreshold = 10;
            port.RtsEnable = true;
            port.DtrEnable = true;
            port.NewLine = "\r";

            this.port.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(port_DataReceived);
        }

上面就是連接埠的配置,不同的modem可能配置不同,需要根據實際的modem進行設定。

Code
public void Open()
        {
            if (!this.port.IsOpen)
                this.port.Open();
            if (!SupportAT)
                throw new Exception("裝置不支援AT指令");
            if (!SupportCID)
                throw new Exception("裝置不支援來顯");
        }
        public void Close()
        {
            if (this.port.IsOpen)
                this.port.Close();
        }
        public bool SupportAT
        {
            get
            {
                this.port.WriteLine("AT");
                System.Threading.Thread.Sleep(500);
                string result = this.port.ReadExisting();
                return result.ToUpper().Contains("OK");
            }
        }
        public bool SupportCID
        {
            get
            {
                string[] commandList = Settings.Instance.SectionValues("CID");
                string result = string.Empty;
                foreach (string command in commandList)
                {
                    this.port.WriteLine(command);
                    System.Threading.Thread.Sleep(500);
                    result = this.port.ReadExisting();
                    if (result.ToUpper().Contains("OK"))
                    {
                        return true;
                    }
                }
                return false;
            }
        }
這是一些方法和屬性的實現。需要注意的是在發出指令後,最好能將線程堵塞一段時間,以保證有硬體足夠的時間來響應,保證能夠接收到完整的回複資訊。這裡的System.Threading.Thread.Sleep(500);就是這個目的。Code
void port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            string phoneNumber = this.port.ReadExisting();
            Regex r = new Regex(@"NMBR\s*=\s*[0-9]*");
            Match m = r.Match(phoneNumber);

            string result = string.Empty;
            if (m != null && m.Success)
            {
                result = m.Value;
                result = result.Substring(result.IndexOf("=") + 1).Trim();
            }
            if (string.IsNullOrEmpty(result))
                return;
            if (Ring != null)
            {
                RingEventArgs eventArgs = new RingEventArgs();
                eventArgs.PhoneNumber = result;
                foreach (EventHandler<RingEventArgs> handler in Ring.GetInvocationList())
                {
                    handler.Invoke(this, eventArgs);
                    if (eventArgs.Handled)
                        break;
                }
            }
        }
Ring響鈴事件實際上是根據DataReceived接收到的資料進行處理,比如判斷是否是來電,截取來電的號碼,然後事件冒泡,觸發Ring事件。不同的modem返回回來的值肯能是不一樣的。上面的正則表達是可能需要再次更改。(網上查到的是 = 號的左右有空格,可是我調試的那個modem卻沒有)

SerialPort 是.net 2.0才出現的。如果是.net 1.1的話可能需要使用MSCOMM

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.