Connection to WiFI Access Point happen once of two in a network with two AP

Dear all

The WiFi.begin(ssid, pass) initialize the library network with a specific SSID. In some home network can happen that two or more AP with the same SSID are in place. It is important that the library selects the best AP (the one with the strongest signal). I've noticed, however that using the https://github.com/espressif/arduino-esp32/archive/master.zip ES32 library it doesn't happen, and to connect to an Access point with the same SSID, the below example works once out of two. After the first hw reset of the nINA-W102 SDK the board connects the AP, after the second no, after the third reset, yes and so on.

#include <WiFi.h>
#include "Esp32MQTTClient.h"

// Please input the SSID and password of WiFi
const char* ssid = "My SSID";
const char* password = "pass";

/*String containing Hostname, Device Id & Device Key in the format:                         */
/*  "HostName=<host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>"                */
/*  "HostName=<host_name>;DeviceId=<device_id>;SharedAccessSignature=<device_sas_token>"    */
static const char* connectionString = "HostName=mqtt.eclipse.org";

static bool hasIoTHub = false;

void setup()
{  
  Serial.begin(115200);
  Serial.println("\n\nStarting connecting WiFi\n");
  delay(20);


  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println("\nWiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  if (!Esp32MQTTClient_Init((const uint8_t*)connectionString))
  {
    hasIoTHub = false;
    Serial.println("Initializing IoT hub failed.");
    return;
  }
  
  hasIoTHub = true;
  
} // Setup

void loop()
{  
  if (hasIoTHub)
  {
    char buff[128];

    // replace the following line with your data sent to Azure IoTHub
    // snprintf(buff, 128, "{\"topic\":\"iot\"}");
    snprintf(buff, 128, "{\"paolo\":\"alarm\"}");
  
    if (Esp32MQTTClient_SendEvent(buff))
    {
      Serial.println("Sending data succeed");
    }
    else
    {
      Serial.println("Failure...");
    }
    
  delay(5000);
  
  } // if
} // loop

SERIAL port output

------------------------------- After first RESET of the board ------------------------------------------------

NINA-B102 EVK reset asserted:

Serial output :

...ets Jun 8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x33 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:10044
load:0x40080400,len:5872
entry 0x400806ac

Starting connecting WiFi <-AP connected !

.
WiFi connected
IP address:
192.168.10.43
Info: Initializing SNTP

Info: SNTP initialization complete

Info: IoT Hub SDK for C, version 1.1.23

------------------------ After the second RESET of the board ------------------------------------------------

ets Jun 8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x33 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:10044
load:0x40080400,len:5872
entry 0x400806ac

Starting connecting WiFi

....................................... <- NO connection to the AP

pberna:
It is important that the library selects the best AP (the one with the strongest signal).

Says who? This sounds more like an application layer task. If you want to connect to the AP with the strongest signal you should look for all valid AP and then connect to the strongest one.

Could you please modify your original post and add code tags to your source code. It should look like this.

Your example code

Please read the "How to post" for additional tips on posting. Good posts tend to get more attention in the forum.

Dear Klaus_K

If it was possible to select a specific AP between two APs, both with the same SSID, it would be a nice solution.
The problem I see is that the API WiFi.begin(ssid, password); can't do that, because it doesn't have the MAC address as an input parameter for the AP selection when the SSIDs are the same.
Please note that the function int n = WiFi.scanNetworks(); is able to recognize different APs with the same SSID, the problem is that doesn't exist a WiFi.begin(ssid, password) that gives the possibility to set a specific AP from two APs with the same SSID.
This "feature" can't be considered an application problem if there are no API that permit to solve the problem

Thanks and Regards
Paolo

pberna:
If it was possible to select a specific AP between two APs, both with the same SSID, it would be a nice solution.

When you have two APs with the same SSID, I would suspect they will use a different channel. You can add the channel as a third parameter. e.g.

WiFi.begin(ssid, password, 1);

So, when you scan the networks you could look at the RSSI and use the channel as identifier.

Dear Klaus

I see that the possible parameters combination for WiFi.begin(); are:

The third parameter should be the key, not the channel number

WiFi.begin(ssid, keyIndex, key);

Furthermore the WiFi.scanNetworks() seems doesn't provide the channel number.

Is it available an updated documentation of the methods ?

You said you are using a ESP32. I installed the tools and libraries trough the board manager. In the following folder

C:\Users\UserName\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\libraries\WiFi\src

I looked at the source file WiFiSTA.h and the parameters are different.

wl_status_t begin(const char* ssid, const char *passphrase = NULL, int32_t channel = 0, const uint8_t* bssid = NULL, bool connect = true);
wl_status_t begin(char* ssid, char *passphrase = NULL, int32_t channel = 0, const uint8_t* bssid = NULL, bool connect = true);

But thanks to your comment I reviewed the files and got you one better. :slight_smile: In WiFiSTA.cpp the bssid parameter comment says you can use a MAC as 4th parameter.

/**
 * Start Wifi connection
 * if passphrase is set the most secure supported mode will be automatically selected
 * @param ssid const char*          Pointer to the SSID string.
 * @param passphrase const char *   Optional. Passphrase. Valid characters in a passphrase must be between ASCII 32-126 (decimal).
 * @param bssid uint8_t[6]          Optional. BSSID / MAC of AP
 * @param channel                   Optional. Channel of AP
 * @param connect                   Optional. call connect
 * @return
 */
wl_status_t WiFiSTAClass::begin(const char* ssid, const char *passphrase, int32_t channel, const uint8_t* bssid, bool connect)

pberna:
Furthermore the WiFi.scanNetworks() seems doesn't provide the channel number.

WiFi.channel will give you the channel number.

Dear Klaus

the indicated WiFiSTAClass is not the WiFi class to all libraries refer to (I'm using for example the EspMQTTClient.h). So even if your class can, perhaps, solve the problem, it is not invoked by other libraries

I recommend to the Arduino developer do not modify their Wifi.begin API adding additional parameters. This avoid any incompatibility with the past. The best thing to do, is to modify the body of Wifi.begin to consider APs with the same SSID and to automatically select the AP with the strongest signal with the specified SSID. Dynamic handover is not necessary

Regards
Paolo

Hi Paolo,

pberna:
the indicated WiFiSTAClass is not the WiFi class to all libraries refer to (I'm using for example the EspMQTTClient.h). So even if your class can, perhaps, solve the problem, it is not invoked by other libraries

It is. Have a look into the source code of the ESP32 WiFi library on your hard drive. You are using the class I have pointed out.

In your example, you are calling WiFi.begin(). All the MQTT stuff happens later. I just added a array for a MAC address and your example compiled without any errors.

Just try. The additional parameters are set in the prototype. If you do not use them, they are set by the compiler using the values from the prototype in the header file.

pberna:
I recommend to the Arduino developer do not modify their Wifi.begin API adding additional parameters.

The additional API parameters are part of the official WiFi library from Espressif.

pberna:
The best thing to do, is to modify the body of Wifi.begin to consider APs with the same SSID and to automatically select the AP with the strongest signal with the specified SSID. Dynamic handover is not necessary

If you modify WiFi.begin you will have to track all the changes you are doing and then implement them again when the library is updated.
What would you want to change? The library has a way to connect to a specific AP. It does exactly what you asked for in reply #2.

pberna:
If it was possible to select a specific AP between two APs, both with the same SSID, it would be a nice solution.
The problem I see is that the API WiFi.begin(ssid, password); can't do that, because it doesn't have the MAC address as an input parameter for the AP selection when the SSIDs are the same.

You can, you just looked at the wrong documentation. The Arduino web page describes the Arduino WiFi library and not the Espressif WiFi library.