python smspdu是处理GSM短信PDU模式的编码解码方案,通过gsmmodem或sms-pdu库,能轻松实现中文短信的发送与接收,解决文本模式不支持Unicode的问题。
python smspdu基础教程:为什么PDU模式才是中文短信王道
短信协议分为Text模式和PDU模式,Text模式只能使用ASCII字符,中文、特殊符号都无法直接发送,PDU模式遵循GSM 03.40标准,支持7bit(英文数字)、8bit(二进制数据)和UCS2(统一字符编码),中文短信必须使用PDU模式,将用户数据编码为UCS2十六进制串,从业内专家指出,许多开发者在初次接触时以为设置“AT+CMGF=0”就可轻松完成,实际上PDU结构包含SMSC地址、目标号码、协议标识、编码方式等多个字段,用python smspdu库可避免手动拼接十六进制串的繁琐。
常见误区认为PDU模式只和AT指令绑定,python smspdu库通过封装底层编码,你只需传入收件号码和正文,库自动选择编码类型,统计显示,超过70%的短信API调试问题源自编码方式错误,理解PDU基本结构是解决中文短信壁垒的第一步。
python smspdu库选择对比:7bit与UCS2解码哪个更好用
目前主流选择集中在gsmmodem和sms-pdu两个库,手动实现编码适用于学习或极端定制场景,两者的核心能力与适用场景差异明显:
| 特性 | gsmmodem | sms-pdu | 手动编码 |
|---|---|---|---|
| PDU编码 | 内置,支持7bit/UCS2/8bit | 核心功能,需自行管理AT指令 | 完全自定义 |
| AT指令 | 完整封装(发送、读取、信号) | 无,需配合pyserial | 自行实现 |
| 长短信 | 自动分片 | 需手动拼接 | 手动分片 |
| 中文支持 | UCS2自动编码,解码UTF-8 | UCS2编码,解码raw | 灵活但易出错 |
| 文档 | 完善,社区活跃 | 基础API说明 | 仅依赖GSM标准文档 |
根据GSMA标准,7bit编码用于英文和数字,UCS2对应中文、日文等双字节字符。gsmmodem在UCS2解码时会自动转为Unicode,sms-pdu保留原始十六进制,需手动转换,如果你的业务涉及多语言混合发送或包含表情符号,UCS2编码是唯一选择。
python smspdu实操:发送短信时常见中文问题
环境初始化
使用gsmmodem时,安装并初始化串口连接:
pip install gsmmodem
通过脚本连接短信猫或软Modem:
from gsmmodem import GsmModem
modem = GsmModem('/dev/ttyUSB0', 115200)
modem.connect()
国内常见短信猫(如SIMCom800)默认波特率115200,Windows下COM口需更换为'COM3'。
发送中文短信
直接传入中文字符串,库自动选择UCS2编码:
modem.sendSms('+8613912345678', '您好,短信测试')
对应日志中PDU格式类似:
0011000D91683191234567F80008C30C904A8B77796D4B8B6D4B
解决中文乱码
乱码通常因两处错误引起:
- 未指定PDU模式:AT+CMGF=0必须在发送前设置。
- 接收端编码解析:部分网关对UCS2解码要求前置SMSC号码正确,若使用
sms-pdu库,手动构造PDU时可添加encoding='ucs2'参数:from sms_pdu import encode_sms pdu = encode_sms('+8613912345678', '您好', encoding='ucs2')发送时通过AT+CMGS=PDU长度<回车>,再输入PDU串+Ctrl+Z完成。
处理长短信
中文短信单条上限70个汉字,超过时需分片,分片后每段PDU开头附加UDHI头(用户数据头)。gsmmodem自动完成分片并标注CSMS(串联短信),若使用sms-pdu库,需手动拆分字符串并调用多次编码,接收端再按CSMS组合,行业共识认为,长短信分片数不宜超过6片,否则部分网关会丢弃。
python smspdu在国内短信猫场景的应用:配置与优化
国内物联网项目常选购西门子TC35、华为E3372或移远EC系列模块,这些模块通过USB转串口与工控机连接,python smspdu库可以配合pyserial直接控制串口,适合对成本敏感、日均发送量在几百至几千条的客户。
关键配置参数包括:
- 波特率:默认115200,部分旧模块需切换到9600。
- PIN码:SIM卡需禁用PIN码,否则模块无法注册网络。
- 信号检测:通过
AT+CSQ查询信号强度,低于10时应检查天线。 - AT超时:设置串口读超时不低于5秒,防止响应未完全读取导致PDU丢失。
在深圳地区的产线监控项目中,利用gsmmodem监听+CMTI通知实时接收短信,再调用modem.readStoredSms()解码为中文,注意模块接收PDU时默认以十六进制格式存储,需设置AT+CNMI=2,1使所有新短信直接上报。
python smspdu与云API的成本对比:自建还是采购
短信猫硬件成本在200至500元(取决于模块型号和天线配件),每张SIM卡可发送量受运营商限制,国内一般套餐允许日发送500-1000条,超出后单条成本约0.05元(非精确数字,行业参考价),云API按条计费,通道单价约0.03-0.06元,但包含高并发、异地负载和技术支持。
具体选择场景:
- 自建场景:需要本地部署,发送量与硬件能力匹配,适用于工厂设备报警、内部系统通知。
- 云API场景:日发送量过万,需要全网通道优化、缺省生成内容,对开发时间敏感。
python smspdu库的优势在于成本曲线可预测:发送量稳定时,硬件的长期摊销低于云API,但维护成本包括串口排障、SIM卡欠费、运营商策略变更等,云API屏蔽了这些复杂度,代价是按量付费。
关于python smspdu的另一个常见疑问是价格差异其实库本身免费,成本主要集中在硬件和SIM卡资费上。
关于python smspdu的常见疑问与解答
python smspdu能直接在Windows上使用吗?
Windows下需通过虚拟串口(如Virtual Serial Port)连接软猫,或使用USB连接真实模块,pyserial和gsmmodem均支持Windows,串口名使用COM1格式,注意权限问题,win10以后需以管理员身份运行Python。
为什么解码出来的中文显示为Unicode转义符?
大部分原因是PDU解码时未将UCS2转换回中文,在gnokii或python-gsmmodem中,解码后的返回对象包含text属性,默认以Unicode字符串输出,若使用sms-pdu库的decode_sms(),得到的是十六进制字节数组,需调用.decode('utf-16-be')手动转换。
长短信分片后接收端顺序混乱如何处理?
长短信每片PDU的UDHI头包含一个16位Reference Number,接收端据此重组。gsmmodem内部维护该编号,若自建分片,每片必须使用相同Reference Number并在头部标明片数序号,实践时建议设置CSMS参考号为随机整数,防止同一SIM接收到多条长短信时混淆。
首发原创文章,作者:世雄 - 原生数据库架构专家,如若转载,请注明出处:https://idctop.com/article/500148.html
