XuGang

记录一个程序员的成长

 

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

 

定义 ModemManager 调度管理类


ModemManager 类用于对所有 Modem 对象进行管理和调度使用。ModemManager 类代码如下:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;
using System.Threading;

namespace RequestResponse001CS
{
    // 拨号器管理者
    public class ModemManager
    {
        //已经安装了拨号器的串口对象
        private List<Modem> modemCollection = null;

        // ModemCollection 的调度编号
        private int modemNumber = -1;

        //当前有无可使用的串口拨号器
        private bool hasEnabled = false;

        //串口拨号器的重新检测间隔分钟
        private int reCheckMinutes = 30; //默认30分钟

        //波特率配置列表
        private Dictionary<string, int> boudrateCollection = null;

        //获得当前时间
        private DateTime checkDateTime = DateTime.Now;

        private ManagerCallback m_callBack = null; //返回委托事件

        #region 委托
        public delegate void ManagerCallback(String message);

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

        
        #region 属性

        public List<Modem> ModemCollection
        {
            get { return modemCollection; }
        }

        //可使用的拨号器个数
        public int EnabledCount
        {
            get
            {
                if (modemCollection == null) return 0;
                else return modemCollection.Count;
            }
        }

        public bool HasEnabled
        {
            get { return hasEnabled; }
            //set { hasPort = value; }
        }

        //波特率配置列表
        public Dictionary<string, int> BoudrateCollection
        {
            get { return boudrateCollection; }
            set { boudrateCollection = value; }
        }

        //串口拨号器的重新检测间隔分钟
        public int ReCheckMinutes
        {
            get { return reCheckMinutes; }
            set { reCheckMinutes = value; }
        }

        #endregion


        #region  构造方法

        public ModemManager(ManagerCallback callBack) 
        {
            if (callBack != null) m_callBack = callBack;
        }
        public ModemManager(int reCheckMinutes, ManagerCallback callBack)
        {
            this.ReCheckMinutes = reCheckMinutes;
            if (callBack != null) m_callBack = callBack;
        }
        public ModemManager(Dictionary<string, int> boudrateCollection, ManagerCallback callBack)
        {
            this.BoudrateCollection = boudrateCollection;
            if (callBack != null) m_callBack = callBack;
        }
        public ModemManager(Dictionary<string, int> boudrateCollection, int reCheckMinutes,ManagerCallback callBack)
        {
            this.BoudrateCollection = boudrateCollection;
            this.ReCheckMinutes = reCheckMinutes;
            if (callBack != null) m_callBack = callBack;
        }

        #endregion  构造方法


        #region  调度方法

        /// <summary>
        /// 调用拨号器
        /// </summary>
        /// <param name="cardNumber"></param>
        public void ModemInvoking(string cardNumber)
        {
            if (hasEnabled == false)
            {
                // 获得串口上已经安装了拨号器的对象
                this.GetModemCollection();
            }
            if (hasEnabled == true)
            {
                this.ModemCalling(cardNumber);
            }

            //定期检测串口列表
            if (checkDateTime.AddMinutes(ReCheckMinutes) <= DateTime.Now)
            {
                // 重新获得串口上已经安装了拨号器的对象
                this.GetModemCollection();
                checkDateTime = DateTime.Now;
            }
        }


        /// <summary>
        /// 获得串口上安装了拨号器的对象
        /// </summary>
        public void GetModemCollection()
        {
            if (modemCollection == null)
            {
                modemCollection = new List<Modem>();
            }

            int modemCollectionCount = modemCollection.Count;

            //步骤一: 重新获得所有的串口名称(列表)
            string[] portNames = SerialPort.GetPortNames();

            //如果当前串口数目 > 正在使用的COM
            if (portNames.Length > modemCollectionCount)
            {
                ReturnMessage("正在检测可以使用的拨号器..."); //测试使用

                foreach (string portName in portNames)
                {
                    //当前串口名是否存在拨号列表中
                    bool existModem = false;

                    if (modemCollectionCount > 0)
                    {
                        existModem = modemCollection.Exists(delegate(Modem myModem)
                        {
                            return portName == myModem.PortName;
                        });
                    }

                    //如果当前串口名不存在拨号列表中,则重新检测!
                    if (!existModem)
                    {
                        ReturnMessage("正在检测:" + portName); //测试使用

                        AddModemToCollection(portName);
                    }
                }
            }

            // 判断当前计算机有无可使用串口端
            hasEnabled = modemCollection.Count <= 0 ? false : true;
        }


        /// <summary>
        /// 对拨号器的调度使用
        /// </summary>
        private void ModemCalling(string cardNumber)
        {
            if (modemCollection == null) return;

            // 等待线程进入 
            Monitor.Enter(modemCollection);

            Modem modem = null;
            try
            {
                //获得当前调用的串口对象的索引号
                int number = GetModemNumber();

                if (number >= 0) //判断是否存在拨号器
                {
                    modem = modemCollection[number];
                    if (modem != null) // && !modem.IsWorking)
                    {
                        ReturnMessage(string.Format("{0} 正在对 SIM卡:{1} 进行拨号...", 
                                                     modem.PortName,cardNumber)); 
                        modem.DialingNumberToModem(cardNumber); //对 SIM 进行拨号,唤醒上位机
                    }
                }
                else
                {
                    ReturnMessage("没有可使用的拨号器,重新对端口进行检测...");
                    this.GetModemCollection();
                }
            }
            catch
            {
                //再一次检查该 COM 能否使用! (范工提议)
                if (modem != null)
                {
                    string portName = modem.PortName;
                    modemCollection.Remove(modem); //从可用列表去除
                    modem.CloseModem();

                    AddModemToCollection(portName);
                }
            }
            finally
            {
                if (modemCollection != null)
                {
                    // 通知其它对象
                    Monitor.Pulse(modemCollection);
                    // 释放对象锁 
                    Monitor.Exit(modemCollection);
                }
            }
        }


        /// <summary>
        /// 获得对 ModemCollection 的调度编号
        /// </summary>
        /// <returns></returns>
        private int GetModemNumber()
        {
            lock (this)
            {
                if (modemNumber + 1 >= modemCollection.Count)
                {
                    if (modemCollection.Count == 0) modemNumber = -1;
                    else modemNumber = 0;
                }
                else
                {
                    modemNumber++;
                }

                return modemNumber;
            }
        }


        /// <summary>
        /// 添加 Modem 到 modemCollection
        /// </summary>
        private void AddModemToCollection(string portName)
        {
            Modem myModem = null;

            //是否设置波特率?
            if (boudrateCollection != null
                && boudrateCollection.ContainsKey(portName)
                && boudrateCollection[portName] != 0)
            {
                myModem = new Modem(portName, boudrateCollection[portName], ReturnMessage);
            }
            else
            {
                myModem = new Modem(portName, ReturnMessage);
            }

            bool hasModem = myModem.CheckPortExistModem();
            if (hasModem)
            {
                modemCollection.Add(myModem);
            }
            else
            {
                myModem.CloseModem();
                myModem = null;
            }
        }


        /// <summary>
        /// 释放所有的串口资源
        /// </summary>
        public void CloseModemCollection()
        {
            if (modemCollection != null)
            {
                for (int i = 0; i < modemCollection.Count; i++)
                {
                    modemCollection[i].CloseModem();
                    modemCollection[i] = null;
                }
                modemCollection = null;
            }

            if (boudrateCollection != null)
            {
                boudrateCollection = null;
            }
        }

        #endregion
    }
}

 

定义 FormModemManager 测试界面类


测试界面 FormModemManager 类用于对 ModemManager 对象进行测试,代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

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

        ModemManager ModemManager;
        Thread thread;

        private void FormModemManager_Load(object sender, EventArgs e)
        {
            ModemManager = new ModemManager(5, TakeControl);
        }

        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 FormModemManager_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (thread != null)
            {
                thread.Abort();
            }
        }

        private void Button_Run_Click(object sender, EventArgs e)
        {
            thread = new Thread(new ThreadStart(Run));
            thread.Start();
        }

        private void Run()
        {
            try
            {
                // 获得串口上已经安装了拨号器的对象
                ModemManager.GetModemCollection();

                if (ModemManager.HasEnabled == false)
                {
                    TakeControl("当前计算机无可使用的串口拨号器!");
                }
                else
                {
                    TakeControl("当前计算机可使用的拨号器如下:");
                    List<Modem> modemCollection = ModemManager.ModemCollection;
                    for (int i = 0; i < modemCollection.Count; i++)
                    {
                        Modem modem = modemCollection[i];
                        TakeControl(string.Format("端口名:{0},波特率:{1}",
                                    modem.PortName, modem.Boudrate.ToString()));
                    }
                }

                while (ModemManager.HasEnabled)
                {
                    // 调用拨号器
                    if (string.IsNullOrEmpty(txtCardNumber.Text.Trim()))
                    {
                        ModemManager.ModemInvoking("135xxxxxxxx"); // SIM 卡号
                    }
                    else ModemManager.ModemInvoking(txtCardNumber.Text.Trim());

                    Thread.Sleep(5000);
                }

                TakeControl("程序运行结束!");
            }
            finally
            {
                // 释放所有串口资源组件
                ModemManager.CloseModemCollection();
            }
        }

        //运行停止
        private void Button_Stop_Click(object sender, EventArgs e)
        {
            if (ModemManager != null)
            {
                ModemManager.CloseModemCollection();
            }
        }


    }
}

 

测试页面截图如下:

 

参考文章 :http://www.dotblogs.com.tw/billchung/category/5702.aspx?Show=All

源码下载:http://download.csdn.net/detail/guangrou/5375603

(完)

posted on 2013-05-13 16:24  钢钢  阅读(1496)  评论(2编辑  收藏  举报

导航