1 開發(fā)板介紹
該開發(fā)板的主控芯片型號為CY8C624A,是一個具有 Cortex-M4F 和 Cortex-M0+ 的 雙核CPU,該主控芯片的功能框圖如下所示:
開發(fā)板兩側(cè)留有供調(diào)試和外接其他模塊的排針接口,如下圖所示。從圖中可以看出預(yù)留出了串口、IIC、SPI、ADC和PWM等常見的外設(shè)和總線接口。
2 設(shè)計簡介
2.1 功能簡介
本次設(shè)計基于 RT-Thread 物聯(lián)網(wǎng)操作系統(tǒng)和 Infineon 開發(fā)板,使用 RT-Studio 作為開發(fā)工具,使用 ESP8266-WIFI 模塊作為物聯(lián)網(wǎng)的通訊介質(zhì),使用騰訊云服務(wù)器作為MQTT服務(wù)器,使用騰訊連連作為人機交互端,整體的功能框圖如下所示:
2.2 ESP8266 簡介
本次使用的 ESP8266 模塊如下圖所示,ESP8266 是一款強大的 WIFI 模塊,支持 AT 指令開發(fā),SDK 開發(fā)、Lua 開發(fā)、Arduino 開發(fā)、Lua 開發(fā)等開發(fā)方式,本次為了方便和主控板通訊采用 AT 指令的方式進(jìn)行開發(fā)。
3 開發(fā)步驟
本次開發(fā)使用 AT 組件和 MQTT 通訊協(xié)議進(jìn)行設(shè)備和服務(wù)器之間的通訊,所以需要在配置中配置相應(yīng)的組件。
3.1 AT 組件
RT-Thread 官方支持了豐富的 AT 設(shè)備,本次所用的 ESP8266 模塊的配置如下所示,需要開啟相應(yīng)的組件并配置路由的信息和AT設(shè)備的串口。
3.2 MQTT 組件
RT-Thread 官方支持了多種 MQTT 組件,本次使用 PahoMQTT 組件進(jìn)行開發(fā),配置如下所示:
3.3 CJson 組件
為了方便和騰訊云服務(wù)器進(jìn)行通訊,在設(shè)計通訊格式時采用物模型的方式進(jìn)行通訊,需要用到 Json 數(shù)據(jù)格式,在嵌入式設(shè)備中通常使用 CJSOn 庫對 Json 數(shù)據(jù)進(jìn)行解析,CJson 的配置如下:
配制好的組件如下圖所示:
3.4 騰訊云服務(wù)器的配置
騰訊云物聯(lián)網(wǎng)開發(fā)平臺作為本項目的云平臺進(jìn)行數(shù)據(jù)的轉(zhuǎn)發(fā)。
4 關(guān)鍵代碼編寫
MQTT任務(wù)的代碼如下,主要寫了登錄,退出,發(fā)布消息的代碼,訂閱回調(diào)函數(shù)。
#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 訂閱回調(diào)函數(shù)
- @param c 客戶端標(biāo)識
- @param msg_data 收到的數(shù)據(jù)
- @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); // 解析收到的數(shù)據(jù)
}
/ - @brief MQTT 默認(rèn)的訂閱回調(diào)函數(shù)
- @param c 客戶端標(biāo)識
- @param msg_data 收到的數(shù)據(jù)
- @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 連接的回調(diào)函數(shù)
- @param c 客戶端標(biāo)識
- @return 無
/
static void infineon_mqtt_connect_callback(MQTTClient c)
{
LOG_D("enter mqtt_connect_callback!");
}
/
@brief MQTT 上線的回調(diào)函數(shù)
@param c 客戶端標(biāo)識
@return 無
/
static void infineon_mqtt_online_callback(MQTTClient c)
{
LOG_D("enter mqtt_online_callback!");
}
/
@brief MQTT 掉線的回調(diào)函數(shù)
@param c 客戶端標(biāo)識
@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 發(fā)布消息
@param send_buff 要發(fā)布的消息的內(nèi)容
@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 新訂閱的回調(diào)函數(shù)
@param client 客戶端標(biāo)識
@param msg_data 收到的數(shù)據(jù)
@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數(shù)據(jù)格式
{
"method":"report", // report 表示設(shè)備屬性上報
"clientToken":"123", // 用于上下行消息配對標(biāo)識
"timestamp":1628646783, // 屬性上報的時間,格式為 UNIX 系統(tǒng)時間戳,不填寫該字段表示默認(rèn)為當(dāng)前系統(tǒng)時間。單位為毫秒
"params":{ // JSON 結(jié)構(gòu)內(nèi)為設(shè)備上報的屬性值
"led":1,
"fan":1
}
}
/
/ *
@brief MQTT 處理線程
@param parameter 線程的入?yún)?br /> @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,連接服務(wù)器
cJSON *root = NULL;
cJSON params = NULL;
char send_str = NULL;
while (1)
{
rt_thread_mdelay(5000); // publish 間隔
root = cJSON_CreateObject(); / 創(chuàng)建一個cJSON對象,要用 cJSON_Delete 釋放內(nèi)存 /
if (root != NULL)
{
cJSON_AddStringToObject(root, "method", "report");
cJSON_AddStringToObject(root, "clientToken", "123");
params = cJSON_CreateObject(); / 創(chuàng)建子對象 /
if (params != NULL)
{
cJSON_AddItemToObject(root, "params", params);
cJSON_AddNumberToObject(params, "led", get_led_status()); // 添加 LED 狀態(tài)
cJSON_AddNumberToObject(params, "fan", get_fan_status()); // 風(fēng)扇狀態(tài)
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); // 防止內(nèi)存泄露,會把下面所有的子節(jié)點都釋放
}
}
}
/
@brief 啟動 MQTT 處理線程
@param 無
@return 無
/
int start_mqtt_thread(void)
{
/ 創(chuàng)建 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); // 創(chuàng)建成功則啟動線程
}
else
{
LOG_E("create mqtt thread failed");
return (-RT_ERROR);
}
return RT_EOK;
}
-
人機交互
+關(guān)注
關(guān)注
12文章
1199瀏覽量
55273 -
物聯(lián)網(wǎng)
+關(guān)注
關(guān)注
2902文章
44122瀏覽量
370427 -
Cortex-M4F
+關(guān)注
關(guān)注
0文章
9瀏覽量
7632 -
RT-Thread
+關(guān)注
關(guān)注
31文章
1265瀏覽量
39853 -
ESP8266
+關(guān)注
關(guān)注
50文章
962瀏覽量
44758
發(fā)布評論請先 登錄
相關(guān)推薦
評論