1970 views|1 replies

1120

Posts

0

Resources
The OP
 

I used STM32MP1 to build an epidemic monitoring platform 3—Implementation of epidemic monitoring platform [Copy link]

1. Introduction

Previously, I used the desktop version of Qt to implement an epidemic monitoring platform: Qt-based real-time monitoring platform for the new coronavirus epidemic data (open source small project) .

Since Qt is cross-platform, and I happen to have a YA157C development board from Mir Technology, can it be implemented on an embedded platform?

The running effect of the desktop Linux version:

YA157C development board achieves the following results:

2. Acquisition of data interface

To put it simply, the implementation of the epidemic monitoring platform is the display of data, but where does the data come from?

Many Internet companies have now developed their own epidemic monitoring platforms. The data source I use here is Tencent News, which has rich data content and is relatively stable.

Data source: Real-time update: Latest developments of the COVID-19 epidemic

For more information on how to obtain the interface address, please refer to: Qt-based real-time monitoring platform for COVID-19 data (open source small project)

If all the data is placed in one interface, the amount of data will be very large, so Tencent divides the data into several interfaces.

#包含最新疫情数据、各省市最新数据、其他国家最新数据
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 

Currently only some basic data is displayed, so we only use the two sets of data https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5in this chinaTotalinterface chinaAdd.

This interface includes a lot of data, including the latest national cumulative and newly added data, the latest data of provinces, cities and other countries, etc. The file size is about 160KB, the LCD screen is a 7-inch IPS screen with a resolution of 1024x600, which is relatively large and can display a lot of information. More data will be added in subsequent versions.

Data format:

{"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. Implementation of Qt interface

In the previous desktop application, I used Qt5 version to develop. Qt5 comes with QJson parsing class, but Qt 4 does not have QJson. In order to adapt to the board with Qt 4 library, I used a third-party JSON parsing library. Here I chose the compact cJSON parsing library: [cJSON download SourceForge.net](https://sourceforge.net/projects/cjson/)

If your board uses the Qt 4 library, you can directly cross-compile and run the program without modifying it.

It only contains two files: cJSON.c and cJSON.h. Just add these two files to the project.

The entire project code is also very simple: GET interface address, save the received data locally, call cJSON to parse the data file, display the parsed data, and delete the data file. The code can be obtained from the open source address at the end of the article. The following introduces the implementation of several key parts of the code:

3.1 Parsing of JSON data

//打开保存的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 Get the local IP address

//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;
} 

The running effect of the desktop Linux version:

4. Run the Qt program on the development board

If everything runs fine on the desktop, you can use the ya157c build kit to compile the project, generate a program that can run on the development board, and then use the scp command to transfer it to the development board.

#使用网线把开发板连接上路由器
#使用udhcpc自动获取IP地址
udhcpc 

#查看获取到的ip地址
ifconfig

#确认连接到互联网
ping www.baidu.com
#如果有回复数据,说明已经成功连接上互联网

#使用scp命令或共享目录的方式把可执行文件传输到开发板上
scp qte_2019_ncov root@192.168.1.109:/home/root

#执行程序
./qte_2019_ncov 

Final result

This version is the previous version. The IP address of the development board and the number of success and failure statistics are not displayed in the upper right corner. This function has been added to the latest version of the program.

Desktop Linux version effect:

5. Use wireless module to connect to the Internet

The YA157C development board has a built-in WiFi & Bluetooth module - AP6212, which can directly connect to the wireless network, so there is no need to use an Ethernet cable to connect to the Internet.

#关闭eth0
ifconfig eth0 down

#启用wlan0
rfkill unblock wifi
ifconfig wlan0 up

#在当前文件夹生成WiFi配置文件
wpa_passphrase "M6_Note" "qwert125" > wifi.conf

#查看生成的WiFi配置信息
catwifi.conf

#加载WiFi配置文件
wpa_supplicant -B -c wifi.conf -i wlan0

#扫描附近的WiFi信息
iw dev wlan0 scan | grepSSID

#自动获取IP地址
udhcpc -i wlan0

#设置DNS
echo "nameserver 114.114.114.114" > /etc/resolv.conf

#连接互联网
iw wlan0 link

#测试网络连接
ping www.wangchaochao.top 

In order to connect to WiFi quickly and conveniently, you can write the above command into a shell script. When you need to connect to WiFi, just execute this script. First generate WiFi configuration information locally:

connect_wifi.sh script file content:

#!/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 | grepSSID

#自动获取IP地址
udhcpc -i wlan0

#配置DNS
echo "nameserver 114.114.114.114" > /etc/resolv.conf

#连接网络
iw wlan0 link echo "WiFi连接成功" 

Just change the WiFi account and password and you can use it directly.

6. Code Download

The entire Qt project code has been open sourced on Github and is compatible with Qt4/Qt5. If the download speed is very slow, you can choose Gitee in China, which will be much faster.

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

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

At present, the interface is still relatively simple. The 7-inch display screen can display a lot of content. We will try our best to improve the interface information in the future. Everyone is welcome to pay attention!


This article is from Mir Technology. Please indicate the source when reprinting.

This post is from RF/Wirelessly

Latest reply

Automatic rooting of data sources is powerful  Details Published on 2020-10-26 14:50
 

5791

Posts

44

Resources
2
 
Automatic rooting of data sources is powerful
This post is from RF/Wirelessly
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

快速回复 返回顶部 Return list