Sending large files over wifi

:wall: that solution has revealed itself to be inconsistent: while it improved success rate considerably increasing the size of the file “allowed” 40 bytes to disappear unfortunately that file size makes testing really tedious (15 min per download, most downloads complete flawlessly) so I’m wondering where I can chase this bug to next to seek a solution (I see nothing problematic in the driver code, at least nothing that would cause the issue I’m receiving currently.

Any chance there’s a http header I can use to take greater care in loss and retrieval?

I repeat my suggestion.
If all Bytes are sent to the wifi device you will hardly have a chance to get it working as you have no access to the wifi device and no access to the code of the receiver (Browser?)
Maybe that it is better to use the ftp protocol (at least if the application is for use in a local network)

I think you can’t use the existing NETMF FTP Server to do so, because it uses Sockets.
Implementing FTP is a not so simple task as one might think (I twaked the existing one a lot to get it working properly).
And if the problem is that bytes are lost when using the Wifi.Send(byte data) method, then you will see the same problem with FTP or any other protocol you implement, as long as you don’t add additional error checking and repeatitions. But this should not be necessary when using TCP/IP based protocols.
Ether the serial connection to the module is bad, or the wifi module (firmware) is a piece of crap.

@ Reinhard Ostermeier -
You are right. If really the firmware of the wifi module is faulty, ftp will not work as well. But before assuming this I would verify directly in the driver that really all Bytes are sent to the wifi device.
Another thing that should be considered if the errors seem random is power supply. For tests the GND and 3.3. V could be supplied directly to the module by separate wires and perhaps an capacitor added near the module.

@ RoSchmi - If the driver is the problem, then it’s inside the Serial.Send method.
I checked the wifi module code and it looks ok for buffers < baue rate.

This is also my view to be fair I haven’t checked with a counter but it seems to just pass the argument along (assuming buffer < baudrate)


public void Send(byte[] data)
        {

            if (data.Length <= _wifly.BaudRate)
            {
                //Write-out directly
                _wifly.Write(data);
                count += data.Length;
            }
           else{potential bugged code}
           return;
}

This logic will be removed in a future version as the user should choose how the data is chunked, however the logic is sound and is working (i used it for the example code as well). I was able to get more stability using a different set of header parameters (specifically 2).

Accept-ranges – Do not use a value here other than none. Depending on implementation, the browser could decide to use 2 threads to download different portions of the same file. Multiple simultaneous requests will lock up the RN171 as it is designed as a singular connection stream.

Connection – I would not use keep-alive here as it could interfere with future requests. For this, it is best to use connection: close as stated in the example code of the module.

I used the code below and a 3.4MB image of wood because the texture is good for noticing minute changes in data integrity visually – missing pixel or color data etc.

public partial class Program
    {
        // This method is run when the mainboard is powered up or reset.   
        void ProgramStarted()
        {
            Debug.Print("Program Started");
            wifi_RN171.Initialize(GTM.GHIElectronics.WiFi_RN171.SocketProtocol.TCP_Server); //Init as TCP Server
            wifi_RN171.EnableHttpServer(); //Enable HTTP Parsing
            wifi_RN171.HttpRequestReceived += new GTM.GHIElectronics.WiFi_RN171.HttpRequestReceivedHandler(wifi_RN171_HttpRequestReceived);
        }

        void wifi_RN171_HttpRequestReceived(GTM.GHIElectronics.HttpStream request)
        {
            string requestedURL = request.Request.URL;

            if (requestedURL == "/index.jpg")
            {
                sdCard.MountSDCard();
                FileStream file = new FileStream("SD\\image2.jpg", FileMode.Open);

                lock (file)
                {
                    request.Response.HeaderData["Content-length"] = file.Length.ToString();
                    request.Response.HeaderData["Content-type"] = "image/jpeg";
                    request.Response.HeaderData["Connection"] = "close";
                    request.Response.HeaderData["Cache-Control"] = "no-cache";
                    request.Response.StatusCode = GTM.GHIElectronics.HttpResponse.ResponseStatus.OK;

                    int baud_rate = 1024;
                    int iterations = (int)(file.Length / baud_rate);
                    int exceeding = (int)(file.Length % baud_rate);
                    int segment_start = 0;

                    if (exceeding > 0) iterations++;

                    for (int i = 0; i < iterations; i++)
                    {
                        //Calculate segment range
                        segment_start = i * baud_rate;
                        byte[] document = new byte[1024];
                        file.Read(document, 0, 1024);

                        //Write the current segment
                        if (i == 0)
                            request.Response.Send(document);
                        else
                            wifi_RN171.Send(document);

                        System.Threading.Thread.Sleep(50);
                    }
                }

                file.Close();
                sdCard.UnmountSDCard();
            }
        }
    }