
本文介绍如何使用go语言直接解析gsm sms pdu格式数据,包括从at指令(如at+cmgl=4)返回的十六进制pdu字符串解码为发件人、接收人、时间戳和短信正文,并提供完整可运行示例及关键注意事项。
本文介绍如何使用go语言直接解析gsm sms pdu格式数据,包括从at指令(如at+cmgl=4)返回的十六进制pdu字符串解码为发件人、接收人、时间戳和短信正文,并提供完整可运行示例及关键注意事项。
在嵌入式通信、iot网关或Modem管理场景中,常需通过串口发送AT指令(如AT+CMGF=0切换为PDU模式,再执行AT+CMGL=4读取所有短信)获取原始PDU字符串。这类字符串(例如0791361907002039040C9136198748701300005150713220052308C8303A8C0EA3C3)是十六进制编码的二进制协议数据,无法直接阅读。幸运的是,Go生态已有成熟、轻量且符合3GPP TS 23.040规范的第三方库支持完整解析。
推荐使用 github.com/xlab/at/sms —— 它专为AT指令交互场景设计,完整实现SMS PDU的读取(ReadFrom)、编码(WriteTo)与字段映射,支持GSM 7-bit、UCS2(UTF-16BE)编码、TP-UDHI标志、状态报告等核心特性。
以下是一个最小可运行示例:
package main import ( "encoding/hex" "fmt" "log" "github.com/xlab/at/sms" ) func main() { // 来自 AT+CMGL=4 响应的 PDU 十六进制字符串(不含行首 +CMGL:...) pduHex := "0791361907002039040C9136198748701300005150713220052308C8303A8C0EA3C3" // 解码为字节切片 pduBytes, err := hex.DecodeString(pduHex) if err != nil { log.Fatal("PDU hex decode failed:", err) } // 初始化 SMS 消息结构体并解析 msg := new(sms.Message) if _, err := msg.ReadFrom(pduBytes); err != nil { log.Fatal("PDU parsing failed:", err) } // 输出结构化信息 fmt.Printf("Sender: %sn", msg.Sender) fmt.Printf("Recipient: %sn", msg.Recipient) fmt.Printf("Timestamp: %vn", msg.Timestamp) fmt.Printf("Content: %sn", msg.Text) fmt.Printf("IsDeliver: %tn", msg.IsDeliver) fmt.Printf("IsStatusReport: %tn", msg.IsStatusReport) }
运行后输出类似:
立即学习“go语言免费学习笔记(深入)”;
Sender: +639170000293 Recipient: +639178840731 Timestamp: 2015-05-07 17:32:20 +0000 UTC Content: Hahahaha IsDeliver: true IsStatusReport: false
✅ 关键注意事项:
- sms.Message.ReadFrom() 期望输入为原始PDU字节流(即已由hex.DecodeString()转换后的[]byte),而非原始十六进制字符串;
- PDU可能包含状态报告(TP-MTI = 0x05)或长短信分段(TP-UDHI = 1),该库会自动识别并填充对应字段(如UserDataHeader);
- 若短信含中文等Unicode字符,PDU通常使用UCS2编码(TP-DCS = 0x08),库会自动按UTF-16BE解码,无需手动处理;
- 实际项目中建议配合串口库(如github.com/tarm/serial)封装AT指令交互逻辑,将AT+CMGL响应中的PDU部分提取后统一解析;
- 该库不依赖CGO,纯Go实现,兼容交叉编译(如ARM嵌入式设备)。
综上,Go完全胜任SMS PDU解析任务——无需调用外部工具或Python脚本,借助成熟库即可在服务端或边缘设备中高效、可靠地完成短信内容提取与结构化处理。