基于RT-Thread和Infineon的物联网demo设计简介

电子说

1.3w人已加入

描述

1 开发板介绍

该开发板的主控芯片型号为CY8C624A,是一个具有 Cortex-M4F 和 Cortex-M0+ 的 双核CPU,该主控芯片的功能框图如下所示:

RT-Thread

开发板两侧留有供调试和外接其他模块的排针接口,如下图所示。从图中可以看出预留出了串口、IIC、SPI、ADC和PWM等常见的外设和总线接口。

RT-Thread

2 设计简介

2.1 功能简介

本次设计基于 RT-Thread 物联网操作系统和 Infineon 开发板,使用 RT-Studio 作为开发工具,使用 ESP8266-WIFI 模块作为物联网的通讯介质,使用腾讯云服务器作为MQTT服务器,使用腾讯连连作为人机交互端,整体的功能框图如下所示:

RT-Thread

2.2 ESP8266 简介

本次使用的 ESP8266 模块如下图所示,ESP8266 是一款强大的 WIFI 模块,支持 AT 指令开发,SDK 开发、Lua 开发、Arduino 开发、Lua 开发等开发方式,本次为了方便和主控板通讯采用 AT 指令的方式进行开发。

3 开发步骤

本次开发使用 AT 组件和 MQTT 通讯协议进行设备和服务器之间的通讯,所以需要在配置中配置相应的组件。

3.1 AT 组件

RT-Thread 官方支持了丰富的 AT 设备,本次所用的 ESP8266 模块的配置如下所示,需要开启相应的组件并配置路由的信息和AT设备的串口。

RT-Thread

3.2 MQTT 组件

RT-Thread 官方支持了多种 MQTT 组件,本次使用 PahoMQTT 组件进行开发,配置如下所示:

RT-Thread

3.3 CJson 组件

为了方便和腾讯云服务器进行通讯,在设计通讯格式时采用物模型的方式进行通讯,需要用到 Json 数据格式,在嵌入式设备中通常使用 CJSOn 库对 Json 数据进行解析,CJson 的配置如下:

RT-Thread

配制好的组件如下图所示:

RT-Thread

3.4 腾讯云服务器的配置

腾讯云物联网开发平台作为本项目的云平台进行数据的转发。

RT-Thread

4 关键代码编写

MQTT任务的代码如下,主要写了登录,退出,发布消息的代码,订阅回调函数。

#include
#include
#include
#include
#include "rtdevice.h"
#define DBG_TAG "mqtt_task.c"
#define DBG_LVL DBG_LOG
#include
#include "paho_mqtt.h"
#include "infineon_esp8266.h"
#include "json_parse.h"
#include "led.h"
#include "cJSON.h"
//#include "cJSON_util.h"
/**

  • MQTT URI farmat:
  • domain mode
  • tcp://iot.eclipse.org:1883
  • ipv4 mode
  • tcp://192.168.10.1:1883
  • ssl://192.168.10.1:1884
  • ipv6 mode
  • tcp://[fe80::20c:29ff:fe9a:a07e]:1883
  • ssl://[fe80::20c:29ff:fe9a:a07e]:1884
    /
    #define MQTT_URI "tcp://T0FR66L94D.iotcloud.tencentdevices.com:1883"
    #define MQTT_CLIENT_ID "T0FR66L94Dinfineon_esp8266"
    #define MQTT_USERNAME "T0FR66L94Dinfineon_esp8266;12010126;AVBVT;1647450202"
    #define MQTT_PASSWORD "68dab4c81b227f841ef86b6223711975106a4a4cfe6556f77504b606430eeae0;hmacsha256"
    #define MQTT_SUBTOPIC "$thing/down/property/T0FR66L94D/infineon_esp8266"
    #define MQTT_PUBTOPIC "$thing/up/property/T0FR66L94D/infineon_esp8266"
    #define MQTT_WILLMSG "Goodbye!"
    /
    define MQTT client context /
    static MQTTClient client;
    static int is_started = 0;
    /
    *
  • @brief MQTT 订阅回调函数
  • @param c 客户端标识
  • @param msg_data 收到的数据
  • @return 无
    */
    static void infineon_mqtt_sub_callback(MQTTClient *c, MessageData *msg_data)
    {
    *((char *) msg_data->message->payload + msg_data->message->payloadlen) = '�';
    LOG_D("mqtt sub callback: %.s",
    //msg_data->topicName->lenstring.len,
    //msg_data->topicName->lenstring.data,
    msg_data->message->payloadlen, (char * )msg_data->message->payload);
    parse_msg(msg_data->message->payloadlen, (char ) msg_data->message->payload); // 解析收到的数据
    }
    /
  • @brief MQTT 默认的订阅回调函数
  • @param c 客户端标识
  • @param msg_data 收到的数据
  • @return 无
    */
    static void infineon_mqtt_sub_default_callback(MQTTClient *c, MessageData *msg_data)
    {
    *((char *) msg_data->message->payload + msg_data->message->payloadlen) = '�';
    LOG_D("mqtt sub default callback: %.s %.s", msg_data->topicName->lenstring.len,
    msg_data->topicName->lenstring.data, msg_data->message->payloadlen, (char * )msg_data->message->payload);
    }
    /
  • @brief MQTT 连接的回调函数
  • @param c 客户端标识
  • @return 无
    /
    static void infineon_mqtt_connect_callback(MQTTClient c)
    {
    LOG_D("enter mqtt_connect_callback!");
    }
    /

    @brief MQTT 上线的回调函数
    @param c 客户端标识
    @return 无
    /
    static void infineon_mqtt_online_callback(MQTTClient c)
    {
    LOG_D("enter mqtt_online_callback!");
    }
    /

    @brief MQTT 掉线的回调函数
    @param c 客户端标识
    @return 无
    /
    static void infineon_mqtt_offline_callback(MQTTClient c)
    {
    LOG_D("enter mqtt_offline_callback!");
    }
    /
  • @brief MQTT 启动
  • @param 无
  • @return 成功返回0,失败返回-1
    /
    int infineon_mqtt_start(void)
    {
    /
    init condata param by using MQTTPacket_connectData_initializer /
    MQTTPacket_connectData condata = MQTTPacket_connectData_initializer;
    static char cid[20] = { 0 };
    if (is_started)
    {
    LOG_E("mqtt client is already connected.");
    return -1;
    }
    /
    config MQTT context param /
    {
    client.isconnected = 0;
    client.uri = MQTT_URI;
    /
    generate the random client ID /
    rt_snprintf(cid, sizeof(cid), "rtthread%d", rt_tick_get());
    /
    config connect param /
    memcpy(&client.condata, &condata, sizeof(condata));
    client.condata.clientID.cstring = MQTT_CLIENT_ID;
    client.condata.keepAliveInterval = 30;
    client.condata.cleansession = 1;
    client.condata.username.cstring = MQTT_USERNAME;
    client.condata.password.cstring = MQTT_PASSWORD;
    /
    config MQTT will param. /
    client.condata.willFlag = 1;
    client.condata.will.qos = 1;
    client.condata.will.retained = 0;
    client.condata.will.topicName.cstring = MQTT_PUBTOPIC;
    client.condata.will.message.cstring = MQTT_WILLMSG;
    /
    malloc buffer. /
    client.buf_size = client.readbuf_size = 1024;
    client.buf = rt_calloc(1, client.buf_size);
    client.readbuf = rt_calloc(1, client.readbuf_size);
    if (!(client.buf && client.readbuf))
    {
    LOG_E("no memory for MQTT client buffer!");
    return -1;
    }
    /
    set event callback function /
    client.connect_callback = infineon_mqtt_connect_callback;
    client.online_callback = infineon_mqtt_online_callback;
    client.offline_callback = infineon_mqtt_offline_callback;
    /
    set subscribe table and event callback /
    client.messageHandlers[0].topicFilter = rt_strdup(MQTT_SUBTOPIC);
    client.messageHandlers[0].callback = infineon_mqtt_sub_callback;
    client.messageHandlers[0].qos = QOS1;
    /
    set default subscribe event callback /
    client.defaultMessageHandler = infineon_mqtt_sub_default_callback;
    }
    /
    run mqtt client /
    paho_mqtt_start(&client);
    is_started = 1;
    return 0;
    }
    /
    *
    @brief MQTT 停止
    @param 无
    @return 成功返回0,失败返回-1
    /
    int infineon_mqtt_stop(void)
    {
    if (is_started == 1)
    {
    is_started = 0;
    return paho_mqtt_stop(&client);
    }
    }
    /
    *
    @brief MQTT 发布消息
    @param send_buff 要发布的消息的内容
    @return 成功返回0,失败返回-1
    /
    int infineon_mqtt_publish(char send_buff)
    {
    if (is_started == 0)
    {
    LOG_E("mqtt client is not connected.");
    return -1;
    }
    paho_mqtt_publish(&client, QOS1, MQTT_PUBTOPIC, send_buff);
    return 0;
    }
    /

    @brief MQTT 新订阅的回调函数
    @param client 客户端标识
    @param msg_data 收到的数据
    @return 无
    */
    void infineon_mqtt_new_sub_callback(MQTTClient *client, MessageData *msg_data)
    {
    *((char *) msg_data->message->payload + msg_data->message->payloadlen) = '�';
    LOG_D("mqtt new subscribe callback: %.s %.s", msg_data->topicName->lenstring.len,
    msg_data->topicName->lenstring.data, msg_data->message->payloadlen, (char * )msg_data->message->payload);
    }
    /

    @brief MQTT 订阅
    @param topic 要订阅的主题的名字
    @return 成功返回0,失败返回-1
    /
    int infineon_mqtt_subscribe(char topic)
    {
    if (is_started == 0)
    {
    LOG_E("mqtt client is not connected.");
    return -1;
    }
    return paho_mqtt_subscribe(&client, QOS1, topic, infineon_mqtt_new_sub_callback);
    }
    /

    @brief MQTT 取消订阅
    @param topic 要取消订阅的主题的名字
    @return 成功返回0,失败返回-1
    */
    int infineon_mqtt_unsubscribe(char topic)
    {
    if (is_started == 0)
    {
    LOG_E("mqtt client is not connected.");
    return -1;
    }
    return paho_mqtt_unsubscribe(&client, topic);
    }
    /

    json数据格式
    {
"method":"report",          // report 表示设备属性上报
"clientToken":"123",        // 用于上下行消息配对标识
"timestamp":1628646783,     // 属性上报的时间,格式为 UNIX 系统时间戳,不填写该字段表示默认为当前系统时间。单位为毫秒
"params":{                  // JSON 结构内为设备上报的属性值
  • "led":1,
    
"fan":1
  • 
    

}


}
/
/
*
@brief MQTT 处理线程
@param parameter 线程的入参
@return 无
*/
void mqtt_thread_entry(void *parameter)
{
while (1)
{
if (get_esp8266_link_status() == 0) // 等到 ESP8266 连接成功后才能连接腾讯云
{
break;
}
else
{
rt_thread_mdelay(1000);
}
}
infineon_mqtt_start(); // 启动mqtt,连接服务器
cJSON *root = NULL;
cJSON params = NULL;
char send_str = NULL;
while (1)
{
rt_thread_mdelay(5000); // publish 间隔
root = cJSON_CreateObject(); /
创建一个cJSON对象,要用 cJSON_Delete 释放内存 /
if (root != NULL)
{
cJSON_AddStringToObject(root, "method", "report");
cJSON_AddStringToObject(root, "clientToken", "123");
params = cJSON_CreateObject(); /
创建子对象 /
if (params != NULL)
{
cJSON_AddItemToObject(root, "params", params);
cJSON_AddNumberToObject(params, "led", get_led_status()); // 添加 LED 状态
cJSON_AddNumberToObject(params, "fan", get_fan_status()); // 风扇状态
send_str = cJSON_Print(root);
if (send_str != NULL)
{
LOG_D("send msg: %sn", send_str);
infineon_mqtt_publish(send_str);
}
}
}
if (send_str != NULL) // 释放空间
{
cJSON_free(send_str);
send_str = NULL;
}
if (root != NULL)
{
cJSON_Delete(root); // 防止内存泄露,会把下面所有的子节点都释放
}
}
}
/

@brief 启动 MQTT 处理线程
@param 无
@return 无
/
int start_mqtt_thread(void)
{
/
创建 MTQTT 处理线程 */
rt_thread_t thread = rt_thread_create("mqtt_thread", mqtt_thread_entry, RT_NULL, 2048, 10, 20);
if (thread != RT_NULL)
{
rt_thread_startup(thread); // 创建成功则启动线程
}
else
{
LOG_E("create mqtt thread failed");
return (-RT_ERROR);
}
return RT_EOK;
}

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分