上一篇使用USB转串口的方式通过ESP8266wifi模块的方式成功连接上了阿里云,现在就要通过单片机来替换电脑上位机了,这样单片机自动的去调用并发送串口数据更加方便,也更加符合一个产品的开发。板载的传感器有NTC温度,光强,这两个主要用来设备上传到平台,另外一个是RGB的灯,这个主要是用来平台下发设备的接收和解析。这里为了直观我直接用串口打印出来。只要数据部分对了其他的都好说。
网页上的运行状态图
温度曲线图
光强曲线图
颜色色值曲线图,这里其实是通过单片机随机函数生成的一个数据,所以变化也是比较大的,为了直观我也把这个值上传到平台。
平台下发数据、设备解析测试。
这里要注意一下,最开始我通过strstr方法来找出关键字“hue”,但是测了下不行,后来找到原因,估计是平台下发的josn数据包中含有多个0,比方说设备收到的是“123456\0789”,这里的‘\0’其实hex就是0x00,也正好是字符串的结尾标识符,这样通过strstr要找出“789”就找不到的,因为再者之前字符串就认为已经是断了,后来自己写了一个查找函数,解决!
网络部分和MQTT部分我都做了封装,非常方便参考和移植,不多说直接贴上代码:
main.c部分
- #include "fy_includes.h"
- #include "fy_tlink.h"
- /*
- 晶振使用的是16M 其他频率在system_stm32f10x.c中修改
- 使用printf需要在fy_includes.h修改串口重定向为#define PRINTF_USART USART1
- */
- _typdef_adc _adc;
- u16 adc_light;
- u16 adc_ntc;
- u16 battery;
- float temperature;
- u8 led_sta;
- u8 sta;
- void Adc_GetValue(void);
- u8 txbuf[256];
- u8 rxbuf[256];
- char mqtt_message[200];
- void Mqtt_Progress(u8 *buf,u16 len);
- void UsartTrance(void)
- {
- while(1)
- {
- Led_Tog();
- Delay_ms(500);
- }
- }
- int main(void)
- {
- u8 cnt_2s=0;
- u16 cnt_5s=0;
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- Systick_Configuration();
- Led_Configuration();
- // UsartTrance();
- Key_Configuration();
- Adc_Configuration();
- Adc_DMA_Configuration((u32)&_adc.buf,ADC_FILTER*ADC_CH_MAX);
- Usart1_Configuration(115200);
- Usart2_Configuration(115200);
- Oled_Configuration();
- Usart1_SendString(" usart1 is ok!\r\n");
- // Usart2_SendString(" usart2 is ok!\r\n");
- Delay_ms(200);
-
- // UsartTrance();
- sta=0;
-
- //检查ESP8266
- if(_net.Init(rxbuf,sizeof(rxbuf),txbuf,sizeof(txbuf))!=0){
- Oled_ShowString(0,0*16,"Net Init OK!",8,16,1);
- // printf("Net Init OK!\r\n");
- sta++;
- }
- else{
- Oled_ShowString(0,0*16,"Net Init Error!",8,16,1);
- // printf("Net Init Error!\r\n");
- sta=0;
- }
- Oled_RefreshGram();
-
- if(sta==1){
- //连接热点
- if(_net.ConnectAP("ssid","password")!=0){
- Oled_ShowString(0,1*16,"Conncet AP OK!",8,16,1);
- // printf("Conncet AP OK!\r\n");
- sta++;
- }
- else {
- Oled_ShowString(0,1*16,"Conncet AP Error!",8,16,1);
- // printf("Conncet AP Error!\r\n");
- sta=0;
- }
- Oled_RefreshGram();
- }
-
- if(sta==2){
- //连接TCP
- if(_net.ConnectServer("TCP","a1ugBNniFGU.iot-as-mqtt.cn-shanghai.aliyuncs.com",1883)!=0) {
- Oled_ShowString(0,2*16,"Conet Server OK!",8,16,1);
- // printf("Conncet Server OK!\r\n");
- sta++;
- }
- else{
- Oled_ShowString(0,2*16,"Server Error!",8,16,1);
- // printf("Conncet Server Error!\r\n");
- sta=0;
- }
- Oled_RefreshGram();
- }
-
- if(sta==3){
- //登录MQTT
- _mqtt.Init(rxbuf,sizeof(rxbuf),txbuf,sizeof(txbuf));
- if(_mqtt.Connect(
- "123456|securemode=3,signmethod=hmacsha1,timestamp=789|",//ClientID
- "FY-STM32&a1ugBNniFGU",//Username
- "b447b9f26938d8eba6b2a4878066aae91839600c"//Password
- ) != 0){
- Oled_ShowString(0,3*16,"Enter MQTT OK!",8,16,1);
- // printf("Enter MQTT OK!\r\n");
- sta++;
- }
- else{
- Oled_ShowString(0,3*16,"Enter MQTT Error",8,16,1);
- // printf("Enter MQTT Error!\r\n");
- sta=0;
- }
- Oled_RefreshGram();
- }
-
- if(sta==4){
- Oled_Clear();
- //订阅主题
- if(_mqtt.SubscribeTopic("/sys/a1ugBNniFGU/FY-STM32/thing/service/property/set",0,1) != 0){
- Oled_ShowString(0,0*16,"Subscribe OK!",8,16,1);
- // printf("SubscribeTopic OK!\r\n");
- }
- else{
- Oled_ShowString(0,0*16,"Subscribe Error!",8,16,1);
- // printf("SubscribeTopic Error!\r\n");
- }
- Oled_RefreshGram();
- }
- Delay_ms(1000);
- Oled_Clear();
- Oled_ShowString(32,0*16,"Mars Tech",8,16,1);
- Oled_ShowString(0,1*16," VCC: 0000 mV",8,16,1);
- Oled_ShowString(0,2*16,"Temp: 00.0 C",8,16,1);
- Oled_ShowString(0,3*16," LUX: 0000 ",8,16,1);
- Oled_RefreshGram();
- sta = 0;
- while(1)
- {
- if(++cnt_2s>=200){
- cnt_2s=0;
- Adc_GetValue();
- temperature = Ntc_GetTemp(adc_ntc)*0.1f;
- Oled_ShowNum(8*6,1*16,battery,4,8,16);
- Oled_ShowNum(8*6,2*16,(u8)temperature,2,8,16);
- Oled_ShowNum(8*6+3*8,2*16,(u16)(temperature*10)%10,1,8,16);
- Oled_ShowNum(8*6,3*16,adc_light,4,8,16);
-
- Oled_RefreshGram();
- }
- if(++cnt_5s>=500){//
- cnt_5s=0;
- sprintf(mqtt_message,
- "{"method":"thing.service.property.set","id":"630262306","params":{\
- "CurrentTemperature":%.1f,\
- "hue":%d,\
- "mlux":%d\
- },"version":"1.0.0"}",
- temperature,
- rand()%0x00ffffff,
- adc_light
- );
-
- _mqtt.PublishData("/sys/a1ugBNniFGU/FY-STM32/thing/event/property/post",mqtt_message,0);
- }
- if(_mqtt.rxlen){
- Mqtt_Progress(_mqtt.rxbuf,_mqtt.rxlen);
- memset(_mqtt.rxbuf,0,_mqtt.rxlen);
- _mqtt.rxlen = 0;
- }
- Delay_ms(10);
- }
- }
- void Adc_GetValue(void)
- {
- u32 sum[ADC_CH_MAX];
- memset(sum,0,sizeof(sum));
- for(u8 ch=0; ch<ADC_CH_MAX; ch++)
- {
- for(u8 filter=0; filter<ADC_FILTER; filter++)
- {
- sum[ch] += _adc.buf[filter][ch];//计算累加和
- }
- }
- adc_light = sum[ADC_LIGHT]/ADC_FILTER;
- adc_ntc = sum[ADC_NTC]/ADC_FILTER;
- battery = sum[ADC_VCC]/ADC_FILTER*3300/4095*11; //mV
- }
- u8 temp;
- void USART2_IRQHandler(void)
- {
- static u8 rxlen = 0;
- if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //判断接收数据寄存器是否有数据
- {
- temp = USART2->DR;
- // USART1->DR = temp;//这里用作串口1打印WIFI模块发送的数据
- if(rxlen>=255) rxlen=0;
- rxbuf[rxlen++] = temp;
- rxlen%=sizeof(rxbuf);
- }
- if(USART_GetITStatus(USART2, USART_IT_IDLE))
- {
- temp = USART2->DR;
- temp = USART2->SR;
- _mqtt.rxlen = rxlen;
- // Mqtt_Progress(rxbuf,rxlen);//主循环做异步处理
- rxlen=0;
- }
- }
- //void *StrStr(void *dest,void *src);
- u8 *p;
- void Mqtt_Progress(u8 *buf,u16 len)
- {
- char *keyStr = "hue";
- u8 keyStrLen = strlen(keyStr)-1;
- u8 i,j;
- for(i=0;i<len-keyStrLen;i++)
- {
- for(j=0;j<keyStrLen;j++)
- {
- if(buf[i+j] != keyStr[j]) break;
- }
- if(j==keyStrLen) break;
- }
- if(i<=len-keyStrLen)
- {
- u16 temp = 0;
- p = &buf<i>;
-
- while(*p != ':') p++;
- p++;
- while(*p != '}')
- {
- temp = temp *10 + (*p - '0');
- p++</i>;
- }
- printf("receive message, hue = %d \r\n",temp);
- // Usart1_SendBuf(buf,len);
- }
- }
- /*********************************************END OF FILE********************************************/
复制代码
net.c部分
- #include "fy_network.h"
- //#define _DEBUG_NET
- static u8 Check(void);
- static u8 Init(u8 *prx,u16 rxlen,u8 *ptx,u16 txlen);
- static void Restore(void);
- static u8 ConnectAP(char* ssid,char* pswd);
- static u8 ConnectServer(char* mode,char* ip,u16 port);
- static u8 DisconnectServer(void);
- static u8 OpenTransmission(void);
- static void CloseTransmission(void);
- static void SendString(char* str);
- static void SendBuf(u8* buf,u16 len);
- _typdef_net _net=
- {
- 0,0,
- 0,0,
- Check,
- Init,
- Restore,
- ConnectAP,
- ConnectServer,
- DisconnectServer,
- OpenTransmission,
- CloseTransmission,
- SendString,
- SendBuf
- };
- /**
- * 功能:初始化ESP8266
- * 参数:None
- * 返回值:初始化结果,非0为初始化成功,0为失败
- */
- static u8 Init(u8 *prx,u16 rxlen,u8 *ptx,u16 txlen)
- {
- _net.rxbuf = prx;_net.rxlen = rxlen;
- _net.txbuf = ptx;_net.txlen = txlen;
-
- memset(_net.rxbuf,0,_net.rxlen);
- memset(_net.txbuf,0,_net.txlen);
-
- _net.CloseTransmission(); //退出透传
- Delay_ms(500);
- _net.SendString("AT+RST\r\n"); //重启ESP8266
- Delay_ms(800);
- if(_net.Check()==0) //使用AT指令检查ESP8266是否存在
- {
- return 0;
- }
- memset(_net.rxbuf,0,_net.rxlen); //清空接收缓冲
- _net.SendString("ATE0\r\n"); //关闭回显
- if(FindStr((char*)_net.rxbuf,"OK",500)==0) //设置不成功
- {
- return 0;
- }
- return 1; //设置成功
- }
- /**
- * 功能:恢复出厂设置
- * 参数:None
- * 返回值:None
- * 说明:此时ESP8266中的用户设置将全部丢失回复成出厂状态
- */
- static void Restore(void)
- {
- _net.CloseTransmission(); //退出透传
- Delay_ms(500);
- _net.SendString("AT+RESTORE\r\n");//恢复出厂
- // NVIC_SystemReset(); //同时重启单片机
- }
- /**
- * 功能:检查ESP8266是否正常
- * 参数:None
- * 返回值:ESP8266返回状态
- * 非0 ESP8266正常
- * 0 ESP8266有问题
- */
- static u8 Check(void)
- {
- u8 check_cnt=5;
- while(check_cnt--)
- {
- memset(_net.rxbuf,0,_net.rxlen); //清空接收缓冲
- _net.SendString("AT\r\n"); //发送AT握手指令
- if(FindStr((char*)_net.rxbuf,"OK",200) != 0)
- {
- return 1;
- }
- }
- return 0;
- }
- /**
- * 功能:连接热点
- * 参数:
- * ssid:热点名
- * pwd:热点密码
- * 返回值:
- * 连接结果,非0连接成功,0连接失败
- * 说明:
- * 失败的原因有以下几种(UART通信和ESP8266正常情况下)
- * 1. WIFI名和密码不正确
- * 2. 路由器连接设备太多,未能给ESP8266分配IP
- */
- static u8 ConnectAP(char* ssid,char* pswd)
- {
- u8 cnt=5;
- while(cnt--)
- {
- memset(_net.rxbuf,0,_net.rxlen);
- _net.SendString("AT+CWMODE_CUR=1\r\n"); //设置为STATION模式
- if(FindStr((char*)_net.rxbuf,"OK",200) != 0)
- {
- break;
- }
- }
- if(cnt == 0)
- return 0;
- cnt=2;
- while(cnt--)
- {
- memset(_net.txbuf,0,_net.txlen); //清空发送缓冲
- memset(_net.rxbuf,0,_net.rxlen); //清空接收缓冲
- sprintf((char*)_net.txbuf,"AT+CWJAP_CUR="%s","%s"\r\n",ssid,pswd);//连接目标AP
- _net.SendString((char*)_net.txbuf);
- if(FindStr((char*)_net.rxbuf,"OK",8000)!=0) //连接成功且分配到IP
- {
- return 1;
- }
- }
- return 0;
- }
- /**
- * 功能:使用指定协议(TCP/UDP)连接到服务器
- * 参数:
- * mode:协议类型 "TCP","UDP"
- * ip:目标服务器IP
- * port:目标是服务器端口号
- * 返回值:
- * 连接结果,非0连接成功,0连接失败
- * 说明:
- * 失败的原因有以下几种(UART通信和ESP8266正常情况下)
- * 1. 远程服务器IP和端口号有误
- * 2. 未连接AP
- * 3. 服务器端禁止添加(一般不会发生)
- */
- static u8 ConnectServer(char* mode,char* ip,u16 port)
- {
- u8 cnt;
- _net.CloseTransmission(); //多次连接需退出透传
- Delay_ms(500);
- //连接服务器
- cnt=2;
- while(cnt--)
- {
- memset(_net.rxbuf,0,_net.rxlen);
- memset(_net.txbuf,0,_net.txlen);
- sprintf((char*)_net.txbuf,"AT+CIPSTART="%s","%s",%d\r\n",mode,ip,port);
- _net.SendString((char*)_net.txbuf);
- if(FindStr((char*)_net.rxbuf,"CONNECT",8000) !=0 )
- {
- break;
- }
- }
- if(cnt == 0)
- return 0;
-
- //设置透传模式
- if(_net.OpenTransmission()==0) return 0;
-
- //开启发送状态
- cnt=2;
- while(cnt--)
- {
- memset(_net.rxbuf,0,_net.rxlen);
- _net.SendString("AT+CIPSEND\r\n");//开始处于透传发送状态
- if(FindStr((char*)_net.rxbuf,">",200)!=0)
- {
- return 1;
- }
- }
- return 0;
- }
- /**
- * 功能:主动和服务器断开连接
- * 参数:None
- * 返回值:
- * 连接结果,非0断开成功,0断开失败
- */
- static u8 DisconnectServer(void)
- {
- u8 cnt;
- _net.CloseTransmission(); //退出透传
- Delay_ms(500);
- while(cnt--)
- {
- memset(_net.rxbuf,0,_net.rxlen);
- _net.SendString("AT+CIPCLOSE\r\n");//关闭链接
- if(FindStr((char*)_net.rxbuf,"CLOSED",200)!=0)//操作成功,和服务器成功断开
- {
- break;
- }
- }
- if(cnt) return 1;
- return 0;
- }
- /**
- * 功能:透传模式下的数据发送函数
- * 参数:
- * buffer:待发送数据
- * 返回值:None
- */
- static void SendBuf(u8* buf,u16 len)
- {
- memset(_net.rxbuf,0,_net.rxlen);
- #ifdef _DEBUG_NET
- Usart1_SendBuf(buf,len);
- #endif
- Net_SendBuf(buf,len);
- }
- /**
- * 功能:透传模式下的数据发送函数
- * 参数:
- * buffer:待发送数据
- * 返回值:None
- */
- static void SendString(char* str)
- {
- memset(_net.rxbuf,0,_net.rxlen);
- #ifdef _DEBUG_NET
- Usart1_SendString(str);
- #endif
- Net_SendString(str);
- }
- static u8 OpenTransmission(void)
- {
- //设置透传模式
- u8 cnt=2;
- while(cnt--)
- {
- memset(_net.rxbuf,0,_net.rxlen);
- _net.SendString("AT+CIPMODE=1\r\n");
- if(FindStr((char*)_net.rxbuf,"OK",200)!=0)
- {
- return 1;
- }
- }
- return 0;
- }
- //退出透传
- static void CloseTransmission(void)
- {
- _net.SendString("+++"); Delay_ms(50);
- _net.SendString("+++"); Delay_ms(50);
- }
- /*********************************************END OF FILE********************************************/
复制代码
net.h部分
- #ifndef __FY_NETWORK_H
- #define __FY_NETWORK_H
- #include "fy_includes.h"
- /*连接AP宏定义*/
- #define SSID "ssid"
- #define PWD "password"
- /*连接服务器宏定义*/
- #define TCP "TCP"
- #define UDP "UDP"
- #define IP "122.114.122.174"
- #define PORT 40915
- #define Net_SendString(str) Usart2_SendString(str)
- #define Net_SendBuf(buf,len) Usart2_SendBuf(buf,len)
- typedef struct
- {
- u8 *rxbuf;u16 rxlen;
- u8 *txbuf;u16 txlen;
-
- u8 (*Check)(void);
- u8 (*Init)(u8 *prx,u16 rxlen,u8 *ptx,u16 txlen);
- void (*Restore)(void);
- u8 (*ConnectAP)(char *ssid,char *pswd);
- u8 (*ConnectServer)(char* mode,char *ip,u16 port);
- u8 (*DisconnectServer)(void);
- u8 (*OpenTransmission)(void);
- void (*CloseTransmission)(void);
- void (*SendString)(char *str);
- void (*SendBuf)(u8 *buf,u16 len);
- }_typdef_net;
- extern _typdef_net _net;
- #endif
- /*********************************************END OF FILE********************************************/
复制代码
mqtt.c部分
- #include "fy_mqtt.h"
- //#define _DEBUG_MQTT
- typedef enum
- {
- //名字 值 报文流动方向 描述
- M_RESERVED1 =0 , // 禁止 保留
- M_CONNECT , // 客户端到服务端 客户端请求连接服务端
- M_CONNACK , // 服务端到客户端 连接报文确认
- M_PUBLISH , // 两个方向都允许 发布消息
- M_PUBACK , // 两个方向都允许 QoS 1消息发布收到确认
- M_PUBREC , // 两个方向都允许 发布收到(保证交付第一步)
- M_PUBREL , // 两个方向都允许 发布释放(保证交付第二步)
- M_PUBCOMP , // 两个方向都允许 QoS 2消息发布完成(保证交互第三步)
- M_SUBSCRIBE , // 客户端到服务端 客户端订阅请求
- M_SUBACK , // 服务端到客户端 订阅请求报文确认
- M_UNSUBSCRIBE , // 客户端到服务端 客户端取消订阅请求
- M_UNSUBACK , // 服务端到客户端 取消订阅报文确认
- M_PINGREQ , // 客户端到服务端 心跳请求
- M_PINGRESP , // 服务端到客户端 心跳响应
- M_DISCONNECT , // 客户端到服务端 客户端断开连接
- M_RESERVED2 , // 禁止 保留
- }_typdef_mqtt_message;
- //连接成功服务器回应 20 02 00 00
- //客户端主动断开连接 e0 00
- const u8 parket_connetAck[] = {0x20,0x02,0x00,0x00};
- const u8 parket_disconnet[] = {0xe0,0x00};
- const u8 parket_heart[] = {0xc0,0x00};
- const u8 parket_heart_reply[] = {0xc0,0x00};
- const u8 parket_subAck[] = {0x90,0x03};
- static void Mqtt_SendBuf(u8 *buf,u16 len);
- static void Init(u8 *prx,u16 rxlen,u8 *ptx,u16 txlen);
- static u8 Connect(char *ClientID,char *Username,char *Password);
- static u8 SubscribeTopic(char *topic,u8 qos,u8 whether);
- static u8 PublishData(char *topic, char *message, u8 qos);
- static void SentHeart(void);
- static void Disconnect(void);
- _typdef_mqtt _mqtt =
- {
- 0,0,
- 0,0,
- Init,
- Connect,
- SubscribeTopic,
- PublishData,
- SentHeart,
- Disconnect,
- };
- static void Init(u8 *prx,u16 rxlen,u8 *ptx,u16 txlen)
- {
- _mqtt.rxbuf = prx;_mqtt.rxlen = rxlen;
- _mqtt.txbuf = ptx;_mqtt.txlen = txlen;
-
- memset(_mqtt.rxbuf,0,_mqtt.rxlen);
- memset(_mqtt.txbuf,0,_mqtt.txlen);
-
- //无条件先主动断开
- _mqtt.Disconnect();Delay_ms(100);
- _mqtt.Disconnect();Delay_ms(100);
- }
- //连接服务器的打包函数
- static u8 Connect(char *ClientID,char *Username,char *Password)
- {
- int ClientIDLen = strlen(ClientID);
- int UsernameLen = strlen(Username);
- int PasswordLen = strlen(Password);
- int DataLen;
- _mqtt.txlen=0;
- //可变报头+Payload 每个字段包含两个字节的长度标识
- DataLen = 10 + (ClientIDLen+2) + (UsernameLen+2) + (PasswordLen+2);
-
- //固定报头
- //控制报文类型
- _mqtt.txbuf[_mqtt.txlen++] = 0x10; //MQTT Message Type CONNECT
- //剩余长度(不包括固定头部)
- do
- {
- u8 encodedByte = DataLen % 128;
- DataLen = DataLen / 128;
- // if there are more data to encode, set the top bit of this byte
- if ( DataLen > 0 )
- encodedByte = encodedByte | 128;
- _mqtt.txbuf[_mqtt.txlen++] = encodedByte;
- }while ( DataLen > 0 );
-
- //可变报头
- //协议名
- _mqtt.txbuf[_mqtt.txlen++] = 0; // Protocol Name Length MSB
- _mqtt.txbuf[_mqtt.txlen++] = 4; // Protocol Name Length LSB
- _mqtt.txbuf[_mqtt.txlen++] = 'M'; // ASCII Code for M
- _mqtt.txbuf[_mqtt.txlen++] = 'Q'; // ASCII Code for Q
- _mqtt.txbuf[_mqtt.txlen++] = 'T'; // ASCII Code for T
- _mqtt.txbuf[_mqtt.txlen++] = 'T'; // ASCII Code for T
- //协议级别
- _mqtt.txbuf[_mqtt.txlen++] = 4; // MQTT Protocol version = 4
- //连接标志
- _mqtt.txbuf[_mqtt.txlen++] = 0xc2; // conn flags
- _mqtt.txbuf[_mqtt.txlen++] = 0; // Keep-alive Time Length MSB
- _mqtt.txbuf[_mqtt.txlen++] = 60; // Keep-alive Time Length LSB 60S心跳包
-
- _mqtt.txbuf[_mqtt.txlen++] = BYTE1(ClientIDLen);// Client ID length MSB
- _mqtt.txbuf[_mqtt.txlen++] = BYTE0(ClientIDLen);// Client ID length LSB
- memcpy(&_mqtt.txbuf[_mqtt.txlen],ClientID,ClientIDLen);
- _mqtt.txlen += ClientIDLen;
- if(UsernameLen > 0)
- {
- _mqtt.txbuf[_mqtt.txlen++] = BYTE1(UsernameLen); //username length MSB
- _mqtt.txbuf[_mqtt.txlen++] = BYTE0(UsernameLen); //username length LSB
- memcpy(&_mqtt.txbuf[_mqtt.txlen],Username,UsernameLen);
- _mqtt.txlen += UsernameLen;
- }
- if(PasswordLen > 0)
- {
- _mqtt.txbuf[_mqtt.txlen++] = BYTE1(PasswordLen); //password length MSB
- _mqtt.txbuf[_mqtt.txlen++] = BYTE0(PasswordLen); //password length LSB
- memcpy(&_mqtt.txbuf[_mqtt.txlen],Password,PasswordLen);
- _mqtt.txlen += PasswordLen;
- }
-
- u8 cnt=2;
- u8 wait;
- while(cnt--)
- {
- memset(_mqtt.rxbuf,0,_mqtt.rxlen);
- Mqtt_SendBuf(_mqtt.txbuf,_mqtt.txlen);
- wait=30;//等待3s时间
- while(wait--)
- {
- //CONNECT
- if(_mqtt.rxbuf[0]==parket_connetAck[0] && _mqtt.rxbuf[1]==parket_connetAck[1]) //连接成功
- {
- return 1;//连接成功
- }
- Delay_ms(100);
- }
- }
- return 0;
- }
- //MQTT订阅/取消订阅数据打包函数
- //topic 主题
- //qos 消息等级
- //whether 订阅/取消订阅请求包
- static u8 SubscribeTopic(char *topic,u8 qos,u8 whether)
- {
- _mqtt.txlen=0;
- int topiclen = strlen(topic);
-
- int DataLen = 2 + (topiclen+2) + (whether?1:0);//可变报头的长度(2字节)加上有效载荷的长度
- //固定报头
- //控制报文类型
- if(whether) _mqtt.txbuf[_mqtt.txlen++] = 0x82; //消息类型和标志订阅
- else _mqtt.txbuf[_mqtt.txlen++] = 0xA2; //取消订阅
- //剩余长度
- do
- {
- u8 encodedByte = DataLen % 128;
- DataLen = DataLen / 128;
- // if there are more data to encode, set the top bit of this byte
- if ( DataLen > 0 )
- encodedByte = encodedByte | 128;
- _mqtt.txbuf[_mqtt.txlen++] = encodedByte;
- }while ( DataLen > 0 );
-
- //可变报头
- _mqtt.txbuf[_mqtt.txlen++] = 0; //消息标识符 MSB
- _mqtt.txbuf[_mqtt.txlen++] = 0x01; //消息标识符 LSB
- //有效载荷
- _mqtt.txbuf[_mqtt.txlen++] = BYTE1(topiclen);//主题长度 MSB
- _mqtt.txbuf[_mqtt.txlen++] = BYTE0(topiclen);//主题长度 LSB
- memcpy(&_mqtt.txbuf[_mqtt.txlen],topic,topiclen);
- _mqtt.txlen += topiclen;
- if(whether)
- {
- _mqtt.txbuf[_mqtt.txlen++] = qos;//QoS级别
- }
-
- u8 cnt=2;
- u8 wait;
- while(cnt--)
- {
- memset(_mqtt.rxbuf,0,_mqtt.rxlen);
- Mqtt_SendBuf(_mqtt.txbuf,_mqtt.txlen);
- wait=30;//等待3s时间
- while(wait--)
- {
- if(_mqtt.rxbuf[0]==parket_subAck[0] && _mqtt.rxbuf[1]==parket_subAck[1]) //订阅成功
- {
- return 1;//订阅成功
- }
- Delay_ms(100);
- }
- }
- if(cnt) return 1; //订阅成功
- return 0;
- }
- //MQTT发布数据打包函数
- //topic 主题
- //message 消息
- //qos 消息等级
- static u8 PublishData(char *topic, char *message, u8 qos)
- {
- int topicLength = strlen(topic);
- int messageLength = strlen(message);
- static u16 id=0;
- int DataLen;
- _mqtt.txlen=0;
- //有效载荷的长度这样计算:用固定报头中的剩余长度字段的值减去可变报头的长度
- //QOS为0时没有标识符
- //数据长度 主题名 报文标识符 有效载荷
- if(qos) DataLen = (2+topicLength) + 2 + messageLength;
- else DataLen = (2+topicLength) + messageLength;
- //固定报头
- //控制报文类型
- _mqtt.txbuf[_mqtt.txlen++] = 0x30; // MQTT Message Type PUBLISH
- //剩余长度
- do
- {
- u8 encodedByte = DataLen % 128;
- DataLen = DataLen / 128;
- // if there are more data to encode, set the top bit of this byte
- if ( DataLen > 0 )
- encodedByte = encodedByte | 128;
- _mqtt.txbuf[_mqtt.txlen++] = encodedByte;
- }while ( DataLen > 0 );
-
- _mqtt.txbuf[_mqtt.txlen++] = BYTE1(topicLength);//主题长度MSB
- _mqtt.txbuf[_mqtt.txlen++] = BYTE0(topicLength);//主题长度LSB
- memcpy(&_mqtt.txbuf[_mqtt.txlen],topic,topicLength);//拷贝主题
- _mqtt.txlen += topicLength;
- //报文标识符
- if(qos)
- {
- _mqtt.txbuf[_mqtt.txlen++] = BYTE1(id);
- _mqtt.txbuf[_mqtt.txlen++] = BYTE0(id);
- id++;
- }
- memcpy(&_mqtt.txbuf[_mqtt.txlen],message,messageLength);
- _mqtt.txlen += messageLength;
- Mqtt_SendBuf(_mqtt.txbuf,_mqtt.txlen);
- return _mqtt.txlen;
- }
- static void SentHeart(void)
- {
- Mqtt_SendBuf((u8 *)parket_heart,sizeof(parket_heart));
- }
- static void Disconnect(void)
- {
- Mqtt_SendBuf((u8 *)parket_disconnet,sizeof(parket_disconnet));
- }
- static void Mqtt_SendBuf(u8 *buf,u16 len)
- {
- #ifdef _DEBUG_MQTT
- Usart1_SendBuf(buf,len);
- #endif
- Usart2_SendBuf(buf,len);
- }
- /*********************************************END OF FILE********************************************/
复制代码
mqtt.h部分
- #ifndef __FY_MQTT_H_
- #define __FY_MQTT_H_
- #include "fy_includes.h"
- typedef struct
- {
- u8 *rxbuf;u16 rxlen;
- u8 *txbuf;u16 txlen;
- void (*Init)(u8 *prx,u16 rxlen,u8 *ptx,u16 txlen);
- u8 (*Connect)(char *ClientID,char *Username,char *Password);
- u8 (*SubscribeTopic)(char *topic,u8 qos,u8 whether);
- u8 (*PublishData)(char *topic, char *message, u8 qos);
- void (*SendHeart)(void);
- void (*Disconnect)(void);
- }_typdef_mqtt;
- extern _typdef_mqtt _mqtt;
- #endif
复制代码
|