几步实现stm32上面移植mqtt
生活随笔
收集整理的這篇文章主要介紹了
几步实现stm32上面移植mqtt
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
最近項(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的話(huà),最好先用官方的TCP例子將TCP調(diào)試通,而且能保證訪(fǎng)問(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)試的話(huà),我采用的是下面那個(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
??* @param??buf êy?Y′?′¢ê×μ??·
??* @param??count ê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 Error\r\n",SOCK_MQTT);
??}else{
? ? printf("%d:Opened\r\n",SOCK_MQTT);
??}
??//á??óTCP·t???÷
??ret = connect(SOCK_MQTT,domain_ip,1883);//???ú±?D??a1883
??if(ret != SOCK_OK){
? ? printf("%d:Socket Connect Error\r\n",SOCK_MQTT);
??}else{
? ? printf("%d:Connected\r\n",SOCK_MQTT);
??}? ? ? ? ? ? ? ?
? ? ? ? return ret;
}
/**
??* @brief??1?±?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 published\n\r");
? ? ? ? else
? ? ? ? ? ? ? ? printf("Publish failed\n\r");
??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í)用的話(huà),這個(gè)還需要加入很多容錯(cuò)機(jī)制~~~~~~~~~~~~ 《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專(zhuān)家共同創(chuàng)作,文字、視頻、音頻交互閱讀
http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt.embedded-c.git/refs/
下載后將 MQTTPacket下面的src文件都加入到自己的MDK工程中。
如果采用W5500的話(huà),最好先用官方的TCP例子將TCP調(diào)試通,而且能保證訪(fǎng)問(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)試的話(huà),我采用的是下面那個(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
??* @param??buf êy?Y′?′¢ê×μ??·
??* @param??count ê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 Error\r\n",SOCK_MQTT);
??}else{
? ? printf("%d:Opened\r\n",SOCK_MQTT);
??}
??//á??óTCP·t???÷
??ret = connect(SOCK_MQTT,domain_ip,1883);//???ú±?D??a1883
??if(ret != SOCK_OK){
? ? printf("%d:Socket Connect Error\r\n",SOCK_MQTT);
??}else{
? ? printf("%d:Connected\r\n",SOCK_MQTT);
??}? ? ? ? ? ? ? ?
? ? ? ? return ret;
}
/**
??* @brief??1?±?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 published\n\r");
? ? ? ? else
? ? ? ? ? ? ? ? printf("Publish failed\n\r");
??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í)用的話(huà),這個(gè)還需要加入很多容錯(cuò)機(jī)制~~~~~~~~~~~~ 《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專(zhuān)家共同創(chuàng)作,文字、視頻、音頻交互閱讀
總結(jié)
以上是生活随笔為你收集整理的几步实现stm32上面移植mqtt的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 复制构造函数 与 赋值函数 的区别
- 下一篇: cJSON 使用笔记