Настроим соединение по UDP протоколу и обменяемся датаграммами.
В файле user_config.h напишем дефайны для точки доступа
#define WiFi_Client_SSID "qwe1" //в SSID обязательно должны быть цифры!!!!
#define WiFi_Client_Password "12345678"
#define UDP_SERVER_IP "192.168.0.53"
#define UDP_SERVER_PORT 30000
В файле main.c добавляем код:
#include "espconn.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;
//------------------------------------------------------
Далее прописываем прототип функции проверки соединения и callback функции (обозначают окончание приема/передачи по UDP)
static void ICACHE_FLASH_ATTR wifi_check_ip(void *arg); //прототип функции
//------------------------------------------------------
//Functions INTERRUPT WiFi
//------------------------------------------------------
//Вызывается после окончания передачи
void ICACHE_FLASH_ATTR udp_client_Tx(void* arg)
{
}
//------------------------------------------------------
//Вызывается после окончания приема
void ICACHE_FLASH_ATTR udp_client_Rx(void* arg, char* pusrdata, uint16_t length)
{
uint16_t idx;
os_printf("UDP : DATA RECEIVED : LEN = %d\n", length);
os_printf("UDP : DATA: ");
for(idx=0;idx<length;idx++)
{
uart_tx_one_char(UART0,pusrdata[idx]);
}
espconn_send(&pConn, (uint8_t*)"Hello from ESP8266!!!\r\n", 23);
}
Далее необходимо написать функцию создания UDP передачи
//------------------------------------------------------
//Создание UDP передачи
//------------------------------------------------------
static void ICACHE_FLASH_ATTR udp_connect()
{
os_timer_disarm(&os_timer01);
pConn.proto.udp = &ConnUDP;
pConn.type = ESPCONN_UDP; //устанавливаем тип
pConn.state = ESPCONN_NONE; //текущее состояние
//формируем IP
uint32_t ip;
char udpserverip[15] = {};
os_sprintf(udpserverip, "%s", UDP_SERVER_IP); //копируем ip
ip = ipaddr_addr(udpserverip); //превращает в целочисленный формат
os_memcpy(pConn.proto.udp->remote_ip, &ip, 4); //копируем ip
//Вводим порты отправителя и получателя
pConn.proto.udp->local_port = espconn_port(); //создаем "случайный" порт для ESP8266
pConn.proto.udp->remote_port = UDP_SERVER_PORT; //записываем порт получателя
//создаем "соединение" по факту - открываем канал связи.
os_printf("UDP espconn create...\r\n");
espconn_create(&pConn); //создаем UDP передачу
espconn_regist_sentcb(&pConn, udp_client_Tx); //указываем callback функцию для передачи (вызывается после отправки)
espconn_regist_recvcb(&pConn, udp_client_Rx); //указываем callback функцию для приема (вызывается после приема)
//Запускаем таймер для проверки что соединение все еще есть
os_timer_setfn(&os_timer01, (os_timer_func_t *)wifi_check_ip, NULL);
os_timer_arm(&os_timer01, 1000, 0);
char data[] = "Hello\r\n";
espconn_send(&pConn, (uint8_t*)data, strlen(data));
}
Перепишем функцию, отвечающую за wifi соединение (см. Wi-Fi STA (станция/клиент))
//------------------------------------------------------
//Functions INTERRUPT
//------------------------------------------------------
static void ICACHE_FLASH_ATTR wifi_check_ip(void *arg)
{
struct ip_info IpConfig; //структура, в которую "складируются" данные о текущем соединении
os_timer_disarm(&os_timer01); //деинициализировать (обнулить) структуру / отключаем таймер
uint8_t WiFi_status=wifi_station_get_connect_status(); //проверяем статус соединения
if(WiFi_status==STATION_GOT_IP)
{
wifi_get_ip_info(STATION_IF, &IpConfig); //получаем ip и другую информацию о esp8266
if (IpConfig.ip.addr!=0) //если получили IP, то меняем статус и выходим
{
if(ConnState!=WIFI_CONNECTED) //если есть соединение, то выходим в функцию udp_connect()
{
ConnState=WIFI_CONNECTED;
os_printf("WiFi connected\r\n");
udp_connect();
return;
}
else {led_state=(led_state==0) ? 1:0; GPIO_OUTPUT_SET(2,led_state); } //мигаем светодиодом
}
}
else
{
espconn_delete(&pConn); //разрываем соединение с хостом (точнее удаляем передачу)
switch (WiFi_status)
{
case STATION_WRONG_PASSWORD:
ConnState=WIFI_CONNECTING_ERROR;
os_printf("STATION_WRONG_PASSWORD\r\n");
break;
case STATION_NO_AP_FOUND:
ConnState=WIFI_CONNECTING_ERROR;
os_printf("STATION_NO_AP_FOUND\r\n");
break;
case STATION_CONNECT_FAIL:
ConnState=WIFI_CONNECTING_ERROR;
os_printf("STATION_CONNECT_FAIL\r\n");
break;
default:
ConnState=WIFI_CONNECTING;
os_printf("STATION_IDLE\r\n");
break;
}
}
os_timer_setfn(&os_timer01, (os_timer_func_t*)wifi_check_ip, NULL); //указываем структура и функцию обратного вызова
os_timer_arm(&os_timer01, 500, 0); //инициализировать (обнулить) структуру
}
Последний шаг — изменим функцию main
//------------------------------------------------------
void ICACHE_FLASH_ATTR user_init()
{
uart_init(BIT_RATE_115200, BIT_RATE_115200);
//-----
gpio_init();
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2);
Set_GPIOs_As_Output(BIT2, 0);
//-----
ets_delay_ms(100);
os_printf("\r\n");
//
//WiFi UDP Client
//
struct station_config stationConf; //структура для настроек wifi
wifi_set_opmode(STATION_MODE); //режим станции (настройка м.б. изменена "на лету")
wifi_station_disconnect(); //разрываем соединение
wifi_station_dhcpc_stop(); //Остановим DHCP клиент
if(wifi_station_get_config(&stationConf))
{
os_memset(stationConf.ssid, 0, sizeof(stationConf.ssid));
os_memset(stationConf.password, 0, sizeof(stationConf.password));
os_sprintf(stationConf.ssid, "%s", WiFi_Client_SSID);
os_sprintf(stationConf.password, "%s", WiFi_Client_Password);
if(!wifi_station_set_config(&stationConf))
{
os_printf("Not set station config!\r\n");
}
}
wifi_set_sleep_type(NONE_SLEEP_T); //отключаем пониженное энергопотребление
wifi_station_connect(); //присоединяемся к wifi
wifi_station_dhcpc_start(); //запускаем DHCP клиент
if(wifi_get_phy_mode() != PHY_MODE_11N) wifi_set_phy_mode(PHY_MODE_11N); //Включаем режим 802.11n
if(wifi_station_get_auto_connect() ==0) wifi_station_set_auto_connect(1); //включаем автоконнект
//используем программный таймер
os_timer_disarm(&os_timer01); //деинициализировать (обнулить) структуру
os_timer_setfn(&os_timer01, (os_timer_func_t*)wifi_check_ip, NULL); //указываем структура и функцию обратного вызова
os_timer_arm(&os_timer01, 1000, 0); //0-однократно, 1-циклический
}
Примечание:
wifi_station_set_config(&stationConf); //данная функция сохраняет настройки в FLASH
wifi_station_set_config_current(&stationConf); //данная функция сохраняет настройки (в RAM?)
Принцип работы описанной выше программы:
В main настраиваем wifi и включаем программный таймер, через 1с попадаем в прерывание по таймеру, проверяем статус соединения и выставляем новый таймер с тиком 500мс (для проверки соединения)
>>если нет соединения, ставим флаг ошибки и выводим в uart ошибку
>>если соединение есть:
- при первичном запуске (IpConfig.ip.addr!=0 и ConnState!=WIFI_CONNECTED), т.е. ip получили, но статус не обновили — изменяем статус «ConnState=WIFI_CONNECTED;» и вызываем функцию udp_connect();
- при повторных запусках мигаем светодиодом
Функция udp_connect() — настраиваем параметры для UDP (заполняем структуру IP адресами и портами, указываем callback функции), после окончания настройки отправляем по UDP_SERVER_IP в 30000 порт сообщение.
При получении сбщ от сервера вызывается функция «udp_client_Rx» и данные выводятся в uart.
Напоминание: DHCP -прикладной протокол, позволяющий сетевым устройствам автоматически получать IP-адрес и другие параметры, необходимые для работы в сети TCP/IP.
Команды терминальной программы в win7:
Узнать свой ip: win+R ввести cmd и прописать ipconfig
Перейти в папку с netcat: win+R ввести cmd и прописать cd «путь до netcat»
Запускаем netcat в командной строке из папки с программой:
прописываем nc -u -l -p 30000
этим мы открыли 30000 порт и слушаем его, можем что-то в него отправить (вписываем данные +enter)