typedef struct {
char SCA[16]; // 簡訊中心號碼
char TPA[16]; // 目標/回覆號碼
char TP_PID; // 協定識別碼
char TP_DCS; // 編碼方式 (7bit/8bit/UCS2)
char TP_SCTS[16]; // 服務時間戳
char TP_UD[161]; // 用戶資料 (編碼前/解碼後)
char index; // 簡訊索引
} SM_PARAM;
PDU 中號碼與時間皆為「兩兩交換」且奇數長度補 'F'。提供 gsmInvertNumbers (正序→反序) 與 gsmSerializeNumbers (反序→正序) 兩工具函式。
gsmEncodePdu0x11 (SUBMIT, VP相對格式) + MR=0 + 目標號碼長度 + TON/NPI + 反序目標號碼TP_DCS 呼叫 gsmEncode7bit/8bit/UCS2 處理用戶資料gsmDecodePdugsmDecode7bit/8bit/UCS2 還原用戶資料gsmSendMessageBOOL gsmSendMessage(const SM_PARAM* p) {
char pdu[512]; int len = gsmEncodePdu(p, pdu);
strcat(pdu, "\x1A"); // Ctrl-Z 結束
// 計算不含 SMSC 的 PDU 位元組數
BYTE smscLen; gsmString2Bytes(pdu, &smscLen, 2); smscLen++;
char cmd[32]; sprintf(cmd, "AT+CMGS=%d ", len/2 - smscLen);
WriteComm(cmd, strlen(cmd));
ReadComm(ans, 128); // 等待 "> "
if(strncmp(ans, ">", 1)!=0) return FALSE;
WriteComm(pdu, strlen(pdu));
ReadComm(ans, 128);
return (strncmp(ans, "+CMS ERROR", 10)!=0);
}
gsmReadMessage (用 CMGL 替代 CMGR)int gsmReadMessage(SM_PARAM* buf) {
WriteComm("AT+CMGL ", 8);
ReadComm(ans, 1024);
if(strstr(ans, "+CMS ERROR")) return 0;
int cnt=0; char* p=strstr(ans, "+CMGL:");
while(p) {
p+=6; sscanf(p, "%d", &buf->index);
p=strstr(p, "\n"); p+=2; // 跳到 PDU 行
gsmDecodePdu(p, buf);
buf++; cnt++;
p=strstr(p, "+CMGL:");
}
return cnt;
}
gsmDeleteMessageBOOL gsmDeleteMessage(int index) {
char cmd[16]; sprintf(cmd, "AT+CMGD=%d ", index);
WriteComm(cmd, strlen(cmd));
ReadComm(ans, 128);
return (strncmp(ans, "+CMS ERROR", 10)!=0);
}
HANDLE hComm;
BOOL OpenComm(LPCSTR port, int baud, int parity, int byteSize, int stopBits) {
hComm = CreateFile(port, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if(hComm==INVALID_HANDLE_VALUE) return FALSE;
DCB dcb = {0}; dcb.DCBlength=sizeof(DCB);
GetCommState(hComm, &dcb);
dcb.BaudRate=baud; dcb.Parity=parity; dcb.ByteSize=byteSize; dcb.StopBits=stopBits;
SetCommState(hComm, &dcb);
COMMTIMEOUTS to = {100, 100, 0, 100, 0}; // 讀寫逾時
SetCommTimeouts(hComm, &to);
return TRUE;
}
int WriteComm(const void* buf, int len) { DWORD w; WriteFile(hComm, buf, len, &w, NULL); return w; }
int ReadComm(void* buf, int max) { DWORD r; ReadFile(hComm, buf, max, &r, NULL); return r; }
void CloseComm() { if(hComm!=INVALID_HANDLE_VALUE) CloseHandle(hComm); }
核心編解碼僅用 ANSI C,無 MFC 相依;序列埠層可替換為 Linux termios 或嵌入式 UART 驅動,極易移植。