1、系统技术简介
1.1 zigbee网络
无线传感器网络是集信息采集、信息传输、信息处理于一体的综合智能信息系统,具有低成本、低功耗、低数据速率、自组织网络等特点。而Zigbee技术是为低速率传感器和控制网络设计的标准无线网络协议栈,是最适合无线传感器网络的标准。Zigbee无线传感器网络是基于Zigbee技术的无线传感器网络。在许多行业有巨大的应用潜力,如环境监控、物流管理、医疗监控、交通管理和军事侦察等方面的应用。
目前普遍使用的无线传感器网络平台主要有Crossbow公司的Mica2/MicaZ和Microchip公司的PICDEMZ等。MicaZ虽然具有Tinyos操作系统,但是没有结合Zigbee技术;PICDEMZ的Zigbee协议栈不完全符合Zigbee的定义,而且功能简单。因此,设计一种Zigbee无线传感器网络平台,可以更好地开发无线传感器网络的应用和Zigbee技术。
本文在分析Zigbee无线传感器网络的特点和关键技术的基础上,提出Zigbee无线传感器网络平台的设计实现方案,并且使用该无线传感器网络平台进行了智能家居安防的实现的实验。结果表明,该平台实现了Zigbee无线传感器网络的基本功能,可以更好地开发Zigbee技术。
ZigBee无线通信技术作为一种介于无线标记技术和蓝牙之间双向无线通信技术,以其距离短、功耗少、速度慢、成本低、可靠性高的特点,正一步步进入无线通信领域的浪潮中。
该技术是基于IEEE批准的802.15.4无线标准研制开发的有关自组网、安全和应用软件方面的技术。ZigBee无线通信技术主要适合于对距离、功耗以及传输速率要求不高的各种电子设备之间进行数据传输的场景。
1.1.1ZigBee无线通信技术的优势
(1)功耗低。ZigBee无线通信技术的传输速率较低,且其发射功率仅为1mW,故采用ZigBee技术的设备非常省电。同时,ZigBee技术运行时,采用休眠模式,更有效的减少了功耗。
(2)成本低。含有ZigBee无线通信技术的模块,起始时成本在大约在6美元。不过随着ZigBee无线通信技术的不断普及,在未来几年,很有可能降到1.8美元左右。ZigBee无线通信协议免专利费也为ZigBee技术的广泛使用奠定基础。
(3)时延短。通信时延和从休眠状态激活的实验都非常短,故对实验要求较高的无线控制设备上面可以采用ZigBee无线通信技术。
(4)网络容量大。每个ZigBee网络最多可以容纳的设备数量有255个。网络容量大且网络组成较为灵活为ZigBee技术的进一步推广做了铺垫。
1.1.2ZigBee无线通信技术的应用场景
ZigBee无线通信技术起初是希望发展一种易于建构的低成本无线网络。在其发展的初期,ZigBee无线通信技术主要以工业或企业市场为主,致力于工业或企业的感应式网络,如提供感应辨识、灯光与安全控制等功能。随后,将逐渐把市场拓展至家庭应用,给整个社会提供便利。
采用ZigBee无线通信技术的应用场景如下,通常满足其中之一即可:
(1)设备预算少,成本低,数据传输量小;
(2)设备整体体积小,无法放置较大的模块;
(3)只能使用一次性电池,不能进行足够的电力支持;
(4)频繁更换电池或者反复充电难度较大,不易实现;
(5)在通信时需要较大范围的通信覆盖,但网络中仅用于监测的设备繁多。
1.2ARM架构简介
ARM的处理器在智能手机和与平板电脑的地位,如同如同Intel之于PC。ARM公司本身不进行芯片的生产,而只是提供生产、芯片架构设计以及核心架构等等授权。在ARM的Cortex系列处理器之前,ARM公司处理器的命名从ARM1开始一直延续到了ARM11。所以我们常听到“ARM的ARM11采用了ARMV6架构“之类的绕口令,第一个ARM表示的是ARM公司,第二个ARM11表示的处理器型号,第三个ARMV6表示的处理器架构。也许是为了规避这绕口的说法,ARM公司自ARM11之后的处理器就改名叫Cortex。Cortex:大脑皮层的意思。目前Cortex的处理器主要分为三大系列:
1.Cortex-A系列,针对终端应用,手机与PC等,比如A8应用于IPHONE4。Cortex-A系列面向尖端的基于虚拟内存的操作系统和用户应用。
2.Cortex-R系列,应用在实时控制领域,比如硬盘控制、引擎管理、基频的实时处理器核心Cortex-R系列
3.Cortex- M系列,针对成本和功耗敏感的MCU和终端应用,如人机接口设备、工业控制系统和医疗器械。Cortex- M系重点针对微控制器和低成本应用提供了优化。Cortex-M系列也可以跑操作系统,不过得要那种最简单的不带虚拟内存的。
1.3linux系统简介
1.3.1Linux系统介绍
Linux内核最初只是由芬兰人李纳斯•托瓦兹(Linus Torvalds)在赫尔辛基大学上学时出于个人爱好而编写的。
Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。
Linux能运行主要的UNIX工具软件、应用程序和网络协议。它支持32位和64位硬件。Linux继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。

1.3.2Linux的发行版
Linux的发行版说简单点就是将Linux内核与应用软件做一个打包。
目前市面上较知名的发行版有:Ubuntu、RedHat、CentOS、Debian、Fedora、SuSE、OpenSUSE、Arch Linux、SolusOS 等。
1.3.3Linux应用领域
今天各种场合都有使用各种Linux发行版,从嵌入式设备到超级计算机,并且在服务器领域确定了地位,通常服务器使用LAMP(Linux + Apache + MySQL + PHP)或LNMP(Linux + Nginx+ MySQL + PHP)组合。
目前Linux不仅在家庭与企业中使用,并且在政府中也很受欢迎。
(1) 巴西联邦政府由于支持Linux而世界闻名。
(2) 有新闻报道俄罗斯军队自己制造的Linux发布版的,做为G.H.ost项目已经取得成果.
(3) 印度的Kerala联邦计划在向全联邦的高中推广使用Linux。
(4) 中华人民共和国为取得技术独立,在龙芯过程中排他性地使用Linux。
(5) 在西班牙的一些地区开发了自己的Linux发布版,并且在政府与教育领域广泛使用,如Extremadura地区的gnuLinEx和Andalusia地区的Guadalinex。
(6) 葡萄牙同样使用自己的Linux发布版Caixa Mágica,用于Magalh?es笔记本电脑和e-escola政府软件。
(7) 法国和德国同样开始逐步采用Linux。
本实验采用的Linux发行版本为服务器:CentOS7.3与网关:Ubuntu16.04
2、需求分析
2.1需求概述
本系统结合Zigbee无线传感网络与Linux web服务器实现用户对家中的安全进行必要的检测,Linux服务器可依据相应的传感器信息,及时的做出响应,在本系统中Linux服务器主机,将扮演家居安防管家的角色,而用户只要连接上服务器,就可对家居的安全进行检测,并做出相应的反应,可减少因家居安全不到位与发现不及时而造成的损失。
2.2系统结构信息
2.2.1传感器节点
依据家庭安防的需求,使用各种传感器进行实时监控,提高效率。可以查看的传感器信息有:
(1) 温湿度传感器
温湿度传感器可检测家中的温湿度,一旦超出了一定的范围,服务器便会操作继电器控制电机,驱动风扇等控制家中的温湿度,并向用户发送相应的提示信息。

(2)光照强度传感器
光照传感器可检测光强的强度,一旦光强超标,服务器便会像用户发去相应的提示信息,以便用户做出相应的措施。

(3)烟雾传感器
烟雾传感器可检测家中的烟雾中气体含量,一旦超出了一定的范围,服务器便会操作继电器控制电机,驱动风扇等控制气体含量,并向用户发送相应的提示信息。

(4)火焰传感器
火焰传感器可在预防突发事件时,达到可观的预防效果,比如预防家中火灾并由服务器想用户发送相应的提示信息等,达到减少经济损失的功能。

(5)继电器

服务器依据收到的传感器数值,检测是否数值超标,并作出响应继而控制继电器发动电动机,并可依据电机转动时间的多少来达到控制细节。
2.2.2网关Nanopc-t3
Nanopc-t3作为网关,接收协调器传过来的串口信息通过TCP的socket服务发送给处理数据的服务器。
2.2.3Linux服务器
服务器从nanopct3处接收到传感器信息,并对相应的信息进行解析,对传感器状态进行判断,并做出相应的响应,并向用户发送提示信息。
3、系统设计

系统主框架
3.1系统结构设计
3.1.1Zigbee终端设计
Zigbee终端传感器检测环境数据,并通过zigbee无线网络发送到协调器处,也可接收协调器处传来的控制信息(主要体现在继电器的控制上)。
3.1.1.1zigbee终端的数据封装
Zigbee终端的数据封装格式如下:
一位数据开始位 :!(“!”标识数据头)
一位传感器类型 :1.2.3……(标识相应的终端类型)
十三位数据位 :xxxxx(传感器的数据,如有余则为空即可)
一位状态位 :1或0(标识传感器的状态)
3.1.2协调器设计
协调器负责的功能有下列几项:
1、接收节点信息
2、接收nanopc-t3串口命令
3、发送控制命令
3.1.3nanopct3网关设计
nanopct3网关负责的功能有下列几项:
1、接受协调器传来的串口数据
2、发送串口数据至服务器
3、接收服务器命令
4、通过串口发送服务器命令至协调器
3.1.4用户客户端设计
用户客户端主要的功能有下列几项:
1、用户数量:8位
2、可查询对应节点的信息
3、可查询已有节点信息
4、接收服务器发送的警报信息
3.2数据库结构设计
3.2.1数据表设计
3.2.1.1类型表(category)

数据项 存储结构 默认
id int(4) PRIMARY KEY
cname varchar(20)

3.2.1.2 数据表(datas)

数据项 存储结构 默认
Did int(4)
Dstate tinyint(1)
Sensor varchar(30)
Dtime datetime

3.2.1.3状态表(state)

数据项 存储结构 默认
Sid int(4) PRIMARY KEY
state tinyint(1) PRIMARY KEY

4、系统实现
4.1Zigbee终端实现
4.1.1温湿度传感器

本实验使用的温湿度传感器件是AM2321,所以该器件的具体实现如下:



在Zigbee网络中发送函数GenericApp_SendTheMessage处理如下:


端口初始化:

4.1.2光照强度传感器
本实验使用的温湿度传感器件是002E,所以该器件的具体实现如下:

在Zigbee网络中发送函数GenericApp_SendTheMessage处理如下:

端口初始化如下:

4.1.3烟雾传感器
本实验使用的温湿度传感器件是002E,所以该器件的具体实现如下:

在Zigbee网络中发送函数GenericApp_SendTheMessage处理如下:

端口初始化如下:

4.1.4火焰传感器实现
由于本实验实现时,难以用到火焰检测,故用按键模拟火焰传感器的整个过程。
注册火焰按键事件:

模拟事件发生:


端口初始化:

4.1.5继电器实现
继电器初始化配置:

继电器接收相应的处理命令,做出相应处理:

4.2Zigbee协调器实现
4.2.1协调器的接收处理
将接收的信息发送给nanopxt3网关:

4.2.2协调器的发送处理
将从nanopct3串口(通过串口回调函数)接收到的信息发送出去:

4.3nanopct3网关实现
Nanopct3网关的具体实现如下(通过socket与服务器建立网络连接,串口与协调器建立连接):

 #include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<unistd.h>
#include<assert.h>
#include<termios.h>
#include<string.h>
#include<sys/time.h>
#include<sys/types.h>
#include<errno.h> /*串口头文件*/#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>/*socket头文件*/#define BUFFER_SIZE 1024    /*文件大小*/static int ret;
static int fd;#define BAUD_RATE_115200      115200              //波特率为      115200
#define BAUD_RATE_19200        19200              //波特率为      19200
#define DATA_BITS_8             8                   //数据位为      8
#define STOP_BITS_1             1                   //停止位为      1
#define PARITY_N                'N'                   //奇偶校验位 无 /************************************************************* * * 函数名:    safe_write(安全写函数) * * 功 能:   安全写入,如果被中断,则会重新开始写入 * * 参 数:   @int fd:               将要读取数据的文件描述词。 * *           @const void *vptr:     要写入的字符串 * *         @size_t n:             写入的长度 * * 返回值: n : 写入的长度 * *         -1: 写入出错,(常见原因:磁盘空间满了或者超过了文件大小限制) * *************************************************************/ ssize_t safe_write(int fd, const void *vptr, size_t n)
{size_t nleft;      //要写入的长度 ssize_t nwritten;  //获取write()返回,接收写入成功的位数 const char *ptr; //要写入的数据 ptr = vptr; nleft = n; while(nleft > 0) {if((nwritten = write(fd, ptr, nleft)) <= 0)     //write()写入成功时,会返回写入的数量;否则,返回-1        {if(nwritten < 0 && errno == EINTR)            //如果出错,则写入的数据nwritten为0。(errno 由系统保存的最新的错误值, EINTR 系统中断调用)nwritten = 0;elsereturn -1; }nleft -= nwritten;            //减去已经写入的长度 ptr += nwritten;          //更新指针指向下次要写入的部分 } return(n);                       //写入完成,则返回写入长度
} /************************************************************* * * 函数名:    uart_write(串口写函数) * * 功 能:   串口写入数据 * * 参 数:  @int fd:               将要读取数据的文件描述词。 * *           @char *w_buf:          要写入的字符串 * *         @size_t len:           写入的长度 * * 返回值: n : 写入的长度 * *         -1: 写入出错,(常见原因:磁盘空间满了或者超过了文件大小限制) * *************************************************************/
int uart_write(int fd,const char *w_buf,size_t len)
{ssize_t cnt = 0; cnt = safe_write(fd,w_buf,len);         //调用safe_write()函数,成功写入时,则会返回写入数据的长度。否则,返回-1 if(cnt == -1){fprintf(stderr,"write error!\n");   //写入出错的信息反馈return -1; } return cnt;
} /************************************************************* * * 函数名:    safe_read(安全读函数) * * 功 能:    安全读取,如果被系统中断,则重新读取 * * 参 数:    @int fd:               将要读取数据的文件描述词 * *            @const void *vptr:     存放读取到的数据的缓冲区 * *            @size_t n:             读取的长度 * * 返回值: n : 读取到的长度 * *            -1: 读取出错 * *************************************************************/
ssize_t safe_read(int fd,void *vptr,size_t n)
{size_t nleft;          //读取的长度 ssize_t nread;          //读取成功返回的长度;失败则返回-1 char *ptr;               //读取的数据所存放的缓冲区 ptr=vptr; nleft=n; while(nleft > 0) {if((nread = read(fd,ptr,nleft)) < 0){if(errno == EINTR)      //被信号中断,则读取不成功nread = 0; else return -1; } else if(nread == 0)break; nleft -= nread;                //剩下还要读取的数据长度 ptr += nread;               //更新下次要读取的起始位置 } return (n-nleft);
} /************************************************************* * * 函数名:    uart_read(串口读函数) * * 功 能:    串口读取数据 * * 参 数:  @int fd:               将要读取数据的文件描述词 * *            @char *r_buf:          存放读取到的数据的缓冲区 * *            @size_t n:             读取的长度 * * 返回值: n : 读取到的长度 * *            -1: 读取出错 * *************************************************************/ int uart_read(int fd,char *r_buf,size_t len)
{ssize_t cnt = 0; fd_set rfds;             //定义一个文件描述符集合的结构体 struct timeval time;      //时间结构体 两个成员变量:@__time_t tv_sec 秒 @__suseconds_t tv_usec 微妙 /*将文件描述符加入读描述符集合*/ FD_ZERO(&rfds);             //将rfds清零,集合不包含任何fd FD_SET(fd,&rfds);            //将fd加入set集合 /*设置超时为30s*/ time.tv_sec = 30;         time.tv_usec = 0; /*实现串口的多路I/O*/ ret = select(fd+1,&rfds,NULL,NULL,&time); switch(ret){case -1: fprintf(stderr,"select error!\n"); return -1; case 0: fprintf(stderr,"time over!\n"); return -1; default: cnt = safe_read(fd,r_buf,len);           //调用安全读取函数safe_read(),返回成功读取数据的长度 if(cnt == -1) {fprintf(stderr,"read error!\n");return -1;}return cnt; }
} /************************************************************* * * 函数名:    uart_open(串口打开文件函数) * * 功 能: 打开串口对应的设备驱动文件 * * 参 数:   @int fd:               将要读取数据的文件描述词 * *            @char *pathname:       文件路径 * * 返回值: fd :   文件描述符 * *           -1 :    串口文件打开出错 * *************************************************************/
int uart_open(int fd,const char *pathname)
{assert(pathname); /*打开串口   设置文件权限参数:    O_RDWR 读写方式     O_NOCTTY 若文件为终端,那么该终端不会成为调用open()的那个进程的控制终端  O_NONBLOCK 使I/O编程非阻塞模式,在读取不到数据或写入缓冲区已满会马上return,不会阻塞  */ fd = open(pathname,O_RDWR|O_NOCTTY|O_NONBLOCK);          if(fd == -1){perror("Open UART failed!"); return -1; } /*清除串口非阻塞标志*/ if(fcntl(fd,F_SETFL,0) < 0)            //指定文件描述的各种操作,(F_SETFL : 设置文件状态标识){fprintf(stderr,"fcntl failed!\n");return -1; } return fd;
} /************************************************************* * * 函数名:    uart_set(串口配置函数) * * 功 能:    配置串口的波特率、数据位、停止位、奇偶校验位、流控 * * 参 数:   @int serial_fd:                串口文件描述符 * *         @int nSpeed:               波特率 * *         @int nBits:                    数据位 * *         @char nEvent:              奇偶校验位 * *           @int nStop:                    停止位 * * 返回值: fd :    文件描述符 * *           -1 :    串口文件打开出错 * *************************************************************/
int uart_set(int serial_fd, int nSpeed, int nBits, char nEvent, int nStop)
{struct termios newtio,oldtio;              //  /*保存测试现有串口参数设置,在这里如果串口号等出错,会有相关的出错信息*/    if( tcgetattr( serial_fd,&oldtio) != 0){printf("[FALSE] Funtion tcgetattr( serial_fd,&oldtio) -> %d\n",tcgetattr( serial_fd,&oldtio));return -1;}     /*结构体初始化为0*/    bzero( &newtio, sizeof( newtio ) );     /*设置字符大小,关流控     CLOCAL: 忽略所有调制解调器的状态行   CREAD:  启用字符接收器     CRTSCTS:启动流控    CSIZE:  启用字符大小位     */  newtio.c_cflag |= CLOCAL | CREAD ;     //设置newtio的控制模式c_cflag,启动字符接收器和忽略所有调制解调器的状态行     newtio.c_cflag &= ~CSIZE;                  //关闭字符大小位   newtio.c_cflag  &= ~CRTSCTS;               //关闭流控  /*设置数据位*/   switch( nBits ){case 7:newtio.c_cflag |= CS7;printf(" Set nBits 7!\n");break;case 8:newtio.c_cflag |= CS8;printf(" Set nBits 8!\n");break;    default:newtio.c_cflag |= CS8;printf(" Set nBits 8!\n");break;}  /*设置奇偶校验位*/switch( nEvent ){case 'o':case 'O': //奇数newtio.c_cflag |= PARENB; //启动奇偶校验newtio.c_cflag |= PARODD; //只使用奇校验printf(" Set nEvent O!\n");break;case 'e':case 'E': //偶数newtio.c_cflag |= PARENB; //启动奇偶校验newtio.c_cflag &= ~PARODD; //只使用偶校验printf(" Set nEvent E!\n");break;case 'n':case 'N': //无奇偶校验位newtio.c_cflag &= ~PARENB;printf(" Set nEvent N!\n");break; default:newtio.c_cflag &= ~PARENB;printf(" Set nEvent N!\n");break;   }   /*设置波特率*/   switch( nSpeed ){case 2400:cfsetispeed(&newtio, B2400);cfsetospeed(&newtio, B2400);printf(" Set nSpeed 2400!\n");break;case 9600:cfsetispeed(&newtio, B9600);cfsetospeed(&newtio, B9600);printf(" Set nSpeed 4800!\n");break;case 19200:cfsetispeed(&newtio, B19200);cfsetospeed(&newtio, B19200);printf(" Set nSpeed 9600!\n");break;case 57600:cfsetispeed(&newtio, B57600);cfsetospeed(&newtio, B57600);printf(" Set nSpeed 57600!\n");break;case 115200:cfsetispeed(&newtio, B115200);cfsetospeed(&newtio, B115200);printf(" Set nSpeed 115200!\n");break;default:cfsetispeed(&newtio, B115200);cfsetospeed(&newtio, B115200);printf(" Set nSpeed 115200!\n");break;    }   /*设置停止位 CSTOPB:10B */if( nStop == 1 ){newtio.c_cflag &= ~CSTOPB;printf(" Set nStop 1!\n");}else if ( nStop == 2 ){newtio.c_cflag |= CSTOPB;printf(" Set nStop 2!\n");  }elseprintf("[FLASE]   Set nStop erroe!\n");  /*设置等待时间VTIME和最小接收字符VMIN*/newtio.c_cc[VTIME] = 0;newtio.c_cc[VMIN] = 0;printf(" Set VTIME=0,VMIN=0 !\n");     /*处理未接收字符*/tcflush(serial_fd,TCIFLUSH);printf(" Flush char of not handle!\n");    /*激活新配置TCSANOW立刻修改*/if((tcsetattr(serial_fd,TCSANOW,&newtio))!=0){perror("[FLASE] Set newtio!\n");return -1;}elseprintf(" Set newtio!\n");return 0;
} /************************************************************* * * 函数名:    uart_close(串口关闭函数) * * 功 能:  关闭串口 * * 参 数:    @int fd:               串口文件描述符 * * 返回值: 0 :     关闭成功* *************************************************************/
int uart_close(int fd)
{assert(fd);close(fd); /*可以在这里做些清理工作*/return 0;
}int main(void)
{const char w_buf[128] = {"T3:Hello!\n"};    //写入缓冲区 size_t w_len = strlen(w_buf); char r_buf[BUFFER_SIZE];         //读取缓冲区 bzero(r_buf,BUFFER_SIZE); //初始化为0   //打开串口对应的设备驱动文件 fd = uart_open(fd,"/dev/ttySAC2");/*串口驱动文件 */ if(fd == -1){fprintf(stderr,"uart_open error\n");exit(EXIT_FAILURE);}  //配置串口参数:波特率:115200       数据位:8位       奇偶校验位:无      停止位:1位 if(uart_set(fd,BAUD_RATE_115200, DATA_BITS_8, PARITY_N, STOP_BITS_1) == -1){fprintf(stderr,"uart set failed!\n");exit(EXIT_FAILURE);}     //串口写入信息 T3:Hello! /*socket配置*/struct sockaddr_in server_addr;server_addr.sin_family = AF_INET;server_addr.sin_port = htons(11332);server_addr.sin_addr.s_addr = inet_addr("192.168.8.137");bzero(&(server_addr.sin_zero), 8);/*创建socket套接字*/int server_sock_fd = socket(AF_INET, SOCK_STREAM, 0);if(server_sock_fd == -1){perror("socket error");return 1;}char recv_msg[BUFFER_SIZE];char input_msg[BUFFER_SIZE] = "Hallo server!";ret = uart_write(fd,w_buf,w_len);if(ret == -1){fprintf(stderr,"uart write failed!\n");exit(EXIT_FAILURE);}if(connect(server_sock_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) == 0){fd_set client_fd_set;/*新建文件集*/struct timeval tv;while(1){tv.tv_sec = 10;tv.tv_usec = 0;FD_ZERO(&client_fd_set);FD_SET(server_sock_fd, &client_fd_set);select(server_sock_fd + 1, &client_fd_set, NULL, NULL, &tv);/*select检测*/bzero(r_buf, BUFFER_SIZE);if(ret = uart_read(fd,r_buf,1024) == -1){fprintf(stderr,"uart read failed!\n");exit(EXIT_FAILURE);}printf("uart: %s\n",r_buf);if(send(server_sock_fd,r_buf, 16 , 0) == -1){perror("发送消息出错!\n");}printf("send seccessful!!\n");if(FD_ISSET(server_sock_fd, &client_fd_set)){bzero(recv_msg, BUFFER_SIZE);long byte_num = recv(server_sock_fd, recv_msg, BUFFER_SIZE, 0);                                                                 if(byte_num > 0)                                                                                                                {if(byte_num > BUFFER_SIZE){byte_num = BUFFER_SIZE;}recv_msg[byte_num] = '\0';printf("服务器信息:%s\n", recv_msg);if(recv_msg[0] == '1'){/*发送给协调器*/uart_write(fd,"1",1);}}else if(byte_num < 0)                                                                                                           {                                                                                                                               printf("接受消息出错!\n");}else                                                                                                                            {printf("服务器端退出!\n");exit(0);}                                                                                                                               }                                                                                                                                   }}                                                                                                                                       //关闭文件 ret = uart_close(fd);if(ret == -1){fprintf(stderr,"uart_close error\n");exit(EXIT_FAILURE);} exit(EXIT_SUCCESS);
}

4.4Linux服务器实现
服务器负责将从网关接收到的数据进行解析,并做出相应的处理与发送报警信息给用户:

#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>  #include <mysql/mysql.h>#define BACKLOG 5     /*完成三次握手但没有accept的队列的长度 */
#define CONCURRENT_MAX 8   /*应用层同时可以处理的连接 */
#define SERVER_PORT 11332
#define BUFFER_SIZE 1024
#define QUIT_CMD ".quit"#define HOST "localhost"/*数据库*/
#define USERNAME "root"
#define PASSWORD "lzx19950822"
#define DATABASE "zigbee"  int client_fds[CONCURRENT_MAX]; int main(int argc, const char * argv[])
{  int i,num;char input_msg[BUFFER_SIZE];  char recv_msg[BUFFER_SIZE];  MYSQL mysqlfd;/*数据库*/mysql_init(&mysqlfd);char *sql;int seccess;char strr[200];/*sprintf函数*/char temp[13],smoke[7],lux[7],flam[13];/*本地地址  */struct sockaddr_in server_addr;  server_addr.sin_family = AF_INET;  server_addr.sin_port = htons(SERVER_PORT);  server_addr.sin_addr.s_addr = INADDR_ANY;//inet_addr("192.168.8.130");  bzero(&(server_addr.sin_zero), 8);  /*创建socket  */int server_sock_fd = socket(AF_INET, SOCK_STREAM, 0);  if(server_sock_fd == -1)  {  perror("socket error");  return 1;  }  /*绑定socket  */int bind_result = bind(server_sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));  if(bind_result == -1)  {  perror("bind error");  return 1;  }  /*listen  */if(listen(server_sock_fd, BACKLOG) == -1)  {  perror("listen error");  return 1;  }  /*fd_set  */fd_set server_fd_set;  int max_fd = -1;  struct timeval tv;  /*超时时间设置  */while(1)  {  tv.tv_sec = 20;  tv.tv_usec = 0;  FD_ZERO(&server_fd_set);  FD_SET(STDIN_FILENO, &server_fd_set);  if(max_fd <STDIN_FILENO)  {  max_fd = STDIN_FILENO;  }  /*printf("STDIN_FILENO=%d\n", STDIN_FILENO);  *//*服务器端socket  */FD_SET(server_sock_fd, &server_fd_set);  /* printf("server_sock_fd=%d\n", server_sock_fd);*/  if(max_fd < server_sock_fd)  {  max_fd = server_sock_fd;  }  /*客户端连接  */for( i =0; i < CONCURRENT_MAX; i++)  {  /*printf("client_fds[%d]=%d\n", i, client_fds[i]);  */if(client_fds[i] != 0)  {  FD_SET(client_fds[i], &server_fd_set);  if(max_fd < client_fds[i])  {  max_fd = client_fds[i];  }  }  }  int ret = select(max_fd + 1, &server_fd_set, NULL, NULL, &tv);  if(ret < 0)  {  perror("select 出错\n");  continue;  }  else if(ret == 0)  {  //printf("select 超时\n");  continue;  }  else  {  /*ret 为未状态发生变化的文件描述符的个数  */if(FD_ISSET(STDIN_FILENO, &server_fd_set))  {  printf("发送消息:\n");  bzero(input_msg, BUFFER_SIZE);  fgets(input_msg, BUFFER_SIZE, stdin);  /*输入“.quit"则退出服务器  */if(strcmp(input_msg, QUIT_CMD) == 0)  {  exit(0);  }  for( i = 0; i < CONCURRENT_MAX; i++)  {  if(client_fds[i] != 0)  {  printf("client_fds[%d]=%d\n", i, client_fds[i]);  send(client_fds[i], input_msg, BUFFER_SIZE, 0);  }  }  }  if(FD_ISSET(server_sock_fd, &server_fd_set))  {  /*有新的连接请求  */struct sockaddr_in client_address;  socklen_t address_len;  int client_sock_fd = accept(server_sock_fd, (struct sockaddr *)&client_address, &address_len);  printf("new connection client_sock_fd = %d\n", client_sock_fd);  if(client_sock_fd > 0)  {  int index = -1;  for(i = 0; i < CONCURRENT_MAX; i++)  {  if(client_fds[i] == 0)  {  index = i;  client_fds[i] = client_sock_fd;  break;  }  }  if(index >= 0)  /*连接成功*/{  printf("新客户端(%d)加入成功 %s:%d\n", index, inet_ntoa(client_address.sin_addr), ntohs(client_address.sin_port));  }  else  {  bzero(input_msg, BUFFER_SIZE);  strcpy(input_msg, "服务器加入的客户端数达到最大值,无法加入!\n");  send(client_sock_fd, input_msg, BUFFER_SIZE, 0);  printf("客户端连接数达到最大值,新客户端加入失败 %s:%d\n", inet_ntoa(client_address.sin_addr), ntohs(client_address.sin_port));  }  }  }  for( i =0; i < CONCURRENT_MAX; i++)  {  if(client_fds[i] !=0)  {  if(FD_ISSET(client_fds[i], &server_fd_set))  {if(fork() == 0){  /*处理某个客户端过来的消息  */bzero(recv_msg, BUFFER_SIZE);  long byte_num = recv(client_fds[i], recv_msg, BUFFER_SIZE, 0);  if (byte_num > 0)  {  if(byte_num > BUFFER_SIZE)  {  byte_num = BUFFER_SIZE;  }    recv_msg[byte_num] = '\0';  printf("客户端(%d):%s\n", i, recv_msg); //连接数据库if(mysql_real_connect(&mysqlfd,HOST,USERNAME,PASSWORD,DATABASE,0,NULL,CLIENT_FOUND_ROWS)){printf("!!!connect mysql success!\n");if(recv_msg[0] == '!')/*数据判断与写入*/{if(recv_msg[1] == '1')/*温湿度传感器*/{for(num = 0;num < 13;num++){temp[num] = recv_msg[num + 2];}sprintf(strr, "insert into  datas values('%c','%c','%s',NOW());",recv_msg[1],recv_msg[15],temp);if(temp[0] > '8'){for( i = 0; i < CONCURRENT_MAX; i++){if(client_fds[i] != 0){printf("infor client_fds[%d]=%d\n", i, client_fds[i]);send(client_fds[i],"WARING!! HUMIDITY 80% HIGHT!!",29, 0);}}     }}if(recv_msg[1] == '2')/*烟雾传感器*/{for(num = 0;num < 8;num++){smoke[num] = recv_msg[num + 2];}sprintf(strr, "insert into  datas values('%c','%c','%s',NOW());",recv_msg[1],recv_msg[15],smoke);if(smoke[0] != 0)    {for( i = 0; i < CONCURRENT_MAX; i++){if(client_fds[i] != 0){printf("infor client_fds[%d]=%d\n", i, client_fds[i]);send(client_fds[i],"WARING!! SMOKE HIGHT!!",22, 0);}}}}if(recv_msg[1] == '3')/*光照传感器*/{for(num = 0;num < 8;num++){lux[num] = recv_msg[num + 2];}sprintf(strr, "insert into  datas values('%c','%c','%s',NOW());",recv_msg[1],recv_msg[15],lux);if(lux[0] != 0){for( i = 0; i < CONCURRENT_MAX; i++){if(client_fds[i] != 0){printf("infor client_fds[%d]=%d\n", i, client_fds[i]);send(client_fds[i],"WARING!! Lux HIGHT!!",20, 0);}}}}if(recv_msg[1] == '4')/*火焰传感器*/{for(num = 0;num < 13;num++){flam[num] = recv_msg[num + 2];}sprintf(strr, "insert into  datas values('%c','%c','%s',NOW());",recv_msg[1],recv_msg[15],flam);if(recv_msg[15] == '1'){for( i = 0; i < CONCURRENT_MAX; i++){if(client_fds[i] != 0){printf("Flam Beeping!!\n");send(client_fds[i],"1Flam Beeping!!",15,0);}}}}}sql=strr;mysql_query(&mysqlfd , "set names utf8");/*设置编码,防止中文乱码*/seccess=mysql_query(&mysqlfd,sql);/*写入数据库*/if(seccess){printf("!!!Insert Error!\n");seccess=mysql_query(&mysqlfd,sql);}else{printf("!!!Insert Success!\n");}}else{printf("!!!Connect mysql Failed!\n");exit(-1);}                                     }  else if(byte_num < 0)  /*退出连接*/{  printf("从客户端(%d)接受消息出错.\n", i);  }  else  {  FD_CLR(client_fds[i], &server_fd_set);  client_fds[i] = 0;  printf("客户端(%d)退出了\n", i);  }}  }  }  }  }  }  return 0;
}

4.5客户端的实现

客户端可查询传感器节点信息与传感信息,并可接收服务器的警报:#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql/mysql.h>  #include<netinet/in.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<unistd.h>  #define BUFFER_SIZE 1024  int main()
{  int sccess = 0;int cmd;  MYSQL mysql;  MYSQL * mysqlconnect = NULL;  const char * query;struct sockaddr_in server_addr;  server_addr.sin_family = AF_INET;  server_addr.sin_port = htons(11332);  server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  bzero(&(server_addr.sin_zero), 8);  int server_sock_fd = socket(AF_INET, SOCK_STREAM, 0);  if(server_sock_fd == -1)  {  perror("socket error");  return 1;  }  char recv_msg[BUFFER_SIZE];  char input_msg[BUFFER_SIZE];  mysqlconnect = mysql_init(&mysql);  if(mysqlconnect == NULL){  sccess = mysql_errno(&mysql);  printf("mysql_init error, %s\n", mysql_error(&mysql));  return sccess;  }  printf("mysql_init ok...\n");  mysqlconnect = mysql_real_connect(mysqlconnect, "localhost", "root", "lzx19950822", "zigbee", 0, NULL, CLIENT_FOUND_ROWS);  if(mysqlconnect == NULL){  sccess = mysql_errno(&mysql);  printf("mysql_real_connect error, err is: %s\n", mysql_error(&mysql));  return sccess;  }  printf("mysql_real_connect ok...\n");  if(connect(server_sock_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) == 0)  {fd_set client_fd_set;  struct timeval tv; while(1)  {  tv.tv_sec = 20;  tv.tv_usec = 0;  FD_ZERO(&client_fd_set);  FD_SET(server_sock_fd, &client_fd_set);  /*数据库查询*/printf("*******************************************\n");printf("*       1.查询温湿度传感器数据            *\n");printf("*       2.查询烟雾传感器数据              *\n");printf("*       3.查询光强传感器数据              *\n");printf("*       4.查询火焰传感器状态              *\n");printf("*       5.查询全部传感器状态数据          *\n");printf("*       6.查询已拥有的传感器              *\n");printf("*******************************************\n");printf("input:");scanf("%d",&cmd);//fgets(cmd,1, stdin);  if(cmd == 1)query = "select * from datas where Did=1";if(cmd == 2)query = "select * from datas where Did=2";if(cmd == 3)query = "select * from datas where Did=3";if(cmd == 4)query = "select * from datas where Did=4";if(cmd == 5)query = "select * from datas";if(cmd == 6)query = "select * from category";sccess = mysql_query(mysqlconnect, query);  if(sccess != 0){  printf("mysql_query error\n");  return sccess;  }  MYSQL_RES *result = mysql_store_result(&mysql);  if(result == NULL){  printf("mysql_store_result error\n");  return -1;  }  int field_num = mysql_field_count(&mysql);  /*表头 */   MYSQL_FIELD * fields = mysql_fetch_fields(result);  int i = 0;  printf("------------------------------------------\n");  for(i= 0; i < field_num; i++){  printf("%s \t", fields[i].name);   }  printf("\n------------------------------------------\n");  /*表内容 */   MYSQL_ROW row = NULL;  while(row = mysql_fetch_row(result)){  for(i= 0; i < field_num; i++){  printf("%s \t", row[i]);   }  printf("\n");  }  mysql_free_result(result);//释放内存  printf("\n------------------------------------------\n"); select(server_sock_fd + 1, &client_fd_set, NULL, NULL, &tv);  if(FD_ISSET(server_sock_fd, &client_fd_set))  {  bzero(recv_msg, BUFFER_SIZE);  long byte_num = recv(server_sock_fd, recv_msg, BUFFER_SIZE, 0);  if(byte_num > 0)  {  if(byte_num > BUFFER_SIZE)  {  byte_num = BUFFER_SIZE;  }  recv_msg[byte_num] = '\0';  printf("服务器:%s\n", recv_msg);  }  else if(byte_num < 0)  {  printf("接受消息出错!\n");  }  else  {  printf("服务器端退出!\n");  exit(0);  }  }  }}mysql_close(mysqlconnect);  printf("mysql_close...\n");  return sccess;
}

5、总结

本系统使用当前流行的ARM Cortex-A53架构芯片S5P6818,并移植功能强大的linux操作系统,实现zigbee网关。为将zigbee无线传感器网络数据传输到互联网提供了一套可行的解决方案。结果表明,此网关系统稳定性高,并具备数据错误检测和纠正能力。由于将传感器数据存储到数据库中,数据的查询和分析都变得非常简单,提高了数据的利用率。

智能家居安防系统设计--期末作业相关推荐

  1. python基于模糊推理的智能家居安防系统设计

    这篇是以前写的. 参考论文为黄明明2019年发表在<河南工程学院:自然科学版>. 摘要:为提高家居生活品质和安全,设计了一种基于模糊推理的智能家居安防系统,有效实现了家居生活的防火.防盗和 ...

  2. 基于CAN总线的家居安防系统设计

    现在,人们对工作和生活环境不仅要求舒适健康.可靠便利,而且更加看重安全性,并利用安防系统来提高家庭抵御各种意外情况的能力.现在的安防系统可借助计算机技术.IC卡技术.通信技术等来实现-- 1引言 现在 ...

  3. 打造智能家居安防系统 七个选购常识你需懂

    公安部统计,每年因入室盗窃造成的家庭损失高达11300亿元,特别是随着拆围墙.建开放型社区政策执行之后,社区盗窃偷盗机率将会暴增,城市家庭安防的需求会更加旺盛.近年来,住宅智能家居安防系统,已成为开发 ...

  4. 浅谈智能家居安防监控的重要性

    2019独角兽企业重金招聘Python工程师标准>>> 智能家居监控安防有多重要?有些人将之比作保险,认为出事了有用,没出事则无用武之地,而这种想法也常会形成一个错误的逻辑:家里一般 ...

  5. 基于51单片机的智能家居安防系统(程序+仿真+PCB)

    @TOC 一.基于51单片机的智能家居安防系统 1.主要功能 通过人体红外检测模块.光敏传感器.蜂鸣器.继电器模块模拟智能家居安防功能. 2.实验结果 3.实验仿真 4.程序源码 /********* ...

  6. 单片机反相器_基于AT89S52单片机的新型智能家居安防系统

    现在,人们对工作和生活环境不仅要求舒适健康.可靠便利,而且更加看重安全性,并利用安防系统来提高家庭抵御各种意外情况的能力.现在的安防系统可借助计算机技术.IC 卡技术.通信技术等来实现,CAN总线应用 ...

  7. c语言智能家居安防系统,智能家居之安防智能控制系统

    家是我们的避风港湾,家里藏着的都是我们生命里所有最宝贵的东西.所以家应该是温馨的,温暖的更应该是安全的.最近新出了一部电影<找到你>讲述的是姚晨主演的主角孩子在家里失踪的故事.孩子在家里失 ...

  8. 智能家居安防整体解决方案

    对于有些人来说,智能家居只是增添华丽的装饰.高端的电器和昂贵的陈设.但对于另部分人来说,智能家居则意味着利用最新的控制科技提高个人生活品味的同时,提高家居安全防范能力. 我们可以称之为"智能 ...

  9. 万物互联时代,智能家居安防的核心是什么?

    21世纪是信息的时代,网络.微电子.光电.通信等高新技术飞速发展,安防系统也随着信息技术及整个信息产业的发展浪潮,由原来的模拟产品逐步过渡到数字化.网络化.智能化监控产品.与此同时,人民生活水平的提高 ...

最新文章

  1. JS中Base64的编码与解码
  2. .Net业务搭配实用技术栈
  3. SnapGene mac 5.3.1 中文分子生物学可视化工具及教程
  4. ifconfig输出网口和ip
  5. Java 用DBCP连接数据库。
  6. 如何使用iMovie对抖动视频进行防抖处理?
  7. C#中的正则表达式 \(([^)]*)\) 详解
  8. 计算机开机画面怎么有2个用户,win7开机画面有两个用户登录 ,怎么样隐藏其中一个(管理员帐号)...
  9. mysql hsqldb_HSQLDB的使用方法
  10. 单词记忆法,由遗忘曲线制定而成
  11. openwrt默认mac地址配置(MT7620a)
  12. java上GUI表格按钮_Java swing选项卡中有表格,表格中有按钮,按钮按不到
  13. Typescript 2+迷你书 :从入门到不放弃
  14. ubuntu下没有中文输入法的解决办法!
  15. tcpdump、nc
  16. Redis-狂神笔记-菜鸟风闲整理
  17. 解决win10资源管理器关后电脑黑屏问题
  18. 网页色彩搭配教程:三个实用方法搞定网页配色设计
  19. ZDNS联合发起创建的“粤港大数据图像和通信应用联合实验室”成功获批
  20. 眼睛疲劳及干涩的防治

热门文章

  1. int、long int 和 long long int 的取值范围
  2. TensorFlow Lite 指导
  3. 装饰者模式及其在 Android Context 中的应用
  4. 仿 iPhone Assistivetouch 自定义view
  5. javascript代码重构之:写好函数
  6. Gradle 安装与配置
  7. 开源堡垒机是什么?开源堡垒机的优缺点是什么?
  8. 微信论坛【申明:来源于网络】
  9. ubuntu mate linux,Ubuntu MATE 18.10 正式发布
  10. 网络通信-滑动窗口协议-SWP