ESP32 e WPS

Sto provando le infinite possibilità di ESP32 tra cui la possibilità di collegarsi al WiFi di casa senza configurare SSID e Password da programma ma semplicemente premendo il tasto WPS (e a questo punto diventa anche uno "sniffer" se qualcuno nel palazzo preme il tasto WPS del suo router... ma questo è un altro discorso)
Il programma WPS, compreso negli esempi della libreria ESP32 DEVKIT, funziona alla perfezione.
Allora ho provato a collegarmi ad un sito per ricevere l'ora esatte e verificare se è effettivamente connesso a internet: tutto OK !

L'unico problema è che se spengo o resetto devo rifare la procedura di accoppiamento WPS perché il programma, giustamente, non memorizza nulla su EEPROM.

Come la memorizzo la

static esp_wps_config_t config;

???

Allego, di seguito, il programma di connessione

This example code provides both Push Button method and Pin
based WPS entry to get your ESP connected to your WiFi router.

Hardware Requirements
========================
ESP32 and a Router having atleast one WPS functionality

This code is under Public Domain License.

Author:
Pranav Cherukupalli <cherukupallip@gmail.com>
*/

#include "WiFi.h"
#include "esp_wps.h"
#include "time.h"
#include <EEPROM.h>
const char* ntpServer = "pool.ntp.org";
const long  gmtOffset_sec = 3600;
const int   daylightOffset_sec = 3600;

void printLocalTime()
{
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    Serial.println("Failed to obtain time");
    return;
  }
  Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
}


/*
Change the definition of the WPS mode
from WPS_TYPE_PBC to WPS_TYPE_PIN in
the case that you are using pin type
WPS
*/
#define ESP_WPS_MODE      WPS_TYPE_PBC
#define ESP_MANUFACTURER  "ESPRESSIF"
#define ESP_MODEL_NUMBER  "ESP32"
#define ESP_MODEL_NAME    "ESPRESSIF IOT"
#define ESP_DEVICE_NAME   "ESP STATION"

static esp_wps_config_t config;

void wpsInitConfig(){
  config.crypto_funcs = &g_wifi_default_wps_crypto_funcs;
  config.wps_type = ESP_WPS_MODE;
  strcpy(config.factory_info.manufacturer, ESP_MANUFACTURER);
  strcpy(config.factory_info.model_number, ESP_MODEL_NUMBER);
  strcpy(config.factory_info.model_name, ESP_MODEL_NAME);
  strcpy(config.factory_info.device_name, ESP_DEVICE_NAME);
}

String wpspin2string(uint8_t a[]){
  char wps_pin[9];
  for(int i=0;i<8;i++){
    wps_pin[i] = a[i];
  }
  wps_pin[8] = '\0';
  return (String)wps_pin;
}

void WiFiEvent(WiFiEvent_t event, system_event_info_t info){
  switch(event){
    case SYSTEM_EVENT_STA_START:
      Serial.println("Station Mode Started");
      break;
    case SYSTEM_EVENT_STA_GOT_IP:
      Serial.println("Connected to :" + String(WiFi.SSID()));
      Serial.print("Got IP: ");
      Serial.println(WiFi.localIP());
      break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
      Serial.println("Disconnected from station, attempting reconnection");
      WiFi.reconnect();
      break;
    case SYSTEM_EVENT_STA_WPS_ER_SUCCESS:
      Serial.println("WPS Successfull, stopping WPS and connecting to: " + String(WiFi.SSID()));
      esp_wifi_wps_disable();
      delay(10);
      WiFi.begin();
      break;
    case SYSTEM_EVENT_STA_WPS_ER_FAILED:
      Serial.println("WPS Failed, retrying");
      esp_wifi_wps_disable();
      esp_wifi_wps_enable(&config);
      esp_wifi_wps_start(0);
      break;
    case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT:
      Serial.println("WPS Timedout, retrying");
      esp_wifi_wps_disable();
      esp_wifi_wps_enable(&config);
      esp_wifi_wps_start(0);
      break;
    case SYSTEM_EVENT_STA_WPS_ER_PIN:
      Serial.println("WPS_PIN = " + wpspin2string(info.sta_er_pin.pin_code));
      break;
    default:
      break;
  }
}

void setup(){
  Serial.begin(115200);
  delay(10);

  Serial.println();
  
  WiFi.onEvent(WiFiEvent);
  WiFi.mode(WIFI_MODE_STA);

  Serial.println("Starting WPS");

  wpsInitConfig();
  esp_wifi_wps_enable(&config);
  esp_wifi_wps_start(0);
  
}

void loop(){

  //init and get the time
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  printLocalTime();
  delay (5000);

}

Qualsiasi cosa in C, con un cast a byte e poi usando sizeof() per sapere quanti byte occupa, lo puoi vedere come un "array" di byte.

Poi se guardi la libreria EEPROM c'e' la put che accetta una struttura, penso possa funzionare.

Grazie Igor, il comando è chiaro.
Ma non ho capito COSA ci devo scrivere.
Ho pensato fosse &config, ma mi scrive solo 4 byte.
Poi io ammetto che queste cose non le capisco, il WiFi su Arduino per me è una novità non sapendo poi come è lo scambio di dati via WPS.
E' il router che "registra" il mio ESP32 e "apre la porta" oppure è sempre il router invia ad ESP32 una key che poi ESP32 ritrasmette quando fa la riconnessione?

A me pare strano che non memorizzi i dati di connessione, forse è un limite della procedura WPS che non ho mai usato.
Io credo che il problema stia nell'esempio perché in setup avvia sempre la procedura WPS che invece bisognerebbe avviare su comando, di solito un pulsante.

Si, appunto, ma probabilmente è un esempio da usare "as is" dove viene poi lasciato all'utente la decisione di come lo vuole implementare, se con un pulsante ecc...
Intanto sto facendo degli esperimenti ma onestamente capisco poco dell'esempio. Quindi ho pensato che la configurazione fosse su &config, ma non è detto che lo sia.

Quindi rimango in attesa dei "geni della lampada, ops.. della scheda" per sapere cosa ne pensano.

Comunque ho visto che c'era un topic già aperto e non vorrei fare dei doppioni, ma il forum sta diventando, giustamente, enorme.

Magari potrei suggerire ai moderatori di spostare anche ESP32 su megatopic (perché qualcosa mi dice che diventerà mega, altro che mega...) anche perché adesso si trova su Hardware ma non è la sua collocazione giusta.

L'ESP8266 conserva le informazioni in un'area apposita, immagino che anche l'ESP32 farà lo stesso.

Quello che devi fare è modificare lo sketch per utilizzare il WPS solo su comando, tipo premendo un pulsante, come i dispositivi commerciali.
Potrebbe anche farlo se non riesce a connettersi entro un certo tempo ma così rischi che entri in quella modalità anche quando non è necessario.

In alternativa per l'ESP8266 c'è la libreria WiFimanager, l'originale non supporta l'ESP32 ma qualcuno l'ha adattata

Questa funziona così: se non riesce a connettersi mette su un Access Point cui ti colleghi, ti si apre una pagina web e li metti i dati della rete WiFi cui dovrà collegarsi, proprio come molti dispositivi IoT. Ha anche la capacità di memorizzare più reti, almeno così dice la documentazione.

Molto interessante. Grazie mille!

steve-cr:
Magari potrei suggerire ai moderatori di spostare anche ESP32 su megatopic (perché qualcosa mi dice che diventerà mega, altro che mega...) anche perché adesso si trova su Hardware ma non è la sua collocazione giusta.

Fatto ! :slight_smile:

Guglielmo