Eclipse Californium CoAP 通配符作为 url 路径
Eclipse Californium CoAP wildcard as url path
我正在使用 Eclipse Californium 开发 CoAP 应用程序,它将仅显式声明根资源路径,其余资源应通过通配符 /root/*
提供和解析,就像在 REST API 上一样或 servlet。
有什么方法可以实现吗?
好的,我做到了。
因此,在对他们的源代码进行了几个小时的挖掘之后,这就是最终的结果。
请注意,它可以工作,但这只是为了展示它是如何完成的,它仍在进行中(我在 3 小时内完成),因为我删除了一些代码,如观察者等。
一旦有时间,我将深入研究 Californium Api 并使其通用和优化 我将创建一个 Github 项目并 link 它这里。
1 : 创建模型 class
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 配置文件
{
"verb": "get",
"endpoint": "/houses/*/rooms/*/sensors/temperature",
"class": "com.wild.coap.resources.TemperatureResource"
}
5 : 创建资源加载器(class 将加载资源的规范定义并独立实例化它们,而不是在服务器上创建树)
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 : 创建自定义 MessageDelieverer
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.");
}
}
}
希望对某人有所帮助。
这是我对这个问题的解决方案。
CoapResource wildcard = new CoapResource("*") {
@Override
public void handleGET(CoapExchange exchange) {
...
}
};
CoapResource root = new CoapResource("root") {
@Override
public Resource getChild(String name) {
return wildcard;
}
};
我正在使用 Eclipse Californium 开发 CoAP 应用程序,它将仅显式声明根资源路径,其余资源应通过通配符 /root/*
提供和解析,就像在 REST API 上一样或 servlet。
有什么方法可以实现吗?
好的,我做到了。
因此,在对他们的源代码进行了几个小时的挖掘之后,这就是最终的结果。
请注意,它可以工作,但这只是为了展示它是如何完成的,它仍在进行中(我在 3 小时内完成),因为我删除了一些代码,如观察者等。
一旦有时间,我将深入研究 Californium Api 并使其通用和优化 我将创建一个 Github 项目并 link 它这里。
1 : 创建模型 class
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 配置文件
{
"verb": "get",
"endpoint": "/houses/*/rooms/*/sensors/temperature",
"class": "com.wild.coap.resources.TemperatureResource"
}
5 : 创建资源加载器(class 将加载资源的规范定义并独立实例化它们,而不是在服务器上创建树)
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 : 创建自定义 MessageDelieverer
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.");
}
}
}
希望对某人有所帮助。
这是我对这个问题的解决方案。
CoapResource wildcard = new CoapResource("*") {
@Override
public void handleGET(CoapExchange exchange) {
...
}
};
CoapResource root = new CoapResource("root") {
@Override
public Resource getChild(String name) {
return wildcard;
}
};