12. Connect to UDP Client

Настроим соединение по 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)

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *