赞
踩
上位机开发环境:Qt Creator 4.8.1
下位机开发环境:树莓派4b
此处省略Qt前端设计,只阐述后端逻辑实现
上位机:
下位机:
初始界面包含登录,网络控制,串口控制三个按钮。此时为未登录状态,登录标志按钮flag=0,此时点击其中的任意按钮,都会跳转到登录按钮。登录成功后,标志按钮flag=1,此时再点击登录按钮,只会弹出QMessageBox消息框提示登录成功,点击网络控制按钮则跳转到网络控制界面,点击串口控制按钮则会跳转到串口控制页面。
.h文件:
- #ifndef WIDGET_H
- #define WIDGET_H
-
- #include <QWidget>
-
- namespace Ui {
- class Widget;
- }
-
- class Widget : public QWidget
- {
- Q_OBJECT
-
- public:
- explicit Widget(QWidget *parent = nullptr);
- ~Widget();
-
-
- private slots:
-
- void on_logButton_clicked();
-
- void on_networkButton_clicked();
-
- void on_serialButton_clicked();
-
- private:
- Ui::Widget *ui;
- };
-
- #endif // WIDGET_H
.c文件:
- #include "widget.h"
- #include "ui_widget.h"
- #include "login.h"
- #include "QMessageBox"
- #include <network.h>
- #include <serial.h>
- extern int flag;
- Widget::Widget(QWidget *parent) :
- QWidget(parent),
- ui(new Ui::Widget)
- {
- ui->setupUi(this);
- }
-
- Widget::~Widget()
- {
-
- delete ui;
- }
-
-
-
- void Widget::on_logButton_clicked()
- {
- if(flag==0)//登录标志位flag=0
- {
- login *lg=new login;
- lg->setGeometry(this->geometry());
- lg->show();
- this->close();
- }
- else if (flag==1) {
- QMessageBox::information(this,"提示","您已成功登录");
- }
-
-
- }
-
- void Widget::on_networkButton_clicked()
- {
- if(flag==0)
- {
- login *lg=new login;
- lg->setGeometry(this->geometry());
- lg->show();
- this->close();
- }
- else if (flag==1) {
- network *net=new network;
- net->setGeometry(this->geometry());
- net->show();
-
- }
-
- }
-
- void Widget::on_serialButton_clicked()
- {
- if(flag==0)
- {
- login *lg=new login;
- lg->setGeometry(this->geometry());
- lg->show();
- this->close();
- }
- else if (flag==1) {
- serial *se=new serial;
- se->setGeometry(this->geometry());
- se->show();
- this->close();
- }
-
- }
登录框输入账号密码,点击"登录",拉取账号密码与数据库进行比对。若对比成功,登录标志flag置1,定时器启动,弹出QMessageBox消息框提示登录成功,保持1.5s,后自动关闭。若失败,登录标志不改变,弹出QMessageBox消息框提示登录失败。
.h文件
- #ifndef LOGIN_H
- #define LOGIN_H
-
- #include <QWidget>
-
- namespace Ui {
- class login;
- }
-
- class login : public QWidget
- {
- Q_OBJECT
-
- public:
- explicit login(QWidget *parent = nullptr);
- ~login();
-
- private slots:
- void on_pushButton_clicked();
-
- void on_backButton_clicked();
-
- private:
- Ui::login *ui;
- };
-
- #endif // LOGIN_H
.c文件
- #include "login.h"
- #include "ui_login.h"
- #include "QString"
- #include "widget.h"
- #include "QMessageBox"
- #include "QTimer"
- login::login(QWidget *parent) :
- QWidget(parent),
- ui(new Ui::login)
- {
- ui->setupUi(this);
- setWindowIcon(QIcon(":/home.ico"));
- }
-
- login::~login()
- {
- delete ui;
- }
-
- extern int flag=0;
- void login::on_pushButton_clicked()
- {
- QString username=ui->countEdit->text();
- QString passwd=ui->passwdEdit->text();
-
- if(username=="8888"&&passwd=="6688")
- {
- Widget *wd=new Widget;
- wd->setGeometry(this->geometry());
- wd->show();
- flag=1;
- QMessageBox *box=new QMessageBox(QMessageBox::Information,"提示","登录成功");
- QTimer::singleShot(1500,box,SLOT(close()));
- this->close();
- }
- else {
- QMessageBox::critical(this,"提示","密码或用户名错误");
-
- }
- }
-
- void login::on_backButton_clicked()
- {
-
- Widget *wd=new Widget;
- wd->setGeometry(this->geometry());
- wd->show();
- this->close();
- }
TCP连接与发送:界面初始化时,就已经初始化好tcpSocket,输入目的ip地址,目的端口后,点击连接,TCP开始与树莓派服务器连接,若连接成功,会接收到连接成功信号,触发绑定的槽函数并弹出QMessageBox消息框提示登录成功,并建立新的TCP连接。随后调节智能家电的参数,点击发送按钮,会将参数打包成TCP数据包,发送到树莓派控制硬件。
UDP连接与发送:网络控制界面开启时,就已经初始化好udpSocket,输入本地端口,点击接收开启连接,若连接成功弹出QMessageBox消息框,若此时有数据传输,则触发接收槽函数,并将接收到的内容显示到lable框中。
.h文件
- #ifndef NETWORK_H
- #define NETWORK_H
-
- #include <QWidget>
- #include <QTcpServer>
- #include <QTcpSocket>
- #include <QUdpSocket>
- namespace Ui {
- class network;
- }
-
- class network : public QWidget
- {
- Q_OBJECT
-
- public:
- explicit network(QWidget *parent = nullptr);
- ~network();
- QTcpSocket *tcpSocket;
- QUdpSocket *udpSocket;
-
- private slots:
- void on_horizontalSlider_valueChanged(int value);
-
- void on_spinBox_valueChanged(int arg1);
-
- void on_openTVButton_clicked();
-
- void on_upButton_clicked();
-
- void on_nextButton_clicked();
-
- void on_TCPconnectButton_clicked();
-
- void connect_slot();
- void readyRead_slot();
- void readyReadUDP_slot();
-
- void on_TCPcloseButton_clicked();
-
- void on_sendButton_clicked();
-
- void on_UDPconnectButton_clicked();
-
-
- void on_UDPcloseButton_clicked();
-
- private:
- Ui::network *ui;
- };
-
- #endif // NETWORK_H
.c文件
- #include "network.h"
- #include "ui_network.h"
- #include <widget.h>
- #include <iostream>
- #include "QMessageBox"
- #include "QString"
- using namespace std;
-
- static int lightnum;//灯的数值
- static int airnum=15;//空调的数值
- static int TVon=0;//0表示电视关闭
- static int TVchannle=35;//表示电视频道
- network::network(QWidget *parent) :
- QWidget(parent),
- ui(new Ui::network)
- {
- ui->setupUi(this);
- setWindowIcon(QIcon(":/home.ico"));
- tcpSocket=new QTcpSocket(this);
- udpSocket=new QUdpSocket(this);
- }
-
- network::~network()
- {
- delete ui;
- Widget *wd=new Widget;
- wd->setGeometry(this->geometry());
- wd->show();
- }
-
- void network::on_horizontalSlider_valueChanged(int value)
- {
- lightnum=ui->horizontalSlider->value();
- ui->light_value_label->setText(QString::number(lightnum));
- }
-
- void network::on_spinBox_valueChanged(int arg1)
- {
- airnum=ui->spinBox->value();
- cout<<airnum<<endl;
- }
-
- void network::on_openTVButton_clicked()
- {
- if(TVon==0)
- {
- TVon=1;
- ui->openTVButton->setText("关");
- }
- else if (TVon==1) {
- TVon=0;
- ui->openTVButton->setText("开");
- }
- }
-
- void network::on_upButton_clicked()
- {
- if(TVon==1)
- {
- TVchannle=TVchannle+1;
- if(TVchannle=100)
- {
- TVchannle=10;
- }
- cout<<TVchannle<<endl;
- }
-
- }
-
- void network::on_nextButton_clicked()
- {
- if(TVon==1)
- {
- TVchannle=TVchannle-1;
- if(TVchannle==10)
- {
- TVchannle=99;
- }
- cout<<TVchannle<<endl;
- }
-
- }
-
- void network::on_TCPconnectButton_clicked()
- {
- //tcpSocket->connectToHost(ui->ipaddrEdit->text(),ui->aimportEdit->text().toUInt());
- tcpSocket->connectToHost("192.168.43.146",50001);
- connect(tcpSocket,SIGNAL(connected()),this,SLOT(connect_slot()));
- }
-
- void network::connect_slot()
- {
- QMessageBox(QMessageBox::Information,"提示","连接成功");
- connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(readyRead_slot()));
- }
- void network::readyRead_slot()
- {
- cout<<"TCP数据来喽!!"<<endl;
- }
-
- void network::on_TCPcloseButton_clicked()
- {
- tcpSocket->close();
- }
-
- void network::on_sendButton_clicked()
- {
- QString temp;
- if(lightnum>9)
- {
- temp.sprintf("%d%d%d%d",lightnum,airnum,TVon,TVchannle);
- }
- else if (0<=lightnum<=9) {
- temp.sprintf("0%d%d%d%d",lightnum,airnum,TVon,TVchannle);
- }
-
- tcpSocket->write(temp.toLocal8Bit().data());
- }
-
- void network::on_UDPconnectButton_clicked()
- {
- if(udpSocket->bind(5554))
- {
- QMessageBox::information(this,"提示","UDP打开成功");
- }
- else {
- QMessageBox::critical(this,"提示","UDP打开失败");
- }
- connect(udpSocket,SIGNAL(readyRead()),SLOT(readyReadUDP_slot()));
- }
-
- void network::readyReadUDP_slot()
- {
- cout<<"UDP数据来咯!"<<endl;
- while (udpSocket->hasPendingDatagrams()) {
- QByteArray array;
- array.resize(udpSocket->pendingDatagramSize());
- udpSocket->readDatagram(array.data(),array.size());
- QString buf;
- buf=array.data();
- ui->plainTextEdit->appendPlainText(buf);
-
- }
-
- }
-
- void network::on_UDPcloseButton_clicked()
- {
- udpSocket->close();
- }
串口界面打开时,使用foreach函数将可用的串口查找出来,保存到QStringList的变量中并在界面上显示,将串口各个参数配置好后,点击"打开",配置的参数被赋给serialPort结构体的各个参数,并触发serialPort的open函数打开串口,若打开成功,QMessageBox弹窗提示打开成功。若打开失败,QMessageBox弹窗提示。
.h文件
- #ifndef SERIAL_H
- #define SERIAL_H
-
- #include <QWidget>
- #include <QSerialPortInfo>
- #include <QSerialPort>
- #include <QTimer>
- #include <QTime>
- namespace Ui {
- class serial;
- }
-
- class serial : public QWidget
- {
- Q_OBJECT
-
- public:
- explicit serial(QWidget *parent = nullptr);
- ~serial();
- QSerialPort *serialPort;
- QTimer timer;
-
- private slots:
- void on_openButton_clicked();
-
- void on_closeButton_clicked();
- void serialPort_ReadyRead_slot();
- void timeout_slot();
- void on_snedButton_clicked();
-
- void on_clearButton_clicked();
-
- void on_backButton_clicked();
-
- private:
- Ui::serial *ui;
- };
-
- #endif // SERIAL_H
.c文件
- #include "serial.h"
- #include "ui_serial.h"
- #include "QMessageBox"
- #include "widget.h"
-
- serial::serial(QWidget *parent) :
- QWidget(parent),
- ui(new Ui::serial)
- {
- ui->setupUi(this);
- setWindowIcon(QIcon(":/home.ico"));
- QStringList serialNamePort;
- foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
- {
- serialNamePort<<info.portName();
- }
- ui->serialcomboBox->addItems(serialNamePort);
- connect(&timer,SIGNAL(timeout()),this,SLOT(timeout_slot()));
-
-
-
- }
-
- serial::~serial()
- {
- delete ui;
- }
-
-
- void serial::serialPort_ReadyRead_slot()
- {
- QString buf;
- QTime time=QTime::currentTime();
- buf=QString(serialPort->readAll());
- ui->revcTextEdit->appendPlainText(time.toString("hh:mm:ss"));
- ui->revcTextEdit->appendPlainText(buf);
-
- }
- void serial::timeout_slot()
- {
-
- }
-
-
- void serial::on_openButton_clicked()
- {
- serialPort=new QSerialPort(this);
- QSerialPort::BaudRate buadRate;
- QSerialPort::DataBits dataBits;
- QSerialPort::StopBits stopBits;
- QSerialPort::Parity checkBits;
-
- if(ui->botecomboBox->currentText()=="4800")
- {
- buadRate=QSerialPort::Baud4800;
- }
- else if (ui->botecomboBox->currentText()=="9600") {
- buadRate=QSerialPort::Baud9600;
- }
- else if (ui->botecomboBox->currentText()=="19200") {
- buadRate=QSerialPort::Baud19200;
- }
- else if (ui->botecomboBox->currentText()=="115200") {
- buadRate=QSerialPort::Baud115200;
- }
-
- if(ui->datacomboBox->currentText()=="5")
- {
- dataBits=QSerialPort::Data5;
- }
- else if (ui->datacomboBox->currentText()=="6") {
- dataBits=QSerialPort::Data6;
- }
- else if (ui->datacomboBox->currentText()=="7") {
- dataBits=QSerialPort::Data7;
- }
- else if (ui->datacomboBox->currentText()=="8") {
- dataBits=QSerialPort::Data8;
- }
-
- if(ui->stopcomboBox->currentText()=="1")
- {
- stopBits=QSerialPort::OneStop;
- }
- else if (ui->stopcomboBox->currentText()=="3") {
- stopBits=QSerialPort::OneAndHalfStop;
- }
- else if (ui->stopcomboBox->currentText()=="2") {
- stopBits=QSerialPort::TwoStop;
- }
-
- if(ui->jiaoyancomboBox->currentText()=="none")
- {
- checkBits=QSerialPort::NoParity;
- }
-
- serialPort->setPortName(ui->serialcomboBox->currentText());
- serialPort->setBaudRate(buadRate);
- serialPort->setDataBits(dataBits);
- serialPort->setStopBits(stopBits);
- serialPort->setParity(checkBits);
-
- if(serialPort->open(QIODevice::ReadWrite)==true)
- {
- QMessageBox::information(this,"提示","成功");
- connect(serialPort,SIGNAL(readyRead()),this,SLOT(serialPort_ReadyRead_slot()));
-
- }
- else {
- QMessageBox::critical(this,"提示","失败");
- }
- }
-
- void serial::on_closeButton_clicked()
- {
- serialPort->close();
- }
-
- void serial::on_snedButton_clicked()
- {
- serialPort->write(ui->snedlineEdit->text().toLocal8Bit().data());
- }
-
- void serial::on_clearButton_clicked()
- {
- ui->revcTextEdit->clear();
- ui->snedlineEdit->clear();
- }
-
-
- void serial::on_backButton_clicked()
- {
- Widget *wd=new Widget;
- wd->setGeometry(this->geometry());
- wd->show();
- this->close();
- }
程序启动后,首先调用pthread_create创建2个线程tcp\serial,并使用pthread_detach分离线程。串口线程创建成功后,使用serialOpen打开串口,配置参数,发送验证性字符随后进入while(1)采集并发送环境信息。tcp线程创建后等待客户端连接,客户端连接成功后,创建第3个udp线程,随后进入while(1)等待tcp数据并处理。udp线程创建成功后,创建套接字,绑定端口和ip地址,等待连接,连接成功后进入while(1)进入发送
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <unistd.h>
- #include <time.h>
- #include <wiringPi.h>
- #include <wiringSerial.h>
- #include <sys/wait.h>
- #include <signal.h>
- #include <pthread.h>
-
- #include <stdio.h>
- #include <time.h>
- #include <sys/time.h>
- #include <stdlib.h>
- #include <signal.h>
- char msg[20];
- void *UDP(void)
- {
- pthread_detach(pthread_self());//将当前线程分离
- //创建套接字
- int sock_fd = socket(AF_INET,SOCK_DGRAM,0);
-
- //绑定地址(IP+PORT)
- struct sockaddr_in srvaddr,ciladdr;
-
- srvaddr.sin_family = AF_INET;//地址族
- //端口
- srvaddr.sin_port = htons(5554); //端口一般取50000以上
- //IP地址
- srvaddr.sin_addr.s_addr = inet_addr("192.168.43.210");//将文本字符串转换为32位无符号网络地址
-
-
-
- char buf[100];
- int len = sizeof(ciladdr);
-
- while(1)
- {
- bzero(buf,100);
- fgets(buf,100,stdin); //从键盘输入数据
- sendto(sock_fd,buf,100,0,(struct sockaddr *)&srvaddr,sizeof(srvaddr));
-
-
-
-
- }
-
- //关闭套接字
- close(sock_fd);
-
- }
-
- int light;
- int airnum;
- int TVon;
- int TVchannel;
-
- void *TCPServer(void)
- {
- pthread_detach(pthread_self());//将当前线程分离
- //创建套接字
- int sock_fd = socket(PF_INET,SOCK_STREAM,0);
-
- //绑定地址(IP+PORT)
- struct sockaddr_in srvaddr;
-
- srvaddr.sin_family = PF_INET;//地址族
- //端口
- srvaddr.sin_port = htons(50001); //端口一般取50000以上
- //IP地址
- srvaddr.sin_addr.s_addr = inet_addr("192.168.43.146");//将文本字符串转换为32位无符号网络地址
-
- bind(sock_fd,(struct sockaddr *)&srvaddr,sizeof(srvaddr));
-
- //设置监听套接字
- listen(sock_fd,4);
-
- //等待客户端连接
- printf("等待连接\n");
-
- int conn_fd = accept(sock_fd,NULL,NULL);
-
- printf("连接成功\n");
-
- pthread_t th3;
- pthread_create(&th3,NULL,UDP,NULL);
-
-
-
- while(1)
- {
- bzero(msg,20);
- recv(conn_fd,msg,20,0);
- printf("recv:%s\n",msg);
-
- light=(msg[0]-48)*10+(msg[1]-48);
- airnum=(msg[2]-48)*10+(msg[3]-48);
- TVon=msg[4]-48;
- TVchannel=(msg[5]-48)*10+(msg[6]-48);
-
-
-
- }
-
- //关闭套接字
- close(conn_fd);
- close(sock_fd);
-
- }
- void *serial()
- {
- pthread_detach(pthread_self());//将当前线程分离
- int fd;
- int cmd;
- int i=0;
- if(wiringPiSetup()==-1)
- {
- printf("setup wiringPi failed!\n");
- return 1;
- }
-
- fd=serialOpen("/dev/ttyAMA0",115200);
- if(-1==fd)
- {
- printf("ttyAMA open error!\n");
- }
-
-
- serialPuts(fd,"message from uart\r\n");
- printf("uart send finish\n");
- delay(1000);
- while(1)
- {
- serialPuts(fd,"Temp: Lum:\0");
- delay(3000);
- serialPrintf(fd,"%d %.1f\r\n",(airnum+5),light*0.657);
- delay(3000);
-
- // serialFlush(fd);
- }
-
- serialClose(fd);
- }
-
- void signal_handler()
- {
- static int i=0;
- i++;
- if(i<=light)
- {
- digitalWrite(7,HIGH);
- }
- else if(light<i<100)
- {
- digitalWrite(7,LOW);
- }
- if(100==i)
- {
- i=0;
- }
- }
-
- int main()
- {
-
- pthread_t th1,th2;
- pthread_create(&th1,NULL,TCPServer,NULL);
- pthread_create(&th2,NULL,serial,NULL);
-
- if(wiringPiSetup()==-1)
- {
- printf("setup wiringPi faild!");
- return 1;
- }
- struct itimerval itv;
- itv.it_interval.tv_sec=0;
- itv.it_interval.tv_usec=500;
-
- itv.it_value.tv_sec=1;
- itv.it_value.tv_usec=0;
-
- pinMode(7,OUTPUT);
- pinMode(1,OUTPUT);
- pinMode(0,OUTPUT);
- setitimer(ITIMER_REAL,&itv,NULL);
- signal(SIGALRM,signal_handler);
-
- while(1)
- {
- if(airnum==15)
- {
- digitalWrite(1,LOW);
- }
- else if(airnum>16)
- {
- digitalWrite(1,HIGH);
- }
-
- if(TVon==0)
- {
- digitalWrite(0,LOW);
- }
- else if(TVon==1)
- {
- digitalWrite(0,HIGH);
- }
- };
- return 0;
- }
这个项目做的马马虎虎,很多设想的功能都是通过模拟的方式实现,还有许多不足之处需要好好打磨斟酌。因此有错误之处,还请批评指正。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。