我目前正在开发一个通过GSM调制解调器设备发送短信的.net项目。我可以设法发送一条短信,但当我开始循环AT命令向多个收件人发送短信时,应用程序的行为变得非常笨重。有时,它只能向可以找到的第一个收件人发送短信,大部分时间都没有。
以下是我向多个收件人发送短信的方法的源代码:
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();
}
}
答案 0 :(得分: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();
}