Author Topic: Problems with WiFi  (Read 16796 times)

SukkoPera

  • Newbie
  • *
  • Posts: 12
Problems with WiFi
« on: January 13, 2014, 03:55:05 pm »
Hi,

I just got my DigiX, and I decided to immediately port my "universal" web server to it. Check it out at https://github.com/SukkoPera/Sukkino.

I am using the Ethernet compatibility layer, for the moment, but I am experiencing weird problems. First of all I cannot understand how I can close the TCP connection after I have sent data back to the client through server.print(). Is server.stop() supposed to do the job?

I need this, because otherwise the browser will just wait for more data and get stuck. This happens with the EthernetCompatible/WebServer example as well, which shows nothing in the browser.

I am working on OSX and testing with both Safari and Chrome. Of course I have configured the Wifi chip so that it connects to my network and that is working fine (I can see and process incoming requests).

Thanks in advance!

digistump

  • Administrator
  • Hero Member
  • *****
  • Posts: 1465
Re: Problems with WiFi
« Reply #1 on: January 14, 2014, 12:03:00 am »
This is a known issue with the library - I welcome any help in solving it, the datasheet for the wifi module is on the wiki, as while it is on my list I have to finish up some other projects first.

tos

  • Newbie
  • *
  • Posts: 5
Re: Problems with WiFi
« Reply #2 on: January 17, 2014, 12:03:29 pm »
What did the job for me was to add the header field "Content-Length: xxx" to the response. This lets the client/browser know when the response is finished. To get this content length you need a short refactoring of the WebServer sketch. Here is what I did:

Code: [Select]
void loop() {
  // listen for incoming
  // an http request ends with a blank line
 

  if (server.available()) {
    char c = server.read();
    Serial.write(c);
    // if you've gotten to the end of the line (received a newline
    // character) and the line is blank, the http request has ended,
    // so you can send a reply
    if (c == '\n' && currentLineIsBlank) {
      String responseBody = "<!DOCTYPE HTML>\r\n";
      responseBody += "<html>\r\n";
      // output the value of each analog input pin
      for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
        int sensorReading = analogRead(analogChannel);
        responseBody += "analog input ";
        responseBody += String(analogChannel, DEC);
        responseBody += " is ";
        responseBody += String(sensorReading, DEC);
        responseBody += "<br />\r\n";
      }
      responseBody += "</html>\r\n";
      // send a standard http response header
      server.println("HTTP/1.1 200 OK");
      server.println("Content-Type: text/html");
      server.println("Content-Length: " + String(responseBody.length(), DEC));
      server.println("Connection: close");  // the connection will be closed after completion of the response
      server.println("Refresh: 5");  // refresh the page automatically every 5 sec
      server.println();
      server.println(responseBody);
      currentLineIsBlank = false;

    }
    else if (c == '\n') {
      // you're starting a new line
      currentLineIsBlank = true;
    }
    else if (c != '\r') {
      // you've gotten a character on the current line
      currentLineIsBlank = false;
    }
  }

  // give the web browser time to receive the data
  delay(1);
}

armband

  • Newbie
  • *
  • Posts: 12
Re: Problems with WiFi
« Reply #3 on: January 19, 2014, 09:33:07 am »
What did the job for me was to add the header field "Content-Length: xxx" to the response. This lets the client/browser know when the response is finished. To get this content length you need a short refactoring of the WebServer sketch. Here is what I did:

The RFC recommendation is to specify the Content-Length in the HTTP header.  Knowing the content size in advance,  will allow the client to close the connection gracefully after it has read the entire message body of the response.  Chunked transfer encoding can be used in cases where the Content-Length cannot be generated in advance [by the server] for inclusion in the response's HTTP header.

I feel I should mention that a brute force approach could be used, as follows: The server could close the connection after sending the response, IMO it is not a good solution because it will prevent the client from reusing the connection (for HTTP 1.1 connection persistence).  That said, a crude workaround for the DigiX + usr-WIFI232 device would be to set the TCP time out to a low value, e,g: wifi.setTCPTimeout(1)  ... I am not advocating this time out approach because it isn't great!

-Graham
« Last Edit: January 19, 2014, 10:00:38 am by armband »

SukkoPera

  • Newbie
  • *
  • Posts: 12
Re: Problems with WiFi
« Reply #4 on: January 20, 2014, 05:10:05 am »
Yes, adding the Content-Length header line is of course an option, but since my webserver is generating (somewhat-) dynamic content, it would be hard to send the correct value. It would require buffering the contents in memory, which isn't a problem per se, since the DigiX has so much more SRAM than the Duemilanove/Uno I usually use, but I would need to refactor my code quite a bit.

I have tried to check the datasheet and the library code and, as far as I can understand, the code is doing the right thing, but the connection isn't really closed :(.

armband

  • Newbie
  • *
  • Posts: 12
Re: Problems with WiFi
« Reply #5 on: January 20, 2014, 06:25:14 pm »
I agree, it should be possible for the server to close the connection. I have spent a little more time on the problem this evening and believe that I have discovered a potential workaround. My test code uses the DigiFi class (wifi in the example) to send a response, as illustrated below.  Note, no Content-Length is included in the HTTP header, also note the call to wifi.stop() after the response has been sent, this should in theory close the connection ... but apparently it doesn't ... read on ...

Code: [Select]
         wifi.println("HTTP/1.1 200 OK");
         wifi.println("Content-Type: text/html");
         wifi.println("<html><head></head><body>");
         wifi.println();
         wifi.print("<form method=get>");
         wifi.print("<input type='radio' name=r value='1'> One<br>");
         wifi.print("<input type='radio' name=r value='2' checked> Two<br>");
         wifi.print("<input type='radio' name=r value='3'> Three<br>");
         wifi.print("<input type=submit value=submit></form>");
         wifi.print("</body></html>");
         //stopping client
         wifi.stop();

I have found that the "+++" command that is sent to the modem by the call to wifi.stop() does not actually switch the modem from transparent back to AT command mode; instead "+++" is sent over the active TCP connection.  The workaround requires  the DigiFi.cpp library file to be modified by adding a small 100ms delay to the head of the DigiFi::startATMode() method as follows:

Code: [Select]
void DigiFi::startATMode()
{
    //silly init sequence for wifi module
    delay(100); // More voodoo - 100ms delay here
    while(Serial1.available()){Serial1.read();}
    debug("start at mode");
    debug("next");
    Serial1.write("+++");
    debug("wait for a");
    while(!Serial1.available()){delay(1);}
    debug("clear buffer");
    while(Serial1.available()){Serial1.read();}
    Serial1.print("A");
    debug(readResponse(0));

    debug("echo off");
    Serial1.print("AT+E\r");
    debug(readResponse(0));
}

It seems the WiFi module needs this pause before the +++ command.  The workround functions in two of my test web server examples ... I would be interested in knowing whether it addresses the problem in other implementations.  Yep, this isn't a great fix, but it appears to be an improvement.
« Last Edit: January 20, 2014, 08:14:48 pm by armband »

digistump

  • Administrator
  • Hero Member
  • *****
  • Posts: 1465
Re: Problems with WiFi
« Reply #6 on: January 21, 2014, 01:18:03 am »
the delay(100) worked for me to solve the StartAT issue - but even with that fixed and stop() added it still loaded forever and never closed the connection.

I changed the delay(100) to delay(50) and that parts still works - so I will push that fix for now

armband

  • Newbie
  • *
  • Posts: 12
Re: Problems with WiFi
« Reply #7 on: January 21, 2014, 06:04:19 am »
Quote
the delay(100) worked for me to solve the StartAT issue - but even with that fixed and stop() added it still loaded forever and never closed the connection.

I changed the delay(100) to delay(50) and that parts still works - so I will push that fix for now

Great, that is an improvement even if it doesn't fully address the problem. I did find the delay somewhat sensitive, you may want to make sure that 50ms works with different combinations of baud rate and flow control settings. My set up uses flow control and the fastest configurable baud rate.  As far as the disconnect is concerned, it is possible that I was being fooled by browser behavior. I will need to be a bit more thorough with my analysis when I get back to it.

As food for thought, if the force disconnect is ultimately achievable via an AT command sequence, I have a hunch that it might still be unwise to place the module in command mode if it is being used by a server side application. I think timing of the inbound connections vs entry into command mode has the hallmark of a potential race condition that may lead to the possibility of AT commands being sent over the TCP link.

armband

  • Newbie
  • *
  • Posts: 12
Re: Problems with WiFi
« Reply #8 on: January 21, 2014, 06:06:45 pm »
Regarding the two issues:

1. startATMode() issue (Sending +++ fails to switch WiFi module from transparent mode to command mode )
   ----------------------
I have confirmed that the value of the delay (see earlier post) is sensitive to the baud rate:- A delay of 50ms works fine when the port speed is set to 9600, but not when it is set to the 460800 baud setting.  The value of 100ms has the desired effect at 460800.  This doesn't make much sense to me and seems somewhat arbitrary ... (my initial thought was that the delay value  should be slightly higher than the free-frame trigger time).  I have also tried adding the line Serial1.flush() immediately before the delay(..), but it has no noticeable effect.

2. Forced TCP disconnect in server mode
    ----------------------------------------
With this I have had no further luck.  Even with the above startATMode() fix, the DigiFi::stop() method (i.e. AT+TCPDIS) still does not appear to close server-side (inbound) connections. (I have however verified that it works as expected for client-side outbound connections).  I am at a loss as to where to proceed, so will fall back on my earlier statements ... Best to include "Content-Length" in the HTTP header, if you don't know the "Content-Length" then use chunked transfer encoding, if that is not feasible then set the WiFi module's TCP timeout to 1s (setTCPTimeout(1)).

SukkoPera

  • Newbie
  • *
  • Posts: 12
Re: Problems with WiFi
« Reply #9 on: January 22, 2014, 03:27:26 am »
As food for thought, if the force disconnect is ultimately achievable via an AT command sequence, I have a hunch that it might still be unwise to place the module in command mode if it is being used by a server side application. I think timing of the inbound connections vs entry into command mode has the hallmark of a potential race condition that may lead to the possibility of AT commands being sent over the TCP link.

Well, I have seen exactly this. My client was receiving the AT+TCPDIS command. I'm not sure why this happened, though. It might be due to other tweaks I had made in the library. I'll report if I see it again.

Some more food for thought: AFAIK, in old 56k modems, the "+++" sequence had to have a certain timing in order to switch to command mode from transparent mode. This is of course due to the fact that "+++" might be legitimate data one wants to send over the connection, in which case it shouldn't be interpreted as a request to switch to command mode. I haven't seen anything about such timing in our datasheet, but maybe this will turn up useful.

@digistump: Since you must have ben a very good customer, can't you get in touch with the manufacturer and ask for help with these issues? It looks completely absurd to me that one can't just close the server connection!

@armband: Chunked transfer encoding is definitely an option I will consider, thanks.
« Last Edit: January 22, 2014, 03:31:10 am by SukkoPera »

armband

  • Newbie
  • *
  • Posts: 12
Re: Problems with WiFi
« Reply #10 on: January 22, 2014, 08:16:56 am »
According to the documentation, when operating in TCP server mode, the usr-WiFi232-g module can support up to 8 client connections. Data received over its serial port is sent to all clients.

It occurs to me that the ability to support multiple inbound connections poses a problem if the server needs to close just one of the connections.  In essence, there is no handle/descriptor that the server can use to reference a given connection.  The best the module could do would be to close all connections on receipt of the AT+TCPDIS. I am speculating that the firmware developers chose to ignore AT+TCPDIS in server mode, rather than going with the "close all" approach.
« Last Edit: January 22, 2014, 08:18:32 am by armband »

digistump

  • Administrator
  • Hero Member
  • *****
  • Posts: 1465
Re: Problems with WiFi
« Reply #11 on: January 28, 2014, 01:58:41 am »
The next release has a full working chunked mode - this seems to be the best fix (that or set TCP Timeout to 1), though I hope to hear back from USR after the Chinese New Year (likely in February).

dfarrell

  • Newbie
  • *
  • Posts: 30
Re: Problems with WiFi
« Reply #12 on: February 17, 2014, 10:12:28 am »
I'm having a basic connect issue with 2 of my three DigiX's.  The first unit I purchased works fine with a external power supply and running in station + ap mode.  Worked so well that I bought two more.  These other two are another story, constant problems associating with my AP. I also have issues when connecting to the DigiX when it is the AP, sometimes a DCHP address, others none, config screens die, etc.  All are powered the same way, all with the same settings.  The solder job of the module to the two failing boards is significantly worse than the working one.  Were the WiFi modules put on after the initial re-flow? I did a factory restore to no avail.  I also have a blink sketch running to be consistent across all three boards. All modules have same version firmware (at least they report that). I should add, I am not using DigiX libs, only Serial1 IO in TCP mode (on working unit).

Update:
I finally downloaded the WiFi manual and tried using AT commands to set parameters and had some success.  Using "AT+WSKEY\r" I could see that the web interface was not accepting my key. If I sent "AT+WSKEY=WPA2PSK,AES,MyKey\r" it would take, but the web interface would not take MyKey  There is some delay (10's of seconds) until the initial connect is made.  There also seems to be interaction with the AP side when in AP+STA mode.

Update2:
One thing I noted in reading the USR documentation.  When set in AP+STA mode, if the STA is not connected the module will periodically scan for an AP for the STA to connect to.  This can interfere with reliable data transfer through the AP side of the module.

« Last Edit: February 25, 2014, 05:27:32 pm by dfarrell »

WarpedPixel

  • Newbie
  • *
  • Posts: 4
Re: Problems with WiFi
« Reply #13 on: April 21, 2014, 12:37:04 am »
I am using the latest release of DigiFi (from about a month ago on GitHub), and I am seeing the same problem described by armband. Since my goal was to use the Webduino library, converting to chunked transfers is complicated. I tried to set the TCP timeout to 1, and now I am seeing AT commands showing up in my web traffic fairly consistently. And that is pretty disastrous, because at that point the DigiFi library will understandably go nuts since it will never get the expected responses for the AT commands which were simply pumped into the http protocol instead. This also did not fix my connection problems, even in the cases that the DigiX does push the right data into the http responses, the browser on the other side sits around spinning forever.

My problem should be fairly simple: from the browser I make a GET request that the DigiX should respond with and html file, which then references a few files (css, js, jpg, all less than 10Kb) which should be requested in sequence. The results are random as to which parts of the request are ever sent back. I am rolling back to the simplest possible case to possibly get a repro I can post.

WarpedPixel

  • Newbie
  • *
  • Posts: 4
Re: Problems with WiFi
« Reply #14 on: April 21, 2014, 01:16:33 am »
Ok, I decided to just build the WebServerChunked sample, and this is what I got:

Code: [Select]
Enter any key to begin
Enter any key to begin
Enter any key to begin
server is at 192.168.1.132
GET / HTTP/1.1
Host: 192.168.1.132:8080
User-Agent: Mozilla/5.0 (Windows NT 6.3;6 v:26e00if6c hlpc/+pitx0*8caeU;po:,aotkl

The part at the bottom looks like garbage. The only changes I made were to go 57600 baud for both the serial debug and for the server iniatialization with begin(). My WiFi module is set to 57600 8N1 in the UI, with TCP timeout of 300.

So I reconfigured everything to 9600 and now I get the expected results. Seems like I am running into problems communicating with the WiFi part without flow control. Setting it back to 57600 but now with CTSRTS enabled in both sides, I also get the expected results. So now at least I can run the chunked sample correctly, you have to crawl before you can walk... ;-)

I went back and enabled flow control in my more complicated app, but unfortunately that did not solve anything, I still have the same apparent problem with connections. Need to look into converting it to chunked mode next week.