qpdu的核心編碼方式已經清楚了,如何實現用at命令收發短訊息呢?
a在上篇中,我們已經討論了7-bit, 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;
// 正常順序的字串轉換為兩兩顛倒的字串,若長度為奇數,補'f'湊成偶數依照g** 07.05,傳送短訊息用at+cmgs命令,閱讀短訊息用at+cmgr命令,列出短訊息用at+cmgl命令,刪除短訊息用at+cmgd命令。但at+cmgl命令能夠讀出所有的短訊息,所以我們用它實現閱讀短訊息功能,而沒用at+cmgr。下面是傳送、讀取和刪除短訊息的實現**:// 如:"8613851872468" --> "683158812764f8"
// psrc: 源字串指標
// pdst: 目標字串指標
// nsrclength: 源字串長度
// 返回: 目標字串長度
int g**invertnumbers(const char* psrc, char* pdst, int nsrclength)
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;
}
// 傳送短訊息以上傳送at命令過程中用到了writecomm和readcomm函式,它們是用來讀寫串列埠的,依賴於具體的作業系統。在windows環境下,除了用mscomm控制項,以及某些現成的串列埠通訊類之外,也可以簡單地呼叫一些windows api用實現。以下是利用api實現的主要**,注意我們用的是超時控制的同步(阻塞)模式。// 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(const int index)
return false;
}
// 串列埠裝置控制代碼q在用at命令同手機通訊時,需要注意哪些問題?handle hcomm;
// 開啟串列埠
// pport: 串列埠名稱或裝置路徑,可用"com1"或"//./com1"兩種方式,建議用後者
// nbaudrate: 波特率
// nparity: 奇偶校驗
// nbytesize: 資料位元組寬度
// nstopbits: 停止位
bool opencomm(const char* pport, int nbaudrate, int nparity, int nbytesize, int nstopbits)
// 關閉串列埠
bool closecomm()
// 寫串列埠
// pdata: 待寫的資料緩衝區指標
// nlength: 待寫的資料長度
void writecomm(void* pdata, int nlength)
// 讀串列埠
// pdata: 待讀的資料緩衝區指標
// nlength: 待讀的最大資料長度
// 返回: 實際讀入的資料長度
int readcomm(void* pdata, int nlength)
a任何乙個at命令發給手機,都可能返回成功或失敗。例如,用at+cmgs命令傳送短訊息時,如果此時正好手機處於振鈴或通話狀態,就會返回乙個"+cms error"。所以,應當在傳送命令後,檢測手機的響應,失敗後重發。而且,因為只有乙個通訊埠,傳送和接收不可能同時進行。
如果串列埠通訊用超時控制的同步(阻塞)模式,一般做法是專門將傳送/接收處理封裝在乙個工作子執行緒內。因為**較多,這裡就不詳細介紹了。所附的demo中,包含了完整的子執行緒和傳送/接收應用程式介面的原始碼。
q以上at命令,是不是所有廠家的手機都支援?
aetsi 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",以區分自定義資料和普通短訊息。
[相關資源]
◆ 本文demo原始碼:**stest.zip (31 kb)
◆ etsi官方**:http://www.etsi.org/
◆ bhw98的專欄:http://www.csdn.net/develop/author/netauthor/bhw98/
通過串列埠收發短訊息 下
原文出處 http www.kernelstudio.com getitem.asp?id 14 q pdu的核心編碼方式已經清楚了,如何實現用at命令收發短訊息呢?a 在上篇中,我們已經討論了7bit,8bit和ucs2這幾種pdu使用者資訊的編碼方式,並且給出了實現 現在,重點描述pdu全串的編...
通過串列埠收發短訊息 下
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命令實現方法。這些是底層的核心 為了保證 的可移植性,我...