首 页 | 新 闻 | Symbian | Windows Mobile| J2ME | 下载中心 | 游戏策划 | 购书指南 | 移动开发视频教程
您现在的位置: 开发视界 >> 专家专栏 >> 新鲜的Lychee >> 文章正文
不可能的任务:获得位置字符串
作者:lychee08…    文章来源:本站原创    更新时间:2006-6-27 13:15:06

在Symbian程序员论坛手机应用部分中有许多关于获得位置字符串的帖子,所以我为自己设置了一个找回位置字符串的任务[1]。

所以在这篇文章中将会介绍如下内容:

基本解释:什么是小区(Cell)? 什么是小区广播消息(CBM)?GSM-CBM 的格式是什么?
高级电话库?
演示应用程序
总结

基本解释:什么是小区(Cell)? 什么是小区广播消息(CBM)?

因为我在工程学课程中已经学习过手机通信,所以开始就清楚小区广播消息是传递位置信息。而有些开发者却假想在SIM卡中有映射表,这是不正确的。
但是在CBM内部发送的内容要依靠载体还是有争议的。我从在线文档中读到在德国某一种运送器发送位置字符串匹配物,通过固定表的映射获得该位置字符串。但是,在印度,我已经检测了两个主要的发送位置字符串的运送器,并且正是我们要获取的东西。

小区(Cell)是指一个圆形区域,在其中心位置设置一个手机连接的基础站。一个小区可以覆盖半径距离0-70km。这根据地区会有所改变。
小区通常是六角形的,并且它的范围依赖于小区范围内的总用户。用户越多,范围越小,反之亦然。

无论何时,一部手机进入小区内,他首先要在基础站内自行注册。CMN被基础站广播到已定义的地理地区,该地区叫做小区广播地区,它可以横跨至少一部手机。CBM用于同时传达有用信息到所有签署商。以上理论已经足够,最后让我们看看GSM-CBM格式:
CBM接受88个字节,并有以下结构:
Octet No.| Field
--------------------------
1-2      | Serial number
3-4      | Message identifier
5        | Data Coding Scheme
6        | Page parameter
7-88     | content of message

对于我们,可以忽略前6位自己,因为它并不服务于我们的目的。所以继续看,从第7位到第88位,在GSM是7位但代码中是8位格式。所以每7位被打包成如下8位形字节式:
8 Original 7-bit message
b06 b05 b04 b03 b02 b01 b00
b16 b15 b14 b13 b12 b11 b10
b26 b25 b24 b23 b22 b21 b20
b36 b35 b34 b33 b32 b31 b30
b46 b45 b44 b43 b42 b41 b40
b56 b55 b54 b53 b52 b51 b50
b66 b65 b64 b63 b62 b61 b60
b76 b75 b74 b73 b72 b71 b70

Encoded(Packed) into 7 8-bit bytes as follows(| - marker not part of message) :
b10 | b06 b05 b04 b03 b02 b01 b00
b21 b20 | b16 b15 b14 b13 b12 b11
b32 b31 b30 | b26 b25 b24 b23 b22
b43 b42 b41 b40 | b36 b35 b34 b33
b54 b53 b52 b51 b50 | b46 b45 b44
b65 b64 b63 b62 b61 b60 | b56 b55
b76 b75 b74 b73 b72 b71 b70 | b66

所以需要一个合适的解码器将剩下的82位字符转换成ASCII 7位数据。
记住解码工作只是从第7位到88位,要忽略前6个字节。
一旦解码,它的内容将全部依赖于运载器。利用ASCII CR(回车)补位。所以所有的有效数据将会变为CR 。

高级电话库

现在,在Symbian中通过公共SDK获得位置信息是不可能的,所以许多专家给我们一个etelmm库,可以获得诸如此类的高级信息。因为没有官方的可用文档,对于我们要寻找很长的报头并理解他们的含义,找到可以给与我们信息的合适类。
首先我尽量取获得位置信息,但是完全无用。然后我发现RMobileBroadcastMessaging类。
有了这个信息,我们可以通过小区广播信息获得位置字符串,我仅需要测试它是否真的现存。
下面开始介绍复杂代码,但是首先简化逻辑:首先需要创建RMobilePhone连接。等待接收CBM。一旦拥有CBM,立即解码就可以获得位置字符串。

RTelServer iServer;   
        RMobilePhone iPhone;
        RTelServer::TPhoneInfo iPhoneInfo;
        TRequestStatus iReqStatus;
         RMobileBroadcastMessaging iBroadcastMsg;
        //GSM CBM's length is 88 bytes
        TBuf8<88> iGsmMsgdata;
        _LIT(KGsmModuleName, "phonetsy.tsy");        
        iServer.Connect();
       
        iServer.LoadPhoneModule( KGsmModuleName );

        TInt enumphone;
               
        User::LeaveIfError(iServer.EnumeratePhones(enumphone));
       
        if (enumphone < 1) {
                   User::Leave(KErrNotFound);
        }
       
        //Initialise the phone object
        User::LeaveIfError(iServer.GetPhoneInfo(0, iPhoneInfo));
       
        User::LeaveIfError(iPhone.Open(iServer, iPhoneInfo.iName));
        iBroadcastMsg.Open(iPhone);
        RMobileBroadcastMessaging::TMobileBroadcastAttributesV1 iAttrInfo;
        TPckg<RMobileBroadcastMessaging::TMobileBroadcastAttributesV1> iDes(iAttrInfo);       
        //Wait for the CBM
        iBroadcastMsg.ReceiveMessage(iReqStatus,iGsmMsgdata,iDes);
        User::WaitForRequest(iReqStatus);
       
        if(iReqStatus.Int()==KErrNone){//show the CBM retrieved
                //first write the 88 bytes of CBm into a file
                //I am doing this as I will be using C
                //code to decode the data
                RFs fs;
                fs.Connect();
                RFile file;
                TBuf<32> aFileName = _L("C:\\log.txt");
                fs.Delete(aFileName);
                file.Replace(fs,aFileName,EFileWrite);
                file.Write(iGsmMsgdata);
                file.Close();
                fs.Close();

                //here starts the decoding code
                //Credits : Vikram K.
                FILE* fp;
                fp = fopen("c:\\log.txt","rb");
                char locationString[94];
                char cbuf;
                int char_cnt=0;
                unsigned int bb = 0;
                /*8-bit to 7-bit conversion*/       
                unsigned char ur,curr,prev = 0;
                int cnt = 0;
                for(cnt = 0;cnt <6;cnt++)
                        fread(&cbuf,1,1,fp);
                while(fread(&cbuf,1,1,fp)){       
                        unsigned char aa = (1 << (7 - bb%7)) - 1;
                        ur = cbuf & aa;
                        ur = (ur << (bb)) | prev;
                        curr = cbuf & (0xff ^ aa);
                        curr = curr >> (7 - bb);                       
                        prev = curr;
                        if(ur == 0xd)
                        {
                                break;
                        }
               
                        locationString[char_cnt] = ur;

                        bb = ++bb % 7;               

                        char_cnt++;
                        if(bb==0)
                        {       
                                locationString[char_cnt++] = prev;
                                prev =0;
                        }
                }

                locationString[char_cnt] = '\0';
                fclose(fp);
                //decoding ends here now just
                //convert the C string to TBuf (Symbian format)
                int len=0;
                while(locationString[len] != NULL)  
                        len++;
                // Create empty descriptor
                HBufC* nameHeap = HBufC::NewLC(len);
                TPtr namePtr(nameHeap->Des());
                // Copy contents
                for(int i=0; i<len; i++)  
                namePtr.Append((TChar)locationString[i]);
                //now you have the location string
                //do whatever you want here..

                // Pop descriptor from cleanup stack
                CleanupStack::PopAndDestroy( nameHeap);                               
                }
        }
        else{//panic
        }
       
        iBroadcastMsg.Close();
        iPhone.Close();
        iServer.UnloadPhoneModule( KGsmModuleName );
        iServer.Close();

以上是给出获得位置字符串的代码,而不是获得CBM的内容,如果幸运就可以在CBM中获得位置字符串。

演示应用程序

为验证所写代码的性能,小的演示应用程序其等待接收CBM,一旦接收立即解析CBM并显示位置。
一旦运行应用程序,选择’Options->Wait for CBM ‘菜单选项。这将冻结屏幕,收到CBM后如下弹出一个对话框。
(JPEG)

总结
完成该任务后,感觉这篇文章回答了许多开发人员未解答的问题并且也可以帮助他们完成他们未完成的应用。对于Symbian 6.1我想etelagsm.h文件包含答案。仅仅是演示应用程序并不涉及到法律问题。
请记住发送给我你们国家的应用结果或粘贴结果在论坛上。
特别感谢Vikram Kataruka 的GSM-7位解码和 Eric Bustarret的合理建议。
有何建议或意见请联系我。

[1]注意:该代码运行在Nokia Series 60 v2.0 Symbian OS 7.0s 上,并在印度通过N6600测试过。对于两个主要运送器工作正常。请将在其他国家的工作情况告诉我。

此文为开发视界翻译转载者请注明出处否则追究法律责任

相关文章:
在P800/P910中找回已拨打号码
Symbian C++程序设计