[Photon] Reconfiguring the WiFi credentials from USB cable without touching any button, or how to Clear the WiFi credentials in DFU mode

The main objective is to have the possibility of reconfiguring the WiFi credentials from USB cable without touching any button, when the current WiFi credentials are set wrong by accident and the Photon cannot connect to the Particle :cloud: or local :cloud:, from where the by user-code we could force entering in Listen Mode (by calling WiFi.listen()) or to Clear the WiFi credentials (by calling WiFi.clearCredentials() and then System.reset()) => Finally calling particle setup wifi to fix the wrong credentials => Reboot.

As we can enter and exit DFU mode from USB cable without touching any button [1][2], I was wondering if we can clear the WiFi credentials from DFU mode (to force the Listen mode in next reboot), but without overwritting the current firmware.

Any advice? Maybe is it possible to call any function of the bootloader from DFU mode to clear the WiFi credentials?.

PD: I know that the WiFi credentials can be usually fixed from Listening mode, but if they are stored in the internal or external flash memory after being set-up, I thought that they could maybe be cleared with dfu-util to force a Listen Mode in the next reboot.

2 Likes

+1 on this. I have directly reached out and asked for help with this from Particle. I have a situation where apparently bad credentials are causing SOS with flash 13. This happens even in Safe mode so it has nothing to do with my firmware. Give that Particle knows exactly where the credentials are stored in flash it should be trivial to supply a DFU command that will reset that region of memory so the device goes back into listening mode and doesn’t try to connect.

@sidwarkd, did you try using WiFi.clearCredentials() and it failed to erase the bad credentials as in the credentials storage is corrupt?

My next hack was to create a custom firmware that just does that and see if I can get it to work. The only mode I have access to now is DFU. Also going to just try to figure out myself the DFU command. I was hoping Particle could save me some time on that.

Also, re-reading your question, is there an issue where calling clearCredentials will bork things? I do call that if my user adds credentials that don’t result in a successful connection to the internet. Is it possible my firmware making that call is initiating the problem?

@sidwarkd, clearing credentials is not the issue. Adding bad credentials will cause issues if those credentials are the only ones for that SSID (extras probably won’t matter anyway). Your software should have some protection against bad creds by allowing only so long to connect and then wiping the credentials and wait for new ones when the device goes into Listening mode on reboot or by forcing Listening mode. @ScruffR or @rickkas7 may have some sample code to contribute.

Sorry for the confusion. This is exactly what my firmware does. It accepts credentials and then tries to connect to WiFi. If that fails I call WiFi.clearCredentials to send it back to listening mode. What I am seeing in some cases is that something goes wrong and I get into an SOS mode. At that point I can’t even get into safe mode because safe mode is really only “kinda safe” mode because it will still try to connect using stored credentials. I would expect, in that scenario, for invalid credentials simply to result in no WiFi connection but instead I’m getting SOS. Once my device is in that state it’s essentially bricked so I’m looking for a DFU command or series of commands to restore the WiFi credential spot of memory back to “factory”.

Digging into the code and it looks like the wifi creds are stored in the filesystem at /sys/wifi_config.bin. So apparently not as simple as DFU clearing an address or two. I’m guessing somebody with filesystem knowledge might have a trick of how to reset that. Marking the file as deleted would probably have unintended consequences as well.

Even so, there must be some way to restore the flash in that address area to what it was from the factory for a specific version. At the end of the day it’s just ones and zeros in flash that got there somehow originally.

Just to close the loop here. I was able to flash user firmware that did nothing more than call WiFi.clearCredentials() and then put the device back in DFU mode with System.dfu(). I was then able to flash my product firmware and have it appropriately go back into listening mode when an invalid password is used for credentials. My guess is that my P1s had a corrupt wifi credential file somehow.

I’ve been able to reproduce the SOS issue on several devices simply by entering an invalid password via the SoftAP flow but it doesn’t happen on all devices. After running the wifi-clearing firmware and re-flashing my firmware all seems to work again. Very strange bug.

Full circle back to the original post. It does not seem like there is a straightforward way to clear WiFi credentials with a dfu-util call but a script could be put together to flash a firmware like the one I made. Said firmware, after clearing the credentials can call System.dfu() and then you could run a DFU command to re-flash your firmware. Kind of clunky but works. If Particle has a cleaner workflow to accomplish the same thing that would be great.

On the Photon and P1 running 0.8.0 or later, you can do it using the particle-usb library. The device must be in listening mode or normal operating mode (not DFU).

This is the node.js script:


const usb = require('particle-usb');


async function main() {	
	let devices = await usb.getDevices();
	
	devices = devices.filter(dev => dev.clearWifiCredentials);
    if (devices.length != 1) {
        console.log('This script requires a single WiFi device connected to the host via USB');
		process.exit(1);		
    }
    let device = devices[0];
    
	try {
		// console.log("found device!", device);
		
		await device.open();
		
		// console.log("opened!");
		
		await device.clearWifiCredentials();
		
		await device.reset();
		
		await device.close();
		process.exit(0);		
	}
	catch(e) {
		console.log("operation failed", e);
		process.exit(1);				
	}
}

main();

You need the particle-usb library as well:

npm install particle-usb

And run the script with a single Photon connected by USB.

node app.js

(This does not work on the Argon at this time as the clear credentials USB command is not yet supported on Gen 3 devices.)

1 Like