Monday, July 16, 2012

Communicating with RaspBerry via GSoap Web Services

According to wikipedia "A Web service is a method of communication between two electronic devices over the Web (Internet)." I would not say over the 'Web', indeed you can communicate within a local area network without the need on going 'Web'.

On this tutorial we are going to explain step by step how to deploy a Web Service on our Rasberry. We are also going to see how to develop a little application in our laptop that will communicate with this Web Service.

The protocol used on a web service is called 'SOAP' and is based on 'XML'. The following diagram explains in a simplified way how a Web Service communication is carried out.

Fig.1 Simplified SOAP exchange diagram

The most common usage of Web Services is via HTTP, and that is the reason behind its popularity. In fact all the existing web infrastructure (from routers to web servers) fits perfectly on this model, without the need of adapt absolutely anything.

How the xml is formed, is specified on the SOAP protocol. Normally the commercial Web Services API, like the ones used on .Net, Java, or C++, hide the complexity of the protocol, so we can focus on our object s model and the 'dirty' work of converting those object on 'XML' (and viceversa) is completely transparent for us.

1. Downloading GSoap.

GSoap is a open source Web Service API, written in C and C++. You can download the last version from here.

There are 2 important tools shipped on the download, the one that we are going to use is called 'soapcpp2' and you can find it on the following path:

./gsoap-2.8/gsoap/bin/linux386/soapcpp2

2. Defining our service interface.

On this example we are going to create a service that returns the hour from our Raspberry.

The service interface is defined in a similar way than a library interface. We are going to create a header defining the method that will be called:

Fig. 2 Sevice Definition header

2. Generating the server classes.

Now that our service is defined, we have to generate the classes that will handle the request. Fortunately this can be done automatically by using 'soapcpp2'. Go to your project path (in my case ~/workspace/workspace64/GSoapTuto/MyRaspberryTimeServer/src) and execute soapcpp2 with the following options:

You will have to change the line 'm = soap_bind(&soap, "192.168.1.54", 2012, 100);' and set the IP of your Raspberry (192.168.1.54 in my case) and the port you want it to listen from (2012 in my case).

If you want to make the resultant program work on Raspberry, you will have to cross-compile it. You can do it by changing the properties of your project and performing the following changes:

Add the 'stdsoap2.cpp' and 'stdsoap2.h' as we did for the server. And finally add 'currentTime.cpp' including the main method with the following content:

Fig 7. Resultant client structure

Finally, on change the line 'soap_endpoint = "http://www.yourdomain.com/currentTime.cgi";' on the file 'soapcurrentTimeProxy.cpp' in order to target your Raspberry:

soap_endpoint = "http://192.168.1.54:2012"; in my case

And that's all!! If you fulfilled all the steps, after compiling and executing your client, you should get a beautiful result like 'The time is 1342473837' indicating the date in seconds from your Raspberry.

If you have a look to the Raspberry console, it should display some info about the just served request:

Then make could not find flex, so:-sudo apt-get install flex ./configure makeand the next error was not finding the ssl and crypto libraries and so I had to:- sudo apt-get install libssl-dev followed by ./configure make sudo make installand now I was told:-You now have successfully built and installed gsoap.Yeah. Now to build my app......:-)

The next issue rears its head.It is required that the system has the IP address of the server as well as the name/title of the webservice as parameters rather than genned into and therefore ostensibly hard coded.Do you by any chance have any suggestions on how I would go about achieving this without having a different binary for each site where my application runs?