Websocket library bug ?

20 Sep 2012

I tried the websocket library to send some Json to pachube (cosm) but didn't get too far so went to basics to test the library

I have been testing out code on the mbed socket server as follows

#include "mbed.h"
#include "EthernetInterface.h"
#include "Websocket.h"
 
 
int main() {
 Serial pc(USBTX, USBRX);
pc.baud (921600);

 
    char recv[256];
 
    EthernetInterface eth;
    eth.init(); //Use DHCP
    eth.connect();
    pc.printf("IP Address is %s\n\r", eth.getIPAddress());
 
    Websocket ws("ws://sockets.mbed.org:443/ws/madmanmav/rw");
    ws.connect();
 
    while (1) {
      //  ws.send("WebSocket Hello World over Ethernet");
     //   wait(1.0);
ws.read(recv);  // read message into recv
printf (recv);  // Print to PC
recv[0]=NULL; // Clear Recv
    }
}

Now on the web interface I can open the sending page and the view page in two browser windows. Then I simply send the letter 'A' as a message , which shows in the view window as 'Message: a' exactly as expected. I get nothing at the Mbed end though untill I send the messeage 64 times then I get AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Similarly if i send TEST in the view page I see 'message: TEST" , but i have to send this message 16 times before the mbed prinf's TESTTESTEST....... 16 times.

It seems the library is buffering 64 chars worth of messages before it will pass them to WS.read() Anyone got any ideas as to this behavior ??

20 Sep 2012

Hi Maverick,

Can you try to use

while (1) {
    if (ws.read())
       printf("%s\r\n", recv);
}

to be sure that the buffer is flushed and that you have effectively received a message.

Cheers, Sam

20 Sep 2012

Hi Samuel That won't compile. Did you mean....

while (1) {
    if (ws.read(recv))
       printf("%s\r\n", recv);    
}

That compiles and so far seems to cure the issue so far. I have much to learn. Can you tell me why printf(recv) without the '"%s",' for referance (still learning C++ idiosyncrasies. Thanks for your help

If i posted a cosm (pachube test) could you look it over for noob errors ?

#include "mbed.h"
#include "EthernetInterface.h"
#include "Websocket.h"
AnalogIn val1(p20);
AnalogIn val2(p19);
DigitalOut myled(LED1);


int main()
{


const char apikey[] = "m3NSqNwvgbenqB3x-6m5OLNjraySAKx3b2FXVUI3SEtRbz0g";
const char feed[]= "/feeds/74961";
    char cms[512];
    char recv[512];
int token = 0;
Serial pc(USBTX, USBRX);
pc.baud (921600);



    EthernetInterface eth;
    eth.init(); //Use DHCP
  
  
  
    eth.connect();
    pc.printf("IP Address is %s\n\r", eth.getIPAddress());

    Websocket ws("ws://api.cosm.com:8080");
    ws.connect();

   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\"},{\"id\" : \"1\",\"current_value\" : \"%4.2f\"}]},\"token\" : \"0x%d\"}",feed,apikey,val1.read()*3.3,val2.read()*3.3,token);
token++;
        int res = ws.send(cms);
 wait(1);
       
      
       ws.read(recv);
            pc.printf("rcv: %s\r\n ", recv);


        
      
    } 
}

the sprinf is to get the JSON into CMS feel free to play with my api key and feed if you like I don't mind

20 Sep 2012

Hi Maverick,

Quote:

Hi Samuel That won't compile. Did you mean....

while (1) {
    if (ws.read(recv))
       printf("%s\r\n", recv);    
}

Yep exactly!

The important thing is not the "%s" but the "\n" at the end. Printf buffers before effectively sending the data. If you put a "\n" at the end of your string, the buffer will be flushed. In your case (without "\n"), 64 bytes was buffered and then flushed.

Quote:

If i posted a cosm (pachube test) could you look it over for noob errors ?

Looks good. The only thing is:

ws.read(recv);
pc.printf("rcv: %s\r\n ", recv);

As the read function returns TRUE if a valid message has been read or FALSE otherwise, I would use the following code:

if(ws.read(recv)) {
    pc.printf("rcv: %s\r\n", recv);
}

Cheers, Sam

20 Sep 2012

Thanks for that Sam (virtual beer on me)cleared up a few things what about the sending side ?? I tried allsorts to get the JOSN values upto cosm websocket , kept getting errors or a -1 return. Tells me my json isn't valid even though i prinf CMS to terminal copy the json and run it through a validator that tells me it is.

Maybe you could look into cosm. as the API docs aren't as friendly to non JS types and are a bit terse. The service itself looks good.

I did have it working after a fashion it seemed to connect and upload the first JSON values (as i saw em change in the cosm interface, and a little java page connected to the same socket) but no value after that

I have already uploaded to nimbits (similar internet of things platform and intend to try convert my working scrawl to a library Pachube web-sockets would be great.

Maybe a side project if yer not busy ? ) Meantime i will keep plugging away to see if I can get it to work this end.

Trying it on Cosm i connect with my JS page as soon as i try to connect with mbed it disconnects the socket :(

Thanks again

20 Sep 2012

Got it working here is the working lashup code to put to cosm via websockets

#include "mbed.h"
#include "EthernetInterface.h"
#include "Websocket.h"
AnalogIn val1(p20);
AnalogIn val2(p19);
DigitalOut myled(LED1);


int main()
{


    const char apikey[] = "YOUR API KEY";
    const char feed[]= "/feeds/YOUR FEED";
    char cms[512];
    char recv[512];
    int token = 0;
    Serial pc(USBTX, USBRX);
    pc.baud (921600);



    EthernetInterface eth;
    eth.init(); //Use DHCP



    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\r\n", recv);
    }

    while (1) {
        myled = 1;
        sprintf (cms,"{\"method\" : \"put\",\"resource\" : \"%s\",\"params\" : {},\"headers\" : {\"X-ApiKey\":\"%s\"},\"body\" :{\"version\" : \"1.0.0\",\"datastreams\" : [{\"id\" : \"0\",\"current_value\" : \"%4.2f\"},{\"id\" : \"1\",\"current_value\" : \"%4.2f\"}]},\"token\" : \"0x%d\"}\r\n",feed,apikey,val1.read()*3.3,val2.read()*3.3,token);
        printf ("%s\r\n",cms);
        token++;
        int res = ws.send(cms);
        myled= 0 ;


        if(ws.read(recv)) {
            pc.printf("rcv: %s\r\n", recv);
            wait(1);
        }




    }
}


/*  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"
}
*/

I will clean it up and publish as a library. Need to add a few things like if the websocket drops out to reconnect ect.

Thanks Sam , you been an inspiration

21 Sep 2012

he, great... it works... i think i will integrate this in my domotica system...

21 Sep 2012

Your welcome Sam is the real hero making the web-socket library. i just bent it to talk to Cosm web-socket interface. Loads to do , like include UTC time stamps , ect

22 Sep 2012

i changed a bit the format of the string, so it's easier to insert new values and read it. Sometimes the code "hangs", need to investigate why.

       sprintf (cms,"{\"method\" : \"put\",\"resource\" : \"%s\",\"params\" : {},\"headers\" : {\"X-ApiKey\":\"%s\"},\
        \"body\" :{\"version\" : \"1.0.0\",\"datastreams\" :[\
        {\"id\" : \"0\",\"current_value\" : \"%2.1f\"},\
        {\"id\" : \"1\",\"current_value\" : \"%2.1f\"},\
        {\"id\" : \"2\",\"current_value\" : \"%2.1f\"},\
        {\"id\" : \"3\",\"current_value\" : \"%2.1f\"},\
        {\"id\" : \"4\",\"current_value\" : \"%2.1f\"},\
        {\"id\" : \"5\",\"current_value\" : \"%2.1f\"},\
        {\"id\" : \"6\",\"current_value\" : \"%2.1f\"},\
        {\"id\" : \"7\",\"current_value\" : \"%2.1f\"},\
        {\"id\" : \"8\",\"current_value\" : \"%2.1f\"}\
        ]},\"token\" : \"0x%d\"}\r\n",feed,apikey,\
                 windaverage,windgust,tempbuiten,tempbinnen,sensor1,sensor2,sensor3,regen,hpa,\
                 token);
22 Sep 2012

increased the recv buffer to 1024 bytes, that seems to be the problem

22 Sep 2012

Hi,

Quote:

increased the recv buffer to 1024 bytes, that seems to be the problem

This is probably the problem. If the response is bigger than your buffer, the program will probably ends up in the hardfault handler. To check that, you can add the following in your main.cpp file for instance:

extern "C" void HardFault_Handler() {
    error("Hard Fault!\n");
}

Cheers, Sam

22 Sep 2012

still hangs... youre example cannot be compiled... "linkage specification not allowed"

22 Sep 2012

I haven't put it in yet but if you hammer the rate too much you can get and error 403 and get disconnected from the socket (not happened to me yet and im hammerin it) Also the socket can get disconnected occasionally due to network instability or a server glitch Cosm's end. Could this be the issue ? how often does it hang ?

Need to put in a check with is_connected(); if not reconnect , just not got round to it yet.

22 Sep 2012

no, the rate is putted back to 10 seconds last time the token was 265.... after that froozen. and for so far it seems it to happens every time, but will take some time (265*10 seconds=44 minutes) i will put the rate back to 1 minute and see what's happening then

22 Sep 2012

I just blasted 417 puts in 5 mins , so rate isn't the issue , no crashes though, I will make more feed values and see if it happens here (only doing 2 a time atm)

23 Sep 2012

yes it is strange... last hangup was after 63 minutes. Anyway i used a thread as timer and some flashing leds and it looks better. included the complete program for anyone who wants to start.

It's now under test standalone in my domotica system... hope's it will continue dumping the data /media/uploads/bert1952/cosm_copy_uvision_lpc1768.zip ------ standalone (without the PC connected) no hangups anymore. I defined only max 6 threads possible. Dont know if that has anything to do with it.

25 Sep 2012

well there is something with the library. I'm running it now 24/24. after some hours, no data is uploaded anymore to Cosm. If i look at the debug output i see that the application sends the data, but no answer anymore in return, the read returns false. this can be a closed socket, however i'm testing the socket before sending, and the response is the socket is open...

i coded it now in such a way that in the case the read is false a new socket is opened, but that doesnt help. Only a restart of the application will continue dumping data to cosm. Upload rate is 14 sec, so that cannot be the problem.

All other functions of the application continues, like http server/email sms etc.

13 Nov 2012

Hi!

Are there any news on this topic?

I have a program which sends data to Cosm with the old Ethernet interface. As this hangs from time to time, I'm trying to use the new interface. But as the new http-client doesn't support headers I need something other. I've found this thread. But it also seems to have problems with Cosm.

Is there a save way to send data to cosm?

Charly

14 Nov 2012

yes, cosm is working. No hanging anymore, but the connection was lost after hours of dumping data

19 Nov 2012

I got the same problems with the websocket library. I post data every aprox. minute to COSM (That seems to be the maximum RTOS timer time) and after some hours it stops doing it.

Besides that I have also problems with pwmout together with the RTOS library.

BTW: Is there a HTTP server and email library available for the RTOS implementation?

19 Nov 2012

I deleted the COSM function as it is unstable Sometime ago i posted a base64 email client in RTOS thread