1 開發板介紹
該開發板的主控芯片型號為CY8C624A,是一個具有 Cortex-M4F 和 Cortex-M0+ 的 雙核CPU,該主控芯片的功能框圖如下所示:
開發板兩側留有供調試和外接其他模塊的排針接口,如下圖所示。從圖中可以看出預留出了串口、IIC、SPI、ADC和PWM等常見的外設和總線接口。
2 設計簡介
2.1 功能簡介
本次設計基于 RT-Thread 物聯網操作系統和 Infineon 開發板,使用 RT-Studio 作為開發工具,使用 ESP8266-WIFI 模塊作為物聯網的通訊介質,使用騰訊云服務器作為MQTT服務器,使用騰訊連連作為人機交互端,整體的功能框圖如下所示:
2.2 ESP8266 簡介
本次使用的 ESP8266 模塊如下圖所示,ESP8266 是一款強大的 WIFI 模塊,支持 AT 指令開發,SDK 開發、Lua 開發、Arduino 開發、Lua 開發等開發方式,本次為了方便和主控板通訊采用 AT 指令的方式進行開發。
3 開發步驟
本次開發使用 AT 組件和 MQTT 通訊協議進行設備和服務器之間的通訊,所以需要在配置中配置相應的組件。
3.1 AT 組件
RT-Thread 官方支持了豐富的 AT 設備,本次所用的 ESP8266 模塊的配置如下所示,需要開啟相應的組件并配置路由的信息和AT設備的串口。
3.2 MQTT 組件
RT-Thread 官方支持了多種 MQTT 組件,本次使用 PahoMQTT 組件進行開發,配置如下所示:
3.3 CJson 組件
為了方便和騰訊云服務器進行通訊,在設計通訊格式時采用物模型的方式進行通訊,需要用到 Json 數據格式,在嵌入式設備中通常使用 CJSOn 庫對 Json 數據進行解析,CJson 的配置如下:
配制好的組件如下圖所示:
3.4 騰訊云服務器的配置
騰訊云物聯網開發平臺作為本項目的云平臺進行數據的轉發。
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;
}
-
人機交互
+關注
關注
12文章
1217瀏覽量
55531 -
物聯網
+關注
關注
2913文章
44923瀏覽量
377006 -
Cortex-M4F
+關注
關注
0文章
9瀏覽量
7659 -
RT-Thread
+關注
關注
31文章
1305瀏覽量
40386 -
ESP8266
+關注
關注
50文章
962瀏覽量
45328
發布評論請先 登錄
相關推薦
評論