| | |

我用stm32mp1做了个疫情监控平台3—疫情监控平台实现 -凯发app

文章来源:米尔科技 发布日期:2020.5.25 浏览次数:339 次

1.前言

之前我使用桌面版本qt实现了肺炎疫情监控平台:

既然qt是跨平台的,正好手里有一块米尔科技的ya157c开发板,那么能不能在嵌入式平台实现一下呢?

桌面linux版本的运行效果:

ya157c开发板实现效果:

2.数据接口的获取

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

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

数据来源:

接口地址的获取方法可以参考:

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

#包含最新疫情数据、各省市最新数据、其他国家最新数据
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](https://sourceforge.net/projects/cjson/)

如果你的板子是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 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寸的显示屏可以显示很多内容,之后会尽量完善界面信息,欢迎大家关注!


本文来自凯发app-凯发k8官网科技,原文地址: http://www.myir-tech.com/resource/540.asp,转载请注明出处。

比较和选型

手册教程

应用笔记

好书推荐

凯发k8官网的技术支持服务指南

常见问题解答

网站地图