
本文介绍如何使用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: %s\n", msg.Sender)
fmt.Printf("Recipient: %s\n", msg.Recipient)
fmt.Printf("Timestamp: %v\n", msg.Timestamp)
fmt.Printf("Content: %s\n", msg.Text)
fmt.Printf("IsDeliver: %t\n", msg.IsDeliver)
fmt.Printf("IsStatusReport: %t\n", 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脚本,借助成熟库即可在服务端或边缘设备中高效、可靠地完成短信内容提取与结构化处理。










