COAP--协议组件
CoAP(Constrained Application Protocol,受限应用协议)是一种应用在物联网世界的类web协议。libcoap是用C语言实现的一套CoAP协议,本文介绍libcoap的相关接口和重要结构体。
简介
CoAP(Constrained Application Protocol,受限应用协议)是一种应用在物联网世界的类web协议。由于物联网中的很多设备都是资源受限型的,即只有少量的内存空间和有限的计算能力,所以传统的HTTP协议应用在物联网上就显得过于庞大而不适用。 IETF的CoRE工作组提出了一种基于REST(Representational State Transfer)架构的CoAP(Constrained Application Protocol)协议,它的详细规范定义在RFC 7252。
目录
CoAP协议特点
- COAP协议网络传输层由TCP改为UDP
- 它基于REST,server的资源地址和互联网一样也有类似url的格式,客户端同样有POST、GET、PUT、DELETE方法来访问server,对HTTP做了简化
- COAP是二进制格式的,HTTP是文本格式的,COAP比HTTP更加紧凑
- 轻量化,COAP最小长度仅仅4字节,一个HTTP的头就占用几十字节
- 支持可靠传输、数据重传、块传输, 确保数据可靠到达
- 支持IP多播,即可以同时向多个设备发送请求
- 非长连接通信,适用于低功耗物联网场景
CoAP的URI
一个CoAP资源可以被一个URI所描述,例如一个设备可以测量温度,那么这个温度传感器的URI被描述为:CoAP://machine.address:5683/temperature?v=1&t=2。
- Uri-Host:服务器主机名称,如machine.address
- Uri-Port:服务器端口号,默认为5683
- Uri-Path:资源路路径,如/temperature
- Uri-Query:访问资源参数,例如?v=1&t=2
CoAP的请求码
在CoAP请求中,请求方法有GET、POST、PUT和DELETE,这些方法和HTTP协议非常相似。
- GET方法:用于获得某资源
- POST方法:用于创建某资源
- PUT方法:用于更新某资源
- DELETE方法:用于删除某资源
配置指南
Menuconfig 配置
在OneOS的SDK根目录下打开\projects\xxxxx文件夹,右键启动OneOS-Cube 工具,在命令行输入 menuconfig 打开可视化配置界面,选择"Components → Network → Protocols → Coap → libcoap-v4.2.1"选项。其中第一项用于使能libCoAP模块,该模块使能后可以选择“Enable libCoAP example”使能示例代码。
(Top) → Components→ Network→ Protocols→ CoAP→ libcoap-v4.2.1
[*] Enable libCoAP: A C implementation of the CoAP(RFC 7252)
[*] Enable libCoAP example
重要定义及数据结构
coap地址信息
用于标识本地及远端的地址信息,其定义如下:
typedef struct coap_address_t
{
uint16_t port;
ip_addr_t addr;
} coap_address_t;
重要成员 | 说明 |
---|---|
port | 连接地址端口号 |
addr | 连接地址ip信息 |
API列表
接口 | 说明 |
---|---|
coap_startup | coap功能模块初始化,包含时钟、随机数等 |
coap_cleanup | coap退出 |
coap_new_context | 建立coap上下文 |
coap_free_context | 删除上下文 |
coap_context_set_keepalive | 设置保活时间 |
coap_new_optlist | 建立opt结构体 |
coap_insert_optlist | 将opt插入链表 |
coap_delete_optlist | 删除opt链表 |
coap_new_client_session | 建立session |
coap_session_release | 删除session |
coap_register_option | 注册opt类型 |
coap_register_response_handler | 注册消息回调函数 |
coap_response_handler_t | 消息回调函数 |
coap_register_event_handler | 注册事件回调函数 |
coap_event_handler_t | 事件回调函数 |
coap_register_nack_handler | 注册未收到期望ACK的回调函数 |
coap_nack_handler_t | nack回调函数 |
coap_new_message_id | 获取新的消息ID |
coap_new_pdu | 创建PDU结构体 |
coap_add_optlist_pdu | 将opt链表添加至PDU |
coap_add_data | 添加data数据到PDU |
coap_add_block | 添加block数据到PDU |
coap_send | 发送PDU消息 |
coap_run_once | 主消息处理循环,处理消息重传、消息接收和分发等 |
coap_can_exit | 判断coap是否有消息等待发送或者分发 |
coap_split_uri | 从字符串提取URI信息,包含主机、端口、路径、请求参数等 |
coap_split_query | 从字符串提取query信息 |
coap_startup
该函数为coap功能模块的初始化接口,用于初始化coap协议需要使用的时钟、随机数等,函数原型如下:
void coap_startup(void);
参数 | 说明 |
---|---|
无 | 无 |
返回 | 说明 |
无 | 无 |
coap_cleanup
该函数为coap功能模块的去初始化接口,函数原型如下:
void coap_cleanup(void);
参数 | 说明 |
---|---|
无 | 无 |
返回 | 说明 |
无 | 无 |
coap_new_context
该函数创建coap功能模块上下文,用于保存协议栈状态信息,函数原型如下:
coap_context_t *coap_new_context(const coap_address_t *listen_addr);
参数 | 说明 |
---|---|
listen_addr | 监听地址,用作client时此处传入NULL |
返回 | 说明 |
NULL | 创建失败 |
非NULL | 创建成功,返回上下文结构体指针 |
coap_free_context
该函数释放coap上下文资源,函数原型如下:
void coap_free_context(coap_context_t *context);
参数 | 说明 |
---|---|
context | 需要释放的coap上下文指针 |
返回 | 说明 |
无 | 无 |
coap_context_set_keepalive
该函数用于设置上下文保活周期,函数原型如下:
void coap_context_set_keepalive(coap_context_t *context, unsigned int seconds);
参数 | 说明 |
---|---|
context | 需要释放的coap上下文指针 |
seconds | 保活周期 |
返回 | 说明 |
无 | 无 |
coap_new_optlist
该函数用于创建opt结构体,函数原型如下:
coap_optlist_t *coap_new_optlist(uint16_t number,
size_t length,
const uint8_t *data);
参数 | 说明 |
---|---|
number | opt类型,由COAP_OPTION_XXX定义 |
length | opt数据长度 |
data | opt数据 |
返回 | 说明 |
NULL | 创建失败 |
非NULL | 创建成功,返回opt结构体指针 |
coap_insert_optlist
该函数用于将opt结构体插入链表,函数原型如下:
int coap_insert_optlist(coap_optlist_t **optlist_chain,
coap_optlist_t *optlist);
参数 | 说明 |
---|---|
optlist_chain | 用于插入数据的链表 |
optlist | opt结构体指针 |
返回 | 说明 |
0 | 插入失败 |
1 | 插入成功 |
coap_delete_optlist
该函数用于删除opt链表,释放链表的内存资源,函数原型如下:
void coap_delete_optlist(coap_optlist_t *optlist_chain);
参数 | 说明 |
---|---|
optlist_chain | opt链表 |
返回 | 说明 |
无 | 无 |
coap_new_client_session
该函数用于创建连接到指定服务器地址的客户session,函数原型如下:
coap_session_t *coap_new_client_session(struct coap_context_t *ctx,
const coap_address_t *local_if,
const coap_address_t *server,
coap_proto_t proto);
参数 | 说明 |
---|---|
ctx | coap上下文 |
local_if | 指定用于网络连接的本地网络接口 |
server | 服务器地址和端口信息 |
proto | 指定连接协议,由COAP_PROTO_XXX宏定义 |
返回 | 说明 |
NULL | 创建失败 |
非NULL | 创建成功,返回session结构体指针 |
coap_session_release
该函数用于释放session资源,函数原型如下:
void coap_session_release(coap_session_t *session);
参数 | 说明 |
---|---|
session | 需要释放的session |
返回 | 说明 |
无 | 无 |
coap_register_option
该函数用于向ctx注册opt,函数原型如下:
void coap_register_option(coap_context_t *ctx, uint16_t type);
参数 | 说明 |
---|---|
ctx | coap上下文 |
type | opt类型 |
返回 | 说明 |
无 | 无 |
coap_register_response_handler
该函数用于注册回复消息的回调函数,函数原型如下:
void coap_register_response_handler(coap_context_t *context,
coap_response_handler_t handler);
参数 | 说明 |
---|---|
context | coap上下文 |
handler | 回调函数 |
返回 | 说明 |
无 | 无 |
coap_response_handler_t
coap回复消息的回调函数,函数原型如下:
typedef void (*coap_response_handler_t)(struct coap_context_t *context,
coap_session_t *session,
coap_pdu_t *sent,
coap_pdu_t *received,
const coap_tid_t id);
参数 | 说明 |
---|---|
context | coap上下文 |
session | 标识连接的session |
sent | 传输数据的pdu |
received | 接收到的pdu |
id | 消息id |
返回 | 说明 |
无 | 无 |
coap_register_event_handler
该函数用于注册事件的回调函数,函数原型如下:
void coap_register_event_handler(struct coap_context_t *context,
coap_event_handler_t hnd);
参数 | 说明 |
---|---|
context | coap上下文 |
hnd | 回调函数,事件宏定义:COAP_EVENT_XXX |
返回 | 说明 |
无 | 无 |
coap_event_handler_t
typedef int (*coap_event_handler_t)(struct coap_context_t *context,
coap_event_t event,
struct coap_session_t *session);
事件回调函数,函数原型如下:
参数 | 说明 |
---|---|
context | coap上下文 |
event | 事件类型,参考COAP_EVENT_XXX宏定义 |
session | 标识连接的session |
返回 | 说明 |
非0 | 处理失败 |
0 | 处理成功 |
coap_register_nack_handler
该函数用于注册超时未收到ack的回调函数,函数原型如下:
void coap_register_nack_handler(coap_context_t *context,
coap_nack_handler_t handler);
参数 | 说明 |
---|---|
context | coap上下文 |
handler | 回调函数 |
返回 | 说明 |
无 | 无 |
coap_nack_handler_t
nack回调函数,函数原型如下:
typedef void (*coap_nack_handler_t)(struct coap_context_t *context,
coap_session_t *session,
coap_pdu_t *sent,
coap_nack_reason_t reason,
const coap_tid_t id);
参数 | 说明 |
---|---|
context | coap上下文 |
session | 标识连接的session |
sent | 传输数据的pdu |
reason | nack详细原因,参见coap_nack_reason_t定义 |
id | 消息id |
返回 | 说明 |
无 | 无 |
coap_new_message_id
该函数用于新建消息ID,函数原型如下:
uint16_t coap_new_message_id(coap_session_t *session);
参数 | 说明 |
---|---|
session | 标识连接信息的session |
返回 | 说明 |
非NULL | 消息ID |
coap_new_pdu
该函数用于新建通信pdu,函数原型如下:
coap_pdu_t *coap_new_pdu(const struct coap_session_t *session);
参数 | 说明 |
---|---|
session | 标识连接信息的session |
返回 | 说明 |
NULL | 创建失败 |
非NULL | 创建成功,返回pdu结构体指针 |
coap_add_optlist_pdu
该函数用于添加opt链表到pdu,函数原型如下:
int coap_add_optlist_pdu(coap_pdu_t *pdu, coap_optlist_t **optlist_chain);
参数 | 说明 |
---|---|
pdu | 标识通信的pdu |
optlist_chain | opt链表 |
返回 | 说明 |
0 | 添加失败 |
1 | 添加成功 |
coap_add_data
该函数用于向pdu添加data数据,函数原型如下:
int coap_add_data(coap_pdu_t *pdu, size_t len, const uint8_t *data);
参数 | 说明 |
---|---|
pdu | 标识通信的pdu |
len | data长度 |
data | data数据 |
返回 | 说明 |
0 | 添加失败 |
1 | 添加成功 |
coap_add_block
该函数用于向pdu添加block数据,函数原型如下:
int coap_add_block(coap_pdu_t *pdu,
unsigned int len,
const uint8_t *data,
unsigned int block_num,
unsigned char block_szx);
参数 | 说明 |
---|---|
pdu | 标识通信的pdu |
len | data长度 |
data | 填充block的data数据 |
block_num | block编号 |
block_szx | block大小 |
返回 | 说明 |
0 | 添加失败 |
1 | 添加成功 |
coap_send
该函数用于向对端发送coap数据,函数原型如下:
coap_tid_t coap_send(coap_session_t *session, coap_pdu_t *pdu);
参数 | 说明 |
---|---|
session | 标识连接信息的session |
pdu | 标识通信的pdu |
返回 | 说明 |
-1 | 发送失败 |
非-1 | 发送成功,返回消息ID |
coap_run_once
该函数用于主消息处理循环,处理消息重传、消息接收和分发等,函数原型如下:
int coap_run_once(coap_context_t *ctx, unsigned int timeout_ms);
参数 | 说明 |
---|---|
ctx | coap上下文 |
timeout_ms | 超时时间,单位:ms |
返回 | 说明 |
-1 | 处理失败 |
非-1 | 发送成功,返回消息ID |
coap_can_exit
该函数用于判断是否有消息等待发送或分发,函数原型如下:
int coap_can_exit(coap_context_t *context);
参数 | 说明 |
---|---|
context | coap上下文 |
返回 | 说明 |
1 | 无等待消息 |
0 | 有等待消息 |
coap_split_uri
该函数用于从字符串解析URI信息,函数原型如下:
int coap_split_uri(const uint8_t *str_var, size_t len, coap_uri_t *uri);
参数 | 说明 |
---|---|
str_var | 包含URI信息的字符串 |
len | 字符串长度 |
uri | 用于保存URI信息的结构体指针 |
返回 | 说明 |
<0 | 解析失败 |
0 | 解析成功 |
coap_split_query
该函数用于从字符串解析query信息,生成标准query结构,函数原型如下:
int coap_split_query(const uint8_t *s,
size_t length,
unsigned char *buf,
size_t *buflen);
参数 | 说明 |
---|---|
s | 包含query信息的字符串 |
length | 字符串长度 |
buf | 保存标准query结构的buf |
buflen | buf最大长度,执行成功时修改为实际写入buf数据长度 |
返回 | 说明 |
<0 | 解析失败 |
0 | query数量 |
使用示例
完整示例较大,可参考components\net\protocols\coap\libcoap-v4.2.1\oneos\client.c的实现。
注意事项
无。