基于STM32MP1和QT的疫情看板

2024-06-18 08:08
文章标签 qt 疫情 stm32mp1

本文主要是介绍基于STM32MP1和QT的疫情看板,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 1.前言
  • 2.数据接口的获取
  • 3.Qt界面的实现
  • 4.在开发板上运行Qt程序
  • 5.使用无线模块联网
  • 6.代码下载

1.前言

之前我使用桌面版本Qt实现了肺炎疫情监控平台:基于Qt的新冠肺炎疫情数据实时监控平台(开源小项目)。既然Qt是跨平台的,正好参加创客比赛,刚买了一块米尔科技的YA157C开发板,那么能不能在嵌入式平台实现一下呢?

桌面Linux版本的运行效果:
在这里插入图片描述
YA157C开发板实现效果:
在这里插入图片描述

2.数据接口的获取

疫情监控平台的实现,简单的说,就是数据的展示,而数据从哪里来呢?

现在很多互联网公司都做了自己的疫情监控平台,我这里采用的是腾讯新闻的数据源,数据内容很丰富,也比较稳定。

数据来源:实时更新:新冠肺炎疫情最新动态

接口地址的获取方法可以参考:基于Qt的新冠肺炎疫情数据实时监控平台(开源小项目)

如果把所有的数据放在一个接口里,数据量会很大,所以腾讯把数据分成了几个接口

#包含最新疫情数据、各省市最新数据、其他国家最新数据
https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5#包含历史数据
https://view.inews.qq.com/g2/getOnsInfo?name=disease_other#最新的辟谣信息
https://vp.fact.qq.com/loadmore?page=0#辟谣信息详情
https://vp.fact.qq.com/miniArtData?id=a2141851348ee5f3772c761e25bb57d7

目前只显示了一些基本的数据,所以我们只使用到了https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5这个接口中的chinaTotalchinaAdd这两组数据。

这个接口包括很多数据,全国累计和新增的最新数据,各省市其他国家的最新数据等等。文件大小大概在160KB,液晶屏是7寸IPS屏,1024x600分辨率的,还是比较大的,可以显示很多信息,后续版本会添加更多数据显示的。

数据格式:

{"ret": 0,"data": {"lastUpdateTime": "2020-03-04 11:12:04","chinaTotal": {"confirm": 80422,"heal": 49914,"dead": 2984,"nowConfirm": 27524,"suspect": 520,"nowSevere": 6416},"chinaAdd": {"confirm": 120,"heal": 2654,"dead": 38,"nowConfirm": -2572,"suspect": -67,"nowSevere": -390},...........其他数据............."isShowAdd": true}
}

3.Qt界面的实现

之前的桌面应用程序中,是使用的是Qt5版本开发的,Qt5自带QJson解析类,而Qt 4没有带QJson。为了适配带有Qt 4库的板子,我使用了第三方JSON解析库。这里选择的是小巧的cJSON解析库:cJSON download | SourceForge.net

如果你的板子是Qt 4的库,那么程序不用修改,直接交叉编译运行即可使用。

只包含两个文件:cJSON.c和cJSON.h,把这两个文件添加到工程里就行了。

整个工程代码也很简单:GET接口地址,把接收到的数据保存到本地,调用cJSON解析数据文件,把解析出的数据显示,数据文件删除。代码可以到文章末尾开源地址获取。下面介绍几个关键部分代码的实现:

3.1 JSON数据的解析

//打开保存的JSON数据文件,并调用解析函数
void Dialog::parseData(QString filename)
{QFile file(filename);if(!file.open(QIODevice::ReadOnly)){qDebug() << "file open failed";return;}QByteArray allData = file.readAll();file.close();
//    qDebug() << allData;getData(allData);file.remove();            //删除文件return;
}
//把数据解析出来并显示在标签上
void Dialog::getData(QByteArray str)
{cJSON *ret_obj;cJSON *root_obj;root_obj = cJSON_Parse(str);   //创建JSON解析对象,返回JSON格式是否正确if (!root_obj){disInfo("JSON format error");qDebug() << "json format error";}else{disInfo("json format ok");qDebug() << "json format ok";ret_obj = cJSON_GetObjectItem(root_obj, "ret");if(cJSON_IsNumber(ret_obj)){int ret = 1;ret = ret_obj->valueint;
//            qDebug() << ret_obj->valueint;}char *data_str = cJSON_GetObjectItem(root_obj, "data")->valuestring;cJSON *data_obj = cJSON_Parse(data_str);if(!data_obj){qDebug() << "data json err";cnt_error++;QString error = "err:" + QString::number(cnt_error);ui->lbe_error->setText(error);}else{qDebug() << "data json ok";char *lastUpdateTime = cJSON_GetObjectItem(data_obj, "lastUpdateTime")->valuestring;qDebug() << lastUpdateTime;ui->lbe_update_time->setText(lastUpdateTime);cJSON *chinaTotal_obj = cJSON_GetObjectItem(data_obj, "chinaTotal");int chinaTotal_confirm    = cJSON_GetObjectItem(chinaTotal_obj, "confirm")->valueint;int chinaTotal_heal       = cJSON_GetObjectItem(chinaTotal_obj, "heal")->valueint;int chinaTotal_dead       = cJSON_GetObjectItem(chinaTotal_obj, "dead")->valueint;int chinaTotal_nowConfirm = cJSON_GetObjectItem(chinaTotal_obj, "nowConfirm")->valueint;int chinaTotal_suspect    = cJSON_GetObjectItem(chinaTotal_obj, "suspect")->valueint;int chinaTotal_nowSevere  = cJSON_GetObjectItem(chinaTotal_obj, "nowSevere")->valueint;ui->lbe_total_confirm->setNum(chinaTotal_confirm);ui->lbe_total_heal->setNum(chinaTotal_heal);ui->lbe_total_dead->setNum(chinaTotal_dead);ui->lbe_total_nowConfirm->setNum(chinaTotal_nowConfirm);ui->lbe_total_suspect->setNum(chinaTotal_suspect);ui->lbe_total_nowSevere->setNum(chinaTotal_nowSevere);cJSON *chinaAdd_obj = cJSON_GetObjectItem(data_obj, "chinaAdd");int chinaAdd_confirm    = cJSON_GetObjectItem(chinaAdd_obj, "confirm")->valueint;int chinaAdd_heal       = cJSON_GetObjectItem(chinaAdd_obj, "heal")->valueint;int chinaAdd_dead       = cJSON_GetObjectItem(chinaAdd_obj, "dead")->valueint;int chinaAdd_nowConfirm = cJSON_GetObjectItem(chinaAdd_obj, "nowConfirm")->valueint;int chinaAdd_suspect    = cJSON_GetObjectItem(chinaAdd_obj, "suspect")->valueint;int chinaAdd_nowSevere  = cJSON_GetObjectItem(chinaAdd_obj, "nowSevere")->valueint;lbeDisplay(ui->lbe_add_confirm, chinaAdd_confirm);lbeDisplay(ui->lbe_add_heal, chinaAdd_heal);lbeDisplay(ui->lbe_add_dead, chinaAdd_dead);lbeDisplay(ui->lbe_add_nowConfirm, chinaAdd_nowConfirm);lbeDisplay(ui->lbe_add_suspect, chinaAdd_suspect);lbeDisplay(ui->lbe_add_nowSevere, chinaAdd_nowSevere);}
//        cJSON_Delete(ret_obj);
//        cJSON_Delete(data_obj);cJSON_Delete(root_obj);//释放内存disInfo("更新完成");cnt_success++;QString success = "ok:" + QString::number(cnt_success);ui->lbe_success->setText(success);}
}//数据的显示
void Dialog::lbeDisplay(QLabel *lbe, int num)
{if(num > 0)lbe->setText("+" + QString::number(num));elselbe->setText(QString::number(num));
}

3.2 获取本地IP地址

//forexample:192.168.1.111
QString Dialog::GetLocalmachineIP()
{QString ipAddress;QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();for(QHostAddress &addr : ipAddressesList){// 找到不是本地ip,并且是ipv4协议,并且不是169开头的第一个地址if(addr != QHostAddress::LocalHost && addr.protocol() == QAbstractSocket::IPv4Protocol && !addr.toString().startsWith("169")){ipAddress = addr.toString();break;}}// if we did not find one, use IPv4 localhostif (ipAddress.isEmpty())ipAddress = QHostAddress(QHostAddress::LocalHost).toString();return ipAddress;
}

桌面Linux版本的运行效果:
在这里插入图片描述

4.在开发板上运行Qt程序

如果在桌面运行正常,就可以使用ya157c构建套件来编译工程,生成可以在开发板上运行的程序,然后使用scp命令传输到开发板上。

#使用网线把开发板连接上路由器
#使用udhcpc自动获取IP地址
udhcpc #查看获取到的ip地址
ifconfig#确认连接到互联网
ping www.baidu.com
#如果有回复数据,说明已经成功连接上互联网#使用scp命令或共享目录的方式把可执行文件传输到开发板上
scp qte_2019_ncov root@192.168.1.109:/home/root#执行程序
./qte_2019_ncov

最终效果
在这里插入图片描述
这个版本是上一个版本的,右上角没有显示开发板的IP地址和成功失败次数统计,最新版本的程序中已经添加了这个功能。

桌面Linux版效果:
在这里插入图片描述

5.使用无线模块联网

YA157C开发板已经板载了一个WiFi & 蓝牙模组——AP6212,可以直接连接无线网,这样就不需要使用网线的方式联网了。
在这里插入图片描述

#关闭eth0
ifconfig eth0 down#启用wlan0
rfkill unblock wifi
ifconfig wlan0 up#在当前文件夹生成WiFi配置文件
wpa_passphrase "M6_Note" "qwert125" > wifi.conf#查看生成的WiFi配置信息
cat wifi.conf#加载WiFi配置文件
wpa_supplicant -B -c wifi.conf -i wlan0#扫描附近的WiFi信息
iw dev wlan0 scan | grep SSID#自动获取IP地址
udhcpc -i wlan0#设置DNS
echo "nameserver 114.114.114.114" > /etc/resolv.conf#连接互联网
iw wlan0 link#测试网络连接
ping www.wangchaochao.top

在这里插入图片描述
在这里插入图片描述

为了方便快捷的连接WiFi,可以把以上命令写成一个shell脚本,需要连接WiFi时,直接执行这个脚本就可以了。先在本地生成WiFi配置信息:

connect_wifi.sh脚本文件内容:

#!/bin/bashWF_SSID="M6_Note"
WF_PASSWORD="qwert125"#关闭eth0
ifconfig eth0 down#使能wlan0
rfkill unblock wifi
ifconfig wlan0 up#输出WiFi信息
echo "WiFi_SSID:$WF_SSID"
echo "WiFi_PASSWORD:$WF_PASSWORD"#在当前文件夹生成WiFi配置信息
wpa_passphrase $WF_SSID $WF_PASSWORD > $WF_SSID.conf#加载WiFi配置文件
wpa_supplicant -B -c /home/root/$WF_SSID.conf -i wlan0#扫描附近的WiFi
iw dev wlan0 scan | grep SSID#自动获取IP地址
udhcpc -i wlan0#配置DNS
echo "nameserver 114.114.114.114" > /etc/resolv.conf#连接网络
iw wlan0 linkecho "WiFi连接成功"

WiFi账号和密码修改一下,就可以直接使用了。
在这里插入图片描述

6.代码下载

整个Qt工程代码已经开源在Github,Qt4/Qt5兼容。如果下载速度很慢,可以选择国内的Gitee速度会快很多。

#Github
https://github.com/whik/qte_2019_ncov#Gitee
https://gitee.com/whik/qte_2019_ncov

目前界面还比较简单,7寸的显示屏可以显示很多内容,之后会尽量完善界面信息,欢迎大家关注!

本文转载来源:公众号:mcu149 作者 whik

这篇关于基于STM32MP1和QT的疫情看板的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1071735

相关文章

QT 中ListView和ListWidget有什么区别

ListView和ListWidget在Qt框架中都是用于显示列表数据的控件,但它们在使用方法和特性上存在一些明显的差异。以下是关于它们用法不一样的地方的详细分析: 数据管理方式: ListView:使用QAbstractItemModel数据模型来管理和显示列表数据。QAbstractItemModel是一个抽象类,允许开发者自定义数据模型以适应特定的数据结构和需求。这使得ListView在处

如何使用Qt的PIMPL习惯用法(PIMPL Idiom

) PIMPL是指“Pointer to IMPLementation”(指向实现的指针),意味着将实现细节隐藏起来,用户类无需关注这些实现细节。在Qt中常用PIMPL习惯用法来清晰地区分接口与实现,尽管Qt官方文档并未详细说明该机制。本文将演示如何在Qt中使用PIMPL习惯用法,并以一个简单的坐标输入对话框作为实例。 原理与动机 PIMPL的核心在于将类的实现细节封装在一个私有类中,这个私

【Qt6.3 基础教程 17】 Qt布局管理详解:创建直观和响应式UI界面

文章目录 前言布局管理的基础为什么需要布局管理器? 盒布局:水平和垂直排列小部件示例:创建水平盒布局 栅格布局:在网格中对齐小部件示例:创建栅格布局 表单布局:为表单创建标签和字段示例:创建表单布局 调整空间和伸缩性示例:增加弹性空间 总结 前言 当您开始使用Qt设计用户界面(UI)时,理解布局管理是至关重要的。布局管理不仅关系到UI的外观,更直接影响用户交互的体验。本篇博

【Qt6.3 基础教程 16】 掌握Qt中的时间和日期:QTimer和QDateTime的高效应用

文章目录 前言QTimer:定时任务的强大工具QTimer的基本用法高级特性:单次定时器 QDateTime:处理日期和时间获取当前日期和时间日期和时间的格式化输出日期和时间计算 用例:创建一个倒计时应用结论 前言 在开发桌面应用程序时,处理时间和日期是一个常见且重要的任务。Qt框架提供了强大的工具来处理与时间相关的功能,其中QTimer和QDateTime是最核心的类。本

基于ZYNQ7000的交叉编译工具链Qt+OpenCV+ffmpeg等库支持总结

最近刚刚接触XILINX的ZYNQ板,刚接触没有十天。XILINX定位它为SOC,我也很认同,起码比TI定位MPU为SOC强很多。据说今年TI的最新产品也加入了ZYNQ板。 之前的MIPS处理器设计与实现的项目就算做告一段落,搞了将近7个月,成果显著,收获颇多,最近打算搞搞ZYNQ。 之前MIPS也有一套交叉编译工具,不过是老师提供的,自己也尝试搞了搞,太辛苦了,而且也没什么成果,因为我

Qt 5.2.0 qwt-6.1.0

环境:win7(32) qt-5.2.0 qwt-6.1.0(qt-6.1.0说支持qt5以上的版本,但是我在配置前没找到最新的qt-5.2.0与qwt-6.1.0,其实步骤的差不多,暂时没发现版本引起的问题) 一.添加环境变量(在cmd测试下qmake,如果有问题重启电脑):  Add "C:\Qt\Qt5.0.1\5.0.1\mingw47_32\bin" to your systems

防止在 Qt 中触发信号

在 Qt 中工作时,有时我们需要暂时阻止某些信号的触发。以下是一个经典场景:我们有一个 QCheckBox 对象,当用户勾选或取消勾选时,需要调用一个函数,因此我们将这个函数连接到 stateChanged(int state) 信号。然而,在某些条件下,我们在代码中更改 QCheckBox 的状态,这会导致触发不需要的信号。那么如何在特定情况下防止信号触发呢? 使用 clicked 信号 如

Python中使用PyQT5库时报错:没有Qt平台插件可以初始化

一、发现问题:无限易pythonGo打开执行的时候报:“没有Qt平台插件可以初始化,请重新安装应用程序。”的错误,点击确定后无限易崩溃闪退。 二、解决问题: 1、重新安装依赖,打开CMD输入pip list,查看Qt5库是否已安装,如果不确定是否完整安装可以再次安装一遍。 2、配置环境变量(注意是用户变量),变量名:QT_QPA_PLATFORM_PLUGIN_PATH 变量值:在CM

Qt——系统

目录 概述 事件 鼠标事件 进入、离开事件 按下事件 释放事件 双击事件 移动事件 滚轮事件 按键事件 单个按键 组合按键 定时器 QTimerEvent QTimer 窗口事件 文件 输入输出设备 文件读写类 文件和目录信息类 多线程 常用API 线程安全 互斥锁 条件变量 信号量 网络 UDP Socket TCP Socket HT

qt开发-10_LineEdit

QLineEdit 小部件是一个单行文本编辑器。行编辑允许用户使用一组有用的编辑函数输入和 编辑一行纯文本。包括撤消和重做、剪切和粘贴以及拖放。通过更改行编辑的 echoMode(),它 还可以用作“只写”字段,用于输入如密码等. 创建好项目后,进入 ui 界面,在左边的控件我们找到 lineedit ,我们拿出两个做一个登录界面。 然后添加两个按钮进去,用于账号切换和登录确认。改