SerialPort实现modem的来电显示

编程入门 行业动态 更新时间:2024-10-10 05:24:20

SerialPort实现modem的<a href=https://www.elefans.com/category/jswz/34/1739201.html style=来电显示"/>

SerialPort实现modem的来电显示

一个朋友接了个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 是 2.0才出现的。如果是 1.1的话可能需要使用 MSCOMM

转载于:.html

更多推荐

SerialPort实现modem的来电显示

本文发布于:2024-03-23 02:09:40,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1739202.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:来电显示   SerialPort   modem

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!