Coap在Andorid中的简单应用

Andlink设备使用了Coap来进行配网和一定的数据交互,因此记录一下。

Coap协议

Coap可以简单理解为是为了在物联网场景下实现web功能而产生的一种轻量级网络协议;
主要特点有使用UDP方式传输以及基于REST等。

coap协议的服务地址和http的url类似:

coap://192.168.52.101:5683/qlink/request

也同样接收POST/GET/PUT/DELETE等请求;
区别在于,coap还将消息类型分为4类:

消息类型 含义
CON 需要回复
NON 无须回复
ACK 回应,对应CON的回复
RST 复位,对应CON错误内容情况下的回复

一般情况下只需要关注前两种类型即可;
比如“POST-CON”和“POST-NON”,前者代表“需要回复的POST请求”,后者代表“不需要回复的POST请求”。

californium

californium是Eclipse旗下的一个成熟的coap库,可在californium找到demo-apps分支并学习。
在gradle中导入:

    implementation 'org.eclipse.californium:californium-core:3.5.0'
    implementation 'org.eclipse.californium:element-connector:3.5.0'
    implementation 'org.eclipse.californium:scandium:3.5.0'
    implementation 'org.eclipse.californium:demo-certs:3.5.0'
    implementation 'org.slf4j:slf4j-simple:1.7.25'

如果有报META-INF相关的错误,则需要进行pick处理:

    packagingOptions {
    
    
        pickFirst 'META-INF/legal/**'
    }
客户端

客户端关注CoapClient类即可,如常用的post请求方法:

public void post(CoapHandler handler, String payload, int format)

三个参数分别为回调、正文、正文格式;
示例如下:

	CoapClient coapClient = new CoapClient("coap://192.168.21.104:5683/qlink/success");
	coapClient.post(new CoapHandler() {
    
    
			@Override
			public void onLoad(CoapResponse coapResponse) {
    
    
				System.out.println(coapResponse.getResponseText());
			}

			@Override
			public void onError() {
    
    

			}
		}, "{\"deviceMac\":\"1\",\"deviceType\":\"2\"}", MediaTypeRegistry.APPLICATION_JSON);

MediaTypeRegistry.APPLICATION_JSON即JSON格式,类似于content-type,有很多种选择;
getResponseText方法可从response中拿到回复的正文内容;
CoapClient默认的消息类型为CON

	/** The type used for requests (CON is default) */
	private Type type = Type.CON;

其他请求方法类似;

服务端

服务端关注CoapServer类,以及注意添加负责处理逻辑的Resource,Resource类似于Handler,但兼任了路径解析功能;

				CoapServer coapServer = new CoapServer(5683);
				Resource root = new CoapResource("qlink");
				root.add(new CoapResource("success"){
    
    
					@Override
					public void handlePOST(CoapExchange exchange) {
    
    
						System.out.println("--------"+getURI());
						System.out.println(exchange.getRequestText());
						
						Response response = new Response(CoAP.ResponseCode.CONTENT);
						response.setPayload("{\"result\":1}");
						response.getOptions().setContentFormat(MediaTypeRegistry.APPLICATION_JSON);
						exchange.respond(response);
					}
				});
				root.add(new CoapResource("regist"){
    
    
					@Override
					public void handlePOST(CoapExchange exchange) {
    
    
						System.out.println("--------"+getURI());
						System.out.println(exchange.getRequestText());
						
						Response response = new Response(CoAP.ResponseCode.CONTENT);
						response.setPayload("{\"result\":1}");
						response.getOptions().setContentFormat(MediaTypeRegistry.APPLICATION_JSON);
						exchange.respond(response);
					}
				});
				coapServer.add(root);
				coapServer.start();

上面的示例中,服务端将监听两个路径即:

coap://host:5683/qlink/success
coap://host:5683/qlink/regist

CoapResource是一个集成的处理类,只需要关注正文内容即可,可自由复写handle**来处理各类请求,在其源码中可见端倪:

//CoapResource.java
	public void handleRequest(Exchange exchange) {
    
    
        Code code = exchange.getRequest().getCode();
        switch(code) {
    
    
        case GET:
            this.handleGET(new CoapExchange(exchange, this));
            break;
        case POST:
            this.handlePOST(new CoapExchange(exchange, this));
            break;
        case PUT:
            this.handlePUT(new CoapExchange(exchange, this));
            break;
        case DELETE:
            this.handleDELETE(new CoapExchange(exchange, this));
            break;
        case FETCH:
            this.handleFETCH(new CoapExchange(exchange, this));
            break;
        case PATCH:
            this.handlePATCH(new CoapExchange(exchange, this));
            break;
        case IPATCH:
            this.handleIPATCH(new CoapExchange(exchange, this));
            break;
        default:
            exchange.sendResponse(new Response(ResponseCode.METHOD_NOT_ALLOWED, true));
        }
    }

回复只需要取得Exchange类,生成Response后使用respond方法即可:

		Response response = new Response(CoAP.ResponseCode.CONTENT);
		response.setPayload("{\"result\":1}");
		response.getOptions().setContentFormat(MediaTypeRegistry.APPLICATION_JSON);
		
		exchange.respond(response);

CoAP.ResponseCode.CONTENT类似于http的状态响应码,同样有很多选择,在这里输出的是2.05;

广播

严格来说是组播
组播不能简单用CoapClient来完成,因为CoapClient默认新建的Request是CON的,而组播并不允许,并会报错警告只能使用使用NON消息类型

System.err: [Thread-3] WARN org.eclipse.californium.core.network.CoapEndpoint - coap CON request to multicast destination 192.168.21.255:5683 is not allowed, as per RFC 7252, 8.1, a client MUST use NON message type for multicast requests

因而只能依照源码自行新建Request:

		Request request = new Request(CoAP.Code.POST, CoAP.Type.NON);
		
		request.setURI("coap://192.168.21.255/qlink/success");
		request.setPayload("{\"deviceMac\":\"11\",\"deviceType\":\"22\"}");

下面两行依次设置请求路径正文
当然,需要对回复进行监听,依旧仿照源码设置Observer即可:

	request.addMessageObserver(new MessageObserverAdapter() {
    
    
			@Override
			public void onResponse(Response response) {
    
    
				System.out.println(response.toString());
				System.out.println(response.getPayloadString());
			}
		});

最后稍微封装一下,主要是让其自行获取组播地址

	private static void broadcast(int port, String path, String content,MessageObserverAdapter observerAdapter) {
    
    
		Inet4Address broadcastAddress = NetworkInterfacesUtil.getBroadcastIpv4();
		String url = String.format(Locale.CHINA, "coap://%s:%d%s", broadcastAddress.getHostAddress(), port, path);

		Request request = new Request(CoAP.Code.POST, CoAP.Type.NON);
		request.setURI(url);
		request.setPayload(content);

		request.addMessageObserver(observerAdapter);
		request.send();
	}

组播的接收用上面的CoapServer服务端接收即可,一般情况下是够用的。
收到服务端的回复输出如下:

NON-2.05   MID=62472, Token=2E390D5C9381DFA7, OptionSet={"Content-Format":"application/json"}, "{"result":1}"
 {"result":1}
NON-2.05   MID=13847, Token=2E390D5C9381DFA7, OptionSet={"Content-Format":"application/json"}, "{"result":2}"
 {"result":2}
注意事项
  • 以上所有操作都建议在子线程中进行;
  • 记得导入org.slf4j:slf4j-simple:1.7.25

以上就是接触coap的一些记录,另外关于californium中的EndPoint以及线程模型之类的,有时间再看吧。

猜你喜欢

转载自blog.csdn.net/ifmylove2011/article/details/125204519
今日推荐