Thingsboard – CoAP 协议介绍

首页 » 物联网技术 » Thingsboard – CoAP 协议介绍

以下内容是在原文基础上演绎的译文。除非另行注明,页面上所有内容采用知识共享-署名(CC BY 2.5 AU)协议共享。

原文地址: ThingsBoard API 参考:MQTT 设备 API

视频教程

CoAP

协议介绍 CoAP 是一种在物联网世界的类 web 协议,它的详细规范定义在 RFC 7252。COAP 名字翻译来就是 “受限应用协议”,顾名思义,使用在资源受限的物联网设备上。物联网设备的 ram,rom 都通常非常小,运行 TCPHTTP 是不可以接受的。

协议特点

CoAP

协议介绍 CoAP 是一种在物联网世界的类 web 协议,它的详细规范定义在 RFC 7252。COAP 名字翻译来就是 “受限应用协议”,顾名思义,使用在资源受限的物联网设备上。物联网设备的 ram,rom 都通常非常小,运行 TCP 和 HTTP 是不可以接受的。

协议特点

Thingsboard - CoAP 协议介绍
CoAP
  • 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 的性能表现是比较突出的,如下图:

Thingsboard - CoAP 协议介绍
ThingsBoard CoAP

更多的数据可以参考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 服务。

以下图片展示服务端的基础架构:

Thingsboard - 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 许可协议。转载请注明出处!