[Feature phone系列]短信模块的设计和实现


短信实现架构,参考文献<<3GPP TS 27.005 V9.0.0 (2009-12)>>

首先,短信的收发有三种模式:Block mode, Text mode and PDU[Protocol data unit] mode.我们使用的是PDU模式,当手机启动之后,电池、搜网完成、SIM卡初始化完成、电话本初始化完成之后,开始初始化SMS.

       AT+CNMI=2,1,2,1,0 //设置新短信的显示模式.详细参数格式如下:

       +CNMI=[<mode>[,<mt>[,<bm>[,<ds>[,<bfr>]]]]]

设置短信相关参数:

       AT+CSMS=1 // 选择服务类型 0表示兼容GSM 07.05 Phase 2 version 4.7.0, 1表示兼容GSM 07.05 Phase 2+ version

       AT+CMGF=1  // 0表示PDU, 1表示Text mode

       AT+CSDH=1  // 0表示不显示短信头信息, 1表示显示短信头信息

       AT+CRSM=192,28482,0,0,0 // 访问SIM上短信信息

       详细指令说明参加下面:

AT+CRSM=<command>[,<fileid>[,<P1>,<P2>,<P3>[,<data>[,<pathid>]]]]
<command> may be
- 176 READ BINARY
- 178 READ RECORD
- 192 GET RESPONSE
- 214 UPDATE BINARY
- 220 UPDATE RECORD
- 242 STATUS
<fileid> integer type; this is the identifier of a elementary datafile on SIM. Mandatory for every command except STATUS and may be e.g.:
- 28471 meaning ACMmax file (6F37)
- 28423 meaning IMSI file (6F07)
- 28473 meaning ACM file (6F39)
- 28481 meaning PUKT file (6F41)
- 28482 meaning SMS file (6F42)     
<P1>, <P2>, <P3> integer type defining the request. These parameters are mandatory for every command, except GET RESPONSE and STATUS. The values are described in GSM 51.011.
<data>: information which shall be written to the SIM (hexadecimal character format; refer +CSCS – string containing hexadecimal characters -)  


短信基本概念:

    短信的几本概念:

    SMS TM // SMS from SC to MS

    SMS MO // SMS from MS to SC

    MT的SMS中SC与MSC的接口叫SMS-GMSC[Gateway MSC],对应MO情况下MSC与SC的接口为SMS-IWMSC (Interworking MSC)。SMS-GMSC与SMS-IWMSC只是在功能上的区分,可以在任一个MSC上实现.

SM MO 部分

SMS是通过使用SS#7协议中的MAP[Mobile Application Part],将短信息协议的数据元素作为MAP信息中的数据域在网络中传输来实现的.如下图:

                    

                                                                                                  SM MO时序图

    从上图中可以看到,当用户发送一条短信时,MS通过空中接口将该文本信息发送给VMSC[访问移动交换中心]/SGSN[GPRS服务支持节点]
    该文本信息由以下部分组成:
       a.正文;
       b.目的地址;
       c.短信服务中心的地址[从SIM卡中手机配置信息得到];

    这里我们忽略空中接口技术,看看短信是如何发送出去的:
    a.VMSC/SGSN会调用MAP服务包中的MAP_MO_FORWARD_SHORT_MESSAGE发送信息给服务中心SC的IW-MSC.
    b.SC发送mo-ForwardSM MAP操作到SMSC[短信服务中心],该操作会在MS的SMS submit中识别、嵌入在一个TCAP[Transaction Capabilities Application Part]消息中,

        使用SCCP[Signalling Connection Control Part]经由核心网传输.

    c.SMSC的IW-MSC在收到MAP mo-ForwardSM信息后,就传送包含文本信息的SMS-PP APDU[Application Protocol Data Unit]到SC中存储起来.随后会将该文本信息转发或者交付给目的地址并且SC会返回一个成功或失败的确认信息.
    d.IW-MSC在收到确认信息后,会发送一个回执给短信发起端的MS的VMSC/SGSN.
    e.最后通过空中接口给短信发起端的MS发送状态报告[该报告只表示SM已经提交给SC]

SM MT部分

 

               

                                                                                                            SM MT时序图

详细过程:

a.SMSC发送包含文本信息、B-Party[目的手机号码]和SMS-PP APDU到GMSC
b.GMSC查找B-Party的位置[负责从HLR获取路由信息]
c.GMSC调用AMP服务包MAP_SEND_ROUTING_INFO_FOR_SM,它发送一个MAP信息sendRoutingInfoForSM[简写,SRI-for-SM]给目的号码的HLR,请求获取目的号码的当前位置.
d.HLR查找B-Party的当前位置,并发送给GMSC.
e.得到B-Party的位置信息后,GMSC调用MAP_MT_FORWARD_SHORT_MESSAGE服务来发送一个  MAP mt-ForwardSM信息给目的号码的当前地址[VMSC/SGSN]
f.VMSC发送请求消息Send_Info_for_MT_SMS给VLR.
g.VMSC获取目的用户的ISDN[Integrated Services Digital Network,综合业务数字网]号,并将结果返回给VMSC.
h.VMSC发送APDU短信息,使用载入在一个SCCP连接的直接传输应用部分DTAP[Direct Transfer Application Part]经由空中接口到达目的端,并会收到目的端的确认响应.
i.VMSC/SGSN在短信交付给目的端后,发送确认信息给SMSC.
j.GMSC讲该短信的确认结果发给SC,已交付的文本信息将会从存储转发引擎SFE[Store and Forward Engine]中删除.


SMSC,Short Message Service Center[短消息服务中心]

SS#7,[7号信令]是一种被广泛应用在公共交换电话网、蜂窝通信网络等现代通信网络的共路信令系统。七号信令系统是国际电信联盟推荐首选的标准信令系统.

MSC,Mobile Switching Center[移动交换中心],MSC是整个GSM网络的核心,它控制所有BSC的业务,提供交换功能及和系统内其它功能的连接,MSC可以直接

         提供或通过移动网关GMSC提供和公共电话交换网[PSTN]、综合业务数字网[ISDN]、公共数据网[PDN]等固定网的接口功能,把移动用户与移动用户、移动用户和固定网用户互相连接起来.
BSC,Base Station Controller[基站控制器]


短信基本网络架构:

Part 1:

                      

                                                                    Entities involved in the provision of SM MT and SM MO: SC,
                                                                                     SMS-GMSC/SMS-IWMSC, MSC and MS.

SME,Short Message Entity


Part 2:

                      

                                                                              The main network structure serving as a basis for the short message transfer.

HLR,Home Location Register[归属位置寄存器],它负责保存用户归属消息及当前位置信息,从而能够建立对手机的呼叫。HLR将归属位置寄存器和鉴权中心集成在一起,提供位置更新、漫游管理、鉴权、呼叫等多种功能;HLR还支持丰富的补充业务,如呼叫前转、呼叫禁止、主叫号码显示及限制、短消息等,用户使用得心应手。

VLR,Visitor Location Register[访问位置寄存器],服务于其控制区域内移动用户的,存储着进入其控制区域内已登记的移动用户相关信息,为已登记的移动用户提供建立呼叫接续的必要条件。VLR 从该移动用户的归属用户位置寄存(HLR)处获取并存储必要的数据。一旦移动用户离开该VLR 的控制区域,则重新在另一个VLR 登记,原VLR 将取消临时记录的该移动用户数据。因此,VLR 可看作为一个动态用户数据库。

VLR中主要包括以下信息单元

  - IMSI
  - MSISDN
  -TMSI(临时移动用户身份Temporary Mobile Subscriber Identification)
  - 移动台登记所在的位置区
  - 补充业务参数




1>开机短信提示

    开机后当手机有新的短消息时候,马上会提示用户有新的短消息.

    这部分主要是依赖于前面讲到的SM相关的AT指令设置,设置新短信的显示模式.

2>短信数据结构

   

     A>SM MT 短信协议格式

                                                   

                                                      1) Provision; Mandatory (M) or Optional (O).
                                                      2) Representation; Integer (I), bit (b), 2 bits (2b), Octet (o), 7 octets (7o), 2-12 octets (2-12o)
                                                      3) Dependent on the TP-DCS


                                                      Layout of SMS-DELIVER

                                                      

                                                      NOTE: Any unused bits will be set to zero by the sending entity and will be ignored by the receiving entity.

      B>SM MO 短信协议格式

                                                     Basic elements of the SMS-SUBMIT type:

                                                     

                                                      1) Provision; Mandatory (M) or Optional (O).
                                                      2) Representation; Integer (I), bit (b), 2 bits (2b), Octet (o), 7 octets (7o), 2-12 octets (2-12o).
                                                      3) Dependent on the TP-DCS

                                                      

                                                       Layout of SMS-SUBMIT:

                                                      

                                                      NOTE: Any unused bits will be set to zero by the sending entity and will be ignored by the receiving entity.

3>短信接收过程[SMS MT]

    MT SMS发送过程如下: 
    1. MT SMS由SC路由至SMS-GMSC,发"Forward mobile terminated short message"信息。 
    2. SMS-GMSC通过向HLR发送"Send routing information for short message"消息来请求路由信息。这个消息包含被叫方方的手机号码(MSISDN)、优先级和SC的地址。
    3. HLR根据MSISDN查找用户数据。出现以下情况会返回一个错误码到SMS-GMSC:MSISDN为空号、用户未开SMS服务、呼叫禁止(Call barred)、用户不可及。否则返回以下路由信息:MSC-id、IMSI、MWD-set(optional 表示SC地址是否已保存在信息等待数据列表Message waiting data中) ,每个MS最多可存8个SC地址。 
    4. 返回的MSC-id用来确定MS目前所处MSC地址,SMS-GMSC向MS所处的MSC发"Forward short message"信息,MSC/VLR从信息中抽取IMSI,只要用户没有关机或忙,MSC会命令BSS寻呼MS。MS回应寻呼,并经过鉴权等过程,短信从SDCCH信道发送到MS,如这时MS正在通话则短信放在SACCH信道上。 
    5. 发送成功的信息返回SMS-GMSC,如不成功则返回错误信息。 
    6. 发送结果返回SC。

                                                      


4>短信发送过程[SMS MO]

     a. MS发一个CM(Connection Management)请求到BTS以建立信令连接;

     b. MSC分配一个信令信道并进行鉴权;

     c. MSC/VLR将短信转至SMS-IWMSC; 

     d. SMS-IWMSC发"FORWARD MOBILE ORIGINATED SHORT MESSAGE"消息,将短信转到SC;

     e. SC收到信息沿原路返回.

MO SMS中用到的协议:
    --连接管理协议(Connection Management Protocol)CP,用于空中接口
    --中继协议(Relay Protocol) CP用于短信的中继.

详细过程如下图:

                                                     


SM的协议架构:


                                  

                                                                                     Protocol layer overview for the Short Message Service point-to-point

SM-AL, Short Message Application Layer

SM-TL, Short Message Transfer Layer

SM-RL, Short Message Relay Layer

SM-LL, Short Message Low Layer

到此为止,关于SMS的方面的协议框架以及实现原理的框架性知识就是这些.


下面我们看看代码实现方面的内容[Text Mode]:

SM MO send function:

void mmi_sms_cmgs_rsp_non_tb_handler(n16 atevent, g_MmiAtCmdInd * pCmdInd)
{
......
        // Handle the chinese character
        if (mmiSmsSendSrvcStatus.isChinesetype == C_MMI_TRUE) 
        {
            n16 waData[MMI_FIM_MAX_SMS_LEN + 1]= {0};
            mmi_unit16_str_cpy(waData, (UINT16*)mmiSmsSendSrvcStatus.data);
            mmi_exchange_high_low_byte((UINT8 *)waData, bLen);
            hexLen = mmi_utl_strn_to_hex(hexMsg, (str8 *)waData, bLen);
        }
       else // Handle english character
        {
            n8 baData[MMI_FIM_MAX_SMS_LEN + 1]= {0};
            bLen = mmi_sms_ucs2str_to_gsm_str((str8*)baData, (str16*)mmiSmsSendSrvcStatus.data, bLen);
            hexLen = mmi_utl_strn_to_hex((str8*)hexMsg, (str8*)baData,bLen);
        }
        /* transfer the message string to HEX coding string */
        hexMsg[hexLen] = 0x1A; /* Ctrl-Z */
        hexMsg[hexLen+1] = 0;

        /* directly send the command (message content) to ACI, regardless the queue in MMI-SYS */
        mmi_send_dual_SIM_at_cmd_req(mmi_utl_strlen8(hexMsg), (n8*)hexMsg,((S_MmiAtCmdInd*)pCmdInd)->sys);
}

SM MT 过程:


void mmi_sms_pasrse_msg_user_data(str8* atResp, T_MMI_SIM_SMS_RECORD *pMsgRec, S_MmiSmsHeaderRecord *pMsgHeaderRec)
{
......
    if ( !(pMsgHeaderRec->msgFlags & MMISMS_FLAG_UDH_EXIST) )
    {
        /* the message is a single page message */
        pMsgHeaderRec->udhLen = 0;
        pMsgHeaderRec->totlPage = 1;
        pMsgHeaderRec->thisPage = 1;
        /* check if the message is addressed for vCard/vCalendar on NBS port number */
        if ( pMsgHeaderRec->dcs.alphabet == DCS_ALPHA_GSM_DEFAULT )
        {
            gsmStrLen = mmiUtl_HexToStr8(gsmStr, atResp);
            mmi_utl_gsm_str_to_ucs2str((str16*)WaData,gsmStr,gsmStrLen);
            mmi_utl_strcpy16_to8((str8*)pMsgRec->baText,(str16 *)WaData);
            mmi_sms_asc_buff_del_special_chara(pMsgRec->baText,gsmStrLen);
            pMsgRec->bLanguage = SMSLOW_LANGUAGE_ASCII;
			
        }
        else if(pMsgHeaderRec->dcs.alphabet == DCS_ALPHA_8BIT)
        {
            gsmStrLen = mmi_utl_hex_to_str8(gsmStr, atResp);
            mmi_utl_strcpy8((str8*)pMsgRec->baText,gsmStr);
            mmi_sms_asc_buff_del_special_chara(pMsgRec->baText,gsmStrLen);
            pMsgRec->bLanguage = SMSLOW_LANGUAGE_ASCII;
        }
        else
        {
            /* the data is in UCS2 */
            userDataLen = (n8)mmi_utl_hex_to_str8(userData, atResp);
            mmi_exchange_high_low_byte((UINT8*)userData, userDataLen);
            memcpy(pMsgRec->baText,userData,userDataLen);
            pMsgRec->bLanguage = SMSLOW_LANGUAGE_UNICODE;
        }
    else
    {
        /* the message (TP-UD) contains User-Data-Header, */
        /* which consists of one or more IEs              */
        if ( pMsgHeaderRec->dcs.alphabet == DCS_ALPHA_GSM_DEFAULT )
        {
            /* TP-UD is in GSM alphabet, pack 8-bit GSM coded TP-UD back into 7-bit */
            /* transfer the Hex-coded string back into 8-bit GSM string */
            gsmStrLen = mmi_utl_hex_to_str8(gsmStr, atResp);
            if ( pMsgHeaderRec->length != gsmStrLen )
            {
                mmiSmsSrvcStatus.msg_format = 0;
                return;
            }
            userDataLen = (n8)mmi_utl_pack_gsm_str8_to_str7(userData, gsmStr, gsmStrLen);
            pMsgRec->bLanguage = SMSLOW_LANGUAGE_ASCII;
        }
        else if(pMsgHeaderRec->dcs.alphabet == DCS_ALPHA_8BIT)
        {
            /* the data is in 8-bit or UCS2 */
            userDataLen = (n8)mmi_utl_hex_to_str8(userData, atResp);
            if ( pMsgHeaderRec->length != userDataLen )
            {
                mmiSmsSrvcStatus.msg_format = 0;
                return;			
            }
            pMsgRec->bLanguage = SMSLOW_LANGUAGE_ASCII;
        }
        else
        {
            /* the data is in 8-bit or UCS2 */
            userDataLen = (n8)mmi_utl_hex_to_str8(userData, atResp);
            if ( pMsgHeaderRec->length != userDataLen )
            {
                mmiSmsSrvcStatus.msg_format = 0;
                return;				
            }
            pMsgRec->bLanguage = SMSLOW_LANGUAGE_UNICODE;
        }
        /* length of TP-UDH is the first byte of TP-UD */
        pMsgHeaderRec->udhLen = userData[0];
        if ( pMsgHeaderRec->udhLen > 0 && pMsgHeaderRec->udhLen <= C_MMI_SMS_TPUD_BYTE && pMsgHeaderRec->udhLen < userDataLen )
        {
            /* TP-UDH exists, parse the UDH for getting concatenated information (IEI=00 or 08) */
            mmi_sms_get_conct_info_in_UDH(pMsgHeaderRec, &userData[1], pMsgHeaderRec->udhLen);
            {
                if ( pMsgRec->baText != C_MMI_NULL )
                {
                    if ( pMsgHeaderRec->dcs.alphabet == DCS_ALPHA_GSM_DEFAULT )
                    {
                        /* convert the data back to ISO-8859(ASCII). */
                        UINT32 tempLen  = (pMsgHeaderRec->length - pMsgHeaderRec->udhLen - 1 -1);
                        mmi_utl_gsm_str_to_ucs2Str(WaData,(UINT8*)&gsmStr[pMsgHeaderRec->udhLen + 1 + 1],tempLen);
                        mmi_utl_strcpy16to8(pMsgRec->baText, (UINT16 *)WaData);
                       if(pMsgRec->bLanguage == SMSLOW_LANGUAGE_ASCII)
                        {
                            mmiSms_AscBuffDelSpecialChara(pMsgRec->baText,tempLen);
                        }
                    }
                    else if (pMsgHeaderRec->dcs.alphabet == DCS_ALPHA_8BIT )
                    {
                        /* For SMS buffer: preserve TP-UD, copy HEX data into data buffer */
                        n32 tempLen  = (n16)(userDataLen - pMsgHeaderRec->udhLen - 1);
                        mmi_utl_memcpy8((str8*)pMsgRec->baText, (str8*)(&userData[pMsgHeaderRec->udhLen + 1]), tempLen);
                        if(pMsgRec->bLanguage == SMSLOW_LANGUAGE_ASCII)
                        {
                            mmi_sms_asc_buff_del_special_chara(pMsgRec->baText,tempLen);
                        }
                    }
                    else
                    {
                        /* For SMS buffer: preserve TP-UD, copy HEX data into data buffer */
                        n32 tempLen  = (n16)(userDataLen - pMsgHeaderRec->udhLen - 1);
                        mmi_utl_memcpy8((str8*)pMsgRec->baText, (str8*)(&userData[pMsgHeaderRec->udhLen + 1]), tempLen);
                        mmi_exchange_high_low_byte(pMsgRec->baText, tempLen);
                        if(pMsgRec->bLanguage == SMSLOW_LANGUAGE_ASCII)
                        {
                            mmi_sms_asc_buff_del_special_chara(pMsgRec->baText,tempLen);
                        }
                    }
                }
            }
        } /* end of processing of Special Message Indication */
    } /* end of TP-UDH exist */


分享一个常见短信Bug:

在很多Feature phone,包括一些智能手机上会把短信长度进行限制英文160字符,中文70个字符.关于这个长度的制定也有个故事,好奇心强的朋友自己搜索一下.

那么当这个长度限制死之后,问题就来了,接收短信方可能会接收到的字符不全!为什么?

因为在GSM编码规范中有部分字符的占位是两个字节,那么当这些特殊字符嵌入到短信内容中的时候就会多挤占一个字节.那么当用户输满160个字符的时候,短息内容在下层进行编码转换的时候,就会超过140个字符.但是GSM规范依然会按照140个字符发送,这个时候就会出现短信字符的丢失.特殊字符如下:

^ Caret / Circumflex 1B14
{ Left curly bracket 1B28
} Right curly bracket 1B29
\ Backslash 1B2F
[ Left square bracket 1B3C
~ Tilde 1B3D
] Right square bracket 1B3E
| Vertical bar 1B40
Euro sign 1B65  

这里需要做一些解释:为什么中文短信是70个字符,而英文短信可以编辑到160个字符.由于GSM规范中如果对英文字符进行7位编码,那么160个字符就可以被压缩到140个字符[这个长度是GSM规范定死的],这个也就是为什么英文短信可以编辑到160个字符.

而中文字符属于宽字符目前大多数嵌入式设备上都是使用Unicode编码了,因此无法对中文宽字符进行合理的压缩,因此每次只能传输70个中文字符.


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值