mirror of
				https://github.com/espressif/ESP8266_RTOS_SDK.git
				synced 2025-10-31 10:45:59 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			253 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			253 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* MDNS-SD Query and advertise Example
 | |
| 
 | |
|    This example code is in the Public Domain (or CC0 licensed, at your option.)
 | |
| 
 | |
|    Unless required by applicable law or agreed to in writing, this
 | |
|    software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 | |
|    CONDITIONS OF ANY KIND, either express or implied.
 | |
| */
 | |
| #include <string.h>
 | |
| #include "freertos/FreeRTOS.h"
 | |
| #include "freertos/task.h"
 | |
| #include "freertos/event_groups.h"
 | |
| #include "esp_system.h"
 | |
| #include "esp_wifi.h"
 | |
| #include "esp_event_loop.h"
 | |
| #include "esp_log.h"
 | |
| #include "nvs_flash.h"
 | |
| #include "mdns.h"
 | |
| #include "driver/gpio.h"
 | |
| #include <sys/socket.h>
 | |
| #include <netdb.h>
 | |
| 
 | |
| /* The examples use simple WiFi configuration that you can set via
 | |
|    'make menuconfig'.
 | |
| 
 | |
|    If you'd rather not, just change the below entries to strings with
 | |
|    the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
 | |
| */
 | |
| #define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID
 | |
| #define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD
 | |
| 
 | |
| #define EXAMPLE_MDNS_HOSTNAME CONFIG_MDNS_HOSTNAME
 | |
| #define EXAMPLE_MDNS_INSTANCE CONFIG_MDNS_INSTANCE
 | |
| 
 | |
| /* FreeRTOS event group to signal when we are connected & ready to make a request */
 | |
| static EventGroupHandle_t wifi_event_group;
 | |
| 
 | |
| /* The event group allows multiple bits for each event,
 | |
|    but we only care about one event - are we connected
 | |
|    to the AP with an IP? */
 | |
| const int IP4_CONNECTED_BIT = BIT0;
 | |
| const int IP6_CONNECTED_BIT = BIT1;
 | |
| 
 | |
| static const char *TAG = "mdns-test";
 | |
| static bool auto_reconnect = true;
 | |
| 
 | |
| static esp_err_t event_handler(void *ctx, system_event_t *event)
 | |
| {
 | |
|     /* For accessing reason codes in case of disconnection */
 | |
|     system_event_info_t *info = &event->event_info;
 | |
| 
 | |
|     switch(event->event_id) {
 | |
|     case SYSTEM_EVENT_STA_START:
 | |
|         esp_wifi_connect();
 | |
|         break;
 | |
|     case SYSTEM_EVENT_STA_CONNECTED:
 | |
|         /* enable ipv6 */
 | |
|         tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA);
 | |
|         break;
 | |
|     case SYSTEM_EVENT_STA_GOT_IP:
 | |
|         xEventGroupSetBits(wifi_event_group, IP4_CONNECTED_BIT);
 | |
|         break;
 | |
|     case SYSTEM_EVENT_AP_STA_GOT_IP6:
 | |
|         xEventGroupSetBits(wifi_event_group, IP6_CONNECTED_BIT);
 | |
|         break;
 | |
|     case SYSTEM_EVENT_STA_DISCONNECTED:
 | |
|         /* This is a workaround as ESP32 WiFi libs don't currently
 | |
|            auto-reassociate. */
 | |
|         if (auto_reconnect) {
 | |
|             ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason);
 | |
|             if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) {
 | |
|                 /*Switch to 802.11 bgn mode */
 | |
|                 esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N);
 | |
|             }
 | |
|             esp_wifi_connect();
 | |
|         }
 | |
|         xEventGroupClearBits(wifi_event_group, IP4_CONNECTED_BIT | IP6_CONNECTED_BIT);
 | |
|         break;
 | |
|     default:
 | |
|         break;
 | |
|     }
 | |
|     mdns_handle_system_event(ctx, event);
 | |
|     return ESP_OK;
 | |
| }
 | |
| 
 | |
| static void initialise_wifi(void)
 | |
| {
 | |
|     tcpip_adapter_init();
 | |
|     wifi_event_group = xEventGroupCreate();
 | |
|     ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
 | |
|     wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
 | |
|     ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
 | |
|     ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
 | |
|     wifi_config_t wifi_config = {
 | |
|         .sta = {
 | |
|             .ssid = EXAMPLE_WIFI_SSID,
 | |
|             .password = EXAMPLE_WIFI_PASS,
 | |
|         },
 | |
|     };
 | |
|     ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid);
 | |
|     ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
 | |
|     ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
 | |
|     ESP_ERROR_CHECK( esp_wifi_start() );
 | |
| }
 | |
| 
 | |
| static void initialise_mdns(void)
 | |
| {
 | |
|     //initialize mDNS
 | |
|     ESP_ERROR_CHECK( mdns_init() );
 | |
|     //set mDNS hostname (required if you want to advertise services)
 | |
|     ESP_ERROR_CHECK( mdns_hostname_set(EXAMPLE_MDNS_HOSTNAME) );
 | |
|     //set default mDNS instance name
 | |
|     ESP_ERROR_CHECK( mdns_instance_name_set(EXAMPLE_MDNS_INSTANCE) );
 | |
| 
 | |
|     //structure with TXT records
 | |
|     mdns_txt_item_t serviceTxtData[3] = {
 | |
|         {"board","esp32"},
 | |
|         {"u","user"},
 | |
|         {"p","password"}
 | |
|     };
 | |
| 
 | |
|     //initialize service
 | |
|     ESP_ERROR_CHECK( mdns_service_add("ESP32-WebServer", "_http", "_tcp", 80, serviceTxtData, 3) );
 | |
|     //add another TXT item
 | |
|     ESP_ERROR_CHECK( mdns_service_txt_item_set("_http", "_tcp", "path", "/foobar") );
 | |
|     //change TXT item value
 | |
|     ESP_ERROR_CHECK( mdns_service_txt_item_set("_http", "_tcp", "u", "admin") );
 | |
| }
 | |
| 
 | |
| static const char * if_str[] = {"STA", "AP", "ETH", "MAX"};
 | |
| static const char * ip_protocol_str[] = {"V4", "V6", "MAX"};
 | |
| 
 | |
| static void mdns_print_results(mdns_result_t * results){
 | |
|     mdns_result_t * r = results;
 | |
|     mdns_ip_addr_t * a = NULL;
 | |
|     int i = 1, t;
 | |
|     while(r){
 | |
|         printf("%d: Interface: %s, Type: %s\n", i++, if_str[r->tcpip_if], ip_protocol_str[r->ip_protocol]);
 | |
|         if(r->instance_name){
 | |
|             printf("  PTR : %s\n", r->instance_name);
 | |
|         }
 | |
|         if(r->hostname){
 | |
|             printf("  SRV : %s.local:%u\n", r->hostname, r->port);
 | |
|         }
 | |
|         if(r->txt_count){
 | |
|             printf("  TXT : [%u] ", r->txt_count);
 | |
|             for(t=0; t<r->txt_count; t++){
 | |
|                 printf("%s=%s; ", r->txt[t].key, r->txt[t].value?r->txt[t].value:"NULL");
 | |
|             }
 | |
|             printf("\n");
 | |
|         }
 | |
|         a = r->addr;
 | |
|         while(a){
 | |
|             if(a->addr.type == IPADDR_TYPE_V6){
 | |
|                 printf("  AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6));
 | |
|             } else {
 | |
|                 printf("  A   : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4)));
 | |
|             }
 | |
|             a = a->next;
 | |
|         }
 | |
|         r = r->next;
 | |
|     }
 | |
| 
 | |
| }
 | |
| 
 | |
| static void query_mdns_service(const char * service_name, const char * proto)
 | |
| {
 | |
|     ESP_LOGI(TAG, "Query PTR: %s.%s.local", service_name, proto);
 | |
| 
 | |
|     mdns_result_t * results = NULL;
 | |
|     esp_err_t err = mdns_query_ptr(service_name, proto, 3000, 20,  &results);
 | |
|     if(err){
 | |
|         ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err));
 | |
|         return;
 | |
|     }
 | |
|     if(!results){
 | |
|         ESP_LOGW(TAG, "No results found!");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     mdns_print_results(results);
 | |
|     mdns_query_results_free(results);
 | |
| }
 | |
| 
 | |
| static void query_mdns_host(const char * host_name)
 | |
| {
 | |
|     ESP_LOGI(TAG, "Query A: %s.local", host_name);
 | |
| 
 | |
|     struct ip4_addr addr;
 | |
|     addr.addr = 0;
 | |
| 
 | |
|     esp_err_t err = mdns_query_a(host_name, 2000,  &addr);
 | |
|     if(err){
 | |
|         if(err == ESP_ERR_NOT_FOUND){
 | |
|             ESP_LOGW(TAG, "%s: Host was not found!", esp_err_to_name(err));
 | |
|             return;
 | |
|         }
 | |
|         ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     ESP_LOGI(TAG, IPSTR, IP2STR(&addr));
 | |
| }
 | |
| 
 | |
| static void initialise_button(void)
 | |
| {
 | |
|     gpio_config_t io_conf;
 | |
|     io_conf.intr_type = GPIO_INTR_DISABLE;
 | |
|     io_conf.pin_bit_mask = 1;
 | |
|     io_conf.mode = GPIO_MODE_INPUT;
 | |
|     io_conf.pull_up_en = 1;
 | |
|     io_conf.pull_down_en = 0;
 | |
|     gpio_config(&io_conf);
 | |
| }
 | |
| 
 | |
| static void check_button(void)
 | |
| {
 | |
|     static bool old_level = true;
 | |
|     bool new_level = gpio_get_level(GPIO_NUM_0);
 | |
|     if (!new_level && old_level) {
 | |
|         query_mdns_host("esp32");
 | |
|         query_mdns_service("_arduino", "_tcp");
 | |
|         query_mdns_service("_http", "_tcp");
 | |
|         query_mdns_service("_printer", "_tcp");
 | |
|         query_mdns_service("_ipp", "_tcp");
 | |
|         query_mdns_service("_afpovertcp", "_tcp");
 | |
|         query_mdns_service("_smb", "_tcp");
 | |
|         query_mdns_service("_ftp", "_tcp");
 | |
|         query_mdns_service("_nfs", "_tcp");
 | |
|     }
 | |
|     old_level = new_level;
 | |
| }
 | |
| 
 | |
| static void mdns_example_task(void *pvParameters)
 | |
| {
 | |
|     /* Wait for the callback to set the CONNECTED_BIT in the event group. */
 | |
|     xEventGroupWaitBits(wifi_event_group, IP4_CONNECTED_BIT | IP6_CONNECTED_BIT,
 | |
|                      false, true, portMAX_DELAY);
 | |
|     while(1) {
 | |
|         check_button();
 | |
|         vTaskDelay(50 / portTICK_PERIOD_MS);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void app_main()
 | |
| {
 | |
|     ESP_ERROR_CHECK( nvs_flash_init() );
 | |
|     initialise_mdns();
 | |
|     initialise_wifi();
 | |
|     initialise_button();
 | |
|     xTaskCreate(&mdns_example_task, "mdns_example_task", 2048, NULL, 5, NULL);
 | |
| }
 | 
