我用STM32MP1做了个疫情监控平台3—疫情监控平台实现
@
0.系列教程
- 我用STM32MP1做了个疫情监控平台1—交叉编译环境搭建
- 我用STM32MP1做了个疫情监控平台2—Qt环境搭建
- 我用STM32MP1做了个疫情监控平台3—疫情监控平台实现
- 我用STM32MP1做了个疫情监控平台4—功能完善界面重新设计
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
这个接口中的chinaTotal
和chinaAdd
这两组数据。
这个接口包括很多数据,全国累计和新增的最新数据,各省市其他国家的最新数据等等。文件大小大概在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));
else
lbe->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 localhost
if (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/bash
WF_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 link
echo "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寸的显示屏可以显示很多内容,之后会尽量完善界面信息,欢迎大家关注!
系列教程
- 我用STM32MP1做了个疫情监控平台1—交叉编译环境搭建
- 我用STM32MP1做了个疫情监控平台2—Qt环境搭建
- 我用STM32MP1做了个疫情监控平台3—疫情监控平台实现
- 我用STM32MP1做了个疫情监控平台4—功能完善界面重新设计
我的公众号:mcu149
我用STM32MP1做了个疫情监控平台3—疫情监控平台实现的更多相关文章
- 我用STM32MP1做了个疫情监控平台4—功能完善界面重新设计
目录 前言 界面展示 新增功能 API 接口说明 多个接口数据的获取和解析 FontAwesome字体图标库的使用 代码下载 系列教程 @ 前言 之前我用STM32MP1和Qt实现了疫情监控平台,系列 ...
- 我用STM32MP1做了个疫情监控平台2—Qt环境搭建
目录 1.嵌入式Qt简介 2.查看开发板Qt库的版本 3.主机搭建Qt环境 4.第一个Qt程序--Hello World 5.一些问题 @ 1.嵌入式Qt简介 Qt 是一个跨平台的应用程序开发框架.使 ...
- 总结2015搭建日志,监控,ci,前端路由,数据平台,画的图与界面 - hugo - ITeye技术网站
总结2015搭建日志,监控,ci,前端路由,数据平台,画的图与界面 - hugo - ITeye技术网站 极分享:高质分享+专业互助=没有难做的软件+没有不得已的加班 极分享:高质分享+专业互助=没有 ...
- 性能测试三十三:监控之Linux系统监控命令大全
1.top命令top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器.下面详细介绍它的使用方法.top - 01:06:48 up 1: ...
- 服务容错保护断路器Hystrix之三:断路器监控(Hystrix Dashboard)-单体监控
turbine:英 [ˈtɜ:baɪn] 美 [ˈtɜ:rbaɪn] n.汽轮机;涡轮机;透平机 一.Hystrix Dashboard简介 在微服务架构中为了保证程序的可用性,防止程序出错导致网络阻 ...
- 重磅发布丨乐维监控:全面兼容云平台,助力企业DevOps转型升级!
2019年伊始,我们迎来了乐维监控的又一重大功能更新——云平台监控,这将有效帮助企业将云上.云下数据聚合,方便统一化的监控管理与维护!未来,乐维监控每一次的产品功能及版本更新,我们都将第一时间于此发布 ...
- 转 HystrixDashboard服务监控、Turbine聚合监控
SpringCloud系列七:Hystrix 熔断机制(Hystrix基本配置.服务降级.HystrixDashboard服务监控.Turbine聚合监控) 1.概念:Hystrix 熔断机制 2.具 ...
- SpringCloud (十) Hystrix Dashboard单体监控、集群监控、与消息代理结合
一.前言 Dashboard又称为仪表盘,是用来监控项目的执行情况的,本文旨在Dashboard的使用 分别为单体监控.集群监控.与消息代理结合. 代码请戳我的github 二.快速入门 新建一个Sp ...
- 快速接入业务监控体系,grafana监控的艺术
做一个系统,如果不做监控,是不完善的. 如果为做一个快速系统,花力气去做监控,是不值得的. 因为,我们有必要具备一个能够快速建立监控体系的能力.即使你只是一个普通开发人员! 个人觉得,做监控有三个核心 ...
随机推荐
- LintCode排序
1.LintCode整数排序 给一组整数,按照升序排序,使用选择排序,冒泡排序,插入排序或者任何 O(n2) 的排序算法. 您在真实的面试中是否遇到过这个题? 是 样例 对于数组 [3, 2, 1, ...
- caffe之那些依赖的库
1. Boost库 Boost是一个可移植的,提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一.Boost强调对跨平台的支持,编译与平台无关.Caffe采用C++为主要开发语言 ...
- Mac 环境docker 安装jenkins
网上很多的教程是讲的是Linux 上的Docker安装Jenkins,但是我用的是Mac,所以参考之前的前辈写的文章,记录一下自己的安装过程.非常感谢参考文章的前辈写的文章. 参考Docker安装Je ...
- JavaScript常见排序算法
1.冒泡排序 function bubble_sort(arr) { if (arr.length <= 1) { return arr; } var len = arr.length; for ...
- Apple store,奢华背后的辛酸
store,奢华背后的辛酸" title="Apple store,奢华背后的辛酸"> 2000年的时候,乔布斯提出了要建造苹果直营店,也就是Apple st ...
- flume install
flume install flume 安装 123456 [root@10 app][root@10 app]# mv apache-flume-1.7.0-bin /mnt/app/flume[r ...
- 11--PHP中的类和对象
PHP类和对象 类是面向对象程序设计的基本概念,通俗的理解类就是对现实中某一个种类的东西的抽象, 比如汽车可以抽象为一个类,汽车拥有名字.轮胎.速度.重量等属性,可以有换挡.前进.后退等操作方法. 通 ...
- 【WPF学习】第五十一章 动画缓动
线性动画的一个缺点是,它通常让人觉得很机械且不能够自然.相比而言,高级的用户界面具有模拟真实世界系统的动画效果.例如,可能使用具有触觉的下压按钮,当单击时按钮快速弹回,但是当没有进行操作时它们会慢慢地 ...
- LeetCode python实现题解(持续更新)
目录 LeetCode Python实现算法简介 0001 两数之和 0002 两数相加 0003 无重复字符的最长子串 0004 寻找两个有序数组的中位数 0005 最长回文子串 0006 Z字型变 ...
- 难住了同事:Java 方法调用到底是传值还是传引用
Java 方法调用中的参数是值传递还是引用传递呢?相信每个做开发的同学都碰到过传这个问题,不光是做 Java 的同学,用 C#.Python 开发的同学同样肯定遇到过这个问题,而且很有可能不止一次. ...