当前位置: 首页 > 文档资料 > YoC 编程基础 >

阿里云 MQTT 传感数据上云例程

优质
小牛编辑
117浏览
2023-12-01

本文介绍如何使用YoC的IoT框架,实现上传数据到阿里云。

本例程可以运行在CB2201开发板上。

本章节介绍了数据上云例程的开发流程,包括应用初始化、网络初始化、模拟传感器、上云通道初始化及其相关事件的处理。

3.1 应用初始化

应用入口函数为app_main,主要实现了网络驱动初始化、传感驱动初始化、上云通道初始化、系统事件和通道事件的订阅等。

void main()
{
    /* 板级初始化 */
    board_yoc_init();

    /* 模拟传感器驱动注册 */
    sensor_simulate_register(NULL, 0);

    /* LED驱动注册 */
    led_rgb_register(&led_config, 1);
    led_set_status(LED_ON);

    /* 订阅网络事件 */
    event_subscribe(EVENT_NETMGR_GOT_IP, network_event, NULL);
    event_subscribe(EVENT_NETMGR_NET_DISCON, network_event, NULL);

    /* 订阅应用自定义事件 */
    event_subscribe(EVENT_DATA_REPORT, user_local_event_cb, NULL);
    event_subscribe(EVENT_CHANNEL_CHECK, user_local_event_cb, NULL);
    event_subscribe(EVENT_CHANNEL_CLOSE, user_local_event_cb, NULL);

    /* 订阅上云通道事件 */
    event_subscribe(EVENT_IOT_CONNECT_SUCCESS, iot_event, NULL);
    event_subscribe(EVENT_IOT_CONNECT_FAILED, iot_event, NULL);
    event_subscribe(EVENT_IOT_DISCONNECTED, iot_event, NULL);
    event_subscribe(EVENT_IOT_PUSH_SUCCESS, iot_event, NULL);
    event_subscribe(EVENT_IOT_PUSH_FAILED, iot_event, NULL);

    /* 启动定时上云定时器 */
    event_publish_delay(EVENT_DATA_REPORT, NULL, DATA_PUSH_INTERVAL);

    /* 阿里云MQTT通道初始化 */
    iot_alimqtt_config_t cfg = {.server_url_suffix =
                                    "iot-as-mqtt.cn-shanghai.aliyuncs.com:1883"};
    iot_handle = iot_new_alimqtt(&cfg);
}

3.2 板级初始化

板级初始化的入口为board_yoc_init,主要完成硬件初始化以及OS组件的初始化,由app_main函数调用。

void board_yoc_init(void)
{
    /* 初始化console驱动 */
#ifdef CONSOLE_ID
    console_init(CONSOLE_ID, 115200, 128);
#else
    console_init(0, 115200, 128);
#endif

    /* 初始化出厂配置Flash分区 */
    nvram_init("factory");

    /* 创建CLI任务 */
    utask_t *task = utask_new("at&cli", 2 * 1024, QUEUE_MSG_COUNT, AOS_DEFAULT_APP_PRI);

#if defined(CONFIG_AT) && CONFIG_AT
    at_server_init(task);
#endif

    /* CLI初始化及系统命令注册 */
    board_cli_init(task);

    /* 网络驱动初始化 */
    network_init();
}

3.3 网络驱动初始化

网络初始化的入口为network_init,主要完成网络设备和网络管理模块的初始化,由board_yoc_init函数调用。

static void network_init(void)
{
    esp_wifi_param_t esp_param;

    /* 与ESP8266模组通讯的串口参数配置 */
    esp_param.device_name    = "uart2";
    esp_param.baud           = 115200;
    esp_param.buf_size       = 4096;
    esp_param.enable_flowctl = 0; 

    /* 复位引脚配置 */
    esp_param.reset_pin      = WIFI_ESP8266_RESET;
    esp_param.smartcfg_pin   = WIFI_ESP8266_SMARTCFG;

    /* 注册esp8266驱动 */
    wifi_esp8266_register(NULL, &esp_param);

    /* 初始化网络管理模块 */
    app_netmgr_hdl = netmgr_dev_wifi_init();
    if (app_netmgr_hdl) {
        netmgr_service_init(NULL);
        netmgr_start(app_netmgr_hdl);
    }
}

3.4 获取传感数据

注册传感器驱动后,应用可以调用传感器API来获取数据。以下是读取传感器的代码,实现在sensor_data.c中。

static void get_sensor_value(char *name)
{
    dev_t *sensor_dev;
    sensor_dht11_t sval;
    int ret, i;

    g_humi_value = -1000;
    g_temp_value = -1000;

    /* 打开传感器设备 */
    sensor_dev = sensor_open(name);
    if (sensor_dev == NULL) {
        LOGE(TAG, "no %s driver", name);
        return;
    }

    /* 采集数据 */
    sensor_fetch(sensor_dev);

    /* 读取传感器数据 */
    if (sensor_getvalue(sensor_dev, (void *)&sval, sizeof(sensor_dht11_t)) < 0) {
        sensor_close(sensor_dev);
        return;
    }

    /* 关闭设备 */
    sensor_close(sensor_dev);

    g_temp_value = sval.degree / 10;
    g_humi_value = sval.rh / 10;

}

3.6 数据上云

3.6.1 上云流程介绍

  • uDATA 存储传感器采集的各种数据,接收云端下发的数据,采用的键值形式来保存数据对

  • IoT框架 整合各个平台的SDK,定义了数据处理及上云接口,规范不同的云平台,抽象为统一的操作流程,采用一致的编程习惯,降低用户使用不同平台的学习成本

  • 主要流程包含如下步骤:初始化上云通道、网络事件处理、初始化uDATA,启动上云通道、数据处理、关闭IoT

3.6.2 初始化上云通道

上云通道创建及事件订阅的具体示例代码参见“应用初始化”章节。

3.6.3 处理网络、云通道事件

static void iot_event(uint32_t event_id, const void *param, void *context)
{
    switch (event_id) {
        case EVENT_IOT_CONNECT_SUCCESS:
            /* 通道连接成功 */
            LOGD(TAG, "CONNNECT SUCCESS");
            g_iot_connected = 1;
            break;

        case EVENT_IOT_CONNECT_FAILED:
        case EVENT_IOT_DISCONNECTED:
            /* 连接失败或者断开连接需要关闭通道*/
            channel_close();
            break;

        case EVENT_IOT_PUSH_SUCCESS:
            /* 数据上传成功 */
            LOGD(TAG, "PUSH_SUCCESS");
            break;

        case EVENT_IOT_PUSH_FAILED:
            /* 数据上传失败 */
            LOGD(TAG, "PUSH_FAILED");
            break;

        default:;
    }
}

static void network_event(uint32_t event_id, const void *param, void *context)
{
    switch(event_id) {
    case EVENT_NETMGR_GOT_IP:
        /* 网络连接成功,启动上云通道 */
        LOGD(TAG, "EVENT_NETMGR_GOT_IP");
        if (g_iot_connected == 0) {
            channel_open();
        }
        break;
    case EVENT_NETMGR_NET_DISCON:
       /* 网络断开,关闭上云通道 */
        channel_close();
        g_iot_connected = 0;
        break;
    }
}

3.6.4 初始化uDATA,启动上云通道

static void init_channel_udata(uData *udata)
{
    /* 温度节点初始化 */
    yoc_udata_set(udata, value_s("temp"), value_i(0), 1);

    /* 湿度节点初始化 */
    yoc_udata_set(udata, value_s("humi"), value_i(0), 1);

    yoc_udata_set(udata, value_s("deviceName"), value_s(aos_get_device_name()), 1);
}

static int channel_open(void)
{
    /* 打开云通道 */
    iot_ch_post = iot_channel_open(iot_handle, "thing/event/property/post,thing/service/property/set");
    if (iot_ch_post == NULL) {
        LOGE(TAG, "iot ch open");
        return -1;
    }

    /* 配置通道发送和接收是的回调处理 */
    iot_channel_config(iot_ch_post, channel_set, channel_get, NULL);

    /* 初始化节点数据 */
    init_channel_udata(iot_ch_post->uData);

    /* 启动云通道 */
    iot_channel_start(iot_ch_post);

    return 0;
}

3.6.5 接收到云端数据

static void channel_set(uData *udata, void *arg)
{
    uData *node;
    /* 遍历所有数据节点,使用node->value.updated判断更新的数据 */
    slist_for_each_entry(&udata->head, node, uData, head)
    {
        if (node->value.updated) {
            if (node->value.type == TYPE_STR) {
                LOGI(TAG, "ch set s (%s,%s)", node->key.v_str, node->value.v_str);
            } else {
                LOGI(TAG, "ch set i (%s,%d)", node->key.v_str, node->value.v_int);
            }
        }
    }
}

3.6.6 发送数据


static void channel_get(uData *udata, void *arg)
{
    int temp = 0, humi = 0;

    /* 获取传感器数据 */
    temperature_capture(SENSOR_NAME, &temp, 0);
    humidity_capture(SENSOR_NAME, &humi, 0);

    /* 同步数据到uData节点 */
    yoc_udata_set(udata, value_s("temp"), value_i(temp), 1);
    yoc_udata_set(udata, value_s("humi"), value_i(humi), 1);
    yoc_udata_set(udata, value_s("led"), value_i(g_led_status), 1);
    yoc_udata_set(udata, value_s("deviceName"), value_s(aos_get_device_name()), 1);
}

static void push_action(void)
{
    /* 发送数据 */
    if (iot_channel_push(iot_ch_post, 1) != 0) {
        LOGE(TAG, "push err");
    }
}

static void user_local_event_cb(uint32_t event_id, const void *param, void *context)
{
    /* 使用自定义消息的延时处理,实现定时发送功能 */
    if (event_id == EVENT_DATA_REPORT){
        /* 发送数据 */
        push_action();

        /* 延时事件,准备下一次的数据上传 */
        event_publish_delay(EVENT_DATA_REPORT, NULL, DATA_PUSH_INTERVAL); 
    }
}

例程运行前需要进行云端配置、获取许可证和上云参数并配置到设备端。 若开发板已经预置好参数,编译烧写完成后,直接转到4.2.4章节。

4.1 阿里云物联网配置

4.1.1 登录(注册)

登录阿里云物联网平台控制台,参考阿里云物联网平台帮助

4.1.2 创建产品

使用物联网平台的第一步是在云端创建产品和对应设备,获取设备证书(ProductKey、DeviceName和DeviceSecret)

  • 实例概览页,找到已创建的公共实例或企业版实例,单击实例名称。

    img

  • 在左侧导航栏,选择设备管理 > 产品,单击创建产品img 具体产品参数可参考创建产品和设备

4.1.3 上云配置

  • 获取三要素

    设备详情中可以查看、复制设备证书信息。设备证书由设备的ProductKey、DeviceName和DeviceSecret组成,是设备与物联网平台进行通信的重要身份认证,建议您妥善保管,在接下来的设备配置中需要用到。 img

参数说明
ProductKey设备所隶属产品的Key,即物联网平台为产品颁发的全局唯一标识符。
DeviceName设备在产品内的唯一标识符。DeviceName与设备所属产品的ProductKey组合,作为设备标识,用来与物联网平台进行连接认证和通信。
DeviceSecret物联网平台为设备颁发的设备密钥,用于认证加密。需与DeviceName成对使用。

  • 获取许可证 我的产品->编辑->许可证,点击下载后即可产生下载压缩包到本地
    img

4.2 设备端配置

4.2.1 烧录许可证

解压后文件中,pieces/*.hex文件是用于烧录的许可证文件。
右键点击工程名->Open Flash Programmer->YoC-CB2201-KP打开FlashProgrammer,点击Browse按钮选择下载到的许可证文件,点击Start开始烧录。烧录完成,按开发板复位键。

4.2.2 编译烧录例程

烧录完成后,按复位键重启

4.2.3 配置上云三要素

将4.1.3中获取到的三要素,使用factory setali命令通过串口调试终端设置到设备,返回setali success完成上云三要素的配置, 在串口中输入信息为:

factory setali PRODUCTKEY DEVICENAME DEVICESECRET

注:需要将PRODUCTKEY DEVICENAME DEVICESECRET更换为具体的内容

4.2.4 配置网络

如ssid名称为Test01,password名称为test1234,在串口中输入信息为:

  kv set wifi_ssid Test01
  kv set wifi_psk test1234

设置完成之后需要按复位按钮重启开发板使得新网络配置生效。 待调试终端打印[I][netmgr ]IP: XXX.XXX.XXX.XXX的信息表示网络已经连接成功。

4.2.5 设备调试串口输出

网络配置成功后,程序会自动启动数据上云
串口调试终端输出如下结果,表示模拟传感器数据上云成功
img

4.3 云端数据展示

在左侧导航栏,单击监控运维 > 日志服务,进入云端运行日志页签,展示如下,点击查看更多日志功能

img img