4

我正在使用 Eclipse Californium 开发 CoAP 应用程序,该应用程序将仅显式声明根资源路径,其余资源应通过通配符提供和解析,/root/*就像在 REST API 或 servlet 上一样。

有没有办法做到这一点?

4

2 回答 2

2

好的,我设法做到了。

因此,在对他们的源代码进行了几个小时的挖掘之后,这就是最终要做的事情。

请注意,它可以工作,但这只是为了展示它是如何完成的,它仍然是一项正在进行的工作(我在 3 小时内完成了此工作),因为我删除了一些代码,如观察者等。

只要我有时间,我会更多地研究 Californium Api 并使其通用和优化,我将创建一个 Github 项目并将其链接到此处。

1:创建模型类

public class ProxyRes {

    public  CoapResource coapRes;
    public  String  path;

    public ProxyRes () {
    }

    public CoapResource getCoapRes () {
        return coapRes;
    }

    public void setCoapRes (CoapResource coapRes) {
        this.coapRes = coapRes;
    }

    public String getPath () {
        return path;
    }

    public void setPath (String path) {
        this.path = path;
    }
}

2:创建一个应该注入通配符列表的抽象 CoapResource

public abstract class AbstractResource extends CoapResource {

    private LinkedList<String> wildcards;

    protected AbstractResource (String name) {
        super (name);
    }

    protected AbstractResource (String name, boolean visible) {
        super (name, visible);
    }

    public LinkedList<String> getWildcards () {
        return wildcards;
    }

    public void setWildcards (LinkedList<String> wildcards) {
        this.wildcards = wildcards;
    }
}

3:创建一个扩展 AbstractResource 的温度资源

public class TemperatureResource extends AbstractResource {

    public TemperatureResource () {
        super (ResourceSpecs.House.Sensors.Temperature);

        getAttributes ().setTitle ("Temperature resource !");
    }

    @Override
    public void handleGET (CoapExchange exchange) {
        String response = "The temperature";
        if (getWildcard () != null) {
            response += " of the " + getWildcard ().get (0) + " on the " + getWildcard ().get (1);
        }
        response += " is : 25 degree C";

        exchange.respond (response);
    }
}

4:在我的eclipse项目的根目录上创建一个资源目录,其中包含我的资源的json conf文件

{
    "verb": "get",
    "endpoint": "/houses/*/rooms/*/sensors/temperature",

    "class": "com.wild.coap.resources.TemperatureResource"
}

5:创建资源加载器(将加载资源的规范定义并独立实例化它们而不是在服务器上创建树的类)

public class ResourcesLoader {

    private final static String Path = new File (".").getAbsolutePath () + File.separator + "resources";

    private List<ProxyRes>  resourcesList;

    public ResourcesLoader () throws Exception {
        resourcesList   = new ArrayList<ProxyRes> ();

        File resources  = new File (Path);
        for (String resName : resources.list ()) {
            File resFile    = new File (resources, resName);
            InputStream is  = new FileInputStream (resFile);
            JsonObject o    = new JsonObject (is);

            resourcesArr.add (o);
            resourcesList.add (buildObject (o));
        }
    }

    private ProxyRes buildObject (JsonObject o) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        ProxyRes r = new ProxyRes ();
        r.setPath (o.getString ("endpoint"));

        Class<?> clazz  = Class.forName (o.getString ("class"));
        CoapResource coapRes = (CoapResource)clazz.newInstance ();
        r.setCoapRes (coapRes);

        return r;
    }

    public List<ProxyRes> getResourcesList () {
        return resourcesList;
    }
}

6:创建自定义 MessageDeliverer

public class DynamicMessageDeliverer implements MessageDeliverer {

    private final List<ProxyRes>    resources;

    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 ();
    }

    public void deliverResponse (Exchange exchange, Response response) {
        if (response == null) throw new NullPointerException();
        if (exchange == null) throw new NullPointerException();
        if (exchange.getRequest() == null) throw new NullPointerException();
        exchange.getRequest().setResponse(response);
        Request request         = exchange.getRequest ();
        List<String> path       = request.getOptions ().getUriPath ();
        System.out.println ("Path retrieved : " + Arrays.toString (path.toArray ()));
    }
}

7:创建服务器

public class WildCoapServer extends CoapServer {

    private static final int COAP_PORT = NetworkConfig.getStandard  ().getInt  (NetworkConfig.Keys.COAP_PORT);

    public WildCoapServer () throws Exception {

        // add endpoints on all IP addresses
        addEndpoints ();

        ResourcesLoader resLoader   = new ResourcesLoader ();
        List<ProxyRes> resources    = resLoader.getResourcesList ();

        setMessageDeliverer (new DynamicMessageDeliverer (resources));
    }

    @Override
    protected Resource createRoot () {
        return new WildRootResource ();
    }

    // Add individual endpoints listening on default CoAP port on all IPv4 addresses of all network interfaces.
    private void addEndpoints () {
        for (InetAddress addr : EndpointManager.getEndpointManager ().getNetworkInterfaces ()) {
            // only binds to IPv4 addresses and localhost
            if (addr instanceof Inet4Address || addr.isLoopbackAddress ()) {
                InetSocketAddress bindToAddress = new InetSocketAddress (addr, COAP_PORT);
                addEndpoint (new CoapEndpoint (bindToAddress));
            }
        }
    }
}

8:启动服务器

public class Main {

    public static void main (String[] args) {

        try {
            WildCoapServer server = new WildCoapServer ();
            server.start ();
        } catch  (Exception e) {
            throw new RuntimeException (e.getMessage (), e);
        }
    }
}

9:使用客户端的温度资源

public class Client {

    public static void main  (String[] args) {

        URI uri = null;
        try {
            uri = new URI ("coap://192.168.200.1:5683/houses/house1/rooms/kitchen/sensors/temperature");
        } catch  (URISyntaxException e) {
            throw new RuntimeException (e.getMessage (), e);
        }

        CoapClient client       = new CoapClient (uri);

        CoapResponse response   = client.get ();

        if (response != null) {

            System.out.println (response.getCode ());
            System.out.println (response.getOptions ());
            System.out.println (response.getResponseText ());

            System.out.println ("\nADVANCED\n");
            // access advanced API with access to more details through .advanced ()
            System.out.println (Utils.prettyPrint (response));

        } else {
            System.out.println ("No response received.");
        }       
    }
}

希望对某人有所帮助。

于 2016-05-19T21:35:30.423 回答
2

这是我对这个问题的解决方案。

CoapResource wildcard = new CoapResource("*") {

    @Override
    public void handleGET(CoapExchange exchange) {
        ...
    }
};

CoapResource root = new CoapResource("root") {
    @Override
    public Resource getChild(String name) {
        return wildcard;
    }
};
于 2018-10-11T18:26:01.520 回答