Advanced Users can post their questions and comments here for the not so Newbie crowd.

Moderator: eriksl

User avatar
By davydnorris
#81262 This is the sort of discussion I hoped would happen :-)

My particular device is deployed in quantity (100's to 1000's) in cities where the Wifi is very polluted. I've found that avoiding any sort of scan of APs is a very good idea. Using this code has reduced my start up and connect time from sometimes over 10 seconds, to under half a second in most cases. My devices are solar and dry cell battery powered, and spend as much time in deep sleep as possible, waking mostly to send a heartbeat and to check for commands and to send event data.

City provided Wifi uses the same SSID on hundreds of stations, each with a different BSSID. They also typically set their hardware to automatically change channels to find the least polluted. My devices are static (strapped to light poles or mounted on walls), and they typically see 3-4 stations with the same SSID, different BSSIDs and different strengths. The code that populates the list of APs is dynamic and uses the rssi, and number of failed connect attempts to adjust the list, and the connect code uses the BSSID to always attempt connection to the last 'best' specific station first.

BTW a fast reconnect is done by using both BSSID and channel. A Wifi channel is the most unreliable element of the connection for a station as routers can be set to channel hop in order to find the clearest signal, but channel is also the most expensive thing to leave out because if you don't specify a channel the radio has to scan through them to find the SSID. Also most scans are not smart - the most commonly used channels tend to be 1, 6 and 11 but most scans will go in numerical order. And when you have 4 stations all with the exact same SSID but different connection quality or strength, you want to pick the best one.

This is why I don't use the built in SDK capability and why I store info on the last connection in RTC memory.
User avatar
By eriksl
#81272 Ah ok, clear, that is an entirely different setup than mine.

It would make sense if the channel scan would first try only channels 1, 6 and 13 and on failure also scan 2,3,4,7,8,9,10,11,12,14. I don't have a clue if the SDK code does that, another one of the poorly documented features.

My hopes are that at some point enough information is revealed, that we can ditch the SDK altogether, running on completely bare hardware and use an open source implementation for the WLAN handling. I bet Espressif uses e.g. code from wpa_supplicant without admitting it.

Good documentation is good, open source is better :-)

So no, I can't really help you out here, fingers crossed somebody else can.
User avatar
By quackmore
#81577
Code: Select all- can anybody think of a more elegant way to check the bssid value? is memcmp with "\0\0\0\0\0\0" the most elegant way? I initially used a union with a uint64_t but this took up valuable space in the RTC memory


don't think this is what you are looking for but anyway:
when comparing MAC addresses efficiently I'd write a custom function that checks from the 6th to the 1st byte
in your scenario it's very likely that city provided wifi will use same vendor equipment and so the first 3 bytes of the MAC will be the same

Code: Select all- when the fast connection fails for the first time, I see a message in the debug info that says 'scandone'. This is what is printed at the end of a channel scan. So I was wondering if anybody knew if the SDK automatically does a channel scan when a connection fails? Perhaps I don't need all my fallbacks?


I think this is because you drop the channel and next connection trial will have necessarily to perform a full scan.

The figures you pointed out (about 10 seconds for a full scan) make sense to me.
Performing a generic active scan means you have to change the channel for sending probe-any requests and,
I may be wrong, this is usually done scanning each channel for 30 ms per seconds leading to a total time around 10s if the RF finds 11 channels.
Why do you wait 1 second before checking for the next channel?
Cause while performing a generic scan you want to guarantee that the wifi keeps operating with no traffic drop.
I mean you wanna keep the effective scan time (on a channel different by the working one) a very little (3% in the example above) percentage of the wifi working time.
I don't see any reason why Espressif should do anything different.

But your scenario is totally different, I'm guessing you don't care about traffic while performing the scan just because there is none.

Then you should perform your custom scan tuning the wifi_ative_scan_time using the sdk structures below and optimize the way you connect to AP to something like this (just for saying ...)
1) try the fast connection
2) on fail of point 1 => perform custom scan on 1,6,11 (or whatever) and connect to the SSID with best rssi
3) on fail of point 2 => perform custom scan on all channels and connect to the SSID with best rssi

by the way you got me curious and I think I will perform some measure of the scan times playing with custom scan parameters ...


Code: Select alltypedef enum {
    WIFI_SCAN_TYPE_ACTIVE = 0,  /**< active scan */
    WIFI_SCAN_TYPE_PASSIVE,     /**< passive scan */
} wifi_scan_type_t;

/** @brief Range of active scan times per channel */
typedef struct {
    uint32_t min;  /**< minimum active scan time per channel, units: millisecond */
    uint32_t max;  /**< maximum active scan time per channel, units: millisecond, values above 1500ms may
                                          cause station to disconnect from AP and are not recommended.  */
} wifi_active_scan_time_t;

/** @brief Aggregate of active & passive scan time per channel */
typedef union {
    wifi_active_scan_time_t active;  /**< active scan time per channel, units: millisecond. */
    uint32_t passive;                /**< passive scan time per channel, units: millisecond, values above 1500ms may
                                          cause station to disconnect from AP and are not recommended. */
} wifi_scan_time_t;

struct scan_config {
    uint8 *ssid;    // Note: ssid == NULL, don't filter ssid.
    uint8 *bssid;    // Note: bssid == NULL, don't filter bssid.
    uint8 channel;    // Note: channel == 0, scan all channels, otherwise scan set channel.
    uint8 show_hidden;    // Note: show_hidden == 1, can get hidden ssid routers' info.
    wifi_scan_type_t scan_type; // scan type, active or passive
    wifi_scan_time_t scan_time; // scan time per channel
};
User avatar
By davydnorris
#81578
quackmore wrote:...
in your scenario it's very likely that city provided wifi will use same vendor equipment and so the first 3 bytes of the MAC will be the same


Thanks for that - but what I was actually doing was looking to see if I have zeroed out the last MAC I had stored in volatile memory and I wanted to check for 6 bytes of 0x00. I couldn't work out if that was the best way or if there was something more elegant. It just felt a bit hacky doing a memcmp and I wondered if there was a nice way of doing numerical compares instead.

quackmore wrote:
Code: Select all- when the fast connection fails for the first time, I see a message in the debug info that says 'scandone'. This is what is printed at the end of a channel scan. So I was wondering if anybody knew if the SDK automatically does a channel scan when a connection fails? Perhaps I don't need all my fallbacks?


I think this is because you drop the channel and next connection trial will have necessarily to perform a full scan.


That's what I was pointing out - at the end of the first attempt, I haven't yet done a retry with the channel dropped, and yet the scandone message appears anyway. Then I drop the channel and do another attempt myself. If the Espressif code is automatically dropping the channel for me when the first try fails, I'm doing an extra superfluous scan that's not needed.

quackmore wrote:...
Why do you wait 1 second before checking for the next channel?



I'm not - at this point I am not manually initiating any scans, I'm just dropping the channel and trying again. Anything you see there is Espressif's code doing the scanning.

I actually do use the manual custom scan several times. I have a config web app that runs in the unit and I scan all the available Wi-fi points to populate a list for the UI.

I also use that same list to geolocate the unit via the Google Geolocation API - my units are deployed in cities with lots of wifi points and lots of GPS shadows so wifi based triangulation works brilliantly. I can usually get within 10m or so of the actual location, and then I bring up a map in the config app with a pin for precise position refinement.