【问题标题】:Serial Port AT Commands for GSM Modem Device not working on loop用于 GSM 调制解调器设备的串行端口 AT 命令无法循环工作
【发布时间】:2017-01-27 06:44:03
【问题描述】:

我目前正在从事一个通过 GSM 调制解调器设备发送 SMS 消息的 .net 项目。我可以很好地发送一条 SMS 消息,但是当我开始循环 AT 命令以向多个收件人发送 SMS 时,应用程序的行为变得非常笨拙。有时它只能向它可以找到的第一个收件人发送短信,大多数时候根本没有。

以下是我向多个收件人发送短信的方法的源代码:

String MessageBody = String.Format("Everyone,\n\nEquipment Current Reading: {0} tph\nCurrent Status: {1}\n\n".Replace("\n",Environment.NewLine), CurrentValue, EqValue);

SerialPort SP = new SerialPort();
SP.PortName = "COM3";



using (TestEntities TE = new TestEntities())
{
    List<vwRecipient_MasterList> RecipientList = TE.vwRecipient_MasterList.Where(r => r.Group_id == R_Group).Select(r => r).ToList();
    foreach (vwRecipient_MasterList Recipient in RecipientList)
    {
        SP.Open();
        String formattedRecipientNo = Char.ConvertFromUtf32(34) + Recipient.MobileNo + Char.ConvertFromUtf32(34);

        SP.Write("AT+CMGF=1" + Char.ConvertFromUtf32(13));
        SP.Write("AT+CMGS=" + formattedRecipientNo + Char.ConvertFromUtf32(13));
        SP.Write(MessageBody + Char.ConvertFromUtf32(26) + Char.ConvertFromUtf32(13));
        SP.Close(); 
    }
}

【问题讨论】:

  • 您应该等待并检查 CMGS 响应。如果第一条短信发送成功,请尝试下一条
  • @manishganvir 我一直在浏览互联网,但找不到有关如何从调制解调器的串行端口读取响应的任何信息。你知道可以指导我的文档吗?
  • 我看到你正在使用 SerialPort() 类。这是否与msdn.microsoft.com/en-us/library/… 相同。如果是这样,您不能使用 Serialport Read 方法吗?检查您是否收到 CMGS 的“OK”响应,然后继续
  • @manishganvir 感谢您指出串行端口类的 Read 方法。我利用ReadExisting() 方法提出了解决方案,如下所示。

标签: c# .net serial-port at-command modem


【解决方案1】:

因此,我根据 MSDN 参考(用于串行端口)和 SO 上的几篇文章对如何使用串行端口类进行了更多研究,我提出了这个非正统的解决方案,涉及使用SerialPort 类提供的 SerialDataReceivedEventHandler 和无限的 while 循环。

首先,我在类范围内创建了两个对 SendSMS(WebMethod) 和 DataRecieved(Event) 方法都可见的属性:

// Holds the text output from the SerialPort 
public string spReadMsg { get; set; }

// Used as a fail-safe terminator of the infinite loop used in the Web Method. 
public DateTime executionTime { get; set; }

以下是 DataRecievedHandler 事件。基本上,此事件所做的只是将来自 SerialPort 的文本响应存储在 SendSMS 方法的 spReadMsg 属性中

private void DataRecievedHandler(object sender, SerialDataReceivedEventArgs e)
{
    try
    {
        SerialPort sp = (SerialPort)sender;
        string indata = sp.ReadExisting();
        Debug.Print("Data Received:");
        Debug.Print(indata);

        // Store to class scope property spReadMsg for the sendSMS method to read.
        spReadMsg = indata;
    }
    catch (Exception ex)
    {
        Debug.Print(ex.Message);          
    }
}

最后,我在 Web 方法中添加了几行代码,以便在成功发送 SMS 消息所需的响应时监听 DataRecieved 事件。

根据这篇关于对调制解调器设备使用 AT 命令的文章:http://www.smssolutions.net/tutorials/gsm/sendsmsat。 SerialPort 应返回 +CMGS: # 响应,以标识消息发送已完成。

所以我所要做的就是等待 +CMGS: 响应,它会让程序知道消息已发送,并准备好将下一条消息发送给下一个收件人。我使用无限 while 循环为 Web 方法制作了一个临时监听器,一旦从串行端口读取响应 +CMGS: 或需要超过 30 秒才能获得所需的响应,该循环就会终止.

[WebMethod]
public void sendSMSMessage_inHouse(String Recipients, String MessageBody)
{

    String sanitizedRecipient = Recipients.Replace(" ", "");
    var RecipientList = Recipients.Split(',').ToList();

    String sanitizedMessage = MessageBody.Replace(@"\n", Environment.NewLine);


    SerialPort SP = new SerialPort();
    SP.PortName = "COM3";
    SP.DataReceived += new SerialDataReceivedEventHandler(DataRecievedHandler);

    SP.Open();

    // Initally set property to the "condtion" value to allow first message to be
    // run without the datarecieved response from the serial port
    spReadMsg = "+CMGS:";

    // Set executionTime inital value for comparison
    executionTime = DateTime.Now;

    foreach (String Recipient in RecipientList)
    {

        // Infinite Loop listens to the response from the serial port
        while (true)
        {
            // If the +CMGS: response was recieved continue with the next message

            // Use Contains comparison for substring check since some of the +CMGS: responses 
            // contain carriage return texts along with the repsonse

            // Then empty the spReadMsg property to avoid the loop from prematurely 
            //sending the next message when the latest serial port response has not yet been 
            //updated from the '+CMGS:' response
            if (!string.IsNullOrEmpty(spReadMsg) && spReadMsg.Contains("+CMGS:"))
            {
                spReadMsg = string.Empty;
                break;
            }

            // If takes longer than 30 seconds to get the response since the last sent 
            //message - break.
            if (DateTime.Now > executionTime.AddSeconds(30))
            {
                break;
            }
        }

        // Once the while loop breaks proceed with sending the next message.            

        String formattedRecipientNo = Char.ConvertFromUtf32(34) + Recipient + Char.ConvertFromUtf32(34);

        SP.Write("AT+CMGF=1" + Char.ConvertFromUtf32(13));
            //Thread.Sleep(800);
        SP.Write("AT+CMGS=" + formattedRecipientNo + Char.ConvertFromUtf32(13));
            //Thread.Sleep(800);
        SP.Write(sanitizedMessage + Char.ConvertFromUtf32(26) + Char.ConvertFromUtf32(13));
            //Thread.Sleep(1000);
            //Thread.Sleep(2000);


        // Get the Datetime when the current message was sent for comparison in
        // the next while loop
        executionTime = DateTime.Now;

    }

    SP.Close();
}

【讨论】:

    猜你喜欢
    • 2019-08-08
    • 1970-01-01
    • 1970-01-01
    • 2012-12-25
    • 1970-01-01
    • 1970-01-01
    • 2015-07-02
    • 2014-02-02
    • 1970-01-01
    相关资源
    最近更新 更多