MQTT移植

一、移植平台:
pahoMQTT,stm32f103,Keil5,要想使用官方封装好MQTT函数 MQTTClient.h ,做如下移植
二、移植过程
1.将在MQTT三个文件中,如下图

找到如下MQTT文件(下图),加入到工程中。

2.打开 MQTTClient.h 头文件,在其中定义如下程序(下图),定时器接口,网络接口,定时器的5个函数,如果已有,屏蔽已有的。

#define int_ValMax 0xffffffff//int stm32 32位
typedef struct Timer Timer;//定时器接口 对外
struct Timer {
unsigned int StartVal;//定时初值
unsigned int end_time;//定时时间
};

typedef struct Network Network;//网络接口 对外
struct Network
{
int my_socket;//当前连接的TCP socket号
//参数要求(c->ipstack, &i, 1, timeout) 返回读到的数据长度
int (mqttread) (Network ipstack, unsigned char* R_buffer, int R_buffer_Lenth, int timeoutMS);//对服务器读 函数需要自己实现
int (mqttwrite) (Network, unsigned char*, int, int);//对服务器写 参数同上 返回写入数据长度
void (disconnect) (Network);//断开TCP连接
};

/* The Timer structure must be defined in the platform specific header,//下面5个函数需要自己实现

  • and have the following functions to operate on it. /
    extern void TimerInit(Timer
    );//定时器初始化
    extern char TimerIsExpired(Timer*);//返回定时器是否超时
    extern void TimerCountdownMS(Timer*, unsigned int);//设置定时时间 单位ms
    extern void TimerCountdown(Timer*, unsigned int);//设置定时时间 单位s
    extern int TimerLeftMS(Timer*);//返回剩余定时时间 单位ms

3.我们要自己实现这些接口函数,还有topic处理的回调函数的实现
3.1定时器的接口函数实现

//以下函数可以外部调用
void TimerInit(Timer* timer)//定时器初始化
{
timer->StartVal = 0;
timer->end_time = 0;
}
//#define int_ValMax 0xffffffff//int stm32 32位
volatile unsigned int MQTT_sysTime = 0;//全局变量 放定时器中
char TimerIsExpired(Timer* timer)//返回定时器是否超时
{
if(MQTT_sysTime >=timer->StartVal)
return((MQTT_sysTime -timer->StartVal) >timer->end_time);
else
return((MQTT_sysTime +int_ValMax -timer->StartVal) >timer->end_time);
}

void TimerCountdownMS(Timer* timer, unsigned int time)//设置定时时间 单位ms
{
timer->StartVal = MQTT_sysTime;
timer->end_time = time;
}

void TimerCountdown(Timer* timer, unsigned int time)//设置定时时间 单位s
{
timer->StartVal = MQTT_sysTime;
timer->end_time = (time *1000);
}

int TimerLeftMS(Timer* timer)//返回剩余定时时间 单位ms
{
if(MQTT_sysTime >=timer->StartVal)
return(timer->end_time -(MQTT_sysTime -timer->StartVal));
else
return(timer->end_time -(MQTT_sysTime +int_ValMax -timer->StartVal));
}

将全局变量MQTT_sysTime放入SysTick_Handler中断函数中,SysTick中断时间1毫秒

3.2网络接口函数的实现有,如下图,由于我采用DMA进行1个完整数据帧的接收,所以对数据接收部分源程序进行了重写,源程序是通过不断的查询方式进行接收。

#define MqttNetwork_USART2 1
int myMqttread(Network* Network, unsigned char* R_buffer, int R_buffer_Lenth, int timeoutMS)//对服务器读 函数需要自己实现
{
// if(Network->my_socket ==MqttNetwork_USART2)
// {
// HAL_UART_Receive(&huart2, R_buffer,R_buffer_Lenth,timeoutMS);
// return R_buffer_Lenth;
// }
if(Network->my_socket ==MqttNetwork_USART2)//UART 采用DMA接收1帧完整数据
{
if(ESP8266_uartRx_f == 1)//接收到数据
{ESP8266_uartRx_f = 0;return 1; }
}
return 0;
}
int myMqttwrite(Network* Network, unsigned char* W_buffer, int W_buffer_Lenth, int timeoutMS)//对服务器写 参数同上 返回写入数据长度
{
if(Network->my_socket ==MqttNetwork_USART2)
{
HAL_UART_Transmit(&huart2,W_buffer,W_buffer_Lenth,timeoutMS);
return W_buffer_Lenth;
}
return 0;
}

UART接收部分程序,DMA初始化,如下图

HAL_UART_Receive_DMA(&huart1,UpgradeCode_array,array_size);
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
HAL_UART_Receive_DMA(&huart2,ESP8266_uartRx,array_size);
__HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);

UART接收部分程序,UART中断对接收数据的处理,注意:用的UART2来接收的数据,UART1用做调试,如下图

if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE))
{
Uart_R_flog = 1;
HAL_UART_DMAStop(&huart1);
HAL_UART_Receive_DMA(&huart1,UpgradeCode_array,array_size);
uint16_t lenth = mystrlen_Inc0((char*)UpgradeCode_array,sizeof(UpgradeCode_array));
HAL_UART_Transmit(&huart2,UpgradeCode_array,lenth,50);
Clear_array(UpgradeCode_array,lenth);//接收清零
}
__HAL_UART_CLEAR_IDLEFLAG(&huart1);

3.3 打开 MQTTClient.c 对MQTT源程序进行重写,如下图

static int readPacket(MQTTClient* c, Timer* timer)//由于UART采用DMA接收1帧完整数据 有冲突 对此函数进行重写
{
MQTTHeader header = {0};
int rc = c->ipstack->mqttread(c->ipstack, c->readbuf, 1, TimerLeftMS(timer));//读第一个字节 辨别信息类型
if (rc == 0)//没有接收到数据
goto exit;

header.byte = c->readbuf[0];//取出MQTT固定报头
rc = header.bits.type;//固定报头类型
if (c->keepAliveInterval > 0)TimerCountdown(&c->last_received, c->keepAliveInterval); // record the fact that we have successfully received a packet

exit:
return rc;
}

3.4 Topic处理回调函数的实现,如下图三个函数需要Topic处理回调函数,MQTT接收到数据后将会调用相应的Topic处理回调函数

回调函数的实现,如下图

my_u8* pPayload = NULL;//接收Json数据
my_u16 Payload_Lenyh = 0;//接收Json数据长度

extern my_u16 myStrlen_Inc0(my_u8 pStr,my_u16 pStr_Lenth);//数组可以包含0
extern void Clear8266_array(uint8_t array,uint16_t array_lenth);//数组清零
void Device_Upgrade(MessageData
MgData)//MQTT设备升级处理回调函数
{
printf("\nDeviceUpgrade Message is Rsave\n");
printf(“TopicName:\n”);
HAL_UART_Transmit(&huart1,(my_u8
)(MgData->topicName->lenstring.data),MgData->topicName->lenstring.len,1000);
printf("\nPayload:\n");
pPayload = (my_u8*)(MgData->message->payload);
Payload_Lenyh = MgData->message->payloadlen;
HAL_UART_Transmit(&huart1,pPayload,Payload_Lenyh,1000);
printf("\n");
}

到此,移植过程完成,但本平台编译的时候发生MQTT枚举SUCCESS与系统相冲突,对其进行了全部替换,如下图

三,测试

unsigned char sendbuf[1024] ={0};
//unsigned char readbuf[1024] ={0};
MQTTClient client_Test;
Network network;
network.mqttread =myMqttread;//指向网络接口函数读
network.mqttwrite = myMqttwrite;
network.my_socket = MqttNetwork_USART2;
MQTTClientInit(&client_Test,&network,5000,sendbuf, sizeof(sendbuf),ESP8266_uartRx, sizeof(ESP8266_uartRx));//创建一个设备并默认初始化

 MQTTSetMessageHandler(&client_Test,"/ota/device/upgrade/a19tZSI5p0d/STM32",Device_Upgrade);//绑定topic与其回调处理函数MQTTPacket_connectData options =MQTTPacket_connectData_initializer;options.cleansession = 1;    //清理会话options.clientID.cstring = "STM32|securemode=3,signmethod=hmacsha1|";//客户端标识符options.username.cstring = "STM32&a19tZSI5p0d";//用户名options.password.cstring = "C78834B21306AFE988A25B5163C15C328DE84F31";//用户密码options.MQTTVersion = 3; //MQTT版本options.willFlag = 0;options.keepAliveInterval = 60;if(MQTTConnect(&client_Test, &options) ==MQTT_SUCCESS)//登陆阿里云平台printf("Device-Connect!\n");elseprintf("Device-DisConnect!\n");Clear8266_array(ESP8266_uartRx,sizeof(ESP8266_uartRx));//接收清零MQTTYield(&client_Test,10000);//定时一段时间 用于接收服务器发来的数据 在此等待10秒用于接收数据
if(pPayload != NULL)//接收到Json数据{

测试结果:成功登陆阿里云平台,并接收到返回数据

附,MQTT移植包,包含了移植的所有文件:https://download.csdn.net/download/mymycsdn321/20664289

pahoMQTT移植相关推荐

  1. ubuntu交叉编译移植paho-mqtt-c

    交叉编译移植paho-mqtt-c库 一.环境说明 近期项目需求,在imx6ull上集成MQTT通讯,准备在ubuntu16.04上通过交叉编译工具链arm-linux-guneabihf- (lin ...

  2. 如何在鸿蒙系统中移植 Paho-MQTT 实现MQTT协议

    MQTT 是当前最主流的物联网通信协议,需要物联网云平台,例如华为云.阿里云.移动OneNET都支持mqtt.而Hi3861则是一款专为IoT应用场景打造的芯片.本节主要讲如何在鸿蒙系统中通过移植第3 ...

  3. pahoMQTT+SIM800C+STM32 移植和使用

    1. 介绍 随着物联网的全面普及,作为终端的单片机也需要联网,本文讲述的是一种低成本的物联网方案,硬件使用GPRS模块和STM32单片机,网络基于MQTT报文协议,相比于WIFI局域网,GPRS(最新 ...

  4. BC20/BC26-opencpu移植cjson,mqtt等注意事项

      如今芯片慌,单片机涨价的厉害,移远的BC20/BC26等模组的opencpu方案节省MCU,提供计算力的服务.还是很节省成本的.   但是使用模组移植一些标准的开源库的时候就会遇到,编译出错.经过 ...

  5. OpenHarmony轻量系统开发【11】移植MQTT

    摘要:本文简单介绍如何移植MQTT 适合群体:适用于润和Hi3861开发板 文中所有代码仓库:https://gitee.com/qidiyun/hihope-3861-smart-home-kit ...

  6. paho架构_GitHub - yanzhangfeng/paho-mqtt: Eclipse Paho MQTT C/C++ client for Embedded platforms

    paho-mqtt 1.介绍 Paho MQTT 是 Eclipse 实现的基于 MQTT 协议的客户端,本软件包是在 Eclipse paho-mqtt 源码包的基础上设计的一套 MQTT 客户端程 ...

  7. PowerBuilder程序 ASA 数据库移植后不能连接解决

    前言: 软件开发工具实践课作业用的powerbuilder自带的数据库画板建立的,建好之后运行成功后就没有再管过了.后来代码在别人的机器跑不起来.报错信息如下 找到原因: 程序运行完后,没有手动断开连 ...

  8. web server大全之GoAhead移植(转载)

    转自:http://linux.chinaunix.net/techdoc/develop/2009/06/19/1119124.shtml 注:最近在做goAhead web server和移植其到 ...

  9. Tomcat V6 Examples移植到Apusic V5.1

    目标:将Tomcat V6的的例子Examples移植到Apusic V5.1上 术语:Tomcat:只提供了WEB容器的开源服务器: Apusic:提供了完整的J2EE支持的商用服务器: %TOMC ...

最新文章

  1. 0x31.数论 - 质数
  2. Timer TimeTask Handler
  3. 华章7-8月份新书简介(2018年)
  4. Java线程之多线程与多进程(1)——以操作系统的角度述说线程与进程
  5. kafka 怎么样连接图形化界面_图形化编程有多简单,点亮LED不到一分钟
  6. OCP 笔记,非常感谢那位告诉的博客。谢谢。
  7. 代码提交本地代码和远程代码不同步问题(笔记)
  8. 【Vegas原创】重建Exchange 2007 OWA的虚拟目录
  9. Windows Server 2012 R2 WSUS-5:组策略配置自动更新
  10. pcie握手机制_【博文连载】PCIe扫盲——Ack/Nak 机制详解(一)
  11. 文件浏览器一定要有个向上级按钮
  12. php日历表代码,PHP实现的简单日历代码_php
  13. python实现自动开机_python自动循环定时开关机(非重启)测试
  14. python except exception_Python 获取异常(Exception)信息的几种方法
  15. elasticsearch索引health 健康状态变为yellow,red处理
  16. gif软件(ShareX)
  17. 每日一练-游戏通关时间最短
  18. JavaSE语法(3)——【逻辑控制:各种分支循环语句】
  19. Connection to tcp://39.96.3.215:1935 failed: Error number -138 occurred
  20. 有趣的第一人称和第三人称游戏

热门文章

  1. 【精选】DO-218AB封装SM8T36A / TVS瞬态抑制二极管主要参数
  2. Python开发微信公众平台(一)
  3. uni-app点击按钮弹出提示框
  4. 分享一波很全的 JS 判断数据类型的方法
  5. 使用移动crm对企业的好处是什么?
  6. [ahk]获取招商证券中的资金
  7. 企业级信息系统开发讲课笔记2.3 利用MyBatis实现关联查询
  8. 利用IEHelper实现简单网址过滤
  9. 时间序列绘制ACF与PACF图像
  10. FreeRTOS学习笔记20200526