使用AT命令与PDU模式发送长短信失败问题求助
我用AT命令发送超过160字符的分条短信,单条短信、特殊字符短信均能正常发送,但分条发送时系统提示发送成功,接收方却收不到短信。以下是基于NodeGSM模块修改的Node.js代码(使用node-sms-pdu生成PDU),以及服务器返回的PDU信息与发送日志。我已尝试调整短信发送间隔、模式、号码及消息格式,问题仍未解决。
核心代码
async sendSMS(msisdn, message) { message += " "; // 判断消息是否包含GSM 7-bit默认字符集以外的字符 const useUCS2 = !isGSMCharacterSet(message); // 根据消息内容设置字符集 const characterSet = useUCS2 ? GSM.CharacterSet.UCS2 : GSM.CharacterSet.GSM; await this.setCharacterSet(characterSet); await this.setMessageFormat(GSM.MessageFormat.PDU); // 生成消息PDU,假设generateSubmit会处理分段需求 const encoding = useUCS2 ? 'ucs2' : 'gsm'; const pdus = smsPdu.generateSubmit(msisdn, message, { encoding }); // 依次发送每个PDU分段 const results = []; for (const pdu of pdus) { // 发送PDU的字节长度,而非消息长度 let length = pdu.length await this.runCommand(`AT+CMGS=${length}`); // 发送PDU并存储结果 const result = await this.runCommand(`${pdu.hex}${CTRL_Z}`); if (result.startsWith('+CMGS:')) { console.log('Segment sent successfully:', result); } else { console.error('Error sending segment:', result); break; // 可优化此处异常处理逻辑 } await new Promise(resolve => setTimeout(resolve, 5000)); // 发送下一段前等待5秒 results.push(result); } return (results, pdus); }
服务器返回信息
正在通过COM18向79429010发送短信:testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest
分段发送成功: +CMGS: 149
分段发送成功: +CMGS: 150
检查COM17状态
正在通过COM18向79429010发送短信:testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest
分段发送成功: +CMGS: 149
分段发送成功: +CMGS: 150
检查COM17状态
response2: [
{
buffer: <Buffer 00 41 00 08 81 97 24 09 01 00 00 a0 05 00 03 00 02 01 e8 e5 39 9d 5e 9e d3 e9 e5 39 9d 5e 9e d3 e9 e5 39 9d 5e 9e d3 e9 e5 39 9d 5e 9e d3 e9 e5 39 9d ... 102 more bytes>,
hex: '0041000881972409010000A0050003000201E8E5399D5E9ED3E9E5399D5E9ED3E9E5399D5E9ED3E9E5399D5E9ED3E9E5399D5E9ED3E9E5399D5E9ED3E9E5399D5E9ED3E9E5399D5E9ED3E9E5399D5E9ED3E9E5399D5E9ED3E9E5399D5E9ED3E9E5399D5E9ED3E9E5399D5E9ED3E9E5399D5E9ED3E9E5399D5E9ED3E9E5399D5E9ED3E9E5399D5E9ED3E9E5399D5E9ED3E9E5399D5E9ED3E9',
length: 151,
encoding: 'gsm'
},
{
buffer: <Buffer 00 41 00 08 81 97 24 09 01 00 00 17 05 00 03 00 02 02 ca 73 3a bd 3c a7 d3 cb 73 3a bd 3c a7 83 00>,
hex: '004100088197240901000017050003000202CA733ABD3CA7D3CB733ABD3CA78300',
length: 32,
encoding: 'gsm'
}
]
短信已成功从COM18发送至79429010。
短信已成功从COM18发送至79429010。
1. 启用模块的Phase 2+短信支持
部分GSM模块需要提前开启Phase 2+支持才能处理长短信,在初始化阶段添加以下命令:
await this.runCommand('AT+CSMS=1');
该命令返回+CSMS: 1,1,1即为启用成功。
2. 强化发送结果校验
修改发送逻辑,确保每段短信不仅收到+CMGS:标识,还需确认模块返回OK,避免模块缓存未发送的情况:
const result = await this.runCommand(`${pdu.hex}${CTRL_Z}`); if (result.startsWith('+CMGS:') && result.includes('OK')) { console.log('Segment sent successfully:', result); } else { console.error('Error sending segment:', result); break; }
3. 验证模块短信状态
发送完成后,通过以下命令检查模块内的短信存储与发送状态,确认分段是否真的被推送至网络:
const status = await this.runCommand('AT+CMGF=0; AT+CMGL="ALL"'); console.log('SMS module status:', status);
4. 调整发送间隔
当前设置的5秒间隔可尝试延长至10秒,部分运营商或模块对连续短信发送有频率限制,过短的间隔可能导致分段被丢弃。
5. 确认PDU的TP-UDHI位设置
从返回的PDU数据看,TP-UDHI位(TPDU第2字节的第6位)已正确设置为1,标识包含用户数据头(UDHI),此点无需修改,但如果更换PDU生成库,需重新验证该字段。
内容的提问来源于stack exchange,提问作者Paul Azzopardi

