【RA4M2设计挑战赛】RTT 之AT组件实现MQTT数据调试
【RA4M2设计挑战赛】RTT CAN智慧屏温湿度计
在上面的基础上,经地几天的调试,把RTT+AT cline MQTT上传服务器调通了。
实现AT + MQTT上传主要难点主要是与DA16200的AT通信上,原先我用串口写的函数,处理不是很方便,这次用RTT 的AT client组件,来处理,非常方便,特别是接收回mqtt的数据是非好。
代码如下,如果还没有弄好的可以借鉴一下(注,这是理想状态的发帖与订阅,如果考虑处理错误信息,可能时间不够,如果哪位大佬有更好的,也可以到这里共享一):
#include <stdlib.h>
#include <string.h>
#include <rtthread.h>
#include <at.h>
#include "at_da16200.h"
#ifndef ULOG_USING_SYSLOG
#define LOG_TAG "AT_DA16200"
#define LOG_LVL LOG_LVL_DBG
#include <ulog.h>
#else
#include <syslog.h>
#endif
#define AT_CLIENT_RECV_BUFF_LEN 512
#define AT_CLIENT_DEVICE_NAME "uart0"
#define AT_WAITE_OK_MAXTIME 3000
#define WIFI_SSID HUAWEI-H10R9U
#define WIFI_PWD 18977381885@
#define AT_ADDR_LEN 32
static rt_err_t wifi_connect_state = -1;
char ip[AT_ADDR_LEN] = {0};
char gateway[AT_ADDR_LEN] = {0}, netmask[AT_ADDR_LEN] = {0};
static void urc_conn_func(struct at_client *client ,const char *data, rt_size_t size)
{
LOG_D("AT Server device WIFI connect success!");
wifi_connect_state = RT_EOK;
}
static void urc_recv_func(struct at_client *client ,const char *data, rt_size_t size)
{
char *ptr;
char *p;
LOG_D("AT Client receive AT Server data!");
LOG_D("%s",data);
ptr = strtok(data, ":");
ptr = strtok(NULL, ",");
while (ptr != NULL) {
rt_kprintf("ptr=%s\n", ptr);
ptr = strtok(NULL, ",");
}
}
int da16200_mqtt_pub(char *msg)
{
int result = RT_EOK;
at_response_t resp = RT_NULL;
if(wifi_connect_state != RT_EOK)
{
LOG_E("MQTT_client not ready!");
return -1;
}
resp = at_create_resp(256, 0, rt_tick_from_millisecond(5000));
if (resp == RT_NULL)
{
LOG_E("No memory for response structure!");
return -2;
}
result = at_exec_cmd(resp, "AT+NWMQMSG='%s'",msg);
if(resp < 0)
{
LOG_E("Pub msg ERRO! cord:%d", result);
}
at_delete_resp(resp);
return result;
}
static void urc_func(struct at_client *client ,const char *data, rt_size_t size)
{
LOG_D("AT Server device startup!");
LOG_D("%s",data);
}
static struct at_urc urc_table[] = {
{"+NWMQCL:1", "\r\n", urc_conn_func},
{"+NWMQMSG:", "\r\n", urc_recv_func},
{"RDY", "\r\n", urc_func},
};
int at_client_port_init(void)
{
at_set_urc_table(urc_table, sizeof(urc_table) / sizeof(urc_table[0]));
return RT_EOK;
}
int at_client_16200_mqtt_init(void)
{
int result = RT_EOK;
at_response_t resp = RT_NULL;
resp = at_create_resp(256, 0, rt_tick_from_millisecond(5000));
if (resp == RT_NULL)
{
LOG_E("No memory for response structure!");
return -2;
}
result = at_client_init(AT_CLIENT_DEVICE_NAME, AT_CLIENT_RECV_BUFF_LEN);
if(result != RT_EOK)
{
LOG_E("at_clinet init erro %d",result);
return result;
}
result = at_client_wait_connect(AT_WAITE_OK_MAXTIME);
if(result != RT_EOK)
{
LOG_E("client to da16200 at timeout %d",result);
return result;
}
if(at_exec_cmd(resp, "ATE") != RT_EOK)
{
LOG_E("AT client send ATE failed,response error!");
return -RT_ERROR;
}
if(at_resp_get_line_by_kw(resp, "on") != NULL)
{
at_exec_cmd(resp, "ATE");
}
if(at_exec_cmd(resp, "AT+WFMODE=0") != RT_EOK)
{
LOG_E("AT client send AT+WFMODE failed,response error!");
return -RT_ERROR;
}
if(at_exec_cmd(resp, "AT+WFJAPA=HUAWEI-H10R9U,18977381885@") != RT_EOK)
{
LOG_E("AT client send AT+WFWFJAPA failed,response error!");
return -RT_ERROR;
}
rt_thread_delay(2000);
if(at_exec_cmd(resp, "AT+NWIP") != RT_EOK)
{
LOG_E("AT client send AT+NWIP failed,response error!");
return -RT_ERROR;
}
rt_thread_delay(1000);
if(at_resp_parse_line_args(resp,2,"%*[^,],%[^,]",&ip)>0)
{
LOG_D("ip:%s ",ip);
}
else{
LOG_E("NWIP erro");
return -RT_ERROR;
}
if(at_exec_cmd(resp, "AT+NWMQBR=%s,%d","192.168.3.192",1883) != RT_EOK)
{
LOG_E("AT client send AT+NWMQBR failed,response error!");
return -RT_ERROR;
}
if(at_exec_cmd(resp, "AT+NWMQTS=%d,%s",1,"lugl_sub") != RT_EOK)
{
LOG_E("AT client send AT+NWMQTS failed,response error!");
return -RT_ERROR;
}
if(at_exec_cmd(resp, "AT+NWMQTP=%s","lugl_pub") != RT_EOK)
{
LOG_E("AT client send AT+NWMQTP failed,response error!");
return -RT_ERROR;
}
at_client_port_init();
if(at_exec_cmd(resp, "AT+NWMQCL=1") != RT_EOK)
{
LOG_E("AT client send AT+NWMQCL failed,response error!");
return -RT_ERROR;
}
at_delete_resp(resp);
return RT_EOK;
}
在主函数获取HS3003的前提下,mqtt把数据发布出去,其订阅的客户端就可以收到了。
![image.png](//file.elecfans.com/web2/M00/90/35/poYBAGPocqqAfXpiAAHeWPNbJyQ027.png)
在电脑端创建接收APP
QT创建界面如下:
![image.png](//file.elecfans.com/web2/M00/90/35/poYBAGPocyqADaXJAAF2sZCHP38004.png)
生成的UI代码:
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
QMetaObject, QObject, QPoint, QRect,
QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QFont, QFontDatabase, QGradient, QIcon,
QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QLabel, QMainWindow, QMenuBar,
QSizePolicy, QStatusBar, QWidget)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
if not MainWindow.objectName():
MainWindow.setObjectName(u"MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName(u"centralwidget")
self.label = QLabel(self.centralwidget)
self.label.setObjectName(u"label")
self.label.setGeometry(QRect(280, 90, 321, 71))
self.label_2 = QLabel(self.centralwidget)
self.label_2.setObjectName(u"label_2")
self.label_2.setGeometry(QRect(200, 10, 481, 81))
font = QFont()
font.setPointSize(24)
self.label_2.setFont(font)
self.label_3 = QLabel(self.centralwidget)
self.label_3.setObjectName(u"label_3")
self.label_3.setGeometry(QRect(100, 170, 111, 101))
font1 = QFont()
font1.setPointSize(20)
self.label_3.setFont(font1)
self.label_4 = QLabel(self.centralwidget)
self.label_4.setObjectName(u"label_4")
self.label_4.setGeometry(QRect(100, 300, 111, 101))
self.label_4.setFont(font1)
self.label_5 = QLabel(self.centralwidget)
self.label_5.setObjectName(u"label_5")
self.label_5.setGeometry(QRect(410, 170, 111, 101))
self.label_5.setFont(font1)
self.label_6 = QLabel(self.centralwidget)
self.label_6.setObjectName(u"label_6")
self.label_6.setGeometry(QRect(400, 300, 111, 101))
self.label_6.setFont(font1)
self.label_TEMP = QLabel(self.centralwidget)
self.label_TEMP.setObjectName(u"label_TEMP")
self.label_TEMP.setGeometry(QRect(210, 170, 111, 101))
self.label_TEMP.setFont(font1)
self.label_HUMI = QLabel(self.centralwidget)
self.label_HUMI.setObjectName(u"label_HUMI")
self.label_HUMI.setGeometry(QRect(220, 310, 101, 81))
self.label_HUMI.setFont(font1)
self.label_V = QLabel(self.centralwidget)
self.label_V.setObjectName(u"label_V")
self.label_V.setGeometry(QRect(560, 160, 111, 101))
self.label_V.setFont(font1)
self.label_I = QLabel(self.centralwidget)
self.label_I.setObjectName(u"label_I")
self.label_I.setGeometry(QRect(550, 300, 111, 101))
self.label_I.setFont(font1)
self.retranslateUi(MainWindow)
QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
self.label.setText(QCoreApplication.translate("MainWindow", u"\u745e\u8428RA4M2\u7269\u8054\u7f51\u8bbe\u8ba1\u5927\u8d5b", None))
self.label_2.setText(QCoreApplication.translate("MainWindow", u"\u51b7\u94fe\u667a\u6167\u76d1\u63a7\u7cfb\u7edf", None))
self.label_3.setText(QCoreApplication.translate("MainWindow", u"\u6e29\u5ea6\uff1a", None))
self.label_4.setText(QCoreApplication.translate("MainWindow", u"\u6e7f\u5ea6\uff1a", None))
self.label_5.setText(QCoreApplication.translate("MainWindow", u"\u7535\u538b\uff1a", None))
self.label_6.setText(QCoreApplication.translate("MainWindow", u"\u7535\u6d41\uff1a", None))
self.label_TEMP.setText("")
self.label_HUMI.setText("")
self.label_V.setText("")
self.label_I.setText("")
python代码如下:
import sys
from PySide6 import QtCore, QtWidgets
from PySide6.QtCore import Slot, QObject, Signal
from temp_humi import Ui_MainWindow
from threading import Thread
import random
from paho.mqtt import client as mqtt_client
import json
with open("./setting.json", "r") as f:
setting = json.load(f)
broker = setting['broker']
port = setting['port']
username = setting['client']
password = setting['passwd']
topic = setting['topic']
client_id = f'ternimal-mqtt-{random.randint(0, 100)}'
class MQTT(QObject):
"""MQTT通信"""
signal = Signal(str, str)
def __init__(self, parent=None):
super().__init__(parent)
def _connect_mqtt(self) -> mqtt_client:
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to MQTT Broker!")
else:
print("Failed to connect, return code %d\n", rc)
client = mqtt_client.Client(client_id)
client.username_pw_set(username=username, password=password)
client.on_connect = on_connect
client.connect(broker, port)
return client
def _subscribe(self, client: mqtt_client):
def on_message(client, userdata, msg):
print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic")
self.signal.emit(msg.topic, msg.payload.decode())
client.subscribe(topic)
client.on_message = on_message
def mqtt_run(self):
client = self._connect_mqtt()
self._subscribe(client)
client.loop_start()
class View(QtWidgets.QWidget, Ui_MainWindow):
def __int__(self):
super().__init__()
self.ctext = ''
self.topic = 'lugl_pub'
@Slot()
def show_data(self, topic, payload):
print("topic:" + topic)
print("payload:" + payload)
try:
mydata = json.loads(payload)
self.label_TEMP.setText(mydata['temp'] + '度')
self.label_HUMI.setText(mydata['humi'] + '%')
except Exception as e:
print("err:" + str(e))
def on_connection_clicked(self):
def run():
client = MQTT()
client.mqtt_run()
client.signal.connect(view.show_data)
t = Thread(target=run)
t.start()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
view = View()
view.setupUi(view)
view.show()
view.setWindowTitle("MQTT测试V1.0")
view.on_connection_clicked()
sys.exit(app.exec())
运行后的效果如下:
![image.png](//file.elecfans.com/web2/M00/90/B9/pYYBAGPoc3mAJH6TAACpLNUUhG8393.png)