C language code for SMS messages

Source: Internet
Author: User
Tags sca

2 message sending
// User information encoding method
# Define gsm_7bit 0
# Define gsm_8bit 4
# Define gsm_ucs2 8

// Short Message Parameter structure, shared encoding/Decoding
// The string ends with 0.
Typedef struct {
Char SCA [16]; // Short Message Service Center number (SMSC address)
Char TPA [16]; // target number or reply number (TP-DA or TP-RA)
Char tp_pid; // User Information Protocol identifier (TP-PID)
Char tp_dcs; // user information encoding method (TP-DCS)
Char tp_scts [16]; // service timestamp string (tp_scts), used for receiving
Char tp_ud [161]; // original user information (TP-UD before or after decoding)
Char index; // Short Message serial number, used for reading
} Sm_param;

We have noticed that the numbers and times in the PDU string are both reversed strings. The following two functions can be used for positive and negative transformation:

// Convert a string in normal order to a string that is reversed by two. If the length is an odd number, fill in 'f' to make it an even number.
// For example, "8613851872468" --> "6831588000064f8"
// Psrc: Source string pointer
// Pdst: Target string pointer
// Nsclength: Source String Length
// Return: the length of the target string.
Int gsminvertnumbers (const char * psrc, char * pdst, int nsclength)
{
Int ndstlength; // The length of the target string.
Char ch; // used to save a character

// Copy the string length
Ndstlength = nsclength;

// Reversing
For (INT I = 0; I <nsclength; I + = 2)
{
Ch = * psrc ++; // Save the first character
* Pdst ++ = * psrc ++; // the character that appears after the copy
* Pdst ++ = CH; // copy the first character
}

// Is the source String Length odd?
If (nsclength & 1)
{
* (PDst-2) = 'F'; // fill in 'F'
Ndstlength ++; // The length of the target string plus 1
}

// Add an ending character to the output string
* Pdst = '\ 0 ';

// Returns the length of the target string.
Return ndstlength;
}

// Convert the string to a string in normal order.
// For example, "683158842564f8" --> "8613851872468"
// Psrc: Source string pointer
// Pdst: Target string pointer
// Nsclength: Source String Length
// Return: the length of the target string.
Int gsmserializenumbers (const char * psrc, char * pdst, int nsclength)
{
Int ndstlength; // The length of the target string.
Char ch; // used to save a character

// Copy the string length
Ndstlength = nsclength;

// Reversing
For (INT I = 0; I <nsclength; I + = 2)
{
Ch = * psrc ++; // Save the first character
* Pdst ++ = * psrc ++; // the character that appears after the copy
* Pdst ++ = CH; // copy the first character
}

// Is the final character 'F?
If (* (pDst-1) = 'F ')
{
Pdst --;
Ndstlength --; // The length of the target string minus 1.
}

// Add an ending character to the output string
* Pdst = '\ 0 ';

// Returns the length of the target string.
Return ndstlength;
}

The following is a complete PDU Codec Module. To simplify programming, some fields use fixed values.

// PDU encoding, used to compile and send Short Messages
// Psrc: Source PDU parameter pointer
// Pdst: Target PDU string pointer
// Return: Target PDU String Length
Int gsmencodepdu (const sm_param * psrc, char * pdst)
{
Int nlength; // internal String Length
Int ndstlength; // The length of the target PDU string.
Unsigned char Buf [256]; // internal buffer

// SMSC address segment
Nlength = strlen (psrc-> SCA); // length of the SMSC address string
Buf [0] = (char) (nlength & 1) = 0? Nlength: nlength + 1)/2 + 1; // length of SMSC address information
Buf [1] = 0x91; // fixed: Number in international format
Ndstlength = gsmbytes2string (BUF, pdst, 2); // convert two bytes to the target PDU string
Ndstlength + = gsminvertnumbers (psrc-> SCA, & pdst [ndstlength], nlength );//
Convert SMSC to target PDU string

// Basic parameters and target addresses of the tpdu segment
Nlength = strlen (psrc-> TPA); // The length of the TP-DA address string
Buf [0] = 0x11; // is to send the SMS (TP-MTI = 01), TP-VP in relative format (TP-VPF = 10)
Buf [1] = 0; // TP-MR = 0
Buf [2] = (char) nlength; // number of destination address numbers (actual length of the TP-DA address string)
Buf [3] = 0x91; // fixed: Number in international format
Ndstlength + = gsmbytes2string (BUF, & pdst [ndstlength], 4); // converts four bytes to the target PDU string
Ndstlength + = gsminvertnumbers (psrc-> TPA, & pdst [ndstlength], nlength );//
Convert TP-DA to target PDU string

// Tpdu segment protocol identifier, encoding method, user information, etc.
Nlength = strlen (psrc-> tp_ud); // The length of the user information string
Buf [0] = psrc-> tp_pid; // protocol identifier (TP-PID)
Buf [1] = psrc-> tp_dcs; // user information encoding method (TP-DCS)
Buf [2] = 0; // validity period (TP-VP) is 5 minutes
If (psrc-> tp_dcs = gsm_7bit)
{
// 7-bit encoding
Buf [3] = nlength; // pre-encoding Length
Nlength = gsmencode7bit (psrc-> tp_ud, & Buf [4], nlength + 1) + 4 ;//
Convert TP-DA to target PDU string
}
Else if (psrc-> tp_dcs = gsm_ucs2)
{
// Ucs2 encoding method
Buf [3] = gsmencodeucs2 (psrc-> tp_ud, & Buf [4], nlength );//
Convert TP-DA to target PDU string
Nlength = Buf [3] + 4; // nlength is equal to the length of the Data Segment.
}
Else
{
// 8-bit encoding
Buf [3] = gsmencode8bit (psrc-> tp_ud, & Buf [4], nlength );//
Convert TP-DA to target PDU string
Nlength = Buf [3] + 4; // nlength is equal to the length of the Data Segment.
}
Ndstlength + = gsmbytes2string (BUF, & pdst [ndstlength], nlength );//
Convert the data segment to the target PDU string

// Returns the length of the target string.
Return ndstlength;
}

// PDU Decoding for receiving and reading Short Messages
// Psrc: Source PDU string pointer
// Pdst: Target PDU parameter pointer
// Return: User Information String Length
Int gsmdecodepdu (const char * psrc, sm_param * pdst)
{
Int ndstlength; // The length of the target PDU string.
Unsigned char TMP; // temporary BYTE variable used internally
Unsigned char Buf [256]; // internal buffer

// SMSC address segment
Gsmstring2bytes (psrc, & TMP, 2); // get the length
TMP = (TMP-1) * 2; // SMSC number String Length
Psrc + = 4; // pointer move back
Gsmserializenumbers (psrc, pdst-> SCA, TMP); // convert the SMSC number to the target PDU string
Psrc + = TMP; // pointer move back

// Basic parameters and reply addresses of tpdu segments
Gsmstring2bytes (psrc, & TMP, 2); // obtain the basic parameters
Psrc + = 2; // pointer move back
If (TMP & 0x80)
{
// Contains the reply address and obtains the reply address information.
Gsmstring2bytes (psrc, & TMP, 2); // get the length
If (TMP & 1) TMP + = 1; // adjust parity
Psrc + = 4; // pointer move back
Gsmserializenumbers (psrc, pdst-> TPA, TMP); // get the TP-RA number
Psrc + = TMP; // pointer move back
}

// Tpdu segment protocol identifier, encoding method, user information, etc.
Gsmstring2bytes (psrc, (unsigned char *) & pdst-> tp_pid, 2); // retrieve protocol identifier (TP-PID)
Psrc + = 2; // pointer move back
Gsmstring2bytes (psrc, (unsigned char *) & pdst-> tp_dcs, 2); // get the encoding method (TP-DCS)
Psrc + = 2; // pointer move back
Gsmserializenumbers (psrc, pdst-> tp_scts, 14); // service timestamp string (tp_scts)

Psrc + = 14; // pointer move back
Gsmstring2bytes (psrc, & TMP, 2); // user information length (TP-UDL)
Psrc + = 2; // pointer move back
If (pdst-> tp_dcs = gsm_7bit)
{
// 7-bit Decoding
Ndstlength = gsmstring2bytes (psrc, Buf, TMP & 7? (INT) TMP * 7/4 + 2: (INT) TMP * 7/4 );//
Format Conversion
Gsmdecode7bit (BUF, pdst-> tp_ud, ndstlength); // converts to TP-DU
Ndstlength = TMP;
}
Else if (pdst-> tp_dcs = gsm_ucs2)
{
// Ucs2 Decoding
Ndstlength = gsmstring2bytes (psrc, Buf, TMP * 2 );//
Format Conversion
Ndstlength = gsmdecodeucs2 (BUF, pdst-> tp_ud, ndstlength );//
Convert to TP-DU
}
Else
{
// 8-bit Decoding
Ndstlength = gsmstring2bytes (psrc, Buf, TMP * 2 );//
Format Conversion
Ndstlength = gsmdecode8bit (BUF, pdst-> tp_ud, ndstlength );//
Convert to TP-DU
}

// Returns the length of the target string.
Return ndstlength;
}

According to GSM 07.05, The at + cmgs command is used to send short messages, the at + cmgr command is used to read short messages, the at + cmgl command is used to list short messages, and the at + cmgd command is used to delete short messages. However, the at + cmgl command can read all short messages, so we use it to read short messages, instead of at + cmgr. The following code sends, reads, and deletes short messages:

// Send Short Message
// Psrc: Source PDU parameter pointer
Bool gsmsendmessage (const sm_param * psrc)
{
Int npdulength; // PDU String Length
Unsigned char nsmsclength; // SMSC String Length
Int nlength; // The length of data received by the serial port
Char cmd [16]; // command string
Char PDU [512]; //
PDU string
Char ans [128]; // response string

Npdulength = gsmencodepdu (psrc, PDU );//
Encode the PDU string according to the PDU Parameter
Strcat (PDU, "\ x01a ");//
End with Ctrl-z

Gsmstring2bytes (PDU, & nsmsclength, 2 );//
Obtains the length of SMSC information in a PDU string.
Nsmsclength ++; // Add the Length Byte itself

// The length in the command, excluding the length of SMSC information, measured in bytes
Sprintf (CMD, "At + cmgs = % d \ r", npdulength/2-nsmsclength );//
Generate command

Writecomm (CMD, strlen (CMD); // output the command string first

Nlength = readcomm (ANS, 128); // read response data

// Determine whether a success is successful based on whether "\ r \ n>" can be found.
If (nlength = 4 & strncmp (ANS, "\ r \ n>", 4) = 0)
{
Writecomm (PDU, strlen (PDU ));//
Get a positive answer and continue to output the PDU string

Nlength = readcomm (ANS, 128); // read response data

// Determine whether the task is successful based on whether the "+ CMS error" can be found.
If (nlength> 0 & strncmp (ANS, "+ CMS error", 10 )! = 0)
{
Return true;
}
}

Return false;
}

// Read short messages
// Replace + cmgl with + cmgr to read all short messages at a time
// PMSG: Short Message Buffer, which must be large enough
// Return: Number of Short Messages
Int gsmreadmessage (sm_param * PMSG)
{
Int nlength; // The length of data received by the serial port
Int nmsg; // Short Message count value
Char * PTR; // Internal Data Pointer
Char cmd [16]; // command string
Char ans [1024]; // response string

Nmsg = 0;
PTR = ans;

Sprintf (CMD, "At + cmgl \ r"); // generate a command

Writecomm (CMD, strlen (CMD); // output command string
Nlength = readcomm (ANS, 1024); // read response data
// Determine whether the task is successful based on whether the "+ CMS error" can be found.
If (nlength> 0 & strncmp (ANS, "+ CMS error", 10 )! = 0)
{
// Read each Short Message cyclically, starting with "+ cmgl :"
While (PTR = strstr (PTR, "+ cmgl :"))! = NULL)
{
PTR + = 6; // skip "+ cmgl :"
Sscanf (PTR, "% d", & PMSG-> index); // read the serial number
Trace ("Index = % d \ n", PMSG-> index );

PTR = strstr (PTR, "\ r \ n"); // locate the next row
PTR + = 2; // skip "\ r \ n"

Gsmdecodepdu (PTR, PMSG); // PDU string Decoding
PMSG ++; // prepare to read the next short message
Nmsg ++; // Add 1 to the Short Message count
}
}

Return nmsg;
}

// Delete Short Message
// Index: Short Message number, starting from 1
Bool gsmdeletemessage (const int index)
{
Int nlength; // The length of data received by the serial port
Char cmd [16]; // command string
Char ans [128]; // response string

Sprintf (CMD, "At + cmgd = % d \ r", index); // generate a command

// Output command string
Writecomm (CMD, strlen (CMD ));

// Read the response data
Nlength = readcomm (ANS, 128 );

// Determine whether the task is successful based on whether the "+ CMS error" can be found.
If (nlength> 0 & strncmp (ANS, "+ CMS error", 10 )! = 0)
{
Return true;
}

Return false;
}

The writecomm and readcomm functions are used to send at commands. They are used to read and write serial ports and depend on specific operating systems. In Windows, apart from MSComm controls and some ready-made Serial Communication classes, you can also call some windows APIs. The following is the main Code implemented using APIs. Note that we use the synchronous (blocking) mode of timeout control.

// Serial device handle
Handle hcomm;

// Open the serial port
// Pport: Serial Port name or device path, which can be "COM1" or "\. \ COM1". The latter is recommended.
// Nbaudrate: baud rate
// Nparity: parity
// Nbytesize: Data byte width
// Nstopbits: Stop bit
Bool opencomm (const char * pport, int nbaudrate, int nparity, int nbytesize, int nstopbits)
{
DCB; // serial control block
Commtimeouts timeouts = {// serial port timeout Control Parameter
100, // read character interval Timeout: 100 MS
1, // time per character during read operation: 1 MS (n characters total n ms)
500, // basic (additional) read Timeout: 500 MS
1, // time of each character when writing: 1 MS (n characters total n ms)
100}; // basic (additional) Write Timeout: 100 MS

Hcomm = createfile (pport, // serial port name or device path
Generic_read | generic_write, // read/write Method
0, // share mode: exclusive
Null, // Default Security Descriptor
Open_existing, // Creation Method
0, // file attributes do not need to be set
Null); // you do not need to refer to the template file.

If (hcomm = invalid_handle_value) return false; // An error occurred while enabling the serial port.

Getcommstate (hcomm, & DCB); // retrieves DCB

DCB. baudrate = nbaudrate;
DCB. bytesize = nbytesize;
DCB. Parity = nparity;
DCB. stopbits = nstopbits;

Setcommstate (hcomm, & DCB); // set DCB

Setupcomm (hcomm, 4096,102 4); // you can specify the size of the input/output buffer.

Setcommtimeouts (hcomm, & Timeouts); // set timeout

Return true;
}

// Close the serial port
Bool closecomm ()
{
Return closehandle (hcomm );
}

// Write the serial port
// Pdata: the buffer pointer of the data to be written.
// Nlength: the length of the data to be written.
Void writecomm (void * pdata, int nlength)
{
DWORD dwnumwrite; // The Data Length sent by the serial port

Writefile (hcomm, pdata, (DWORD) nlength, & dwnumwrite, null );
}

// Read the serial port
// Pdata: The data buffer pointer to be read
// Nlength: maximum data length to be read
// Return: the actual length of data read.
Int readcomm (void * pdata, int nlength)
{
DWORD dwnumread; // The length of data received by the serial port

Readfile (hcomm, pdata, (DWORD) nlength, & dwnumread, null );

Return (INT) dwnumread;
}

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.