转载请注明出处:http://blog.csdn.net/ruoyunliufeng/article/details/38515343
这将是本项目的最后一篇,实现监控报警功能,可能还有改进的地方,我先放出第一个版本,后续更新请留意本博客。
一.软件框架
二.源代码
/***************************************************************
*版权:GPLv2,希望用到或更改代码的小伙伴自觉遵守
*文件名称:监控报警测试
*内容摘要:
*其它说明:实现远程监控报警功能
*当前版本:V1.0
*作 者:若云流风
*完成日期:2014.8.8
***************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//for gsm
#define FUNC_RUN 0
#define FUNC_NOT_RUN 1
#define DEVICE_TTYS "/dev/ttySAC1" //modem分配的UART口,0为与PC调试串口,2为红外串口,故选择1
#define MAX_LEN_OF_SHORT_MESSAGE 14
#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
void GSM_call(int fd_g);
void GSM_Send_Message(int fd_g);
/*
wvm_buttonstest
*/
int fd_b,fd_l,fd_p,fd_g,pos,alert;
/*初始化设备*/
void init_ttyS(int fd_g)
{
struct termios options;
bzero(&options, sizeof(options)); // clear options
cfsetispeed(&options,B115200); // setup baud rate,输入、输出都为115200
cfsetospeed(&options,B115200);
options.c_cflag |= (CS8 | CREAD); //Enable the receiver and Select 8 data bits
options.c_iflag = IGNPAR; //Ignore parity errors
tcflush(fd_g, TCIFLUSH); //*TCIFLUSH 刷清输入队列. 在打开串口后,串口其实已经可以开始读取 数据了 ,这段时间用户如果没有读取,将保存在缓冲区里,如果用户不想要开始的一段数据,或者发现缓冲区数据有误,可以使用这个函数清空缓冲
tcsetattr(fd_g, TCSANOW, &options); //Set the new options for the port
}
/*基本功能函数*/
void GSM_GPRS_send_cmd_read_result(int fd_g, char *send_buf, int rcv_wait)
{
char rcv_buf[2048];
if((send_buf==NULL) || (send_GSM_GPRS_cmd(fd_g,send_buf))){ // send success , then read
bzero(rcv_buf,sizeof(rcv_buf)); //将rcv_buf清零,为接收做准备
if (read_GSM_GPRS_datas(fd_g,rcv_buf,rcv_wait)){
printf ("%s\n",rcv_buf);
}
else{
printf ("read error\n");
}
}
else{
printf("write error\n");
}
}
/*为GSM短信控制关闭警报*/
void GSM_GPRS_send_cmd_read_result_alert(int fd_g, char *send_buf, int rcv_wait)
{
char rcv_buf[2048];
if((send_buf==NULL) || (send_GSM_GPRS_cmd(fd_g,send_buf)))// send success , then read
{
bzero(rcv_buf,sizeof(rcv_buf)); //将rcv_buf清零,为接收做准备
if (read_GSM_GPRS_datas(fd_g,rcv_buf,rcv_wait))
{
/*关闭警报密码:82E5 4E91 6D41 98CE 若云流风(更改密码请更改此处)*/
if (rcv_buf[pos-24] == '8' && rcv_buf[pos-23] == '2'&& rcv_buf[pos-22] == 'E' && rcv_buf[pos-21] == '5'&& rcv_buf[pos-20] == '4' && rcv_buf[pos-19] == 'E'&& rcv_buf[pos-18] == '9' && rcv_buf[pos-17] == '1'&&rcv_buf[pos-16] == '6' && rcv_buf[pos-15] == 'D'&& rcv_buf[pos-14] == '4' && rcv_buf[pos-13] == '1'&& rcv_buf[pos-12] == '9' && rcv_buf[pos-11] == '8'&& rcv_buf[pos-10] == 'C' && rcv_buf[pos-9] == 'E')
alert=0;
/*开启警报密码:6D41 98CE 82E5 4E91 流风若云(更改密码请更改此处)*/
if (rcv_buf[pos-24] == '6' && rcv_buf[pos-23] == 'D'&& rcv_buf[pos-22] == '4' && rcv_buf[pos-21] == '1'&& rcv_buf[pos-20] == '9' && rcv_buf[pos-19] == '8'&& rcv_buf[pos-18] == 'C' && rcv_buf[pos-17] == 'E'&&rcv_buf[pos-16] == '8' && rcv_buf[pos-15] == '2'&& rcv_buf[pos-14] == 'E' && rcv_buf[pos-13] == '5'&& rcv_buf[pos-12] == '4' && rcv_buf[pos-11] == 'E'&& rcv_buf[pos-10] == '9' && rcv_buf[pos-9] == '1')
alert=1;
}
/* else
{
printf ("read error\n");
}
*/
}
else
{
printf("write error\n");
}
}
/*发命令:主机->GSM*/
int send_GSM_GPRS_cmd(int fd_g, char *send_buf)
{
ssize_t ret;
ret = write(fd_g,send_buf,strlen(send_buf));
if (ret == -1)
{
printf ("write device %s error\n", DEVICE_TTYS);
return -1;
}
return 1;
}
/*读数据:GSM->主机
*此处我在测试的时候发现发送和接收的字符串长度不一致,最后经过试验发现
*发送的时候例如:AT+CSCS="UCS2"\r发送15个字节
* 接收的时候是21字节,后来发现接收除了发送的AT+CSCS="UCS2"\r以外还接收了\r\nOK\r\n这样就说明了多出的6个字节了。
*最后一个有效字节是pos-9 pos-24,四个汉字加密
*/
int read_GSM_GPRS_datas(int fd_g, char *rcv_buf,int rcv_wait)
{
int retval;
fd_set rfds;
struct timeval tv;
//int ret,pos;
int ret;
tv.tv_sec = 2.5; // 秒wait 2.5s
tv.tv_usec = 0; //毫秒
pos = 0; // point to rceeive buf
while (1)
{
FD_ZERO(&rfds); //清除套接字集合
FD_SET(fd_g, &rfds); //用于在文件描述符集合中增加一个新的文件描述符(读数据)
retval = select(fd_g+1 , &rfds, NULL, NULL, &tv);
if (retval == -1) //(-1)出错
{ //超时
perror("select()");
break;
}
else
if (retval) //(正数)已经准备好的描述符数
{ //判断是否还有数据
ret = read(fd_g, rcv_buf+pos, 2048);
pos += ret; //读出的数据长度
if (rcv_buf[pos-2] == '\r' && rcv_buf[pos-1] == '\n') //如果读到字符串末尾
{
FD_ZERO(&rfds);
FD_SET(fd_g, &rfds);
retval = select(fd_g+1 , &rfds, NULL, NULL, &tv);
if (!retval) break; // no datas, break
}
}
else //(0)没有准备好描述符
{
printf("No data\n");
break;
}
}
return 1;
}
/*GSM初始化*/
void GSM_init_test(int fd_g)
{
char *send_buf="AT+CSCS=\"UCS2\"\r"; //选择TE字符集
GSM_GPRS_send_cmd_read_result(fd_g,send_buf,RECEIVE_BUF_WAIT_1S);
send_buf="AT+CNMI=2,1,0,0,0\r"; //设置新消息提示
GSM_GPRS_send_cmd_read_result(fd_g,send_buf,RECEIVE_BUF_WAIT_1S);
send_buf="AT+CMGF=0\r"; //PDU格式
GSM_GPRS_send_cmd_read_result(fd_g,send_buf,RECEIVE_BUF_WAIT_1S);
}
/*发送信息*/
void GSM_Send_Message(int fd_g)
{
char *send_buf="AT+CMGS=29\r"; //发送PDU格式短信
GSM_GPRS_send_cmd_read_result(fd_g,send_buf,RECEIVE_BUF_WAIT_1S);
char *send_buf_pud="0891683108406105F011000D91685141128978F00008000E003153F7573070B962A58B66002E"; //1号地点报警 (8870发送的内容)
GSM_GPRS_send_cmd_read_result(fd_g,send_buf_pud,RECEIVE_BUF_WAIT_1S);
send_buf="\x01a"; //ctrl+z
GSM_GPRS_send_cmd_read_result(fd_g,send_buf,RECEIVE_BUF_WAIT_1S);
sleep(3); //加3S延时,给手机接收短信的时间,否则和拨号造成冲突,无法拨号
}
/*打电话*/
void GSM_call(int fd_g)
{
int i;
char *send_buf="ATD114;\r\0"; //发送缓冲区
GSM_GPRS_send_cmd_read_result(fd_g,send_buf,RECEIVE_BUF_WAIT_1S); //拨号
}
/*做一些GSM初始化的工作*/
int gsm_init(fd_g)
{
init_ttyS(fd_g); // init device
GSM_init_test(fd_g);
return 0;
}
/*按键后触发的函数*/
void my_signal_fun(int signum)
{
printf("open my_signal_fun\n");
unsigned char key_val;
unsigned int led_val;
unsigned int cmd;
//unsigned int alert=1;
read(fd_b, &key_val, 1);
printf("key_val: 0x%x\n", key_val);
if(key_val==0x4)
{
char *send_buf="AT+CMGR=1\r"; //读取短消息1
GSM_GPRS_send_cmd_read_result_alert(fd_g,send_buf,RECEIVE_BUF_WAIT_1S);
send_buf="AT+CMGD=1\r"; //删除短消息1(所有的用1,4)
GSM_GPRS_send_cmd_read_result(fd_g,send_buf,RECEIVE_BUF_WAIT_1S);
//alert=1;
if(alert==1)
{
GSM_Send_Message(fd_g);
GSM_call(fd_g);
while(alert)
{
cmd=1;
led_val=1;
write(fd_l, &led_val, 4);
ioctl(fd_p,cmd,700);
//printf("on\n");
send_buf="AT+CMGR=1\r"; //读取短消息1
GSM_GPRS_send_cmd_read_result_alert(fd_g,send_buf,RECEIVE_BUF_WAIT_1S);
led_val=0;
write(fd_l, &led_val, 4);
ioctl(fd_p,cmd,2000);
sleep(1);
}
//做一些清理工作,警报关闭,灯光关闭,删除短信
led_val=0;
cmd=0;
write(fd_l, &led_val, 4);
ioctl(fd_p,cmd,0);
send_buf="ATH\r"; //删除短消息1(所有的用1,4)
GSM_GPRS_send_cmd_read_result(fd_g,send_buf,RECEIVE_BUF_WAIT_1S);
send_buf="AT+CMGD=1\r"; //删除短消息1(所有的用1,4)
GSM_GPRS_send_cmd_read_result(fd_g,send_buf,RECEIVE_BUF_WAIT_1S);
}
}
}
/*主函数*/
int main(int argc, char **argv)
{
unsigned char key_val;
int ret;
int Oflags;
alert=1; //初始化警报开启
signal(SIGIO, my_signal_fun);
fd_b = open("/dev/buttons", O_RDWR);
if (fd_b < 0)
{
printf("can't open/dev/buttons\n");
}
printf("open /dev/buttons\n");
fd_l = open("/dev/led", O_RDWR);
if (fd_l < 0)
{
printf("can't open/dev/led\n");
}
printf("open /dev/led\n");
fd_p = open("/dev/wvm_pwm", O_RDWR);
if (fd_b < 0)
{
printf("can't /dev/wvm_pwm\n");
}
printf("open /dev/wvm_pwm\n");
fd_g = open("/dev/ttySAC1", O_RDWR); //打开TTY设备
if (fd_b < 0)
{
printf("can't /dev/ttySAC1\n");
}
printf("open /dev/ttySAC1\n");
gsm_init(fd_g);
fcntl(fd_b, F_SETOWN, getpid());
Oflags = fcntl(fd_b, F_GETFL);
fcntl(fd_b, F_SETFL, Oflags | FASYNC);
while (1)
{
sleep(1000);
}
return 0;
}