CoAP学习笔记——STM32平台上实现CoAP Server
2015-05-12 15:29
369 查看
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。
2.终端描述 所有的终端信息均保存在endpoints全局数组中,该全局数组位于endpoints.c文件中。
URI采用以下方式描述:
请求处理函数采用以下方式:
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正如它的名称一样,简单好用,函数不多但是可以实现最基本的功能。
【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正如它的名称一样,简单好用,函数不多但是可以实现最基本的功能。
相关文章推荐
- 通过串口实现stm32的IAP功能————stm32学习笔记
- STM32学习笔记4(TIM32位定时器的实现)
- STM32学习笔记7(增量式PID的实现)
- CoAP学习笔记——nodeJS node-coap安装和使用(Linux平台)
- CoAP学习笔记——nodeJS node-coap安装和使用(windows平台)
- STM32 IAP功能实现学习笔记 ---详细说明
- OpenCL 学习笔记6 在CPU/GPU平台上的实现
- TCP-IP学习笔记八:RPC(Netty和Spring)实现webServer框架
- 微信平台开发学习笔记二(翻译功能的实现)
- STM32学习笔记:单片机按键单击、双击、长按功能实现
- STM32学习笔记:单片机按键单击、双击、长按功能实现
- Hive学习笔记1@Hiveserver2高可用实现
- 转:Stm32学习笔记:按键单击、双击、长按功能实现
- STM32实现IAP功能的学习笔记
- STM32实现IAP功能的学习笔记
- CAN 学习笔记一_【基于STM32的CANopen通讯协议的实现】
- 【python学习笔记】Python实现协程yield方法和gevent库
- 机器学习实战笔记(3.3)-朴素贝叶斯算法(多项式模型的朴素贝叶斯实现)
- stm32学习笔记 F1系列DMA
- 【Java】ServerSocket的学习笔记