最近項目需要,stm32上面使用到mqtt了,百度了下,發(fā)現(xiàn)網(wǎng)上資料還是挺少的,雖然有幾份相關(guān)的資料,下載下來之后,看到了mqtt的底層代碼竟然還有錯誤,這個問題導致了我后面一直調(diào)試不通,后來,我直接從官方下載了mqtt的源碼用比較器比較后找到了原因,最后果斷將官方的mqtt底層代碼移植上來,mqtt的發(fā)布還是比較順利,訂閱雖然可以收到消息,但是由于沒有移植os,發(fā)布消息時,訂閱接受有時無法收到消息,這個還在優(yōu)化,我使用的是stm32f103c8t6平臺+w5500.其實只要帶以太網(wǎng)接口就行。首先我們從mqtt官方下載源碼
http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt.embedded-c.git/refs/
下載后將MQTTPacket下面的src文件都加入到自己的MDK工程中。
如果采用W5500的話,最好先用官方的TCP例子將TCP調(diào)試通,而且能保證訪問外網(wǎng),可以借鑒下網(wǎng)上那個STM32F405+W5500的例子,我覺得那個還是挺好的,我也是主要借鑒了那個例子,不過我還是不太喜歡他把TCP的建立封裝到mqtt里面,一開始我也是采用他那種方法,不過一直出錯,后來我采用了狀態(tài)機實現(xiàn),先讓TCP和mqtt服務(wù)器建立TCP連接在調(diào)用mqtt的連接,發(fā)布等API,這樣比較好調(diào)試。調(diào)試的話,我采用的是下面那個頁面調(diào)試的http://m2m.demos.ibm.com/mqttclient/#log
其實真正要你實現(xiàn)的mqtt接口,主要是transport.c里面的幾個API
int transport_sendPacketBuffer(unsigned char* buf, int buflen)
{
return send(SOCK_MQTT,buf,buflen);
}
/**
* @brief×èè?·?ê??óê?TCP·t???÷·¢?íμ?êy?Y
* @parambuf êy?Y′?′¢ê×μ??·
* @paramcount êy?Y?o3???3¤?è
* @retval D?óú0±íê??óê?êy?Y꧰ü
*/
int transport_getdata(unsigned char* buf, int count)
{
return recv(SOCK_MQTT,buf,count);
}
/**
* @brief′ò?aò???socket2¢á??óμ?·t???÷
* @param?T
* @retval D?óú0±íê?′ò?a꧰ü
*/
int transport_open(void)
{
int32_t ret;
//D??¨ò???Socket2¢°ó?¨±?μ????ú5000
ret = socket(SOCK_MQTT,Sn_MR_TCP,4500,Sn_MR_ND);
if(ret != SOCK_OK){
printf("%d:Socket Errorrn",SOCK_MQTT);
}else{
printf("%d:Openedrn",SOCK_MQTT);
}
//á??óTCP·t???÷
ret = connect(SOCK_MQTT,domain_ip,1883);//???ú±?D??a1883
if(ret != SOCK_OK){
printf("%d:Socket Connect Errorrn",SOCK_MQTT);
}else{
printf("%d:Connectedrn",SOCK_MQTT);
}
return ret;
}
/**
* @brief1?±?socket
* @param?T
* @retval D?óú0±íê?1?±?꧰ü
*/
int transport_close(void)
{
close(SOCK_MQTT);
return 0;
}
以上的其實transport_open(void)我沒調(diào)用,讓狀態(tài)機來實現(xiàn)了這步。
int mqtt_publish(char *pTopic,char *pMessage)
{
int32_t len,rc;
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
unsigned char buf[200];
MQTTString topicString = MQTTString_initializer;
int msglen = strlen(pMessage);
int buflen = sizeof(buf);
data.clientID.cstring = "Client74925";
data.keepAliveInterval = 15;
data.cleansession = 1;
len = MQTTSerialize_connect(buf, buflen, &data); /* 1 */
topicString.cstring = pTopic;
len += MQTTSerialize_publish(buf + len, buflen - len, 0, 0, 0, 0, topicString, (unsigned char*)pMessage, msglen); /* 2 */
len += MQTTSerialize_disconnect(buf + len, buflen - len); /* 3 */
rc = transport_sendPacketBuffer(buf,len);
if (rc == len)
printf("Successfully publishednr");
else
printf("Publish failednr");
return 0;
}
=========================================
void do_tcp_client(void)
{
uint8 connect_State = 0;
uint16 len1;
switch(getSn_SR(SOCK_MQTT)) /*??è?socketμ?×′ì?*/
{
case SOCK_CLOSED: /*socket′|óú1?±?×′ì?*/
socket(SOCK_MQTT,Sn_MR_TCP,local_port++,Sn_MR_ND);
break;
case SOCK_INIT: /*socket′|óú3?ê??ˉ×′ì?*/
connect(SOCK_MQTT,domain_ip,1883); /*socketá??ó·t???÷*/
break;
case SOCK_ESTABLISHED: /*socket′|óúá??ó?¨á¢×′ì?*/
memset(buff,0,500);
#if 0
connect_State=mqtt_subscrib("planets/earth",buff);
if(connect_State)
{
printf("%s",buff);
}
#endif
if(heartbeatflag>=TIME_5S)
{
heartbeatflag=0;
mqtt_publish("planets/earth","firstName: Brett, lastName:McLaughlin,email:aaaa");
}
break;
case SOCK_CLOSE_WAIT: /*socket′|óúμè′y1?±?×′ì?*/
close(SOCK_MQTT);
break;
}
}
上面的發(fā)布我每5s發(fā)送一條消息,公司的電腦加密了,無法截圖,只能copy下網(wǎng)頁測試的數(shù)據(jù)
============================================================================
(06:23:57.487) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:02.492) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:02.810) >> [planets/earth][retained] Hello world!(06:24:02.810) Subscribed to [planets/earth][qos 0](06:24:07.501) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:12.497) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:17.490) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:22.490) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:27.491) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:32.481) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:37.490) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:42.497) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:47.491) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa
訂閱消息的函數(shù)目前暫且不公布,主要是還在優(yōu)化,其次我覺得有點雞肋,以其誤導大伙,還不如不公開~~~~~~~~~~~~,如果大伙覺得有意思,可以把mqtt的ping也加上去,如果實用的話,這個還需要加入很多容錯機制~~~~~~~~~~~~