串行端口AT用于GSM调制解调器设备的命令不在环路上工作



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

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

String MessageBody = String.Format("Everyone,nnEquipment Current Reading: {0} tphnCurrent Status: {1}nn".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(); 
}
}

因此,我在MSDN参考(针对串行端口)和So的几篇文章的基础上,对如何使用串行端口类进行了更多的研究,并提出了这个非正统的解决方案,其中包括使用SerialPort类提供的SerialDataReceivedEventHandler和无限while循环。

首先,我在类作用域中创建了两个属性,这两个属性对SendSMS(WebMethod)和DataRecived(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; }

以下是DataReceiveedHandler事件。基本上,此事件所做的只是将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消息所需响应时侦听DataRecived事件。

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

因此,我所要做的就是等待+CMGS:响应,这将使程序知道消息已经发送,并准备将下一条消息发送给下一个收件人。我为web方法制作了一个临时监听器,使用了一个无限while循环,一旦从串行端口读取响应+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();
}

最新更新