Zephyr连入阿里云物联网平台--使用

本文说明如何使用移植在zephyr上使用Link Kit SDK开发物联网应用

移植一文中说明了如何将阿里云的link kit sdk移植到zephyr,这里我们更进一步使用link kit sdk在zephyr开发一个应用,用于发布本地的温度和湿度到阿里云,并订阅阿里云上收到的温度和湿度到本地。

云端 链接到标题

云端主要是增加功能定义,在阿里云物联网平台上点击"产品->功能定义",在自定义功能中"添加功能",如下图 add 点击添加功能后会弹出功能框,如下图 addmenu 这里我添加了湿度和温度两个,类型,取值,步长都根据实际device来设置,标识符唯一标示功能的字符串,在device端会用到,如下图 t h

设备端 链接到标题

设备端使用Zephyr的驱动获取温湿度,再通过阿里云SDK将温湿度送到云端

主程序 链接到标题

void main(void)
{    
    int                     res = 0;
    int                     loop_cnt = 0;
    iotx_mqtt_param_t       mqtt_params;

    //获取DHT11的device handle,方便之后从DHT11读取温湿度
	struct device *dev = device_get_binding("DHT11"); 
	printk("dev %p name %s\n", dev, dev->config->name);
	
    //因为使用的是ethernet连入网络,因此初始化ethernet
    struct net_if *iface = net_if_get_default();
    ethernet_init(iface);

    //读取连入阿里云的鉴权信息
    HAL_GetProductKey(DEMO_PRODUCT_KEY);
    HAL_GetDeviceName(DEMO_DEVICE_NAME);
    HAL_GetDeviceSecret(DEMO_DEVICE_SECRET);

    EXAMPLE_TRACE("mqtt example");

    //可以根据实际情况设置iotx_mqtt_param_t,这里只设置
    memset(&mqtt_params, 0x0, sizeof(mqtt_params));   
    mqtt_params.handle_event.h_fp = example_event_handle;

     //  初始化MQTT
    pclient = IOT_MQTT_Construct(&mqtt_params);
    if (NULL == pclient) {
        EXAMPLE_TRACE("MQTT construct failed");
        return -1;
    }

    //订阅信息
    res = example_subscribe(pclient);
    if (res < 0) {
        IOT_MQTT_Destroy(&pclient);
        return -1;
    }

    //每40s获取一次本地温湿度并发布到云端
    while (1) {
        if (0 == loop_cnt % 200) {
            sensor_sample_fetch(dev);								  //从dh11读取数据
            sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &temp); //读取温度
            sensor_channel_get(dev, SENSOR_CHAN_HUMIDITY, &humidity); //读取湿度
            example_publish(pclient);       //发布
        }

        IOT_MQTT_Yield(pclient, 200);

        loop_cnt += 1;
    }

    return 0;
}

发布 链接到标题

注意其payload,已json数据的形式将温度和湿度通过IOT_MQTT_Publish_Simple发送到云端

int example_publish(void *handle)
{
    int             res = 0;

    //Topic模板
    const char *fmt = "/sys/%s/%s/thing/event/property/post";
    char *topic = NULL;
    int  topic_len = 0;

    //Payload模板
    char *payload = "{\
                                         \"id\": %d,\
                                        \"params\": {\
                                                                    \"TargetTemperature\": %d,\
                                                                    \"Humidity\": %d\
                                                                },\
                                        \"method\": \"thing.event.property.post\"}";

    topic_len = strlen(fmt) + strlen(DEMO_PRODUCT_KEY) + strlen(DEMO_DEVICE_NAME) + 1;
    topic = HAL_Malloc(topic_len);
    if (topic == NULL) {
        EXAMPLE_TRACE("memory not enough");
        return -1;
    }
    memset(topic, 0, topic_len);
    //准备topic数据
    HAL_Snprintf(topic, topic_len, fmt, DEMO_PRODUCT_KEY, DEMO_DEVICE_NAME);


    memset(acPayload, 0, 128);
    //准备payload数据,温度,湿度
    HAL_Snprintf(acPayload, 128, payload, idnumber++, temp.val1, humidity.val1);

    EXAMPLE_TRACE("Topic %s\n", topic);
    EXAMPLE_TRACE("Payload %s\n", acPayload);

    //
    res = IOT_MQTT_Publish_Simple(0, topic, IOTX_MQTT_QOS0, acPayload, strlen(acPayload));
    if (res < 0) {
        EXAMPLE_TRACE("publish failed, res = %d", res);
        HAL_Free(topic);
        return -1;
    }

    HAL_Free(topic);
    return 0;
}

topic 链接到标题

使用云端已定义好的topic,如图 POST 对照加入topic模板,其中字符串分别对应的是product key和device name

const char *fmt = "/sys/%s/%s/thing/event/property/post";
HAL_Snprintf(topic, topic_len, fmt, DEMO_PRODUCT_KEY, DEMO_DEVICE_NAME);

Payload 链接到标题

这里将报温度和湿度已Json格式上报 模板如下:

char *payload = "{\
\"id\": %d,\
\"params\": {\
\"TargetTemperature\": %d,\
\"Humidity\": %d\
},\
\"method\": \"thing.event.property.post\"}";

对应的value可根据情况定义,代码中是顺序增加的. 温度和湿度的key从前面提到的在云端的“标识符”来,对应的value就是想要上报的温度和湿度 method将topic的device name的string对应转换而来,thing/event/property/post -> thing.event.property.post 这点必须匹配,否则上报数据会出错 实例:

"id": 1,"params": {"TargetTemperature": 29,"Humidity": 29},"method": "thing.event.property.post"}

云端显示的示例在概览一文有贴出,这里贴出一下device端的log

uart:~$ publish
example_publish|116 :: Topic /sys/a10Bd3A14DDC/4Z3Oeud7Sh5cod49oo2U/thing/event/property/post

example_publish|117 :: Payload {"id": 1,"params": {"TargetTemperature": 29,"Humidity": 29},"method": "thing.event.property.post"}


> {
>     "id":  1,
>     "params":  {
>         "TargetTemperature":  29,
>         "Humidity":  29
>     },
>     "method":  "thing.event.property.post"
> }

订阅 链接到标题

device订阅也很简单,下面代码示例订阅user/get topic内容,当收到云端发布的信息后,将数据打印出来

void example_message_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
{
    iotx_mqtt_topic_info_t *topic_info = (iotx_mqtt_topic_info_pt) msg->msg;

    switch (msg->event_type) {
        case IOTX_MQTT_EVENT_PUBLISH_RECEIVED:
            /* print topic name and topic message */
            EXAMPLE_TRACE("Message Arrived:");
            EXAMPLE_TRACE("Topic  : %.*s", topic_info->topic_len, topic_info->ptopic);
            EXAMPLE_TRACE("Payload: %.*s", topic_info->payload_len, topic_info->payload);
            EXAMPLE_TRACE("\n");
            break;
        default:
            break;
    }
}

int example_subscribe(void *handle)
{
    int res = -1;
    const char *fmt = "/%s/%s/user/get";
    char *topic = NULL;
    int topic_len = 0;

    topic_len = strlen(fmt) + strlen(DEMO_PRODUCT_KEY) + strlen(DEMO_DEVICE_NAME) + 1;
    topic = HAL_Malloc(topic_len);
    if (topic == NULL) {
        EXAMPLE_TRACE("memory not enough");
        return -1;
    }
    memset(topic, 0, topic_len);
    HAL_Snprintf(topic, topic_len, fmt, DEMO_PRODUCT_KEY, DEMO_DEVICE_NAME);

    //订阅信息
    res = IOT_MQTT_Subscribe(handle, topic, IOTX_MQTT_QOS0, example_message_arrive, NULL);
    if (res < 0) {
        EXAMPLE_TRACE("subscribe failed");
        HAL_Free(topic);
        return -1;
    }

    HAL_Free(topic);
    return 0;
}

topic 链接到标题

使用云端已定义好的topic,如图 get 和上面代码自行对应不再详述

云端发布 链接到标题

点击Topic的发布消息,在弹出的对话框中发布数据,如图 Send 发布成功后device端可以收到数据,log如下

example_event_handle|132 :: msg->event_type : 12
example_message_arrive|052 :: Message Arrived:
example_message_arrive|053 :: Topic  : /a10Bd3AmDDC/4Z0Oeud7Sh4cod49oo2U/user/get
example_message_arrive|054 :: Payload: Hello half coder!!
example_message_arrive|055 ::

其它 链接到标题

测试过程中有zephyr网络用一会就不通的情况,原因是NET_PKG和BUF给小了,增大即可

CONFIG_NET_PKT_RX_COUNT=34
CONFIG_NET_PKT_TX_COUNT=34
CONFIG_NET_BUF_RX_COUNT=34
CONFIG_NET_BUF_TX_COUNT=34

后记 链接到标题

终于将zephyr接入阿里云收尾,主要是将云端和device串起来并了解zephyr上使用阿里云物联网SDK, 更深入的内容是MQTT/阿里云物联网SDK的使用相关,就不再深入研究了。

参考 链接到标题

https://code.aliyun.com/edward.yangx/public-docs/wikis/user-guide/linkkit/Quick_Start#%E4%BB%A5MQTT%20Topic%E7%BC%96%E7%A8%8B%E6%96%B9%E5%BC%8F%E6%8E%A5%E5%85%A5%E8%AE%BE%E5%A4%87