Aller au contenu

TP04 : interface Wi-Fi et SNTP

NTP est un protocole de synchronisation des horloges pour les équipements d’Internet. SNTP en est sa version simplifiée pour les petits équipements.

Dans ce laboratoire, qui se déroule pendant 2 périodes de cours, sous forme d’exercice, nous nous connecterons au Wi-Fi avec le module de communication ESP32-WROOM-32 et nous irons synchroniser le RTC de notre cible sur un serveur de temps SNTP.

Prérequis : TP03 première partie et un module ESP32 version 2.2.0

Documentation utile : Commandes AT de l’ESP32.

Réalisation

  • Connexions au Wi-Fi de laboratoire avec notre module ESP32.
  • Connexions à un serveur SNTP.
  • Mise à jour régulière du RTC de notre cible (Thread spécifique).
  • Affichage de l’heure sur le display de la cible (facultatif).

Informations utiles

Commandes Wi-Fi pour l’ESP32

Connexion sur un AP Wi-Fi

bool Esp32::wifiConnect(const char* ssid, const char* pwd)
{
    smutex_.lock();
    esp_parser_.send("AT+CWMODE=1");
    esp_parser_.recv("OK");
    esp_parser_.send("AT+CWJAP=\"%s\",\"%s\"", ssid, pwd);
    if (esp_parser_.recv("OK")) {
        smutex_.unlock();
        return true;
    } else {
        smutex_.unlock();
        return false;
    }
}

Déconnexion d’un AP Wi-Fi

bool Esp32::wifiDisconnect()
{
    smutex_.lock();
    esp_parser_.send("AT+CWQAP");
    if (esp_parser_.recv("OK")) {
        smutex_.unlock();
        return true;
    } else {
        smutex_.unlock();
        return false;
    }
}

Lecture de l’adresse IP V4 fournie par le DHCP de l’AP Wi-Fi

bool Esp32::getIPAddress(uint8_t* ip, uint8_t* gw, uint8_t* msk)
{
    smutex_.lock();
    esp_parser_.send("AT+CIPSTA?");
    if (esp_parser_.recv("+CIPSTA:ip:\"%hhd.%hhd.%hhd.%hhd\"\r\n", &ip[0], &ip[1], &ip[2], &ip[3]) &&
        esp_parser_.recv("+CIPSTA:gateway:\"%hhd.%hhd.%hhd.%hhd\"\r\n", &gw[0], &gw[1], &gw[2], &gw[3]) &&
        esp_parser_.recv("+CIPSTA:netmask:\"%hhd.%hhd.%hhd.%hhd\"\r\n", &msk[0], &msk[1], &msk[2], &msk[3]) &&
        esp_parser_.recv("OK"))
    {
        smutex_.unlock();
        return true;
    } else {
        smutex_.unlock();
        return false;
    }
}

avec la méthode d’appel de cette fonction dans votre code …

void getIPInfo()
{
    uint8_t ip[4] = {0,0,0,0}, gw[4] = {0,0,0,0}, msk[4] = {0,0,0,0};
    if (esp_->getIPAddress(ip, gw, msk)){
        printf("Wi-Fi IP Address: %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
        printf("Wi-Fi Gateway: %d.%d.%d.%d\n", gw[0], gw[1], gw[2], gw[3]);
        printf("Wi-Fi IP Mask: %d.%d.%d.%d\n", msk[0], msk[1], msk[2], msk[3]);
    } else {
        printf("No IP Adresse info !!\n");
    }
}

Au démarrage de votre application, vous pouvez faire une initialisation propre du module avec une commande Esp32::restore ou Esp32::reset.

  • Esp32::reset permet un reboot physique de l’ESP32.
  • Esp32::restore permet de réinitialiser l’ESP32 avec ses paramètres initiaux.
bool Esp32::reset()
{
    cs_ = kCsOff_;
    ThisThread::sleep_for(1s);
    cs_ = kCsOn_;

    smutex_.lock();
    if (esp_parser_.recv("ready"))
    {
        smutex_.unlock();
        return true;
    } else {
        smutex_.unlock();
        return false;
    }
}
bool Esp32::restore()
{
    smutex_.lock();
    if (esp_parser_.send("AT+RESTORE") &&
        esp_parser_.recv("OK") &&
        esp_parser_.recv("ready"))
    {
        smutex_.unlock();
        return true;
    } else {
        smutex_.unlock();
        return false;
    }
}

Rapport et rendu

Il n’est pas demandé de rapport ni de rendu pour ce travail.

Attention : Cette matière sera examinée dans le TE 2 et en examen oral.

Vous pouvez demander une correction ou une analyse en mode revue de code de votre travail, en classe, lors de la prochaine leçon.

Exemples de codes pour l’interface SNTP

Vous trouverez ici en complément les quelques éléments de code que nous avons discuté en cours sur l’implémentation de la partie SNTP.

Configuration du service SNTP dans l’interface Esp32 :

bool Esp32::configureTimeServer(uint8_t timeZone, const char* timeServer)
{
    smutex_.lock();
    esp_parser_.send("AT+CIPSNTPCFG=1,%d,\"%s\"", timeZone, timeServer);
    if (esp_parser_.recv("OK")) {
        smutex_.unlock();
        return true;
    } else {
        smutex_.unlock();
        return false;
    }
}

Et un exemple de son utilisation dans un objet d’application :

// definition
static constexpr uint8_t kCHTimeZone_ = 2;
string kTimeServer_ = "ch.pool.ntp.org";


// appel
void SNTP::setTimeServer()
{
    const char *timeServer = kTimeServer_.c_str();
    if (esp_->configureTimeServer(kCHTimeZone_, timeServer)) printf("Time Server configured\n");
    else printf("Time Server not configured !!\n");
}

Lecture du temps dans l’interface Esp32 :

string Esp32::getNetworkTime()
{
    string sTime = "";
    smutex_.lock();
    esp_parser_.send("AT+CIPSNTPTIME?");
    if (esp_parser_.recv("+CIPSNTPTIME:")){
        bool next = true;
        while (next){
            char c = esp_parser_.getc();
            if (c != '\n') sTime.push_back(c);
            else next = false;
        }
    }
    esp_parser_.recv("OK");
    smutex_.unlock();
    return sTime;
}

Et un exemple de son utilisation dans un objet d’application :

void SNTP::getTime()
{
    // String to char* conversion to avoid compilation warnings in printf
    string sTime = esp_->getNetworkTime();
    const char *cTime = sTime.c_str();
    printf("Time : %s\n", cTime);
}

Vous trouverez encore ici une référence fort utile expliquant les différences et l’utilisation/conversion des chaînes de caractères en C et la classe String en C++ :