使用 GSM 调制解调器发送英文短信 (D-Link DWM-156)

send English SMS with GSM Modems (D-Link DWM-156)(使用 GSM 调制解调器发送英文短信 (D-Link DWM-156))
本文介绍了使用 GSM 调制解调器发送英文短信 (D-Link DWM-156)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 AT 命令在 C#.Net 中为 GSM 调制解调器 (D-Link DWM-156) 开发应用程序.我在发送英文短信时遇到问题.我尝试发送你好",但我在手机中收到 □□□□ 或者...除了你好.

I am developing an application for GSM Modems (D-Link DWM-156) in C#.Net using AT commands. I have a problem sending English SMS. I try to send "hello", But I receive □□□□ in my phone or ...exept hello.

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
");
Thread.Sleep(2000);

serialPort1.WriteLine("AT+CMGF=1
");
Thread.Sleep(1000);

serialPort1.WriteLine("AT+CMGS="09390149196"
")
Thread.Sleep(2000);

serialPort1.WriteLine("hello" + "x1A");
Thread.Sleep(1000);

推荐答案

修复很少(可能更多,但我没有看到完整代码).

Few fixes (maybe more but I don't see full-code).

  • 不要使用 WriteLine() 而是使用 Write() 因为 (单独)是命令行和结果代码终止符.
  • SerialPort.WriteLine() 默认情况下会写入 usASCII 编码字符串,但您的 GSM 调制解调器需要使用 AT 命令指定的编码字符串.将 SerialPort.Encoding 属性设置为特定编码并发送 CSCS 命令.您可以使用 CSCS=? AT 命令询问支持的编码.即使应该应用默认的 GSM,我也会避免隐含地依赖它.
  • 您不需要在每个命令之后等待,但您必须等待调制解调器应答(检查 OKERROR 字符串).
  • Do not use WriteLine() but Write() because for (alone) is the command line and result code terminator character.
  • SerialPort.WriteLine() by default writes a usASCII encoded string but your GSM modem expect strings encoded as specified with an AT command. Set SerialPort.Encoding property to a specific encoding and send CSCS command. You can ask supported encodings with CSCS=? AT command. Even if default GSM should apply I'd avoid to rely implicitly on this.
  • You do not need to wait after each command but you have to wait for modem answer (checking for OK or ERROR strings).

来自 docs:

命令行由三个元素组成:前缀、正文和终止字符.命令行前缀由字符AT"或at"组成 [...] 终止字符可以由用户选项(参数 S3)选择,默认为 CR.

A command line is made up of three elements: the prefix, the body, and the termination character. The command line prefix consists of the characters "AT" or "at" [...] The termination character may be selected by a user option (parameter S3), the default being CR.

在伪代码中:

void SendCommand(string command) {
    serialPort.Write(command + "
");

    // 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

要检查响应(绝对避免任意等待!)你可以从这样的东西开始(未经测试的原始适配,所以你可能需要一些调试,另见 这篇文章):

To check response (absolutely avoid arbitrary waits!) you can start with something like this (raw untested adaption so you may need some debugging, see also this post):

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 
 and 
.
        if (response.EndsWith("
OK
"))
            break;

        if (response.EndsWith("
> "))
            break;

        if (response.EndsWith("
ERROR
"))
            break;
    }

    return response;
}

在发送命令之前添加 _receive.Reset(),当然还要添加 OnPortDataReceived 作为 SerialPort.DataReceived 事件的处理程序:

Adding _receive.Reset() just before you send your command and of course also adding OnPortDataReceived as handler for SerialPort.DataReceived event:

void OnPortDataReceived(object sender,
    SerialDataReceivedEventArgs e)
{
    if (e.EventType == SerialData.Chars)
        _receive.Set();
}

如果您遇到问题(但可以连接),您可以将 替换为 .某些调制解调器不正确(假设 没有使用 S3 参数映射到 13 以外的任何其他东西)默认情况下将此字符用作命令行终止符(即使它应该只出现在 V1 详细输出的输出中).更改您的代码或发送适当的 S3.

If you have some trouble (but you can connect) you may replace with . Some modems incorrectly (assuming <CR> has not been mapped to anything else than 13 using S3 parameter) use this character as command line terminator by default (even if it should be present in output only for V1 verbose output). Either change your code or send appropriate S3.

这篇关于使用 GSM 调制解调器发送英文短信 (D-Link DWM-156)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)