幾步實(shí)現(xiàn)stm32上面移植mqtt
最近項(xiàng)目需要,stm32上面使用到mqtt了,百度了下,發(fā)現(xiàn)網(wǎng)上資料還是挺少的,雖然有幾份相關(guān)的資料,下載下來(lái)之后,看到了mqtt的底層代碼竟然還有錯(cuò)誤,這個(gè)問(wèn)題導(dǎo)致了我后面一直調(diào)試不通,后來(lái),我直接從官方下載了mqtt的源碼用比較器比較后找到了原因,最后果斷將官方的mqtt底層代碼移植上來(lái),mqtt的發(fā)布還是比較順利,訂閱雖然可以收到消息,但是由于沒(méi)有移植os,發(fā)布消息時(shí),訂閱接受有時(shí)無(wú)法收到消息,這個(gè)還在優(yōu)化,我使用的是stm32f103c8t6平臺(tái)+w5500.其實(shí)只要帶以太網(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èn)外網(wǎng),可以借鑒下網(wǎng)上那個(gè)STM32F405+W5500的例子,我覺(jué)得那個(gè)還是挺好的,我也是主要借鑒了那個(gè)例子,不過(guò)我還是不太喜歡他把TCP的建立封裝到mqtt里面,一開(kāi)始我也是采用他那種方法,不過(guò)一直出錯(cuò),后來(lái)我采用了狀態(tài)機(jī)實(shí)現(xiàn),先讓TCP和mqtt服務(wù)器建立TCP連接在調(diào)用mqtt的連接,發(fā)布等API,這樣比較好調(diào)試。調(diào)試的話,我采用的是下面那個(gè)頁(yè)面調(diào)試的http://m2m.demos.ibm.com/mqttclient/#log
其實(shí)真正要你實(shí)現(xiàn)的mqtt接口,主要是transport.c里面的幾個(gè)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;
}
以上的其實(shí)transport_open(void)我沒(méi)調(diào)用,讓狀態(tài)機(jī)來(lái)實(shí)現(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ā)送一條消息,公司的電腦加密了,無(wú)法截圖,只能copy下網(wǎng)頁(yè)測(cè)試的數(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)化,其次我覺(jué)得有點(diǎn)雞肋,以其誤導(dǎo)大伙,還不如不公開(kāi)~~~~~~~~~~~~,如果大伙覺(jué)得有意思,可以把mqtt的ping也加上去,如果實(shí)用的話,這個(gè)還需要加入很多容錯(cuò)機(jī)制~~~~~~~~~~~~