Skip to content

Hostname changes only after hard reset #5662

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
felixgeissler opened this issue Jan 24, 2019 · 14 comments
Closed

Hostname changes only after hard reset #5662

felixgeissler opened this issue Jan 24, 2019 · 14 comments
Assignees
Milestone

Comments

@felixgeissler
Copy link

Faced a strange behavior of WiFi.hostname() yesterday. Seems that my hostname only get's set after a hard reset.

I did setup a WiFo connection with:

WiFi.hostname(wiFiHostname);
WiFi.begin(ssid, passwd);

After that I try to connect to the network credentials read from EEPROM. If the connection fails I switch the mode to AP with WiFi.mode(WIFI_AP); and starting a captive portal to get new credentials from the user. My ESP then resets and connects to the new network. Unfortunately even though the ESP connects now in STA mode, it won't apply the hostname.
Only when I hard reset the device and the ESP connects again to the network the hostname is used.

Any ideas, what have gone wrong?

Full code:

#include <EEPROM.h>
#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>

/* RELAIS SETTINGS */
#define relaisPin D1

/* DEVICE SETTINGS */
const char* cnfSSID = "ESPDevice Config";
const char* wiFiHostname = "espdevice";

/* PROCESSING VARIABLES */
char ssid[30];
char passwd[30];
bool wifiFailure = false;
bool relaisState = LOW;

/* CONFIG WEBPAGE */
String cnfSuccessHtml = "<div class=\"alert\"> <span class=\"closebtn\" onclick=\"this.parentElement.style.display='none';\">&times;</span> Received network credentials - Restarting now. </div>";
String cnfhtml1 ="<!DOCTYPE html> <html lang=\"en\" dir=\"ltr\"> <head> <meta charset=\"utf-8\"> <title>ESP8266 Configurator</title> <style>html, body{padding: 0; margin: 0; font-family: Helvetica, sans-serif; background-color: #1a2431; color: white;}.wrappper{margin-top: 40px;}main{width: 90%; max-width: 500px; margin: 30px auto;}.alert{padding: 20px; background-color: #28a745; color: white; margin-bottom: 15px; border-radius: .25rem;}.closebtn{margin-left: 15px; color: white; font-weight: bold; float: right; font-size: 22px; line-height: 20px; cursor: pointer; transition: 0.3s;}.closebtn:hover{opacity: .6;}input{width: 100%; margin-bottom: 1.4em; padding: .375rem .75rem; font-size: 1rem; line-height: 1.5; color: #495057; background-color: #fff; background-clip: padding-box; border: 1px solid #ced4da; border-radius: .25rem; box-sizing: border-box;}label{display: inline-block; margin-bottom: .5rem;}.form-actions{display: flex; justify-content: space-between;}button{display: inline-block; font-weight: 400; width: 48%; text-align: center; white-space: nowrap; vertical-align: middle; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; border: 1px solid transparent; padding: .375rem .75rem; font-size: 1rem; line-height: 1.5; border-radius: .25rem; transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;}button[type=\"submit\"]{color: #fff; background-color: #28a745; border-color: #28a745;}button[type=\"submit\"]:hover{color: #fff; background-color: #218838; border-color: #1e7e34;}button[type=\"reset\"]{color: #fff; background-color: #f44336; border-color: #f44336;}button[type=\"reset\"]:hover{color: #fff; background-color: #C83B31; border-color: #C83B31;}footer{position: fixed; bottom: 0; padding: 30px 0; width: 100%; text-align: center; font-size: 0.8em;}a{color: #ff6c40; text-decoration: none;}.colored{color: #ff6c40;}</style> </head> <body> <div class=\"wrappper\"> <main> <h1><span class=\"colored\">ESP8266</span>WiFi Connector</h1>";
String cnfhtml2 = "<form action=\"/\" method=\"post\"> <p> Please enter you WiFi credentials down below. Your WiFi credentials won't be shared with anyone else. </p><label for=\"ssidInput\">Network Name:</label> <input type=\"text\" id=\"ssidInput\" name=\"ssid\" value=\"\" placeholder=\"SSID\"> <label for=\"ssidInput\">Network Password:</label> <input type=\"password\" id=\"passwordInput\" name=\"passwd\" value=\"\" placeholder=\"Password\"> <div class=\"form-actions\"> <button type=\"submit\">Submit</button> <button type=\"reset\">Reset</button> </div> </form> </main> <footer>Copyright by <a href=\"https://github.com/felixgeissler\" target=\"_blank\">Felix Geißler</a>, 2018</footer> </div> </body> </html>";

/* MAIN WEBPAGE */
String html ="<!DOCTYPE html> <html lang=\"en\" dir=\"ltr\"> <head> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"> <link rel=\"icon\" href=\"data:,\"> <meta charset=\"utf-8\"> <title>Wohnzimmerlampe Controler</title> <style media=\"screen\"> body{ text-align: center; font-family: \"Trebuchet MS\", Arial; margin-left:auto; margin-right:auto; background-color: #1a2431; color: white; padding: 2em; } button{ font-size: 1.4em; width: 100%; max-width: 400px; height: 3em; border-radius: 2em; margin-top: 3em; color: white; transition: all 800ms; opacity: 1; outline: none; } button:hover{ width: 95%; opacity: .9; } .colored{ color: #ff6c40; } .btn-on{ background-color: transparent; border: 1px solid white; } .btn-off{ border: 1px solid #ff6c40; background-color: #ff6c40; } .btn-err{ border: 1px solid red; background-color: red; } </style> <script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\"></script> </head> <body> <h1><span class=\"colored\">Wohnzimmerlampe</span> Controller</h1> <button id=\"toggleButton\" class=\"btn-on\" onchange=\"toggleRelais()\"></button> <script type=\"text/javascript\"> var button = document.getElementById(\"toggleButton\"); $.ajaxSetup({ timeout: 1000 }); window.onload = function(){ $.get(\"/status\", function(data, status){ handleButton(data); }); }; button.addEventListener(\"click\", function(){ $.get(\"/toggle\", function(data, status){ handleButton(data); }); }); function handleButton(data){ if(data == 'on'){ button.setAttribute('class', 'btn-off'); button.innerHTML = 'Off'; }else if(data == 'off'){ button.setAttribute('class', 'btn-on'); button.innerHTML = 'On'; }else{ button.setAttribute('class', 'btn-err'); button.innerHTML = 'ERROR'; } } </script> </body> </html>";

/* NETWORK */
const byte dnsPort = 53;
IPAddress apIP(192, 168, 1, 1);
DNSServer dnsServer;
ESP8266WebServer server(80);


void(* resetFunc) (void) = 0; //declare reset function @ address 0

void setup() {

  pinMode(relaisPin, OUTPUT);
  
  Serial.begin(115200);
  EEPROM.begin(80);
  int EEadress = 0;
  EEPROM.get(EEadress, ssid);
  EEadress += sizeof(ssid);
  EEPROM.get(EEadress, passwd);
  Serial.println("\nWIFI credentials from EEPROM: ");
  Serial.println(ssid);
  Serial.println(passwd);

  WiFi.hostname(wiFiHostname);
  WiFi.begin(ssid, passwd);
  
  for(int i=0; i<21; i++){
    if(WiFi.status() != WL_CONNECTED){
      if(i<20){
        delay(500);
        Serial.println("Waiting to connect…");
        wifiFailure = false;
      }else{
        Serial.println("Connection failed!");
        wifiFailure = true;
      }
    }else{
      Serial.println("Connected on IP adress: ");
      Serial.println(WiFi.localIP()); //Print the local IP
      break;
    }
  }
  
  if(wifiFailure){
    Serial.println("Creating ConfigAP");
    WiFi.mode(WIFI_AP);
    WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
    WiFi.softAP(cnfSSID);
    
    Serial.print("AP IP address: ");
    Serial.println(WiFi.softAPIP());

    // if DNSServer is started with "*" for domain name, it will reply with
    // provided IP to all DNS request - Captive Portal for WiFi settings
    dnsServer.start(dnsPort, "*", apIP);

    //Associating the config handler function to all paths
    server.onNotFound(handleConf);
  }else{
    WiFi.mode(WIFI_STA);
     //Associating the handler functions to the paths
    server.on("/toggle", toggle);  
    server.on("/status", stat);
    server.on("/", root);
  }

  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
  if(wifiFailure){
    dnsServer.processNextRequest();
  }
  
  server.handleClient();
}

/* -------------------- */
/*    CONFIG PROGRAM    */
/* -------------------- */

void writeCredentials(String newSSID, String newPASSWD){
  char SSIDbuff[30];
  char PASSWDbuff[30];
  newSSID.toCharArray(SSIDbuff, 30);
  newPASSWD.toCharArray(PASSWDbuff, 30);
  
  Serial.println("Writing credentials to EEPROM.");
  EEPROM.begin(sizeof(SSIDbuff)+sizeof(PASSWDbuff));
  int EEaddress = 0;
  EEPROM.put(EEaddress, SSIDbuff);
  EEaddress += sizeof(SSIDbuff);
  EEPROM.put(EEaddress, PASSWDbuff);
  EEPROM.commit();
  EEPROM.end();
  Serial.println("Restarting ESP");
}

void handleConf() {
  if ((server.hasArg("ssid")&&server.hasArg("passwd"))) {
    Serial.println("Writing WiFi credentials:");
    Serial.println(server.arg("ssid"));
    Serial.println(server.arg("passwd"));
    writeCredentials(server.arg("ssid"), server.arg("passwd"));
    
    server.send(200, "text/html", cnfhtml1+cnfSuccessHtml+cnfhtml2);
    
    delay(1000);
    Serial.println("Restarting now.");
    resetFunc();
  }
  else {
    server.send(200, "text/html", cnfhtml1+cnfhtml2);
  }
}

/* -------------------- */
/*      MAIN PROGRAM    */
/* -------------------- */

void toggle(){
  relaisState = !relaisState;
  digitalWrite(relaisPin, relaisState);
  
  String statusMsg = "";
  if (relaisState){
    statusMsg = "on";
    Serial.println("Relais is now ON");
  }else{
    statusMsg = "off";
    Serial.println("Relais is now OFF");
  }
  server.send(200, "text/plain", statusMsg);
}

void stat(){
  String statusMsg = "";
  if (relaisState){
    statusMsg = "on";
  }else{
    statusMsg = "off";
  }
  server.send(200, "text/plain", statusMsg);
  Serial.println("Current status has been sent.");
}

void root(){
  server.send(200, "text/html", html);
  Serial.println("Web interface has been sent.");
}
@d-a-v
Copy link
Collaborator

d-a-v commented Jan 24, 2019

Will probably be fixed by #5652

@devyte
Copy link
Collaborator

devyte commented Jan 24, 2019

@felixgeissler please test pr #5652 and report back here.

@felixgeissler
Copy link
Author

@felixgeissler please test pr #5652 and report back here.

Gonna try that shortly.

@felixgeissler
Copy link
Author

@devyte Couldn't figure out what to do -.-
Could u help me out with this?

@d-a-v
Copy link
Collaborator

d-a-v commented Jan 24, 2019

If you are using git and command line, you can

git pull
git fetch origin pull/5652/head:pr-5652-hostname
git checkout pr-5652-hostname
git branch

After testing,

git checkout master

@d-a-v
Copy link
Collaborator

d-a-v commented Jan 24, 2019

#5652 is merged, you just need to update git master. Feedback is welcome

@devyte
Copy link
Collaborator

devyte commented Jan 26, 2019

2.5.0-beta3 is released and it contains this change. Please retest.

@d-a-v d-a-v added the waiting for feedback Waiting on additional info. If it's not received, the issue may be closed. label Feb 3, 2019
@devyte
Copy link
Collaborator

devyte commented Nov 9, 2019

No feedback in a long while. We just released 2.6.0 now.
Also, I can't reproduce, my own app can changes hostname without having to reboot.
Closing.

@devyte devyte closed this as completed Nov 9, 2019
@tschaban
Copy link

I'm struggling with the same issue with
bool ret = wifi_station_set_hostname(aHostname);
it keeps return false only on soft reset while hard reset makes it return always true.
@felixgeissler did you find the fix?
I'm on arduino 2.7.4

@d-a-v
Copy link
Collaborator

d-a-v commented Dec 22, 2020

@tschaban Did you try calling WiFi.hostname(name) before WiFi.begin(...) ?

@tschaban
Copy link

tschaban commented Dec 22, 2020

sure
I nutshell extract from the code looks like that

  • with hard reset the hostname is set
  • with soft reset wifi_station_set_hostname(aHostname) returns false ;(

setup() {
  WiFi.hostname("T2");
  WiFi.setSleepMode(WIFI_NONE_SLEEP);
  WiFi.mode(WIFI_STA);
}


  loop() { 
  if (WiFi.status() == WL_CONNECTED) {
            WiFi.begin(ssid,password);
     // some delay here
  }
}


Soft reset is made with ESP.restart();

@d-a-v
Copy link
Collaborator

d-a-v commented Dec 22, 2020

Why do you need to later call wifi_station_set_hostname(aHostname) if WiFi.hostname("T2") is called ?
Do you call it with a different name ?
Or did you enable debug mode and saw the debug message WiFi.hostname(T2): wifi_station_set_hostname() failed ?
Or is it always WiFi.hostname(...) but with a different behavior after a soft-reset ?

The two are similar wifi_station_set_hostname and WiFi.hostname, but the second calls the first and tries to informs the dhcp server.

However if you see the above debug message, there should be something we could try.

What's the purpose of this snippet: (is it != instead of ==?)

  if (WiFi.status() == WL_CONNECTED) {
            WiFi.begin(ssid,password);

@tschaban
Copy link

tschaban commented Dec 22, 2020

@d-a-v I've debugged WiFi.hostname() manually to see where it returns false and it returns false once wifi_station_set_hostname() is called within WiFi.hostname().
I'm not calling wifi_station_set_hostname(), just WiFi.hostname()

to your last question. you're right - there is !=

@d-a-v d-a-v self-assigned this Dec 22, 2020
@d-a-v d-a-v added type: bug and removed waiting for feedback Waiting on additional info. If it's not received, the issue may be closed. labels Dec 22, 2020
@d-a-v d-a-v added this to the 3.0.0 milestone Dec 22, 2020
@d-a-v d-a-v reopened this Dec 22, 2020
@d-a-v
Copy link
Collaborator

d-a-v commented Feb 27, 2021

Testing on git master with sketch:

#include <ESP8266WiFi.h>
#include <PolledTimeout.h>
#include <coredecls.h>

#ifndef STASSID
#define STASSID "your-ssid"
#define STAPSK  "your-password"
#endif

const char* ssid = STASSID;
const char* password = STAPSK;

using esp8266::polledTimeout::oneShotMs; 
oneShotMs changeHostName(oneShotMs::neverExpires);

void time_is_set()
{
    timeval tv;
    gettimeofday(&tv, nullptr);
    srandom(tv.tv_usec);
    changeHostName.reset(1000);
    Serial.printf("time is set\n");
}

void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.print("connecting to ");
  Serial.println(ssid);
  
  settimeofday_cb(time_is_set);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
}

void loop() {
    if (changeHostName)
    {
        String name = "abc";
        name += random(100);
        bool ok = WiFi.hostname(name.c_str());
        Serial.printf("hostname('%s')=%d\n", name.c_str(), ok);
        changeHostName.reset(random(10000));
    }
}

Execution:

...
22:40:32.337792376 ip:10.0.1.179,mask:255.255.255.0,gw:10.0.1.254
22:40:32.366648565 time is set
22:40:33.363575369 hostname('abc56')=1
22:40:35.627482741 hostname('abc17')=1
22:40:36.016333667 hostname('abc25')=1   <-- tried
22:40:39.267910186 pm open,type:2 0
22:40:45.527547156 hostname('abc73')=1   <-- tried
22:40:53.106757421 hostname('abc0')=1    <-- tried
22:41:01.009640990 hostname('abc10')=1   <-- tried
22:41:09.605268962 hostname('abc96')=1   <-- tried
22:41:16.166270483 hostname('abc44')=1
22:41:20.558682746 hostname('abc47')=1
22:41:25.029459830 hostname('abc62')=1
22:41:25.944751174 hostname('abc24')=1
22:41:28.213915017 hostname('abc49')=1

On linux console: (trying to type fast)

# unix prompt is YYMMDDHHMMSS

210227224047:~>ping abc25
ping: abc25: Name or service not known          # (too late)
210227224048:~>ping abc73
^C                                              # (dns lagging)
210227224058:~>ping abc0
PING abc0.lan (10.0.1.179) 56(84) bytes of data.
64 bytes from abc0.lan (10.0.1.179): icmp_seq=1 ttl=255 time=209 ms
^C
210227224103:~>ping abc10
PING abc10.lan (10.0.1.179) 56(84) bytes of data.
64 bytes from abc10.lan (10.0.1.179): icmp_seq=1 ttl=255 time=41.2 ms
^C
210227224109:~>ping abc10
ping: abc10: Name or service not known          # (router doesn't know it anymore)
210227224110:~>ping abc96
PING abc96.lan (10.0.1.179) 56(84) bytes of data.
64 bytes from abc96.lan (10.0.1.179): icmp_seq=3 ttl=255 time=17.7 ms
^C

Notice that at 22:41:09, abc10 name does not answer anymore, replaced by abc96.

Closing as working and issue can't be reproduced.

@d-a-v d-a-v closed this as completed Feb 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants