Создадим TCP клиент на микроконтроллере (модуле) ESP8266.
В файле user_config.h напишем дефайны для точки доступа
#define WiFi_Client_SSID "qwe1" //в SSID обязательно должны быть цифры!!!!
#define WiFi_Client_Password "12345678"
#define TCP_SERVER_IP "192.168.0.53"
#define TCP_SERVER_PORT 30000
В файле main.c
Добавляем #include:
#include "driver/uart.h"
#include "espconn.h"
#include "mem.h"
Добавляем переменные:
//------------------------------------------------------
//User_Variables
//------------------------------------------------------
static os_timer_t os_timer01;
static uint8_t led_state=0;
//for wifi
struct espconn pConn;
esp_udp ConnUDP;
//------------------------------------------------------
//перечисление и переменная с состоянием Wifi
typedef enum{
WIFI_CONNECTING,
WIFI_CONNECTING_ERROR,
WIFI_CONNECTED
} tConnState;
static tConnState ConnState=WIFI_CONNECTING;
//------------------------------------------------------
Добавляем следующий код:
static void ICACHE_FLASH_ATTR wifi_check_ip(void *arg); //прототип функции
//------------------------------------------------------
//Functions INTERRUPT WiFi
//------------------------------------------------------
static void ICACHE_FLASH_ATTR TCP_client_disconnect_cb(void *arg)
{
struct espconn *pConn = (struct espconn *)arg;
//удаляем структуры из динамической памяти
os_free(pConn->proto.tcp);
os_free(pConn);
os_printf("TCP disconnected\r\n");
}
void ICACHE_FLASH_ATTR TCP_client_Tx_cb(void* arg)
{
os_printf("TCP packet sent\r\n");
}
//------------------------------------------------------
void ICACHE_FLASH_ATTR TCP_client_Rx_cb(void* arg, char* pusrdata, uint16_t length)
{
struct espconn *pConn = (struct espconn *)arg;
for(uint16_t idx=0;idx<length;idx++) uart_tx_one_char(UART0,pusrdata[idx]);
os_printf("\r\n");
espconn_disconnect(pConn);
}
static void ICACHE_FLASH_ATTR TCP_client_connect_cb(void *arg)
{
struct espconn *pConn = (struct espconn *)arg;
espconn_regist_sentcb(pConn, TCP_client_Tx_cb);
espconn_regist_recvcb(pConn, TCP_client_Rx_cb);
espconn_regist_disconcb(pConn, TCP_client_disconnect_cb);
char msg[]="Hello from ESP8266!!!\r\n";
espconn_sent(pConn, (uint8_t*) msg, strlen(msg));
}
Напишем функцию создания TCP соединения:
//------------------------------------------------------
//Создание TCP передачи
//------------------------------------------------------
static void ICACHE_FLASH_ATTR TCP_connect()
{
//выделим память по размеру struct espconn и заполним ее нулями, указатель присвоим pCon
struct espconn *pConTCP = (struct espconn *)os_zalloc(sizeof(struct espconn));
if (pConTCP == NULL) //если не присвоили - выходим
{
os_printf("TCP connect failed\r\n");
return;
}
pConTCP->type = ESPCONN_TCP; //устанавливаем тип
pConTCP->state = ESPCONN_NONE; //текущее состояние
//формируем IP и порт
pConTCP->proto.tcp=(esp_tcp*)os_zalloc(sizeof(esp_tcp)); //выделяем в памяти место под структуру для TCP
pConTCP->proto.tcp->local_port=espconn_port(); //генерируем случайный порт esp8266
pConTCP->proto.tcp->remote_port=TCP_SERVER_PORT;
uint32_t ip;
char tcpserverip[15]={};
os_sprintf(tcpserverip, "%s", TCP_SERVER_IP); //копируем ip
ip = ipaddr_addr(tcpserverip); //превращает в целочисленный формат
os_memcpy(pConTCP->proto.tcp->remote_ip, &ip, 4); //копируем ip
//Устанавливаем соединение
espconn_regist_connectcb(pConTCP, TCP_client_connect_cb); //Регистрируем callback функцию для установки соединения
os_printf("UDP espconn create...\r\n");
espconn_connect(pConTCP); //устанавливаем соединение (соединяемся с TCP сервером)
}
Функция прерывания по программному таймеру осталась практически прежней, в нее необходимо дописать функцию для установки TCP соединения:
ConnState=WIFI_CONNECTED;
os_printf("WiFi connected\r\n");
TCP_connect(); //Функция для настройки и установки TCP соединения
return;
main функция осталась без изменений.
//—————————————————————
Принцип работы описанной выше программы:
Большая часть программы аналогична работе UDP Client:
В main настраиваем wifi и включаем программный таймер, через 1с попадаем в прерывание по таймеру, проверяем статус соединения и выставляем новый таймер с тиком 500мс (для проверки соединения)
>>если нет соединения, ставим флаг ошибки и выводим в uart ошибку
>>если соединение есть:
- при первичном запуске (IpConfig.ip.addr!=0 и ConnState!=WIFI_CONNECTED), т.е. ip получили, но статус не обновили — изменяем статус «ConnState=WIFI_CONNECTED;» и вызываем функцию tcp_connect();
- при повторных запусках мигаем светодиодом
Отличия:
Функция tcp_connect() — настраивает и устанавливает TCP соединение, также в ДИНАМИЧЕСКОЙ памяти выделяем место для структур espconn и esp_tcp
>>когда TCP соединение установится — вызывается функция TCP_client_connect_cb, в которой прописываются callback функции и отправляется сбщ «Hello from ESP8266!!!»
>>после отправки сбщ попадаем в функцию TCP_client_Tx_cb где пока что просто выводим в uart сбщ. «TCP packet sent»
>>при приеме вызывается функция TCP_client_Rx_cb, в которой в uart выводится полученное сбщ. и вызывается функция TCP_client_disconnect_cb.
>>TCP_client_disconnect_cb — Удаляем из динамической памяти (созданы в функции tcp_connect() ) место под структуры espconn и esp_tcp
Для эмуляции работы сервера:
>> Запустить netcat
>> прописать: nc -l -p 30000 (этим откроем соединение)
>>получить сбщ. от esp8266 (Hello from ESP8266!!!)
>>отправить данные в esp8266 (они также отобразятся в терминальной программе)
Примечание: команды терминальной программы в win7:
Узнать свой ip: win+R ввести cmd и прописать ipconfig
Перейти в папку с netcat: win+R ввести cmd и прописать cd «путь до netcat»
Запускаем netcat в командной строке из папки с программой:
прописываем nc -u -l -p 30000
этим мы открыли 30000 порт и слушаем его, можем что-то в него отправить (вписываем данные +enter)