thingsboard 之 coap 协议介绍 · 物联网平台-威尼斯人最新

thingskit · 2020年03月02日 · 最后由 回复于 2022年08月19日 · 832 次阅读
本帖已被设为精华帖!

可复制:121202538

中文社区:

tb 的 mqtt 设备协议 tb 澳门人威尼斯3966官网:

tb github:

tb 提供的体验地址:

by thingsboard team

以下内容是在原文基础上演绎的译文。除非另行注明,页面上所有内容采用知识共享-共享。

原文地址: thingsboard api 参考:

演示视频:

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        the payload for post and put requests
    -b, --block2 

put 和 post put 和 post 请求如下例所示

echo -n 'hello world' | coap post coap://localhost/message

thingsboard 的 coap 传输协议架构

因为 thingsboard 最新 release,是基于微服务架构,不利用单独理解代码。 thingsboard coap 设备传输协议源代码: 本文基于上面源代码后,剔除相关的安全验证和处理之后搭建简易的讲解项目:

coap 框架

thingsboard 的 coap 设备传输协议是基于 californium。californium 是一款基于 java 实现的 coap 技术框架,该项目实现了 coap 协议的各种请求响应定义,支持 con/non 不同的可靠性传输模式。 californium 基于分层设计且高度可扩展,其内部模块设计及接口定义存在许多学习之处; 值得一提的是,在同类型的 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 服务。

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

coaptransportresource

此类负责处理请求

get

public void handleget(coapexchange exchange) {
    optional 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 getfeaturetype(request request) {
        list 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 = 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 协议有所了解了,感谢大家的阅读!

本文作者: 穆书伟

本文链接: 物联网时代

澳门人威尼斯3966的版权声明: 本博客所有文章除特别声明外,均采用 by-nc-sa 许可协议。转载请注明出处!

1楼 已删除
2楼 已删除
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册
网站地图