这节主要实现mqtt移植,在上一节的基础上利用ESP32完善接口
主要思路:MQTT作为一个应用层协议,对接底层TCP通信时候只需要满足“连接”、“发送”、“接收”、“断开” 四个接口即可,如下图所示,不管对接的底层是什么,只要能满足四个接口即可。
1、连接 socket_connect
int platform_net_socket_connect(const char *host, const char *port, int proto)
{
char cmd[100];
char *ssid = "W201314H";
char *pwd = "heguobao";
unsigned int rc;
rc = ESP8266_SendCommand("AT+RST", "OK", 2000);
if (rc)
return -1;
HAL_Delay(800);
rc = ESP8266_SendCommand("AT+CWMODE=1", "OK", 500);
if (rc)
return -1;
sprintf(cmd, "AT+CWJAP=\"%s\",\"%s\"", ssid, pwd);
rc = ESP8266_SendCommand(cmd, "OK", 5000);
if (rc)
return -1;
rc = ESP8266_SendCommand("AT+CIPCLOSE", "OK", 500);
sprintf(cmd, "AT+CIPSTART=\"TCP\",\"%s\",%s,0", host, port);
rc = ESP8266_SendCommand(cmd, "OK", 5000);
if (rc)
return -1;
ESP8266_GetIP();
return 0;
}
uint8_t ESP8266_SendCommand(char *cmd, char *reply, uint16_t timeout)
{
char buf[256] = {0};
strcat(buf, cmd); //strcpy
if (strstr(buf, "\r\n") == 0)
{
strcat(buf, "\r\n");
}
USART2_ClearBuf();
USART2_Transmit((uint8_t *)buf, strlen(buf), 500);
memset(buf, 0, 256);
while(timeout != 0)
{
if (USART2_Receive((uint8_t *)buf))
{
if (strstr(buf, reply))
{
printf("%s Send ok!\r\n", cmd);
return 0;
}
}
timeout--;
HAL_Delay(1);
}
printf("%s Send error!\r\n", cmd);
return 1;
}
uint8_t ESP8266_GetIP(void)
{
uint16_t timeout = 500;
char buf[256] = {0};
strcat(buf, "AT+CIFSR\r\n");
USART2_ClearBuf();
USART2_Transmit((uint8_t *)buf, strlen(buf), 500);
memset(buf, 0, 256);
while(timeout != 0)
{
if (USART2_Receive((uint8_t *)buf))
{
if (strstr(buf, "OK"))
{
Show_IP(buf);
return 0;
}
else
{
timeout--;
HAL_Delay(1);
}
}
}
printf("Get IP Failed! \r\n");
return 1;
}
2、发送 socket_write
int platform_net_socket_write_timeout(int fd, unsigned char *buf, int len, int timeout)
{
extern int ESP8266_Send_Packet(unsigned char *data, int len);
int i;
if (len == 2)
printf("datas: 0x%x, 0x%x\r\n", buf[0], buf[1]);
printf("Send Packet: ");
for (i = 0; i < len; i++)
printf("%02x ", buf[i]);
printf("\r\n");
return ESP8266_Send_Packet(buf, len);
}
int ESP8266_Send_Packet(unsigned char *data, int len)
{
char buf[256] = {0};
sprintf(buf, "AT+CIPSEND=%d\r\n", len);
if (ESP8266_SendCommand(buf, "OK", 500) == 0)
{
ESP8266_SendRawData(data, len, "SEND OK", 1000);
return len;
}
return 0;
}
uint8_t ESP8266_SendRawData(unsigned char *data, int len, char *reply, uint16_t timeout)
{
char buf[256] = {0};
USART2_ClearBuf();
USART2_Transmit((uint8_t *)data, len, 500);
memset(buf, 0, 256);
while(timeout != 0)
{
if (USART2_Receive((uint8_t *)buf))
{
if (strstr(buf, reply))
{
return 0;
}
else
{
timeout--;
HAL_Delay(1);
}
}
}
return 1;
}
3、接收 socket_recv
int platform_net_socket_recv_timeout(int fd, unsigned char *buf, int len, int timeout)
{
extern int ESP8266ReadPacket(unsigned char *buf, int len);
int time = platform_timer_now();
int rlen = 0;
int ret = len;
timeout += time;
while ((platform_timer_now() < timeout) && len)
{
rlen = ESP8266ReadPacket(buf, len);
buf += rlen;
len -= rlen;
}
return (ret - len);
}
int ESP8266ReadPacket(unsigned char *buf, int len)
{
int i;
for (i = 0; i < len; i++)
{
if (g_PacketR != g_PacketW)
{
buf[i] = g_ESP8266PacketBuff[g_PacketR];
g_PacketR = (g_PacketR+1) & 511;
}
else
{
return i;
}
}
return i;
}
4、断开socket_close
int platform_net_socket_close(int fd)
{
ESP8266_SendCommand("AT+CIPCLOSE", "OK", 500);
return 0;
}
MQTT在通信时候所有的数据传输接口经过层层封装,最终都是调用那4个接口!