CoAP协议(RFC 7252)使用RESTful服务框架,通过统一的资源标识、统一的操作接口、可自描述的消息,实现物联网设备端与服务端所需交互。AliOS Things中CoAP组件的结构图如下。

其包括:

  • CoAP CoreCoAP核心模块,主要包括上下文处理、会话处理、DTLS适配、IO适配。 该模块实现CoAP主流程,对外提供标准CoAP协议行为。
  • Adpater:连云适配模块,主要包括连接上下文、认证、消息处理。该模块对上提供连接云平台所需API。用户可以基于该API实现数据上报的应用。

API列表

名称 说明
IOT_CoAP_Init 初始化CoAP上下文
IOT_CoAP_Deinit 去初始化CoAP上下文。
IOT_CoAP_DeviceNameAuth 与服务端对设备三元组信息进行认证。
IOT_CoAP_Yield 处理远端数据与发送响应超时。
IOT_CoAP_SendMessage 向远端topic发送数据。
IOT_CoAP_GetMessagePayload 提取消息体。
IOT_CoAP_GetMessageCode 提取回复消息码。

使用

添加该组件

在使用CoAP的组件或应用对应的aos.mk中添加

$(NAME)_COMPONENTS += libcoap

在使用CoAP的组件或应用对应的Config.in中添加

select AOS_COMP_LIBCOAP if !AOS_CREATE_PROJECT

头文件

对外头文件代码位于include/network/coap,包括

coap.h

使用时只需包含

#include <coap.h>

使用示例

/*初始化CoAP上下文*/
p_ctx = IOT_CoAP_Init(&config);

if (NULL != p_ctx) {
   /*与云端进行认证*/
   if (IOT_CoAP_DeviceNameAuth(p_ctx) == IOTX_SUCCESS) {
     do {
        /*接收数据,并处理超时*/
        IOT_CoAP_Yield(p_ctx);
     } while (m_coap_client_running);
   } else {
      LOGE(TAG, "CoAP authentication failed");
   }
   /*去初始化*/
   IOT_CoAP_Deinit(&p_ctx);
}

更详细的例子请参考application/example/coap_demo

API 详情

IOT_CoAP_Init

原型

iotx_coap_context_t *IOT_CoAP_Init(iotx_coap_config_t *p_config);

接口说明

根据配置参数,初始化CoAP上下文,创建DTLS Session。

参数说明

参数 数据类型 方向 说明
p_config iotx_coap_config_t * 输入 CoAP配置参数

其中,iotx_coap_context_t为void,数据类型iotx_coap_config_t定义见标准宏和结构体说明。

返回值说明

说明
非NULL 成功,CoAP上下文句柄指针
NULL 失败

接口示例

iotx_coap_config_t      config;
iotx_coap_context_t *p_ctx = NULL;

/* 设置参数 */
memset(&config, 0, sizeof(iotx_coap_config_t));
config.p_url = url;
config.p_devinfo = (iotx_coap_device_info_t *)&deviceinfo;
config.wait_time_ms = 3000;

/* 根据参数,初始化上下文 */
p_ctx = IOT_CoAP_Init(&config);

IOT_CoAP_Deinit

原型

void IOT_CoAP_Deinit(iotx_coap_context_t **p_context);

接口说明

去初始化CoAP上下文

参数说明

参数 数据类型 方向 说明
p_context iotx_coap_context_t ** 输入 CoAP上下文句柄指针的地址

返回值说明

接口示例

iotx_coap_config_t      config;
iotx_coap_context_t *p_ctx = NULL;

/* 根据参数,初始化上下文 */
p_ctx = IOT_CoAP_Init(&config);

/* 去初始化 */
IOT_CoAP_Deinit(&p_ctx);

IOT_CoAP_DeviceNameAuth

原型

int IOT_CoAP_DeviceNameAuth(iotx_coap_context_t *p_context);

接口说明

与服务端对设备三元组信息进行认证。

参数说明

参数 数据类型 方向 说明
p_context iotx_coap_context_t * 输入 CoAP上下文句柄指针

返回值说明

说明
0 成功
负值 失败,参考iotx_ret_code_t定义

其中,iotx_ret_code_t定义见标准宏和结构体说明。

接口示例

iotx_coap_config_t      config;
iotx_coap_context_t *p_ctx = NULL;

/* 根据参数,初始化上下文 */
p_ctx = IOT_CoAP_Init(&config);

/* 认证设备信息 */
IOT_CoAP_DeviceNameAuth(p_ctx);

IOT_CoAP_Yield

原型

int IOT_CoAP_Yield(iotx_coap_context_t *p_context);

接口说明

处理远端数据与发送响应超时。

参数说明

参数 数据类型 方向 说明
p_context iotx_coap_context_t * 输入 CoAP上下文句柄指针

返回值说明

说明
非负 成功
负值 失败

接口示例

if (IOT_CoAP_DeviceNameAuth(p_ctx) == IOTX_SUCCESS) {
   do {
      /* 处理远端数据与请求超时 */
      IOT_CoAP_Yield(p_ctx);
   } while (m_coap_client_running);
}

IOT_CoAP_SendMessage

原型

int IOT_CoAP_SendMessage(iotx_coap_context_t *p_context, char *p_path, iotx_message_t *p_message);

接口说明

向远端topic发送数据

参数说明

参数 数据类型 方向 说明
p_context iotx_coap_context_t * 输入 CoAP上下文句柄指针
p_path char * 输入 topic路径
p_message iotx_message_t * 输入 需要发生的消息

返回值说明

说明
0 成功
负值 失败,参考iotx_ret_code_t定义

接口示例

iotx_message_t message;
/* 设置发送topic*/
snprintf(path, IOTX_URI_MAX_LEN, "/topic/%s/%s/user/update", IOTX_PRODUCT_KEY, IOTX_DEVICE_NAME);
/* 配置发送消息 */
memset(&message, 0, sizeof(iotx_message_t));
message.p_payload = (unsigned char *)"{\"name\":\"hello world\"}";
message.payload_len = strlen("{\"name\":\"hello world\"}");
message.resp_callback = iotx_response_handler;
message.msg_type = IOTX_MESSAGE_CON;
message.content_type = IOTX_CONTENT_TYPE_JSON;
/* 发送消息 */
IOT_CoAP_SendMessage(p_ctx, path, &message);

IOT_CoAP_GetMessagePayload

原型

int IOT_CoAP_GetMessagePayload(void *p_message, unsigned char **pp_payload, int *p_len);

接口说明

提取消息体

参数说明

参数 数据类型 方向 说明
p_message void * 输入 消息指针
pp_payload unsigned char ** 输出 存储消息体指针的地址
p_len int * 输出 消息体长度

返回值说明

说明
0 成功
负值 失败,参考iotx_ret_code_t定义

接口示例

/* 响应消息处理回调 */
static void iotx_response_handler(void *arg, void *p_response)
{
 
    int            len       = 0;
    unsigned char *p_payload = NULL;

    /* 提取消息体内容 */
    IOT_CoAP_GetMessagePayload(p_response, &p_payload, &len);
}

IOT_CoAP_GetMessageCode

原型

int IOT_CoAP_GetMessageCode(void *p_message, iotx_coap_resp_code_t *p_resp_code);

接口说明

提取回复消息码

参数说明

参数 数据类型 方向 说明
p_message void * 输入 消息指针
p_resp_code iotx_coap_resp_code_t * 输出 消息码

其中,iotx_coap_resp_code_t定义见标准宏和结构体说明。

返回值说明

说明
0 成功
负值 失败,参考iotx_ret_code_t定义

/* 响应消息处理回调 */
static void iotx_response_handler(void *arg, void *p_response)
{
    iotx_coap_resp_code_t resp_code;
    /* 提取消息体码 */
    IOT_CoAP_GetMessageCode(p_response, &resp_code);
}

配置说明

CoAP可配置项包括:

  • 是否使用DTLS,默认为使用DTLS
  • 是否使用阿里云IOT平台PSK认证方式,默认使用阿里云IOT平台PSK认证方式
  • 是否开启Debug输出,默认开启Debug输出
  • 是否定义BUILD_AOS,默认为定义BUILD_AOS宏

移植说明

CoAP模块需要实现连接wrapper、系统wrapper、认证wrapper。

连接wrapper

接口 描述

ssize_t coap_network_send( coap_socket_t *sock, const struct coap_session_t *session, const uint8_t *data, size_t datalen )

数据发送

sock:CoAP socket上下文

session:CoAP session

data:需要发送数据地址

datalen:数据长度

返回值:>0发送长度,-1失败

ssize_t coap_network_read( coap_socket_t *sock, struct coap_packet_t *packet )

数据接收

sock:CoAP socket上下文

packet:接收数据结构体

返回值:>0接收长度,-1失败

int coap_socket_connect_udp(coap_socket_t *sock, const coap_address_t *local_if, const coap_address_t *server, int default_port, coap_address_t *local_addr, coap_address_t *remote_addr);

建立UDP与远端的连接

sockCoAP socket上下文

local_if:本地地址

server:远端地址

default_port:默认端口号

local_addr:实际使用本地地址

remote_addr:实际远端的地址

返回值:0发送长度,-1失败

void coap_socket_close(coap_socket_t *sock)

关闭连接

client:HTTP上下文

返回值:HTTPC_RESULT

int coap_dtls_send(coap_session_t *coap_session, const uint8_t *data, size_t data_len);

发送dtls数据

c_session:coap session

data:需要发送的数据地址

data_len:数据长度

返回值:>0发送长度,-1失败

int coap_dtls_receive(coap_session_t *coap_session, const uint8_t *data, size_t data_len);

接收dtls数据

c_session:coap session

data:接收缓存地址

data_len:缓存大小

返回值:>0接收长度,-1失败

void *coap_dtls_new_client_session( coap_session_t *coap_session);

创建客户端dtls session

c_session:coap session

返回值:非空 dlts session,NULL失败

void coap_dtls_free_session(coap_session_t *coap_session);

释放dtls session

返回值:

系统wrapper

接口 描述
void *coap_malloc_type( coap_memory_tag_t type, size_t size);

分配空间

type:类型

size:分配大小

返回值:分配地址,NULL失败

void coap_free_type(coap_memory_tag_t type, void *p);

释放空间type:类型

p:内存地址

返回值:

void *coap_realloc(void *mem, unsigned int size)

重分配mem:内存地址

size:重新分配的大小

返回值:分配地址,NULL失败

认证wrapper

接口 描述
void * coap_wrapper_cjson_parse(const char *src);

解析json

src:原字符串地址

返回:解析后json地址,NULL失败

void * coap_wrapper_cjson_object_item(void *root, const char *key)

获取key对应的json节点

root:json地址

key:key值字段

返回值:json节点地址,NULL失败

char * coap_wrapper_cjson_value_string(void *node)

获取json节点字符串

node:json节点地址

返回值:字符串地址,NULL失败

int coap_wrapper_cjson_value_int(void *node)

获取json节点整型值

node:json节点地址

返回值:整型值

void coap_wrapper_cjson_release(void *root)

释放json

root:json地址

void coap_wrapper_hmac_md5(const char *msg, int msg_len, char *digest, const char *key, int key_len);

对字符串md5加密

msg:字符串地址

msg_len:字符串长度

digest:生成的摘要

key:密钥

key_len:密钥长度

返回值:无

void * coap_wrapper_aes128_init(const unsigned char *key, const unsigned char *iv, bool is_encrypt)

aes128初始化

key:密钥地址

IV:IV地址

is_encrypt:是否加密

返回值:aes上下文

int coap_wrapper_aes128_destroy(void *aes)

销毁aes上下文:

aes:aes上下文地址

返回值:0成功;1失败

int coap_wrapper_aes128_cbc_decrypt(void *aes, const void *src, unsigned int blockNum,void *dst);

aes128解密

aes:aes上下文地址

src:源地址

blockNum:块数量

dst:目标地址

返回值:0成功;1失败

int coap_wrapper_aes128_cbc_encrypt(void *aes, const void *src, unsigned int blockNum, void *dst);

aes128加密

aes:aes上下文地址

src:源地址

blockNum:块数量

dst:目标地址

返回值:0成功;1失败

void coap_wrapper_sha256(const unsigned char *input, unsigned int ilen, unsigned char output[32]);

sha256加密

input:源地址

ilen:输入长度

output:目标地址

返回值:无

标准宏和结构体说明

iotx_coap_config_t结构体定义

typedef struct {
    char                    *p_url;         /* 连接地址URL */
    int                      wait_time_ms;  /* 连接等待时间,单位毫秒 */
    iotx_coap_device_info_t *p_devinfo;     /* 设备四元组信息 */
    iotx_event_handle_t      event_handle;  /* 事件回调 */
} iotx_coap_config_t;

iotx_ret_code_t枚举定义

typedef enum {
    IOTX_ERR_RECV_MSG_TIMEOUT = -9, /* 接收消息超时 */
    IOTX_ERR_SEND_MSG_FAILED  = -8, /* 发送消息失败 */
    IOTX_ERR_MSG_TOO_LOOG     = -7, /* 消息体太长 */
    IOTX_ERR_URI_TOO_LOOG     = -6, /* topic URI太长 */
    IOTX_ERR_NOT_AUTHED       = -5, /* 设备未认证 */
    IOTX_ERR_AUTH_FAILED      = -4, /* 设备认证失败 */
    IOTX_ERR_BUFF_TOO_SHORT   = -3, /* 缓存太小 */
    IOTX_ERR_NO_MEM           = -2, /* 内存分配失败 */
    IOTX_ERR_INVALID_PARAM    = -1, /* 参数非法 */
    IOTX_SUCCESS              =  0, /* 成功 */
} iotx_ret_code_t;

iotx_coap_resp_code_t枚举定义

typedef enum {
    IOTX_COAP_RESP_CODE_CONTENT        = 0x45,       /* 对应2.05, 内容 */
    IOTX_COAP_RESP_CODE_BAD_REQUEST    = 0x80,       /* 对应4.00, 非法请求 */
    IOTX_COAP_RESP_CODE_UNAUTHORIZED   = 0x81,       /* 对应4.01, token非法或过期 */
    IOTX_COAP_RESP_CODE_NOT_FOUND      = 0x84,       /* 对应4.04, Path或URI不存在 */
    IOTX_COAP_RESP_CODE_URL_TOO_LONG   = 0x8E,       /* 对应4.14, URI太长 */
    IOTX_COAP_RESP_CODE_INTERNAL_SERVER_ERROR = 0xA0,/* 对应5.00, 服务器内部错误 */
} iotx_coap_resp_code_t;