stm32 + W5500 实现一个简单的 CoAP 服务器

硬件:stm32f103+W5500
软件:microcoap开源库

void CoAP_Server(void)
{
    coap_packet_t pkt;

    switch(getSn_SR(SOCK_UDPS))    /*获取socket的状态*/
    {
        case SOCK_CLOSED:          /*socket处于关闭状态*/
            socket(SOCK_UDPS, Sn_MR_UDP, local_port,0); /*初始化socket*/
          break;

        case SOCK_UDP:       /*socket初始化完成*/
            delay_ms(10);
            if(getSn_IR(SOCK_UDPS) & Sn_IR_RECV)
            {
                setSn_IR(SOCK_UDPS, Sn_IR_RECV);  /*清接收中断*/
            }
            if((len = getSn_RX_RSR(SOCK_UDPS))>0)   /*接收到数据*/
            {
                data_len = recvfrom(SOCK_UDPS, buf, len, remote_ip, &remote_port);               /*W5500接收计算机发送来的数据*/
//              buf[data_len] = '\0';         /*添加字符串结束符*/
//              printf("%s\r\n", buf);       /*打印接收缓存*/ 

                if (0 != (rc = coap_parse(&pkt, buf, data_len)))
                {
                    printf("Bad packet rc=%d\r\n", rc);
                }
                else
                {
                    size_t rsplen = sizeof(buf);
                    coap_packet_t rsppkt;

                    coap_handle_req(&scratch_buf, &pkt, &rsppkt);       // 遍历endpoints数组

                    if (0 != (rc = coap_build(buf, &rsplen, &rsppkt)))  // 构造CoAP响应 coap_build 成功返回 0
                    {
                         printf("coap_build failed rc = %d\n", rc);
                    }
                    else
                    {
                        printf("--------------------\r\n");
                        printf("Sending Buffer: \r\n");
                        coap_dump(buf, rsplen, true);
                        printf("\r\n");

                        sendto(SOCK_UDPS, buf, rsplen, remote_ip, remote_port); /*W5500把接收到的数据发送给Remote*/
                    }
                }
            }
        break;
    }
}

这里写图片描述

endpoints列表

程序进行CoAP请求处理时将遍历endpoints列表,endpoints列表可以理解为一组端点集合(也可以理解为路由集合或资源集合),每个端点表示一个CoAP请求处理的最小“单元”,每个端点的由请求方法请求处理函数请求URI媒体类型组成。
具体如下:

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

上面包含四个不同的端点(路由或资源):支持GET方法的“well_known_core”端点、“hello”端点、“light”端点。支持PUT方法的“light”端点。此处“light”端点不但支持GET方法还支持PUT方法。

hello资源

hello资源需要有URI和路由处理函数两部分定义,实现如下:

static const coap_endpoint_path_t path_hello = {1, {"hello"}};
static int handle_get_hello(coap_rw_buffer_t *scratch, 
                            const coap_packet_t *inpkt, coap_packet_t *outpkt, 
                            uint8_t id_hi, uint8_t id_lo)
{
    char hello[32] = "{\"Hello\":\"World!\"}";  // JSON
    return coap_make_response(scratch, outpkt, 
                            (const uint8_t *)&hello, strlen(hello), 
                            id_hi, id_lo, &inpkt->tok, 
                            COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_APPLICATION_JSON);
}

在上述代码中:

  • coap_endpoint_path_t path_hello = {1, {"hello"}};定义hello资源的URI,该资源的URI为“hello”,通过coap://IP:5683/hello变可以访问该资源。
  • handle_get_hello()定义hello资源的处理函数,该函数将会向CoAP客户端返回JSON格式的固定负载{hello:world!}。
    这里写图片描述
    工具使用方法

测试

COAP协议全面分析
这里写图片描述
浏览器请求:
这里写图片描述
使用Wireshark抓取数据包。
请求GET /.well-known/core/haha 资源
这里写图片描述
CoAP回应 GET /.well-known/core/haha 资源
这里写图片描述

参考资料:
IoT开发实战:CoAP卷
The Constrained Application Protocol (CoAP)

猜你喜欢

转载自blog.csdn.net/Hola_ya/article/details/81737466