以下内容是在原文基础上演绎的译文。除非另行注明,页面上所有内容采用知识共享-署名(CC BY 2.5 AU)协议共享。
原文地址: ThingsBoard API 参考:MQTT 设备 API
CoAP
协议介绍 CoAP 是一种在物联网世界的类 web 协议,它的详细规范定义在 RFC 7252。COAP 名字翻译来就是 “受限应用协议”,顾名思义,使用在资源受限的物联网设备上。物联网设备的 ram,rom 都通常非常小,运行 TCP 和 HTTP 是不可以接受的。
协议特点
CoAP
协议介绍 CoAP 是一种在物联网世界的类 web 协议,它的详细规范定义在 RFC 7252。COAP 名字翻译来就是 “受限应用协议”,顾名思义,使用在资源受限的物联网设备上。物联网设备的 ram,rom 都通常非常小,运行 TCP 和 HTTP 是不可以接受的。
协议特点
- CoAP 协议网络传输层由 TCP 改为 UDP。
- 它基于 REST,server 的资源地址和互联网一样也有类似 url 的格式,客户端同样有 POST,GET,PUT,DELETE 方法来访问 server,对 HTTP 做了简化。
- COAP 是二进制格式的,HTTP 是文本格式的,COAP 比 HTTP 更加紧凑。
- 轻量化,COAP 最小长度仅仅 4B,一个 HTTP 的头都几十个 B 了。
- 支持可靠传输,数据重传,块传输。 确保数据可靠到达。
- 支持 IP 多播, 即可以同时向多个设备发送请求。
- 非长连接通信,适用于低功耗物联网场景。
客户端库设置
安装 安装 node.js,然后执行以下命令:
npm install coap-cli -g
用法
Usage: coap [command] [options] url
Commands:
get performs a GET request
put performs a PUT request
post performs a POST request
delete performs a DELETE request
Options:
-h, --help output usage information
-V, --version output the version number
-o, --observe Observe the given resource
-n, --no-new-line No new line at the end of the stream
-p, --payload <payload> The payload for POST and PUT requests
-b, --block2 <option> set the block2 size option
-q, --quiet Do not print status codes of received packets
-c, --non-confirmable non-confirmable
-t, --timeout <seconds> The maximum send time in seconds
-T, --show-timing Print request time, handy for simple performance tests
-O, --coap-option <key,value> Add COAP-Option to the request (repeatable)
PUT 和 POST PUT 和 POST 请求如下例所示
echo -n 'hello world' | coap post coap://localhost/message
Thingsboard 的 CoAP 传输协议架构
因为 Thingsboard 最新 release,是基于微服务架构,不利用单独理解代码。 Thingsboard CoAP 设备传输协议源代码:https://github.com/thingsboard/thingsboard/tree/release-2.0/transport/coap 本文基于上面源代码后,剔除相关的安全验证和处理之后搭建简易的讲解项目: https://github.com/sanshengshui/IOT-Technical-Guide/tree/master/IOT-Guide-Coap
CoAP 框架
Thingsboard 的 CoAP 设备传输协议是基于 Californium。Californium 是一款基于 Java 实现的 Coap 技术框架,该项目实现了 Coap 协议的各种请求响应定义,支持 CON/NON 不同的可靠性传输模式。 Californium 基于分层设计且高度可扩展,其内部模块设计及接口定义存在许多学习之处; 值得一提的是,在同类型的 Coap 技术实现中,Californium 的性能表现是比较突出的,如下图:
更多的数据可以参考Californium-可扩展云服务白皮书 本文以框架的源码分析为主,其他内容不做展开。
项目结构
.
└── main
└── java
├── com
│ └── sanshengshui
│ └── coap
│ ├── adaptors
│ │ └── JsonCoapAdaptor.java
│ ├── CoapTransportResource.java
│ ├── common
│ │ └── FeatureType.java
│ └── session
│ └── SessionMsgType.java
└── IOTCoapServer.java
代码讲解
IOTCoapServer
public class IOTCoapServer {
private static final String V1 = "v1";
private static final String API = "api";
private static String host = "127.0.0.1";
private static Integer port = 5683;
private static long timeout = 10000;
public static void main(String[] args) throws UnknownHostException {
CoapServer coapServer = new CoapServer();
CoapResource api = new CoapResource(API);
api.add(new CoapTransportResource(V1,timeout));
coapServer.add(api);
InetAddress addr = InetAddress.getByName(host);
InetSocketAddress sockAddr = new InetSocketAddress(addr, port);
coapServer.addEndpoint(new CoapEndpoint(sockAddr));
coapServer.start();
}
}
- 第 12 行代码: CoapServer 用作创建服务端。
- 第 12-15 行: CoapResource 是 resource 的基本实现,扩展这个类来编写您自己的资源。通过向资源添加 “v1”、” api” 和超时时间的设置,则 coap 的基础 url 为:coap://localhost:port/api/v1/。
- 第 16-18 行: Endpoint 负责与网络进行通信, 如果没有一个 Endpoint 与 CoapServer 进行绑定,那就创建一个默认的 Endpoint,默认就是 ucp 实现传输层。
- 第 19 行,启动 CoAP 服务。
以下图片展示服务端的基础架构:
CoapTransportResource 此类负责处理请求
GET
public void handleGET(CoapExchange exchange) {
Optional<FeatureType> featureType = getFeatureType(exchange.advanced().getRequest());
if (!featureType.isPresent()) {
} else if (featureType.get() == FeatureType.TELEMETRY) {
exchange.respond(CoAP.ResponseCode.BAD_REQUEST);
} else if (featureType.get() == FeatureType.ATTRIBUTES) {
processRequest(exchange, SessionMsgType.GET_ATTRIBUTES_REQUEST);
} else {
exchange.respond(CoAP.ResponseCode.BAD_REQUEST);
}
}
如果我们客户端发起的是 GET 请求,那么将会进入到 handleGET(CoapExchange exchange) 方法。
getFeatureType(Request request)判断coap协议长度是否大于3。当大于等于3,获取/api/v1/${param}的param元素。
public static final int FEATURE_TYPE_POSITION = 3;
private Optional<FeatureType> getFeatureType(Request request) {
List<String> uriPath = request.getOptions().getUriPath();
try {
if (uriPath.size() >= FEATURE_TYPE_POSITION) {
return Optional.of(FeatureType.valueOf(uriPath.get(FEATURE_TYPE_POSITION - 1).toUpperCase()));
}
} catch (RuntimeException e) {
}
return Optional.empty();
}
- 通过判断 param 是否是 temperature 还是 attributes 进行相关的逻辑操作。
- 当不是上述类型,回复状态为 BAD_REQUEST 的状态码。
POST
@Override
public void handlePOST(CoapExchange exchange) {
Optional<FeatureType> featureType = getFeatureType(exchange.advanced().getRequest());
if (!featureType.isPresent()) {
exchange.respond(CoAP.ResponseCode.BAD_REQUEST);
} else {
switch (featureType.get()) {
case ATTRIBUTES:
processRequest(exchange, SessionMsgType.POST_ATTRIBUTES_REQUEST);
break;
case TELEMETRY:
processRequest(exchange, SessionMsgType.POST_TELEMETRY_REQUEST);
break;
}
}
}
- 如果我们客户端发起的是 POST 请求,那么将会进入到 handlePOST(CoapExchange exchange) 方法。
- 对获取的 uri 的类型是 temperature 还是 attributes 来做相关的逻辑操作。
逻辑处理
private void processRequest(CoapExchange exchange, SessionMsgType type) {
exchange.accept();
Exchange advanced = exchange.advanced();
Request request = advanced.getRequest();
try {
switch (type) {
case GET_ATTRIBUTES_REQUEST:
case POST_TELEMETRY_REQUEST:
case POST_ATTRIBUTES_REQUEST:
//这个类在之前的物模型博文中有所讲解,大家可以翻看!
JsonCoapAdaptor.convertToMsg(type,request);
break;
default:
throw new IllegalArgumentException("Unsupported msg type: " + type);
}
exchange.respond("Data has been received");
} catch (AdaptorException e){
exchange.respond(CoAP.ResponseCode.BAD_REQUEST, e.getMessage());
} catch (IllegalArgumentException e) {
exchange.respond(CoAP.ResponseCode.INTERNAL_SERVER_ERROR, e.getMessage());
}
}
项目演示
遥测上传 API 要将遥测数据发布到服务器节点,请将 POST 请求发送到以下 URL:
coap://host/api/v1/telemetry
最简单的支持数据格式是:
{"key1":"value1", "key2":"value2"}
或者
[{"key1":"value1"}, {"key2":"value2"}]
请注意,在这种情况下,服务器端时间戳将分配给上传的数据! 如果您的设备能够获取客户端时间戳,您可以使用以下格式:
{"ts":1451649600512, "values":{"key1":"value1", "key2":"value2"}}
在上面的示例中,我们假设 “1451649600512” 是具有毫秒精度的 unix 时间戳。例如,值’1451649600512’ 对应于’Fri,2016年1月1日12:00:00.512 GMT’ 例子:
echo -n '{"size":21,"type":"device"}' | coap post coap://demo.thingsboard.io/api/v1/telemetry
结果:
key= 1564105084015
属性名=size 属性值=21
属性名=type 属性值=device
属性 API 属性 API 允许设备
- 将客户端设备属性上载到服务器。
- 从服务器请求客户端和共享设备属性。
将属性更新发布到服务器 要将客户端设备属性发布到 ThingsBoard 服务器节点,请将 POST 请求发送到以下 URL:
coap://host/api/v1/attributes
例子:
echo -n '{"size":21,"type":"device","status":true}' | coap post coap://localhost:5683/api/v1/attributes
结果:
key= 1564105158573
属性名=size 属性值=21
属性名=type 属性值=device
属性名=status 属性值=true
从服务器请求属性值 要向 ThingsBoard 服务器节点请求客户端或共享设备属性,请将 GET 请求发送到以下 URL:
coap://host/api/v1/attributes?clientKeys=attribute1,attribute2&sharedKeys=shared1,shared2
例子:
coap get coap://localhost:5683/api/v1/attributes?clientKeys=attribute1,attribute2&sharedKeys=shared1,shared2
结果:
(2.05) Data has been received
到此,物联网时代,相信大家对 IOT 架构下的 CoAP 协议有所了解了,感谢大家的阅读!
本文作者: 穆书伟
本文链接: https://blog.grozacloud.com/2019/07/25/-跟着 Thingsboard 学 IOT 架构-CoAP 设备协议物联网时代
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!