11 years, 1 month ago.

Websocket connection issue

When the power cycles and during the time my internet comes up, the websocket misses the connection. Then, even if the internet is alive, ws.connect() does no good. I have tried numerous methods that I could think of but could not bring the websocket up.

Help please. I need this board unattended to be able to start posting data to a remote website.

thanks Orhan

EDIT:

This code reads two analog inputs, submits one of them to cosm, and periodically fires a test relay.

Here is the code. If (during a power outage) the mbed gets an IP through my router but the internet has not been established yet, the websocket connection before the infinite loop cannot be made. After that, inside the infinite loop, even if I try to detect ws.is_connected() as false and try to reconnect the websocket (this time there is internet), it returns (1) initially but falls to (0) immediately.

I have lots of debugging pc.printf statements along the code to see what happens where, so sorry about that.

I currently worked around the issue by detecting this state and forcing a soft reset.

Thanks,

Orhan

#include "mbed.h"
#include "EthernetInterface.h"
#include "Websocket.h"
#include "SDFileSystem.h"
#include "Watchdog.h"

Serial pc(USBTX, USBRX); // tx, rx

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

//SDcard in-out check pin 30
DigitalIn Sd_in(p30);

DigitalOut Dout1(p9);
DigitalOut Dout2(p10);
DigitalOut Dout3(p11);
DigitalOut Dout4(p12);
DigitalOut Dout5(p13);
DigitalOut Dout6(p14);

AnalogIn Voltage_pin(p15);
AnalogIn Temperature(p16);

DigitalOut Dout7(p17);
DigitalOut Dout8(p18);
DigitalOut Dout9(p19);
DigitalOut Dout10(p20);

//Relay activation
DigitalOut Relay1(p21);

SDFileSystem sd(p5, p6, p7, p8, "sd"); // the pinout on the mbed Cool Components workshop board

Watchdog wd;

extern "C" void HardFault_Handler() {
    error("Hit HardFault handler!\n\r");
}

extern "C" void mbed_reset();

int main() {

    time_t seconds = time(NULL);
    
    float voltnow,tnow;
    int sd_in_last=0;
    int i=0;
    int test_eth_connection = 1;
    char timebuf[40];

    char mac[6];
    mbed_mac_address(mac); 
    
    //Watchdog timer to set a reset if no activity within 30 secs
    wd.Configure(45);

    pc.printf("Initialized %.2f Volts at %s\n\r",Voltage_pin.read(),ctime(&seconds));

    if(Sd_in == 1){
        sd_in_last = 1;
        mkdir("/sd/mydir", 0777);
  
        
        //Watchdog log
        if(wd.WatchdogCausedReset()){
            FILE *fp_wd = fopen("/sd/mydir/Reset_log.txt", "a");
            if(fp_wd == NULL) {
                error("Could not open file for write\n\r");
                fclose(fp_wd);
            }else{
                strftime(timebuf,40, "%I:%M:%S %p %d/%m/%Y", localtime(&seconds));
                fprintf(fp_wd, "WD Reset at %s\n\r",timebuf);
                fclose(fp_wd);
            }
        }//End Watchdog log
  
        
        FILE *fp = fopen("/sd/mydir/sdtest.txt", "a");
        if(fp == NULL) {
            error("Could not open file for write\n\r");
            fclose(fp);
        }else{
            led2=1;
            
            //fprintf(fp, "Hello fun SD Card World! %.2f Volts\n",Voltage_pin.read());

            char temp[1]={0},id[10]={0};

            //Print MAC address
            pc.printf("Ethernet MAC: ");
            for(i=0; i<6;i++) {
                pc.printf("%02X ", mac[i]);
                strcat(id, temp);
            }
            pc.printf("%s\n\r",id);

            fclose(fp);
        }
        led2=0; 
    }
    
    
    //data stream for COSM
    const char apikey[] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    const char feed[]= "/feeds/XXXXXXX";
    char cms[512];
    char recv[512];
    int token = 0;
 
    EthernetInterface eth;
    eth.init(); //Use DHCP
    test_eth_connection = eth.connect();
    pc.printf("IP Address is %s\n\r", eth.getIPAddress());
 
    Websocket ws("ws://api.cosm.com:8080/feeds/");
    ws.connect();
    
    if(ws.read(recv)) {
        pc.printf("rcv: %s\n\r", recv);
    }

    
    seconds = time(NULL);
    pc.printf("Time set RTC %d\n\r");

    pc.printf("Time s %d\n\r",seconds);
    if(seconds<1362535800){
        set_time(1362535800);  // Set RTC time
        pc.printf("New Time set RTC %d\n\r");
    }
 
    //Infinite loop
    while (1) {
    
    if(Sd_in == 1 && sd_in_last == 1){
        led3 = 1;
        pc.printf("Duba 10\n\r");
    }
    else if(Sd_in == 1 && sd_in_last == 0){
        led3 = 1;
        //initialize 2 times this is kind of a bug
        wait(1);//Give the Sd card some time
        sd.disk_initialize();
        pc.printf("SD Card reinitialized 1\n\r");
        wait(0.5);
        sd.disk_initialize();
        pc.printf("SD Card reinitialized 2\n\r");
        sd_in_last = 1;
    }
    else if(sd_in_last == 1) {
        led3 = 0;
        sd_in_last = 0;
        wait(1);
        pc.printf("SD Card removed\n\r");
    }

    led1 = 1;
    seconds = time(NULL);
    tnow = (Temperature.read()*3.3)*1000/10;
    voltnow = Voltage_pin.read()*3.3;
    pc.printf("Duba 30\n\r");

    /*  JSON REQUEST FORMAT***********************************
    {
      "method" : "put",
      "resource" : "/feeds/504",
      "params" : {},
      "headers" : {"X-ApiKey":"abcdef123456"},
      "body" :
        {
          "version" : "1.0.0",
          "datastreams" : [
            {
              "id" : "0",
              "current_value" : "980"
            },
            {
              "id" : "1",
              "current_value" : "-261"
            }
          ]
        },
      "token" : "0x12345"
    }
     
    // Response:
    {
      "token" : "0x12345",
      "status" : 200,
      "resource" : "/feeds/504"
    }
    */

    pc.printf("Duba 35\n\r");
    
    //COSM Data Formation, for our logger in JSON form
    sprintf (cms,"{\"method\" : \"put\",\"resource\" : \"%s\",\"params\" : {},\"headers\" : {\"X-ApiKey\":\"%s\"},\"body\" :{\"version\" : \"1.0.0\",\"datastreams\" : [{\"id\" : \"0\",\"current_value\" : \"%4.2f\"}]},\"token\" : \"0x%d\"}\r\n",feed,apikey,tnow,token);
    pc.printf ("%s\n\r",cms);
    token++;
    
    
    if(test_eth_connection != 0){
        pc.printf("Trying ethernet in loop IP Address is %s\n\r", eth.getIPAddress());
        //eth.init(); //Use DHCP
        pc.printf("Duba 32\n\r");
        test_eth_connection = eth.connect();
        pc.printf("Duba 33\n\r");
        
    }
  

//The  ws.is_connected() check below did not work:
/*  
  if(!ws.is_connected()){
               if(test_eth_connection == 0){
                      ws.connect();
               }//End test_eth_connection check
    }//End if ws.connected check
*/


//So I now use soft reset here:    
    if(!ws.is_connected()){
        if(test_eth_connection == 0){
            if(Sd_in == 1){//Sd check
                FILE *fp_wd = fopen("/sd/mydir/Reset_log.txt", "a");
                if(fp_wd == NULL) {
                    error("Could not open file for write\n\r");
                    fclose(fp_wd);
                }else{
                    strftime(timebuf,40, "%I:%M:%S %p %d/%m/%Y", localtime(&seconds));
                    fprintf(fp_wd, "Soft Reset at %s\n\r",timebuf);
                    fclose(fp_wd);
                }
            }//End Sd check
            mbed_reset();//There is ethernet connection (most possibly internet) so lets restart for websocket
        }//End if test ethernet
    }//End if ws.connected check
    
    //Keep result from COSM
    pc.printf("Will send %d\n\r",ws.is_connected());
    int res = ws.send(cms);
    pc.printf("Tried sending (is connected %d) \n\r",ws.is_connected());
    led1= 0 ;
 
    pc.printf("Duba 40\n\r");
 
    if(ws.read(recv)) {
        pc.printf("rcv: %s\n\r", recv);
        //wait(15);    
    }
    //COSM Stuff ends here
 
    //Local Logging to SD card
    //Format time (time is captured when sensors are read)
    strftime(timebuf,40, "%I:%M:%S %p %d/%m/%Y", localtime(&seconds));
    pc.printf("Recording %.6f Volts and %.2f Degrees C at %s\n\r",voltnow,tnow,ctime(&seconds));

    if(Sd_in == 1){
        FILE *fp = fopen("/sd/mydir/sdtest.txt", "a");
        pc.printf("Duba 90\n\r");
        if(fp == NULL) {
            error("Could not open file for write\n\r");
            fclose(fp);
        }else{
            led2=1;
            fprintf(fp, "Recording %.6f Volts and %.2f Degrees C at %s\n",voltnow,tnow,timebuf);
            fclose(fp);
            pc.printf("Duba 95\n\r");
        }
    }//End if Sd_in
    //End of local logging
    pc.printf("Duba 100\n\r");

    led2=0;
    //Relay Test Stuff
    Relay1 = 1;
    wait(1);
    Relay1 = 0;
    
    pc.printf("Duba 110\n\r");
    
    
    led1 = 1;
    wait(0.2);
    led1 = 0;
 
    wait(13);
    
    wd.Service();
    pc.printf("Duba 120\n\r");
    }//End while(1) Infinite loop
   
}//end main

Hi, can you post your code? are you using the ethernetinterface? Is the mbed able to fetch an IP address before trying to connect the websocket server?

posted by Samuel Mokrani 06 Mar 2013

Please see line 216 for the code that did not work, and line 226 for the workaround. Thanks

posted by Orhan Dengiz 06 Mar 2013

Hi, can you try to reduce your code because it is huge. Then you say

Quote:

it returns (1) initially but falls to (0) immediately

Does it mean that you are able to connect the websocket just once after that you lost the connection? If it returns 1 why do you need to connect again?

Cheers, Sam

posted by Samuel Mokrani 06 Mar 2013

Here is the reduced version. The problem is; if during power up there is no internet connectivity, socket cannot be initialized later on.

#include "mbed.h"
#include "EthernetInterface.h"
#include "Websocket.h"
#include "SDFileSystem.h"
#include "Watchdog.h"
Serial pc(USBTX, USBRX); // tx, rx
 
DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);
 
//SDcard in-out check pin 30
DigitalIn Sd_in(p30);

AnalogIn Voltage_pin(p15);
AnalogIn Temperature(p16);
 
DigitalOut Relay1(p21);
 
SDFileSystem sd(p5, p6, p7, p8, "sd");
 
Watchdog wd;
 
extern "C" void HardFault_Handler() {
    error("Hit HardFault handler!\n\r");
}
 
extern "C" void mbed_reset();
 
int main() {
 
    time_t seconds = time(NULL);
    float voltnow,tnow;
    int sd_in_last=0;
    int i=0;
    int test_eth_connection = 1;
    char timebuf[40];
 
    char mac[6];
    mbed_mac_address(mac); 
    
    wd.Configure(45);
 
    const char apikey[] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    const char feed[]= "/feeds/XXXXXXX";
    char cms[512];
    char recv[512];
    int token = 0;
 
    EthernetInterface eth;
    eth.init(); //Use DHCP
    test_eth_connection = eth.connect();
    pc.printf("IP Address is %s\n\r", eth.getIPAddress());
 
    Websocket ws("ws://api.cosm.com:8080/feeds/");
    ws.connect();
    
    if(ws.read(recv)) {
        pc.printf("rcv: %s\n\r", recv);
    }
 
    while (1) {

    sprintf (cms,"{\"method\" : \"put\",\"resource\" : \"%s\",\"params\" : {},\"headers\" : {\"X-ApiKey\":\"%s\"},\"body\" :{\"version\" : \"1.0.0\",\"datastreams\" : [{\"id\" : \"0\",\"current_value\" : \"%4.2f\"}]},\"token\" : \"0x%d\"}\r\n",feed,apikey,tnow,token);
    pc.printf ("%s\n\r",cms);
    token++;
    
    if(test_eth_connection != 0){
        //eth.init(); //Use DHCP
        test_eth_connection = eth.connect();
        
    }
  
 
//This one below does not work, although we know there is active internet connection
/*  
  if(!ws.is_connected()){
               if(test_eth_connection == 0){
                      ws.connect();
               }//End test_eth_connection check
    }//End if ws.connected check
*/

//So soft reset is used to bring the socket up    
    if(!ws.is_connected()){
        if(test_eth_connection == 0){

            mbed_reset();//There is ethernet connection (most possibly internet) so lets restart for websocket

        }//End if test ethernet
    }//End if ws.connected check
    
    //COSM Stuff ends here
 
 
    led2=0;

    led1 = 1;
    wait(0.2);
    led1 = 0;
 
    wait(13);
    
    wd.Service();

    }//End while(1) Infinite loop
   
}//end main
posted by Orhan Dengiz 16 Mar 2013

2 Answers

11 years, 1 month ago.

Hi Orhan!

I have a similar program and the same problem :-(

My program runs for hours and suddenly the connection breaks. I've tested a lot ( reconnect, disconnect (Ethernet and/or Websocket), destroy object and create new one) but it didn't help It seems that the TCP-connection remains open somewhere (router, cosm, somewhere else?) and then you can't create a new one. I've added a very long wait() before I reconnect. It's better now, but not working all the time.

Do you always get a connection after the soft reset ?

Charly

11 years, 1 month ago.

Karl, if I have an alive internet connection at the time of soft reset, yes. It works everytime that I tried. The thing is, if in the future I need to keep long term variables in the memory, the soft reset will not be a valid solution for this problem. I think it should be possible to fix in the library.

Orhan