espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.62k stars 7.41k forks source link

Modify MDNS hostname after begin() #7047

Open zekageri opened 2 years ago

zekageri commented 2 years ago

Related area

ESP32

Hardware specification

ESP32

Is your feature request related to a problem?

I wanted to modify the MDNS hostname after it was initialized, but did not find a library way to do it.

Describe the solution you'd like

I'm thinking about a function which would take a new hostname as a parameter and if it has to, restarts the service.

boolean MDNSResponder::setHostname( const char* newHostname ){
    _hostname = hostName;
    _hostname.toLowerCase();
    if( mdns_hostname_set( newHostname  ) ) {
        log_e("Failed setting MDNS hostname");
        return false;
    }
    return true;
}

Describe alternatives you've considered

Reiniting the entire mdns service with MDNS.end(); and MDNS.begin( hostname );

Example:

void networkSystem::handleExistingMDNS(){
    #if NETWORK_DEBUG_MODE
        Serial.println("MDNS hostname already exists.");
    #endif
    String newHost = fileSys.config.hostname;
    newHost += "_" + String(conflictingMDNSCount);
    strcpy(fileSys.config.hostname, newHost.c_str());
    #if NETWORK_DEBUG_MODE
        Serial.printf("MDNS hostname changed to: %s\n", fileSys.config.hostname);
    #endif
    reinitMDNS();
}

void networkSystem::reinitMDNS(){
    MDNS.end();
    setupMDNS();
}

void networkSystem::check_MDNS_Services(){
    if( !connected || servicesChecked ){ return; }
    int nrOfServices = MDNS.queryService("http", "tcp");
    if (nrOfServices == 0) {
        Serial.println("No services were found.");
        return;
    }
    Serial.printf("%d services were found.\n", nrOfServices);
    for (int i = 0; i < nrOfServices; i=i+1) {
        Serial.println("---------------");

        const char* serviceHostname = MDNS.hostname(i).c_str();

        if( strcmp(serviceHostname, fileSys.config.hostname) == 0 ){
            conflictingMDNSCount++;
        }

        Serial.printf("Hostname: %s\n", serviceHostname );
        Serial.printf("IP address: %s\n", MDNS.IP(i).toString().c_str() );
        Serial.printf("Port: %d\n", MDNS.port(i));

        Serial.println("---------------");
    }
    Serial.printf("%d conflicting MDNS hostnames found.\n", conflictingMDNSCount);
    if( conflictingMDNSCount > 0 ){
        handleExistingMDNS();
    }
    conflictingMDNSCount    = 0;
    servicesChecked         = true;
}

void networkSystem::setupMDNS(){
    if( MDNS.begin( fileSys.config.hostname ) ) {
        #if NETWORK_DEBUG_MODE
            Serial.println("MDNS responder started");
        #endif
        MDNS.addService("http", "tcp", 80);
        MDNS.addServiceTxt("http", "tcp", "hsh_service", "HsH");
        MDNS.addServiceTxt("http", "tcp", "hsh_service_prop2", "HsH");
        MDNS.addServiceTxt("HsH", "hshProto", "hsh_service_prop3", "HsH");

        check_MDNS_Services();
    }else{
        #if NETWORK_DEBUG_MODE
            Serial.println("MDNS responder failed");
        #endif
    }
}

Additional context

For example, i have the same devices on the network with the same preconfigured mdns name. If one is on the network, and i want to put another, it could query the services and check if it has duplicate mdns names. If it has, it would then add +1 or something unique to it's hostname and set it again.

I have checked existing list of Feature requests and the Contribution Guide

zekageri commented 2 years ago

It would be even better to be able to query the services BEFORE i setup my own hostname on the network. Because to setup my hostname, now i have to start the mdns at the same time.