Epidemic situation Kanban based on STM32MP1 and QT

Catalog

1. Preface

Previously, I used the desktop version Qt to implement the pneumonia epidemic monitoring platform: Novel coronavirus pneumonia epidemic data real-time monitoring platform based on Qt (open source small project) . Since Qt is cross platform and just participated in the maker competition and just bought a YA157C development board of Meer technology, can it be implemented in the embedded platform?

Running effect of desktop Linux version:

YA157C development board realization effect:

2. Acquisition of data interface

The implementation of the epidemic monitoring platform, in short, is the display of data, and where does the data come from?

Now many Internet companies have made their own epidemic monitoring platform. I use Tencent News data source here, which is rich in data content and relatively stable.

Data source: Update: novel coronavirus pneumonia epidemic

The interface address can be obtained by referring to: Novel coronavirus pneumonia epidemic data real-time monitoring platform based on Qt (open source small project)

If we put all the data in one interface, the data volume will be very large, so Tencent divides the data into several interfaces

#Including the latest epidemic data, the latest data of provinces and cities, and the latest data of other countries
https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5

#Include historical data
https://view.inews.qq.com/g2/getOnsInfo?name=disease_other

#The latest disinformation
https://vp.fact.qq.com/loadmore?page=0

#Details of disinformation
https://vp.fact.qq.com/miniArtData?id=a2141851348ee5f3772c761e25bb57d7

At present, only some basic data is displayed, so we only use the two sets of data, chinaTotal and chinaAdd, in the interface of https://view.ines.qq.com/g2/getonsinfo? Name = release ﹣ H5.

This interface includes a lot of data, the latest data accumulated and added nationwide, the latest data of other countries in various provinces and cities, etc. The file size is about 160KB. The LCD screen is a 7-inch IPS screen with a resolution of 1024x600. It can display a lot of information. More data will be added in the subsequent version.

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
        },
        ...........Other data.............
        "isShowAdd": true
    }
}

3. Implementation of QT interface

In the previous desktop applications, Qt5 version is used for development. Qt5 comes with QJson parsing class, while QT4 does not. In order to adapt the board with Qt 4 library, I used the third-party JSON parsing library. The compact cJSON parsing library is selected here: cJSON download | SourceForge.net

If your board is the Qt 4 library, then the program can be used without modification and directly cross compiled and run.

There are only two files: cJSON.c and cJSON.h. add these two files to the project.

The whole 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 describes the implementation of several key parts of the code:

3.1 analysis of JSON data

//Open the saved JSON data file and call the parsing function
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();            //Delete files
    return;
}
//Parse the data and display it on the label
void Dialog::getData(QByteArray str)
{
    cJSON *ret_obj;
    cJSON *root_obj;

    root_obj = cJSON_Parse(str);   //Create JSON parsing object and return whether the JSON format is correct
    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);//Free memory
        disInfo("Update completed");
        cnt_success++;
        QString success = "ok:" + QString::number(cnt_success);
        ui->lbe_success->setText(success);
    }
}

//Display of data
void Dialog::lbeDisplay(QLabel *lbe, int num)
{
    if(num > 0)
        lbe->setText("+" + QString::number(num));
    else
        lbe->setText(QString::number(num));
}

3.2 get local IP address

//forexample:192.168.1.111
QString Dialog::GetLocalmachineIP()
{
    QString ipAddress;
    QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
    for(QHostAddress &addr : ipAddressesList)
    {
        // Find the address that is not local ip, is the ipv4 protocol, and is not the first address at the beginning of 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;
}

Running effect of desktop Linux version:

4. Run Qt program on development board

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

#Connect the development board to the router using the network cable
#Using udhcpc to obtain IP address automatically
udhcpc 

#View the acquired ip address
ifconfig

#Confirm connection to the Internet
ping www.baidu.com
#If there is reply data, it indicates that the Internet has been successfully connected

#Using scp command or shared directory to transfer executable files to development board
scp qte_2019_ncov root@192.168.1.109:/home/root

#Execution procedure
./qte_2019_ncov

Final effect

This version is of the previous version. The upper right corner does not show the IP address of the development board and the statistics of success and failure times. This function has been added to the latest version of the program.

Desktop Linux effect:

5. Use wireless module for networking

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

#Close eth0
ifconfig eth0 down

#Enable wlan0
rfkill unblock wifi
ifconfig wlan0 up

#Generate WiFi profile in current folder
wpa_passphrase "M6_Note" "qwert125" > wifi.conf

#View generated WiFi configuration information
cat wifi.conf

#Load WiFi profile
wpa_supplicant -B -c wifi.conf -i wlan0

#Scan nearby WiFi information
iw dev wlan0 scan | grep SSID

#Get IP address automatically
udhcpc -i wlan0

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

#Connect to the Internet
iw wlan0 link

#Test network connection
ping www.wangchaochao.top


In order to connect to WiFi conveniently and quickly, you can write the above command as a shell script. If you need to connect to WiFi, you can directly execute the script. First generate WiFi configuration information locally:

Contents of the connect.wifi.sh script file:

#!/bin/bash

WF_SSID="M6_Note"
WF_PASSWORD="qwert125"

#Close eth0
ifconfig eth0 down

#Enabling wlan0
rfkill unblock wifi
ifconfig wlan0 up

#Output WiFi information
echo "WiFi_SSID:$WF_SSID"
echo "WiFi_PASSWORD:$WF_PASSWORD"

#Generate WiFi configuration information in the current folder
wpa_passphrase $WF_SSID $WF_PASSWORD > $WF_SSID.conf

#Load WiFi profile
wpa_supplicant -B -c /home/root/$WF_SSID.conf -i wlan0

#Scan nearby WiFi
iw dev wlan0 scan | grep SSID

#Get IP address automatically
udhcpc -i wlan0

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

#Connection network
iw wlan0 link


echo "WiFi Successful connection"

If you change your WiFi account and password, you can use it directly.

6. Code download

The whole QT project code has been open-source in Github, Qt4/Qt5 compatible. If the download speed is very slow, you can choose domestic Gitee to be much faster.

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

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

At present, the interface is relatively simple. The 7-inch display screen can display a lot of content. After that, it will try to improve the interface information. Welcome to pay attention!

The source is: official account: mcu149 author whik

52 original articles published, 7 praised, 30000 visitors+
Private letter follow

Tags: Qt JSON network Linux

Posted on Fri, 13 Mar 2020 04:25:25 -0400 by landysaccount