免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
X.Y.E.A.H .net平臺(tái)手機(jī)管理軟件開發(fā)

.net平臺(tái)手機(jī)管理軟件開發(fā)

(一) 簡(jiǎn)介

通過幾個(gè)月零零碎碎地學(xué)習(xí)各方面知識(shí)之后在這個(gè)大二的寒假筆者終于用VB.Net寫出了西門子手機(jī)的輔助軟件——Siemens Support Tool。雖然我沒有最終的完成這個(gè)軟件的所有設(shè)計(jì),但核心的功能已經(jīng)開發(fā)完成,界面也基本到位,我的學(xué)習(xí)的目的也就達(dá)到了。在2月12日正式停止開發(fā)的以后,我想到把寒假20幾天的辛苦歷程作一個(gè)總結(jié),為以后重溫這部分知識(shí)起到一定的作用,也為廣大編程愛好者提供一些幫助和啟發(fā)。筆者才疏學(xué)淺,編程也是零碎時(shí)間自學(xué)過來(lái)的,所以有缺陷和謬誤請(qǐng)大家斧正。

(二) 為何要設(shè)計(jì)?設(shè)計(jì)目的?

用過西門子手機(jī)的都知道西門子手機(jī)在人性化設(shè)計(jì)方面做得比較好,但是讓筆者失望的是電腦端上使用的官方軟件SDS,其缺點(diǎn)是操作不方便,速度比較慢,感覺人性化設(shè)計(jì)不到位。后來(lái)官方推出了用于65系列的Mobile Phone Manager,界面很好看,但安裝后大于120MB的容量及其較慢的速度又讓人大跌眼鏡。

GhostMobile(簡(jiǎn)稱GM)是我用過的國(guó)產(chǎn)非官方軟件里面比較好的一款,但經(jīng)常出現(xiàn)傳輸中一直等待的情況。估計(jì)作者并沒有超時(shí)設(shè)計(jì)。另外GM文件傳輸速度很慢,短信管理不方便,后來(lái)也由于作者使用了新的手機(jī),也就放棄了GM。后來(lái)又找到一款Siemens Mobile Control,簡(jiǎn)稱SiMoCo,是國(guó)外的非官方軟件。800多kb的身軀及其速度、功能方面都超過了官方及GM,令人刮目相看,一度成為我最喜歡的軟件。但用后發(fā)現(xiàn)一些問題,軟件過于專業(yè),選項(xiàng)太多,對(duì)中文的支持不好。

所以最終的目的就是做一款能夠?qū)崿F(xiàn)文件傳輸、短信、便簽、任務(wù)、重要記事管理的軟件。

(三) 準(zhǔn)備工作

2004的暑假我已經(jīng)做了一部分,實(shí)現(xiàn)了基本的文件傳輸和短信功能,當(dāng)時(shí)取名叫作M55 File Transfer Tool。后來(lái)在東北手機(jī)網(wǎng)上公開了,有一些GM無(wú)法連接的手機(jī)我的軟件都可以連接,所以到現(xiàn)在為止有些網(wǎng)友還在使用我的這個(gè)軟件。但由于知識(shí)不夠,做得不是很理想,經(jīng)常出現(xiàn)問題。

短信部分是官方網(wǎng)站下載的ATC_Command_Set_For_L55_Platform,詳細(xì)地講述了55平臺(tái)上的AT指令集。其實(shí)SMS部分的AT指令各大手機(jī)廠商都是通用的,已基本上屬于同一的指令集了。但是發(fā)現(xiàn)文件傳輸是OBEX卻不是那么簡(jiǎn)單。

官方并沒有任何開發(fā)文檔說(shuō)明數(shù)據(jù)傳輸使用的是什么協(xié)議,我用Serial Monitor監(jiān)視到了數(shù)據(jù)傳輸?shù)倪^程,全是HEX代碼,不知道是什么意思。那段時(shí)間一度陷入迷茫狀態(tài),不知道如何下手。后來(lái)在google搜索,又在CSDN里發(fā)了一些帖子求救,但卻沒有一個(gè)能夠明確說(shuō)明的。有一個(gè)網(wǎng)友的留言給了我一些線索,他說(shuō)可能是藍(lán)牙協(xié)議里面的部分。

這條線索給我了極大的鼓舞,因?yàn)楹髞?lái),順藤摸瓜找到了紅外線傳輸協(xié)議,意外地發(fā)現(xiàn)了IrOBEX的描述協(xié)議竟然和監(jiān)視到的HEX代碼的結(jié)構(gòu)一樣。隨后經(jīng)過仔細(xì)的研究發(fā)現(xiàn)就是OBEX協(xié)議,此協(xié)議可以作為上層協(xié)議用在紅外線協(xié)議、藍(lán)牙協(xié)議等。此過程大約經(jīng)歷了2個(gè)多月。其實(shí)現(xiàn)在看來(lái)這個(gè)問題簡(jiǎn)單了,手機(jī)的工廠模式的串口監(jiān)視里面就會(huì)顯示當(dāng)前使用的協(xié)議。當(dāng)數(shù)據(jù)傳輸開始時(shí),會(huì)自動(dòng)從GIPSY變?yōu)镺BEX。但那個(gè)時(shí)候哪知道呢?

跨越了OBEX協(xié)議的障礙以后我寫了一個(gè)OBEX-Multithread類,寫得很垃圾,把十六進(jìn)制轉(zhuǎn)換成字符串,然后再轉(zhuǎn)回來(lái)在發(fā)送。中間使用了string作字符串操作,速度很慢,測(cè)試以后只能勉強(qiáng)超過GM的傳輸速度。

后來(lái)借著Serial Monitor監(jiān)視GM讀取手機(jī)通訊薄的原理,發(fā)現(xiàn)通訊薄是在\telecom\pb目錄里面,但是這個(gè)目錄在手機(jī)里面是隱藏的,無(wú)法直接訪問。由于原來(lái)寫得OBEX庫(kù)很糟糕,只能對(duì)應(yīng)文件傳輸,對(duì)于這個(gè)特殊文件夾里面的文件都無(wú)法操作。修改了之后效果不好,遂放棄了OBEX-Multithread。

由于學(xué)習(xí)的原因,中途也只得停下來(lái)準(zhǔn)備期末考試和六級(jí)。中途無(wú)聊的時(shí)候研究IrMC里面的vCard、vNote、vCalc格式,基本弄懂了如何同步通訊薄、便簽、日歷。2005年1月14日,放假回家了就正式開始動(dòng)工,把所有的東西都重新寫,對(duì)我來(lái)說(shuō),這是一個(gè)巨大的挑戰(zhàn)。

(四) AT指令簡(jiǎn)介

AT指令在當(dāng)代手機(jī)通訊中起著重要的作用,能夠通過AT指令控制手機(jī)的許多行為,包括撥叫號(hào)碼、按鍵控制、傳真、GPRS等。西門子M55手機(jī)為我提供了很多的AT指令,網(wǎng)絡(luò)上關(guān)于AT指令的資料也很多,我這里提取一些比較重要的做個(gè)簡(jiǎn)單解釋。其他的手機(jī)也基本上通用,更詳細(xì)的資料請(qǐng)查閱手機(jī)生產(chǎn)商的資料。

欲使用AT命令,可以安裝微軟的超級(jí)終端程序,選擇好端口連接速度以后就可以正常使用了。

AT指令用法

1、 測(cè)試命令(Test Command)
在AT指令后面加上“=?”即構(gòu)成測(cè)試命令。
例如“AT+CSCS=?”會(huì)列舉出所有支持的字符集。

2、 讀取命令(Read Command)
在AT指令后面加上“?”即構(gòu)成讀取命令。
例如“AT+CSCS?”會(huì)列舉出當(dāng)前設(shè)置。

3、 執(zhí)行命令(Execute Command)
一般而言在AT指令后加上“=”及命令參數(shù)即可。有些命令例如AT+CMGR命令沒有參數(shù),直接就可以執(zhí)行。

注:并不是所有的AT指令都支持1和2。

常用基本AT指令

命令 作用
AT 測(cè)試連接是否正確
ATE0 關(guān)閉回顯。程序初始化AT部分首先關(guān)閉回顯。
ATE1 打開回顯。使用超級(jí)終端測(cè)試命令時(shí)打開。
AT+CGMI 得到廠商信息
AT+CGMR 得到手機(jī)版本號(hào)
AT+CGSN 得到手機(jī)序列號(hào)(IMEI)
AT+CIMI 得到手機(jī)IMSI號(hào)碼
AT+CSCS 獲取、設(shè)置手機(jī)當(dāng)前字符集??稍O(shè)置為GSM或UCS2
AT+CBC 獲取手機(jī)電量
AT+CCLK 獲取設(shè)置手機(jī)時(shí)鐘
AT+CNUM 機(jī)身號(hào)碼。分為線路一和線路二
AT+CSQ 當(dāng)前信號(hào)
AT+COPS 網(wǎng)絡(luò)營(yíng)運(yùn)商
AT+CSCA 短信中心號(hào)碼

以上這些指令都用于與手機(jī)連接的時(shí)候初始化用。取得手機(jī)IMEI及IMSI可以給使程序支持更多的手機(jī)連接并且保持?jǐn)?shù)據(jù)獨(dú)立。

短信部分

命令 作用
AT+CPMS 選擇短信儲(chǔ)存地點(diǎn)??蛇x擇ME(SIM卡)和MT(機(jī)身)
AT+CMGL 列出指定狀態(tài)的短信息的PDU代碼
AT+CMGR 列出指定序號(hào)的短信息PDU代碼
AT+CMGS 發(fā)送短信
AT+CMGD 刪除指定的短信
AT+CMGF 短信格式。分為Text模式和PDU模式
AT+CNMI 設(shè)置新短消息通知電腦端
AT+CSCA 短信中心

以上命令是短消息部分最經(jīng)常使用的命令。具體條目及使用方法會(huì)在后面講解。

(五)  OBEX介紹

一、什么是OBEX,它有什么用途?

OBEX全稱為Object Exchange,中文對(duì)象交換,所以稱之為對(duì)象交換協(xié)議。它在此軟件當(dāng)中有著核心地位,文件傳輸和IrMC同步都會(huì)使用到它。

OBEX協(xié)議構(gòu)建在IrDA架構(gòu)的上層.

OBEX協(xié)議通過簡(jiǎn)單的使用“PUT”和“GET”命令實(shí)現(xiàn)在不同的設(shè)備、不同的平臺(tái)之間方便、高效的交換信息。支持的設(shè)備廣泛,例如PC,PDA,電話,攝像頭,自動(dòng)答錄機(jī),計(jì)算器,數(shù)據(jù)采集器,手表等等。

OBEX協(xié)議定義了一種柔性的概念——objects。也即是對(duì)象。這些對(duì)象可以包括文件,診斷信息,電子商務(wù)卡片,銀行的存款等等。Objects在這里沒有高級(jí)的技術(shù)含義,而是視你的應(yīng)用而定。

OBEX協(xié)議小到可作“命令和控制”功能,例如對(duì)電視機(jī),錄像機(jī)等的操作。大道可以做很復(fù)雜的操作,例如數(shù)據(jù)庫(kù)的事務(wù)處理和同步。

OBEX能夠具有以下幾個(gè)特點(diǎn):

1、  友好的應(yīng)用——可實(shí)現(xiàn)快速開發(fā)。

2、  緊縮——可用在資源有限的小型設(shè)備上。

3、  跨平臺(tái)

4、  柔性的數(shù)據(jù)支持。

5、  方便的作為其他Internet傳輸協(xié)議的上層協(xié)議。

6、  可擴(kuò)展性——提供了對(duì)未來(lái)需求的擴(kuò)充支持而不影響以存在的實(shí)現(xiàn)。例如可擴(kuò)展安全,數(shù)據(jù)壓縮等。

7、  可測(cè)試可調(diào)試。

更為具體的關(guān)于OBEX的介紹請(qǐng)查閱IrOBEX協(xié)議。

二、OBEX對(duì)象模型

關(guān)于Headers

對(duì)象模型回答了對(duì)象是如何在OBEX協(xié)議描述的。這個(gè)模型必須包括被傳輸?shù)膶?duì)象和對(duì)對(duì)象的描述。為了做到這點(diǎn),OBEX定義了Headers的概念。

一個(gè)Header反映了對(duì)象的一個(gè)方面,例如名字、長(zhǎng)度、描述文字或者對(duì)象本身。例如,一個(gè)文件對(duì)象demo.txt會(huì)包含它的名字,一個(gè)類型標(biāo)示為“text”,長(zhǎng)度和文件本身。

Headers的構(gòu)成

Headers簡(jiǎn)單的由和組成,簡(jiǎn)稱為和。

HI由一個(gè)字節(jié)組成,指出了Header包含的內(nèi)容以及它的格式。HV包含了一個(gè)或者多個(gè)字節(jié),其結(jié)構(gòu)由HI所決定。

所有的Header都是可選的,取決于設(shè)備的類型和事務(wù)的種類。你可以使用所有的Header,或者一些,或者沒有。ID可以使Header可解析以及與傳輸順序無(wú)關(guān),也可以使不支持的Header被忽略掉。

HI又可以分為兩部分,高2位和低6位。高2位確定了HI的編碼方式(見表二),低6位確定了HI的意義(見表三)。兩個(gè)表都是我從IrOBEX中的表摘抄并部分翻譯過來(lái)的。

表二

HI的第8和第7位

意義

00(0×00)

以Null(0×00)結(jié)尾的的Unicode文字。2個(gè)字節(jié)的無(wú)符號(hào)整數(shù)長(zhǎng)度前綴。

01(0×40)

Byte塊,2個(gè)字節(jié)的無(wú)符號(hào)整數(shù)前綴。

10(0×80)

1Byte容量。

11(0xC0)

4Byte容量,以高位先傳輸為原則。

表三

HI

Header名稱

描述

0xC0

Count

連接中用于指名對(duì)象的數(shù)量。

0×01

Name

對(duì)象的名字。一般為文件名。

0×42

Type

對(duì)象的類型。例如text,html,binary,manufacture specific

0×44

0xC4

Time

時(shí)間戳。ISO 8601版本
時(shí)間戳。4Byte版本(用于兼容)

0×05

Description

對(duì)對(duì)象的文本描述

0×46

Target

操作的目的服務(wù)名

0×47

HTTP

一個(gè)HTTP1.x頭

0×48

Body

對(duì)象的一部分

0×49

End of body

對(duì)象的最后一部分

0×4A

Who

OBEX Application標(biāo)識(shí),用于表明是否是同一個(gè)應(yīng)用。

0xCB

Connection ID

用于OBEX多路連接的標(biāo)識(shí)

0×4C

App.Parameters

擴(kuò)展的應(yīng)用層請(qǐng)求和回復(fù)信息

0×4D

Auth.Challenge

Authentication digest-challenge

0×4E

Auth.Response

Authentication digest-response

0×4F

Object Class

對(duì)象的OBEX對(duì)象類

0×10 to 0×2F

Reserved

保留

0×30 to 0×3F

User defined

用戶自定義的。

 

 

關(guān)于常用Header的更詳盡的解釋,更詳盡信息請(qǐng)參考IrOBEX

1、Name
              Name是一個(gè)用來(lái)描述對(duì)象名稱的Header,由以Null(0×00)結(jié)尾的Unicode字符串組成。例如:DEMO.TXT

2、Length
Length描述了對(duì)象的大小,由4個(gè)字節(jié)組成。如果Length事先知道,這個(gè)Header應(yīng)該被用到。這樣可以讓接受者迅速的知道需要分配多少空間,可使處理更為迅速。但這也不是必須的,有些情況下長(zhǎng)度無(wú)法確認(rèn),但設(shè)備可以通過End-Body Header知道什么時(shí)候結(jié)束。

3、Time

Time描述了對(duì)象的最后修改的時(shí)間。使用ISO8601格式。

本地時(shí)間格式:YYYYMMDDTHHMMSS

UTC時(shí)間格式:YYYYMMDDTHHMMSSZ

格式中的T可以方便的區(qū)分日期和時(shí)間。UTC時(shí)間使用Z作為標(biāo)記。建議使用UTC時(shí)間。
4、Body、End-of-Body

       Body Header由HI、一個(gè)2Byte長(zhǎng)度的描述和整個(gè)的對(duì)象本身。End-of-Body組成和Body組成一樣,但標(biāo)識(shí)了這是對(duì)象的最后一部分。如果對(duì)象本來(lái)就很小,就直接使用End-of-Body。

 

三、請(qǐng)求(Request)和回應(yīng)(Response

OBEX使用Request和Response作為最基本的操作。請(qǐng)求的每個(gè)Request必然有一個(gè)Response,否則可認(rèn)為Request失敗。

Request由一個(gè)或多個(gè)的Packet(包)組成,每個(gè)包的結(jié)構(gòu)如下表

Request數(shù)據(jù)包結(jié)構(gòu)

Byte 0

Byte 1,2

Byte 3 to n

操作碼(opcode)

Packet Length(包長(zhǎng)度)

Headers或請(qǐng)求信息

 

由于每個(gè)Request可能有多個(gè)Packet,opcode的最高位稱為Final bit。如果被設(shè)置為1,那么說(shuō)明這是Request的最后一個(gè)Packet。例如:當(dāng)用PUT操作發(fā)送一個(gè)大文件時(shí),會(huì)有幾個(gè)Packet作為一個(gè)Request。那么只有最后一個(gè)Packet的FinalBit設(shè)置為1。

 

Response也由一個(gè)或多個(gè)Packet組成,每個(gè)包的結(jié)構(gòu)如下表

Response數(shù)據(jù)包結(jié)構(gòu)

Byte 0

Byte 1,2

Byte 3 to n

Response Code(返回值)

Response Length(回應(yīng)長(zhǎng)度)

ResponseData回應(yīng)的數(shù)據(jù)

 

同樣的ResponseCode的最高位也叫做FinalBit。ResponseData可能包含對(duì)象和Header,或者其它信息。

下表列出了了常見的opcode和responseCode,更詳盡的請(qǐng)參考IrOBEX 1.2文檔。

opcode

Opcode(w/high bit set)

定義

意義

0×80 *

Connect

連接

0×81 *

Disconnect

斷開連接

0×02(0×82)

Put

發(fā)送一個(gè)對(duì)象

0×03(0×83)

Get

取得一個(gè)對(duì)象

0×04(0×84)

Reserved

保留的

0×85 *

SetPath

設(shè)置路徑

0xFF *

Abort

取消當(dāng)前的操作

0×06到0×0F

Reserved

作為擴(kuò)展保留

0×10到0×1F

User definable

用戶自定義的

*總是設(shè)置FinalBit

 

ResponseCode

ResponseCode

定義

0×10(0×90)

Continue(繼續(xù))

0×20(0xA0)

OK,Success

0×40(0xC0)

Bad Request(服務(wù)端不明白R(shí)equest)

0×41(0xC1)

Unauthorized(未授權(quán)的)

0×43(0xC3)

Fobidden(禁止——服務(wù)器明白R(shí)equest,但拒絕)

0×44(0xC4)

Not Found(未找到)

 

四、說(shuō)明。

1、 Connect(連接)

此操作初始化會(huì)話然后設(shè)置參數(shù)。其Request格式為

Byte 0

Byte 1,2

Byte 3

Byte 4

Byte 5,6

Byte 7 to n

0×80

包長(zhǎng)度

OBEX版本

標(biāo)志

最大OBEX包長(zhǎng)度

可選Header

注:OBEX版本現(xiàn)在為1.0。

Response格式為:

Byte 0

Byte 1,2

Byte 3

Byte 4

Byte 5,6

Byte 7 to n

ResponseCode

包長(zhǎng)度

OBEX版本

標(biāo)志

最大OBEX包長(zhǎng)度

可選Header

對(duì)于更多關(guān)于Connect的說(shuō)明請(qǐng)參考IrOBEX

2、 Disconnect(斷開當(dāng)前會(huì)話)

此操作斷開OBEX會(huì)話。例如斷開當(dāng)前FolderListing Service,然后使用Connect連接到IrMC Sync Service實(shí)現(xiàn)同步通訊薄等功能。

Disconnect格式為:

Byte 0

Bytes 1,2

Bytes 3 to n

0×81

包長(zhǎng)度

可選Header

成功的斷開會(huì)返回0Xa0,拒絕會(huì)返回0xD3

3、 Put操作

Put操作從客戶端發(fā)送一個(gè)對(duì)象到服務(wù)端。一般至少含有Name和Length兩個(gè)Header。對(duì)于文件而言有可能還有Date/Time Header。

Put操作的格式如下:

Byte 0

Bytes 1,2

Bytes 3 to n

0×02(當(dāng)FinalBit設(shè)置時(shí)為0×82)

PacketLength包長(zhǎng)度

一組Header

回應(yīng)格式如下:

Byte 0

Bytes 1,2

Bytes 3 to n

ResponseCode(要求繼續(xù)為0×90;成功為0xA0)

包長(zhǎng)度

可選Header

關(guān)于Put操作的更詳細(xì)的用法將在文件傳輸部分作解釋。

4、 Get操作

Get操作從服務(wù)端返回一個(gè)對(duì)象。

Get操作的格式如下:

Byte 0

Bytes 1,2

Bytes 3 to n

0×03

包長(zhǎng)度

一組Header

回應(yīng)格式如下:

Byte 0

Bytes 1,2

Bytes 3 to n

Response Code

包長(zhǎng)度

可選Header

關(guān)于Get操作更詳細(xì)的用法將在文件傳輸部分作解釋。

5、 Abort操作

Abort操作中斷一個(gè)多包操作(例如發(fā)送一個(gè)大文件)。Abort操作可以包含描述中斷原因的Description Header。

Abort操作的格式如下:

Byte 0

Bytes 1,2

Bytes 3 to n

0xFF

包長(zhǎng)度

可選Header

Abort對(duì)應(yīng)的應(yīng)該是一個(gè)成功的操作(0xA0),指明這個(gè)操作已被接收并且服務(wù)端已經(jīng)重新與客戶端同步。如果返回的另外的值,客戶端應(yīng)該Disconnect。

6、 SetPath

SetPath操作用于切換對(duì)方的路徑。通常使用一個(gè)Name Header用于指定對(duì)方路徑名稱。如果為空,則返回默認(rèn)目錄,通常為根目錄

SetPath操作格式如下:

(六)  OBEX應(yīng)用——文件傳輸部分

在手機(jī)數(shù)據(jù)傳輸方面基本OBEX應(yīng)用分為

l         文件傳輸

l         IrMC同步

文件傳輸又可以細(xì)分為以下基本操作

l         初始化連接

l         斷開連接

l         設(shè)置路徑

l         取得目錄信息

l         創(chuàng)建目錄

l         上傳下載文件

l         刪除文件或空目錄

在筆者的軟件當(dāng)中設(shè)計(jì)了OBEX這個(gè)類,里面包含了以上所有的基本操作。另外針對(duì)M55的服務(wù)端的特殊性又設(shè)計(jì)了更名、取得磁盤空間信息、移動(dòng)、拷貝文件的功能。具體請(qǐng)參考源代碼。

下面具體講述各個(gè)操作的細(xì)節(jié)。

l         初始化連接

初始化連接包括了使手機(jī)進(jìn)入OBEX狀態(tài)再到發(fā)送Connect指令的一系列過程。具體流程參考下圖。

ATÆAT^SQWE=0ÆAT^SQWE=3ÆConnectÆ連接到Folder-Listing Service

其中AT^SQWE=0和AT^SQWE=3是西門子特有的隱藏的AT指令,甚至在官方的AT指令集里面都沒有提到。其作用是初始化手機(jī)到OBEX模式。

發(fā)送Connect指令收到手機(jī)回復(fù)以后確定Max Packet Length等參數(shù)。最后連接到Folder-Listing Service進(jìn)行文件操作。如果需要IrMC同步的話,在Connect后直接連接到IrMC Sync Service即可,手機(jī)立刻進(jìn)入同步模式,所有的應(yīng)用程序退出。

在筆者的程序中當(dāng)中首先使用AT指令確定手機(jī)當(dāng)前的工作,如果超時(shí),嘗試發(fā)送+++并等待1秒鐘以便手機(jī)從不正常的OBEX狀態(tài)中退出。然后在此發(fā)送AT,成功后即進(jìn)行文件操作,否則引發(fā)一個(gè)錯(cuò)誤。

l         斷開連接

這里的斷開連接是指從OBEX模式退出到AT狀態(tài)中。在AT指令中,連續(xù)發(fā)送三個(gè)0×2B然后等待一秒鐘以上即可退出數(shù)據(jù)模式進(jìn)入常規(guī)AT模式。

l         設(shè)置路徑

程序中使用SetPath操作設(shè)置路徑。需要注意的是,可以設(shè)計(jì)兩種風(fēng)格的過程:一種使用絕對(duì)路徑,另一種使用相對(duì)路徑。

對(duì)于手機(jī)而言,經(jīng)筆者實(shí)踐證明,使用絕對(duì)路徑要比使用相對(duì)路徑方便,而且更準(zhǔn)確,但效率上稍遜,特別是在多層目錄的情況下。由于手機(jī)沒有能夠返回當(dāng)前路徑的方法,所以相對(duì)路徑總難以控制,只有通過程序控制,極容易出現(xiàn)錯(cuò)誤。所以建議使用絕對(duì)路徑。

如果使用絕對(duì)路徑,那么路徑名將呈現(xiàn)\path1\path2這種形式。首先回到根目錄,然后一級(jí)一級(jí)的到達(dá)目的。在筆者的OBEX類當(dāng)中,可以看到BacktoRoot這個(gè)過程。其作用就是把當(dāng)前程序路徑切換到根目錄以免引起混亂。

l         取得目錄信息

要取得一個(gè)目錄的文件信息可以用發(fā)送Get指令。該Get指令需要一個(gè)TypeHeader,其值為x-obex/folder-listing

隨后服務(wù)端會(huì)返回一個(gè)xml文件,包含了整個(gè)目錄的信息。例如子目錄名、文件名、大小、最后修改時(shí)間。再通過xml解析后就會(huì)得到目錄信息。

l         創(chuàng)建目錄

當(dāng)SetPath的Flags的Bit1設(shè)為1并且無(wú)法找到目錄時(shí),服務(wù)端會(huì)創(chuàng)建這個(gè)目錄并進(jìn)入。

請(qǐng)注意,再次使用SetPath并將Flags的Bit0設(shè)為1返回上層目錄,否則容易引起混亂。

l         上傳下載文件

使用Put和Get命令可以實(shí)現(xiàn)上傳和下載文件。注意所有的文件操作都在SetPath所指定的目錄下進(jìn)行。

使用Put命令實(shí)現(xiàn)上傳時(shí),至少需要提供NameHeader,BodyHeader,一般還要提供LengthHeader,DateTimeHeader。大文件傳輸需要正確處理BodyHeader,不能超出了服務(wù)端最大所能接收的Packet的大小,否則會(huì)出現(xiàn)錯(cuò)誤。

需要注意的是如果當(dāng)前文件存在,那么Put命令不會(huì)覆蓋已有的文件而是追加,導(dǎo)致錯(cuò)誤。傳輸文件之前需要首先刪除同名文件。

使用Get命令實(shí)現(xiàn)下載時(shí),只需要提供NameHeader即可。具體例子參考上一節(jié)。

l         刪除文件或空目錄

使用Put命令,其NameHeader指定為文件名或目錄名并將BodyHeader設(shè)置為空即可。

非空目錄無(wú)法刪除,會(huì)返回錯(cuò)誤。

 

(七)  IrMC簡(jiǎn)介

要實(shí)現(xiàn)通訊薄、日歷、便簽的同步,需要用到IrDA協(xié)議里面的IrMC部分。

IrMC全稱為Ir Mobile Communications。它定義了利用IR無(wú)線傳輸?shù)脑O(shè)備之間通訊的規(guī)則。IrMC協(xié)議文檔詳細(xì)敘述了IrMC的方方面面,可以在我的主頁(yè)(http://dream-world.nease.net)下載到PDF版本。

下面主要講述我在開發(fā)當(dāng)中所用到的部分以及實(shí)現(xiàn)方法。更為詳細(xì)的資料請(qǐng)參考IrMC協(xié)議。

Phonebook

在手機(jī)軟件桌面端通訊薄的管理是整個(gè)軟件的必備功能之一,利用其信息可以方便的和Outlook等軟件實(shí)現(xiàn)同步,實(shí)現(xiàn)更強(qiáng)大的功能。

通訊薄的管理分為讀取、刪除、增添、修改。通過這幾個(gè)功能的組合可以實(shí)現(xiàn)更為強(qiáng)大的同步功能。下面分條概述。

l         讀取

n         讀取所有的Entry
使用OBEX的GET命令取得\telecom\pb.vcf文件。
得到的的文件是一個(gè)vCard文件,里面包含了所有的通訊薄。其格式為vCard格式。關(guān)于vCard的簡(jiǎn)介及編碼器解碼器見后。下面給出一個(gè)范例:
BEGIN:VCARD
VERSION:2.1
X-IRMC-LUID:1017646
X-ESI-CATEGORIES;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E5=AE=B6=E4=BA=BA
N:test
ADR:;;Street;city;;610000;country
ORG:company
TEL;HOME:123456
TEL;WORK:123456
TEL;CELL:123456
TEL;FAX:123456
TEL;FAX;HOME:123456
EMAIL;INTERNET:a@a.ao
EMAIL;HOME;INTERNET:b@g
URL:http
BDAY:1985-04-23
END:VCARD
也可以通過X-IRMC-LUID所給的LUID號(hào)碼直接取得相應(yīng)的vCard。

1.         讀取指定LUID的Entry
使用OBEX的GET命令取得\telecom\pb\luid\xxxx.vcf,其中xxxx代表了LUID號(hào)碼。
得到的依然是一個(gè)vCard文件,只不過只包含特定LUID號(hào)碼的vCard信息??梢院?jiǎn)單的通過Outlook查看vCard所包含的信息。

l         刪除
欲刪除一個(gè)Entry

1.         連接到IrMC_Sync_Service(發(fā)送0×80, 0×0, 0×13, 0×10, 0×0, 0×40, 0×6, 0×46, 0×0, 0xC, 0×49, 0×52, 0×4D, 0×43, 0×2D, 0×53, 0×59, 0×4E, 0×43)使手機(jī)處于同步狀態(tài)。

2.         得到ChangeCount

ChangeCount是手機(jī)里面儲(chǔ)存修改次數(shù)的一個(gè)數(shù)值,主要用于同步。具體相關(guān)資料請(qǐng)參考IrMC協(xié)議。

3.         構(gòu)建數(shù)據(jù)包。
Opcode:PUT
NameHeader:xxxx.vcf(xxxx為欲刪除的entry的LUID)
AppParam:0×11,ChangCount字符串形式長(zhǎng)度(Integer),ChangeCount的ANSI形式

4.         使用OBEX的PUT命令,傳輸一個(gè)xxxx.vcf(xxxx指LUID)空文件到\telecom\pb\luid覆蓋即可。

5.         發(fā)送0×81, 0×0, 0×3斷開IrMC_Sync_service

l         添加
欲添加一個(gè)文件:

1.         連接到IrMC_Sync_Service

2.         得到ChangeCount

3.         構(gòu)建數(shù)據(jù)包
Opcode:PUT
NameHeader:.vcf
AppHeader:0×11,ChangeCount字符串長(zhǎng)度(Interger),ChangCount的ANSI形式
Body或者End-of-Body Header:vcf文件內(nèi)容

4.         OBEX的PUT命令上傳到\telecom\pb\.vcf文件即可。
注意:文件名取名為“.vcf”。

5.         發(fā)送0×81, 0×0, 0×3斷開IrMC_Sync_service

l         修改
修改過程與添加過程相似,只是將文件名改為欲修改的vCard的LUID.vcf就行了。

 

Notes

       便簽是大多數(shù)手機(jī)都提供的功能,能夠方便的記錄簡(jiǎn)短的信息。在我的M55手機(jī)上能夠儲(chǔ)存150Byte的信息,也就是150個(gè)英文或者75個(gè)漢字。軟件通過管理便簽可以與Outlook等軟件同步,實(shí)現(xiàn)更高級(jí)的功能。

       管理Notes的方法和Phonebook類似。得到全部Notes的vNote只需要獲取\telecom\nt.vnt即可。刪除、添加、修改只需要把\telecom\pb\luid改為\telecom\nt\luid即可。在此不再贅述。

 

       Calendar
日歷功能提供了事件提醒功能,分為重要記事(vEvent)和任務(wù)(vTodo)。通過管理日歷,同樣可以實(shí)現(xiàn)和Outlook同步,實(shí)現(xiàn)電腦和手機(jī)的同步。

       管理Calendar的方法和Phonebook類似。得到全部vCalendar只需要獲取\telecom\cal.vcs。刪除、添加、修改只需要把\telecom\pb\luid改為\telecom\cal\luid即可。在此不再贅述。

       但值得注意的是vCalendar的結(jié)構(gòu)

BEGIN:VCALENDAR

VERSION:1.0

BEGIN:VEVENT

….

END:VEVENT

BEGIN:VTODO

END:VTODO

END:VCALENDAR

完整的vCalender包含了至少一個(gè)vEvent或者一個(gè)vTodo,因此在添加、修改vEvent、vTodo時(shí)要將其補(bǔ)充為一個(gè)完整的vCalender結(jié)構(gòu),否則服務(wù)端會(huì)拒絕操作。

 

遇到的問題:

在實(shí)際操作中,遇到問題最多的地方在Phonebook部分。我的手機(jī)第一次同步的時(shí)候經(jīng)常出現(xiàn)數(shù)據(jù)庫(kù)被鎖的情況,用SiMoCo讀取也是一樣,說(shuō)明是手機(jī)拒絕寫操作。這時(shí)候關(guān)閉手機(jī)再重新啟動(dòng)就好了。至于原因,我還沒有搞清楚,希望能有高人指點(diǎn)

(八)  vCard、vNote、vCalender格式簡(jiǎn)介

vCard稱為電子商務(wù)卡片,主要用于記錄通訊薄的聯(lián)系人信息等,方面不同設(shè)備之間的數(shù)據(jù)交換。自筆者的M55手機(jī)中,可以發(fā)送一條短信到對(duì)方,其中包含了vCard格式的聯(lián)系人信息,西門子其他型號(hào)的手機(jī)可以接收解碼存儲(chǔ)。另外通過手機(jī)紅外線傳輸?shù)诫娔X上的聯(lián)系人也是用的vCard格式。如果安裝了Outlook,則可以直接打開vCard并看到其包含的信息。下面主要簡(jiǎn)要介紹一下vCard格式,其他vNote、vCalender格式和vCard相近,就不再贅述。更詳細(xì)的資料請(qǐng)參考vCard Specification,在筆者主頁(yè)有相關(guān)下載。

關(guān)于vCard、vNote、vCalender的.Net簡(jiǎn)單編碼解碼器請(qǐng)參閱SIEMENS SUPPORT TOOL源代碼中的IrMC部分。

vCard Object(vCard對(duì)象)

一個(gè)vCard數(shù)據(jù)流可以包含一個(gè)或者多個(gè)vCard Object。在數(shù)據(jù)流中一個(gè)vCard Object定義為以“BEGIN:VCARD”開始并以“END:VCARD”結(jié)束的數(shù)據(jù)。如果只有到達(dá)了數(shù)據(jù)流尾都沒有出現(xiàn)“END:VCARD”,則整個(gè)vCard Object包含從“BEGIN:VCARD”開始到數(shù)據(jù)流結(jié)束的地方。

       vCard Property(vCard屬性)

       vCard是一個(gè)或多個(gè)Property的集合。一個(gè)Property是唯一命名的值。一系列的Property可以在vCard中成為一組。

vCard Property的格式如下:

PropertyName[‘;’ PropertyParameters]’:’PropertyValue

1、  PropertyName及PropertyParameters不區(qū)分大小寫。

2、  PropertyParameters可選,可以為零個(gè)或多個(gè),與ProperyName以分號(hào)相隔,與PropertyValue以冒號(hào)相隔。

3、  vCard可以分多行呈現(xiàn)。由于在這個(gè)軟件里面應(yīng)用得不多,所以筆者也沒有鉆研具體實(shí)現(xiàn)方法??梢詤⒖紇Card Specification。

例如TEL;HOME;+86111222333其PropertyName為TEL,PropertyParameters為HOME,PropertyValue為+86111222333。

Encoding(編碼)

vCard默認(rèn)的編碼方式是7-Bit。默認(rèn)編碼方式可以使用ENCODING屬性參數(shù)(Property parameter)改變。其值為可以為BASE64;QUOTED-PRINTABLE;8BIT。這個(gè)參數(shù)可以用在任何的Property里。

例如:

X-ESI-CATEGORIES;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E5=AE=B6=E4=BA=BA

下面簡(jiǎn)要說(shuō)明QUOTED-PRINTABLE編碼方式,更為詳細(xì)的資料請(qǐng)參考相關(guān)文檔:

ASCII可顯示字符基本保持不變。Unicode字符或者UTF8編碼字符使用等號(hào)加其對(duì)應(yīng)16進(jìn)制代碼表示。例如上述CHARSET為UTF8的字符=E5=AE=B6=E4=BA=BA對(duì)應(yīng)的UTF8編碼0xE5,0xAE,0xB6代表中文“家”,其他的代表“人”。另外如果其中有可顯示ASCII碼,保持原樣輸出。

例如ENCODING=QUOTED-PRINTABLE:Home=E5=AE=B6People=E4=BA=BA

解碼后為“Home家People人”。

Character Set(字符集)

默認(rèn)的字符集是ASCII。可以通過CHARSET參數(shù)改變默認(rèn)的字符集。其參數(shù)可取的值為所有IANA(Internet Assigned Numbers Authority)注冊(cè)的字符集。這個(gè)參數(shù)可以用于任何Property,但某些Property并不起作用。

例如:

X-ESI-CATEGORIES;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E5=AE=B6=E4=BA=BA

vCard例子:

BEGIN:VCARD

VERSION:2.1

X-IRMC-LUID:1017646

X-ESI-CATEGORIES;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E5=AE=B6=E4=BA=BA

N:test

ADR:;;Street;city;;610000;country

ORG:company

TEL;HOME:123456

TEL;WORK:123456

TEL;CELL:123456

TEL;FAX:123456

TEL;FAX;HOME:123456

EMAIL;INTERNET:a@a.ao

EMAIL;HOME;INTERNET:b@g

URL:http

BDAY:1985-04-23

END:VCARD

(九)  短信部分——PDU簡(jiǎn)介及其格式

PDU是大多數(shù)手機(jī)短信通訊的核心,僅有少數(shù)手機(jī)只支持Text模式(例如筆者的MOTO C330)。PDU模式比起Text模式可以提供能為強(qiáng)大的功能,但其編碼較Text模式困難。無(wú)論哪種模式,我們都可以通過AT指令控制終端實(shí)現(xiàn)短信的發(fā)送、接收、刪除等管理。下面主要介紹PDU的構(gòu)成及編碼解碼。

PDU的構(gòu)成

PDU是由一串由“0-9”及“A-F”組成。表面上看起來(lái)就是一組16進(jìn)制的數(shù)所組成的。

下面舉一個(gè)發(fā)送和接收的例子。

1、  手機(jī)發(fā)送的一個(gè)PDU串:

0891683108200805F011190D91683188902848F40008FF108FD9662F4E0067616D4B8BD577ED4FE

對(duì)比3GPP協(xié)議得到:(二進(jìn)制代碼從左到右依次為高位->低位)

短信中心地址字段

08    地址長(zhǎng)度:8個(gè)字節(jié),包括其后的91

91    地址類型:10010001
Bit7:1。始終為1
Bits 6,5,4:Type-of-Number(號(hào)碼類型):001,代表Internation Number。也即是號(hào)碼前加“+”。注意:對(duì)某些比較特殊的號(hào)碼,例如手機(jī)與小靈通的互通時(shí),這里不能設(shè)置為001,而要設(shè)置成000,代表號(hào)碼前沒有“+”,否則無(wú)法接收。

       Bits 3,2,1:Numbering-plan-identification:一般默認(rèn)為0001,表示電話號(hào)碼類型的。

683108200805F0   短信中心號(hào)碼:一個(gè)字節(jié)內(nèi)反轉(zhuǎn),8613800280500,如果長(zhǎng)度為奇數(shù)則需要加“F”補(bǔ)齊

       FirstOctet字段

11       包含TP-MTI(2bit),TP-RD(1bit),TP-VPF(2bit),TP-RP(1bit),TP-UDHI(1bit),TP-SRR(1bit)

二進(jìn)制表示形式:0 0 0 10 0 01

TP-MTI:01

       TP-Message-Type-Indicator(消息類型指示符)

Bit1,0:01      指示為SMS-SUBMIT類型
TP-RD:0

TP-Reject-Duplicates(是否拒絕相同重復(fù)消息)

Bit2:0          指示短消息中心接受未轉(zhuǎn)發(fā)的具有相同TP-MR的消息。

TP-VPF:10

       TP-Validity-Period-Format(有效期格式)

       Bit4,3:10      指示使用相對(duì)格式。

TP-SRR:0

       TP-Status-Report-Request

       Bit5:0          指示不使用狀態(tài)報(bào)告。

TP-UDHI:0
       TP-User-Data-Header-Indicator(用戶數(shù)據(jù)頭標(biāo)示)
Bit6:0          指示這是一個(gè)SMS消息,沒有用戶數(shù)據(jù)頭。EMS消息需要設(shè)置。

TP-RP:0
       TP-Reply-Path(回復(fù)路徑)
Bit7:0          指示沒有設(shè)置回復(fù)路徑。

消息參考值TP-MR

19    TP-Message-Reference

       對(duì)方號(hào)碼字段

              0D91683188902848F4

              其結(jié)構(gòu)與短信中心號(hào)碼字段部分類似,不再贅述。

       協(xié)議標(biāo)識(shí)TP-PID

              00    TP-Protocol-Identifier(上層協(xié)議指示),一般設(shè)置為00,表示普通GSM,點(diǎn)對(duì)點(diǎn)
       編碼方法TP-DCS

              08    TP-Data-Coding-Scheme(數(shù)據(jù)編碼設(shè)置),指示TP-UD的編碼方式。08代表Unicode方式。00為7Bit編碼

       有效期TP-VP

FF   TP-Validity-Period(有效期)。FF表示最大。

       用戶數(shù)據(jù)長(zhǎng)度TP-UDL

10    TP-User-Data-Length(用戶數(shù)據(jù)長(zhǎng)度)

                     0×10長(zhǎng)度。注意不同編碼下用戶長(zhǎng)度定義不同。

       用戶數(shù)據(jù)TP-UD

8FD9662F4E0067616D4B8BD577ED4FE    TP-User-Data
中文“這是一條測(cè)試短信”的Unicode編碼

 

2、  手機(jī)接收的PDU串

0891683108200805F0040D91683188902848F4000850208151754500108FD9662F4E0067616D4B8BD577ED4FE1

短信中心地址字段

        0891683108200805F0:+861380280500

FirstOctet

       04

               其二進(jìn)制代碼:00000100

               TP-MTI:00

               TP-MMS(TP-More-Message-to-Send):1 短信中心沒有更多的消息發(fā)送

               TP-SRI:0

               TP-UDHI:0

               TP-RP:0

發(fā)送方號(hào)碼

        0D91683188902848F4:+8613880982844

協(xié)議標(biāo)識(shí)
              00    TP-DCS  點(diǎn)對(duì)點(diǎn)

編碼方式

        08    TP-DCS  Unicode編碼

短信中心時(shí)間戳
50208151754500 TP-SCTS   字節(jié)反轉(zhuǎn)05/02/18 15:57:45  最后的00代表時(shí)區(qū),這里為0

用戶數(shù)據(jù)長(zhǎng)度

        10    TP-DHL

用戶數(shù)據(jù)

        8FD9662F4E0067616D4B8BD577ED4FE1         TP-UD

       中文“這是一條測(cè)試短信”的Unicode編碼

(十)  短信部分——VB.NET解碼PDU

早在2004年1月份我就開始初步的研究PDU的編碼解碼原理,對(duì)于PDU也有比較深刻的認(rèn)識(shí)。隨后按照3GPP協(xié)議寫了一個(gè)PDU Decoder,后來(lái)寫成PDU Decoder文章發(fā)表在CodeProject上面,有幾個(gè)好心的外國(guó)網(wǎng)友給我指出了一些BUG,現(xiàn)在成了一個(gè)比較完善的Decoder。具體的源碼在http://blog.csdn.net/hesicong/archive/2004/09/24/115356.aspx 。本文講解編碼器的構(gòu)成以及我所使用的解碼方法及技巧。

解碼器的構(gòu)成

NameSpace SMS

                      Decoder

MustInheritClass     SMSBase

Class                             EMS_RECEIVED

Class                             EMS_SUBMIT

Class                             SMS_RECEIVED

Class                             SMS_STATUS_REPORT

Class                             SMS_SUBMIT

Class                             PDUDecoder

SMSBase部分

SMSBase類是必須繼承類,它包含了PDU的基本結(jié)構(gòu)以及一些相關(guān)輔助函數(shù),是最基本的類,其他的類都是從SMSBase繼承的。通過SMSBase的Shared函數(shù)GetSMSType可以得到PDU的類型,從而確定使用的Class。

SMSBase包含了所有短信類型所共有的基本信息部分以及一個(gè)指示短信類型的枚舉SMSType,繼承的類擴(kuò)展其特有的基本信息部分。

            Public SCAddressLength As Byte  ‘Service Center Address length

            Public SCAddressType As Byte    ‘Service Center Type[See GSM 03.40]

            Public SCAddressValue As String ‘Service Center nuber

            Public FirstOctet As Byte       ‘See GSM 03.40

 

            Public TP_PID As Byte

            Public TP_DCS As Byte

            Public TP_UDL As Byte

            Public TP_UD As String

            Public Text As String

            Public Type As SMSType

            Public UserData As String

 

            Public Enum SMSType

                SMS_RECEIVED = 0

                SMS_STATUS_REPORT = 2

                SMS_SUBMIT = 1

                EMS_RECEIVED = 64 ‘It is “Reserved” on my phone??

                EMS_SUBMIT = 65

   End Enum

 

SMSBase中定義了一個(gè)必須重寫的過程GetOrignalData,其參數(shù)為PDUCode,目的是為了得到PDU的基本信息。不同的短信類型具有不同的解碼過程,所以作為一個(gè)必須重寫的函數(shù)。

Public MustOverride Sub GetOrignalData(ByVal PDUCode As String)

 

SMSBase中還有一系列的輔助函數(shù),具體實(shí)現(xiàn)方法見源代碼:

處理PDU代碼的:

處理PDU代碼我運(yùn)用了自稱為“按需裁減”的技巧,就是把需要的數(shù)據(jù)提取出來(lái)解碼,然后從原PDUCode中刪除這一部分,在傳遞給下一個(gè)函數(shù)處理。這樣就不用考略具體的偏移量,簡(jiǎn)化了操作,增強(qiáng)了適應(yīng)性。為了能夠減少返回處理過的PDUCode麻煩,我使用了ByRef,執(zhí)行過程以后PDUCode就自動(dòng)被裁減了。

‘Get a byte from PDU string

Shared Function GetByte(ByRef PDUCode As String) As Byte

‘Get a string of certain length

Shared Function GetString(ByRef PDUCode As String, ByVal Length As Integer) As String

‘Get date from SCTS format

Shared Function GetDate(ByRef SCTS As String) As Date

         ‘Swap two bit

         Shared Function Swap(ByRef TwoBitStr As String) As String

         ‘Get phone address

         Shared Function GetAddress(ByRef Address As String) As String

         Shared Function GetSMSType(ByVal PDUCode As String) As SMSBase.SMSType

TP-UD解碼部分:

       TP-UD的解碼的任務(wù)主要集中在Unicode的解碼和7BitCode的解碼。其中Unicode的解碼很方便,只需要將兩個(gè)字節(jié)的PDUCode通過Val函數(shù)轉(zhuǎn)換成為數(shù)字,在通過ChrW函數(shù)即可得到。

       而7BitCode就顯得比較難,下面以Test四個(gè)字符簡(jiǎn)單介紹其基本原理,具體的編碼方式請(qǐng)參考相關(guān)資料。

              Byte1      11010100       0xD4

              Byte2      11110010       0xF2

              Byte3      10011100       0×9C

              Byte4      00001110       0×0E

              注:各字符二進(jìn)制代碼:

              T:1010100   e:1100101    s:1110011    t:1110100

       從這個(gè)例子可以看出一個(gè)Byte包含了一個(gè)字符的ASCII碼的二進(jìn)制部分及后續(xù)字符的二進(jìn)制部分的低位。這樣8個(gè)字符可以壓縮成為7個(gè)Byte,SMS中140Byte的TP-UD長(zhǎng)度就可以容納160個(gè)英文字母。

通過觀察可以看出,只要我們從后到前把所有的二進(jìn)制代碼拼接到一塊,就能夠方便的處理,上面例子通過拼接后得到:

00001110100111001111001011010100

我們可以直接通過從后往前的按7個(gè)一組的原則進(jìn)行截取在處理就可以得到解碼后的代碼。為了編程的方便,我設(shè)計(jì)了一個(gè)簡(jiǎn)單易懂的解碼過程,比起通過做乘除法來(lái)進(jìn)行運(yùn)算的簡(jiǎn)單,但最終效率不及它。但我想在普通場(chǎng)合應(yīng)用也綽綽有余了。

1、  Decode7Bit得到一個(gè)PDU的TP-UD部分

2、  InvertHexString反轉(zhuǎn)十六進(jìn)制代碼:例如123456=〉563412

3、  Binary字符串得到反轉(zhuǎn)后的十六進(jìn)制代碼的二進(jìn)制表示。注意這里依然使用字符串來(lái)表示二進(jìn)制,為了便于“拼接”和“切割”

4、  根據(jù)charCount所提供的字符數(shù)(來(lái)自TP_UDL)按7個(gè)一組從字符串位往前截取,并用Chr函數(shù)轉(zhuǎn)換成ASCII碼。

以下是一些函數(shù)的聲明部分,具體函數(shù)請(qǐng)參見Blog內(nèi)的PDUDecoder

         ‘Deoce a unicode string

         Shared Function DecodeUnicode(ByVal strUnicode As String) As String

         ‘Decode 7bit to English

Shared Function InvertHexString(ByVal HexString As String) As String

Shared Function ByteToBinary(ByVal Dec As Byte) As String

Shared Function BinaryToInt(ByVal Binary As String) As Integer

Shared Function Decode7Bit(ByVal str7BitCode As String, ByVal charCount As Integer) As String

 

SMS_SUBMIT、SMS_RECEIVED、SMS_STATUS_REPORT

由于SMS_RECEIVED、SMS_STATUS_REPORT與SMS_SUBMIT比較相似,所以我重點(diǎn)講講SMS_SUBMIT。

當(dāng)用SMSBase的GetSMSType確定一個(gè)PDUCode為SMS_SUBMIT時(shí),就可以聲明一個(gè)SMS_SUBMIT類的實(shí)例,通過傳遞此PDUCode作為構(gòu)造函數(shù)的參數(shù)。構(gòu)造函數(shù)立即調(diào)用GetOrignalData函數(shù)解碼。

參考協(xié)議知道SMS_SUBMIT比SMSBase多出以下部分:

Public TP_MR As Byte

Public DesAddressLength As Byte

Public DesAddressType As Byte

Public DesAddressValue As String

Public TP_VP As Byte

參考協(xié)議我們可以很方便的得到GetOrignalData函數(shù)的實(shí)現(xiàn):

    Public Overrides Sub GetOrignalData(ByVal PDUCode As String)

        SCAddressLength = GetByte(PDUCode)

        SCAddressType = GetByte(PDUCode)

        SCAddressValue = GetAddress((GetString(PDUCode, (SCAddressLength - 1) * 2)))

        FirstOctet = GetByte(PDUCode)

 

        TP_MR = GetByte(PDUCode)

 

        DesAddressLength = GetByte(PDUCode)

        DesAddressType = GetByte(PDUCode)

        DesAddressLength += DesAddressLength Mod 2

        DesAddressValue = GetAddress((GetString(PDUCode, DesAddressLength)))

 

        TP_PID = GetByte(PDUCode)

        TP_DCS = GetByte(PDUCode)

        TP_VP = GetByte(PDUCode)

        TP_UDL = GetByte(PDUCode)

        TP_UD = GetString(PDUCode, TP_UDL * 2)

End Sub

這就完成了整個(gè)解碼過程,通過SMSBase的巧妙設(shè)計(jì),此解碼過程顯得簡(jiǎn)單方便。

 

EMS_SUBMIT、EMS_RECEIVED

對(duì)于EMS(增強(qiáng)型短信),其基本結(jié)構(gòu)和SMS類似,主要的區(qū)別就是Information Element(IE)。所以EMS_SUBMIT繼承了SMS_SUBMIT,EMS_RECEIVED繼承了SMS_RECEIVED

參考3GPP協(xié)議EMS部分我們可以做出以下的結(jié)構(gòu)和定義

    Public Structure InfoElem       ‘See document “How to create EMS”

        Public Identifier As Byte

        Public Length As Byte

        Public Data As String

    End Structure

Public TP_UDHL As Byte

為了得到IE我寫了一個(gè)函數(shù):

    Shared Function GetIE(ByVal IECode As String) As InfoElem()

        Dim tmp As String = IECode, t As Integer = 0

        Dim result() As InfoElem

        Do Until IECode = “”

            ReDim Preserve result(t)

            With result(t)

                .Identifier = GetByte(IECode)

                .Length = GetByte(IECode)

                .Data = GetString(IECode, .Length * 2)

            End With

            t += 1

        Loop

        Return result

End Function

然后參考協(xié)議可以寫出GetOrignalData函數(shù)。具體就不再贅述。

 

PDUDecoder

這個(gè)類的由一個(gè)結(jié)構(gòu),一個(gè)重要的解碼函數(shù),組成。

結(jié)構(gòu)定義了需要取得的基本信息,可以視需要修改。我這里提供一個(gè)范例

Public Structure BaseInfo

Public SourceNumber As String

Public DestinationNumber As String

Public ReceivedDate As Date

Public Text As String

Public Type As SMS.Decoder.SMSBase.SMSType

Public EMSTotolPiece As Integer

Public EMSCurrentPiece As Integer

Public StatusFromReport As SMS_STATUS_REPORT.EnumStatus

Public DestinationReceivedDate

End Structure

解碼函數(shù)的聲明如下:

Public Shared Function Decode(ByVal PDUCode As String) As BaseInfo

內(nèi)部主要處理步驟如下(源代碼請(qǐng)參考PDUDecoder)

1.         根據(jù)SMSBase的GetSMSType函數(shù)得到短信類型SMSType

2.         根據(jù)SMSType生成對(duì)應(yīng)的類的實(shí)例

3.         解碼PDU,得到基本結(jié)構(gòu)

4.         通過基本結(jié)構(gòu)得到BaseInfo結(jié)構(gòu)里面需要的數(shù)據(jù)

5.         通過decode7bit或者decodeUnicode函數(shù)得到TP_UD數(shù)據(jù)

 

到此為止,這就是整個(gè)PDU Decoder的詳細(xì)介紹,具體使用可以參見Siemens Support Tool里面相關(guān)部分,在此不再贅述

PDU的編碼器的工作原理是解碼器的逆過程。根據(jù)需要編碼器只需要編碼發(fā)送的PDU代碼,工作相對(duì)簡(jiǎn)單。本文講解編碼思路,具體代碼請(qǐng)參考Blog中PDUEncoder部分

我把PDU的編碼分為兩部分,SMS和EMS。EMS部分我只提供了ConcatenatedShortMessage的編碼器。這是超長(zhǎng)短信的編碼,用得最多。

SMS編碼

編碼一個(gè)SMS一般需要如下的信息:

       TP_Data_Coding_Scheme     TP_UD編碼方式

              TP_Destination_Address       對(duì)方號(hào)碼

              TP_Message_Reference        參考號(hào)碼

              TP_Status_Report_Request   狀態(tài)報(bào)告

              TP_User_Data                            用戶信息

              TP_Validity_Priod                 有效期

              ServiceCenterNumber           短信中心號(hào)碼

       所以在編碼器中存在以上的屬性,并在Set中加入了處理代碼,將可讀信息轉(zhuǎn)換成對(duì)應(yīng)的十六進(jìn)制信息。

       特別注意的是TP_User_Data屬性,它可以根據(jù)用戶數(shù)據(jù)編碼自動(dòng)設(shè)置TP_UDL。對(duì)于純英文編碼,TP_UDL為所有的字符數(shù);對(duì)于Unicode編碼,由于一個(gè)字符由兩個(gè)字節(jié)表示,TP_UDL為所有的字符數(shù)*2。注意檢查TP_User_Data的長(zhǎng)度,對(duì)于SMS來(lái)說(shuō)編碼后的TP_UD長(zhǎng)度不能超過140字節(jié)。也就是說(shuō)英文160個(gè)字符(140/7*8),中文70個(gè)字符。

對(duì)于TP_UD的編碼在解碼器中也有說(shuō)明,在此不再贅述。

我還設(shè)計(jì)了幾個(gè)枚舉變量:

              ENUM_TP_DCS                         編碼方式

              ENUM_TP_SRI                          狀態(tài)報(bào)告

              ENUM_TP_VALID_PERIOD 有效期

              ENUM_TP_VPF                         有效期格式

       這些枚舉變量可以簡(jiǎn)化輸入,也利于日后擴(kuò)充。

       當(dāng)以上內(nèi)容設(shè)置好以后,基本上一個(gè)短信的架子就出來(lái)了。此時(shí)調(diào)用GetSMSPDUCode進(jìn)行組合,簡(jiǎn)單的把十六進(jìn)制拼接起來(lái)就形成了一個(gè)完整的PDU代碼。

EMS——ConcatenatedShortMessage部分

編碼EMS較SMS復(fù)雜,但每條EMS的基礎(chǔ)還是SMS,所以我直接繼承了SMS類。區(qū)別主要是要處理好TP_UD和IE。對(duì)于ConcatenatedShortMessage,由于其IE和TP_UDHL占據(jù)了TP_UD的部分空間,所以每條短信英文只能容納133字符,中文66字符。我們可以通過此信息得到短信條數(shù)。

如果TP_DCS為Unicode編碼,則短信條目為:
TotalMessages = (TP_UD.Length / 4) \ 66 + ((TP_UD.Length / 4 Mod 66) = 0)+1

如果為7bit,則為:

TotalMessages = (tp_ud.Length \ 266) - ((tp_ud.Length Mod 266) = 0)+1

注意在程序中我為了簡(jiǎn)化以后的數(shù)組操作,就沒有加一。

確定了短信條數(shù)以后通過一個(gè)循環(huán)就可以提取出每條短信的TP_UD。

Select Case tp_dcs

Case ENUM_TP_DCS.UCS2

tmpTP_UD = Mid(TP_UD, i * 66 * 4 + 1, 66 * 4)’When TP_UDL is odd, the max length of an Unicode string in PDU code is 66 Charactor.See [3GPP TS 23.040 V6.5.0 (2004-09] 9.2.3.24.1

Case ENUM_TP_DCS.DefaultAlphabet

tmpTP_UD = Mid(tp_ud, i * 133 * 2 + 1, 133 * 2)

End Select

此后還需要編碼IE部分,關(guān)鍵代碼是確定TP_UDL的值。對(duì)于TP_DCS為7bit來(lái)說(shuō)確定此值顯得比較復(fù)雜,弄不好容易出現(xiàn)多一個(gè)少一個(gè)的錯(cuò)誤。

If tp_dcs = ENUM_TP_DCS.UCS2 Then

TP_UDL = tmpTP_UD.Length / 2 + 6 + 1 ‘6: length of IE

End If

If tp_dcs = ENUM_TP_DCS.DefaultAlphabet Then

TP_UDL = Fix((tmpTP_UD.Length + 7 * 2) * 4 / 7)   ‘6:length of IE

End If

然后根據(jù)3GPP里關(guān)于EMS的結(jié)構(gòu)的說(shuō)明就可以編寫出EMS PDU的處理程序。詳見原代碼。

如果需要擴(kuò)展EMS以適應(yīng)更多種類的EMS,可以參考3GPP寫出更為強(qiáng)大的編碼程序。但最關(guān)鍵的還是需要處理好IE以及TP_UDL。

(十二)  短信部分——通過RS232發(fā)送和接收短信

通常,發(fā)送和接收短信的終端都是通過串行接口連接電腦,這類設(shè)備用得比較多的是GSM Modem和手機(jī)。這類設(shè)備通常都支持PDU模式,但仍有少數(shù)設(shè)備只支持Text模式。

設(shè)備硬件連接好以后可以通過發(fā)送AT指令測(cè)試設(shè)備是否連接正確能否正常通訊。在這里我使用Windows自帶的“超級(jí)終端”工具進(jìn)行通訊。此工具可以在程序——附件——通訊里面找到,如果沒有請(qǐng)確認(rèn)是否安裝了此組件?;蛘咴谶\(yùn)行里面輸入“hypertrm”也可以快速啟動(dòng)“超級(jí)終端”。

以下所有范例均以Siemens M55手機(jī)作為終端,有可能跟你設(shè)備返回的不同。具體參數(shù)清參閱設(shè)備相關(guān)AT指令集。本手機(jī)AT指令集在我主頁(yè)上有下載。

準(zhǔn)備工作:

1、  測(cè)試連接:“AT8 ”測(cè)試終端是否連接正確。成功后返回“OK”。

2、  設(shè)置回顯:(此步驟為了測(cè)試方便)ATE18

3、  查閱及設(shè)置字符集:
AT+CSCS=?8
+CSCS: (”GSM”,”UCS2″)
說(shuō)明該終端支持GSM與UCS2兩種字符集。一般對(duì)于中文環(huán)境設(shè)置為UCS2
AT+CSCS=”UCS2″8

4、  取得短信中心號(hào)碼:
AT+CSCA? 8
+CSCA: “+8613800280500″,145

5、  查詢并設(shè)置SMS格式:
查詢:AT+CMGF= 8
返回:+CMGF: (0)
0代表PDU模式。你的設(shè)備可能有其他的選項(xiàng),請(qǐng)參考設(shè)備的AT指令集。
設(shè)置:AT+CMGF=08

6、  查詢并設(shè)置短信儲(chǔ)存位置:
查詢:AT+CPMS=?8
返回:+CPMS: (”MT”,”SM”,”ME”),(”MT”,”SM”,”ME”),(”MT”,”SM”,”ME”)
       其中MT表示設(shè)備所有可用儲(chǔ)存位置。SM代表SIM卡,ME代表機(jī)身。
一般設(shè)置為:AT+CPMS= “MT”,”MT”,”MT”8

查詢短信:

1、  查詢具有相同狀態(tài)的所有短信
指令:AT+CMGL=n
其中n代表0-4的數(shù)字。
0——未讀得短信。執(zhí)行命令以后自行變?yōu)橐炎x取。
1——已讀短信。
2——草稿。
3——已發(fā)送短信。
4——全部
返回(例):
+CMGL: 76,3,,20

0891683108200805F011620D91683194041338F50000FF0530972D8603
76——序號(hào)

3——狀態(tài):發(fā)送

20——PDU串長(zhǎng)度

2、  查詢特定序號(hào)的短信
指令:AT+CMGR=n8
其中n代表序號(hào)
返回(例):
+CMGR: 3,,20
0891683108200805F011620D91683195041338F50000FF0530972D8603
3——狀態(tài):發(fā)送
20——PDU串長(zhǎng)度

注意:PDU串長(zhǎng)度表示PDU中除去短信中心部分剩下的代碼的長(zhǎng)度的1/2。例如上述PDU中PDU長(zhǎng)度部分為11620D91683195041338F50000FF0530972D8603,40個(gè)字符,表示20個(gè)字節(jié)。

 

儲(chǔ)存PDU
指令
AT+CMGW=[PDU長(zhǎng)度] 8
>[PDU串]
例如
AT+CMGW=208

> 0891683108200805F011620D91683195041338F50000FF0530972D8603
注意,輸入PDU后按“CTRL+Z”終止。程序中使用0×1A,0×1D作為終止。

返回:+CMGW: 85
85——序號(hào)

 

發(fā)送PDU

1、  發(fā)送輸入的PDU串
指令:
AT+CMGS=[PDU長(zhǎng)度] 8
>[PDU代碼]

2、  發(fā)送指定序號(hào)的PDU串
指令:
AT+CMSS=[序號(hào)] 8

 

接收短信

接收剛收到的短信有兩種方法:輪詢終端;使用事件

輪詢終端可以定期的使用AT+CMGL=0指令讀取未讀取得指令。方法簡(jiǎn)單,但許多時(shí)候都在做無(wú)用功,效率低下,一般不建議采用。下面主要講解事件法:

指令:
       AT+CNMI=,,,,

參數(shù):
mode

       0——緩存在終端

       1——直接發(fā)送到TE

mt

       0——接收到新的SMS不返回事件

       1——如果接收到的SMS存儲(chǔ)在ME,則返回
+CMTI:,

       2——除了Class2 SMS,新的SMS直接發(fā)送到終端,返回:
+CMT:

       3——Class3 SMS使用mt=2的方法返回,其他類型的使用mt=1的方法返回。

bm

       0——小區(qū)廣播不通知

       2——新的小區(qū)廣播通知,返回
+CBM:

       3——Class3格式的小區(qū)廣播通知,使用bm=2格式

ds

       0——狀態(tài)報(bào)告不通知

       1——新的狀態(tài)報(bào)告通知,返回:
+CDS:

       2——如果新的狀態(tài)報(bào)告存儲(chǔ)到ME,則返回:

              +CDSI:,

brf

       1——始終為1

例:

       一般我們使用AT+CNMI=1,1,0,2,1

當(dāng)收到新的短信時(shí)終端返回:

       +CMTI:ME,5

新的狀態(tài)報(bào)告:

       +CDSI:ME,6

程序可以通過判斷返回值并使用AT+CMGR指令返回新到短信

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
手機(jī)短信的PDU編碼和解碼
GSM短消息的解析
用AT命令發(fā)送PDU短信(轉(zhuǎn))
利用手機(jī)模塊實(shí)現(xiàn)短消息
短信開發(fā)基礎(chǔ)知識(shí)以及短信貓發(fā)短信wappush短信.
轉(zhuǎn):短消息調(diào)試筆記
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服