原文出處: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命令實現方法。這些是底層的核心 為了保證 的可移植性,我...