短消息Text编码原码(下载至PJ Naughter的主页)
pdu编码示例:
//message中的位的设置可以参考文档中的说明
//红色的字表示可能与mfcsms中不同的地方
CString CSMSMessage::CreatePDUMessage() const
{
CByteArray message;
//message.SetSize(0, 280);
//First thing to do is work on the Service Center Number
if (!AddEncodedSMSCNumber(message, m_sServiceCenterNumber, m_ServiceCenterNumberAddressType))
return _T("");
//Form the SMS-SUBMIT octet
BYTE bySMSSubmit = 0x1; //By default set this PDU to an SMS-SUBMIT
if (m_bUseValidityPeriod)
{
if (m_bUseRelativeValidityPeriod)
bySMSSubmit |= 0x10;
else
bySMSSubmit |= 0x18;
}
if (m_bRequireStatusReport)
bySMSSubmit |= 0x20;
message.Add(bySMSSubmit);
//Next is the TP-Message-Reference. We let the phone set the message reference itself
message.Add(0x0);
//Next is the Phone number
ASSERT(m_sPhoneNumber.GetLength()); //Must specify a number to deliver the message to
if (!AddEncodedPhoneNumber(message, m_sPhoneNumber, m_PhoneNumberAddressType))
return _T("");
//Next is the Protocol Identifier
message.Add(0x0);
//Next is the Data encoding scheme (this code always use PDU encoding)
message.Add(0x8);
//Next is the validity period
if (m_bUseValidityPeriod)
{
if (m_bUseRelativeValidityPeriod)
{
//Relative Validity period is pseudo logarithmitly encoded into 1 octet
BYTE byValidityPeriod = 0;
if (m_RelativeValidityPeriod <= CTimeSpan(0, 12, 0, 0))
byValidityPeriod = (BYTE) ((m_RelativeValidityPeriod.GetTotalSeconds() / 300) - 1);
else if (m_RelativeValidityPeriod <= CTimeSpan(1, 0, 0, 0))
byValidityPeriod = (BYTE) (((m_RelativeValidityPeriod.GetTotalSeconds() - 43200) / 1800) + 143);
else if (m_RelativeValidityPeriod <= CTimeSpan(30, 0, 0, 0))
byValidityPeriod = (BYTE) ((m_RelativeValidityPeriod.GetTotalSeconds() / 86400) + 166);
else
byValidityPeriod = (BYTE) ((m_RelativeValidityPeriod.GetTotalSeconds() / 604800) + 192);
message.Add(byValidityPeriod);
}
else
{
//Absolute Validity period is encoded into 7 octets
message.Add(SwappedNibble(m_AbsoluteValidityPeriod.wYear % 100));
message.Add(SwappedNibble(m_AbsoluteValidityPeriod.wMonth));
message.Add(SwappedNibble(m_AbsoluteValidityPeriod.wDay));
message.Add(SwappedNibble(m_AbsoluteValidityPeriod.wHour));
message.Add(SwappedNibble(m_AbsoluteValidityPeriod.wMinute));
message.Add(SwappedNibble(m_AbsoluteValidityPeriod.wSecond));
long nLocalTimeZone = labs(m_TimeZone);
BYTE byTimeZone = SwappedNibble(nLocalTimeZone / 15);
if (m_TimeZone < 0)
byTimeZone |= 0x80;
message.Add(byTimeZone);
}
}
//Next is the length of the user data
int nMessageLength = m_sMessage.GetLength();
int nActualLen=0;
for(int j=0;j<nMessageLength;j++)
{
BYTE data=(BYTE)m_sMessage.GetAt(j);
int nNibble = (int)data;
if(nNibble>=0&&nNibble<=127)
nActualLen=nActualLen+2;
else
nActualLen=nActualLen+1;
}
if (nMessageLength > 255)
{
TRACE(_T("CSMSMessage::CreatePDUMessage, Cannot encode %s as it is longer than the maximum size of 255\n"), m_sMessage);
return _T("");
}
if (nMessageLength == 0)
{
TRACE(_T("CSMSMessage::CreatePDUMessage, Failing as no message has been specified to be sent\n"));
return _T("");
}
//Initially we just add a place holder as it will be updated later on once we have added the actual data
int nDataLengthIndex = message.GetSize();
message.Add((BYTE) nActualLen);
//Finally before we return from the function, convert from the BYTE array representation to the string version
WCHAR wcBuffer[256];
char cBuffer[256];
memset(cBuffer,0,256);
memset(wcBuffer,0,256*2);
MultiByteToWideChar(CP_ACP, 0, m_sMessage, nMessageLength, wcBuffer, 256);
memcpy((void*)cBuffer,(void*)wcBuffer,256);
char tmp;
for(int k =0; k<nMessageLength; k++)
{
tmp = cBuffer[2*k];
cBuffer[2*k] = cBuffer[2*k+1];
cBuffer[2*k+1]=tmp;
}
for(k=0;k<nActualLen;k++)
message.Add(cBuffer[k]);
int nArraySize = message.GetSize();
CString sMsg;
int nBufferSize = (nArraySize*2) + 1;
TCHAR* pszData = sMsg.GetBuffer(nBufferSize);
int nPDUOutputIndex = 0;
for (int i=0; i<nArraySize; i++)
{
BYTE byData = message.GetAt(i);
int nNibble1 = (byData & 0xF0) >> 4;
if (nNibble1 > 9)
pszData[nPDUOutputIndex] = (TCHAR) (nNibble1 - 10 + _T('A'));
else
pszData[nPDUOutputIndex] = (TCHAR) (nNibble1 + _T('0'));
++nPDUOutputIndex;
int nNibble2 = byData & 0xF;
if (nNibble2 > 9)
pszData[nPDUOutputIndex] = (TCHAR) (nNibble2 - 10 + _T('A'));
else
pszData[nPDUOutputIndex] = (TCHAR) (nNibble2 + _T('0'));
++nPDUOutputIndex;
}
sMsg.ReleaseBuffer(nPDUOutputIndex);
return sMsg;
}
使用at指令发送端消息示例:
//Check to see if there is a modem on the specified serial port
char* pszATMsg = "AT\r";//测试连接是否成功
Write(pszATMsg, strlen(pszATMsg));
if (!WaitForSerialResponse("OK", dwTimeout, 32))
{
CString sError;
sError.LoadString(IDS_SMSSERIALPORT_FAIL_RECEIVE_RESPONSE_FROM_MODEM);
AfxThrowSMSException(sError, E_SMS_NO_MODEM_RESPONSE);
}
char* pszSelectMessageMsg = "AT+CSMS=0\r"; //Select Message service
Write(pszSelectMessageMsg, strlen(pszSelectMessageMsg));
if (!WaitForSerialResponse("OK", dwTimeout, 32))
{
CString sError;
sError.LoadString(IDS_SMSSERIALPORT_MODEM_DOES_NOT_SUPPORT_SMS);
AfxThrowSMSException(sError, E_SMS_NO_SMS_SUPPORT);
}
char* pszMessageFormat = "AT+CMGF=0\r"; //Set the transfer mode to PDU
Write(pszMessageFormat, strlen(pszMessageFormat));
if (!WaitForSerialResponse("OK", dwTimeout, 32))
{
CString sError;
sError.LoadString(IDS_SMSSERIALPORT_FAIL_SET_PDU_MODE);
AfxThrowSMSException(sError, E_SMS_SET_PDU_MODE);
}
CString sSendCommand;
sSendCommand.Format(_T("AT+CMGS=%d\r"), nMsgSize); //Prepare to send the PDU
LPSTR pszAsciiSendCommand = T2A((LPTSTR) (LPCTSTR) sSendCommand);
Write(pszAsciiSendCommand, strlen(pszAsciiSendCommand));
if (!WaitForSerialResponse(">", dwTimeout, 32))
{
CString sError;
sError.LoadString(IDS_SMSSERIALPORT_FAIL_SEND_SMS_MESSAGE_TO_MODEM);
AfxThrowSMSException(sError, E_SMS_SEND_MESSAGE_TO_MODEM);
}
//And finally write out the PDU as a string
LPSTR pszAsciiPDU = T2A((LPTSTR) (LPCTSTR) sData);
int nAsciiPDULength = strlen(pszAsciiPDU);
Write(pszAsciiPDU, nAsciiPDULength);//pszAsciiPDU是短消息的PDU编码
Write("\x1A", 1);
if (!WaitForSerialResponse("OK", dwTimeout, 32 + nAsciiPDULength))
{
CString sError;
sError.LoadString(IDS_SMSSERIALPORT_FAIL_SEND_SMS_MESSAGE);
AfxThrowSMSException(sError, E_SMS_SEND_MESSAGE);
}