WiFi Creditials directly to Photon

Would it be possible to use a touchscreen to handle the wifi connection by adding credentials through a wifi scanning library and then entering the creds. through the touchscreen?

1 Like

See: http://docs.particle.io/photon/firmware/#wifi-setcredentials

Oh yeah, using WiFi.setCredentials(); I’m assuming the can be done and then stored in eeprom for future use.

Or can this be called once and after that its been called it will store them automatically?

Does anyone know of a library that scans for nearby networks?

@wesner0019, once you call that function. credentials are saved in the WiFi module.

for wifi scanning - https://github.com/spark/firmware/tree/develop/user/applications/wifitester

1 Like

WiFi scanning is available internally to the system but we haven’t broken that out to a public API. It’s something that’s been requested at least a couple of times - we’ll definitely consider it!

Suggestions welcomed as to what a scan API that might look like!

WiFi.scan() ? :smiley:

erm…yeah…I was hoping for more details, like how multiple networks are passed back to user code! :stuck_out_tongue:

3 Likes

@mdma I did not check specs on how the chip itself works, but I would do something like:

WIFI.startScan() - switches to network scanning mode OR starts scanning, if it can be online and scan at once. Resets any acquired networks list. Scanning is one shot event, which populates list of available networks and stops the process
WIFI.stopScan() - returns back to normal mode if the chip can’t scan for networks when connected to one
int WIFI.availableNetworksCount() - returns count od networks discovered, or -1 if scan is in progress yet
char* WIFI.SSID(int networkNumber) - gets SSID for discovered network (without argument gives currently connected SSID)
short WIFI.RSSI(int networkNumber) - as above
int WIFI.authType(int networkNumber) - returns auth type constant for scanned network (NONE, WEP, WPA, WPA2)
WIFI.clearAvailableNetworks() - clears all lists, releases all resources

Pseudo code:

// initiates the scan
WIFI.startScan();
// wait for scan to finish
while (-1 == WIFI.availableNetworksCount())
    delay(10);
// walk through all discovered networks
for (int i = 0; i < WIFI.availableNetworksCount(); i++) {
    // skip any networks with password
    if (NONE != WIFI.authType(i))
        continue;
    // sets the current wifi to the discovered one
    WIFI.setCredentials(WiFi.SSID(i));
    // connect to the WiFi
    WIFI.connect();
    break;
}
// release any resources
WIFI.clearAvailableNetworks();

Maybe use a callback to transfer the network data out from the scan instead? I like the idea of having all of the network information available all together, but the memory constraints could make it very resource hungry.

The amount of buffer needed could be quite variable from use case to use case. Someone who wants to output the results to serial needs to buffer only one result at a time, someone who wants to display the n strongest results needs to buffer n results, and someone who wants to sort and print all results needs to store as many results as there are access points in range. Using a callback gives the user control of the memory consumption.

How about a usage like this?

void wifiScanResultCallback(char * ssid, int rssi, unsigned long sec)
{
    if(sec == WLAN_SEC_UNSEC)
    {
        WIFI.cancelScan();
        WIFI.setCredentials(ssid);
        WIFI.connect();
    }
}

void initiateScan()
{
    WIFI.scan(&wifiScanResultCallback, 5000); //specify timeout of 5000ms
}
1 Like

Check this issue, there is already discussion there: https://github.com/spark/firmware/issues/453

It suggest having a method which fills array of structs with all data available. I would recommend passing just one structure at a time and iterating over list of available networks, just to save memory (keep just one network info at a time, not whole lists).

I will add this suggestion in the issue discussion.

I like that. I was thinking very much on those lines - having a callback interface as the primary access. The coding might be advanced for some beginners so I was thinking of wrapping that up with a simple interface where the user can provide a buffer, and we fill in the first X results.

E.g.

WiFiScanResult results[20];
WiFI.scan(results, 20);
for (int i=0; i<20; i++) {
   if (results[i].security==UNSEC) {
   // ...
   }
}

But definitely the callback interface comes first.

3 Likes

So I was having a fiddle and managed to create some sort of a nasty hack of an interface. It can be used from the web IDE too.
The internal function wlan_scan_aps is somewhat limited in that it’s callback only provides only the ssid and the signal strength, but regardless, this function can be used by creating a function pointer to it, bypassing the linker and allowing the function to be called without linking to internal functions or breaking out the api. This is version dependent, and what works on 0.4.1 doesn’t work anywhere else without a new pointer.

I replicated the code involved and added BSSID, security type and radio channel to the callback.
This only works on the Photon, as I do not have a Core to test on.
This makes use of five internal functions not exposed to the public API.

To use it call
perform_wireless_scan(myCallback, myotherdata)
where myotherdata is a pointer to something (a usefull class for instance).

MyCallback is of the format
void myCallback(void* myotherdata, const char ssid[33], const uint8_t bssid[6], int channel, int security, int rssi) {... code here ...}

The security field is one of the following
SECURITY_OPEN, SECURITY_WPA, SECURITY_WPA2, SECURITY_ENTERPRISE, SECURITY_UNKNOWN

The perform_wireless_scan function blocks until all local networks have been scanned and reported to the callback. This last a few seconds at most, usually about 1 second. The callback is not called once the function has returned.

I’ve included the code and header for this to include in your own project until a public API is available. I’ve also included an example that prints to USB serial when the setup button is pressed. You can find all of that here. It should work unless I’ve made a mistake somewhere.

Note that as is, this only works on version 0.4.1 of the Photon firmware (flashed over DFU), though changing the commenting in wifiscanner.cpp allows it to work on version 0.4.3 (the latest release, which is unstable on my Photon).

This is also likely to break at any time, so I advise against using it in production code.

2 Likes

These guys did a nifty project that scans for unsecured WiFi networks, causing a toy sword to glow:

http://blog.particle.io/2014/12/17/warsting-a-wifi-scanning-sword-for-hobbits/

Seems to do what’s being described here albeit in a low-level C way, having it as part of the out-of-the box API would be cool.

Of course it’s on the Particle blog so many of you have likely seen it!