xugang

记录一个.NET 程序员的成长

 

使用SerialPort 对象实现串口拨号器通信[上]

 

首先,定义 CommandInfo 结构体


结构体 CommandInfo 用于保存当前 AT 指令的相关信息,代码如下:

    enum CommandDirection
    { 
       None = 0, 
       Read = 1, 
       Write = 2
    }

    enum CommandKey
    {
        None = 0, 
        AT = 1, 
        ATD = 2,
        ATH = 3,
        AT_CFUN = 4
    }

    struct CommandInfo
    {
        public CommandDirection TransType; // 写入 / 读取

        public CommandKey Command;     // 命令类型

        public int CommandLength;   // 命令自身长度 (不包含\r\n)

        public Byte[] SourceData;   // 数据源

        public int SourceDataLength;// 数据源长度 (包含\r\n 等转义字符)

        public int sleep100msNumber;// 延时100毫秒数
    }

 

然后,定义拨号器 Modem 类


一个 Modem 对象表示一个拨号器,Modem 对象的成员、属性、委托、构造方法如下:

    private SerialPort m_port;
    private Boolean sending = false;
    private Boolean receiving;
    private string m_portName = "";   // 串口名称
    private int m_boudrate = 0;       // 波特率

    private SetCallback m_callBack = null; //返回委托事件
    
    #region 委托
    public delegate void SetCallback(String message);

    //委托返回信息
    private void ReturnMessage(String message)
    {
        if (message.Length > 0 && m_callBack != null)
        {
            m_callBack(message);
        }
    }
    #endregion

    #region  属性
    //串口名称
    public string PortName
    {
        get { return m_portName; }
        set { m_portName = value; }
    }

    // 串行波特率
    public int Boudrate
    {
        get 
        {
            if (0 == this.m_boudrate)
            {
                this.m_boudrate = this.DefaultBoudrate; //默认波特率
            }
            return m_boudrate; 
        }
        set { m_boudrate = value; }
    }

    // 默认串行波特率(只读)
    public virtual int DefaultBoudrate
    {
        get { return 9600; }
    }
    #endregion

    #region  构造方法
    public Modem(string _portName, int _baudRate, SetCallback _callBack)
        : this(_portName, _callBack)
    {
        if (_baudRate != 0)
        {
            this.m_boudrate = _baudRate;  // BaudRate 串行波特率
        }
    }

    public Modem(string _portName, SetCallback _callBack)
    {
        CreateModem(_portName);

        if (_callBack != null) m_callBack = _callBack;

        try
        {
            OpenModem();
        }
        catch
        {
            CloseModem();
        }

    }
    #endregion

 

拨号器所对应的串口的基本方法如下:

    #region 拨号器的基本方法
    private void CreateModem(string portName)
    {
        if (this.m_port == null)
        {
            this.m_port = new SerialPort(portName, this.Boudrate, Parity.None, 8, StopBits.One);
            this.m_port.ReadTimeout = 50000; //50秒超时时间

            this.m_port.RtsEnable = true; // 是否启用请求发送 (RTS) 信号
            //Request To Send 是由计算机发送信号到联接的调制解调器,以请示允许发送数据。

            //this.m_port.DtrEnable = true; // 是否使(DTR)线有效。
            //Data Terminal Ready 是计算机发送到调制解调器的信号,指示计算机在等待接受传输。 

            this.PortName = portName;
        }
    }
    private void CreateModem()
    {
        if (this.m_port == null)
        {
            this.m_port = new SerialPort(this.PortName, this.Boudrate, Parity.None, 8, StopBits.One);
            this.m_port.ReadTimeout = 50000; //50秒超时时间

            this.m_port.RtsEnable = true; // 是否启用请求发送 (RTS) 信号
            //Request To Send 是由计算机发送信号到联接的调制解调器,以请示允许发送数据。

            //this.m_port.DtrEnable = true; // 是否使(DTR)线有效。
            //Data Terminal Ready 是计算机发送到调制解调器的信号,指示计算机在等待接受传输。 
        }
    }

    // Opening modem port
    public Boolean OpenModem()
    {
        CreateModem();
        try
        {
            if (!m_port.IsOpen)
            {
                this.m_port.Open();
            }
            return true;
        }
        catch (Exception ex)
        {
            //這邊你可以自訂發生例外的處理程序
            ReturnMessage(String.Format("出现异常:{0}", ex.ToString()));
            return false;
        }
    }


    // Closing modem port
    public void CloseModem()
    {
        try
        {
            if (!sending && this.m_port != null && this.m_port.IsOpen)
            {
                this.m_port.Close();
                //ReturnMessage("端口已关闭");
            }
        }
        catch (Exception ex)
        {
            //這邊你可以自訂發生例外的處理程序
            ReturnMessage(String.Format("出现异常:{0}", ex.ToString()));
        }
    }
    #endregion

 

拨号器的 “发送命令” 和 “返回接受” 方法是整个Modem 对象的核心,代码如下:

    // 向端口发送命令
    private bool SendData(Object dataInfo)
    {
        if (dataInfo == null) return false;

        CommandInfo sourceInfo = (CommandInfo)dataInfo;

        string returnString = "";
        bool receiveSate = false;

        if (sourceInfo.SourceData != null)
        {
            Byte[] buffer = sourceInfo.SourceData;
            try
            {
                sending = true;
                m_port.Write(buffer, 0, buffer.Length);
                receiving = true;
                Thread.Sleep(200);

                //comport.DiscardInBuffer();    //清空输入缓冲区
                //comport.DiscardOutBuffer();   //清空输出缓冲区

                receiveSate = DoReceive(sourceInfo, ref returnString);

                //返回处理
                switch (sourceInfo.Command)
                {
                    case CommandKey.AT: // 处理 AT 指令
                        Process_AT_Command(returnString);
                        break;

                    case CommandKey.ATD: // 处理 ATD 指令
                        Process_ATD_Command(returnString);
                        break;

                    case CommandKey.ATH: // 处理 ATH 指令
                        Process_ATH_Command(returnString);
                        break;

                    case CommandKey.AT_CFUN: // 处理 AT_CFUN 指令
                        Process_AT_CFUN_Command(returnString);
                        break;

                    case CommandKey.None: //处理 其他未知 指令
                    default:
                        Process_None_Command(returnString);
                        break;
                }   
            }
            catch (Exception ex)
            {
                //这里你可以自定义发生例外的处理程序
                CloseModem();
                ReturnMessage(String.Format("出现异常:{0}", ex.ToString()));
            }
            finally
            {
                sending = false;
            }
        }

        return receiveSate;
    }


    // 接受端口返回数据
    private bool DoReceive(CommandInfo dataInfo, ref String returnString)
    {
        List<Byte> tempList = new List<Byte>();
        Byte[] buffer = new Byte[1024];
        Int32 ticks = 0;
        //string returnString = "";
        bool receiveSate = false;

        while (receiving)
        {
            Thread.Sleep(100);
            if (m_port.BytesToRead > 0)
            {
                try
                {
                    Int32 receivedLength = m_port.Read(buffer, 0, buffer.Length);
                    Array.Resize(ref buffer, receivedLength);
                    foreach (Byte item in buffer)
                    {
                        if (item != 0x0d && item != 0x0a)
                        {
                            tempList.Add(item);
                        }
                    }
                    //tempList.AddRange(buffer);
                    Array.Resize(ref buffer, 1024);
                }
                catch (TimeoutException timeEx)
                {
                    //這邊你可以自訂發生例外的處理程序
                    tempList.Clear();
                    m_port.DiscardInBuffer();    //清空输入缓冲区
                    receiving = false;
                    ReturnMessage(String.Format("读取超时:{0}", timeEx.ToString()));
                }
                catch (Exception ex)
                {
                    //這邊你可以自訂發生例外的處理程序
                    CloseModem();
                    receiving = false;
                    ReturnMessage(String.Format("出现异常:{0}", ex.ToString()));
                }
            }

            //返回字符 > 发送字符
            if (tempList.Count > dataInfo.CommandLength)
            {
                //(测试使用) 返回的所有字符串信息
                //string returnAllString = System.Text.Encoding.Default.GetString(tempList.ToArray()); 

                Byte[] returnByte = new Byte[tempList.Count - dataInfo.CommandLength];
                Array.Copy(tempList.ToArray(), dataInfo.CommandLength, returnByte, 0, returnByte.Length);

                //返回的字符串信息(剔除了发送字符)
                returnString = System.Text.Encoding.Default.GetString(returnByte).ToUpper();
                //returnString = System.Text.Encoding.Unicode.GetString(returnByte).ToUpper();
                receiving = false;
                receiveSate = true;  //表示成功接收返回
            }

            ticks++;
            if (ticks >= dataInfo.sleep100msNumber)
            {
                receiving = false;
                ReturnMessage("接收延时过久!");
            }
        }

        return receiveSate;

        //返回数据监听结束后的业务处理
        //ProcessReceive(dataInfo, returnString);
    }

 

需要使用的 AT 指令定义的方法如下:

    // 检测当前端口是否安装有拨号器
    public bool CheckPortExistModem()
    {
        bool hasModem = false;

        if (!sending && OpenModem())
        {
            CommandInfo dataInfo = new CommandInfo();
            dataInfo.TransType = CommandDirection.Write;
            dataInfo.Command = CommandKey.AT;
            dataInfo.CommandLength = 2;
            dataInfo.SourceDataLength = 4;
            dataInfo.SourceData = ConvertStringToBytes("AT\r\n");
            dataInfo.sleep100msNumber = 10;

            //Thread t = CreateThread();
            //t.Start(dataInfo); //xg

            hasModem = SendData(dataInfo); //不使用多线程的方式
        }

        return hasModem;
    }


    // 发送拨号指令唤醒上位机
    public void DialingNumberToModem(string _number)
    {
        if (!sending && OpenModem())
        {
            CommandInfo dataInfo = new CommandInfo();
            dataInfo.TransType = CommandDirection.Write;
            dataInfo.Command = CommandKey.ATD;
            dataInfo.CommandLength = 15;
            dataInfo.SourceDataLength = 17;
            dataInfo.SourceData = ConvertStringToBytes(string.Format("ATD{0};\r\n", _number));
            dataInfo.sleep100msNumber = 500;

            //Thread t = CreateThread();
            //t.Start(dataInfo);

            SendData(dataInfo); //不使用多线程的方式
        }
    }

    // 发送挂机指令停止拨号
    private void StopDialingNumberToModem()
    {
        if (OpenModem())  // if (!sending && OpenModem())
        {
            CommandInfo dataInfo = new CommandInfo();
            dataInfo.TransType = CommandDirection.Write;
            dataInfo.Command = CommandKey.ATH;
            dataInfo.CommandLength = 3;
            dataInfo.SourceDataLength = 5;
            dataInfo.SourceData = ConvertStringToBytes("ATH\r\n");
            dataInfo.sleep100msNumber = 20;

            //Thread t = CreateThread();
            //t.Start(dataInfo);

            SendData(dataInfo); //不使用多线程的方式
        }
    }

    //重启拨号器
    private void RebootToModem()
    {
        if (OpenModem())  // if (!sending && OpenModem())
        {
            CommandInfo dataInfo = new CommandInfo();
            dataInfo.TransType = CommandDirection.Write;
            dataInfo.Command = CommandKey.AT_CFUN;
            dataInfo.CommandLength = 11;
            dataInfo.SourceDataLength = 15;  // AT+CFUN=1,1\r\nOK
            dataInfo.SourceData = ConvertStringToBytes("AT+CFUN=1,1\r\n");
            dataInfo.sleep100msNumber = 100;

            //Thread t = CreateThread();
            //t.Start(dataInfo);

            SendData(dataInfo); //不使用多线程的方式
        }
    }

    private Byte[] ConvertStringToBytes(String dataString)
    {

       //if (Regex.IsMatch(dataString, "([^0-9a-fA-F])"))
       //{
       //    //表示有不符的字元
       //    ReturnMessage("Block 数据错误");
       //    return null;
       //}

       byte[] buff = Encoding.ASCII.GetBytes(dataString);
       return buff;
   }

 

对应的 AT 指令返回数据处理如下:

        //处理 AT 指令
        private void Process_AT_Command(String returnString)
        {
            if (returnString == "OK")
            {
                //拨号器正常
                ReturnMessage(String.Format("AT指令正常,返回信息:{0}", returnString));
            }
            else
            {
                ReturnMessage(String.Format("AT指令异常,返回信息:{0}", 
                                     returnString != "" ? returnString : ""));
            }
        }

        //处理 ATD 指令
        private void Process_ATD_Command(String returnString)
        {
            switch (returnString)
            {
                case "ERROR":  //当拨打电话不成功时,返回 ERROR
                case "NO DIALTONE": //未检测到拨号音,返回 NO DIALTONE
                    ReturnMessage(String.Format("返回信息:{0},重启拨号器...", returnString));
                    RebootToModem(); //重启拨号器
                    break;

                case "NO CARRIER": //被叫方接通电话,然后主动挂机,信道已释放。返回 NO CARRIER
                    ReturnMessage(String.Format("返回信息:{0}", returnString));
                    break;

                case "BUSY":  //检测到占线信号,直接挂机。返回 BUSY 
                case "OK":    //当接通电话时,返回 OK 
                case "":
                default:
                    ReturnMessage(String.Format("返回信息:{0},发送挂机指令...", 
                                         returnString != "" ? returnString : ""));
                    StopDialingNumberToModem();  //发送挂机指令停止拨号 ATH
                    break;
            }
        }

        //处理 ATH 指令
        private void Process_ATH_Command(String returnString)
        {
            ReturnMessage(String.Format("已挂机,返回信息:{0}", 
                                 returnString != "" ? returnString : ""));
        }

        //处理 AT_CFUN 指令
        private void Process_AT_CFUN_Command(String returnString)
        {
            if (returnString == "OK^SYSSTART")
            {
                //重启成功
                ReturnMessage(String.Format("拨号器重启成功,返回信息:{0}", returnString));
            }
            else ReturnMessage(String.Format("拨号器重启异常,返回信息:{0}", 
                                      returnString != "" ? returnString : ""));
        }

        //处理 其他未知 指令
        private void Process_None_Command(String returnString)
        {
            ReturnMessage(String.Format("拨号器其他情况,返回信息:{0}", 
                                 returnString != "" ? returnString : ""));
        }

 

整个 Modem 类的代码如下:

Modem.cs 整体代码
using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;
using System.Threading;
using System.Windows.Forms;

namespace RequestResponse001CS
{
    public class Modem
    {
        private SerialPort m_port;
        private Boolean sending = false;
        private Boolean receiving;

        private string m_portName = "";   // 串口名称
        private int m_boudrate = 0;       // 波特率
        //private bool m_isWorking = false; // 是否正在使用
        //private string m_answer = "";     // 返回数据缓冲区
        //private DateTime lastUseTime = DateTime.MinValue; //最后一次使用时间

        private SetCallback m_callBack = null; //返回委托事件
        
        #region 委托
        public delegate void SetCallback(String message);

        //委托返回信息
        private void ReturnMessage(String message)
        {
            if (message.Length > 0 && m_callBack != null)
            {
                m_callBack(message);
            }
        }
        #endregion

        #region  属性

        //串口名称
        public string PortName
        {
            get { return m_portName; }
            set { m_portName = value; }
        }

        //是否正在使用
        //public bool IsWorking
        //{
        //    get { return m_isWorking; }
        //    set { m_isWorking = value; }
        //}

        // 串行波特率
        public int Boudrate
        {
            get 
            {
                if (0 == this.m_boudrate)
                {
                    this.m_boudrate = this.DefaultBoudrate; //默认波特率
                }
                return m_boudrate; 
            }
            set { m_boudrate = value; }
        }

        // 默认串行波特率(只读)
        public virtual int DefaultBoudrate
        {
            get { return 9600; }
        }

        // Modem answer to command (只读)
        //public string Answer
        //{
        //    get { return m_answer; }
        //}

        //当前拨号器能否使用 (解决连续使用拨号问题)
        //public bool EnableWork
        //{
        //    get
        //    {
        //        TimeSpan span = DateTime.Now - lastUseTime;
        //        return span.TotalSeconds >= 60;
        //    }
        //    //set { enableUse = value; }
        //}

        #endregion

        #region  构造方法
        public Modem(string _portName, int _baudRate, SetCallback _callBack)
            : this(_portName, _callBack)
        {
            if (_baudRate != 0)
            {
                this.m_boudrate = _baudRate;  // BaudRate 串行波特率
            }
        }

        public Modem(string _portName, SetCallback _callBack)
        {
            CreateModem(_portName);

            if (_callBack != null) m_callBack = _callBack;

            try
            {
                OpenModem();
            }
            catch
            {
                CloseModem();
            }

        }
        #endregion

        #region 拨号器的基本方法
        private void CreateModem(string portName)
        {
            if (this.m_port == null)
            {
                this.m_port = new SerialPort(portName, this.Boudrate, Parity.None, 8, StopBits.One);
                this.m_port.ReadTimeout = 50000; //50秒超时时间

                this.m_port.RtsEnable = true; // 是否启用请求发送 (RTS) 信号
                //Request To Send 是由计算机发送信号到联接的调制解调器,以请示允许发送数据。

                //this.m_port.DtrEnable = true; // 是否使(DTR)线有效。
                //Data Terminal Ready 是计算机发送到调制解调器的信号,指示计算机在等待接受传输。 

                this.PortName = portName;
            }
        }
        private void CreateModem()
        {
            if (this.m_port == null)
            {
                this.m_port = new SerialPort(this.PortName, this.Boudrate, Parity.None, 8, StopBits.One);
                this.m_port.ReadTimeout = 50000; //50秒超时时间

                this.m_port.RtsEnable = true; // 是否启用请求发送 (RTS) 信号
                //Request To Send 是由计算机发送信号到联接的调制解调器,以请示允许发送数据。

                //this.m_port.DtrEnable = true; // 是否使(DTR)线有效。
                //Data Terminal Ready 是计算机发送到调制解调器的信号,指示计算机在等待接受传输。 
            }
        }

        // Opening modem port
        public Boolean OpenModem()
        {
            CreateModem();
            try
            {
                if (!m_port.IsOpen)
                {
                    this.m_port.Open();
                }
                return true;
            }
            catch (Exception ex)
            {
                //這邊你可以自訂發生例外的處理程序
                ReturnMessage(String.Format("出现异常:{0}", ex.ToString()));
                return false;
            }
        }


        // Closing modem port
        public void CloseModem()
        {
            try
            {
                if (!sending && this.m_port != null && this.m_port.IsOpen)
                {
                    this.m_port.Close();
                    //ReturnMessage("端口已关闭");
                }
            }
            catch (Exception ex)
            {
                //這邊你可以自訂發生例外的處理程序
                ReturnMessage(String.Format("出现异常:{0}", ex.ToString()));
            }
        }
        #endregion

        #region 所有发送命令方法 commands method

        // 检测当前端口是否安装有拨号器
        public bool CheckPortExistModem()
        {
            bool hasModem = false;

            if (!sending && OpenModem())
            {
                CommandInfo dataInfo = new CommandInfo();
                dataInfo.TransType = CommandDirection.Write;
                dataInfo.Command = CommandKey.AT;
                dataInfo.CommandLength = 2;
                dataInfo.SourceDataLength = 4;
                dataInfo.SourceData = ConvertStringToBytes("AT\r\n");
                dataInfo.sleep100msNumber = 10;

                //Thread t = CreateThread();
                //t.Start(dataInfo); //xg

                hasModem = SendData(dataInfo); //不使用多线程的方式
            }

            return hasModem;
        }


        // 发送拨号指令唤醒上位机
        public void DialingNumberToModem(string _number)
        {
            if (!sending && OpenModem())
            {
                CommandInfo dataInfo = new CommandInfo();
                dataInfo.TransType = CommandDirection.Write;
                dataInfo.Command = CommandKey.ATD;
                dataInfo.CommandLength = 15;
                dataInfo.SourceDataLength = 17;
                dataInfo.SourceData = ConvertStringToBytes(string.Format("ATD{0};\r\n", _number));
                dataInfo.sleep100msNumber = 500;

                //Thread t = CreateThread();
                //t.Start(dataInfo);

                SendData(dataInfo); //不使用多线程的方式
            }
        }

        // 发送挂机指令停止拨号
        private void StopDialingNumberToModem()
        {
            if (OpenModem())  // if (!sending && OpenModem())
            {
                CommandInfo dataInfo = new CommandInfo();
                dataInfo.TransType = CommandDirection.Write;
                dataInfo.Command = CommandKey.ATH;
                dataInfo.CommandLength = 3;
                dataInfo.SourceDataLength = 5;
                dataInfo.SourceData = ConvertStringToBytes("ATH\r\n");
                dataInfo.sleep100msNumber = 20;

                //Thread t = CreateThread();
                //t.Start(dataInfo);

                SendData(dataInfo); //不使用多线程的方式
            }
        }

        //重启拨号器
        private void RebootToModem()
        {
            if (OpenModem())  // if (!sending && OpenModem())
            {
                CommandInfo dataInfo = new CommandInfo();
                dataInfo.TransType = CommandDirection.Write;
                dataInfo.Command = CommandKey.AT_CFUN;
                dataInfo.CommandLength = 11;
                dataInfo.SourceDataLength = 15;  // AT+CFUN=1,1\r\nOK
                dataInfo.SourceData = ConvertStringToBytes("AT+CFUN=1,1\r\n");
                dataInfo.sleep100msNumber = 100;

                //Thread t = CreateThread();
                //t.Start(dataInfo);

                SendData(dataInfo); //不使用多线程的方式
            }
        }


        //private Thread CreateThread()
        //{
        //    Thread t = new Thread(SendData);
        //    t.IsBackground = true;
        //    return t;
        //}


        // 向端口发送命令
        private bool SendData(Object dataInfo)
        {
            if (dataInfo == null) return false;

            CommandInfo sourceInfo = (CommandInfo)dataInfo;

            string returnString = "";
            bool receiveSate = false;

            if (sourceInfo.SourceData != null)
            {
                Byte[] buffer = sourceInfo.SourceData;
                try
                {
                    sending = true;
                    m_port.Write(buffer, 0, buffer.Length);
                    receiving = true;
                    Thread.Sleep(200);

                    //comport.DiscardInBuffer();    //清空输入缓冲区
                    //comport.DiscardOutBuffer();   //清空输出缓冲区

                    receiveSate = DoReceive(sourceInfo, ref returnString);

                    //返回处理
                    switch (sourceInfo.Command)
                    {
                        case CommandKey.AT: // 处理 AT 指令
                            Process_AT_Command(returnString);
                            break;

                        case CommandKey.ATD: // 处理 ATD 指令
                            Process_ATD_Command(returnString);
                            break;

                        case CommandKey.ATH: // 处理 ATH 指令
                            Process_ATH_Command(returnString);
                            break;

                        case CommandKey.AT_CFUN: // 处理 AT_CFUN 指令
                            Process_AT_CFUN_Command(returnString);
                            break;

                        case CommandKey.None: //处理 其他未知 指令
                        default:
                            Process_None_Command(returnString);
                            break;
                    }   
                }
                catch (Exception ex)
                {
                    //这里你可以自定义发生例外的处理程序
                    CloseModem();
                    ReturnMessage(String.Format("出现异常:{0}", ex.ToString()));
                }
                finally
                {
                    sending = false;
                }
            }

            return receiveSate;
        }

        // 接受端口返回数据
        private bool DoReceive(CommandInfo dataInfo, ref String returnString)
        {
            List<Byte> tempList = new List<Byte>();
            Byte[] buffer = new Byte[1024];
            Int32 ticks = 0;
            //string returnString = "";
            bool receiveSate = false;

            while (receiving)
            {
                Thread.Sleep(100);
                if (m_port.BytesToRead > 0)
                {
                    try
                    {
                        Int32 receivedLength = m_port.Read(buffer, 0, buffer.Length);
                        Array.Resize(ref buffer, receivedLength);
                        foreach (Byte item in buffer)
                        {
                            if (item != 0x0d && item != 0x0a)
                            {
                                tempList.Add(item);
                            }
                        }
                        //tempList.AddRange(buffer);
                        Array.Resize(ref buffer, 1024);
                    }
                    catch (TimeoutException timeEx)
                    {
                        //這邊你可以自訂發生例外的處理程序
                        tempList.Clear();
                        m_port.DiscardInBuffer();    //清空输入缓冲区
                        receiving = false;
                        ReturnMessage(String.Format("读取超时:{0}", timeEx.ToString()));
                    }
                    catch (Exception ex)
                    {
                        //這邊你可以自訂發生例外的處理程序
                        CloseModem();
                        receiving = false;
                        ReturnMessage(String.Format("出现异常:{0}", ex.ToString()));
                    }
                }

                //返回字符 > 发送字符
                if (tempList.Count > dataInfo.CommandLength)
                {
                    //(测试使用) 返回的所有字符串信息
                    //string returnAllString = System.Text.Encoding.Default.GetString(tempList.ToArray()); 

                    Byte[] returnByte = new Byte[tempList.Count - dataInfo.CommandLength];
                    Array.Copy(tempList.ToArray(), dataInfo.CommandLength, returnByte, 0, returnByte.Length);

                    //返回的字符串信息(剔除了发送字符)
                    returnString = System.Text.Encoding.Default.GetString(returnByte).ToUpper();
                    //returnString = System.Text.Encoding.Unicode.GetString(returnByte).ToUpper();
                    receiving = false;
                    receiveSate = true;  //表示成功接收返回
                }

                ticks++;
                if (ticks >= dataInfo.sleep100msNumber)
                {
                    receiving = false;
                    ReturnMessage("接收延时过久!");
                }
            }

            return receiveSate;

            //返回数据监听结束后的业务处理
            //ProcessReceive(dataInfo, returnString);
        }

        //处理 AT 指令
        private void Process_AT_Command(String returnString)
        {
            if (returnString == "OK")
            {
                //拨号器正常
                ReturnMessage(String.Format("AT指令正常,返回信息:{0}", returnString));
            }
            else
            {
                ReturnMessage(String.Format("AT指令异常,返回信息:{0}", 
                                     returnString != "" ? returnString : ""));
            }
        }

        //处理 ATD 指令
        private void Process_ATD_Command(String returnString)
        {
            switch (returnString)
            {
                case "ERROR":  //当拨打电话不成功时,返回 ERROR
                case "NO DIALTONE": //未检测到拨号音,返回 NO DIALTONE
                    ReturnMessage(String.Format("返回信息:{0},重启拨号器...", returnString));
                    RebootToModem(); //重启拨号器
                    break;

                case "NO CARRIER": //被叫方接通电话,然后主动挂机,信道已释放。返回 NO CARRIER
                    ReturnMessage(String.Format("返回信息:{0}", returnString));
                    break;

                case "BUSY":  //检测到占线信号,直接挂机。返回 BUSY 
                case "OK":    //当接通电话时,返回 OK 
                case "":
                default:
                    ReturnMessage(String.Format("返回信息:{0},发送挂机指令...", 
                                         returnString != "" ? returnString : ""));
                    StopDialingNumberToModem();  //发送挂机指令停止拨号 ATH
                    break;
            }
        }

        //处理 ATH 指令
        private void Process_ATH_Command(String returnString)
        {
            ReturnMessage(String.Format("已挂机,返回信息:{0}", 
                                 returnString != "" ? returnString : ""));
        }

        //处理 AT_CFUN 指令
        private void Process_AT_CFUN_Command(String returnString)
        {
            if (returnString == "OK^SYSSTART")
            {
                //重启成功
                ReturnMessage(String.Format("拨号器重启成功,返回信息:{0}", returnString));
            }
            else ReturnMessage(String.Format("拨号器重启异常,返回信息:{0}", 
                                      returnString != "" ? returnString : ""));
        }

        //处理 其他未知 指令
        private void Process_None_Command(String returnString)
        {
            ReturnMessage(String.Format("拨号器其他情况,返回信息:{0}", 
                                 returnString != "" ? returnString : ""));
        }

        //处理监听返回业务
        //private void ProcessReceive(CommandInfo dataInfo, String returnString)
        //{
               
        //}


        private Byte[] ConvertStringToBytes(String dataString)
        {

            //if (Regex.IsMatch(dataString, "([^0-9a-fA-F])"))
            //{
            //    //表示有不符的字元
            //    ReturnMessage("Block 数据错误");
            //    return null;
            //}

            byte[] buff = Encoding.ASCII.GetBytes(dataString);
            return buff;
        }


        /// <summary>
        /// 直接向端口发送命令!
        /// </summary>
        /// <param name="command">命令字符串</param>
        private void SendCommandToModem(string command)
        {
            if (!this.m_port.IsOpen) this.OpenModem();

            byte[] buff = Encoding.ASCII.GetBytes(command);
            try
            {
                this.m_port.Write(buff, 0, buff.Length);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        #endregion
    }
}

 

最后,定义 FormModem 测试页面


测试页面 FormModem 代码如下:

using System;
using System.Windows.Forms;

namespace RequestResponse001CS
{
    public partial class FormModem : Form
    {
        public FormModem()
        {
            InitializeComponent();
        }

        Modem modem;
        private Modem.SetCallback call;

        private void Form1_Load(object sender, EventArgs e)
        {
            //sending = false;
            call = new Modem.SetCallback(this.TakeControl);
            modem = new Modem("COM8", call);
        }


        public void TakeControl(string message)
        {
            if (this.InvokeRequired)
            {
                Modem.SetCallback d = new Modem.SetCallback(TakeControl);
                this.Invoke(d, new object[] { message });
            }
            else
            {
                //MessageBox.Show(message);
                this.txtMessageShow.Text = this.txtMessageShow.Text + message + "\r\n";

                this.txtMessageShow.Select(this.txtMessageShow.Text.Length, 0);
                this.txtMessageShow.ScrollToCaret(); 
            }
        }


        private void Button_AT_Click(object sender, EventArgs e)
        {
            modem.CheckPortExistModem();
        }

        private void Button_ATD_Click(object sender, EventArgs e)
        {
            if (TextBox1.Text.Trim() != "")
            {
                modem.DialingNumberToModem(TextBox1.Text.Trim());
            }
            else modem.DialingNumberToModem("135xxxxxxxxxxx");
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            modem.CloseModem();
        }

    }
}

 

测试页面截图如下:

 

(完)

posted on 2013-05-13 15:51 钢钢 阅读(...) 评论(...) 编辑 收藏

导航

统计

公告