[Resolved]- Firmware upgrade via SoftAP!

It appears to be a limitation in the code provided by WICED (formerly Broadcom, now Cypress). If you sign their NDA you can access the code and recompile it locally using gcc for a larger size I think. There is no way I can think of to do this without compiling locally or doing multiple parts.

You should create a github issue for this too so it is on the team’s agenda.

The WICED owners have committed to a more open source model for that code in the future, so it would be easier then.

By using javascript, I was able to split the file into two parts (or more) and handle that on the particle photon side…

Here is the javascript example that need to be optimised. Any suggestions are open. I’m a noob with javascript.

// Because we want to access DOM node,
// we initialize our script at page load.
window.addEventListener('load', function () {

  // This variables will be used to store the form data
  var file = {
        dom    : document.getElementById("i2"),
        binary : null,
        length : 0
      };
 var data     = "";
  // We use the FileReader API to access our file content
  var reader = new FileReader();

  // Because de FileReader API is asynchronous, we need
  // to store it's result when it has finish to read the file
  reader.addEventListener("load", function () {
    file.binary = reader.result;
    
  });

  // At page load, if a file is already selected, we read it.
  if(file.dom.files[0]) {
    reader.readAsBinaryString(file.dom.files[0]);
	file.length = reader.length;
  }

  // However, we will read the file once the user selected it.
  file.dom.addEventListener("change", function () {
    if(reader.readyState === FileReader.LOADING) {
      reader.abort();
    }
    
    reader.readAsBinaryString(file.dom.files[0]);
	file.length = reader.length;
  });

  // The sendData function is our main function
  function sendData() {
    // At first, if there is a file selected, we have to wait it is read
    // If it is not, we delay the execution of the function
    if(!file.binary && file.dom.files.length > 0) {
      setTimeout(sendData, 10);
      return;
    }

	// To construct our multipart form data request,
    // We need an XMLHttpRequest instance
    var XHR      = new XMLHttpRequest();
	var XHR2      = new XMLHttpRequest();
	// We need a sperator to define each part of the request
    var boundary = "blob";

	//console.log(data);
    // We define what will happen if the data are successfully sent
    XHR.addEventListener('load', function(event) {
      //alert('Yeah! Data sent and response loaded.');
	  XHR2.open("POST", "http://192.168.0.1/upgrade2");
		XHR2.setRequestHeader('Content-Type','multipart/form-data; boundary=' + boundary);
		XHR2.sendAsBinary(data);
    });
	XHR2.addEventListener('load', function(event) {
      alert('Yeah! Data sent and response loaded.2');
    });

    // We define what will happen in case of error
    XHR.addEventListener('error', function(event) {
      alert('Oups! Something goes wrong.');
    });
	XHR2.addEventListener('error', function(event) {
      alert('Oups! Something goes wrong.2');
    });
    
    file.length = 10;   
    // And we'll store our body request as a string.
    
	var toomuchdata = 0;
    // So, if the user has selected a file
    if (file.dom.files[0]) {
		console.log("File selected");
		console.log(file.binary.length);
		var i = 0;
		while(i < file.binary.length)
		{
			data = "";
			
			// We start a new part in our body's request
			data += "------" + boundary + "\r\n";

			// We said it's form data (it could be something else)
			data += 'content-disposition: form-data; '
			// We define the name of the form data
			+ 'name="'         + file.dom.name          + '"; '
			// We provide the real name of the file
			+ 'filename="'     + file.dom.files[0].name + '"\r\n';
			// We provide the MIME type of the file
			data += 'Content-Type: ' + file.dom.files[0].type + '\r\n';
			data += 'FileSize: ' + file.binary.length + '\r\n';

			// There is always a blank line between the meta-data and the data
			data += '\r\n';

			// We happen the binary data to our body's request
			
			var toRead = 0;
			if(file.binary.length - i > 60000)
			{
				toRead = 60000;
			}
			else
			{
				toRead = file.binary.length - i;
			}
			data += file.binary.substr(i, toRead);  
			i += toRead;
			
			data += '\r\n';
			data += '------' + boundary + '--' + '\r\n';
			if(toomuchdata)
			{
				// 
			}
			else
			{
				// We setup our request
				XHR.open("POST", "http://192.168.0.1/upgrade");
				// We add the required HTTP header to handle a multipart form data POST request
				XHR.setRequestHeader('Content-Type','multipart/form-data; boundary=' + boundary);
				XHR.sendAsBinary(data);
			}
			toomuchdata = 1;
		}
	}	
  }

  // At least, We need to access our form
  //var form   = document.getElementById("myForm");

  // to take over the submit event
  //form.addEventListener('submit', function (event) {
  //  event.preventDefault();
  //  sendData();
  //);
  document.getElementById("myForm").addEventListener("submit", function(event){
    event.preventDefault();
	sendData();
	});
	
	XMLHttpRequest.prototype.sendAsBinary = function(datastr) {
    function byteValue(x) {
        return x.charCodeAt(0) & 0xff;
    }
    var ords = Array.prototype.map.call(datastr, byteValue);
    var ui8a = new Uint8Array(ords);
    this.send(ui8a.buffer);
};
});
2 Likes

I have optimised and working code. I’ll update the github tomorrow.

Next thing I need to figure out is how to load webpages from memory and return content to the writer.
One way would be to load the page completly into a giant buffer.
Is there other ways to pass data to : result->write?

The new version is available on github here (https://github.com/Suprazz/ParticleUpgradeViaSoftAP) and it seems to work well with windows 10 and android. It handle files of any size!

3 Likes

Update.
with 1.4.4 it’s not working anymore.
I get a internal server error 500 from the photon and my POST command is refused immediately when I try to do the upgrade.
But all other pages works fine and if I go to /upgrade manually, it works and return an error that no data was sent (like expected).

Any idea why it was working fine and now, nothing works?