FreeRTOS下WIFI模块下的socket(三)
·
该章节主要为ESP8266方面的应用程序
一.ESP8266连接AP
int esp8266_connect_ap(char *ssid, char *passwd)
{
PAT_Device ptDev = get_esp8266_device();
if(NULL == ptDev)
return -1;
char cmd[128];
char *fix_cmd = NULL;
//设置WiFi模式为STA
fix_cmd = "AT+CWMODE=1\r\n";
if(at_exec_cmd(ptDev, (int8_t *)fix_cmd, NULL, 0, NULL, AT_TIMEOUT))
return -1;
//连接AP
if(passwd)
{
snprintf((char *)cmd, sizeof(cmd), "AT+CWJAP=\"%s\",\"%s\"\r\n", ssid, passwd);
}
else
{
snprintf((char *)cmd, sizeof(cmd), "AT+CWJAP=\"%s\",\"\"\r\n", ssid);
}
if(at_exec_cmd(ptDev,(int8_t *)cmd, NULL, 0, NULL, 5000)) // 5秒超时
return -1;
//查询IP地址(可选)
fix_cmd = "AT+CIFSR\r\n";
if(at_exec_cmd(ptDev, (int8_t *)fix_cmd, NULL, 0, NULL, AT_TIMEOUT))
return -1;
//执行: AT+GMR(可选)
// fix_cmd = "AT+GMR\r\n";
// if(at_exec_cmd(ptDev, (int8_t *)fix_cmd, NULL, 0, NULL, AT_TIMEOUT))
// return -1;
//执行: AT+CIPRECVMODE=0 接收数据的模式
fix_cmd = "AT+CIPRECVMODE=0\r\n";
if(at_exec_cmd(ptDev, (int8_t *)fix_cmd, NULL, 0, NULL, AT_TIMEOUT))
return -1;
return 0;
}
二.ESP8266作为server监听(TCP连接)
//esp8266作为server监听(TCP连接)
//backlog对ESP8266来说最大支持4个连接
int esp8266_listen(int socket, int backlog)
{
PAT_Device ptDev = get_esp8266_device();
if(NULL == ptDev)
return -1;
if(socket < 0 || socket > AT_MAX_SOCKETS_NUM)
return -1;
PAT_Socket ptSocket = &ptDev->sockets[socket];
char cmd[32];
//执行: AT+CIPMUX=1\r\n 使能多连接
if(at_exec_cmd(ptDev, (int8_t *)"AT+CIPMUX=1\r\n", NULL, 0, NULL, AT_TIMEOUT))
return -1;
//执行: AT+CIPSERVERMAXCONN=4\r\n 允许4个连接
sprintf(cmd, "AT+CIPSERVERMAXCONN=%d\r\n", backlog);
if(at_exec_cmd(ptDev, (int8_t *)cmd, NULL, 0, NULL, AT_TIMEOUT))
return -1;
//执行: AT+CIPSERVER=1,8888 建立服务器监听端口
//获取到端口号
char cmdbuf[32];
struct sockaddr_in *ptAddr = (struct sockaddr_in *)&ptSocket->local;
uint16_t port = ntohs(ptAddr->sin_port);
sprintf(cmdbuf, "AT+CIPSERVER=1,%d\r\n", port);
if(at_exec_cmd(ptDev, (int8_t *)cmdbuf, NULL, 0, NULL, AT_TIMEOUT))
return -1;
return 0;
}
三.ESP8266作为server被client连接(TCP连接)
//esp8266作为server被client连接(TCP连接)
//配置client的socket信息
int esp8266_accept(int socket, struct sockaddr *name, socklen_t *namelen)
{
PAT_Device ptDev = get_esp8266_device();
if(NULL == ptDev)
return -1;
if(socket < 0 || socket > AT_MAX_SOCKETS_NUM)
return -1;
if(NULL == name)
return -1;
PAT_Socket ptSocket = &ptDev->sockets[socket];
//获得锁
xSemaphoreTake(ptSocket->at_send_lock, portMAX_DELAY);
//执行: AT+CIPSTATUS 查询网络连接信息
char *cmd = "AT+CIPSTATUS\r\n";
if(at_exec_cmd(ptDev, (int8_t *)cmd, NULL, 0, NULL, AT_TIMEOUT))
{
//释放锁
xSemaphoreGive(ptSocket->at_send_lock);
return -1;
}
struct sockaddr_in *ptAddr = (struct sockaddr_in *)&ptSocket->local;
uint16_t server_port = ntohs(ptAddr->sin_port);
//解析接收到的数据AT结构里的resp
//STATUS:<stat>
//+CIPSTATUS:<link ID>,<type>,<remote IP>,<remote port>,<local port>,<tetype>
if(ptDev->resp_line_counts >= 2) //跳过第1行
{
for(int i=1; i<ptDev->resp_line_counts && i <AT_RESP_MAX_LINE; i++)
{
uint8_t *line = ptDev->resp[i]; //指向当前行(每行以'\0'结尾)
if(strstr((char *)line, "+CIPSTATUS:")) //做对比
{
//解析格式: +CIPSTATUS:<link ID>,<type>,<remote IP>,<remote port>,<local port>,<tetype>
int hw_socket;
uint16_t recv_socket=0;
char type[10] = {0};
uint8_t remote_ip[32] = {0};
uint16_t remote_ip_len=0;
uint16_t remote_port;
uint16_t local_port;
int tetype;
int parsed = sscanf((const char *)line, "+CIPSTATUS:%hu,%9[^,],\"%31[^,],%hu,%hu,%d",
(uint16_t *)&recv_socket, type, remote_ip, &remote_port, &local_port, &tetype);
if(parsed == 6)
{
hw_socket = recv_socket;
if(get_socket_for_hw_socket(hw_socket) != NULL) //找到一个used为1,但是uaser_data不为hw_socket的socket。(已创建,但未连接)
{ //没找到的话,创建一个新的硬件socket,并填充
continue;
}
if(local_port != server_port)
{
continue;
}
//新分配设置socket结构体,来填充返回的hw_socket结构
int sw_socket = esp8266_socket(AF_INET, SOCK_STREAM, 0);
if(sw_socket < 0 || sw_socket > AT_DEVICE_SOCKETS_NUM)
{
return -1;
}
PAT_Socket ptSocket2 = &ptDev->sockets[sw_socket];
ptSocket2->user_data = (void *)hw_socket;
ptSocket2->at_socket_open_flag=1;
struct sockaddr_in *addr = (struct sockaddr_in *)name;
addr->sin_family = AF_INET; //协议
addr->sin_port = htons(remote_port); //端口
remote_ip_len = strlen((char *)remote_ip);
if(remote_ip_len <=32)
{
remote_ip[remote_ip_len-1] =0;
remote_ip[remote_ip_len] =0;
}
inet_pton(AF_INET, (char *)remote_ip, &addr->sin_addr); //ip
if(namelen)
{
*namelen = sizeof(struct sockaddr_in);
}
ptSocket2->remote =(*((struct sockaddr*)addr));
addr = (struct sockaddr_in *)&ptSocket->local; //指向local,修改server端port
addr->sin_family = AF_INET;
addr->sin_port = htons(local_port);
//释放锁
xSemaphoreGive(ptSocket->at_send_lock);
at_reset_resp(ptDev);
return sw_socket; // 返回链接ID作为socket描述符
}
}
}
}
//释放锁
xSemaphoreGive(ptSocket->at_send_lock);
return -1; // 解析失败或无连接
}
四.ESP8266作为client去连接server端(TCP/UDP连接)
//esp8266作为client去连接server端(TCP连接)
//esp8266发送at命令去连接(UDP连接)
//AT+CIPSTART=<link ID>,<type>,<remote IP>,<remote port>[,<TCP keep alive>]
int esp8266_connect(int socket, const struct sockaddr *name, socklen_t namelen)
{
PAT_Device ptDev = get_esp8266_device();
if(NULL == ptDev)
return -1;
if(socket < 0 || socket > AT_MAX_SOCKETS_NUM)
return -1;
if(NULL == name)
return -1;
PAT_Socket ptSocket = &ptDev->sockets[socket];
int link_id = 0;
//作为client去连接server,link_id只有1个无所谓,我分配他索引值
if(socket > AT_DEVICE_SOCKETS_NUM)
{
link_id = AT_MAX_SOCKETS_NUM;
}
else
{
link_id = socket;
if(link_id < 0)
{
// 释放锁
xSemaphoreGive(ptSocket->at_send_lock);
return -1;
}
}
//转化一下remote的ip和port
struct sockaddr_in *ptAddr = (struct sockaddr_in *)name;
uint16_t remote_port = ntohs(ptAddr->sin_port); //remote port
uint16_t local_port = 0;
if(ptSocket->type == SOCK_DGRAM)
{
struct sockaddr_in *local = (struct sockaddr_in *)&ptSocket->local;
local_port = ntohs(local->sin_port); //local port
}
char cmd[64] = {0};
char *ipstr;
ipaddr_to_ipstr(name, ipstr); //remote ip
//发送指令
if(ptSocket->type == SOCK_STREAM) //TCP
{
sprintf(cmd, "AT+CIPSTART=%d,\"%s\",\"%s\",%d\r\n", link_id, "TCP", ipstr, remote_port);
}
else if(ptSocket->type == SOCK_DGRAM) //UDP
{
sprintf(cmd, "AT+CIPSTART=%d,\"%s\",\"%s\",%d,%d\r\n", link_id, "UDP", ipstr, remote_port, local_port);
}
if(at_exec_cmd(ptDev, (int8_t *)cmd, NULL, 0, NULL, AT_TIMEOUT))
{
// 释放锁
xSemaphoreGive(ptSocket->at_send_lock);
return -1;
}
ptSocket->user_data = (void *)link_id;//socket id赋值
ptSocket->at_socket_open_flag=1;
// 释放锁
xSemaphoreGive(ptSocket->at_send_lock);
return 0;
}
五.ESP8266连接上后发送指令
//esp8266连接上发送指令: AT+CIPSEND=<link ID>,<length>(TCP连接)
//esp8266连接上发送指令: AT+CIPSEND=[<link ID>,]<length>[,<remote IP>,<remote port>](UDP连接)
int esp8266_sendto(int socket, const void *data, size_t size, int flags, const struct sockaddr *to, socklen_t tolen)
{
// 对于TCP连接: AT+CIPSEND=<link ID>,<length>
// 对于UDP: AT+CIPSEND=[<link ID>,]<length>[,<remote IP>,<remote port>]
PAT_Device ptDev = get_esp8266_device();
if(NULL == ptDev)
return -1;
if(socket < 0 || socket > AT_MAX_SOCKETS_NUM)
return -1;
if(NULL == data)
return -1;
PAT_Socket ptSocket = &ptDev->sockets[socket];
char cmd[64] = {0};
int hw_socket = ((int)(ptSocket->user_data));
if(hw_socket < 0 || hw_socket > AT_MAX_SOCKETS_NUM || size==0)
return -1;
// 获得锁
xSemaphoreTake(ptSocket->at_send_lock, portMAX_DELAY);
if(ptSocket->type == SOCK_STREAM)
{
sprintf(cmd, "AT+CIPSENDEX=%d,%d\r\n", hw_socket, size);
}
else if(ptSocket->type == SOCK_DGRAM && to != NULL)
{
char ipstr[32] = {0};
struct sockaddr_in *paddr = (struct sockaddr_in *)to;
uint16_t port = ntohs(paddr->sin_port);
ipaddr_to_ipstr((const struct sockaddr *)paddr, ipstr);
sprintf((char *)cmd, "AT+CIPSENDEX=%d,%d,\"%s\",%d\r\n", hw_socket, size, ipstr, port);
}
else
{
// 释放锁
xSemaphoreGive(ptSocket->at_send_lock);
return -1;
}
//发送AT命令
at_exec_cmd(ptDev, (int8_t *)cmd, NULL, 0, NULL, (AT_TIMEOUT));
osDelay(30);
if(at_send_datas(ptDev,(uint8_t *)data, size, (AT_TIMEOUT)))
{
//释放锁
xSemaphoreGive(ptSocket->at_send_lock);
return -1;
}
// 释放锁
xSemaphoreGive(ptSocket->at_send_lock);
return 0;
}
六.ESP8266连接上后接收数据(TCP/UDP连接)
//esp8266连接上后接收数据(TCP/UDP连接)
int esp8266_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
{
PAT_Device ptDev = get_esp8266_device();
if(NULL == ptDev)
return -1;
if(socket < 0 || socket > AT_MAX_SOCKETS_NUM)
return -1;
if(NULL == mem)
return -1;
PAT_Socket ptSocket = &ptDev->sockets[socket];
uint8_t data;
size_t recv_len = 0;
uint8_t *pdata = (uint8_t *)mem;
//对于UDP,先发起AT命令来连接
if((ptSocket->type == SOCK_DGRAM) && (from != NULL))
{
if(ptSocket->at_socket_open_flag==0)
{
if(esp8266_connect(socket, from, *fromlen))
{
return -1;
}
}
}
//尝试从接收队列读取遗留的数据
while(xQueueReceive(ptSocket->recv_queue, &data, 0) == pdTRUE)
{
if(recv_len < len)
{
pdata[recv_len] = data;
}
recv_len++;
if(recv_len >= len)
{
return recv_len;
}
}
if(recv_len > 0)
{
return recv_len;
}
//无数据则等待信号量
if(xSemaphoreTake(ptSocket->at_packet_sem, portMAX_DELAY) != pdTRUE)
{
return -1;
}
//再次尝试从接收队列读取数据
while(xQueueReceive(ptSocket->recv_queue, &data, 0) == pdTRUE)
{
if(recv_len < len)
{
pdata[recv_len] = data;
}
recv_len++;
if(recv_len >= len)
{
return recv_len;
}
}
return recv_len;
}
更多推荐



所有评论(0)