本文以C Link SDK中的Demo文件./demos/coap_basic_demo.c
为例,介绍如何调用Link SDK的API,使用对称加密的方式,将CoAP协议的设备接入物联网平台并进行消息收发。
背景信息
CoAP接入的更多信息,请参见概述。
步骤一:初始化
添加头文件。
#include "aiot_coap_api.h" #include "aiot_state_api.h" #include "aiot_sysdep_api.h"
配置底层依赖和日志输出。
aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile); aiot_state_set_logcb(demo_state_logcb);
调用aiot_coap_init,创建CoAP客户端实例,并初始化默认参数。
coap_handle = aiot_coap_init(); if (coap_handle == NULL) { printf("aiot_coap_init failed\n"); return -1; }
步骤二:配置功能
调用aiot_coap_setopt,配置以下功能。
配置连接参数。
示例代码:
/* TODO: 替换为自己设备的设备证书和接入地址 */ char *product_key = "${YourProductKey}"; char *device_name = "${YourDeviceName}"; char *device_secret = "${YourDeviceSecret}"; char *host = "${YourInstanceId}.coap.iothub.aliyuncs.com"; /* DTLS加密端口为5684,应用层对称加密端口为5682 */ uint16_t port = 5682; …… …… /* 配置连接的服务器地址 */ aiot_coap_setopt(coap_handle, AIOT_COAPOPT_HOST, host); /* 配置连接的服务器端口 */ aiot_coap_setopt(coap_handle, AIOT_COAPOPT_PORT, &port); /* 配置设备productKey */ aiot_coap_setopt(coap_handle, AIOT_COAPOPT_PRODUCT_KEY, (void *)product_key); /* 配置设备deviceName */ aiot_coap_setopt(coap_handle, AIOT_COAPOPT_DEVICE_NAME, (void *)device_name); /* 配置设备deviceSecret */ aiot_coap_setopt(coap_handle, AIOT_COAPOPT_DEVICE_SECRET, (void *)device_secret);
相关参数:
参数
示例
说明
host
iot-06z00ax1o******.coap.iothub.aliyuncs.com
设备的接入域名。
企业版实例和新版公共实例:在实例详情页面的开发配置面板,查看接入域名。
旧版公共实例:接入域名格式为
coap.
${YourRegionId}
.link.aliyuncs.com
。
新旧版公共实例和企业版实例、以及接入域名的更多信息,请参见查看实例终端节点。
product_key
a18wP******
设备认证信息。更多信息,请参见获取设备认证信息。
本例程的身份认证方式为一机一密。
device_name
LightSwitch
device_secret
uwMTmVAMnGGHaAkqmeDY6cHxxB******
配置状态监控。
配置状态监控的回调函数。
示例代码:
aiot_coap_setopt(coap_handle, AIOT_COAPOPT_RECV_HANDLER, demo_coap_recv_handler); aiot_coap_setopt(coap_handle, AIOT_COAPOPT_EVENT_HANDLER, demo_coap_event_handler);
相关参数:
配置项
示例值
说明
AIOT_COAPOPT_RECV_HANDLER
demo_coap_recv_handler
接收消息回调函数。
AIOT_COAPOPT_EVENT_HANDLER
demo_coap_event_handler
内部事件回调函数。
定义状态监控回调函数。
在Token变化时,触发回调函数,设置执行操作。在编写回调函数的处理时,您需考虑以下几点。
状态监控的数据结构类型为aiot_coap_event_t。
状态监控的消息类型包括:
AIOT_COAPEVT_AUTH_TOKEN_RECEIVED:当获取到连接物联网平台所需的auth_token时,触发回调函数。
AIOT_COAPEVT_AUTH_TOKEN_EXPIRED:当auth_token过期时,触发回调函数。
说明auth_token的有效期为7天。
void demo_coap_event_handler(void *handle, aiot_coap_event_t *event, void *userdata) { switch (event->type) { /* 设备收到auth token */ case AIOT_COAPEVT_AUTH_TOKEN_RECEIVED: { printf("event: auth token received\n"); } break; case AIOT_COAPEVT_AUTH_TOKEN_EXPIRED: { printf("event: auth token expired\n"); /* TODO: 您需要重新调用aiot_coap_auth以获取auth token */ } break; default: break; } }
定义消息的回调函数。
在读取到网络报文时,触发回调函数,执行设置的处理。示例仅做打印处理,您在编写处理逻辑时,需考虑以下几点。
应答报文的数据结构类型为aiot_coap_recv_t。
应答报文消息的类型为AIOT_COAPRECV_RESPONSE。
根据业务需要,处理状态码。状态码的更多信息,请参见CoAP连接通信。
void demo_coap_recv_handler(void *handle, const aiot_coap_recv_t *packet, void *userdata) { switch (packet->type) { case AIOT_COAPRECV_RESPONSE: { /* TODO: 以下代码如果不被注释, SDK收到COAP报文时, 会通过这个用户回调打印COAP报文的code, token 以及payload */ /* printf("rx code: 0x%x, token: 0x%04x \r\n", packet->data.rsp_code, packet->data.msg_token); if (0 != packet->data.payload_len) { printf("response: %.*s\r\n", packet->data.payload_len, (char *)packet->data.payload); } */ } break; default: break; } }
步骤三:请求连接
调用aiot_coap_auth,向物联网平台CoAP服务器,发送身份认证请求,获取Token。
res = aiot_coap_auth(coap_handle);
if (res < 0) {
printf("auth error,: -0x%04X\n", -res);
aiot_coap_deinit(&coap_handle);
return -1;
}
步骤四:发送消息
调用aiot_coap_send,在demo_coap_post_lightswitch
中,向指定Topic发送消息。
编写代码时,需注意:
发送消息的数据类型为aiot_coap_request_t,是aiot_coap_send的入参。
消息的类型为AIOT_COAP_MSG_TYPE_CON。
示例代码及其参数说明如下:
示例代码:
/* 用COAP通道上报业务数据给云平台, 例如:灯已关闭 */ int32_t demo_coap_post_lightswitch(void *handle, const char *product_key, const char *device_name) { int32_t res; char demo_request_uri[200] = {0}; snprintf(demo_request_uri, 200, "%s%s%s%s%s", "/topic/sys/", product_key, "/", device_name, "/thing/event/property/post"); const char *demo_request_payload = "{\"id\":\"1\",\"version\":\"1.0\",\"params\":{\"LightSwitch\":0}}"; uint32_t req_token = 0; /* 定义一个请求 */ aiot_coap_request_t req = { .payload = (uint8_t *)demo_request_payload, .msg_type = AIOT_COAP_MSG_TYPE_CON, /* 上行的数据格式为json */ .content_format = AIOT_COAP_CT_APP_JSON, .msg_token = &req_token }; /* 用COAP通道向云平台上报1条业务数据, 接口是aiot_coap_send() */ res = aiot_coap_send(handle, demo_request_uri, &req); if (res < 0) { printf("aiot_coap_send res = -0x%04X\r\n", -res); return res; }
相关参数:
示例
说明
"/topic/sys/", product_key, "/", device_name, "/thing/event/property/post");
上报消息的Topic,需具备发布权限。
示例代码为物模型Topic。
关于Topic的更多信息,请参见什么是Topic。
{\"id\":\"1\",\"version\":\"1.0\",\"params\":{\"LightSwitch\":0}}
上报消息的payload。
步骤五:接收应答
消息发送后,物联网平台返回应答报文。设备端调用aiot_coap_recv接收CoAP应答数据,根据事件回调函数,执行对应处理。
res = aiot_coap_recv(handle);
if (res == 0) {
/* 成功接收到服务器应答, 且业务应答码为=0, 说明数据上报成功 */
return 0;
} else {
printf("aiot_coap_recv res = -0x%04X\r\n", -res);
return -1;
}
}
步骤六:请求下行消息
调用aiot_coap_request_message,向云平台请求下行的消息。
/* 主动拉消息示例, 需要用户调用云端pub发布消息,设备才能收到下行消息 */
msg_id = aiot_coap_request_message(coap_handle, 1);
···
步骤七:接收应答
消息发送后,物联网平台返回应答报文。设备端调用aiot_coap_recv接收CoAP应答数据,根据事件回调函数,执行对应处理。
res = aiot_coap_recv(handle);
if (res == 0) {
/* 成功接收到服务器应答, 且业务应答码为=0, 说明数据上报成功 */
return 0;
} else {
printf("aiot_coap_recv res = -0x%04X\r\n", -res);
return -1;
}
}
步骤八:退出程序
调用aiot_coap_deinit,销毁客户端实例,释放资源。
res = aiot_coap_deinit(&coap_handle);
if (res < STATE_SUCCESS) {
printf("aiot_coap_deinit failed: -0x%04X\n", -res);
return -1;
}