通過串列埠收發短訊息 下

2021-04-15 10:55:35 字數 4078 閱讀 3328

原文出處:http://www.kernelstudio.com/getitem.asp?id=14

q pdu的核心編碼方式已經清楚了,如何實現用at命令收發短訊息呢?

a 在上篇中,我們已經討論了7bit, 8bit和ucs2這幾種pdu使用者資訊的編碼方式,並且給出了實現**。現在,重點描述pdu全串的編碼和解碼過程,以及g** 07.05的at命令實現方法。這些是底層的核心**,為了保證**的可移植性,我們盡可能不用mfc的類,必要時用ansi c標準庫函式。

首先,定義如下常量和結構:

// 使用者資訊編碼方式

#define g**_7bit        0

#define g**_8bit        4

#define g**_ucs2        8

// 短訊息引數結構,編碼/解碼共用

// 其中,字串以''/0''結尾

typedef struct **_param;

大家已經注意到pdu串中的號碼和時間,都是兩兩顛倒的字串。利用下面兩個函式可進行正反變換: // 正常順序的字串轉換為兩兩顛倒的字串,若長度為奇數,補''f''湊成偶數

// 如:"8613851872468" --> "683158812764f8"

// psrc: 源字串指標

// pdst: 目標字串指標

// nsrclength: 源字串長度

// 返回: 目標字串長度

int g**invertnumbers(const char* psrc, char* pdst, int nsrclength)

// 源串長度是奇數嗎?

if (nsrclength & 1)

// 輸出字串加個結束符

*pdst = ''/0'';

// 返回目標字串長度

return ndstlength;

}// 兩兩顛倒的字串轉換為正常順序的字串

// 如:"683158812764f8" --> "8613851872468"

// psrc: 源字串指標

// pdst: 目標字串指標

// nsrclength: 源字串長度

// 返回: 目標字串長度

int g**serializenumbers(const char* psrc, char* pdst, int nsrclength)

// 最後的字元是''f''嗎?

if (*(pdst-1) == ''f'')

// 輸出字串加個結束符

*pdst = ''/0'';

// 返回目標字串長度

return ndstlength;

}以下是pdu全串的編譯碼模組。為簡化程式設計,有些欄位用了固定值。 // pdu編碼,用於編制、傳送短訊息

// psrc: 源pdu引數指標

// pdst: 目標pdu串指標

// 返回: 目標pdu串長度

int g**encodepdu(const **_param* psrc, char* pdst)

else if (psrc->tp_dcs == g**_ucs2)

else

ndstlength += g**bytes2string(buf, &pdst[ndstlength], nlength);        // 轉換該段資料到目標pdu串

// 返回目標字串長度

return ndstlength;

}// pdu解碼,用於接收、閱讀短訊息

// psrc: 源pdu串指標

// pdst: 目標pdu引數指標

// 返回: 使用者資訊串長度

int g**decodepdu(const char* psrc, **_param* pdst)

// tpdu段協議標識、編碼方式、使用者資訊等

g**string2bytes(psrc, (unsigned char*)&pdst->tp_pid, 2);    // 取協議標識(tp-pid)

psrc += 2;        // 指標後移

g**string2bytes(psrc, (unsigned char*)&pdst->tp_dcs, 2);    // 取編碼方式(tp-dcs)

psrc += 2;        // 指標後移

g**serializenumbers(psrc, pdst->tp_scts, 14);        // 服務時間戳字串(tp_scts)

psrc += 14;       // 指標後移

g**string2bytes(psrc, &tmp, 2);    // 使用者首席資訊官度(tp-udl)

psrc += 2;        // 指標後移

if (pdst->tp_dcs == g**_7bit)

else if (pdst->tp_dcs == g**_ucs2)

else

// 返回目標字串長度

return ndstlength;

}依照g** 07.05,傳送短訊息用at+cmgs命令,閱讀短訊息用at+cmgr命令,列出短訊息用at+cmgl命令,刪除短訊息用at+cmgd命令。但at+cmgl命令能夠讀出所有的短訊息,所以我們用它實現閱讀短訊息功能,而沒用at+cmgr。下面是傳送、讀取和刪除短訊息的實現**: // 傳送短訊息

// psrc: 源pdu引數指標

bool g**sendmessage(const **_param* psrc)

}return false;

}// 讀取短訊息

// 用+cmgl代替+cmgr,可一次性讀出全部短訊息

// pmsg: 短訊息緩衝區,必須足夠大

// 返回: 短訊息條數

int g**readmessage(**_param* pmsg)

}return nmsg;

}// 刪除短訊息

// index: 短訊息序號,從1開始

bool g**deletemessage(int index)

return false;

}q 在用at命令同手機通訊時,需要注意哪些問題?

a 任何乙個at命令發給手機,都可能返回成功或失敗。例如,用at+cmgs命令傳送短訊息時,如果此時正好手機處於振鈴或通話狀態,就會返回乙個"+cms error"。所以,應當在傳送命令後,檢測手機的響應,失敗後重發。而且,因為只有乙個通訊埠,傳送和接收不可能同時進行。

如果串列埠通訊用超時控制的同步(阻塞)模式,一般做法是專門將傳送/接收處理封裝在乙個工作子執行緒內。因為**較多,這裡就不詳細介紹了。所附的demo中,包含了完整的子執行緒和傳送/接收應用程式介面的原始碼。

q 以上at命令,是不是所有廠家的手機都支援?

a etsi g** 07.05規範直到2023年才形成最終release版本(ver 7.0.1),在這之前及之後一段時間內,不排除各廠商在dte-dce的短訊息at命令有所不同的可能性。我們用到的幾個pdu模式下的at命令,是基本的命令,從原則上講,各廠家的手機以及g**模組應該都支援,但可能有細微差別。

q 使用者資訊(tp-ud)內除了一般意義上的短訊息,還可以是和聲音資料。關於手機鈴聲和格式方面,有什麼規範嗎?

a 為統一手機鈴聲、格式,motorola和ericsson, siemens, alcatel等共同開發了ems(enhanced messaging service)標準,並於2023年2月份公布。這些廠商格式相同。但另一手機巨頭nokia未參加標準的制定,手機鈴聲、格式與它們不同。所以沒有形成統一的規範。ems其實並沒有超越g** 07.05,只是tp-ud資料部分包含一定格式而已。各廠家的手機鈴聲、格式資料,可以查閱相關**。

q 使用者資訊(tp-ud)其實可以是任何的自定義資料,是嗎?

a 是的,儘管手機上會顯示亂碼。這種情況下,編碼方式已經沒有任何意義。但注意仍然要遵守規範。比如,若指定7-bit編碼方式,tp-udl應等於實際資料長度的8/7(用進一法,而不是四捨五入)。在利用**s進行點對點或多點對一點的資料通訊的應用中,可以傳輸各種自定義資料,如gps資訊,環境監測資訊,加密的個人資訊,等等。

如果在傳輸自定義資料的同時還要收發普通短訊息,最簡單的辦法是在資料前面額外加個識別標誌,比如"ffff",以區分自定義資料和普通短訊息。

通過串列埠收發短訊息 下

qpdu的核心編碼方式已經清楚了,如何實現用at命令收發短訊息呢?a在上篇中,我們已經討論了7 bit,8bit和ucs2這幾種pdu使用者資訊的編碼方式,並且給出了實現 現在,重點描述pdu全串的編碼和解碼過程,以及g 07.05的at命令實現方法。這些是底層的核心 為了保證 的可移植性,我們盡可...

通過串列埠收發短訊息 下

q pdu的核心編碼方式已經清楚了,如何實現用at命令收發短訊息呢?a 在上篇中,我們已經討論了7bit,8bit和ucs2這幾種pdu使用者資訊的編碼方式,並且給出了實現 現在,重點描述pdu全串的編碼和解碼過程,以及gsm 07.05的at命令實現方法。這些是底層的核心 為了保證 的可移植性,我...

通過串列埠收發短訊息 下

q pdu的核心編碼方式已經清楚了,如何實現用at命令收發短訊息呢?a 在上篇中,我們已經討論了7bit,8bit和ucs2這幾種pdu使用者資訊的編碼方式,並且給出了實現 現在,重點描述pdu全串的編碼和解碼過程,以及gsm 07.05的at命令實現方法。這些是底層的核心 為了保證 的可移植性,我...