因此,我根据 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();
}