硬件: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;
}
}
程序进行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资源需要有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)