WIFI name (char*) behaves strangely when save to static class

Viewed 108

I'm using esp-wroom-32 dev kit to make a small IoT project. My application has a WiFi scanner function.

When I placed everything in one main.cpp file, everything was ok, but my code was hard to read or maintain, therefore, I decided to move the WiFi function into classes. It consists of 2 files:

  1. WirelessNetworkManager (for scanning networks, save into its memory and retrieved for future use)
  • .h file
class WirelessNetworkManager {

private:

    // Available networks that have been searched.
    LinkedList<WirelessNetwork> _availableNetworks;

    // Network which have been selected.
    WirelessNetwork *_selectedNetwork;

    // The last time when networks are scanned.
    float _lastScanTime;

    // Id of network which item will be retrieved previously.
    int _previousPageId;

    // Id of network from which item will be retrieved
    int _pageId;

public:

    WirelessNetworkManager();

    // Get list of available networks.
    LinkedList<WirelessNetwork> *getAvailableNetworks();

    // Get list of wireless networks by using page id & maximum records per page.
    WirelessNetwork *getAvailableNetworks(int pageId, int maxRecords, int &length);

    // Get the id of page.
    int getPageId() const;

    // Get the selected network.
    WirelessNetwork *getSelectedNetwork();

    // Select wireless network by specifying its index.
    void selectWirelessNetwork(int index);

    // Disconnect to from the connect network (if any)
    static void disconnect() ;

    // Mark page to be loaded.
    void markPageLoaded();

    // Whether network records must be updated.
    bool shouldRecordsRefreshed() const;

    // Go to next network page
    void goForward();

    // Go to previous network page
    void goBackward();
};
  • .cpp file
#include <WirelessNetworkManager.h>
#include <WiFi.h>

//#region Constructor

WirelessNetworkManager::WirelessNetworkManager() {
    this->_lastScanTime = -1.0f;
    this->_selectedNetwork = nullptr;
    this->_availableNetworks = LinkedList<WirelessNetwork>();
    this->_pageId = 0;
    this->_previousPageId = -1;
}

//#endregion

//#region Methods

LinkedList<WirelessNetwork> *WirelessNetworkManager::getAvailableNetworks() {

    LinkedList<WirelessNetwork> *allNetworks = nullptr;

    // Clear the previous loaded network.
    this->_availableNetworks.clear();
    this->_previousPageId = -1;
    this->_pageId = 0;

    // Clear the selected network.
    this->_selectedNetwork = nullptr;

    // WiFi.scanNetworks will return the number of networks found
    int iDiscoveredNetworks = WiFi.scanNetworks();
    delay(20);

    // No network is discovered.
    if (iDiscoveredNetworks == 0) {
        return &this->_availableNetworks;
    }

    LinkedList<WirelessNetwork> availableNetworks;

    for (int iNetworkIndex = 0; iNetworkIndex < iDiscoveredNetworks; iNetworkIndex++) {
        String ssid(WiFi.SSID(iNetworkIndex));
        char iSignalStrength = WiFi.RSSI(iNetworkIndex);
        bool bIsProtected = WiFi.encryptionType(iNetworkIndex) != WIFI_AUTH_OPEN;

        // Enlist the available networks.
        WirelessNetwork availableNetwork = WirelessNetwork(ssid.c_str(), iSignalStrength, bIsProtected);
        availableNetworks.add(availableNetwork);
    }

    this->_availableNetworks = availableNetworks;

    allNetworks = &this->_availableNetworks;
    return allNetworks;
}

WirelessNetwork *WirelessNetworkManager::getAvailableNetworks(int pageId, int maxRecords, int& length) {


    if (this->_availableNetworks.size() < 1) {
        length = 0;
        return new WirelessNetwork[0];
    }

    // Update the page id.
    this->_pageId = pageId;

    // Get the records which must be skipped.
    int skippedRecords = this->_pageId * maxRecords;
    int endRecordId = skippedRecords + maxRecords;
    if (endRecordId > this->_availableNetworks.size()) {
        endRecordId = this->_availableNetworks.size();
    }

    length = endRecordId - skippedRecords;
    WirelessNetwork availableNetworks[length];

    Serial.print("Items = ");
    Serial.println(this->_availableNetworks.size());

    Serial.print("Skipped records = ");
    Serial.println(skippedRecords);

    Serial.print("End records = ");
    Serial.println(endRecordId);

    int index = 0;
    for (int j = skippedRecords; j < endRecordId; j++) {

        Serial.print("Id ");
        Serial.println(j);

        char szItemTitle[128] = "";
        char szValue[10] = "";
        char szNetworkName[128] = "";
        const bool bIsProtected = this->_availableNetworks.get(j).getProtected();

        strcat(szItemTitle, " ");
        strcat(szNetworkName, this->_availableNetworks.get(j).getName());
        strcat(szItemTitle, szNetworkName);
        strcat(szItemTitle, !bIsProtected ? " " : "*");
        Serial.println(szItemTitle);

        WirelessNetwork availableNetwork(szNetworkName,
                                         this->_availableNetworks.get(j).getStrength(), this->_availableNetworks.get(j).getProtected());
        availableNetworks[index] = availableNetwork;
//        *(availableNetworks + index) = availableNetwork;
        index++;
    }

    length = 0;
    return new WirelessNetwork[0];
}

int WirelessNetworkManager::getPageId() const {
    return this->_pageId;
}

WirelessNetwork *WirelessNetworkManager::getSelectedNetwork() {
    return this->_selectedNetwork;
}

void WirelessNetworkManager::selectWirelessNetwork(int index) {

    if (index < 0 || index > this->_availableNetworks.size() - 1) {
        return;
    }

    WirelessNetwork selectedNetwork = this->_availableNetworks.get(index);
    this->_selectedNetwork = &selectedNetwork;
}

void WirelessNetworkManager::disconnect() {
    WiFi.disconnect();
}

void WirelessNetworkManager::markPageLoaded() {
    this->_previousPageId = this->_pageId;
}

bool WirelessNetworkManager::shouldRecordsRefreshed() const {
    return this->_pageId != this->_previousPageId;
}

void WirelessNetworkManager::goForward() {
    // TODO: Check if page can be gone forward or not.
    this->_pageId++;
}

void WirelessNetworkManager::goBackward() {
    // TODO: Check if page can be gone backward or not.
    if (this->_pageId < 2) {
        return;
    }

    this->_pageId--;
}

//#endregion
  1. WirelessNetwork (define wireless network as entities)

.h file

class WirelessNetwork {
private:

    // Name of network.
    char m_szName[128];

    // Signal strength.
    char m_iSignalStrength;

    // Whether wifi is protected or not.
    bool m_bIsProtected;

public:

    WirelessNetwork();

    // Constructor
    WirelessNetwork(const char *name, char signalStrength, bool isProtected);

    WirelessNetwork(WirelessNetwork const &wirelessNetwork);

    // Get network name.
    const char *getName();

    // Get network strength.
    char getStrength();

    // Whether wifi is protected or not.
    bool getProtected();
};

.cpp file

#include "WirelessNetwork.h"
#include <cstring>

//#region Constructor

WirelessNetwork::WirelessNetwork() {

}

WirelessNetwork::WirelessNetwork(const char *name, char signalStrength, bool bIsProtected) {
    strcpy(this->m_szName, name);
    this->m_iSignalStrength = signalStrength;
    this->m_bIsProtected = bIsProtected;
}

WirelessNetwork::WirelessNetwork(WirelessNetwork const &wirelessNetwork) {
    strcpy(this->m_szName, wirelessNetwork.m_szName);
    this->m_iSignalStrength = wirelessNetwork.m_iSignalStrength;
    this->m_bIsProtected = wirelessNetwork.m_bIsProtected;
}

//#endregion

//#region Methods

const char *WirelessNetwork::getName() {
    char* szName = this->m_szName;
    return szName;
}

char WirelessNetwork::getStrength() {
    return this->m_iSignalStrength;
}

bool WirelessNetwork::getProtected() {
    return this->m_bIsProtected;
}


//#endregion

This is how I use them in main.cpp file:

#include <Wire.h> //Including wire library
#include "WiFi.h"
#include "WirelessNetwork.h"
#include <LinkedList.h>
#include <HTTPClient.h>
#include <WirelessNetworkManager.h>

#define NETWORK_VIEW_ID 1


#define NETWORK_STATUS_LOADED 1
#define NETWORK_STATUS_LOADING  2


// Instance for managing wireless connection.
WirelessNetworkManager *m_WirelessNetworkManager = new WirelessNetworkManager();

int m_iMaxNetworkPageItems = 4;
bool m_bMustLoadWifiNetworks = true;
int m_iActivatedScreen = NETWORK_VIEW_ID;
int m_NetworkProcessStatus = NETWORK_STATUS_LOADING;

void setup() {

    // Open serial connection.
    Serial.begin(115000);

    // Set WiFi to station mode and disconnect from an AP if it was previously connected
    WiFi.mode(WIFI_STA);
    WiFi.disconnect();
}

void loop() {

    String message;

    if (m_iActivatedScreen != NETWORK_VIEW_ID) {
        return;
    }

    // Networks must be loaded.
    if (m_bMustLoadWifiNetworks) {

        m_bMustLoadWifiNetworks = false;
        m_NetworkProcessStatus = NETWORK_STATUS_LOADING;

        // Scan for available networks.
        LinkedList <WirelessNetwork> *availableNetworks = m_WirelessNetworkManager->getAvailableNetworks();

        // No network is discovered.
        if (availableNetworks->size() < 1) {
            return;
        }

        for (int i = 0; i < availableNetworks->size(); i++) {
            char szItemTitle[128] = "";
            char szValue[10] = "";
            char szNetworkName[128] = "";
            const bool bIsProtected = availableNetworks->get(i).getProtected();

            strcat(szItemTitle, " ");
            strcat(szNetworkName, availableNetworks->get(i).getName());
            strcat(szItemTitle, szNetworkName);
            strcat(szItemTitle, !bIsProtected ? " " : "*");

            // Log the networks onto terminal
            Serial.println(szItemTitle);
        }

        m_NetworkProcessStatus = NETWORK_STATUS_LOADED;
    }

    // Wifi already loaded.
    if (m_NetworkProcessStatus == NETWORK_STATUS_LOADED && m_WirelessNetworkManager->shouldRecordsRefreshed()) {

        int pageId = m_WirelessNetworkManager->getPageId();

        // Get the available networks which have been paginated.
        int length = 0;
        WirelessNetwork *paginatedNetworks = m_WirelessNetworkManager->getAvailableNetworks(pageId,
                                                                                            m_iMaxNetworkPageItems,
                                                                                            length);

        Serial.print("Length = ");
        Serial.println(length);
        for (int iNetworkIndex = 0; iNetworkIndex < length; iNetworkIndex++) {

            // Get the available network.
            WirelessNetwork availableNetwork = *(paginatedNetworks + iNetworkIndex);

            char szItemTitle[128] = "";
            char szValue[10] = "";
            char szNetworkName[128] = "";
            const bool bIsProtected = availableNetwork.getProtected();

            strcat(szItemTitle, " ");
            strcat(szNetworkName, availableNetwork.getName());
            strcat(szItemTitle, szNetworkName);
            strcat(szItemTitle, !bIsProtected ? " " : "*");

            delay(20);
        }

        m_WirelessNetworkManager->markPageLoaded();
    }
}

This is what happening:

  1. When I use m_WirelessNetworkManager->getAvailableNetworks() to scan for available networks and display them on the screen, the networks are displayed correctly, which are:
  • WiFI 01
  • Wifi 02
  • Wifi 03
  • Wifi 04
  1. Those wifi networks are saved automatically into WirelessNetworkManager
  2. Then I used WirelessNetwork *paginatedNetworks = m_WirelessNetworkManager->getAvailableNetworks(pageId, m_iMaxNetworkPageItems,length) to display records with pagination info, the list was displayed as:
  • WiFI 01
  • *&(&(*&( (Strange characters)
  • &*^&*^*& (Strange characters)

It is very weird, I'm still debugging this issue, one thing I'm thinking about is char* pointer, I think they are pointing to dangling pointer, but don't know whether what I'm thinking is correct or not.

Are there any ways to handle string correctly in C++ ? As C#, string is primitive, can we do that in C++ ?

Thank you,

0 Answers
Related