使用GSM调制解调器发送英文短信(D-Link DWM-156)
我正在使用AT命令在C#.Net中开发GSM调制解调器(D-Link DWM-156)的应用程序。 发送英文短信时遇到问题。 我试着发送“你好”,但是我在手机里收到□□□□或者……你好。
serialPort1.DataBits = 8; serialPort1.Parity = Parity.None; serialPort1.StopBits = StopBits.One; serialPort1.BaudRate = 9600; serialPort1.DtrEnable = true; serialPort1.RtsEnable = true; serialPort1.DiscardInBuffer(); serialPort1.DiscardOutBuffer(); serialPort1.WriteLine("AT\r"); Thread.Sleep(2000); serialPort1.WriteLine("AT+CMGF=1\r"); Thread.Sleep(1000); serialPort1.WriteLine("AT+CMGS=\"09390149196\"\r") Thread.Sleep(2000); serialPort1.WriteLine("hello" + "\x1A"); Thread.Sleep(1000);
几个修复(可能更多,但我没有看到完整的代码)。
- 不要使用
WriteLine()
而是使用Write()
因为\r
(单独)是命令行和结果代码终止符。 -
SerialPort.WriteLine()
默认写入usASCII编码的字符串,但您的GSM调制解调器需要使用AT命令编码的字符串编码。 将SerialPort.Encoding
属性设置为特定编码并发送CSCS
命令。 您可以通过CSCS=?
询问支持的编码CSCS=?
AT命令。 即使默认GSM应该适用,我也要避免隐含地依赖于此。 - 您不需要在每个命令之后等待,但您必须等待调制解调器应答(检查
OK
或ERROR
字符串)。
来自docs :
命令行由三个元素组成:前缀,正文和终止字符。 命令行前缀由字符“AT”或“at”组成[…]终止字符可以由用户选项(参数S3)选择,默认值为CR。
在伪代码中:
void SendCommand(string command) { serialPort.Write(command + "\r"); // Do not put here an arbitrary wait, check modem's response // Reading from serial port (use timeout). CheckResponse(); } serialPort.DataBits = 8; serialPort.Parity = Parity.None; serialPort.StopBits = StopBits.One; serialPort.BaudRate = 9600; serialPort.DtrEnable = true; serialPort.RtsEnable = true; serialPort.Encoding = Encoding.GetEncoding("iso-8859-1"); serialPort.DiscardInBuffer(); serialPort.DiscardOutBuffer(); SendCommand("AT"); // "Ping" SendCommand("AT+CMGF=1"); // Message format SendCommand("AT+CSCS=\"PCCP437\""); // Character set SendCommand("AT+CMGS=\"123456\"") // Phone number SendCommand("hello" + "\x1A"); // Message
要检查响应(绝对避免任意等待!)你可以从这样的事情开始(原始的未经测试的适应性,所以你可能需要一些调试,请参阅这篇文章 ):
AutoResetEvent _receive; string ReadResponse(int timeout) { string response = string.Empty; while (true) { if (_receive.WaitOne(timeout, false)) { response += _port.ReadExisting(); } else { if (response.Length > 0) throw new InvalidOperationException("Incomplete response."); else throw new InvalidOperationException("No response."); } // Pretty raw implementation, I'm not even sure it covers // all cases, a better parsing would be appreciated here. // Also note I am assuming verbose V1 output with both \r and \n. if (response.EndsWith("\r\nOK\r\n")) break; if (response.EndsWith("\r\n> ")) break; if (response.EndsWith("\r\nERROR\r\n")) break; } return response; }
在发送命令之前添加_receive.Reset()
,当然还要将OnPortDataReceived
添加为SerialPort.DataReceived
事件的处理程序:
void OnPortDataReceived(object sender, SerialDataReceivedEventArgs e) { if (e.EventType == SerialData.Chars) _receive.Set(); }
如果您遇到麻烦(但可以连接),可以用\n
替换\r
\n
。 某些调制解调器不正确 (假设
尚未映射到使用S3
参数的13
以外的任何其他内容)默认情况下使用此字符作为命令行终止符(即使它仅在V1
详细输出中存在于输出中)。 更改代码或发送适当的S3
。