Embedded Linux Qt Application Development: WiFi Search, Display, and Connection

Click the “Embedded Application Research Institute” above, and select “Top/Star Public Account

Useful resources delivered to you first!

Source: CSDN

Author | Rookie Qingqing

Organizer | Embedded Application Research Institute

Recently, I have been working on the WiFi connection features for an embedded Linux product. I spent a week successfully completing the scanning, connecting, and status querying of WiFi on QT, and also implemented full keyboard input functionality. The entire logic is somewhat complex, and some design ideas were inspired by the analysis of the brother below. I will open-source it in another way when I have time.

When the WiFi is off, the entire page only has those two controls, so the page is quite simple.

Embedded Linux Qt Application Development: WiFi Search, Display, and Connection

However, as someone without a requirements document, I was dumbfounded at first glance. It’s like when the client says: My requirements are very simple, just develop a mobile Taobao for me.

Is it really that simple? (Black man question) After roughly brainstorming all the hard and hidden requirements, I asked the PM: Is it a page flip or a swipe? The PM replied: It’s a swipe, just like Apple’s. “Got it”

There’s no way around it; someone has to suffer in development. If the programmer isn’t suffering, then the user must be. If the PM doesn’t want to suffer, the programmer has to suffer. If the programmer doesn’t want to suffer, then the boss will suffer, and your wallet won’t be happy this month either.

Alright, let’s analyze what functional points such a seemingly simple page needs.

First, let me introduce my environment. I use Qt in a Linux environment, cross-compiling to debug on an ARM board, which comes with a WiFi module, and I can use most Linux commands freely.

First, I need to get WiFi information through console commands. According to the diagram, I need at least the WiFi name, signal strength, and encryption method. There are many commands to get WiFi, but simply calling commands to get the WiFi information file is not directly usable; I also need to extract the string information from it. Assuming we have obtained this content through some commands, we also need to pass them to the main program through code. Only by doing this can the preparatory work be considered complete.

When entering the WiFi page for the first time, the WiFi button is off by default. Clicking the WiFi button triggers a lot of processing. First, it searches for nearby WiFi and displays it on the lower part of the page. The search and extraction of information have been handled above; we just need to read them line by line in the main program using the system command.

Next, the display becomes a bit tricky. First, we need a rough layout. Since we need to implement dragging, we need to create a large ScrollArea and place a widget inside it as the drag canvas. In this widget, we need to insert WiFi content one by one; they are small widgets containing three controls: WiFi name, signal strength, and encryption method, arranged side by side. In code, it looks like this:

vLayout = new QVBoxLayout;
{
    gridLayout = new QGridLayout;
    
    wifiWidget[curLine] = new QWidget(this);
    
    gridLayout -> addWidget(wifiNameLabel[curLine],0,0,1,3);
    gridLayout -> addWidget(lockLabel[curLine],0,3,1,1);
    gridLayout -> addWidget(signLevelLabel[curLine],0,4,1,1);
    
    wifiWidget[curLine] -> setLayout(gridLayout);
    vLayout -> addWidget(wifiWidget[curLine]);
}
scrollWidget -> setLayout(vLayout);

Since ScrollArea comes with borders and scroll bars, if we want to design it in the Apple style, we need to modify the properties of ScrollArea.

scrollArea -> setFrameShape(QFrame::NoFrame);   // No border
scrollArea -> setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);   // Disable scroll bar

At this point, we have a WiFi page that is visually acceptable, but it cannot be dragged yet.

Next, we need to set the content displayed in the WiFi list. By using readLine() and other methods, we get the WiFi name and pass it to the WiFi name label. Similarly, we obtain the signal strength, calculate the WiFi quality, and pass it to the corresponding image of the signal label. Finally, we check if there is encryption; currently, most are WPA2 encrypted, and WiFi without a password will not parse such content.

Then comes the careful layout. If we want to set a visible separator line between adjacent WiFi information, we can set the stylesheet for the widget.

border-bottom: 1px solid black;

The open button stops here for now; next is the close button.

When the close button is clicked, we need to disconnect the WiFi, and we will also use the system command for this. Then, we hide the ScrollArea and the widget inside it, restoring the page to its previous state with only two controls.

It is advisable to write the open and close button events together and check them separately, then separate the methods for WiFi searching and disconnecting.

Next, let’s discuss mouse events. When the WiFi button is open, the user can click on any WiFi to enter the password input connection page. Since the click is not on a button but on a widget, we cannot use Qt’s slot functions, so we can use eventFilter as a substitute. We install an eventFilter on each WiFi widget.

installEventFilter(this);

Then we edit the eventFilter. First, we need to trigger the eventFilter through some mouse event; generally, the mouse release event is the most suitable.

By the way, the previous page cannot be dragged yet. To implement dragging, we need to modify the mouse events, mainly controlling the change in coordinates.

void mouseMoveEvent(QMouseEvent *e)
{
    if (!m_bMousePressed)
    {
        return;
    }

    QPoint currentPt = e->pos();

    int dist = m_PressPosition.y() - currentPt.y();

    scrollArea->verticalScrollBar()->setValue(scrollArea->verticalScrollBar()->value() + dist);

    m_PressPosition = currentPt;

    keeping = true;
}

void mousePressEvent(QMouseEvent *e)
{
    m_bMousePressed = true;

    m_PressPosition = e->pos();
}

void mouseReleaseEvent(QMouseEvent *e)
{
    Q_UNUSED(e);
    m_bMousePressed = false;

    m_PressPosition.setX(0);
    m_PressPosition.setY(0);

    keeping = false;
}

Here, keeping is used to monitor whether the mouse is pressed. If we don’t add this, there will be issues when judging press or release events. If the press triggers the eventFilter, you will find that dragging will directly jump; if the release triggers the eventFilter, then after dragging the page, it will immediately jump back to the WiFi connection page you first clicked. Therefore, such a monitoring flag is essential.

With mouse events, we can now write the eventFilter. At the beginning of the eventFilter, we first check the keeping flag. If the user is currently in the keeping (dragging state), we do not need to respond and directly return. First, we need to determine which WiFi was clicked; we can do this by monitoring obj->objectName().contains the widget name. When we define the WiFi widget earlier, we can set a custom WiFi name and include various information about the WiFi, then monitor the clicked obj to see which WiFi widget was clicked. Once we determine which WiFi was clicked, we can pop up the password input page just like writing a slot function.

Speaking of adding, we also need to control it through the system command. You just need to pass the WiFi name selected by the user on the WiFi page and the password entered on this page into the system command; the specific details are not difficult.

Finally, there is the memory function.

Why do we need memory? The page’s switch is off by default. When the user connects to WiFi successfully, exits this page, and accidentally re-enters this page, although the WiFi is still connected, the page will only have those two bare controls, and the user will definitely be confused. Therefore, we need to remember the switch state of the user when leaving the page. We can write the state of the switch using QSettings to a configuration file.

The key is the timing of reading and writing, which needs to be controlled according to the actual situation. In addition, when the user re-enters the page and the button is on, we need to search for WiFi again and display it.

Besides, there are a lot of detail issues. Due to space limitations, this article only introduces a general framework; there are still some detailed functional points that I haven’t included. In short, the actual coding for this part is far more troublesome than what is written above. Moreover, due to the lack of documentation, many features were thought of suddenly and modified extensively.

So, even though the PM only showed me two controls, the logic behind them is profound. Many seemingly simple requirements are just that the proposer has not thought carefully or lacks the ability to think, failing to see the essence of the problem.

For PMs, a detailed requirement document and a summary design document are very important for programmers. Although programmers often do not read these documents, they are equivalent to a dictionary— a dictionary for software development. Only by fully understanding the content can one quickly form the software architecture and write beautiful, maintainable, and highly reusable code.

Past Highlights

Embedded QT Application Development for QR Code Generation

How to Solve Incomplete Data Reception in Qt Serial Communication?

Realizing the dream of a small car, building a smart small car (4) with Qt upper computer control

WiFi DTU Product Design and Implementation (Based on STM32F103 + QT Configuration Upper Computer Case Design Sharing)

If you find this article helpful, please click<span>[Looking]</span> and share it, which is also a support for me.

Leave a Comment