6 years, 10 months ago.  This question has been closed. Reason: The best answer at this moment is to change the code to handle blocking!

WiflyInterface RN-XV ping cmd while using TCPSocketServer and TCPSocketConnection classes!

I understand the WiflyInterface class has the member function is_connected but this only tells you if a TCP socket is currently connected when using the RN-XV module! I would like to have a method for detecting if the RN-XV module is still connected to the access point it may have started out connected to when you use the init member function?

Looking through the RN-XV user manual I see the command called ping i. I have tested this command to ping an ip address and this seems to be a good way to verify the RN-XV module is connected. My question is how do you use this command when you are using the TCPSocketServer and TCPSocketConnection classes with the current mbed RTOS as a http server that is currently waiting for a connection? Are there any examples that show how to issue a wifly cmd when sockets are used. I figure the tcp sockets maybe need to be turned off then the command to the wifly module issued then the tcp sockets need to be restarted but i can't seem to get this to work!

The reason for this question is because once you have the TCP socket stuff setup and working it works great but what if the router the RN-XV module is connected to gets reset then the incoming socket now never gets detected in the WiflyInterface class because the RN-XV module is not connected anymore. I figure some kind of interrupt timer should be setup to watch the RN-XV module and see if it is still connected and if not then the device should be reset and the wifly connection should be reinitialized!

Any thoughts on this would be appreciated! I have a reliable working web server that returns information about some sensors that i want to use but i feel i need some method for this code to detect issues like external connection interruptions!

Hello Philip Smith,

are you using blocking or non-blocking calls? You alleged that you can't get it work, why don't you share a snippet of your code?

posted by Martin Kojtal 17 Nov 2013

As you recognize, it momentarily switches away from your socket connection to process the command. sendCommand(...) calls send(...) which issues an attach_rx(false). This lets it then bypass the socket services you may have running, put the WiFly module in command mode, send the command and process the result. When it is complete, it attach_rx(true), to route traffic on to the socket services. There can be a problem in this sequence - if both ends of the network don't know what is happening, you may see information stream in while you are sending the ping command.

posted by David Smart 28 Nov 2013

Yes I figured that this idea would have the described problem that you identify David! It seems to me that this questions about blocking working or not or how to get it to work is one question. The other question is how to test a connection with the wifly module being used when using TCPSocketServer and TCPSocketConnection. Blocking would be a possible way to do this testing with but possibly not the best method. At this moment my the only other solution i have is to set up a timer based reset of the mbed and software that simply restarts the complete process including the wifly connection to the router connection. Really the main question i wanted answered is how to ensure the wifly connection is working!

posted by Philip Smith 29 Nov 2013

2 Answers

6 years, 9 months ago.

Some of the blocking/non-blocking code in the mbed library wasn't working as I expected. I won't rule out the possibility I didn't understand how to use it properly, but I couldn't get non-blocking to work. So, I created a derivative library with changes to support non-blocking (and many other tweaks). WiflyInterface - derived from mbed

from mbed library - is not non-blocking, cannot return -1

int TCPSocketServer::accept(TCPSocketConnection& connection) {
    int nb_available = 0, pos = 0;
    char c;
    string str;
    bool o_find = false;
    while (1) {
        while(!wifi->readable());
        nb_available = wifi->readable();
        for (int i = 0; i < nb_available; i++) {
            c = wifi->getc();
            if (c == '*') {
                o_find = true;
            }
            if (o_find && c != '\r' && c != '\n') {
                str += c;
                pos = str.find("*OPEN*");
                if (pos != string::npos) {
                    wifi->flush();
                    return 0;
                }
            }
        }
    }

compared to

from my derivative library, is non-blocking aware

int TCPSocketServer::accept(TCPSocketConnection& connection)
{
    int nb_available = 0;
    char c;
    const char OPEN[] = "*OPEN*";   // seeking this to accept

    acceptTimerStart();
    while (1) {
        nb_available = wifi->readable();
        if (nb_available == 0 && !_blocking && acceptTimeout())
            return -1;
        for (int i = 0; i < nb_available; i++) {
            c = wifi->getc();
            if (c != OPEN[acceptIndex])
                acceptIndex = 0;
            if (c == OPEN[acceptIndex]) {
                acceptIndex++;
                if (acceptIndex == strlen(OPEN)) {
                    wifi->setConnectionState(true);
                    acceptIndex = 0;    // for next pass
                    return 0;
                }
            }
        }
    }
}

Accepted Answer

Thank you for offering this option David. I am still looking at this idea. I was more or less thinking the same idea as your code here suggests but i was still just trying to look at all the other possible stuff involved. I will post once i see how this code works once i have time. Thank again!

posted by Philip Smith 29 Nov 2013

Having looked at this before and re looking at it now i can not see how the existing Mbed code as you show above could return -1 for non blocking. As your above text shows "from mbed library - is not non-blocking, cannot return -1" i think your changes seem reasonable because the Mbed code does not even consider blocking or non blocking. I was having a hard time with that conclusion originally because i general think everybody else has much better code then i make. I will do some testing and see how this goes.

posted by Philip Smith 29 Nov 2013

Well Thank you Very much David! I have now simply imported your library and simply started using it... Seems to work with what i wanted to do and i like your improvements to the class. I was going to start to make my own solution but after looking at what you have done i am very grateful because you have done it for me. Here is a link to the class for others that need this also https://mbed.org/users/WiredHome/code/WiflyInterface/ Thanks again!

posted by Philip Smith 01 Dec 2013
6 years, 10 months ago.

Well i have been asked by Martin to provide some example. Here is one thought i had but i am still trying to understand the new TCPSocketServer and TCPSocketConnection classes in the context of the wifly module so i am sure that this example is totally off base.

#include "mbed.h"
#include <stdio.h>
#include <string.h>
#include "RHT03.h"
#include "WiflyInterface.h"

#define PORT   4446
#define READTIME 4
#define TIMEOUT 2000
#define ALLGOOD 3000
#define TOMUCH  1024

/* wifly object where:
*     - p28 and p27 are for the serial communication (p28 to pin3(UART_RX) on wifly)(p27 to pin2(UART_TX) on wifly)
*     - p26 is for the reset pin (p26 to pin5(RESET)on wifly)
*     - p25 is for the connection status (p25 to pin15(GPIO 6/SEN 7)on wifly)
*/

WiflyInterface wifly(p28, p27, p26, p25, "myssid", "mypassword", WPA);

TCPSocketServer svr;
bool serverIsListened = false;

TCPSocketConnection client;
bool clientIsConnected = false;

DigitalOut led1(LED1); //server listning status
DigitalOut led2(LED2); //socket connecting status
DigitalOut sensorLed(LED4); //sensor reading indicator
DigitalOut connectionTestLed(LED3); // wifly connection testing indicator

RHT03 humtemp(p24);  // DTH22 sensor on pin 24 with pull up resistor of 5k.

float temp,hum;
int readingAge = 0;

Ticker ledTick;
Ticker Sensors;
Ticker TestConnection;

void ledTickfunc()
{
    if(serverIsListened)  {
        led1 = !led1;
    } else {
        led1 = false;
    }
}

void Sensorsread()
{
    if(serverIsListened) {
        readingAge = readingAge + READTIME;
        sensorLed=true;
        if(humtemp.readData() == RHT_ERROR_NONE) {
            temp = humtemp.getTemperatureC(); //Gets the current temperature in centigrade
            hum = humtemp.getHumidity(); //Gets the current humidity in percentage
            readingAge = 0;
        }
        sensorLed=false;
    }
}

void TestWiflyConnection()
{
    bool test = true;
    connectionTestLed = test;
    if(!wifly.is_connected()) {
        if(wifly.cmdMode()) {
            wifly.sendCommand("ping i\r");  // note infact this code does not currently check the response of the wifly module 
            wifly.exit();                   // the response will need to be checked once i get this working!
            test = false;
        }
        connectionTestLed = test;
    }
}

int main (void)
{
    ledTick.attach(&ledTickfunc,1.0);
    Sensors.attach(&Sensorsread,READTIME);
    //TestConnection.attach(&TestWiflyConnection,60);

    printf("Starting Wifly!\r\n");
    //wifly.init(); // use DHCP
    wifly.init("192.168.0.120","255.255.255.0","192.168.0.10");  // use static ip address
    while (!wifly.connect()); // join the network
    printf("IP Address is %s\n\r", wifly.getIPAddress());
    printf("Wifly set comm idle 2 test %d\r\n",wifly.sendCommand("set comm idle 2"));
    // note this Wifly command "set comm idle 2" seems to make the issue of a browser stay connected, go away!
    // This command means time out on a tcp connection after 2 seconds!
    // This command does not seem to be in wifly.cpp initalization code so it is good to have here!
    printf("Wifly set comm time 200 test %d\r\n",wifly.sendCommand("set comm time 200"));
    // Note this Wifly command "set comm time 200" sets the time after tcp incomming message recieved will wait before sending packet.
    // This command means wait 200 ms.  This means packets are less fragmented from Wifly to Mbed via serial uart.
    // It seems in wifly.cpp there is a "set c t 20" so that means that this command here would force the wifly to increase its time so all good!
    
    TestWiflyConnection(); // not this is the command for testing the wifly connection to router and web but will only work if TCPSocketServer and TCPSocketConnection are disabled 
    
    //setup tcp socket
    svr.set_blocking(false,1500);
    //client.set_blocking(false);
    if(svr.bind(PORT)< 0) {
        printf("tcp server bind failed.\n\r");
        return -1;
    } else {
        printf("tcp server bind successed.\n\r");
        serverIsListened = true;
    }

    if(svr.listen(1) < 0) {
        printf("tcp server listen failed.\n\r");
        return -1;
    } else {
        printf("tcp server is listening...\n\r");
    }

    //listening for http GET request
    while (serverIsListened) {
        //no blocking mode is set above for both TCPSocketConnection and TCPSocketServer (not sure if they both need non blocking or just one needs to be set?)
        printf("About to wait for connection!\n\r");
        if(svr.accept(client)<0) {
            printf("no connection time to test wifly connection to router!\n\r");
            //******************************************************
            // Thought this would be the place for TestWiflyConnection() but on some kind of intermittent time basis.
            // Also i figured that the TCPSocketServer and TCPSocketConnection would need to be closed then restarted before and after TestWiflyConnection()
            // or the wifly module will be confused.
            // but it seems that this place in the code never gets executed in blocking or nonblocking because the svr.accept(client) never returns -1 unless the wifly module has some issue!
            // So i am confused what blocking and non blocking are even for with the wifly module.  It seems that i might just need to scrap the complete new tcp stack stuff 
            // and control the wifly module myself and make my own tcp stack interface to the wifly module!
            //**************************************************
        } else {
            printf("connection success!\n\rIP: %s\n\r",client.get_address());
            clientIsConnected = true;
            led2 = true;
            char buffer[1024] = {};
            int checkRecieve = 0;
            Timer timeOut;
            timeOut.start();
            while(clientIsConnected) {
                char temp[256] = {};
                checkRecieve = client.receive(temp,255);
                //printf("Recieved: %d\r\n%s\r\n",strlen(temp),temp);
                strcat(buffer,temp);
                if(timeOut.read_ms()>2000) {
                    // i am goint to presume here that after 2 second i will not continue anyways!
                    printf("Message end not recieved in time out allowed! Connection presummed stalled!\r\n");
                    printf("Buffer currently: %d\r\n%s\r\n",strlen(buffer),buffer);
                    timeOut.stop();
                    clientIsConnected = false;
                    led2 = false;
                    checkRecieve = TIMEOUT;
                }
                if(checkRecieve == -1) {
                    printf("failed to read data from client.\r\n");
                    clientIsConnected = false;
                    led2 = false;
                }
                if(strlen(buffer)>1023) {
                    printf("Recieved message too large from client!\r\n");
                    clientIsConnected = false;
                    led2 = false;
                    checkRecieve = TOMUCH;
                }
                if(strstr(buffer, "\r\n\r\n")) {
                    printf("Recieved terminator in message!\r\n");
                    clientIsConnected = false;
                    led2 = false;
                    checkRecieve = ALLGOOD;
                }
            }
            if (checkRecieve == ALLGOOD) {
                if(buffer[0] == 'G' && buffer[1] == 'E' && buffer[2] == 'T') {
                    if(buffer[4] == '/' && buffer[5] == ' ') {
                        printf("GET / incomming.\n\r");
                        //setup http response header & data
                        char sendHeader[256] = {};
                        char sendMessage[256] = {};
                        sprintf(sendMessage,"<!DOCTYPE html><html><HEAD><TITLE>Temp Humd CO2</TITLE></HEAD><body>Temp: %2.1f<br>Humd: %2.1f<br>Age: %2ds<br></body></html>\r\n\r\n",temp,hum,readingAge);
                        sprintf(sendHeader,"HTTP/1.0 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\nConnection: Close\r\n\r\n",strlen(sendMessage));
                        client.send(sendHeader,strlen(sendHeader));
                        client.send(sendMessage,strlen(sendMessage));

                        clientIsConnected = false;
                        led2 = false;
                        printf("Header %s\r\n",sendHeader);
                        printf("Message %s\r\n",sendMessage);
                    }

                } else {
                    printf("Get not recieved!");
                    clientIsConnected = false;
                    led2 = false;
                }
            }
            printf("Recieved %d\r\n%s\r\n",strlen(buffer),buffer);
        }
        printf("close connection.\n\rtcp server is listening...\n\r");
        client.close();
        led2 = false;
    }
}

Ok this example code does work! Testing shows that if the router the wifly module is connected to resets then future connections never happen. The example only has a comment at the location i think some code should be to do this wifly module connection test but i do not have any code there because the execution never gets there anyways in my testing! Other directions to go i have not idea yet untill i can understand these other classes and also understand blocking and non blocking with the wifly module as this seems to currently have no meaning! pks

Part of the question here is what does blocking mean and non blocking when the wifly module is used? How to use blocking and non blocking? I thought that non blocking means that if the socket does not have a connection and no transfer is happening that the code would continue. This code shows that blocking set to false or true seems to be no different from each other when using the wifly module. It may be that i have set blocking false incorrectly in this example but i have tried several ways to do this with the WiflyInterface class being used with TCPSocketServer and TCPSocketConnection classes and as i say in my question that started this tread that it does not work! I have not tried to use non blocking with TCPSocketServer and TCPSocketConnection class and the ethernet connection!

posted by Philip Smith 19 Nov 2013

reposting as an "answer", not a "comment"

posted by David Smart 28 Nov 2013