HTTP通信方式适合单纯的数据上报的场景,本文讲解设备如何通过HTTP/S上报消息到物联网平台。

背景信息

使用HTTP与物联网平台通信的示意图如下所示:

HTTP连接示意图

HTTP/S接入说明

目前, 仅中国(上海、深圳)地域支持HTTP通信数据上报。HTTP服务器地址为 https://iot-as-http.cn-shanghai.aliyuncs.com(上海)、https://iot-as-http.cn-shenzhen.aliyuncs.com(深圳)。

本Topic规范和MQTT的Topic规范一致。

  • 上报数据请求: https://iot-as-http.cn-shanghai.aliyuncs.com/topic/${topic}
  • Topic变量${topic}的值可以与MQTT连接通信的Topic相复用。
  • 不支持以?query_String=xxx格式传参。
注意
  • 数据上行接口传输的数据大小限制为128 KB
  • HTTP请求只支持POST方式。
  • 设备认证请求的HTTP header中的Content-Type必须为application/json
  • 数据上报请求的HTTP header中的Content-Type必须为application/octet-stream
  • 设备认证返回的token会在一定周期后失效(目前token有效期是7天), SDK遇到token失效, 需要用户重新获取。
  • 目前不支持从物联网平台主动向设备发送数据,因此如果用户的云端应用需要主动发送命令给设备,请使用MQTT连接设备。

API列表

以下是完整的HTTP上报部分API列表及简要说明(详见core/aiot_http_api.h)。

接口名 说明
aiot_http_init 创建一个HTTP上云实例并设置默认参数。
aiot_http_setopt 设置HTTP实例选项,详见HTTP设置参数说明
aiot_http_auth 向服务器发送身份认证请求,获取token。
aiot_http_send 上报数据到物联网平台。
aiot_http_recv 接受HTTP应答数据,将应答数据保存到用户缓冲区中。
aiot_http_deinit 销毁参数所指定的HTTP实例, 回收资源。

例程讲解

  1. 进入程序入口,给SDK配置全局的底层依赖和日志回调

    底层依赖描述了硬件平台的资源使用方式,比如怎样获取时钟,分配内存等。日志回调是用户的函数,SDK有log输出的时候会进入这个函数。

    int main(int argc, char *argv[])
    {
        ...
        ...
        /* 配置SDK的底层依赖 */
        aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile);
        /* 配置SDK的日志输出 */
        aiot_state_set_logcb(demo_state_logcb);
  2. 给HTTP上报配置连接参数

    这些连接参数包括如何建立TLS连接、服务器地址在哪、连接时的设备证书是什么、连接后的数据及事件回调函数是什么等等。

    /* 创建1个HTTP客户端实例并内部初始化默认参数 */
        http_handle = aiot_http_init();
        /* 配置设备安全凭证 */
        aiot_http_setopt(http_handle, AIOT_HTTPOPT_NETWORK_CRED, &cred);
        /* 配置设备设备证书 */
        aiot_http_setopt(http_handle, AIOT_HTTPOPT_PRODUCT_KEY, PRODUCT_KEY);
        aiot_http_setopt(http_handle, AIOT_HTTPOPT_DEVICE_NAME, DEVICE_NAME);
        aiot_http_setopt(http_handle, AIOT_HTTPOPT_DEVICE_SECRET, DEVICE_SECRET);
        ...
        ...
  3. 向服务器发起连接

    使用aiot_http_auth()接口,以上面设置的连接参数,向HTTP服务器发起身份认证请求。

    /* 设备认证, 获取token */
        res = aiot_http_auth(http_handle);
        if (res == 0) {
            printf("aiot_http_auth succeed\r\n");
        } else {
            /* 如果认证失败, 就销毁实例, 回收资源, 结束程序退出 */
            printf("aiot_http_auth failed, res = -0x%04x\r\n", -res);
            aiot_http_deinit(&http_handle);
            return -1;
        }
  4. 认证成功后, 可尝试上报1条业务消息

    将演示函数demo_http_post_lightswitch()中的注释去掉,它会上报1条业务消息。

    /* TODO: 以下代码如果不被注释, 会演示上报 1 次数据到物联网平台 */
        demo_http_post_lightswitch(http_handle);
  5. 上报这1条业务消息的日志

    以下文本是由SDK传出,在demo_state_logcb()中打印,若需关闭可筛选入参code0x040B的情况。

    [1578127395.533][LK-0409] > POST /topic/sys/a13FNXXXXXX/http_basic_demo/thing/event/property/post HTTP/1.1
    [1578127395.533][LK-0409] > Host: iot-as-http.cn-shanghai.aliyuncs.com
    [1578127395.544][LK-0409] > Content-Type: application/octet-stream
    [1578127395.544][LK-0409] > Password: f40aab6d66bf4d5bbccdcb9308XXXXXX
    [1578127395.544][LK-0409] > Content-Length: 53
    [1578127395.544][LK-0409] >
    
    [LK-040A] > 7B 22 69 64 22 3A 22 31  22 2C 22 76 65 72 73 69 | {"id":"1","versi
    [LK-040A] > 6F 6E 22 3A 22 31 2E 30  22 2C 22 70 61 72 61 6D | on":"1.0","param
    [LK-040A] > 73 22 3A 7B 22 4C 69 67  68 74 53 77 69 74 63 68 | s":{"LightSwitch
    [LK-040A] > 22 3A 30 7D 7D                                   | ":0}}
  6. 云平台接收到这1条业务消息后的回应

    以下文本是由SDK传出,在demo_state_logcb()中打印,若需关闭可筛选入参code0x040B的情况。

    [1578127395.611][LK-040B] < HTTP/1.1 200
    [1578127395.611][LK-040B] < Date: Sat, 04 Jan 2020 08:43:15 GMT
    [1578127395.611][LK-040B] < Content-Type: application/json
    [1578127395.611][LK-040B] < Content-Length: 71
    [1578127395.611][LK-040B] < Connection: keep-alive
    [1578127395.611][LK-040B] < Server: Tengine
    [1578127395.611][LK-040B] < EagleEye-TraceId: 0bc16ebc15781273955947236e3e2b
    [1578127395.611][LK-040B] < Strict-Transport-Security: max-age=0
    [1578127395.611][LK-040B] < Timing-Allow-Origin: *
    [1578127395.611][LK-040B] <
  7. 最后销毁实例,回收资源,退出演示程序

    HTTP上报不是长连接协议,保持客户端连接也无法接收服务端的消息,所以例程无论是否上报,接下来都会正常结束。

    /* 销毁HTTP实例 */
        aiot_http_deinit(&http_handle);
        printf("program exit as normal return\r\n");
        printf("\r\n");
    
        return 0;
    }