EM310,AT指令之_文本和PDU短信解析
简介
本文主要将了接收中英文短信的各个字段的解释.
- 短信编码的相关知识
- 0.参数设置
- 发送中文短信
- 发送英文短信
- 1、接收中文短信
- 2、接收纯英文或数字
短信编码的相关知识
操作SIM卡中的数据操作主要有两个地方,一个是短信操作,还有一个通讯录操作,两种编码略有差别:
1、短信息操作:
在短信息中,默认一条短信的最大长度为140个字节。
纯ASCII字符主要采用7-bit编码格式,即只是利用了字符的后7位数据,这样160个ASCII字符只占用140个字节。这样我们手机的一条短信就可以发送160个ASCII字符了
(160*7=1120=140*8)
160*7 | 140*8 |
7-bit | 8-bit |
ASCII | ucs2的一半 |
包含汉字的字符采用UCS2编码格式,即UNICODE的2字节编码格式。这样每个汉字占用两个字节,只要短信中包含中文,整条短信的字符都要采用UCS2编码,这样一条短信最多就只能发送70个字符(汉字,英文字符,标点等)了。
2、通讯录操作:
通讯录中的姓名长度限制不一样,本人使用的TD模块限制长度为14个字节。
单独的ASCII字符正常都使用8-bit编码格式,即每个字节都占用8位,这也是最为正常的存储格式了。
如果包含中文等字符,则正常采用80编码格式,即整个姓名字符以80开头,后面跟上UCS2数据,但有些情况下又会采用81或者82开头。
a) 80 开头:
80开头的为ucs2格式(注意:后面的字符必须有中文才行,否则可能是以80开头的纯ASCII字符串),大头在前,小头在后。
例1:中国(\u4e2d\u56fd)
UNICODE编码为:4E2D56FD
用ucs2的80方案表示是:80 4E2D 56FD
例2:杜10娘 (\u675c \0031 \0030 \u5a18)1和0的unicode见下面的表.
UNICODE编码为:675C 0031 0030 5A18
用ucs2的80方案表示是:80675C003100305A18
显然只要有中文,数字也得占用两个字节。
b) 81 开头:
81开头的格式中,包含一个基址(一个字节)。有这个基址,就可以用一个字节表示一个ucs2字符了。
在格式上,81是标识,后一个字节表示整个字符串长度,再后面一个字节是基址,再往后的就都是数据了。先举一例:
例3:杜杜杜
UNICODE编码为:675C 675C 675C
0x675C
67 0x6700
5C 0x005C
用ucs2的80方案表示是:80 675C 675 C675C
用ucs2的81方案表示是:81 03 CE DC D CDC
分析一下UCS2的81方案:8103CEDCDCDC
81:为标记
03:表示整个字符串为3个字符
CE:一个字节为基址。解析的方法为:将基址(CE)左移七位,并在最高位添加一个0(这样就16位啦)。此时基址变为0x6700,然后再判断后面的数据字节。
DCDCDC:3个数据字节 DC, DC, DC 。如果数据字节的最高位为0,则认为此字节是一个ASCII字符。如果数据字节的最高位为1,则低7位为基址的一个偏移,实际的UCS2字符为基址加上这个偏移值。由于此处三个数据字节最高位都为1,5C=1 101 1100
则实际的3个字符的 偏移值为:5C, 5C, 5C。实际的UCS2编码为: 0x675C 0x675C 0x675C, 此处我们就看的明白了。
例4:一丁丂七丄丅 (注:这些字符属于GBK字符集)
UNICODE编码为:4E00 4E01 4E02 4E03 4E04 4E05
用ucs2的80方案表示是:80 4E004E014E024E034E044E05
用ucs2的81方案表示是:81069C808182838485
分析一下UCS2的81方案:81069C808182838485
81:为标记
06:表示整个字符串为6个字符
9C:一个字节为基址。解析的方法为:将基址(9C)左移七位,并将最高位置为0,最低位再补一个0(这样就16位啦)。此时基址
变为0x4E00,然后再判断后面的数据字节。
808182838485:6个数据字节 80,81,82,83,84,85 。由于此处六个数据字节最高位都为1,则实际的6个字符的偏移值为:00,
01,02,03,04,05。实际的UCS2编码为:0x4E00,0x4E01,0x4E02,0x4E03,0x4E04,0x4E05。 OK。
c) 82 开头:
82开头的格式中,包含一个基址(两个字节)。有这个基址,就可以用一个字节表示一个ucs2字符了。
在格式上,81是标识,后一个字节表示整个字符串长度,再后面两个字节是基址,再往后的就都是数据了。先举一例:
例5:8025EF芳
UNICODE编码为:00380030003200350045004682B3
用ucs2的80方案表示是:8000380030003200350045004682B3
用ucs2的81方案表示是:(因为格式的限制,最多容纳128个中文和127个英文,所以此处无法用81格式表示)
用ucs2的82方案表示是:82078280383032354546B3
分析一下UCS2的82方案:82078280383032354546B3
82:为标记
07:表示整个字符串为7个字符
8280:两个字节为基址。
383032354546B3:7个数据字节 38,30,32,35,45,46,B3。如果数据字节的最高位为0,则认为此字节是一个ASCII字符。如果
数据字节的最高位为1,低7位为基址的一个偏移,实际的UCS2字符为基址加上这个偏移值。由于此处七个数据字节的前六个字节最高
位为0,所以表示6个ASCII字符0x38,0x30,0x32,0x35,0x45,即8,0,2,5,E,F。第七个字节的最高位为1,则此数据的
偏移值为0x33,需要加上基址 0x8280,UCS2编码为0x82B3(芳)
例6:杜杜1
UNICODE编码为:675C675C0031
用ucs2的80方案表示是:80675C675C0031
用ucs2的81方案表示是:8103CEDCDC31
用ucs2的82方案表示是:82036700DCDC31
分析一下UCS2的82方案:82036700DCDC31
82:为标记
03:表示整个字符串为6个字符
6700:两个字节为基址。
DCDC31:36个数据字节 DC,DC,31。由于此处三个字节的前两个字节最高位为1,则此数据的偏移值为0x5C,需要加上基址
0x6700,UCS2编码为:0x675C(杜)。第三个字节的最高位为0,所以表示一个ASCII字符:0x31,即 1。
此处只是稍微分析了一下UCS2三种格式(80,81,82)的解码,想必知道了各个字段的含义,编码也就轻松多了。
代码 | 显示 | 描述 |
---|---|---|
U+0030 | 0 | 数字 0 |
U+0031 | 1 | 数字 1 |
U+0032 | 2 | 数字 2 |
U+0033 | 3 | 数字 3 |
U+0034 | 4 | 数字 4 |
U+0035 | 5 | 数字 5 |
U+0036 | 6 | 数字 6 |
U+0037 | 7 | 数字 7 |
U+0038 | 8 | 数字 8 |
U+0039 | 9 | 数字 9 |
0.参数设置
1、短信收发模式设置
短消息的发送和接收控制模式有三种:
模式 | 说明 |
Block模式 | 使用Block模式需要手机生产厂家提供驱动支持。 |
PDU模式 | 支持中文,英文,PDU模式已取代Block模式, |
Text模式 | 不支持中文 |
因此,为了系统的通用性,兼容中英文短消息的发送接收,建议使用PDU模式来处理短消息,这样应设置:AT+CMGF=0 //PDU方式
然后在此应用中为了解码方便,而且也不需要中文,可以使用Text模式.AT+CMGF=1 //text方式
2、新信息处理方式设置
格式:AT+CNMI=[<mode>[,<mt >[,<bm>[,<ds>[,<bfr>]]]]]
示例:
AT+CNMI=2,1 NOTE:将短信存储到ME 或SIM 卡后,再给出新短信指示
OK
+CMTI: "SM",1 NOTE:显示新短信指示
AT+CNMI=2,2 NOTE:收到短信,直接给出短信内容
OK
+CMT: "8613902288001",,"07/04/19,22:36:19+32",145,4,0,0,"8613912345500",145,4
TEST
这里我们使用的是:AT+CNMI=2,1,0,0,0 //将短信存储到ME 或SIM 卡后,再给出新短信指示
3、回显设置
ATE1 //有回显,方便测试
ATE10//无回显,便于数据处理.
4、消息服务设置
短信发送
以要将“你好”发送到13752141860,信息中心号码为:+8613800220500为例:
1、PDU数据格式分析
应发送的PDU字符串为:
0891683108200205F031000D┃91┃683157121468F0┃00┃08┃AA044F60597D
下面对这段PDU数据进行详细分析:
(1)08
信息中心号码的长度,将91683108200205F0的长度除2,格式化成2位的16进制字符串所得
也就是 16/2=8(10)=0x08(16).
(2)91 //主叫短信中心号码类型'91是TON/NPI遵守International/E.164标准,指在号码前需加‘+’号
91—10010001 //每一位数字转换为4位二进制数,各位分别表示:
1 固定值
001 //数值类型(Type of Number):000—未知,001—国际,010—国内,111—留作扩展;
0001//号码鉴别(Numbering plan identification):0000—未知,0001—ISDN/电话号码(E.164/E.163),1111—留作扩展;
(3) 683108200205F0 //短信息中心号码
转换方法:如果号码前面有+号,去掉“+”号→如果没有“86”,在号码前加上“86”:8613800220500→看看现在号码的长度是否为偶数,如果不是,在号码后面加上“F”:8613800220500F→将奇数位和偶数位交换,得到结果:683108200205F0
(4)31 //TPDU头字节 (以十六进制表示)
31(16)=00110001(2) //每一位数字转换为4位二进制数
0 //应答路径—TP-RP(TP-Reply-Path):0—不设置; 1—设置
0 //用户数据头标识—TP-UDHL(TP-User-Data-Header-Indicator):0—不含任何头信息; 1—含头信息
1 //状态报告要求—TP-SPR(TP-Status-Report-Request):0—不需要报告; 1—需要报告(有些地方写0为需要报告,经偶测试是错误的)
10 //有效期格式—TP-VPF(TP-Validity-Period-Format):00—不提供(Not present); 10—整型(标准);01—预留; 11—提供8位字节的一半(Semi-Octet Represented)
0 //拒绝复制—TP-RD(TP-Reject-Duplicates):0—接受复制; 1—拒绝复制
01 //信息类型提示—TP-MTI(TP-Message-Type-Indicator):00—读出(Deliver); 01—提交(Submit)
(5)00 //信息类型
0D┃91┃683157121468F0┃00┃08┃AA044F60597D
(6)0D //被叫号码长度,8613752141860的长度格式化为2位16进制所得13(10)=0x0D(16)
(7)91 //被叫短信中心号码类型'91是TON/NPI遵守International/E.164标准,指在号码前需加‘+’号,小灵通为81
(8)683157121468F0 //被叫号码,转换方法同(3)
13752141860-->8613752141860-->8613752141860F-->683157121468F0
(9)00 //协议标识 TP—PID
00--00000000 //每一位转换为4位二进制数
00 //Bit No.7与Bit No.6: 00—如下面定义的分配Bit No.0—Bit No.5;01—参见GSM03.40协议标识完全定义;10—预留;11—为服务中心(SC)特殊用途分配Bit No.0—Bit No.5。 一般将这两位置为00。
0 //Bit No.5:0—不使用远程网络,只是短消息设备之间的协议;1—使用远程网络。
00000 //Bit No.0—Bits No.4:00000—隐含;00001—电传;00010—group 3 telefax;00100—语音;00101—欧洲无线信息系统(ERMES);00110—国内系统;10001—任何基于X.400的公用信息处理系统;10010—Email。
(10)08 //数据编码方案,08:中文编码,00为英文或数字,Bit No.7与Bit No.6.Bit No.7的编码解码比较复杂,建议在发送纯英文或数字的短信时仍使用中文编码,测试通过.
08--00001000
00 //Bit No.7与Bit No.6 :一般设置为00;
0 //Bit No.5:0—文本未压缩,1—文本用GSM标准压缩算法压缩;
0 //Bit No.4:0—表示Bit No.1、Bit No.0为保留位,不含信息类型信息,1—表示Bit No.1、Bit No.0含有信息类型信息;
00 //Bit No.3与Bit No.2:00—默认的字母表,01—8bit,10—USC2(16bit),11—预留;
00 //Bit No.1与Bit No.0:00—Class 0,01—Class 1,10—Class 2(SIM卡特定信息),11—Class 3。
0D┃91┃683157121468F0┃00┃08┃AA044F60597D
(11)AA //有效期TP-VP(TP-Valid-Period),16进制数
AA表示短信息被保留的时间为4天,其计算方法依照下表。
VP值(10进制数) | 短消息有效长度 |
0~143 | (VP+1)×5分钟 |
144~167 | 12时+(VP-143)×30分 |
168~196 | 1天×(VP-166) |
197~255 | 1周×(VP-192) |
(12)04 //用户数据长度TP-UDL(TP-User-Data-Length),4F60597D的长度除2格式化为2位16进制数所得
(13)4F60597D //用户数据TP-UD(TP-User-Data),这个就是我们发送的内容"你好"的UniCode码了
"你好"\u4f60 \u597d 工具: http://app.baidu.com/2unicode?keyword=unicode%E8%BD%AC
在PDU模式中,发送普通的ASCII字符用7-bit编码方式,将一串7-bit字符编码为8-bit数据,每8个字符可压缩成7个。如果发送中文字符,则采用UCS2编码方式,每个中文字符用16位的Unicode字符表示.将字符串转换为UniCode码的过程网上有很多,这里提供DELPHI下的编码函数:
***********************************************************
function Thread_Smsg.str_Gb2UniCode(text:string):String;
var
i,j,len:Integer;
cur:Integer;
t:String;
ws:WideString;
begin
Result:='';
ws:=text;
len:=Length(ws);
i:=1;
j:=0;
while i<=len do
begin
cur:=ord(ws[i]);
FmtStr(t,'%4.4X',[cur]); //BCD转换
Result:=Result+t;
inc(i);
//移位计数达到7位的特别处理
j:=(j+1)mod 7;
end;
end;
***********************************************************
2、发送短信
做好了要发送的PDU数据包以后终于可以开始发送短信了。
首先发送AT,GSM回答OK,表明建立连接成功,可以测试各类AT指令;
接着发送AT+CMGS=17,17是指将PDU数据中短信中心号码后面的字符串(本例中即为31000D91683157121468F00008AA044F60597D)的长度除以2,格式化为2位的十进制数;最大长度为164,测试过165以上就会返回ERROR。
但是这里有个问题,70个汉字编辑成PDU后长度是155,但是这140个字符是汉字和字母数字的组合,长度就有可能超过164,因为每一位的数字或字母也被转为4位的UNICODE码。
发送长度后,GSM会返回>,然后我们发送刚才编辑的PDU字符串:0891683108200205F031000D91683157121468F00008AA044F60597D以CTRL+Z结束;
08 91 683108203005F0 31 00 0D 91 685112059236F9 00 08 AA 04 4F60597D
0891683108200205F031000D91685112059236F90008AA044F60597D
0891683108200305F031000D91685112059236F90008AA044F60597D
0891683108200305F031000D91685112059236F90008AA044F60597D
--------------------------------------------------------------------------------
短信中心:
+8613800230500
8613800230500
8613800230500F
683108200305F0
被叫号码
15215029639
8615215029639
8615215029639F
685112059236F9
如果GSM返回:就表示发送成功了。
+CMGS: 183 //183是发送短信时产生的顺序号,在对方接收到短信发回状态报告时候,状态报告中会包含此顺序号
OK
这里需要注意的是手机返回OK只能确认是成功发送到GSM网络上,接收方是否真正收到短信需要通过发送报告得知。有关如何获得发送报告在“发送报告的PDU数据分析”中有说明。
1、接收中文短信
以接收13752141860 号码发送来的“你好”,信息中心号码为:+8613800220500为例,手机接收到字符串为:
+CMT: ,24
0891683108200205F0240D91683157121468F0000860800331220000044F60597D
可以添加下分隔符来方便阅读:
08┃91┃683108200205F0┃240D┃91┃683157121468F0┃00┃08┃608003312200┃00┃04┃4F60597D
>>首先分析第一行:
+CMT 表示新短信指示代码格式为收到短消息立即显示;若+CMTI则指示收到短消息存储到存储器里;是否直接显示是通过CNMI设置的;
24 表示PDU数据中短信中心号码后面的字符串长度/2,即240D91683157121468F0000860800331220000044F60597D的长度除以2;(48)/2=24.
>>然后分析第二行,也就是分析接收到的PDU数据:
(1)08
信息中心号码的长度,将91683108200205F0的长度除2,格式化成2位的16进制字符串所得
也就是 16/2=8(10)=0x08(16).
(2)91 //短信中心号码类型
短信中心号码类型'91是TON/NPI遵守International/E.164标准,指在号码前需加‘+’号
91—10010001 //每一位数字转换为4位二进制数
1 固定为1
001 //数值类型(Type of Number):000—未知,001—国际,010—国内,111—留作扩展;
0001//号码鉴别(Numbering plan identification):0000—未知,0001—ISDN/电话号码(E.164/E.163),1111—留作扩展;
(3)683108200205F0 //短信中心号码,转换方法:
短信中心号码: +8613800220500
转换方法:如果号码前面有+号,去掉“+”号→如果没有“86”,在号码前加上“86”:
86 13 80 02 20 50 0→看看现在号码的长度是否为偶数,如果不是,在号码后面加上“F”:8613800220500F→将奇数位和偶数位交换,得到结果:683108200205F0
(4)24 //TPDU头字节
PS.继续讲解前,先标志下数据,好区分点.
0D┃91┃683157121468F0┃00┃08┃608003312200┃00┃04┃4F60597D
(5)0D
发送源号码长度,8613752141860的长度格式化为2位16进制所得
也就是13(10)=0x0D(16)
(6)91 //发送源号码类型
(7)683157121468F0 //发送源号码
13752141860-(加86)-->8613752141860--(判断奇偶)—> 86 13 75 21 41 86 0F
然后奇偶互换,683157121468F0
(8)00 //协议标识 TP—PID
(9)08 //数据编码方案,08:中文编码,00为英文或数字,Bit No.7与Bit No.6
00--00000000 //每一位转换为4位二进制数
00 //Bit No.7与Bit No.6: 00—如下面定义的分配Bit No.0—Bit No.5;01—参见GSM03.40协议标识完全定义;10—预留;11—为服务中心(SC)特殊用途分配Bit No.0—Bit No.5。 一般将这两位置为00。
0 //Bit No.5:0—不使用远程网络,只是短消息设备之间的协议;1—使用远程网络。
00000 //Bit No.0—Bits No.4:00000—隐含;00001—电传;00010—group 3 telefax;00100—语音;00101—欧洲无线信息系统(ERMES);00110—国内系统;10001—任何基于X.400的公用信息处理系统;10010—Email。
(10)608003312200 //日期时间,奇偶互换:06-08-30 13:22:00,
(11)00 //时区
(12)04 //用户数据长度TP-UDL(TP-User-Data-Length),4F60597D的长度除2格式化为2位16进制数所得
(13) 4F60597D //”你好”的UNICODE码,同样提供一个DELPHI下的解码函数:
2、接收纯英文或数字
上面例子中接收到的是中文短信“你好”,那么当接收到的短信是纯中文或者数字的时候又如何解码呢?
例如接收到13752141860发送的英文短信“hello”,手机接收到的字符串为:
+CMT: ,24
0891683108200205F0240D91683157121468F00000608003416270000461F1980C
简单复习下:
- +CMT 表示新短信指示代码格式为收到短消息立即显示
- 24 表示PDU数据中短信中心号码,683108200205F0后面的字符串长度/2,
- 08 将91683108200205F0的长度除2,格16进制字符串所得 16/2=8(10)=0x08(16).
- 91 短信中心号码类型
- 683108200205F0 短信中心号码
- 24 TPDU头字节
- 0D┃91┃683157121468F0┃00┃00┃608003416270┃00┃04┃61F1980C
- 0D 发送源号码长度,8613752141860,16进制所得 13(10)=0x0D(16)
- 91 发送源号码类型
- 683157121468F0 发送源号码
- 00 协议标识 TP—PID接下的的00:先前提到了这两位表示数据编码方案,08为中文编码,00为英文或数字,当手机发送普通的ASCII字符即使用7-bit编码方式,说明我们接收到的短信是英文或者数字格式的,而不是中文UNICODE码,比较一下:
0D┃91┃683157121468F0┃00┃00┃608003416270┃00┃04┃61F1980C (文本短信)
0D┃91┃683157121468F0┃00┃08┃608003312200┃00┃04┃4F60597D (中文短信)
继续复习:
- 608003416270 日期时间,奇偶互换
- 00 时区
- 04 用户数据长度 61F1980C 的长度除2,16进制数为8(10)=04(16)
- 61F1980C ”你好”的7-bit码
根据前面的00我们知道这是一段7-bit码,而不再是UNICODE码,7-bit的解码过程很复杂,大体过程是:
将源数据每7个字节分为一组,解码成8个字符。基本自然是:将第n个字节左移n位,再加上前一字节的剩余数据,即第(n-1)个字节右移(8-n)位的数值,屏幕最高位,即得到一目标字符数据,n=0…6。第7个字节右移1位就得到解码后的第8个字符数据。
以上改编自http://blog.csdn.net/god2469/article/details/6294070
3.GMS 03.38
Foreword 前言.................................................................................................................................5
1 Scope 范围.....................................................................................................................................7
2 Normative references标准的参考....................................................................................................7
3 Definitions and abbreviations .定义与缩写....................................................................7
4 SMS Data Coding Scheme 短消息数据编码方案...............................................................8
5 Cell Broadcast Data Coding Scheme蜂窝广播数据编码方案..................................9
6 Individual parameters 单独的参数.....................................10
6.1 General principles 通用的规则.............................................................................10
6.1.1 General notes.通用注释.........................................................................10
6.1.2 Character packing字符封包.........................................................................11
6.1.2.1 SMS Point-to-Point Packing 短消息点对点包装................................11
6.1.2.1.1 Packing of 7-bit characters ............11
6.1.2.2 SMS Cell Broadcast Packing...............................................12
6.1.2.2.1 Packing of 7-bit characters ...................12
6.2 Alphabet tables字母表..............................................................................12
6.2.1 Default alphabet .默认字母表...........................................................................13
History历史............................................................................................................................................14