CoAP Calibration Path Parameters

I am working on a CoAP application using Eclipse Californium, and I need to pass parameters using a URL, as in quiet web services. Is it possible to do this in the implementation of the California stake, and if so, let me know how to do it. eg:

coap://localhost:5683/foo/{fooID} 
+5
source share
3 answers

The short answer is yes, you can do it.

As stated in JavaDocs

  • When the request arrives at the server, {@link ServerMessageDeliverer} searches the resource tree for the destination resource. It moves down the resource tree, looking for one destination URI for another, and by calling the {@link #getChild (String)} method for each element. It is allowed to override this method and return an arbitrary resource. This allows, for example, serving URIs with wildcards or delegating requests to any sub-URIs to the same resource.

So basically you have to override the deliverRequest and possibly findResource methods in org.eclipse.californium.core.server.ServerMessageDeliverer to return the corresponding resource that will process the request. You will also need to parse the Exchange Request UriPath as part of the handleHET / PUT / POST / etc resource to retrieve the path variable (this can be done using CoapExchange.advanced (). GetRequest (). GetOptions (). GetUriPath () )

Based on the Californium source code, it's pretty easy to override the default behavior for a query provider.

Good luck with that!

+5
source

You can override deliverRequest as pointed out by Alex. However, my approach is that I do not pre-register the resource tree, I register the resource by resources without preserving the hierarchy.

 public DynamicMessageDeliverer (List<ProxyRes> resources) { this.resources = resources; } public void deliverRequest (final Exchange exchange) { Request request = exchange.getRequest (); List<String> path = request.getOptions ().getUriPath (); final Resource resource = registerResources (path); if (resource != null) { executeResource (exchange, resource); } else { exchange.sendResponse (new Response (ResponseCode.NOT_FOUND)); throw new RuntimeException ("Did not find resource " + path.toString() + " requested by " + request.getSource()+":"+request.getSourcePort()); } } private void executeResource (final Exchange exchange, final Resource resource) { // Get the executor and let it process the request Executor executor = resource.getExecutor (); if (executor != null) { exchange.setCustomExecutor (); executor.execute (new Runnable () { public void run () { resource.handleRequest (exchange); } }); } else { resource.handleRequest (exchange); } } private Resource registerResources (List<String> list) { LinkedList<String> path = new LinkedList<String> (list); String flatRequestedEndpoint = Arrays.toString (path.toArray ()); LinkedList<String> wildcards = new LinkedList <String> (); ProxyRes retainedResource = null; for (ProxyRes proxyRes : resources) { String[] res = proxyRes.getPath ().replaceFirst ("/", "").split ("/"); int length = res.length; if (length != path.size ()) { continue; } String flatResEndpoint = Arrays.toString (res); if (flatResEndpoint.equals (flatRequestedEndpoint)) { retainedResource = proxyRes; break; } boolean match = true; for (int i = 0; i < length; i ++) { String str = res[i]; if (str.equals ("*")) { wildcards.add (path.get (i)); continue; } if (!str.equals (path.get (i))) { match = false; break; } } if (!match) { wildcards.clear (); continue; } retainedResource = proxyRes; break; } if (retainedResource == null) { return null; } ((AbstractResource)retainedResource.getCoapRes ()).setWildcard (wildcards); return retainedResource.getCoapRes (); } 

The complete response code with steps is here: Eclipse Californium CoAP wildcard as a URL

+1
source

From what I have seen so far, creating a custom ServerMessageDeliverer seems to be a more complicated solution. Actually, the correct solution seems to be to override CoapResource#getChild(String) so that it returns the resource you want to associate with this name. ServerMessageDeliverer more like a way to implement some kind of controller that delivers or distributes requests in a more complex environment.

For the question where the last part of the URI is a parameter, the solution might look like this:

 public class UriParameterResource extends CoapResource { public UriParameterResource() { super("foo"); } @Override public void handleGET(CoapExchange exchange) { List<String> uriPath = exchange.getRequestOptions().getUriPath(); // check if there is a sub-resource given, and if so use it for processing if (uriPath.size() > 1) { exchange.respond("Process " + uriPath.get(1)); } else { exchange.respond(ResponseCode.NOT_IMPLEMENTED); } } @Override public Resource getChild(String name) { // even sub-resources will land in the GET of this resource return this; } } 

Regarding the answer from @Copernic, I personally think that this is not consistent with the idea of ​​REST. Each part of the URI path must return its own resource associated with its parent, which makes it a tree structure for each definition, and not a flat list that simply checks the parts of the path as some parameter.

IMHO even an example of sensors can be resolved using CoapResource implementations, where a child variable resource can be dynamically resolved. Below is a snippet below, of course, this should depend on the real situation when the house and its rooms must be somehow registered.

 public class HousesResource extends CoapResource { public HousesResource() { super("houses"); } @Override public void handleGET(CoapExchange exchange) { // could return a list of available houses exchange.respond(ResponseCode.NOT_IMPLEMENTED); } @Override public Resource getChild(String name) { Resource child = super.getChild(name); if (child == null) { child = new HouseResource(name); add(child); } return child; } class HouseResource extends CoapResource { public HouseResource(String name) { super(name); add(new RoomsResource()); } @Override public void handleGET(CoapExchange exchange) { exchange.respond(ResponseCode.NOT_IMPLEMENTED); } } class RoomsResource extends CoapResource { public RoomsResource() { super("rooms"); } @Override public void handleGET(CoapExchange exchange) { // could return a list of available rooms exchange.respond(ResponseCode.NOT_IMPLEMENTED); } @Override public Resource getChild(String name) { Resource child = super.getChild(name); if (child == null) { child = new RoomResource(name); add(child); } return child; } } class RoomResource extends CoapResource { public RoomResource(String roomName) { super(roomName); add(new SensorsResource()); } @Override public void handleGET(CoapExchange exchange) { // could return a summary board about the room exchange.respond(ResponseCode.NOT_IMPLEMENTED); } } class SensorsResource extends CoapResource { public SensorsResource() { super("sensors"); add(new TemperatureResource()); } @Override public void handleGET(CoapExchange exchange) { // this could return a list of registered sensors exchange.respond(ResponseCode.NOT_IMPLEMENTED); } } class TemperatureResource extends CoapResource { public TemperatureResource() { super("temperature"); } @Override public void handleGET(CoapExchange exchange) { // as the structure is fixed we know that two levels up // there is the room, and four levels up there is the house String room = getParent().getParent().getName(); String house = getParent().getParent().getParent().getParent().getName(); exchange.respond("The temperature of the " + house + " in the " + room + " is : 25 degree"); } } } 

In this example, resources are dynamically created if they did not exist before. It can also be exchanged using some search or registration mechanism (for example, a house is registered through PUT or PUSH).

Do not misunderstand me. The @Copernic solution seems to work and is probably a suitable solution for some scenarios (for example, each house has its own server and requests should be redirected), but for a fairly simple scenario it seems to me that this is not the way to go.

0
source

All Articles