Websocket and Mbed

» Import this programWebsocket_Wifly_HelloWorld

WebSocket Hello World using the wifly interface

» Import this programWebsocket_Ethernet_HelloWorld

websocket client ethernet hello world example

As explained in this webpage, the WebSocket protocol allows full-duplex, bi-directional communications between a server and clients.

The websocket server

In this tutorial, we will be using a public server provided by mbed for testing purposes.

So you just have to program your mbed!

If you want more information regarding the server side code, see Mbed WebSocket server and Websockets Server

This tutorial is divided into two parts:

  • Part 1 - Sending Hello World over a WebSocket communication over WiFi
  • Part 2 - Sending Hello World over a WebSocket communication over Ethernet

You may wish to skip to the relevant section after you have chosen whether you are using WiFi or Ethernet

Part 1 - Sending data from the Mbed: Wifi

Materials required

For this part you need:

  • an mbed ;)
  • a Wifly module like this
  • a router

1.1 - Code

You may wish to skim the page on the WiFly module.

The main code:

#include "mbed.h"
#include "WiflyInterface.h"
#include "Websocket.h"


/* wifly interface:
*     - p9 and p10 are for the serial communication
*     - p19 is for the reset pin
*     - p26 is for the connection status
*     - "mbed" is the ssid of the network
*     - "password" is the password
*     - WPA is the security
*/
WiflyInterface wifly(p9, p10, p19, p26, "mbed", "password", WPA);

int main() {
    wifly.init(); //Use DHCP
    while (!wifly.connect());
    printf("IP Address is %s\n\r", wifly.getIPAddress());

    Websocket ws("ws://sockets.mbed.org:443/ws/demo/wo");
    while (!ws.connect());

    while (1) {
            ws.send("WebSocket Hello World over Wifly");
            wait(1.0);
    }
}

» Import this programWebsocket_Wifly_HelloWorld

WebSocket Hello World using the wifly interface

ssid, key, mode, channel

Don't forget to adapt:

  • the ssid and the key of your network in the Wifly constructor
  • the mode and the channel of your choice in the WebSocket constructor


1.2 - You should be ready!

  • You can now download this program into your mbed
  • Visit the webpage of your own channel: http://sockets.mbed.org/your_own_channel/viewer

Information

You can join the server, create your own channel, send and view messages over your channel just by visiting:

http://sockets.mbed.org


1.3 - Demo

You can check that all is working by visiting the webpage of your own channel: http://sockets.mbed.org/your_own_channel/viewer
For instance: http://sockets.mbed.org/samux/viewer

demo
Et Voilà! We are able to send data on our webpage over a wifi network!

Part 2 - Sending Hello World from the Mbed: Ethernet

Materials required

For this part you need:

2.1 - Code

The main code:

#include "mbed.h"
#include "EthernetInterface.h"
#include "Websocket.h"
 
 
int main() {
    char recv[30];
 
    EthernetInterface eth;
    eth.init(); //Use DHCP
    eth.connect();
    printf("IP Address is %s\n\r", eth.getIPAddress());
 
    Websocket ws("ws://sockets.mbed.org:443/ws/demo/wo");
    ws.connect();
 
    while (1) {
        ws.send("WebSocket Hello World over Ethernet");
        wait(1.0);
    }
}

» Import this programWebsocket_Ethernet_HelloWorld

websocket client ethernet hello world example


Note that the WebSocket API is the same for using a WiFi module or an Ethernet connection

mode, channel

Don't forget to edit:

  • the mode and the channel of your choice in the WebSocket constructor


2.2 - You should be ready!

  • You can now download this program into your mbed
  • Visit the webpage of your own channel: http://sockets.mbed.org/your_own_channel/viewer

Information

You can join the server, create your own channel, send and view messages over your channel just by visiting:

http://sockets.mbed.org


2.3 - Demo

You can check that all is working by visiting the webpage of your own channel: http://sockets.mbed.org/your_own_channel/viewer
For instance: http://sockets.mbed.org/samux/viewer

demo
Et Voilà! We are able to see on our webpage Hello World over an Ethernet network!

Now, if you want, you can write your own webpage to process and display the data coming in on your channel whichever way you wish!

Conclusion

After this tutorial, you are able to send messages to every webpage connected to a websocket server. You can imagine sending data from sensors and print or display values received in the webpage. Sensors are now accessible all over the world. You can take a look to the Internet Of Things project where data are sent and displayed in real time using another HTML5 feature: canvas.




1 related question:


31 comments:

16 Nov 2011

Hello, I must say this is absolutely nice piece of work which solve big problem with connecting to mbed which obtains IP from DHCP. This IP may vary and reachability is limited to reading this IP assigned to mbed from DHCP on terminal or display attached to mbed. But if mbed has no display and is not possible to check IP every time if mbed connected to LAN via cable or wirelessly this is what You will love.

And now comes my question. Because I can see there are 3 connection modes and one of them is named read and write, I would like to ask if there is any plan about adding ability to write data to mbed from internet browser. I think something easy like field to write text with button named "send to mbed" or simple button which will command mbed to send data or stop sending data.

I think websockets opens absolutely new world to every aplication used on mbed where is required any user interface. Because I wanted to add user interface to command mbed I was thinking about any software to write for PC side and use USB connection. But Websockets changes everything.

You can make own server with Tornado and then You have ability to command mbed not only from PC (USB connection limits to have mbed still connected) but from every device with ability to display web pages and it means not only PC but also tablets, smartphones, TVs...

And as I think it is easier to make web page on server then to create program for PC. So I see mbed with endless options at (not only) home automation with not only sensing data but with capability to be commanded and if I add plus like no need to know IP of mbed and beauty user interface...

I must say that this is AWESOME

17 Nov 2011

Hi little,

There is already a webpage which allows to send messages over a channel: http://sockets.mbed.org/[your_channel]/sender. If you connect an mbed on the same channel in rw or ro mode, it will receive all messages which are exchanged over the channel.

You can use a program like this to read messages:

while (1) {
   if(ws.read(recv)) {
      pc.printf("%s\r\n", recv);
   }
   Net::poll();
}
17 Nov 2011

Thank You very much for example how to read data which are sent from web page. Btw as I see You are doing very much for comunity about USB devices and websockets which both I am very interested in so I thank You. This is what makes mbed very usable fo newbies like me.

I never have been in touch with c++ or microcontrollers but with examples and reading series about c++ I was able to proceed step by step further. Started with very minor changes to examples and now I am much far than in June when I started...

21 Dec 2011

I have followed the tutorial, and seem to have it mostly working. When I go to my channel http://sockets.mbed.org/<my_chan> I can see that there is a connection (from my mbed). My mbed is sending a little data at a 0.1s interval like your sample. But when I click the view link (i.e. http://sockets.mbed.org/<my_chan>/viewer), I get the following message:

Websocket viewer: connection not active!

Any ideas on how to debug this? Since the connection is recognized on the main page, it seems to be connected, but reading or writing (I am using "rw" mode on the mbed) does not work. Both pages give that error. Is it possible there is a problem on the server side?

Thanks! I am really excited to get this working.

21 Dec 2011

You may be encountering an issue relating to the recent final publication of the websocket standard - http://www.rfc-editor.org/rfc/rfc6455.txt. This final version included some changes which browsers like Chrome released a week ago or so, but the server has not yet been updated to reflect this. Hence, server and client are incompatible.

We are awaiting a release from the upstream server software developers (http://www.tornadoweb.org) and will try and get it live as soon as it's available.

23 Dec 2011

Hello,

I have a problem regarding on the connection establishment on the web server “http://sockets.mbed.org/sjchia844z” (my channel). I modified the program above, I can connect the wifly module to the Wireless Hotspot but cannot connect to the web server. I used the LED indicator on the mbed to find the problem of the program and found out that the program is stuck on the “while” loop of the connection of the server.

#include "mbed.h"
#include "Wifly.h"
#include "Websocket.h"

int FinalWindTurbineValue = 0;
DigitalOut Light1(LED1);
DigitalOut Light2(LED2);


Serial pc(USBTX, USBRX);

//Here, we create an instance, with pins 9 and 10 connecting to the 
//WiFly's TX and RX pins, and pin 21 to RESET. We are connecting to the 
//network, password, and we are using WPA.
Wifly wifly(p9, p10, p21, "network", "password", true);

//Defining the AnalogIn pins that are connected to the Wind Turbine.
AnalogIn WindTurbine1 (p20);
BusOut    unused(p15,p16,p17,p18,p19); // Make unused analog pin to DigitalOut

//Here, we create a WebSocket instance in 'wo' (write-only) mode
//on the 'sjchia844z' channel
Websocket ws("ws://sockets.mbed.org/ws/sjchia844z/wo", &wifly);

int main() {
    char json_str[100];

    pc.printf("Activating the Wind Turbine Connection.\r\n");
    pc.printf("Starting the Wind Turbine test...\r\n");

    while (1) {
        while (1) {
            Light1 = 1;
            while (!wifly.join())  //we connect to the network
                wifly.reset();

            if (!ws.connected())
             { Light2 = 1; //we connect to the server
                wifly.reset();
             }
            else
             {
             break;}  
        }

        while (1) {
            wait(0.1);
    
             FinalWindTurbineValue = WindTurbine1 * 3.3;
             pc.printf("The Values are %d A.\r\n", FinalWindTurbineValue);
    
                //Here, we format the string we will be sending to the server
                //the format we are sending in is JSON
                sprintf(json_str, "The Values are %d .\r\n", FinalWindTurbineValue);
                ws.send(json_str);  //And we send the string
        }
    }
}

By the way, the state of channel “sjchia844z” has zero connection on the web server. Is there any problems on the program or do I need to configure the mbed web server to my needs?

Thanks

23 Dec 2011

Hello Chia,

You are using the connected() method instead of the connect() method to join the websocket server. The connected() method returns the state of the websocket connection but doesn't connect the server.

I tried this program and it works for me:

#include "mbed.h"
#include "Wifly.h"
#include "Websocket.h"

int FinalWindTurbineValue = 0;
DigitalOut Light1(LED1);
DigitalOut Light2(LED2);


Serial pc(USBTX, USBRX);

//Here, we create an instance, with pins 9 and 10 connecting to the
//WiFly's TX and RX pins, and pin 21 to RESET. We are connecting to the
//network, password, and we are using WPA.
Wifly wifly(p9, p10, p21, "network", "password", true);

//Defining the AnalogIn pins that are connected to the Wind Turbine.
AnalogIn WindTurbine1 (p20);
BusOut    unused(p15,p16,p17,p18,p19); // Make unused analog pin to DigitalOut

//Here, we create a WebSocket instance in 'wo' (write-only) mode
//on the 'sjchia844z' channel
Websocket ws("ws://sockets.mbed.org/ws/sjchia844z/wo", &wifly);

int main() {
    char json_str[100];

    pc.printf("Activating the Wind Turbine Connection.\r\n");
    pc.printf("Starting the Wind Turbine test...\r\n");

    while (1) {
        Light1 = 1;
        while (!wifly.join())  //we connect to the network
            wifly.reset();

        while (!ws.connect()) {
            Light2 = 1; //we connect to the server
        }

        while (1) {
            wait(0.1);

            FinalWindTurbineValue = WindTurbine1 * 3.3;
            pc.printf("The Values are %d A.\r\n", FinalWindTurbineValue);

            //Here, we format the string we will be sending to the server
            //the format we are sending in is JSON
            sprintf(json_str, "The Values are %d .\r\n", FinalWindTurbineValue);
            ws.send(json_str);  //And we send the string
        }
    }
}

Hope that helps

Sam

05 Jan 2012

Hello again,

Is it possible to replace the websocket address to a localhost inside the mbed program for testing purposes as I would like to use AutoBahn websocket to connect the mbed to the localhost webserver I created.

By the way, Thanks for the solution, tried out and it worked! :) Also, I found out that websocket connection require a strong Wifi connection so that's why it could not work for weeks...

Many Thanks.

04 Apr 2012

Hello, i have a question. How to increase the buffer for incoming data? I send to mbed a large string and the mbed crashes, you use "char recv[40];" i increment recv to 512 and dont works well :( .

10 Apr 2012

user Diego io0set wrote:

Hello, i have a question. How to increase the buffer for incoming data? I send to mbed a large string and the mbed crashes, you use "char recv[40];" i increment recv to 512 and dont works well :( .

I solved, and I added REALLY RPC to websockets :)

19 Apr 2012

Hello. This is amazing application of the mbed. I am not completely clear what a "router" in the ethernet application means. Does'nt mbed have an onboard ethernet port? Why can't that be used to connect to the network directly? Awaiting your response. Thank you in advance.

23 May 2012

I've been tying to connect my mbed to the website via ethernet. The ethernet connection works for test programs such as the one at http://mbed.org/handbook/Ethernet. WHen running the test program here, I get past "Connected, IP address is: X" before getting "cannot connect to websocket, retrying." I imported the program directly from here, so there is no error in transcription. Any help would be much appreciated.

23 May 2012

Websocket only works in CHROME for me anyway!!

Ceri

23 May 2012

I am using Chrome, so the issue must be elsewhere.

24 May 2012

Hi Charles,

Don't have the hardware to test but some advice: - Are you using a firewall ? Are you just using a simple router ? - Can you enable DEBUG in Websocket.cpp and say me what is going on ?

Sam

24 May 2012

How do I download the EthernetNetIf program as a library? It always tries to save it as a new program in my compiler.

12 Jun 2012

user Jeff Frankart wrote:

How do I download the EthernetNetIf program as a library? It always tries to save it as a new program in my compiler.

While in the compiler, select import. Search for "ethernetnetif" in the programs section. Select the most recent. Select import as library and select your program you want to import in to.

25 Jun 2012

user UniLeedsElec21 UniLeedsElec21 wrote:

Hello. This is amazing application of the mbed. I am not completely clear what a "router" in the ethernet application means. Does'nt mbed have an onboard ethernet port? Why can't that be used to connect to the network directly? Awaiting your response. Thank you in advance.

I am trying to connect the mbed via an ethernet cable to the RJ45 port on my laptop. The HTTPServer program compiles and runs perfectly on the mbed (verified with teraterm). IP address is set properly - which is assigned in the program using EthernetNetIf. But I cannot open the webpage on the mbed (I am typing http://192.168.0.101/MBED.htm in the browser). Do I need a router in between? I am not connecting to the internet. I want to communicate between the laptop and the mbed using ethernet.

Edit: Issue fixed. Need to configure the TCP/IP settings at the PC as well if using static IP and without router i.e. mBed <-> PC

31 Jul 2012

I am working with the mbed and web sockets and wanted to know if there was a way to monitor if the socket was open? I have tried using the the connected() method but when you do this you can miss messages coming from the server. Is there any to to make sure the socket is alive without losing data?

20 Nov 2012

Assistant needed here, this following code does not work, It able to connect to the wifi but unable to connect through web sockets. Help Appreciated

Funny thing is that even after disconnecting my mbed, yet the http://sockets.mbed.org/ws_ERIC_demo page shows 1 active connection but http://sockets.mbed.org/ws_ERIC_demo/viewer shows no active connection.

WiflyInterface wifly(p9, p10, p25, p26, "new_et", "12345*", WPA);

int main() {
    wifly.init(); //Use DHCP
    while (!wifly.connect());
    printf("IP Address is %s\n\r", wifly.getIPAddress());

    Websocket ws("ws://sockets.mbed.org:433/ws/ws_ERIC_demo/wo");
    while (!ws.connect());
    printf("websocket connected");

    while (1) {
            ws.send("ERIC'S websocket");
            wait(1.0);
    }
}
20 Nov 2012

Hi Eric,

  • Which mbed are you using (lpc1768 or lpc11u24) ?
  • Be sure to correctly connect the reset/tcp_status pins. More info are available here.
  • Be sure to use the latest version of the websocket library (click on the websocket folder - you can then update it directly on the online IDE on the right hand side)

Cheers, Sam

20 Nov 2012

Hi Samuel, Thanks for your reply, Im using mbed NXP LPC1768, I check and confirmed that the connection correct, I am able to retrieve my IP but I tried the code and realize it got stuck at the while loop as shown below:

 printf("connecting websockets");
    while(!ws.connect())
    printf("websocket connected");

never it prints websocket connected

would appreciate your help. Thanks in advance

20 Nov 2012

Hi Eric,

Just to be sure, can you use returns in you printf statements:

printf("connecting websockets\r\n");
while(!ws.connect())
printf("websocket connected\r\n");

By the way which wifi module are you using ?

Cheers, Sam

20 Nov 2012

I tried the following code for printing the return but it doesn't work

printf("connecting websockets");
printf("%b",ws.connect());
printf("websocket connected");

I am using RN-XV wifi module. Is there any problem with it? Thanks

20 Nov 2012

I further experiment with the wifly module, I tried the HTTPClient_Wifly_HelloWorld program and realize that it succesfully fetch but fail to post. It seems that all outgoing data is not working..its kinda frustrating

20 Nov 2012

Hi Eric,

No, what I meant was to use "\r\n" at the end of your printf to be sure that the message is flushed (in order to see it on the pc side).

Can you enable the debug mode in Websocket.cpp:

//Debug is disabled by default
#if 0

to

//Debug is disabled by default
#if 1

Can you let me know what is printed when the debug is enabled ?

Cheers, Sam

20 Nov 2012

It shows "Unable to connect to (sockets.mbed.org) on port (80) " this seems more like a server error to me or is it?

Thanks for you tips on enabling the debug mode

03 Dec 2012

Hi Samuel,

I have problems using this wifly program. I tried to enable the debug and also add the printf("connecting websockets\r\n") printf("websocket connected\r\n") above to test. It printed

/media/uploads/zoubarry/---.jpg

Could you plz tell me what goes wrong?

Thank you so much!

ZZ

03 Dec 2012

Hi ZZ,

Everything is fine. the WebSocket DBG messages means that you have received the handshake of the server. Then the WebSocket INFO message means that you are connected to the websocket.

Are you able to see messages sent by your mbed here: http://sockets.mbed.org/zoubarry/viewer ?

Be sure to use the latest versions of the wifly and websocket libraries. You can update them directly from the online IDE by right clicking on the library and then update.

Cheers, Sam

30 Dec 2012

Hi,

I'm using an mbed NXP LPC1768 to communicate over Ethernet with a Node.js WebSocket server and things are going quite well, almost perfect :).

The client on the mbed is implemented as follows:

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

int main() {
    char recv[30];
    int count = 0;
 
    EthernetInterface eth;
    eth.init(); //Use DHCP
    eth.connect();
    printf("IP Address is %s\r\n", eth.getIPAddress());
 
    Websocket ws("ws://192.168.1.33:8080/");
    ws.connect();

    while (1) {
        int res = ws.send("WebSocket Hello World!");

        if (ws.read(recv)) {
            count += 1;
            if (count % 1000 == 0) {
                printf("%d messages echoed (%s)\r\n", count, recv);
            }
        }
    }
}

The clients task is to send messages to the server as quickly as possible. Note that there is no wait in the clients infinite loop. Everything works fine until a second client starts to communicate with the server. The second client is a Node.js client but this is probably not relevant. It's task is also to send messages to the server as quickly as possible.

Shortly after the Node.js client is started, i.e., a few seconds later, the mbed client stops functioning with the following error message:

tcp_write: pbufs on queue => at least one queue non-empty:325 in file /workspaces/Websocket_Ethernet_HelloWorld/src/EthernetInterface/lwip/core/tcp_out.c

Here's the assertion code from tcp_out.c:

  if (pcb->snd_queuelen != 0) {
    LWIP_ASSERT("tcp_write: pbufs on queue => at least one queue non-empty",
      pcb->unacked != NULL || pcb->unsent != NULL);
  } else {
    LWIP_ASSERT("tcp_write: no pbufs on queue => both queues empty",
      pcb->unacked == NULL && pcb->unsent == NULL);
  }

The assertion fails because pcb->snd_queuelen is not 0 (it's actually 1), but both pcb->unacked and pcb->unsent are NULL.

I'm not entirely sure, but I think this is a timing issue caused by multiple threads modifying data structures in the background but the modifications are not being synchronized correctly.

The following lines of code are from the read method in class Websocket:

        socket.set_blocking(false, 1);
        if (socket.receive(&opcode, 1) != 1) {
            socket.set_blocking(false, 2000);
            return false;
        }

        socket.set_blocking(false, 2000);

The initial call to set_blocking with a timeout of 1ms appears to result in the issue. If the timeout is changed from 1ms to 100ms the issue no longer occurs. If all three calls to set_blocking are removed everything functions correctly too.

Is modifying the timeout from 1ms to 100ms a solution to the problem or a workaround?

22 Feb 2013

Hi Samuel

With the read method

Websocket.cpp

bool read(char * message);

what size message buffer should I pass to avoid buffer overrun?

Or put it another way, should the read method not have a parameter to specify the size of the buffer available?

Thanks Daniel