RestServer
Answer
5/9/17 12:32 PM

Hello,

would it be possible to get any demo or something like this, how to use the RestServer.

We can read out any sensor data and would like to call "http://.../sensorName" in the browser to get the value of the given sensor.

Unfortunately we could not find any sample, how to code the restService.travers function. (connection to WLan was successful).

RestSettings_T restService;

restService.httpPort = 80;
restService.httpServiceEnabled = true;
restService.traverse = &onRestRequest;

retStatusConnect = (Retcode_T) RestServer_startInstance(&restService);

if (retStatusConnect == RETCODE_OK) {
      printf("RestServer instance started successfully.\n\r");
}

How do I implement "onRestRequest"?

Best regards,

 

 

 

0 (0 Votes)
RE: RestServer
Answer
5/10/17 3:53 PM as a reply to Andreas Werbelow.

Hello Andreas,

unfortunately, there is no guide on how to implement the XDK as a REST Server yet, and we are not able to provide a sample code either.

Nevertheless, any needed information should be available in descriptions included in the interfaces.

In particular on how to implement the traverse function, I would recommend to read the documentation of the Serval_RestServer header file:

Your-Project > SDK > xdk110 > Libraries > ServalStack > api > Serval_Restserver.h

You can find the definition of the Traversal Function on line 149, with the documentation above that line.

The general outline of how to implement the traversal function is as follows:
The traversal function receives as input a reference to RestSettings_T, a VisitorFunction, and a void-pointer. Those three are already predefined in the ServalStack's implementation, so you do not have to concern yourself with their initialization or implementation.
The traversal function iterates over all RESTful Resources and applies the visitor function from the internal implementation to each of the resources. Per default, the visitor function compares the URI of the resource the traversal function is visiting to the URI of the device you are calling. It returns true, if the URIs match.
If the visitor function returns true, break the loop and return the resource that has been matched.
The visitor function receives a resource-pointer as input and the void pointer of the traverse function as an in-out-pointer for data.
Finally, the traversal function returns a pointer to the last resource the traversal function visited, i.e. the resource that matched.
The ServalStack implementation will later call the handler you specified for that resource. Such a handler could, for example, show the value of a sensor.

In other words, I recommend a general structure:
The signature should be onRestRequest(rest_service_ptr, visitorFunc, data_ptr) (with types as seen in the documentation mentioned above)
Initialize a Pointer for Rest Resources resource_ptr,
Iterate over all your resources and call visitorFunc(resource_ptr, data_ptr)
If visitorFunc returns 1 (= true), break.
Let traverseFunc return resource_ptr.

I hope this is helpful. If you have further questions, feel free to ask, and I will investigate more deeply into this matter.

Kind regards,
Franjo

0 (0 Votes)
RE: RestServer
Answer
5/11/17 6:46 AM as a reply to Franjo Stjepandic.

Hello,

at first I want to ask if the following settings for the restService are implemented correctly.

RestSettings_T restSettings;

restSettings.httpPort = 80;

restSettings.httpServiceEnabled = true;

restSettings.traverse = onRestRequest;

retStatusConnect = (Retcode_T) RestServer_startInstance(&restSettings);

Now there is the question about the onRestRequest function: You wrote that it receives a reference to RestSettings_T, VisitorFunction and a void pointer. As I saw in the header file the signature should be something like this:

RestResource_T onRestRequest(RestSettings_T * settings, RestServer_VisitorFunc_T fu, void * v)

The visitorFunction possibly has the following signature:

bool visitFunc(RestResource_T * res, void *) 

Now the traversal function .... , where do I get the resources from to iterate over and to call the visitorFunction ? 

And where and why does the traversalFunction get a pointer to the visitFunction?

Your recommended structure to initialize a RestResource ptr, and to iterate over them... where should the pointer point to, which resources do you mean to iterate over?

Best regards,
Andreas

0 (0 Votes)
RE: RestServer
Answer
5/11/17 4:44 PM as a reply to Andreas Werbelow.

Hello Andreas,

Your implementation of restSettings is nearly correct, just change the onRestRequest to &onRestRequest as follows:

restSettings.traverse = &onRestRequest;


Because the .traverse field of the RestSettings_T expects a reference to a function.

It would also be useful to use the function Ip_convertIntToPort(80) on the port number as follows:

restSettings.httpPort = Ip_convertIntToPort(80);


because the .httpPort field expects the type Ip_Port_T, which the mentioned function returns. You will require to include "Serval_Ip.h" for that function, though.

As for the traversal functions, this forum seems to have cut off part of the signature you provided here for the onRestRequest.
The signature should be as follows:


RestResource_T onRestRequest(RestSettings_T * settings, RestServer_VisitorFunc_T visitorFunc, void * uri)


(the variable names might vary, the types are important).

This traversal function gets called everytime the Rest Server receives a request. You do not need call the traversal function yourself, this will all be handled when you call RestServer_startInstance(&restSettings); by the Stack that gets created during that function.

But the implementation of the traversal function has to be made by yourself, because the resources, which are traversed, are not known beforehand.

You create those resources, by yourself. You can find the structure of a Resource in the header-file Serval_RestServer.h, which I mentioned in my last post, at line 90. Additionally, its type-definition is at line 129.

The .url field is a path, such as /accelerometer. Types and Interfaces should be set, but they can be arbitrary at the beginning. The most important thing is the handler. This is also a function you have to create by yourself, but will be called automatically. The resource just needs a pointer.

So, if you have the resources you want defined, you could store the pointers to those resources in an array. In the traverse function, you initialize a RestResource_T *resource_pointer, and then you iterate over the array, and apply the visitorFunc to each of them until the visitorFunc returns true. And as mentioned, the visitorFunc receives as input the pointer to the current resource and the void-pointer from the traversal function’s signature.

The visitor function is already predetermined. It’s one of those things that the RestServer_startInstance function does for you.

The only thing you need are the resources, the handlers for resources and the traversal function onRestRequest, and of course the rest-settings.

Please tell me if this is helpful and do not hesitate to ask if you have further questions.


Kind regards,
Franjo

0 (0 Votes)