CoAP学习笔记——STM32平台上实现CoAP Server

0.前言

CoAP是受限制的应用协议(Constrained Application Protocol)的代名词。在当前由PC机组成的世界,信息交换是通过TCP和应用层协议HTTP实现的。但是对于小型设备而言,实现TCP和HTTP协议显然是一个过分的要求。为了让小设备可以接入互联网,CoAP协议被设计出来。CoAP是一种应用层协议,它运行于UDP协议之上而不是像HTTP那样运行于TCP之上。CoAP协议非常小巧,最小的数据包仅为4字节。

本文将使用STM32平台实现一个CoAP Server Demo。本文将详细说明如何使用STM32这样的低成本MCU实现CoAP Server的步骤,本文试图说明CoAP协议虽然很“年轻”,但是有用、好用且易用。

【代码仓库】

如果想获得本文的示例代码请点击——【bitbucket】,示例代码中的doc目录有本文所使用开发板的原理图和相关说明。

【相关博文】

物联网学习笔记——索引博文

CoAP学习笔记——nodeJS node-coap安装和使用(windows平台)

1.使用LwIP处理CoAP数据包

    新建一个套接字,绑定UDP 5683端口,侦听该端口数据使用microcoap响应函数解析,最后获得返回结果即可。示例中使用了RT Thread中移植好的LwIP协议栈,网卡驱动为ENC28J60。

void coap_server(void* para)
{
    int fd;
    struct sockaddr_in servaddr, cliaddr;
    coap_rw_buffer_t scratch_buf = {scratch_raw, sizeof(scratch_raw)};
    if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
    {
        printf("Socket Error\r\n");
        return;
    }
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(PORT);
    rt_memset(&(servaddr.sin_zero), 0, sizeof(servaddr.sin_zero));

    if ((bind(fd, (struct sockaddr *)&servaddr, sizeof(servaddr))) == -1)
    {
       printf("Bind error\r\n");
       return;
    }
    endpoint_setup();
    rt_kprintf("Coap Server Start!\r\n");
    while(1)
    {
        int n, rc;
        socklen_t len = sizeof(cliaddr);
        coap_packet_t pkt;
        n = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&cliaddr, &len);
#ifdef MICROCOAP_DEBUG
        printf("\r\n--------------------\r\n");
        printf("Received Buffer: \r\n");
        coap_dump(buf, n, true);
        printf("\r\n");
#endif
        if (0 != (rc = coap_parse(&pkt, buf, n)))
        {
            printf("Bad packet rc=%d\r\n", rc);
        }
        else
        {
            size_t rsplen = sizeof(buf);
            coap_packet_t rsppkt;
#ifdef MICROCOAP_DEBUG
            printf("Dump Packet: \r\n");
            coap_dumpPacket(&pkt);
#endif
            coap_handle_req(&scratch_buf, &pkt, &rsppkt);
            if (0 != (rc = coap_build(buf, &rsplen, &rsppkt)))
            {
                 printf("coap_build failed rc=%d\n", rc);
            }
            else
            {
#ifdef MICROCOAP_DEBUG
                printf("--------------------\r\n");
                printf("Sending Buffer: \r\n");
                coap_dump(buf, rsplen, true);
                printf("\r\n");
#endif
#ifdef MICROCOAP_DEBUG
                coap_dumpPacket(&rsppkt);
#endif
                sendto(fd, buf, rsplen, 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr));
            }
        }
    }
}

代码中使用了多个LwIP Socket部分的函数,例如socket, bind, recvfrom, sendto等。

其中coap_parse函数把从UDP获得的payload转化为符合CoAP规范的结构体,coap_handle_req函数根据CoAP请求中的URI,调用响应的处理函数。最后由coap_build函数把处理的结果系列化为UDP负载。

2.终端描述

    所有的终端信息均保存在endpoints全局数组中,该全局数组位于endpoints.c文件中。

const coap_endpoint_t endpoints[] =
{
    {COAP_METHOD_GET, handle_get_well_known_core, &path_well_known_core, "ct=40"},
    {COAP_METHOD_GET, handle_get_light, &path_light, "ct=0"},
    {COAP_METHOD_PUT, handle_put_light, &path_light, NULL},
    {COAP_METHOD_GET, handle_get_test_json, &path_test_json, "ct=50"},
    {(coap_method_t)0, NULL, NULL, NULL}
};

【1】每个endpoint需要CoAP访问方法,相应的处理函数,URI路径描述,资源描述方法等。

【2】CoAP协议中定义了多种访问方法,GET、PUT、POST和DELETE等方法。

【3】handle_get_light等函数主要用于处理CoAP请求,根据不同的请求调用不同的处理方法。

【4】ct=xx指定资源描述方法,例如ct=0表示字符串形式描述,ct=50表示JSON形式描述。

URI采用以下方式描述:

static const coap_endpoint_path_t path_light = {1, {"light"}};
static const coap_endpoint_path_t path_well_known_core = {2, {".well-known", "core"}};    

light的URI为 coap://<ip>:5683/light

well-known/core的URI为 coap://<ip>:5683/.well-known/core

请求处理函数采用以下方式:

static int handle_get_light(coap_rw_buffer_t *scratch,
                            const coap_packet_t *inpkt,
                            coap_packet_t *outpkt,
                            uint8_t id_hi, uint8_t id_lo)
{
    return coap_make_response(scratch,
                              outpkt,
                              (const uint8_t *)&light, 1,
                              id_hi, id_lo,
                              &inpkt->tok,
                              COAP_RSPCODE_CONTENT,
                              COAP_CONTENTTYPE_TEXT_PLAIN);
}

除了指定返回内容之外,可通过COAP_RSPCODE_CONTENT指定返回是否成功,也可以通过COAP_CONTENTTYPE_TEXT_PLAIN指定返回内容的格式。更多的定义请查看microcoap的源代码。

3.简单测试

    可使用CoAP命令行工具测试CoAP Server工作是否正常,或者使用火狐浏览器的coap插件。

使用CoAP命令行测试工具——coap-cli,详细的安装步骤请参考【CoAP学习笔记——nodeJS node-coap安装和使用(windows平台)】第2部分

3.1 light Demo

输入指令,尝试修改light状态

coap put  -p 1 coap://10.13.11.116/light

返回

(2.05)  1

说明

-p参数可用于指定coap的负载,此处1表示打开light,0表示关闭light。

图3.1 light PUT方法输出

输入指令,尝试获得light状态

coap get coap://10.13.11.116/light

返回

(2.05)  1

控制台输出

图3.2 light GET方法输出

3.2 JSON格式Demo

指令

coap get coap://10.13.11.116/test_json

返回

(2.05)

{

"value": 12

}

控制台输出

图3.3 JSON格式测试输出

4.CoAP格式分析

    通过示例代码并借助wireshark可分析CoAP数据包的各个部分,可加上CoAP协议的理解。wireshark中已经支持CoAP协议,在过滤窗口中输入coap便可抓取所有coap数据包。

CoAP协议的分析请参考——【CoAP学习笔记——CoAP格式详解

图4.1 wireshark分析CoAP

5. 总结

    microcoap正如它的名称一样,简单好用,函数不多但是可以实现最基本的功能。

时间: 2024-11-03 14:24:19

CoAP学习笔记——STM32平台上实现CoAP Server的相关文章

CoAP学习笔记——nodeJS node-coap安装和使用(windows平台)

0 前言 本文尝试在windows平台中搭建基于nodeJS的CoAP Server. linux平台搭建和使用过程可参考--CoAP学习笔记--nodeJS node-coap安装和使用(Linux平台) [测试环境]--windows [相关博文] [CoAP协议学习--CoAP基础] [CoAP学习笔记--CoAP资源发现] [CoAP学习笔记--服务器端繁忙时的处理请求流程] [树莓派学习笔记--webiopi安装与入门]webiopi中集成了CoAP Server,可以方便地通过CoA

CoAP学习笔记——nodeJS node-coap安装和使用(Linux平台)

 0 前言 本文说明如果安装和使用node-coap.CoAP是专门为物联网系统开发的面向网络的应用层协议栈,CoAP建立在UDP协议之上尽可能减少网络开销,又具有HTTP Restful类型的特性.node-coap使用nodejs实现了coap的客户端和服务器端. [测试环境]--ubuntu/Linux [相关博文] [CoAP协议学习--CoAP基础] [CoAP学习笔记--CoAP资源发现] [CoAP学习笔记--服务器端繁忙时的处理请求流程] [树莓派学习笔记--webiopi安装与

CoAP学习笔记——Libcoap安装和使用

0.CoAP和libcoap CoAP是一种面向网络的协议,采用了与HTTP类似的特征,核心内容为资源抽象.REST交互以及可扩展的头选项等. 为了克服HTTP对于受限环境的劣势,CoAP既考虑到数据报长度的最优化,又考虑到提供可靠通信.一方面,CoAP提供URI,REST 式的方法如GET,POST,PUT和DELETE,以及可以独立定义的头选项以提高可扩展性.另一方面,CoAP基于UDP协议,为了弥补UDP传输的不可靠性,CoAP定义了带有重传机制的事务处理机制. libcoap是CoAP协

CoAP学习笔记——nodeJS node-coap返回JSON数据包

0 前言 本文说明如何使用node-coap返回JSON数据包.CoAP是专门为物联网系统开发的面向网络的应用层协议栈,CoAP建立在UDP协议之上尽可能减少网络开销,又具有HTTP Restful类型的特性.node-coap使用nodejs实现了coap的客户端和服务器端. [测试环境]--ubuntu/Linux [相关博文] [CoAP协议文档--The Constrained Application Protocol (CoAP)] [CoAP协议学习--CoAP基础] [CoAP学习

CoAP学习笔记——CoAP格式详解

0 前言 CoAP是受限制的应用协议(Constrained Application Protocol)的代名词.在当前由PC机组成的世界,信息交换是通过TCP和应用层协议HTTP实现的.但是对于小型设备而言,实现TCP和HTTP协议显然是一个过分的要求.为了让小设备可以接入互联网,CoAP协议被设计出来.CoAP是一种应用层协议,它运行于UDP协议之上而不是像HTTP那样运行于TCP之上.CoAP协议非常小巧,最小的数据包仅为4字节. 更多博文请参考--[物联网学习笔记--索引博文] 1 Co

学习笔记:Caffe上LeNet模型理解

学习笔记:Caffe上LeNet模型理解 Caffe中用的模型结构是著名的手写体识别模型LeNet-5(http://yann.lecun.com/exdb/lenet/a35.html).当年美国大多数银行就是用它来识别支票上面的手写数字的.能够达到这种商用的地步,它的准确性可想而知,唯一的区别是把其中的sigmoid激活函数换成了ReLU. 为什么换成ReLU,上一篇blog中找到了一些相关讨论,可以参考. CNN的发展,关键就在于,通过卷积(convolution http://deepl

学习笔记_springmvc文件上传和拦截器

文件上传 用到这两个包 配置视图解析器:springmvc配置文件配置 <!-- id必须要是"multipartResolver" --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- maxUploadSize文件上传的最大值,单位是byte

老男孩视频第一部前面的部分学习笔记(在51cto上听的)

如何才能学好Linux运维 学习运维需要计算机基础,版本的选择我选择:centos 学习Linux运维四项基本原则 需要刻苦勤奋,持之以恒  入门比较难 Linux运维需要很多的知识,不但学习Linux操作本身还得学好周边的知识. 学好Linux运维四要素: 1.设定目标,是学好Linux运维的关键所在 2.寻找方法 通过书藉学习--阅读,实践,总结,和网友讨论:然后再阅读,再实践,再总结                 如何请教别人帮助自己--寻找帮忙                 3.勤奋

学习笔记:Caffe上配置和运行MNIST

学习笔记:Caffe上配置和运行MNIST MNIST,一个经典的手写数字库,包含60000个训练样本和10000个测试样本,图片大小28*28,在Caffe上配置的第一个案例 1首先,获取minist的数据包. 这个版本是四个数据包cd $CAFFE_ROOT./data/mnist/get_mnist.sh [html] view plaincopy #!/usr/bin/env sh # This scripts downloads the mnist data and unzips it