Zephyr连入阿里云物联网平台--使用
本文说明如何使用移植在zephyr上使用Link Kit SDK开发物联网应用
在移植一文中说明了如何将阿里云的link kit sdk移植到zephyr,这里我们更进一步使用link kit sdk在zephyr开发一个应用,用于发布本地的温度和湿度到阿里云,并订阅阿里云上收到的温度和湿度到本地。
云端 链接到标题
云端主要是增加功能定义,在阿里云物联网平台上点击"产品->功能定义",在自定义功能中"添加功能",如下图
点击添加功能后会弹出功能框,如下图
这里我添加了湿度和温度两个,类型,取值,步长都根据实际device来设置,标识符唯一标示功能的字符串,在device端会用到,如下图

设备端 链接到标题
设备端使用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,如图
对照加入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,如图
和上面代码自行对应不再详述
云端发布 链接到标题
点击Topic的发布消息,在弹出的对话框中发布数据,如图
发布成功后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的使用相关,就不再深入研究了。