如何在VB.NET中通过AT指令获取短信发送的实时投递状态?
VB.NET中通过AT指令发送短信并获取投递状态实现方案
一、核心逻辑:通过AT指令响应判断发送结果
发送AT+CMGS指令后,模块会返回特定响应标识状态:
- 发送流程中,模块先返回
>提示符,此时输入短信内容并追加Ctrl+Z(ASCII码26)完成发送 - 发送成功:模块返回
+CMGS: <消息ID>,末尾伴随OK - 发送失败:返回
ERROR或+CMS ERROR: <错误码>类响应
二、VB.NET实现步骤(带UI状态提示)
1. 串口基础配置
确保已初始化与GSM模块匹配的SerialPort实例(波特率、奇偶校验等参数需和模块一致),以下示例假设串口实例名为sp。
2. 异步发送与状态更新(避免UI阻塞)
串口通信属于耗时操作,必须用异步方法保证界面流畅,同时实现状态提示:
Private Async Sub btnSendSMS_Click(sender As Object, e As EventArgs) Handles btnSendSMS.Click ' 弹出发送中提示 MessageBox.Show("发送中", "状态提示", MessageBoxButtons.OK, MessageBoxIcon.Information) Try ' 1. 设置短信为文本模式 sp.WriteLine("AT+CMGF=1" & vbCrLf) Await Task.Delay(200) ' 等待模块响应,时长可根据模块调整 Dim resp1 As String = sp.ReadExisting() If Not resp1.Contains("OK") Then MessageBox.Show("发送失败:无法设置文本模式", "状态提示", MessageBoxButtons.OK, MessageBoxIcon.Error) Return End If ' 2. 发起短信发送请求 sp.WriteLine($"AT+CMGS=""{txtPhone.Text}""" & vbCrLf) Await Task.Delay(300) Dim resp2 As String = sp.ReadExisting() If Not resp2.Contains(">") Then MessageBox.Show("发送失败:未收到模块输入提示符", "状态提示", MessageBoxButtons.OK, MessageBoxIcon.Error) Return End If ' 3. 发送短信内容+结束符(Ctrl+Z) sp.WriteLine("HELLO WORLD" & Chr(26)) Await Task.Delay(1000) ' 等待模块处理并返回结果 Dim finalResp As String = sp.ReadExisting() ' 4. 判断最终发送结果 If finalResp.Contains("+CMGS:") AndAlso finalResp.Contains("OK") Then MessageBox.Show("消息已发送", "状态提示", MessageBoxButtons.OK, MessageBoxIcon.Information) Else Dim errorMsg As String = "发送失败" If finalResp.Contains("+CMS ERROR:") Then errorMsg &= $":{finalResp.Split("+CMS ERROR:")(1).Trim()}" End If MessageBox.Show(errorMsg, "状态提示", MessageBoxButtons.OK, MessageBoxIcon.Error) End If Catch ex As Exception MessageBox.Show($"发送失败:{ex.Message}", "状态提示", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try End Sub
3. 关键注意事项
- 必须用异步操作:同步方法会导致UI在等待串口响应时卡死,无法正常显示状态提示
- 适配模块响应速度:不同GSM模块的响应时长不同,可根据实际情况调整
Task.Delay的等待时间 - 错误码解析:
+CMS ERROR后的数字对应具体错误原因,可查阅模块AT指令手册获取详细说明
三、实时终端投递状态的补充
AT+CMGS仅能判断短信是否成功提交到运营商网络,若要获取终端是否实际收到短信,需额外配置:
- 发送
AT+CNMI=2,2指令,开启短信状态报告推送 - 当终端收到短信后,模块会返回
+CDS: <状态报告内容>响应,解析其中的状态字段即可得到最终投递结果
内容的提问来源于stack exchange,提问作者John Calvin Anas
相关产品推荐
相关产品推荐

