当我得到GSM调制解调器时如何实现重试机制 例外:没有从手机收到数据?



public class GSMModemConnection { 我做了一个Windows服务来接收短信,我正在使用Wavecom Gsm调制解调器1306B。但过了一秒钟,我得到了一个 例外:没有从手机接收到数据。我在StackOverflow中搜索过,我发现了这个链接 异常:没有从手机收到数据

有人指出要创建一个重试机制,但我不知道如何实现它。

static void Main(string[] args)
{
GSMModemConnection gsm = new GSMModemConnection();
var result = gsm.OpenPort();
Console.WriteLine(result.PortName);

while (true)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
ShortMessage execResult = gsm.ReadSMS(result, "AT+CMGL="ALL"");
Console.WriteLine(execResult.Message);
Console.WriteLine(execResult.Status);
}
}

public class GSMModemConnection
{
public AutoResetEvent receiveNow;
//string strPortName, string strBaudRate
public SerialPort OpenPort()
{
receiveNow = new AutoResetEvent(false);
SerialPort port = new SerialPort();
port.PortName = "COM3";
port.BaudRate = 115200 /*Convert.ToInt32(strBaudRate)*/;               //updated by Anila (9600)
port.DataBits = 8;
port.StopBits = StopBits.One;
port.Parity = Parity.None;
port.ReadTimeout = 300;
port.WriteTimeout = 300;
port.Encoding = Encoding.GetEncoding("iso-8859-1");
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
port.Open();
port.DtrEnable = true;
port.RtsEnable = true;
return port;
}
//Close Port
public void ClosePort(SerialPort port)
{
port.Close();
port.DataReceived -= new SerialDataReceivedEventHandler(port_DataReceived);
port = null;
}
//Execute AT Command
public string ExecCommand(SerialPort port, string command, int responseTimeout, string errorMessage)
{
try
{
//receiveNow = new AutoResetEvent();
port.DiscardOutBuffer();
port.DiscardInBuffer();
receiveNow.Reset();
port.Write(command + "r");
//Thread.Sleep(3000); //3 seconds
string input = ReadResponse(port, responseTimeout);
if ((input.Length == 0) || ((!input.EndsWith("rn> ")) && (!input.EndsWith("rnOKrn"))))
throw new ApplicationException("No success message was received.");
return input;
}
catch (Exception ex)
{
throw new ApplicationException(errorMessage, ex);
}
}
//Receive data from port
public void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (e.EventType == SerialData.Chars)
receiveNow.Set();
}
public string ReadResponse(SerialPort port, int timeout)
{
string buffer = string.Empty;
do
{
if (receiveNow.WaitOne(timeout, false))
{
string t = port.ReadExisting();
buffer += t;
}
else
{
if (buffer.Length > 0)
throw new ApplicationException("Response received is incomplete.");
else
throw new ApplicationException("No data received from phone.");
}
}
while (!buffer.EndsWith("rnOKrn") && !buffer.EndsWith("rn> ") && !buffer.EndsWith("rnERRORrn"));
return buffer;
}
public ShortMessage ReadSMS(SerialPort port, string p_strCommand)
{
// Set up the phone and read the messages
ShortMessage messages = null;
try
{
#region Execute Command
// Check connection
var a = ExecCommand(port, "AT", 300, "No phone connected");
// Use message format "Text mode"
var b = ExecCommand(port, "AT+CMGF=1r", 300, "Failed to set message format.");
// Use character set "PCCP437"
//var c = ExecCommand(port, "AT+CSCS="PCCP437"", 300, "Failed to set character set.");
// Select SIM storage
//var d = ExecCommand(port, "AT+CPMS="SM"", 300, "Failed to select message storage.");
// Read the messages
string input = ExecCommand(port, p_strCommand, 5000, "Failed to read the messages.");
#endregion
#region Parse messages
messages = ParseMessages(input);
#endregion
}
catch (Exception ex)
{
throw ex;
}
if (messages != null)
return messages;
else
return null;
}
public ShortMessage ParseMessages(string input)
{
ShortMessage msg = new ShortMessage();
//ShortMessageCollection messages = new ShortMessageCollection();
try
{
Regex r = new Regex(@"+CMGL: (d+),""(.+)"",""(.+)"",(.*),""(.+)""rn(.+)rn");
Match m = r.Match(input);
while (m.Success)
{
//msg.Index = int.Parse(m.Groups[1].Value);
msg.Index = int.Parse(m.Groups[1].Value);
msg.Status = m.Groups[2].Value;
msg.Sender = m.Groups[3].Value;
msg.Alphabet = m.Groups[4].Value;
msg.Sent = m.Groups[5].Value;
msg.Message = m.Groups[6].Value;
//messages.Add(msg);
m = m.NextMatch();
}
}
catch (Exception ex)
{
throw ex;
}
return msg;
}
}

您确实有一个重试机制,其中包含以下表达式中的 DO-WHILE 循环:

public string ReadResponse(SerialPort port, int timeout)
{
string buffer = string.Empty;
do
{
if (receiveNow.WaitOne(timeout, false))
{
string t = port.ReadExisting();
buffer += t;
}
else
{
if (buffer.Length > 0)
throw new ApplicationException("Response received is incomplete.");
else
throw new ApplicationException("No data received from phone.");
}
}
while (!buffer.EndsWith("rnOKrn") && !buffer.EndsWith("rn> ") && !buffer.EndsWith("rnERRORrn"));
return buffer;
}

您可以做的是降低错误报告机制的粒度。 例如,在这种情况下,行throw new ApplicationException()将中断循环并在 Exec(( 函数中捕获,然后再次抛出。如果您只想等待循环关闭并执行 DO-WHILE 循环,我将替换代码的以下部分:

else
{
if (buffer.Length > 0)
throw new ApplicationException("Response received is incomplete.");
else
throw new ApplicationException("No data received from phone.");
}

跟:

else
{
if (buffer.Length > 0)
bufferError += "Response received is incomplete.n";
else
bufferError += "No data received from phone.n";
}

为什么? 在 DO-WHILE 循环之后,缓冲区将返回字符串。空或某个值。 在代码中,您有:

string input = ReadResponse(port, responseTimeout);
if ((input.Length == 0) || ((!input.EndsWith("rn> ")) && (!input.EndsWith("rnOKrn"))))
throw new ApplicationException("No success message was received.");
return input;

基本上,如果返回的缓冲区是字符串。空将再次引发异常。

通过返回缓冲区错误,您可以稍后决定如何处理它,但 DO-WHILE 循环将至少运行一次,直到满足 WHILE 表达式中的条件。 其余代码应如下所示:

//Thread.Sleep(3000); //3 seconds
string bufferErrors = string.Empty;
string input = ReadResponse(port, responseTimeout, bufferErrors);
if ((input.Length == 0) || ((!input.EndsWith("rn> ")) && (!input.EndsWith("rnOKrn"))))
throw new ApplicationException("No success message was received.");
if (!string.IsNullOrWhiteSpace(bufferErrors))
{
//Handle bufferErrors
}
return input;

请记住在 ReadResponse 中声明 out 参数

public string ReadResponse(SerialPort port, int timeout, out string bufferError)
{
string buffer = string.Empty;
bufferError = string.Empty;

最新更新