文章目录

    • 前言
  • 一、实现效果
    • 视频演示
  • 二、程序设计
    • 1. 界面背景图设计
    • 2. 信号槽设计
    • 3. 定时器设计
    • 4. 动态曲/折线图的设计
    • 5. 摄像头扫码
    • 6. 注册设计
    • 7. 登录设计
    • 8. 巡检人员设计
  • 三、综合分析

前言

本篇源于 “ 2022 湖南省大学生物联网应用创新设计竞赛技能赛参考样题 ”
——应用物联网的共享电动自行车

针对共享电动自行车应用场景,设计实现共享电动自行车、用户、管理等相关人、物互联的物联网系统。假设系统由电动自行车、后端服务器、前端应用终端、以及电动自行车专用巡检装置组成,各部分功能作用如下:

一、电动自行车:
1)每台电动自行车有一个唯一的 ID 号,以及由 GPS 采集的位置信息(比赛中,GPS 及地图信息可用人工输入固定位置编号代替);
2)电动自行车电池可换,每个电池上有唯一 RFID 信息,可被电动自行车读取;
3)电动自行车驱动部分有一个总开关,能够被远程控制其开关,以允许电动自行车被合法租用人驾驶;
4)电动自行车由直流电机驱动,能被控制不同速度转动(竞赛条件下可用任何小型直流电机代替),设有控制直流电机转速的操控开关、以及测量直流电机实际转速的装置;
5)电动自行车驾驶时设有左、右转向指示,当转向时对应转向指示灯开始闪烁(亮 0.7 秒、灭 0.3 秒,循环);
6)电动自行车设有一个夜间自动照明灯,当环境亮度低于所设定阈值时,照明灯自动打开;
7)电动自行车设有 1 个喇叭(可蜂鸣器代),行车需要时可提示路上行人、或当检测到故障时报警;
8)电动自行车的电池状态可被检测(比赛场景简化为检测以下数据:电压 V1、电压 V2、温度T1、温度 T2),设电池主要数据为:电池电压 V1、充放电电流 I = | V1 -V2| / R (R 为固定的电流测量采样电阻阻值)、电池工作温升 T=T2-T1;
9)电动自行车上能够显示其重要相关信息和数据;
10)电动自行车具备与远程服务器通信,将数据传输到后台服务器、或被查询、或被控制;
11)挑战性功能 1:当断电(如更换电池)时,一些设置的与电动车相关个性信息应该保留,复电后仍然有效。
12)挑战性功能 2:断网(如骑行到无网络场地)期间,电动自行车记录的信息在网络连通后,能够不丢失地将全部数据传送至后端服务器。

二、后端服务器:
1)构建网络后端服务器,收发、管理、控制多个电动自行车数据(竞赛场景管理不少于 2 台电动自行车);
2)按应用场景和题目要求,对后台数据计算、处理、运用;
3)按应用场景和题目要求,为应用前端(移动用户和计算机网络用户)提供服务。

三、前端应用:
网络终端(如计算机)或移动终端(如智能手机 App)针对应用场景和题目要求的相关应用功能,如信息显示、或远程控制、或预警、或统计等。

四、巡检装置:
电动自行车维护维修的专用移动装置。当巡检人员携带该巡检装置到达电动自行车附近时,可无线方式与电动自行车交互,方便维护维修人员快速了解电动自行车状况。搭建、设计、完成该物联网系统,实现共享电动自行车、用户、管理人员之间的互联互通,实现电动自行车数据采集、控制、传输、存储、查询和显示的全过程,用户能够更加方便地使用共享电动自行车,管理人员也能更加清晰透明地了解电动自行车实时和历史状态。

一、实现效果

1. 模式选择

2. 普通用户

3. 巡检人员




视频演示

物联网共享电单车管理系统

二、程序设计

本篇中信号与槽用之最多,且大多控件都是直接在ui界面设置的,这样方便在比赛中修改,所以我在这只对主要部分进行简述,如需详情请留言评论区。

1. 界面背景图设计

界面背景图一般放置构造函数中,且在ui->setupUi(this);之后

  QPixmap pixmap = QPixmap(":/picture/pc10.png").scaled(this->size());       //设置背景图片QPalette  palette (this->palette());palette .setBrush(QPalette::Background, QBrush(pixmap));this-> setPalette( palette );

2. 信号槽设计

这里我介绍俩种常见的信号槽设计:
(1) 在ui界面中对要设置的信号控件右击

这样,系统就会自动给你创建出信号槽,你只用在该槽内设置操作数即可。

(2) 用connect函数中进行编写信号槽 如:

connect(ui->pushButton,&QPushButton::clicked,[=](){this->hide();Widget *w=new Widget;w->show();});

上述操作为,在该文件的ui界面 点击名为pushButton的控件(&QPushButton::clicked为文件QPushbutton自带的点击函数),如何触发信号执行={ };里面的操作。

3. 定时器设计

定时器的概念就不用我多说了把,毕竟都是学这行的,顾名思义,定时器就是用来定时的,直接上操作代码,简单粗暴且易懂。

  timerDrawLine = new QTimer();timerDrawLine->start(500);connect(timerDrawLine,&QTimer::timeout,[=](){DrawLine();});
}

用计时器之前记得定义头文件#include 哦,简单来说 这几句代码的意思是创建一个名为timerDrawLine 的定时器,设置定时时间位500ms(注意单位是ms <1s=1000ms>),connect函数上面刚介绍完,&QTimer::timeout的意思是到设置时间了,就立即执行={ }里面些操作代码。

4. 动态曲/折线图的设计

在这里我引入随机数,通过不断产生的随机数再结合定时器动态画出曲/折线图,定时器中操作为:

  timerDrawLine = new QTimer();timerDrawLine->start(500);connect(timerDrawLine,&QTimer::timeout,[=](){DrawLine();});

在pro文件中记得加上 QT += charts
不废话,曲/折线程序设计为:


#include <QtCharts/QChartView>
#include <QtCharts/QSplineSeries>
#include <QtCharts/QLineSeries>
#include <QValueAxis>
#include <QTimer>QT_CHARTS_USE_NAMESPACE
#define MAX_X   10
#define MAX_Y   100void lineseries::Chart_Init()
{//初始化QChart的实例chart = new QChart();//初始化QSplineSeries的实例lineSeries = new QSplineSeries();//lineSeries = new QLineSeries();//设置曲线的名称lineSeries->setName("随机数测试曲线");//把曲线添加到QChart的实例chart中chart->addSeries(lineSeries);//声明并初始化X轴、两个Y轴QValueAxis *axisX = new QValueAxis();QValueAxis *axisY = new QValueAxis();//设置坐标轴显示的范围axisX->setMin(0);axisX->setMax(MAX_X);axisY->setMin(0);axisY->setMax(MAX_Y);//设置坐标轴上的格点axisX->setTickCount(11);axisY->setTickCount(11);//设置坐标轴显示的名称QFont font("Microsoft YaHei",8,QFont::Normal);//微软雅黑。字体大小8axisX->setTitleFont(font);axisY->setTitleFont(font);axisX->setTitleText("X-Test");axisY->setTitleText("Y-Test");//设置网格不显示axisY->setGridLineVisible(false);//下方:Qt::AlignBottom,左边:Qt::AlignLeft//右边:Qt::AlignRight,上方:Qt::AlignTopchart->addAxis(axisX, Qt::AlignBottom);chart->addAxis(axisY, Qt::AlignLeft);//把曲线关联到坐标轴lineSeries->attachAxis(axisX);lineSeries->attachAxis(axisY);//把chart显示到窗口上ui->graphicsView1->setChart(chart);ui->graphicsView1->setRenderHint(QPainter::Antialiasing);      // 设置渲染:抗锯齿,如果不设置那么曲线就显得不平滑
}
void lineseries::DrawLine()
{static int count = 0;if(count > MAX_X){//当曲线上最早的点超出X轴的范围时,剔除最早的点,lineSeries->removePoints(0,lineSeries->count() - MAX_X);// 更新X轴的范围chart->axisX()->setMin(count - MAX_X);chart->axisX()->setMax(count);//当折线上最早的点超出X轴的范围时,剔除最早的点,lineSeries1->removePoints(0,lineSeries1->count() - MAX_X);// 更新X轴的范围chart1->axisX()->setMin(count - MAX_X);chart1->axisX()->setMax(count);}//增加新的点到曲线末端int ht=rand()%94+2;lineSeries->append(count, ht);//随机生成2到95的随机数lineSeries1->append(count, ht);count ++;
}void lineseries::Chart_Init1()
{//初始化QChart的实例chart1 = new QChart();//初始化QSplineSeries的实例lineSeries1 = new QLineSeries();//设置曲线的名称lineSeries1->setName("随机数测试折线");//把折线添加到QChart的实例chart中chart1->addSeries(lineSeries1);//声明并初始化X轴、两个Y轴QValueAxis *axisX = new QValueAxis();QValueAxis *axisY = new QValueAxis();//设置坐标轴显示的范围axisX->setMin(0);axisX->setMax(MAX_X);axisY->setMin(0);axisY->setMax(MAX_Y);//设置坐标轴上的格点axisX->setTickCount(11);axisY->setTickCount(11);//设置坐标轴显示的名称QFont font("Microsoft YaHei",8,QFont::Normal);//微软雅黑。字体大小8axisX->setTitleFont(font);axisY->setTitleFont(font);axisX->setTitleText("X-Test");axisY->setTitleText("Y-Test");//设置网格不显示axisY->setGridLineVisible(false);//下方:Qt::AlignBottom,左边:Qt::AlignLeft//右边:Qt::AlignRight,上方:Qt::AlignTopchart1->addAxis(axisX, Qt::AlignBottom);chart1->addAxis(axisY, Qt::AlignLeft);//把折线关联到坐标轴lineSeries1->attachAxis(axisX);lineSeries1->attachAxis(axisY);//把chart显示到窗口上ui->graphicsView2->setChart(chart1);ui->graphicsView2->setRenderHint(QPainter::Antialiasing);      // 设置渲染:抗锯齿,如果不设置那么折线就显得不平滑
}

5. 摄像头扫码

此功能用于开发的app在移动端模拟扫描自行车上的二维码,将捕获到的数据发送到服务器,服务器获取该自行车的相关信息,进行判断自行车是否满足解锁条件,再将数据返回到移动端。

开启摄像须在pro文件中添加

QT  += multimedia multimediawidgets

其中Multimedia模块提供了丰富的接口,可以轻松地使用平台的多媒体功能。例如进行媒体播放、使用相机和收音机等;multimediawidgets可以实现点击播放按钮,可以播放视频;点击暂停按钮,可以停止播放视频;拉动进度条,可以定位视频播放位置。

首先,定义相关类名,这里为考虑读者通俗易懂,我起类名为“saoma”进行演示,在头文件里定义好相关对象 如下:

    QCamera *camera;QCameraViewfinder *viewfinder;QCameraImageCapture *imageCapture;QImage image;

然后在构造函数中操作摄像头,摄像头会自动获取设备资源,若无摄像头功能,会自动报错 具体操作如下:

//摄像头信息获取QList<QCameraInfo> cameras = QCameraInfo::availableCameras();foreach (const QCameraInfo &cameraInfo, cameras) {camera = new QCamera(cameraInfo);qDebug()<<cameraInfo.deviceName();}//设置摄像头捕获模式camera->setCaptureMode(QCamera::CaptureStillImage);//图像回显viewfinder = new QCameraViewfinder(this);camera->setViewfinder(viewfinder);this->setCentralWidget(viewfinder);//QCameraImageCapture 是获取摄像头捕捉的图片 相关类imageCapture = new QCameraImageCapture(camera);//启动摄像头this->camera->start();

运行如下:

6. 注册设计

在登录、注册操作中,较难设计的是判断这个用户的是否达到注册要求的标准,如用户名不得含有“@#*&”类似的特殊字符,俩次密码需要输入相同,手机号需要11位;登陆时检测这个用户是否已注册,账号密码是否存在,忘记密码时需要点击找回密码且在找回密码的界面里手机号不得输入错误等等。
(1) 创建用户类user,引入vector容器用于存储和判断

#include "user.h"
#include <QString>
#include <QDebug>User::User()
{}QList<User *> User::userlist;
User::User(QString userName,QString userPwd,QString userNumber)
{this->userName =  userName;this->userPwd = userPwd;this->userNumber = userNumber;this->userState =0;//0为不在线
}User::User(QString userName, QString userPwd, QString userNumber, int userState)
{this->userName =  userName;this->userPwd = userPwd;this->userNumber = userNumber;this->userState =userState;//1为在线
}
//用户名
QString User::GetUserName()
{return userName;
}void User::SetUserName(QString userName)
{this->userName =  userName;
}
//密码
QString User::GetUserPwd()
{return userPwd;
}void User::SetUserPwd(QString userPwd)
{this->userPwd =  userPwd;
}
//手机号
QString User::GetUserNumber()
{return userNumber;
}void User::SetUserNumber(QString userNumber)
{this->userNumber =  userNumber;
}
//用户状态
int User::GetUserState()
{return userState;
}void User::SetUserState(int userState)
{this->userState =  userState;
}void User::print()
{for (int i=0;i<userlist.size();i++) {qDebug()<<userlist.at(i);}
}

(2) 输入判断

 if(ui->userEdit->text()=="")//名字判断{//弹窗(是否指定窗口,标题,内容)QMessageBox::information(NULL,"错误","用户名为空");}else if(ui->pwdEdit->text()=="")//密码判断{QMessageBox::information(NULL,"错误","密码为空");}else if(ui->pwdEdit->text().length()<6)//密码长度判断{QMessageBox::information(NULL,"错误","密码长度有误");}else if(ui->nextpwdEdit->text()==""){QMessageBox::information(NULL,"错误","重新输入密码为空");}else if(ui->nextpwdEdit->text().length()<6)//重新输入密码长度判断{QMessageBox::information(NULL,"错误","重新输入密码长度有误");}else if(ui->numberEdit->text()==""){QMessageBox::information(NULL,"错误","密码为空");}else if(ui->numberEdit->text().length()<11)//判断电话号码长度{QMessageBox::information(NULL,"错误","电话号码长度有误");}else if(ui->nextpwdEdit->text()!=ui->pwdEdit->text()){QMessageBox::information(NULL,"错误","密码和重新输入密码不一致");}else{int i=0;//判断次数for(i=0;i<User::userlist.size();i++){if(ui->userEdit->text()==User::userlist.at(i)->GetUserName())//名字是否已被注册判断{QMessageBox::information(NULL,"错误","名字已被注册");break;}else if(ui->numberEdit->text()==User::userlist.at(i)->GetUserNumber())//电话号码是否已被注册判断{QMessageBox::information(NULL,"错误","电话号码已被注册");break;}}if(i>=User::userlist.size()){User *newuser = new User(ui->userEdit->text(),ui->pwdEdit->text(),ui->numberEdit->text());User::userlist.push_back(newuser);QMessageBox::information(NULL,"成功","注册成功");this->hide();  //关闭注册界面窗口}}
void Widget::regSlot(QString name,QString pwd,QString number)
{User *newuser = new User(name,pwd,number);User::userlist.push_back(newuser);
}

7. 登录设计

在登录界面需要输入已注册好的账号与密码,若忘记密码需要点击界面下方的”找回密码“,按照设计要求一步步操作,输入正确的手机号,获取验证码,输入新密码等。
在界面登录上方我设计了一个“输出已存储的用户”按钮,实则是给程序员设计的,这样方便查看已注册的用户信息;其次 界面还添加了“自动登录”和“记住密码”功能,因为我其实是根据“腾讯QQ”的样式进行设计的(haha)。
(1) 判断用户输入是否有误

void Widget::on_btn_denglu_clicked()
{int flag=0;for (int i=0;i<User::userlist.size();i++) {if(ui->yonghuming->text()==User::userlist.at(i)->GetUserName()){flag=1;if(ui->mima->text()==User::userlist.at(i)->GetUserPwd()){QMessageBox::information(NULL,"success","登录成功");}else {QMessageBox::information(NULL,"error","密码错误");}}}if(flag==0)  QMessageBox::information(NULL,"error","用户不存在");
}

(2) 二维码设计
点击右下方的二维码可弹出一个二维码对话框,支持扫码登录。

8. 巡检人员设计

巡检人员相当于管理员,权限自然大些,所以在这里我就没设计巡检人员的注册功能,直接在程序中给定了巡检人员的账号密码,正确输入即可成功登录,登录成功后可查看硬件“自行车”的相关信息,即自行车电压、电流、温湿度、气压、速度等等,详情可在上方界面中查看,这些每个控件我都有给其设置专有的信号槽,这样方便与服务器那边交接(按提要求可知,最终开发出来的app是要和服务器交互的,不可能自己跟自己玩是吧)。
在这里我用的是上方介绍的第一种信号槽方式设计:

void root_set::on_ton1_clicked()
{qDebug()<<"点击了蓝牙选择框";
}void root_set::on_ton2_clicked()
{qDebug()<<"点击了扫描";
}void root_set::on_ton3_clicked()
{qDebug()<<"点击了断开";
}void root_set::on_ton4_clicked()
{qDebug()<<"点击了发送";
}void root_set::on_ton5_clicked()
{qDebug()<<"点击了获取";
}void root_set::on_ton6_clicked()
{qDebug()<<"点击了清空";
}void root_set::on_ton7_clicked()
{qDebug()<<"点击了设定";
}void root_set::on_ton8_clicked()
{qDebug()<<"点击了开控制";
}void root_set::on_ton9_clicked()
{qDebug()<<"点击了关控制";
}void root_set::on_ton10_clicked()
{qDebug()<<"点击了图表";lineseries *line=new lineseries;line->show();
}void root_set::on_ton11_clicked()
{qDebug()<<"点击了时间";
}void root_set::on_ton12_clicked()
{qDebug()<<"点击了转速";
}void root_set::on_ton13_clicked()
{qDebug()<<"点击了电压";
}void root_set::on_ton14_clicked()
{qDebug()<<"点击了电流";
}void root_set::on_ton15_clicked()
{qDebug()<<"点击了所有";
}void root_set::on_ton16_clicked()
{qDebug()<<"点击了查询";
}void root_set::on_toolButton_clicked()
{this->hide();action * ac=new action;ac->show();
}

三、综合分析

在此项目中,我几乎所有控件都在ui界面中设计的,(在平时操作中 我不是不推荐在ui界面操作的),这样确实省了不少事,但不利于实际的项目开发,项目文件如下:

需要Qt相关资料或项目源码的可以留言评论区或直接私信我 Respect!

Qt 物联网系统界面开发 “ 2022湖南省大学生物联网应用创新设计竞赛技能赛 ——应用物联网的共享电动自行车 ”相关推荐

  1. 第六届全国大学生生物医学工程创新设计竞赛参赛经历

    前言/背景 第六届全国大学生生物医学工程创新设计竞赛是生物医学工程及相关专业锻炼自己创新实践能力的一个很好地平台,我通过实验室师兄师姐的分享得知了这个比赛,又在老师的推荐下进行组队参赛.2020年因为 ...

  2. 全国大学生FPGA创新设计竞赛:FPGA—相位干涉仪测向算法

    1.项目总体及相位干涉仪测向概述 根据调查发现,对于一些特定信号的快速精准定位一直是世界性难题.不仅仅是对某些会给国家和社会带来严重安全威胁的非法信号的定位跟踪,还可能是对紧急情况下的搜求信号的精确定 ...

  3. 2019年全国大学生“TI杯”电子设计竞赛综合测评电路仿真

    2019年全国大学生电子设计竞赛综合测评电路仿真 看到网传的综合测评题目后,就在Multisim14.0上做了仿真,各个模块的原理模.数电书上都有讲到,不喜勿喷,仅供参考.面我们先来看看题目,题目如下 ...

  4. 大学生如何参加创新创业竞赛、编写项目计划书?(超详细博客链接整合,佛系更新中)

    目录 前期工作 项目计划书阶段 前言 编写项目计划书 常见竞赛参赛经验 本篇从前到后列了一些大学生参加创新创业竞赛.编写项目计划书,汇总了对应的详细内容博客的链接,佛系更新中. 前期工作 选题建议篇: ...

  5. 基于物联网的校园直饮水管理系统(2022年湖南省物联网应用创新竞赛(技能赛))

    文章目录 物联网赛题 A. 直饮水机 B. 后端服务器 C. 前端应用终端 D. 巡检装置 一.思维导图 二.硬件选择 三.STM32端 四.服务器端 物联网赛题 1.应用场景描述 直饮水在校园和公共 ...

  6. Qt/C++音视频开发45-音视频类结构体参数的设计

    一.前言 视频监控内核组件重构和完善花了一年多时间,整个组件个人认为设计的最好的部分就是各种结构体参数的设计,而且分门别类,有枚举值,也有窗体相关的结构体参数,解码相关的结构体参数,同时将部分常用的结 ...

  7. 基于Cortex-A53内核Linux系统gec6818开发板的电子自助点餐设计

    由于是多文件下编译,涉及的文件很多,还有链接库,发源代码读者也不能编译运行,因此不将源代码下发打印.将所有的文件压缩成包,放到百度网盘上,话不多说上链接,有简陋功能展示视频.(可直接扫描二维码). 链 ...

  8. 2022 第五届 浙江省大学生网络与信息安全竞赛技能赛 预赛 Writeup,5题

    文章目录 1.Web:nisc_easyweb 2.Web:nisc_学校门户网站 3.Web:吃豆人吃豆魂 4.MISC:好怪哦 5.RE:ManyCheck 1.Web:nisc_easyweb ...

  9. 2022 第五届 浙江省大学生网络与信息安全竞赛技能赛 决赛 Writeup,5题

    文章目录 1.MISC:checkin_gift 2.MISC:m4a 3.Crypto:Math 4.RE:ezandroid 5.Web:babysql 1.MISC:checkin_gift 题 ...

最新文章

  1. AspNet MVC与T4,我定制的视图模板
  2. 修理机器人基维斯_魔兽世界修理机器人沃尔特和移动邮箱怎么做
  3. 【PHP ThinkPHP框架】小bug汇总[更新]
  4. 《软件需求规格说明书》 ---学士之路
  5. [C++基金会]位计算 游戏开发中的应用
  6. 《ASP.NET Core 微服务实战》-- 读书笔记(第1章 、第2章)
  7. Java中的do-while循环——通过示例学习Java编程(11)
  8. 又发现一个visual studio 2015的坑啊。
  9. EJB3与EJB2的差别
  10. ckeditor复制html样式丢失,Ckeditor选择html无法正常使用铬浏览器
  11. 浙大PAT乙级1004. 成绩排名 (20)
  12. java 执行 awk_3.1 biostar lesson3 linux学习日记;java版本;awk
  13. SQL2005服务器上安装SQL2008失败
  14. csdn官网(csdn官网免费下载)
  15. Spring框架基础(中)
  16. WebStorm调试
  17. 腾讯云账号实名认证和域名实名认证的区别
  18. Python 3.x 安装 web.py ,血泪!!
  19. 苹果店里卖移动套餐,走出甲方思维
  20. Windows 批处理(bat) if条件判断语句使用教程

热门文章

  1. my sql常用的数据类型
  2. 委内瑞拉石油币至今连“一毛钱”都没筹到,腾讯投资的轻松筹入局区块链 | 区块链日报
  3. 员工的激励与自我激励 - 项目管理系列文章
  4. MySQL5.7安装时GPG check FAILED 问题
  5. 轻量级3D绘制软件Blender下载、安装、汉化设置教程分享
  6. webhttp协议django初识
  7. 回收站文件恢复,分享4个巧妙解决方法!
  8. r5 5600g用什么主板 r5 5600g配什么显卡
  9. 那些快速被提拔的员工,都有这4个特质
  10. 团队项目之现场编程(牛码)