使用RT-Thread通过MQTT连接华为物联网平台实验

硬件环境:

(1)开发板:ST官方的stm32wb55-st-nucleo开发板

(2)wifi模块:esp8266

(3)温湿度传感器:DHT22

(4)单色oled屏:主控ssd1306,分辨率126x64

软件环境:

(1)开发环境:Keil MDK v5.29

(2)RTOS:RT-Thread 4.0.3

实现目标:将温度、湿度数据上报到华为云物联网平台。

 

一、准备工作

(1)安装ENV工具,参见官方文档《Env 用户手册》:

https://www.rt-thread.org/document/site/#

(2)安装git下载最新的rt-thread源码,可到github或码云gitee上下载:

git clone https://gitee.com/rtthread/rt-thread.git

(3)查看rt-thread源码的bsp文件夹内已经适配了stm32wb55-st-nucleo开发板,进入“...\rt-thread\bsp\stm32\stm32wb55-st-nucleo”,打开env运行scons --dist将工程抽离成独立工程(看个人习惯,喜欢一个项目一个工程文件夹就抽离一下)。

(4)先对工程文件进行编译,看看有没有错误,理论上官方默认状态是无错误的。打开env再运行:

        pkgs --upgrade

        pkgs --update

        scons --target=mdk5

然后用keil打开工程,编译0错误,0警告。准备工作完成。

二、获取需要的软件包

   rt-thread提供非常多的软件包,主要任务就是怎么把软件包利用起来。本次操作需要的软件包:DHT22驱动、ESP8266驱动、MQTT软件包、json软件包,另外把oled屏驱动添加到工程。

1. 添加DHT22驱动

(1)DHT22与开发板连接,电源、地、数据就三根线,数据线我连接到开发板的GPIOB 9引脚上,需要查找一下GPIOB 9在rt-thread系统内对应的引脚号(打开drv_gpio.c文件,看到引脚列表pins[]可见对应编号为25),后面需要配置到menuconfig内。(注意:新版驱动去掉了pins[]列表,暂时不知道去哪里查找引脚对应的编号,可能需要在代码内使用GET_PIN(B,9)获取了

(2)添加DHTxx驱动软件包,工程目录内打开env,执行menuconfig,开启软件包和例程,版本选择最新,引脚号配置为25:

2. 添加oled显示屏驱动

(1)在工程目录内建立user_add_files文件夹,将后期用户代码都放在这个文件夹内。并在user_add_files文件夹内新建SConscript文件,内容如下(目的是scons时自动添加文件夹内的所有文件到工程):

import os
from building import *
objs = []
cwd  = GetCurrentDir()
list = os.listdir(cwd)

for item in list:
    if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
        objs = objs + SConscript(os.path.join(item, 'SConscript'))
Return('objs')

(2)在user_add_files文件夹内新建oled_ssd1306_drv文件夹并新建对应的SConscript文件, oled驱动文件放到oled_ssd1306_drv文件夹:

SConscript文件内容:

from building import *
cwd     = GetCurrentDir()
src     = Glob('*.c')
CPPPATH = [cwd]
group   = DefineGroup('oled_ssd1306_drv', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

 

(3)使用scons --target=mdk5重新构建工程,发现oled驱动已添加到工程:

(4)在main.c中添加测试代码:

#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#include "oled.h"
#include "dhtxx.h"
/* defined the LED1 pin: PB5 */
#define LED_G_PIN    GET_PIN(B, 0)
#define LED_R_PIN    GET_PIN(B, 1)
#define LED_B_PIN    GET_PIN(B, 5)
int main(void)
{
    /* set LED0 pin mode to output */
    rt_pin_write(LED_R_PIN, PIN_LOW);
    rt_pin_write(LED_G_PIN, PIN_LOW);
    rt_pin_write(LED_B_PIN, PIN_LOW);
    rt_pin_mode(LED_R_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED_G_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED_B_PIN, PIN_MODE_OUTPUT);
    dht_device_t sensor = dht_create(PKG_USING_DHTXX_SAMPLE_PIN);
    oled_dev.display_on();
    char disp_str[50];
    for(;;)
    {
        rt_thread_mdelay(3000);
        if(dht_read(sensor))
	{
	    rt_int32_t temp = dht_get_temperature(sensor);
	    rt_int32_t humi = dht_get_humidity(sensor);
	    rt_kprintf("Temp: %d, Humi: %d\n", temp, humi);
	    rt_sprintf(disp_str,"Humi: %d.%d %%",humi/10,humi%10);
	    oled_dev.show_string(0,4,(unsigned char *)disp_str,16,1);  
	    rt_sprintf(disp_str,"Temp: %d.%d C",temp/10,temp%10);
	    oled_dev.show_string(0,24,(unsigned char *)disp_str,16,1); 
	    oled_dev.refresh();
	}
	else
	{
	    rt_kprintf("Read dht sensor failed.\n");
	     rt_pin_write(LED_R_PIN, PIN_HIGH);
	}
    }
    return RT_EOK;
}

编译烧录运行:

 3. 添加ESP8266 WIFI模块驱动

(1)stm32wb55芯片有两个串口(lpuart1和uart1,正好一个做控制台、一个连接wifi模块,配置时注意区分,我将lpuart1作为控制台,uart1连接wifi),在menuconfig下面路径找到esp8266,开启并根据实际情况配置wifi密码和串口号:

(2)保存 --> pkgs --update --> scons --target=mdk5

(3)keil打开工程 --> 编译 --> 烧录 --> 运行,打开串口工具,查看信息,已经可以发现wifi正常连接上了。

4. 添加MQTT软件包,当时有4个MQTT软件包可选,哪个好用不了解,暂时选择my mqtt。

利用软件包自带的sample进行测试,直接编译烧录,控制台输入mqtt_start:

根据打印信息,可以看出已与服务器连接;之后发布一个消息试试,内容为hello!,由于例程已订阅的默认主题和发布的默认主题相同,所以如果MQTT运行正常则发布的内容会被原样接收到,测试如下,说明my mqtt软件包初步运行正常。

5.因为需要使用json串传输数据,所以添加json软件包。

三、在华为物联网平台上创建产品

注册华为云账号,在华为物联网平台上创建产品、建立产品模型、创建设备,具体过程及传输的json字符串格式参见官方指导文件《MQTT设备快速接入》文档:

(https://support.huaweicloud.com/qs-iothub/iot_05_0006.html)

我的产品截图:

模型定义截图(只添加温度和湿度两个属性):

四、上传温度和湿度数据到华为云

(1)根据my_mqtt软件包自带的sample例程的函数,稍作调整,用于上报数据,mqtt_start函数采用rtthread上电自动运行方式INIT_APP_EXPORT(mqtt_start)。

编写数据上报函数(JSON串格式参见上面华为MQTT设备快速接入文档):

/*
 * 函数名称:user_humiture_send_to_server
 * 输入参数:temp 温度数据,单位0.1C
 *          humi 湿度数据,单位0.1%
 * 返回数据:-1 发送失败
 *           0 发送成功
 */
int8_t user_humiture_send_to_server(int temp,int humi)
{
    cJSON *root_prop;
    cJSON *root_serv;
    cJSON *array_serv;
    cJSON *root;
    char *cjson_str = NULL;
    //检查mqtt连接状态
    if(paho_mqtt_is_connected(&client) == 0) return -1;
    //生成json字符串
    root_prop = cJSON_CreateObject();
    cJSON_AddNumberToObject(root_prop, "humidity", (humi/10) + 0.1 * (humi%10));
    cJSON_AddNumberToObject(root_prop, "temperature", (temp/10) + 0.1 * (temp%10));
    //
    root_serv = cJSON_CreateObject();
    cJSON_AddStringToObject(root_serv, "service_id", "humiture");
    cJSON_AddItemToObject(root_serv, "properties", root_prop);
    cJSON_AddStringToObject(root_serv, "event_time", "NULL"); //"20201207T002920Z"
    //
    array_serv = cJSON_CreateArray();
    cJSON_AddItemToArray(array_serv,root_serv);
    //
    root  = cJSON_CreateObject();
    cJSON_AddItemToObject(root, "services", array_serv);
    //发布数据
    cjson_str = cJSON_PrintUnformatted(root);
    mqtt_publish(cjson_str);
    //释放内存
    cJSON_Delete(root);
    cJSON_free(cjson_str);
    return 0;
}

 

(2)在main函数内调用数据上报函数,具体见后面我的实验工程代码,编译烧写运行程序;登录华为云查看设备状态为在线,可见云端已收到数据:

(3)数据上报华为云初步测试成功,我的测试工程代码:

链接:https://pan.baidu.com/s/10I-BtE3UVGmxp7F2TpNxHA

提取码:38sr

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章