使用示例

本文以C Link SDK中的Demo文件./demos/coap_basic_demo.c为例,介绍如何调用Link SDK的API,使用对称加密的方式,将CoAP协议的设备接入物联网平台并进行消息收发。

背景信息

CoAP接入的更多信息,请参见概述

步骤一:初始化

  1. 添加头文件。

    #include "aiot_coap_api.h"
    #include "aiot_state_api.h"
    #include "aiot_sysdep_api.h"
  2. 配置底层依赖和日志输出。

        aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile);
        aiot_state_set_logcb(demo_state_logcb);
  3. 调用aiot_coap_init,创建CoAP客户端实例,并初始化默认参数。

        coap_handle = aiot_coap_init();
        if (coap_handle == NULL) {
            printf("aiot_coap_init failed\n");
            return -1;
        }

步骤二:配置功能

调用aiot_coap_setopt,配置以下功能。

  1. 配置连接参数。

    • 示例代码:

       /* 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******

  2. 配置状态监控。

    1. 配置状态监控的回调函数。

      • 示例代码:

            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

        内部事件回调函数。

    2. 定义状态监控回调函数。

      在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;
          }
      }
    3. 定义消息的回调函数。

      在读取到网络报文时,触发回调函数,执行设置的处理。示例仅做打印处理,您在编写处理逻辑时,需考虑以下几点。

      • 应答报文的数据结构类型为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;
    }

后续步骤

  • 例程文件配置完成后,需进行编译,生成可执行文件./output/coap-basic-demo

    更多信息,请参见编译与运行

  • 关于运行结果的详细说明,请参见运行日志