×
单片机 > 单片机程序设计 > 详情

几步实现stm32上面移植mqtt

发布时间:2020-09-02 发布时间:
|

 最近项目需要,stm32上面使用到mqtt了,百度了下,发现网上资料还是挺少的,虽然有几份相关的资料,下载下来之后,看到了mqtt的底层代码竟然还有错误,这个问题导致了我后面一直调试不通,后来,我直接从官方下载了mqtt的源码用比较器比较后找到了原因,最后果断将官方的mqtt底层代码移植上来,mqtt的发布还是比较顺利,订阅虽然可以收到消息,但是由于没有移植os,发布消息时,订阅接受有时无法收到消息,这个还在优化,我使用的是stm32f103c8t6平台+w5500.其实只要带以太网接口就行。  首先我们从mqtt官方下载源码
http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt.embedded-c.git/refs/
下载后将MQTTPacket下面的src文件都加入到自己的MDK工程中。


如果采用W5500的话,最好先用官方的TCP例子将TCP调试通,而且能保证访问外网,可以借鉴下网上那个STM32F405+W5500的例子,我觉得那个还是挺好的,我也是主要借鉴了那个例子,不过我还是不太喜欢他把TCP的建立封装到mqtt里面,一开始我也是采用他那种方法,不过一直出错,后来我采用了状态机实现,先让TCP和mqtt服务器建立TCP连接在调用mqtt的连接,发布等API,这样比较好调试。调试的话,我采用的是下面那个页面调试的http://m2m.demos.ibm.com/mqttclient/#log

其实真正要你实现的mqtt接口,主要是transport.c里面的几个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;
}

以上的其实transport_open(void)我没调用,让状态机来实现了这步。
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;

        }
}
上面的发布我每5s发送一条消息,公司的电脑加密了,无法截图,只能copy下网页测试的数据
============================================================================
(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
订阅消息的函数目前暂且不公布,主要是还在优化,其次我觉得有点鸡肋,以其误导大伙,还不如不公开~~~~~~~~~~~~,如果大伙觉得有意思,可以把mqtt的ping也加上去,如果实用的话,这个还需要加入很多容错机制~~~~~~~~~~~~

关键字:stm32  移植  mqtt 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
单片机中高阻态的实质及意义