您的位置:首页 > 运维架构 > Linux

Linux下短信功能实现

2016-02-22 11:39 369 查看
Linux下短信功能的实现

Linux版本Linux-3.2.0,无线模块是华为909SE,使用USB转串口模式,短信接口为/dev/ttyUSB4。

1 驱动

USB转串口驱动自行下载合适的版本,安装后无线模块会自动转化为8个串口,ttyUSB0~ttyUSB7,其中ttyUSB0用于网络数据的传输,ttyUSB4用于短信发送与接收。转化后可作为串口直接使用。

2 初始化

串口初始化:串口的初始化与一般一般串口相同,请自行参考串口初始化配置。

下面是串口配置的主要代码:

usbfd = open(Interface_USB4, O_RDWR); // 选择串口句柄

set_speed(usbfd , 115200); //设置串口速度函数

set_other_attribute(usbfd, 8, 1, 0, 0); //设置串口其他参数的函数

static int speed_arr[] = {B230400, B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1800, B1200, B600, B300};

static int name_arr[] = {230400, 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1800, 1200, 600, 300};

int set_speed(int fd, int speed)

{

int i, status;

struct termios Opt;

tcgetattr(fd, &Opt);

for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++) {

if (speed == name_arr[i]) {

tcflush(fd, TCIOFLUSH);

cfsetispeed(&Opt, speed_arr[i]);

cfsetospeed(&Opt, speed_arr[i]);

status = tcsetattr(fd, TCSANOW, &Opt);

if (status != 0) {

printf("tcsetattr failed\n");

return -1;

}

tcflush(fd,TCIOFLUSH);

return 0;

}

}

return -1;

}

int set_other_attribute(int fd, int databits, int stopbits, int parity, int mode)

{

struct termios options;

if (tcgetattr(fd, &options) != 0) {

printf("tcgetattr failed\n");

return -1;

}

options.c_cflag &= ~CSIZE;

switch (databits) /*¨¦?¨º?Y?¨º*/

{

case 7:

options.c_cflag |= CS7;

break;

case 8:

options.c_cflag |= CS8;

break;

default:

fprintf(stderr,"Unsupported data size\n");

return -1;

}

switch (parity)

{

case 'n':

case 'N':

options.c_cflag &= ~PARENB; /* Clear parity enable */

options.c_iflag &= ~INPCK; /* Enable parity checking */

break;

case 'o':

case 'O':

case 1:

options.c_cflag |= (PARODD | PARENB); /* ¨¦???§¹?*/

options.c_iflag |= INPCK; /* Disnable parity checking */

break;

case 'e':

case 'E':

case 2:

options.c_cflag |= PARENB; /* Enable parity */

options.c_cflag &= ~PARODD; /* ?????§¹?*/

options.c_iflag |= INPCK; /* Disnable parity checking */

break;

case 'S':

case 's': /*as no parity*/

case 0:

options.c_cflag &= ~PARENB;

options.c_cflag &= ~CSTOPB;

break;

default:

fprintf(stderr,"Unsupported parity\n");

return -1;

}

/* ¨¦???¦Ë*/

switch (stopbits)

{

case 1:

options.c_cflag &= ~CSTOPB;

break;

case 2:

options.c_cflag |= CSTOPB;

break;

default:

fprintf(stderr,"Unsupported stop bits\n");

return -1;

}

/* Set input parity option */

if (parity != 'n')

options.c_iflag |= INPCK;

tcflush(fd,TCIFLUSH);

options.c_iflag = 0;

options.c_oflag = 0;

options.c_lflag = 0;

options.c_cc[VTIME] = 50; /* ¨¦?3??15 seconds*/

options.c_cc[VMIN] = 1; /* Update the options and do it NOW */

// options.c_oflag 0;

switch(mode)

{

/*case 1://rs485

options.c_cflag |= RS485;

printf("Enable RS485 !\n");

break;

case 2://HWHD

options.c_cflag |= HWHD;

printf("Enable HWHD !\n");

break;

case 3://Modem

options.c_cflag |= Modem;

printf("Enable Modem !\n");

break;

case 4://ISO7816T0

options.c_cflag |= ISO7816T0;

printf("Enable ISO7816 T=0 \n");

break;

case 5://ISO7816T1

options.c_cflag |= ISO7816T1;

printf("Enable ISO7816 T=1 \n");

break;

case 6://IrDA

options.c_cflag |= IrDA;

printf("Enable IrDA \n");

break;*/

default:

break;

}

if (tcsetattr(fd,TCSANOW,&options) != 0)

{

perror("SetupSerial 3");

return -1;

}

#if 0

tcgetattr(fd, &options);

printf("c_iflag: %x\rc_oflag: %x\n", options.c_iflag, options.c_oflag);

printf("c_cflag: %x\nc_lflag: %x\n", options.c_cflag, options.c_lflag);

printf("c_line: %x\nc_cc[VTIME]: %d\nc_cc[VMIN]: %d\n", options.c_line, options.c_cc[VTIME], options.c_cc[VMIN]);

#endif

return 0;

}

模块初始化:根据使用的模块,进行配置。包括短信模式、字符模式、新消息到来提醒、短信存储位置、清除已读短信等配置。

MsgInit;//模块初始化函数

int MsgInit(void)

{

int rec;

rec = ATCMDSend("AT+IPR=0\r\n", strlen("AT+IPR=0\r\n") , "OK", 3);

if (rec != 0)

{

printf("波特率自适应设置失败\n");

return -1;

}

rec = ATCMDSend("AT+CMGF=1\r\n", strlen("AT+CMGF=1\r\n") , "OK", 3);

if (rec != 0)

{

printf(短信模式配置失败\n");

return -1;

}

rec = SetGSMMode();

if (rec != 0)

{

printf("字符格式设置失败\n");

return -1;

}

rec = ATCMDSend("AT+CNMI=2,1,0,0,0\r\n", strlen("AT+CNMI=2,1,0,0,0\r\n") , "OK", 3);

if(rec != 0)

{

printf("新消息提示设置失败\n");

return -1;

}

rec = SetFlashMode();

if (rec != 0)

{

printf("短信存储器选择失败\n");

return -1;

}

rec = ATCMDSend("AT+CMGD=1,4\r\n", strlen("AT+CMGD=1,4\r\n") , "OK", 5);

if (rec != 0)

{

printf("清空短消息失败\n");

return -1;

}

printf("=====message initial done!\n");

return 0;

}

3 短信读取与发送:短信接收与发送分别使用不同的线程独立完成,在接收过程中提取接收的短信号码,留作发送时使用。

短信接收线程:

void SMS_RECV(int arg)

{

int readlen ;

int timeout=0;

int ct=0;

char ATrxbuf[COMPORT_BUFSIZE]={0};

if(fcntl(usbfd, F_SETFL, FNDELAY) < 0)

{

printf("[%s:%d]>>>>error\n\n\n", __FILE__, __LINE__);

}

while(1)

{

readlen = read(usbfd, ATrxbuf+ct, COMPORT_BUFSIZE);

if(readlen > 0)

{

//printf("Thread_SMS_RECV message<<<<<<<<\n %s \n>>>>>>>>>\n", ATrxbuf);

timeout=0;

if(readlen + ct < COMPORT_BUFSIZE)

{

ct += readlen;

}

else

{

ct = 0;

bzero(ATrxbuf, COMPORT_BUFSIZE);

}

}

else

{

if((ct>0)&&(timeout > 5))//50ms once

{

//printf("ct= %d \n", ct);

//printf("readlen= %d \n", readlen);

//printf("<<<<<<ATrxbuf[]>>>>>>\n",ATrxbuf);

printf("%s \n", ATrxbuf);

//printf("<<<<<<<<END>>>>>>>>>>\n",ATrxbuf);

Msg_CheckAndSend(ATrxbuf, ct);

//AckDataAnalyse(ATrxbuf, ct);

timeout = 0;

ct = 0;

bzero(ATrxbuf, COMPORT_BUFSIZE);

}

}

timeout++;

usleep(10000);//10ms

}

}

int Msg_CheckAndSend(char *Msgdata,int len)

{

char *p1=NULL,*p2=NULL, *p3=NULL,*p4=NULL,*p5=NULL;

char Msgbuf[COMPORT_BUFSIZE]={0};

int rec=0, i=3;

unsigned int lenOfsms;

bzero(Msgbuf, COMPORT_BUFSIZE);

memcpy(Msgbuf, Msgdata, len-2);/*except "\r\n"*/

memcpy(Msgdata, Msgbuf, len-2);/*except "\r\n"*/

if ((p4 = strstr(Msgdata, "CMTI")) != NULL)

{

printf("--------------------------------------\n");

p5 = strstr(p4, ",");

if (p5 != NULL)

{

Msgindex = atoi(p5+1);

printf("MsgindexOfNewSMS>>>>>>> %d <<<<<<\n", Msgindex);

Msgflag = 1;/*means get new message*/

}

printf("--------------------------------------\n");

}

if ((p1 = strstr(Msgdata, "+CMGR:")) != NULL)

{

printf("++++++++++++++++++++++++++++++++++++++\n");

p2 = strstr(p1, "+86");

if (p2 != NULL)

{

memcpy(phonenumber, p2+3, 11);

//printf("\n p2:<<<<<<<<\n %s \n>>>>>>>>>\n", p2);//for debug

}

else

{

printf("骚扰短信或通信公司短信,不处理");

}

p3 = strstr(p1, "\n");

if (p3 != NULL)

{

bzero(Msgbuf, COMPORT_BUFSIZE);

lenOfsms = strlen(p3)-9;

memcpy(Msgbuf, p3+1, lenOfsms);//store SMS into Msgbuf

//printf("\n p3:<<<<<<<<\n %s \n>>>>>>>>>\n", p3);//for debug

#if 1 /*debug print*/

printf("PhoneNO:<<<<<<<< %s >>>>>>>>>\n", phonenumber);

printf("lenOfsms:<<<<<<<< %d >>>>>>>>>\n", lenOfsms);

printf("SMS_Detail: <<<<<<<<\n%s\n>>>>>>>>>\n", Msgbuf);

#endif

printf("######################################\n");

Msg_FixParam(Msgbuf, lenOfsms);//短信解析线程

}

}

}

短信发送线程:

void Thread_SendATcmd(int arg)

{

int rec=1;

unsigned int i=2;/*×î´ó³¢ÊÔ·¢Ë͵ĴÎÊý*/

char tempbuf[5]={0}, ATSendbuf[30]={0};

/*----------------------------------*/

// test read message

/*----------------------------------*/

while(1)

{

if (Msgflag == 1)//means recv new SMS

{

while(i--) //

{

rec = ATcmd_ReadMsg();

if (rec == 0)

break;

}

Msgflag = 0;

i = 3;

}

usleep(10*1000);//10ms

}

}

发送读取短信命令的函数:

int ATcmd_ReadMsg(void)

{

int rec;

char tempbuf[100]={0};

strcpy(tempbuf, "AT+CMGR=");

sprintf(&tempbuf[strlen(tempbuf)],"%d", Msgindex);

strcat(tempbuf, "\r\n");

//printf("send-AT-read-SMS-cmd: %s\n", tempbuf);

rec = ATCMDSend(tempbuf, strlen(tempbuf), "OK", 3);

if (rec == 0)

{

ATCMDSend("AT+CMGD=1,3\r\n", strlen("AT+CMGD=1,3\r\n") , NULL, 0);

//删除已读短信

}

return rec;

}

实现过程中参考的参考的主要代码:(功能较单一,代码简洁)

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <fcntl.h> // open() close()

#include <unistd.h> // read() write()

#include <termios.h> // set baud rate

#include <fcntl.h>

#include <sys/select.h>

#include <sys/time.h>

#include <sys/types.h>

#define FUNC_RUN 0

#define FUNC_NOT_RUN 1

#define SIMPLE_TEST 1

#define READ_SIM_CARD_ID 2

#define SHORT_MESSAGE 3

#define FUNC_QUIT 4

#define SEND_SHORT_MESSAGE 1

#define READ_SHORT_MESSAGE 2

#define CONFIG_SHORT_MESSAGE_ENV 3

#define QUIT_SHORT_MESSAGE 4

#define DEVICE_TTYS "/dev/ttyUSB4" //(有些人的文件是”/dev/ttyS0,看看你是用那个串口”自己对号入座啦!)

#define MAX_LEN_OF_SHORT_MESSAGE 140

#define RECEIVE_BUF_WAIT_1S 1

#define RECEIVE_BUF_WAIT_2S 2

#define RECEIVE_BUF_WAIT_3S 3

#define RECEIVE_BUF_WAIT_4S 4

#define RECEIVE_BUF_WAIT_5S 5

//------------------------------------- read datas from GSM/GPRS ---------------------------

// succese return 1

// error return 0

int read_GSM_GPRS_datas(int fd, char *rcv_buf,int rcv_wait)

{

int retval;

fd_set rfds;

struct timeval tv;

int ret,pos;

tv.tv_sec = rcv_wait; // wait 2.5s

tv.tv_usec = 0;

pos = 0; // point to rceeive buf

while (1)

{

FD_ZERO(&rfds);

FD_SET(fd, &rfds);

retval = select(fd+1 , &rfds, NULL, NULL, &tv);

if (retval == -1)

{

perror("select()");

break;

}

else if (retval)

{ // pan duan shi fou hai you shu ju

ret = read(fd, rcv_buf+pos, 2048);

pos += ret;

if (rcv_buf[pos-2] == '\r' && rcv_buf[pos-1] == '\n')

{

FD_ZERO(&rfds);

FD_SET(fd, &rfds);

retval = select(fd+1 , &rfds, NULL, NULL, &tv);

if (!retval) break;// no datas, break

}

}

else

{

printf("No data\n");

break;

}

}

return 1;

} // end read_GSM_GPRS_datas

//------------------------------------- send cmd ------------------------------------------// succese return 1

// error return 0

int send_GSM_GPRS_cmd(int fd, char *send_buf)

{

ssize_t ret;

ret = write(fd,send_buf,strlen(send_buf));

if (ret == -1)

{

printf ("write device %s error\n", DEVICE_TTYS);

return -1;

}

return 1;

} // end send_GSM_GPRS_cmd

//------------------------------------- send cmd and read back result ----------------------

void GSM_GPRS_send_cmd_read_result(int fd, char *send_buf, int rcv_wait)

{

char rcv_buf[2048];

if((send_buf==NULL) || (send_GSM_GPRS_cmd(fd,send_buf)))

{ // send success , then read

bzero(rcv_buf,sizeof(rcv_buf));

if (read_GSM_GPRS_datas(fd,rcv_buf,rcv_wait))

{

printf ("%s\n",rcv_buf);

}

else

{

printf ("read error\n");

}

}

else

{

printf("write error\n");

}

} // end GSM_GPRS_send_cmd_read_result

//------------------------------------- send cmd : "at" to GSM/GPRS MODEM ------------------

void GSM_simple_test(int fd)

{

char *send_buf="AT\r";

GSM_GPRS_send_cmd_read_result(fd,send_buf,RECEIVE_BUF_WAIT_1S);

} // end GSM_simple_test

//------------------------------------- send cmd : "at+ccid" to GSM/GPRS MODEM -------------

void GSM_read_sim_card_id(int fd)

{

char *send_buf="AT+CMGD=1,4\r";

GSM_GPRS_send_cmd_read_result(fd,send_buf,RECEIVE_BUF_WAIT_1S);

} // end GSM_read_sim_card_id

//------------------------------------- GSM/GPRS send short message ------------------------

void GSM_Send_Message(int fd)

{

char cmd_buf[23];

char *sendtxt_buf="AT+CMGF=1\r";

char short_message_buf[MAX_LEN_OF_SHORT_MESSAGE];

int i;

char rcv_buf;

bzero(cmd_buf,sizeof(cmd_buf));

bzero(short_message_buf,sizeof(short_message_buf));

printf ("send short message:\n");

GSM_GPRS_send_cmd_read_result(fd,sendtxt_buf,RECEIVE_BUF_WAIT_1S);

cmd_buf[0]='A';

cmd_buf[1]='T';

cmd_buf[2]='+';

cmd_buf[3]='C';

cmd_buf[4]='M';

cmd_buf[5]='G';

cmd_buf[6]='S';

cmd_buf[7]='=';

cmd_buf[8]='"';

printf ("please input telephone number:");

i = 9;

while (1)

{

cmd_buf[i]=getchar();

if (cmd_buf[i]=='\n') break;

i++;

}

cmd_buf[i]='"';

cmd_buf[i+1]='\r';

cmd_buf[i+2]='\0';

// send cmd : at+cmgs="(telephone number)"

GSM_GPRS_send_cmd_read_result(fd,cmd_buf,RECEIVE_BUF_WAIT_1S);

// input short message

printf("please input short message:");

i = 0;

while(i < MAX_LEN_OF_SHORT_MESSAGE-2)

{

short_message_buf[i] = getchar();

if (short_message_buf[i]=='\n') break;

i++;

}

short_message_buf[i] = 0x1A;

short_message_buf[i+1] = '\r';

short_message_buf[i+2] = '\0';

// send short message

GSM_GPRS_send_cmd_read_result(fd, short_message_buf,RECEIVE_BUF_WAIT_4S);

printf("\nend send short message\n");

} // end GSM_Send_Message

//------------------------------------- GSM/GPRS read all short message --------------------

void GSM_Read_Message(int fd)

{

char *send_buf="AT+CMGR=1\r"; //\"ALL\"\r";

char rcv_buf[2048];

GSM_GPRS_send_cmd_read_result(fd,send_buf,RECEIVE_BUF_WAIT_3S);

printf("end read first short message\n");

} // end GSM_Read_Message

//------------------------------------- GSM/GPRS Config short message env ------------------

void GSM_Conf_Message(int fd)

{

char *send_buf="AT+CMGF=1\r";

char *send_center_buf="AT+CSCA=\"+8613800210500\"\r";

GSM_GPRS_send_cmd_read_result(fd,send_buf,RECEIVE_BUF_WAIT_1S);

//char *sedd_buf="AT+CPMS=\"SM\"\r";

//GSM_GPRS_send_cmd_read_result(fd,send_buf,RECEIVE_BUF_WAIT_1S);

//printf("message storage in SM.");

// set short message center number

GSM_GPRS_send_cmd_read_result(fd,send_center_buf,RECEIVE_BUF_WAIT_1S);

printf("end config short message env\n");

} // end GSM_Conf_Message

//------------------------------------- GSM/GPRS short message -----------------------------

void GSM_short_mesg(int fd)

{

int flag_sm_run, flag_sm_select;

flag_sm_run = FUNC_RUN;

while (flag_sm_run == FUNC_RUN)

{

printf ("\n Select:\n");

printf ("1 : Send short message \n");

printf ("2 : Read first short message \n");

printf ("3 : Config short message env\n");

printf ("4 : quit\n");

printf (">");

scanf("%d",&flag_sm_select);

getchar();

// temp

// printf ("input select:%d\n",flag_sm_select);

// end temp

switch (flag_sm_select)

{

case SEND_SHORT_MESSAGE : { GSM_Send_Message(fd);}

case READ_SHORT_MESSAGE : { GSM_Read_Message(fd);}

case CONFIG_SHORT_MESSAGE_ENV : { GSM_Conf_Message(fd);}

case QUIT_SHORT_MESSAGE : { flag_sm_run = FUNC_NOT_RUN;}

default :

{

printf("please input your select use 1 to 3\n");

}

}

}

printf ("\n");

} // end GSM_send_mesg

//------------------------------------- print ----------------------------------------------

void print_prompt(void)

{

printf ("Select what you want to do:\n");

printf ("1 : Simple Test\n");

printf ("2 : Del all msg\n");

printf ("3 : Short message\n");

printf ("4 : Quit\n");

printf (">");

} // end print_prompt

//------------------------------------- Control GSM/GPRS MODULE ----------------------------

void func_GSM(int fd)

{

int flag_func_run;

int flag_select_func;

ssize_t ret;

flag_func_run = FUNC_RUN;

while (flag_func_run == FUNC_RUN)

{

print_prompt(); // print select functions

scanf("%d",&flag_select_func); // user input select

getchar();

switch(flag_select_func)

{

case SIMPLE_TEST : {GSM_simple_test(fd); break;}

case READ_SIM_CARD_ID : {GSM_read_sim_card_id(fd); break;}

//case MAKE_A_CALL : {GSM_call(fd); break;}

//case WAIT_A_CALL : {GSM_wait_call(fd); break;}

case SHORT_MESSAGE : {GSM_short_mesg(fd); break;}

case FUNC_QUIT :

{

flag_func_run = FUNC_NOT_RUN;

printf("Quit GSM/GPRS function. byeb");

break;

}

default :

{

printf("please input your select use 1 to 7\n");

}

}

}

}// end func_GPRS

//------------------------------------- init seriel port ----------------------------------

void init_ttyS(int fd)

{

struct termios options;

bzero(&options, sizeof(options)); // clear options

cfsetispeed(&options,B9600); // setup baud rate

cfsetospeed(&options,B9600);

options.c_cflag |= (CRTSCTS | CS8 | CLOCAL | CREAD);

options.c_iflag = IGNPAR;

tcflush(fd, TCIFLUSH);

tcsetattr(fd, TCSANOW, &options);

}//end init_ttyS

//------------------------------------- main -----------------------------------------------

int main(void)

{

int fd;

printf("\nGSM/GPRS TESTS\n\n");

// open seriel port

fd = open(DEVICE_TTYS, O_RDWR);

if (fd == -1)

{

printf("open device %s error\n",DEVICE_TTYS);

}

else

{

init_ttyS(fd); // init device

func_GSM(fd); // GSM/GPRS functions

// close ttyS0

if (close(fd)!=0) printf("close device %s error",DEVICE_TTYS);

}

return 0;

}// end main
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: