ZigBee+Linux+QT搭建自动喷淋系统
本文提出了一种基于嵌入式Linux与ZigBee技术的花园自动喷淋系统,通过无线传感器网络技术和嵌入式系统编程、嵌入式网络技术的结合,构建一套针对自动灌溉领域应用的远程智能管理系统。
该系统通过ZigBee技术实现远程数据的采集及控制命令的传输,采用CC2530模块作为控制装置的核心,外接温度传感器、土壤湿度传感器、光照强度传感器、烟雾气体浓度传感器、继电器模块分别实现数据的采集和灌溉控制;网关以A9系列的FS4412开发板作为主控模块,采用Linux操作系统作为软件系统,并在该操作系统上通过网络编程技术编写了登录注册服务器、摄像头服务器、串口服务器等网络管理代码,实现了网关服务器的搭建。网关数据最终传输到QT客户端进行进一步的分析及显示,QT客户端提供了良好的UI界面,方便用户进行人机交互。
系统设计方案
设计本系统总计框架如图所示,主要由数据采集终端模块,网关模块和PC客户端模块组成。该设计使用Linux操作系统网络编程技术,程序实现TCP服务器,Linux操作系统移植到FS4412开发板,完成对QT客户端的远程接入,数据终端环境数据通过ZigBee协议栈自主网络,传输信息数据到协调器节点,协调器与ARM框架A9系列的FS4412开发板之间使用UART传输数据,实现硬件模块的通信和控制。
数据采集终端模块
由环境信息采集传感器、CC2530主控芯片,喷淋装置,电源管理模块构成。传感器部件包括温度传感器、土壤湿度传感器、光照传感器,以获取当前植物生长的土壤湿度,环境温度,光照强度。喷淋装置通过继电器控制,连接电源,水泵开始正常工作,通过喷头进行喷淋灌溉。数据采集终端硬件硬件设计图(包含传感器硬件选型)如下所示
开发环境
Ubuntu20.04:VMware Workstation Pro搭载的Linux操作系统,用来搭建串口通信和数据处理,登录注册,视频监控 的服务器。
QT4.6.2:QT版本,用来搭建UI界面,方便人机交互。
IAR EW:zigbee系列,CC2530开发板软件开发环境。
软件设计
在系统设计方案和硬件选型已经完成的基础上,我们开始进行软件部分的设计。为更好区分各功能模块,软件设计部分分别搭建三个独立运行的功能服务器端,最后在QT客户端实现完整的功能。
Ubuntu20.04环境下程序设计
登录注册
login.c
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <strings.h>
#include <time.h>
#include <stdlib.h>
//搭建tcp服务器
int main(void)
{
int sockfd,connfd;
int ret;
sockfd = socket(AF_INET,SOCK_STREAM , 0); //买手机
//如果成功就返回生成的SOCKET,如果失败就返回INVALID_SOCKET(-1)
if(sockfd == -1)
{
perror("socket error");
return 1;
}
//卡 addr
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(5555);
addr.sin_addr.s_addr = inet_addr("0");
ret = bind(sockfd,(struct sockaddr *)&addr,sizeof(addr)); //插卡
//listen函数的第一个参数即为要监听的socket描述字,第二个参数为相应socket可以排队的最大连接个数。
listen(sockfd,5); //开机
if(listen(sockfd,5) == -1)
{
perror("listen error");
return 1;
}
while(1)
{
connfd = accept(sockfd,NULL,NULL); //接听
if(connfd<0)
{
perror("accpet() failed");
return 1;
}
printf("链接成功\n");
while(1)
{
char buf[256];
char str1[32]; //注册账号
char str2[32]; //注册密码
char str3[32]; //登陆账号
char str4[32]; //登陆密码
//超级用户
char root[255] = "root";
char m[255] = "abc";
bzero(buf,sizeof(buf)); //清空数组
ret = recv(connfd,buf,sizeof(buf),0);
if(ret<=0){
printf("client quit\n");
break;
}
if(strcmp(buf,"1") == 0) {
bzero(str1,sizeof(str1));
bzero(str2,sizeof(str2));
recv(connfd,str1,sizeof(str1),0);
recv(connfd,str2,sizeof(str2),0);
printf("\n注册\n帐号/密码\n%s\n%s\n",str1,str2);
bzero(buf,sizeof(buf));
send(connfd,"s",sizeof("s"),0);
//break;
} else if(strcmp(buf,"2") == 0) {
bzero(str3,sizeof(str3));
bzero(str4,sizeof(str4));
recv(connfd,str3,sizeof(str3),0);
recv(connfd,str4,sizeof(str4),0);
bzero(buf,sizeof(buf));
if(( strcmp(str1,str3) == 0) && (strcmp(str2,str4) == 0) || (strcmp(root,str3) == 0) && (strcmp(m,str4) == 0) )
{
printf("\n登陆成功\n");
send(connfd,"l",sizeof("l"),0);
} else {
printf("\n登陆失败\n");
printf("\n帐号/密码\n%s\n%s\n",str3,str4);
send(connfd,"x",sizeof("x"),0);
}
}
else if(strcmp(buf,"3") == 0){
printf("\n退出\n");
}
}
}
return 0;
}
串口控制数据服务器
main.c
#include "serial.h"
int main()
{
int fd=open("/dev/ttyUSB0",O_RDWR|O_NOCTTY);
if(fd<0)
{
printf("fd=%d:open error\n",fd);
perror("open:");
return -1;
}
printf("%d\n",fd);
int ret=set_serial(fd,115200,8,'N',1);
if(ret<0)
{
perror("set_serial:");
return -1;
}
server_init(fd);
}
serial.c
#include "serial.h"
int set_serial(int fd,int nspeed,int nbits,char nevent,int nstop)
{
struct termios newttys1,oldttys1;
//保存原有的串口配置
if(tcgetattr(fd,&oldttys1)!=0)
{
perror("setserial 1\n");
return -1;
}
//恢复串口为阻塞状态
if(fcntl(fd,F_SETFL,0)<0)
{
printf("fcntl failed!\n");
return -1;
}
else
{
printf("fcntl=%d\n",fcntl(fd,F_SETFL,0));
}
bzero(&newttys1,sizeof(newttys1));
//CREAD开启串行数据接收,CLOCAL打开本地连接模式
newttys1.c_cflag|=(CLOCAL|CREAD);
newttys1.c_cflag&=~CSIZE;//设置数据位
//数据位选择
switch(nbits)
{
case 7:
newttys1.c_cflag|=CS7;
break;
case 8:
newttys1.c_cflag|=CS8;
break;
}
//设置奇偶校验位
switch(nevent)
{
case 'O'://奇校验
newttys1.c_cflag |= PARENB;//开启奇偶校验
//INPCK打开输入奇偶校验,ISTRIP去除字符的第八个比特
newttys1.c_iflag |= (INPCK|ISTRIP);
newttys1.c_cflag |= PARODD;//启动奇校验(默认偶校验)
break;
case 'E'://偶校验
newttys1.c_cflag |= PARENB;
newttys1.c_cflag |=(INPCK|ISTRIP);
newttys1.c_cflag &=~PARODD;
break;
case 'N':
newttys1.c_cflag&=~PARENB;
break;
}
//设置波特率
switch(nspeed)
{
case 2400:
cfsetispeed(&newttys1,B2400);
cfsetospeed(&newttys1,B2400);
break;
case 4800:
cfsetispeed(&newttys1,B4800);
cfsetospeed(&newttys1,B4800);
break;
case 9600:
cfsetispeed(&newttys1,B9600);
cfsetospeed(&newttys1,B9600);
break;
case 115200:
cfsetispeed(&newttys1,B115200);
cfsetospeed(&newttys1,B115200);
break;
default:
cfsetispeed(&newttys1,B9600);
cfsetospeed(&newttys1,B9600);
break;
}
//设置停止位,若停止位为1,则清除CSTOPB,若停止位为2,则激活CSTOPB
if(nstop==1)
{
newttys1.c_cflag&=~CSTOPB;
}
else if(nstop==2)
{
newttys1.c_cflag|=CSTOPB;
}
//设置最少字符和等待时间,对于接收字符和等待时间没有特别要求时
newttys1.c_cc[VTIME]=0;//非规范模式读取时的超时时间
newttys1.c_cc[VMIN]=0;//非规范模式读取时的最小字符数
//tcflush清空终端未完成的输入/输出请求及数据;
//TCIFLUSH表示清空正收到的数据,且不读去出来
tcflush(fd,TCIFLUSH);
//激活配置使其生效
if((tcsetattr(fd,TCSANOW,&newttys1))!=0)
{
perror("com set error");
return -1;
}
return 0;
}
serial.h
#ifndef _SERIAL_H_
#define _SERIAL_H_
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
int server_init(int fd);
int set_serial(int fd,int nspeed,int nbits,char nevent,int nstop);
#endif
server.c
#include "serial.h"
unsigned char envbuf[15]={0};
int server_init(int fd)
{
int sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd<0)
{
perror("socket");
return -1;
}
struct sockaddr_in seraddr;
struct sockaddr_in cliaddr;
socklen_t len=sizeof(cliaddr);
bzero(&seraddr,sizeof(seraddr));
bzero(&cliaddr,sizeof(cliaddr));
seraddr.sin_family=AF_INET;
seraddr.sin_port=htons(7777);
seraddr.sin_addr.s_addr=inet_addr("0");
if(bind(sockfd,(const struct sockaddr*)&seraddr,sizeof(seraddr))<0)
{
perror("bind");
return -1;
}
if(listen(sockfd,5)<0)
{
perror("listen");
return -1;
}
int connfd=accept(sockfd,(struct sockaddr*)&cliaddr,&len);
if(connfd<0)
{
perror("accept");
return -1;
}
printf("%s:%d connected!!\n",inet_ntoa(cliaddr.sin_addr),ntohs(cliaddr.sin_port));
char buf[32]={0};
int ret;
while(1)
{
if((ret=read(connfd,buf,sizeof(buf)))>0)
{
if(strncmp(buf,"env",3)==0)
{
bzero(envbuf,sizeof(envbuf));
//send 环境
if(read(fd,envbuf,sizeof(envbuf))==sizeof(envbuf));
{
printf("=====%s=====\n", envbuf);
int ret = write(connfd,envbuf,sizeof(envbuf));
if(ret<0)
{
perror("write");
exit(-1);
}
printf("ret = %d\n", ret);
}
}
else if(strncmp(buf,"auto_on",7)==0)
{
//发送命令,开启自动喷淋模式
envbuf[0]=0xdd;
envbuf[4]=0x00;
if(write(fd,envbuf,5)<0)
{
perror("write");
return -1;
}
}
else if(strncmp(buf,"auto_off",8)==0)
{
//发送命,关闭自动喷淋模式
envbuf[0]=0xdd;
envbuf[4]=0x01;
if(write(fd,envbuf,5)<0)
{
perror("write");
return -1;
}
}
else if(strncmp(buf,"hand_on",7)==0)
{
//发送命令,手动打开喷淋装置
envbuf[0]=0xdd;
envbuf[4]=0x02;
if(write(fd,envbuf,5)<0)
{
perror("write");
return -1;
}
}
else if(strncmp(buf,"hand_off",8)==0)
{
//发送命,手动关闭喷淋装置
envbuf[0]=0xdd;
envbuf[4]=0x03;
if(write(fd,envbuf,5)<0)
{
perror("write");
return -1;
}
}
}
else if(ret<0)
{
perror("read");
exit(-1);
}
else
{
printf("client quit!\n");
break;
}
bzero(buf,sizeof(buf));
}
}
串口数据控制服务器程序放在一个文件夹运行,运行方式可参考
1.编译:gcc *.c -o 新命名
2.运行:./新命名
图像视频服务器
camera.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <stdlib.h>
#include <linux/videodev2.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <arpa/inet.h>
typedef struct{
int length;
int offset;
char *start;
}VideoBuffer;
VideoBuffer pic_buffers[3];
int fd=0;
int sockfd=0;
struct v4l2_buffer enqueue,dequeue;
//打开摄像头
int open_camera(char *path)
{
fd=open(path,O_RDWR);
if(fd<0)
{
printf("open /dev/video0 failed\n");
return -1;
}
return 0;
}
//关闭摄像头
int close_camera()
{
close(fd);
}
//获取摄像头相关信息
void get_camerainfo(void)
{
struct v4l2_format fmt;
fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(ioctl(fd,VIDIOC_G_FMT,&fmt)==-1)
{
perror("VIDIOC_G_FMT:");
return ;
}
printf("current data format information:\n");
printf("width=%d\n",fmt.fmt.pix.width);
printf("height=%d\n",fmt.fmt.pix.height);
}
//设置摄像头具体格式
int set_format()
{
struct v4l2_format fmt;
fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width=640;
fmt.fmt.pix.height=480;
fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_MJPEG;
fmt.fmt.pix.field=V4L2_FIELD_INTERLACED;
int ret=ioctl(fd,VIDIOC_S_FMT,&fmt);
if(ret<0)
{
perror("VIDIOC_S_FMT:");
return -1;
}
printf("----------------VIDIOC_S_FMT------------------\n");
printf("type:%d\n",fmt.type);
printf("width:%d\n",fmt.fmt.pix.width);
printf("heigt:%d\n",fmt.fmt.pix.height);
return 0;
}
//获取摄像头图片采集的缓存buf
int get_buf(void)
{
struct v4l2_requestbuffers req;
memset(&req,0,sizeof(req));
req.count=3;
req.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory=V4L2_MEMORY_MMAP;
if(ioctl(fd,VIDIOC_REQBUFS,&req)<0)
{
perror("VIDIOC_REQBUFS:");
return -1;
}
return 0;
}
//映射buf到用户空间
void bufmap(void)
{
int numBufs=0;
struct v4l2_buffer temp_buf;
for(numBufs=0;numBufs<3;numBufs++)
{
memset(&temp_buf,0,sizeof(temp_buf));
temp_buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
temp_buf.memory=V4L2_MEMORY_MMAP;
temp_buf.index=numBufs;
//获取第一个缓存的地址到pic_buf
if(ioctl(fd,VIDIOC_QUERYBUF,&temp_buf)<0)
{
printf("VIDIOC_QUERYBUF failed\n");
return;
}
pic_buffers[numBufs].length=temp_buf.length;
pic_buffers[numBufs].offset=(size_t)temp_buf.m.offset;
pic_buffers[numBufs].start=mmap(NULL,temp_buf.length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,temp_buf.m.offset);
if(pic_buffers[numBufs].start==MAP_FAILED)
{
perror("pic_buffers error:\n");
return ;
}
//将缓存取放入队列中
if(ioctl(fd,VIDIOC_QBUF,&temp_buf)<0)
{
perror("VIDIOC_QBUF:");
return ;
}
}
enqueue.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
dequeue.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
enqueue.memory=V4L2_MEMORY_MMAP;
dequeue.memory=V4L2_MEMORY_MMAP;
}
//开始采集
void start_on()
{
enum v4l2_buf_type type;
type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(ioctl(fd,VIDIOC_STREAMON,&type)<0)
{
perror("VIDIOC_STREAMON :");
return ;
}
}
int get_picture(char *buffer,int *length)
{
int ret;
ret=ioctl(fd,VIDIOC_DQBUF,&dequeue);
if(ret!=0)
{
perror("VIDIOC_DQBUF:");
return -1;
}
//获取图片数据
memcpy(buffer,pic_buffers[dequeue.index].start,pic_buffers[dequeue.index].length);
*length=pic_buffers[dequeue.index].length;
//把数据取出后,重新入队
enqueue.index=dequeue.index;
ret=ioctl(fd,VIDIOC_QBUF,&enqueue);
if(ret!=0)
{
perror("enqueue fail");
return -1;
}
return 0;
}
//停止摄像头
int stop_camera()
{
int ret;
int off=1;
ret=ioctl(fd,VIDIOC_STREAMOFF,&off);
if(ret!=0)
{
perror("stop camera fail");
return -1;
}
return 0;
}
int bufunmap()
{
int i;
for(i=0;i<3;i++)
{
munmap(pic_buffers[i].start,pic_buffers[i].length);
}
return 0;
}
int server_init()
{
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd<0)
{
perror("socket:");
return -1;
}
struct sockaddr_in seraddr;
memset(&seraddr,0,sizeof(seraddr));
seraddr.sin_family=AF_INET;
seraddr.sin_port=htons(8888);
seraddr.sin_addr.s_addr=inet_addr("0.0.0.0");
if(bind (sockfd,(const struct sockaddr*)&seraddr,sizeof(seraddr))<0)
{
perror("bind");
return -1;
}
int ret=listen(sockfd,7);
if(ret<0)
{
perror("listen:");
return -1;
}
int connfd=accept(sockfd,NULL,NULL);
if(connfd>0)
{
printf("client has connectd!\n");
}
else
{
printf("connect failed\n");
return -1;
}
return connfd;
}
char pic[1024*768*3]={0};
int main()
{
int length=0;
int connfd=0;
open_camera("/dev/video0");
get_camerainfo();
set_format();
get_buf();
bufmap();
connfd=server_init();
start_on();
char piclen[20]={0};
while(1)
{
get_picture(pic,&length);
printf("pic length=%d\n",length);
sprintf(piclen,"%d",length);
if(write(connfd,piclen,20)<0)
{
perror("write:");
return -1;
}
if(write(connfd,pic,length)<0)
{
perror("write:");
return -1;
}
}
// stop_camera();
// bufunmap();
// close_camera();
}
QT客户端设计
Headers模块源码(头文件)
login.h
#ifndef LOGIN_H
#define LOGIN_H
#include <QWidget>
#include <QMainWindow>
#include <QTcpSocket>
#include <QDebug>
namespace Ui {
class login;
}
class login : public QWidget
{
Q_OBJECT
public:
explicit login(QWidget *parent = 0);
~login();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
void tcp_recv();
void on_pushButton_3_pressed();
private:
Ui::login *ui;
QTcpSocket *socket;
};
#endif // LOGIN_H
camera.h
#ifndef CAMERA_H
#define CAMERA_H
#include <QPainter>
#include <QWidget>
#include <QTcpSocket>
#include <QMainWindow>
#include <QDebug>
namespace Ui {
class camera;
}
class camera : public QWidget
{
Q_OBJECT
public:
explicit camera(QWidget *parent = 0);
~camera();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void picshow();
private:
Ui::camera *ui;
QTcpSocket *socket;
int flag = 0;
char piclength[20]={0};
int piclen = 0;
char picbuf[1024*768*3];
};
#endif // CAMERA_H
mainwindows.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTcpSocket>
#include <QTimer>
#include <camera.h>
#include <login.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
void on_pushButton_4_clicked();
void show_connect();
void senddata();
void recvdata();
void on_pushButton_connect_clicked();
private:
Ui::MainWindow *ui;
QTcpSocket *tcpsocket;
QTimer *timer;
};
#endif // MAINWINDOW_H
Sources模块源码
login.cpp
#include "login.h"
#include "ui_login.h"
#include "mainwindow.h"
#include <QLabel>
#include <QMovie>
login::login(QWidget *parent) :
QWidget(parent),
ui(new Ui::login)
{
ui->setupUi(this);
socket = new QTcpSocket;
//设置背景图
QPixmap pixmap = QPixmap(":/picture/6.jpg").scaled(this->size());
QPalette palette(this->palette());
palette.setBrush(QPalette::Background, QBrush(pixmap));
this->setPalette(palette);
//设置label窗口部件动态图
// ui->label->setScaledContents(true);
// QMovie *iconShow = new QMovie(":5.gif");
// ui->label->setMovie(iconShow);
// iconShow->start();
//this->close();
connect(socket,&QTcpSocket::readyRead,this,&login::tcp_recv);
}
login::~login()
{
delete ui;
}
void login::on_pushButton_3_pressed()
{
socket->abort();
socket->connectToHost("192.168.1.30", 5555);
}
void login :: tcp_recv()
{
QByteArray data = socket->readAll();
qDebug()<<"recv:"<<QString(data);
if(0==strcmp(data,"l")){
//this->close();
//MainWindow *fa = new MainWindow();
//this->close();
//fa->show();
}
}
void login::on_pushButton_clicked()
{
//登录功能模块
MainWindow *fa = new MainWindow();
this->close();
fa->show();
QString name = ui->lineEdit->text();
QString pawd = ui->lineEdit_2->text();
char buf[256]="2";
socket->write(buf,sizeof(buf)); //发送注册请求
char data[32];
strcpy(data, name.toLatin1().data());
socket->write(data,32); //发送名字
strcpy(data,pawd.toLatin1().data());
socket->write(data,32); //发送密码
}
void login::on_pushButton_2_clicked()
{
//注册功能模块
QString name = ui->lineEdit->text();//获取用户名
QString pawd = ui->lineEdit_2->text();//获取密码
char buf[256]="1";
socket->write(buf,sizeof(buf)); //发送注册请求
char data[32];
strcpy(data, name.toLatin1().data());
socket->write(data,32); //发送名字
strcpy(data, pawd.toLatin1().data());
socket->write(data,32); //发送密码
socket->read(data,32);
}
camera.cpp
#include "camera.h"
#include "ui_camera.h"
#include "mainwindow.h"
camera::camera(QWidget *parent) :
QWidget(parent),
ui(new Ui::camera)
{
ui->setupUi(this);
socket = new QTcpSocket;
//设置背景图片
QPixmap pixmap = QPixmap(":/picture/10.jpg").scaled(this->size());
QPalette palette(this->palette());
palette.setBrush(QPalette::Background, QBrush(pixmap));
this->setPalette(palette);
connect(socket,&QTcpSocket::readyRead,this,&camera::picshow);
}
void camera::picshow()
{
if(flag == 0)
{
socket->read(piclength, 20);
qDebug()<<"piclength="<<piclength;
piclen=atoi(piclength);
flag=1;
}
else
{
if(socket->bytesAvailable()<piclen)
return ;
socket->read(picbuf,piclen);
QPixmap pixmap;
qDebug()<<piclen;
pixmap.loadFromData((uchar*)picbuf,piclen,"JPEG");
ui->label->setPixmap(pixmap);
flag=0;
}
}
camera::~camera()
{
delete ui;
}
void camera::on_pushButton_clicked()
{
// socket->connectToHost("10.67.27.12", 8888);
socket->connectToHost("192.168.1.30", 8888);
}
void camera::on_pushButton_2_clicked()
{
socket->abort();
this->close();
// MainWindow *mainW = new MainWindow();
// mainW->show();
}
mainwindows.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QPixmap pixmap = QPixmap(":/picture/8.jpg").scaled(this->size());
QPalette palette(this->palette());
palette.setBrush(QPalette::Background, QBrush(pixmap));
this->setPalette(palette);
tcpsocket = new QTcpSocket(this);
timer = new QTimer(this);
ui->lcdSoil->display(0);
ui->lcdTemp->display(0);
ui->lcdLight->display(0);
ui->lcdGas->display(0);
connect(tcpsocket, SIGNAL(connected()), this, SLOT(show_connect()));
connect(tcpsocket, SIGNAL(readyRead()), this, SLOT(recvdata()));
connect(timer, SIGNAL(timeout()), this, SLOT(senddata()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_connect_clicked()
{
//tcpsocket->connectToHost(ui->lineEdit->text(),ui->lineEdit_2->text().toInt());
// timer->start(2000);
tcpsocket->abort();
tcpsocket->connectToHost("192.168.1.30",7777);
timer->start(2000);
}
void MainWindow::show_connect()
{
ui->lineEdit_3->setText("connected!");
}
//发送命令请求环境数据
void MainWindow::senddata()
{
char cmd[] = "env";
tcpsocket->write(cmd, sizeof(cmd));
}
//环境数据接收
void MainWindow::recvdata()
{
char buf[16] = {0};
tcpsocket->read(buf,15);
qDebug()<<buf;
int soilHum, dstemp, GasData,LightData;
soilHum = QString(buf).split(' ')[0].toInt();
dstemp = QString(buf).split(' ')[1].toInt();
GasData = QString(buf).split(' ')[2].toInt();
LightData = QString(buf).split(' ')[3].toInt();
//传输到界面显示
ui->lcdSoil->display(soilHum);
ui->lcdTemp->display(dstemp);
ui->lcdLight->display(LightData);
ui->lcdGas->display(GasData);
}
void MainWindow::on_pushButton_2_clicked()
{
//自动喷淋选择
static int flag = 0;
if(flag == 0)
{
tcpsocket->write("auto_on");
ui->pushButton_2->setText("关闭自动喷淋");
flag = 1;
}
else{
tcpsocket->write("auto_off");
ui->pushButton_2->setText("开启自动喷淋");
flag = 0;
}
}
void MainWindow::on_pushButton_3_clicked()
{
//手动打开喷淋
static int flag = 0;
if(flag == 0)
{
tcpsocket->write("hand_on");
ui->pushButton_3->setText("关闭手动喷淋");
flag = 1;
}
else{
tcpsocket->write("hand_off");
ui->pushButton_3->setText("开启手动喷淋");
flag = 0;
}
}
void MainWindow::on_pushButton_4_clicked()
{
camera *cam = new camera();
cam->show();
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include "login.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// MainWindow w;
// w.show();
login t;
t.show();
return a.exec();
}
界面设计展示
登录注册界面
数据显示及其控制界面
视频监控界面
注:需要CC2530底层设计代码可私信,传感器引脚定义如下
在完成系统间的连通测测试,简单录了一个视频,介绍本系统使用流程,以及基本实现的功能。
视频展示
以上就是自动喷淋系统设计过程,本系统中,各部分功能代码是分开的,所以有着很强的可操作性,可根据喷淋范围将zigbee+路由的形式,扩大环境监测范围,把CC2530开发板替换成STM32或其它开发板均可实现功能,cortex-A9开发板主要提供一个无线网关功能,将Linux服务器移植到开发板,只用网线连接电脑,实现远程监控,也可直接将CC2530开发板的协调器端接入USB接口到电脑,均可实现自动喷淋功能。觉得麻烦的话,可以使用esp8266开发板,连接one-net云平台,该平台。