WPS: Inasequible al desaliento

Place your projects here
Post Reply
User avatar
Fernando Perez
Posts: 378
Joined: Mon Feb 15, 2021 10:09 pm
Location: Santander (Spain)
Has thanked: 195 times
Been thanked: 267 times

WPS: Inasequible al desaliento

Post by Fernando Perez »

I have done this translation with chatGPT. You have to innovate!

WPS: Indefatigable.
My apologies for the excessive length of this message.
I believe I have already talked in this forum about my obsession with making it easy for our gadgets with Annex to connect to the Wifi network, that is, the Internet, when we send them as gifts to our elderly family and friends with little or no computer knowledge.

As I see Cicciocb a bit hesitant to directly incorporate the WPS protocol into Annex, I will tell you about my experiments on this topic and what I have achieved so far.

I have set up two identical ESP32 devices (the Wemos D1 mini model) on the left side of each expansion board. One will be programmed in C using the Arduino IDE and the other in Annex.
On the right side of the boards, I have mounted a homemade display consisting of a 10mm RGB LED with a common anode, translucent plastic, and current limiting resistors. They are Chanzon brand and very inexpensive. The problem is that they came in bags of 50 units and I don't know what to do with so many of them!!

But they have been very useful in this case so that the end user can see how the Wifi connection process is developing in their home and inform me of the colors that are appearing.

PREPARATION:
In the first ESP32, I have loaded the C program shown using the Arduino IDE.
The only adaptation you will have to make is to replace the fictitious MAC address with the real one of your ESP32 with Annex in line 27, obtained through wlog MAC$(1) in the Immediate window.
For those of you who want to follow in my footsteps, I used IDE 1.8.19 and the Expressif 1.0.6 library.
The board configuration are shown in the video.
With this scenario, I have not encountered any dependency errors, library errors, or other problems that usually accompany Arduino projects, compiling and loading at the first attempt this time.
In the second ESP32, I have loaded Annex 1.50.1 LFS, [Local Link Removed for Guests]
Both .bas programs are shown, and a "clean" configuration has been left, that is, only the AP name, login, and password for protected access and the time zone.

USE:
The end user receives the two modules and the following instructions:
1) Find the button marked WPS on your router.
2) Connect the two received modules to the power supply.
3) When both LEDs are red, press the WPS button on the router for a few seconds.
4) If everything went well, the module with Annex will connect to the Internet and execute the program it contains.
5) The WPS module has already fulfilled its function and it is not necessary to connect it again. You can return it to me to send it to another person.

EXPLANATION:
The first module activates the red LED light, erases any saved data from a previous Wifi configuration from the flash memory, and enters "WPS listen" mode.
When it receives a valid WPS transmission, it saves the router SSID, password, and IP address offered by the router's DHCP in a struct variable.
And changes the light to amber to indicate correct reception.
Immediately, it attempts to transmit this data to the second device via ESPNOW, identified by the MAC address in line 27.
If successful, it changes the light to green. If it fails, the light remains blue.
The second module, when turned on, verifies if it has already received its configuration data previously, checking if there is a file called wifi.dat or not.
If it exists, it opens and uses its data to connect to wifi through wifi.connect. Then, it loads the main program using bas.load.
If wifi.dat does not exist, it enters ESPNOW listening mode, creates and saves the data in that file, and performs a reboot.
During this process, the colors change for better tracking.
In line 55, I have prefixed the fourth element (host address) of our IP to 90 because routers typically start assigning automatic addresses above 100.
I have trimmed the video to avoid boring you further because the Annex program takes an additional 40 seconds to complete the process after receiving the data.

Video: https://youtu.be/rHPp1Q8wCxs

WPS.ino

Code: [Local Link Removed for Guests]

#include <WiFi.h>
#include <esp_wps.h>
#include <esp_wifi.h>
#include <esp_now.h>

const int red = 23;
const int green = 18;
const int blue = 26;

static esp_wps_config_t config;

String MyIP;
String MyPass;
String MySSID;
String message;

boolean done = false;

typedef struct struct_message {
  char a[75];
} struct_message;

struct_message myData;

// mac address of the receiver, obtained by WLOG MAC$(1)
// for ESP32 Wemos D1 mini:
uint8_t broadcastAddress[] = {0x3C, 0x61, 0x05, 0xXX, 0xXX, 0xXX};
esp_now_peer_info_t peerInfo;

// -------- callback when data is sent --------
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  if (status == ESP_NOW_SEND_SUCCESS) {
    Serial.println("Packet Delivery Success");
    // LED: green light
    digitalWrite(red, HIGH);
    digitalWrite(green, LOW);
    digitalWrite(blue, HIGH);
  } else {
    Serial.println("Packet Delivery Fail");
    // LED: blue light
    digitalWrite(red, HIGH);
    digitalWrite(green, HIGH);
    digitalWrite(blue, LOW);
  }  
}

// -------- listening events --------
void WiFiEvent(WiFiEvent_t event, system_event_info_t info){
  switch(event){
    case SYSTEM_EVENT_STA_START:
      Serial.println("Starting WPS listener");
      break;
    case SYSTEM_EVENT_STA_GOT_IP:
      MyIP = WiFi.localIP().toString().c_str(); 
      break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
      WiFi.reconnect();
      break;
    case SYSTEM_EVENT_STA_WPS_ER_SUCCESS:
      esp_wifi_wps_disable();
      delay(10);
      WiFi.begin();
      break;
    case SYSTEM_EVENT_STA_WPS_ER_FAILED:
      esp_wifi_wps_disable();
      esp_wifi_wps_enable(&config);
      esp_wifi_wps_start(0);
      break;
    default:
      break;
  }
}

// -------- erase WiFi data in flash memory --------
void Network_reset(){
   wifi_config_t current_conf;
   esp_wifi_get_config((wifi_interface_t)ESP_IF_WIFI_STA, &current_conf);
   memset(current_conf.sta.ssid, 0, sizeof(current_conf.sta.ssid));
   memset(current_conf.sta.password, 0, sizeof(current_conf.sta.password));
   esp_wifi_set_config((wifi_interface_t)ESP_IF_WIFI_STA, &current_conf);
}

// -----------------------------------------------------------
void wpsInitConfig(){
  config.crypto_funcs = &g_wifi_default_wps_crypto_funcs;
  config.wps_type = WPS_TYPE_PBC;
  strcpy(config.factory_info.manufacturer, "ESPRESSIF");
  strcpy(config.factory_info.model_number, "ESP32");
  strcpy(config.factory_info.model_name, "ESPRESSIF IOT");
  strcpy(config.factory_info.device_name, "ESP STATION");
}

// -----------------------------------------------------------
void setup(){
  Serial.begin(115200);
  delay(1000);
  Serial.println();

  pinMode(red, OUTPUT);
  pinMode(green, OUTPUT);
  pinMode(blue, OUTPUT);
  // LED: red light
  digitalWrite(red, LOW);
  digitalWrite(green, HIGH);
  digitalWrite(blue, HIGH);
     
  WiFi.onEvent(WiFiEvent);
  WiFi.mode(WIFI_MODE_STA);

  // Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  esp_now_register_send_cb(OnDataSent);
  
  // Register peer
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0;  
  peerInfo.encrypt = false;
  
  // Add peer        
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }

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

// -----------------------------------------------------------
void loop(){
  wifi_config_t config;
  esp_err_t err = esp_wifi_get_config(WIFI_IF_STA, &config);
  MySSID = (char*) config.sta.ssid;
  MyPass = (char*) config.sta.password;

  if (MyPass == "") {
    Serial.println("Press the WPS button on the router");
  } else {
    Serial.println();
    Serial.println(MySSID); 
    Serial.println(MyPass);
    Serial.println(MyIP);

    if (done == false) {
      Serial.println("Receiving data from the router");
      // LED: amber light
      digitalWrite(red, LOW);
      digitalWrite(green, LOW);
      digitalWrite(blue, HIGH);
      done = true;
      delay(5000);
    }
    delay(3000);

    message = MySSID + " " + MyPass + " " + MyIP;
    message.toCharArray(myData.a, 75);
    esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData)); 
  }
  delay(3000);
}
boot.bas

Code: [Local Link Removed for Guests]

' LED RGB common anode
red = 23 : pin.mode red, OUTPUT
blue = 26 : pin.mode blue, OUTPUT
green = 18 : pin.mode green, OUTPUT
' invert for common cathode:
LOW = 0 : HIGH = 1

line$ = "" : times = 0

if file.exists("/wifi.dat") then
  gosub wifiConnect
else
  gosub espnowConnect
  onEspNowMsg message
  wait  
endif

' Here begins the real program:
r = bas.load "/rainbow.bas"

END

' -------------------------
message:
  line$ = espnow.read$
  if times > 4 then  ' wait 4 messages
    file.append "/wifi.dat", line$
    reboot
  else
    times = times + 1
  endif        
return

' -------------------
espnowConnect:
  fail = espnow.begin()
  if fail then
    wlog "ESP-NOW Error"
    ' LED: blue light
    pin(red) = HIGH
    pin(blue) = LOW
    pin(green) = HIGH    
    END
  else
    wlog "ESP-NOW active" 
   ' LED: red light
   pin(red) = LOW
   pin(blue) = HIGH
   pin(green) = HIGH  
  endif
return

' -------------------
wifiConnect:
  MyIP$ = "90"
  MyMask$ = "255.255.255.0"
  MyGateway$ = "1"
  
  line$ = file.read$("/wifi.dat")
  MySSID$ = word$(line$, 1)
  MyPass$ = word$(line$, 2)
  baseIP$ = word$(line$, 3)
  MyIP$ = replace$(baseIP$, word$(baseIP$, 4, "."), MyIP$)
  MyGateway$ = replace$(baseIP$, word$(baseIP$, 4, "."), MyGateway$)
     
  wlog MySSID$
  wlog MyPass$
  wlog baseIP$
  wlog MyIP$
  wlog MyMask$
  wlog MyGateway$

  wifi.connect MySSID$, MyPass$,, MyIP$, MyMask$, MyGateway$

  pause 2000
  if wifi.status = 3 then
    wlog "Conected to internet"
    ' LED: green light
    pin(red) = HIGH
    pin(blue) = HIGH
    pin(green) = LOW
  else
    wlog "Internet connection fails"
    ' LED: blue light
    pin(red) = HIGH
    pin(blue) = LOW
    pin(green) = HIGH    
  endif  

return

rainbow.bas

Code: [Local Link Removed for Guests]

LOW = 0 : HIGH = 1

red = 23 : pin.mode red, OUTPUT
blue = 26 : pin.mode blue, OUTPUT
green = 18 : pin.mode green, OUTPUT

while 1

  pin(red) = LOW
  pin(blue) = LOW
  pin(green) = LOW
  pause 150

  pin(red) = LOW
  pin(blue) = LOW
  pin(green) = LOW
  pause 150

  pin(red) = LOW
  pin(blue) = LOW
  pin(green) = HIGH
  pause 150

  pin(red) = LOW
  pin(blue) = HIGH
  pin(green) = LOW
  pause 150

  pin(red) = LOW
  pin(blue) = HIGH
  pin(green) = HIGH
  pause 150

  pin(red) = HIGH
  pin(blue) = LOW
  pin(green) = LOW
  pause 150

  pin(red) = HIGH
  pin(blue) = LOW
  pin(green) = HIGH
  pause 150

  pin(red) = HIGH
  pin(blue) = HIGH
  pin(green) = LOW
  pause 150

  pin(red) = HIGH
  pin(blue) = HIGH
  pin(green) = HIGH
  
  connect = ping("www.google.com")
  if connect then
    wlog "Ping to Google OK" 
  else
    wlog "Internet connection fails"
  endif
  pause 5000

wend

BeanieBots
Posts: 344
Joined: Tue Jun 21, 2022 2:17 pm
Location: South coast UK
Has thanked: 182 times
Been thanked: 112 times

Re: WPS: Inasequible al desaliento

Post by BeanieBots »

A very neat and clever idea. Thanks for sharing.
One possible thought for your 'spare' LEDs.
Something my elderly relatives don't seem to get is that there are WIFI blackspots around there homes.
Perhaps you could add some extra LEDs to indicate RSSI so that once setup, they can roam around and get an idea of where and where not they can use devices that use WIFI.
User avatar
cicciocb
Site Admin
Posts: 2041
Joined: Mon Feb 03, 2020 1:15 pm
Location: Toulouse
Has thanked: 436 times
Been thanked: 1342 times
Contact:

Re: WPS: Inasequible al desaliento

Post by cicciocb »

Hi Fernando,
It looks like a nice idea for the configuration.

I could eventually in the future implement a mechanism for the inclusion of the WPS configuration but I miss of valid ideas on how make it easy.
Post Reply