記錄兩種是stm32 mqtt實現方法
1.使用keil自帶庫MQTTPacket實現
安裝install
安裝完成後點擊運行時環境按鈕
選中MQTTpacket
代碼實現添加和使用
首先包含頭文件 #include "MQTTPacket.h"
static MQTTTransport mytransport; //定義MQTT全局傳輸結構體
static uint8_t mqtt_parse_buf[1024] = {0}; 臨時解析數據數組大小自己看數據包大小
實現兩個函數:
//4g發送數據 阻塞發送
void transport_sendPacketBuffer(unsigned char* buf, int buflen)
{
HAL_UART_Transmit(&huart_4g, buf, buflen, 5000);
HAL_UART_Receive_IT(&huart_4g, &temp_value_4g, 1);
}
//4g獲取數據 沒有數據返回0
int transport_getdatanb(void *sck, unsigned char* buf, int count)
{
if(mqtt_4f_buf_index >= count && HAL_GetTick() - mqtt_4g_tick >= 3) {
memcpy(buf, mqtt_4g_buf, count);
memcpy(mqtt_4g_buf, mqtt_4g_buf + count, mqtt_4f_buf_index - count); //複製到前面
mqtt_4f_buf_index = mqtt_4f_buf_index - count;
return count;
}
return 0;
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == HUART_4G){
mqtt_4g_buf[mqtt_4f_buf_index++] = temp_value_4g;
mqtt_4f_buf_index = mqtt_4f_buf_index >= sizeof(mqtt_4g_buf) ? 0 : mqtt_4f_buf_index; //超出緩衝區
HAL_UART_Receive_IT(&huart_4g, &temp_value_4g, 1);
mqtt_4g_tick = HAL_GetTick();
}
}
發送採用阻塞,接收採用中斷,發送完成後必須重新開始中斷接收不然會出現不能接收的現象。
數據通信採用4G串口透傳,其他方式以此類推都可以使用
先初始化4G模塊或者其他模塊或者socket
初始化連接到服務器
//MQTT init
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
int buflen = sizeof(mqtt_parse_buf);
mytransport.getfn = transport_getdatanb;
mytransport.state = 0;
//
data.keepAliveInterval = 180;
data.cleansession = 1;
data.clientID.cstring = CCID; //clientId唯一id
data.username.cstring = "admin";
data.password.cstring = "123456";
//連接
int len = MQTTSerialize_connect(mqtt_parse_buf, buflen, &data);
transport_sendPacketBuffer(mqtt_parse_buf, len);
//等待確認
while(1) {
int frc = MQTTPacket_readnb(mqtt_parse_buf, buflen, &mytransport);
if (frc == CONNACK){
unsigned char sessionPresent, connack_rc;
if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, mqtt_parse_buf, buflen) != 1 || connack_rc != 0){
printf("Unable to connect, return code %d\n", connack_rc);
Soft_Reset();
}
break;
}
else if (frc == -1) {
printf("mqtt login error\n");
}
}
printf("MQTT OK");
初始換完成後執行MQTT循環
void MQTT_4G_POLL(void)
{
static uint8_t no_reply_count = 0;
static uint32_t mqtt_poll_tick = 0;
static int len = 0, buflen = sizeof(mqtt_parse_buf);
int msgtype = MQTTPacket_readnb(mqtt_parse_buf, buflen, &mytransport);
switch(msgtype) {
case -1:
mqtt_4f_buf_index = 0;
mytransport.state = 0;
break;
case PUBLISH:
{
unsigned char dup;
int qos, len = 0;
unsigned char retained;
unsigned short msgid;
int payloadlen_in = 0;
unsigned char* payload_in;
MQTTString receivedTopic;
MQTTDeserialize_publish(&dup, &qos, &retained, &msgid, &receivedTopic, &payload_in, &payloadlen_in, mqtt_parse_buf, sizeof(mqtt_parse_buf));
mqtt_recive_publish(receivedTopic.lenstring.data, receivedTopic.lenstring.len, (char *)payload_in, payloadlen_in);
if(qos == 1) {
len = MQTTSerialize_ack(mqtt_parse_buf, sizeof(mqtt_parse_buf), PUBACK, dup, msgid);
transport_sendPacketBuffer(mqtt_parse_buf, len);
}
if(qos == 2) {
len = MQTTSerialize_ack(mqtt_parse_buf, sizeof(mqtt_parse_buf), PUBREC, dup, msgid);
transport_sendPacketBuffer(mqtt_parse_buf, len);
}
break;
}
case SUBACK:
{
unsigned short packet_id = 0;
int count = 0, req_qos = 0;
if(MQTTDeserialize_suback(&packet_id, 1, &count, &req_qos, mqtt_parse_buf, sizeof(mqtt_parse_buf)) == 1 && packet_id > 0) {
//printf("subsucess:%d\n", subscribe_devices[254]);
}
break;
}
case PINGRESP:
no_reply_count = 0; //收到心跳回復
break;
default:
break;
}
//50s 發送心跳
if(HAL_GetTick() - mqtt_poll_tick > 50000) {
if(no_reply_count > 3) {
Soft_Reset();
}
len = MQTTSerialize_pingreq(mqtt_parse_buf, buflen);
transport_sendPacketBuffer(mqtt_parse_buf, len);
no_reply_count++;
mqtt_poll_tick = HAL_GetTick(); //更新檢測時間
}
}
發佈和訂閱函數實現
//發佈消息
static void publish(char * topic, unsigned char * payload)
{
MQTTString topicString = MQTTString_initializer;
topicString.cstring = topic;
int len = MQTTSerialize_publish(mqtt_parse_buf, sizeof(mqtt_parse_buf), 0, 0, 0, 0, topicString, payload, strlen((char *)payload));
transport_sendPacketBuffer(mqtt_parse_buf, len);
}
//訂閱
static void subscribe(char * subtopic_buf)
{
static uint16_t picket_id = 1;
MQTTString topicString = MQTTString_initializer;
int req_qos = 1, len = 0;
int buflen = sizeof(mqtt_parse_buf);
//訂閱
topicString.cstring = subtopic_buf;
len = MQTTSerialize_subscribe(mqtt_parse_buf, buflen, 0, ++picket_id, 1, &topicString, &req_qos);
transport_sendPacketBuffer(mqtt_parse_buf, len);
}