0

I am working on sending data from multiple clients to a server, all of which are NodeMCUs. I have been able to send data for a single iteration. Trouble arises when I want it to send data repeatedly so that if I update my client data, this new data should be reflected at the server as well.

Since I am using multiple clients, I have employed MAC addresses as the means of identifying the clients. This way, the signals received from a particular client are given as output to a particular pin.

To send data perpetually, I tried to use an infinite loop: while(true), but it reads the first connected client even on recognizing the second client.

Here's my server code:

#include <ESP8266WiFi.h>
#define Max_Clients 5

extern "C" {
  #include <user_interface.h>
}

WiFiServer server(80); //Initialize the server on Port 80
WiFiClient *clients[Max_Clients] = {NULL}; //Initializing client(s)
String inputs [Max_Clients] ={""}; //Initializing to store the string received from clients

int32_t freq = 10000;

IPAddress remoteIP();

void setup() {
  pinMode(D1,OUTPUT); //Intializing pins for showing output and input
  pinMode(D2,OUTPUT);
  pinMode(D3,OUTPUT);
  pinMode(A0,INPUT);
  Serial.begin(9600); //Start communication between the ESP8266-12E and the monitor window
  analogWriteFreq(freq);
  WiFi.mode(WIFI_AP); //This ESP8266-12E is an AccessPoint 
  WiFi.softAP("NodeMCU_js", "12345678"); //Provide the (SSID, password)
  IPAddress myIP = WiFi.softAPIP(); //Obtain the IP of the Server
  Serial.println("Server IP is: "); //Print the IP to the monitor window 
  Serial.println(myIP);
  server.begin(); //Start the HTTP Server
}

void loop() {
  WiFiClient client = server.available(); //Check if a new Client has connected to the server
  unsigned char number_client;
  struct station_info *stat_info;
  struct ip_addr *IPaddress;
  IPAddress address;
  int k=0;
  if (client) {  
    Serial.println("A new Client has connected :)");
   for (int i=0 ; i<Max_Clients ; ++i){ //Acknowledges and sets up new clients
    if (NULL == clients[i]){
      Serial.println(i);
      clients[i] = new WiFiClient(client); //nothing in clients[i] means it is a new client
      break;
    }
   }

   while (true){ 
    delay(3000);
    number_client = wifi_softap_get_station_num();
    stat_info = wifi_softap_get_station_info();
    Serial.println();
    Serial.print("Total connected clients are = ");
    Serial.print(number_client);
    Serial.println();
    while (stat_info != NULL){
      for(int i=0 ; i<number_client ; ++i)  { //For available clients
        if (NULL != clients[i]) {
          IPaddress = &stat_info->ip;
          address = IPaddress->addr;
          Serial.println();
          Serial.print("Client = ");
          Serial.print(i+1);
          Serial.println();
          Serial.print("Client IP Address = ");
          Serial.print(address);
          Serial.println();
          Serial.print("Client MAC Address = ");
          Serial.print(stat_info->bssid[0],HEX);
          Serial.print(":");
          Serial.print(stat_info->bssid[1],HEX);
          Serial.print(":");
          Serial.print(stat_info->bssid[2],HEX);
          Serial.print(":");
          Serial.print(stat_info->bssid[3],HEX);
          Serial.print(":");
          Serial.print(stat_info->bssid[4],HEX);
          Serial.print(":");
          Serial.print(stat_info->bssid[5],HEX);
          Serial.println();

          if (stat_info->bssid[0] == 0xDC && stat_info->bssid[1] == 0x4F && stat_info->bssid[2] == 0x22 && stat_info->bssid[3] == 0x17 && stat_info->bssid[4] == 0xEE && stat_info->bssid[5] == 0x95) {
            Serial.println("Compared MAC address successfully - 1 :)");
            String request1 = clients[i]->readStringUntil('\r');
            Serial.print("Client 1 asks: ");
            Serial.print(request1);
            inputs[i] = request1;
            int duty1 = request1.toInt();
            analogWrite(D1,duty1);
            clients[i]->flush();
            k++;
            clients[i]->print("From Central Server to Client 1 - 150\r");
          }

          if (stat_info->bssid[0] == 0xDC && stat_info->bssid[1] == 0x4F && stat_info->bssid[2] == 0x22 && stat_info->bssid[3] == 0x18 && stat_info->bssid[4] == 0x1F && stat_info->bssid[5] == 0x9D) {
            Serial.println("Compared MAC address successfully - 2 :)");
            String request2 = clients[i]->readStringUntil('\r');
            Serial.print("Client 2 asks: ");
            Serial.print(request2);
            inputs[i] = request2;
            int duty2 = request2.toInt();
            analogWrite(D2,duty2);
            clients[i]->flush();
            clients[i]->print("From Central Server to Client 2 - 200\r");
            k++;
            }

          if (stat_info->bssid[0] == 0xDC && stat_info->bssid[1] == 0x4F && stat_info->bssid[2] == 0x22 && stat_info->bssid[3] == 0x18 && stat_info->bssid[4] == 0xB && stat_info->bssid[5] == 0x71) {
            Serial.println("Compared MAC address successfully - 3 :)");
            String request3 = clients[i]->readStringUntil('\r');
            Serial.print("Client 3 asks: ");
            Serial.print(request3);
            inputs[i] = request3;
            int duty3 = request3.toInt();
            analogWrite(D3,duty3);
            clients[i]->flush();
            k++;
            clients[i]->print("From Central Server to Client 3 - 250\r");
          }

        if (k == 0){
            Serial.println();
            Serial.println("Client not recognised.");
          }  

          stat_info = STAILQ_NEXT(stat_info, next);
          Serial.println();
        }
       }
      }
     }
    }
   } //void loop closure

Here's my client code:

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>

char ssid[] = "NodeMCU_js";
char password[] = "12345678";

WiFiClient client; // Creates a client that can connect to to a specified internet IP address and port as defined in client.connect()
IPAddress server(192,168,4,1);

void setup() {
  pinMode(A0,INPUT);
  pinMode(D6,OUTPUT);
  WiFi.persistent(false);
  WiFi.mode(WIFI_STA);
  Serial.begin(9600); //Serial connection
  WiFi.begin(ssid,password); //WiFi connection
  while (WiFi.status() != WL_CONNECTED) { //Wait for the WiFI connection completion
    delay(500);
    Serial.println("Connecting...");    
  }
  Serial.println("Connected.");
  client.connect(server, 80);   // Connection to the server
}

void loop() {
  if(WiFi.status() == WL_CONNECTED){ //Check WiFi connection status
    while(true){
      int duty = analogRead(A0);
      client.print(String(duty)+"\r"); //Client's message to the server
      String answer = client.readStringUntil('\r'); //Reading response from the server
      Serial.print("Central Server: 200"); //Printing the response
      Serial.print(answer);
     }
   } else {
     Serial.println("Error in WiFi connection");   
   }
}

Kindly suggest a solution. Thanks in advance.

7
  • why do you think there is a relation between client returned by the WebServer and client station number from soft AP?
    – Juraj
    Jun 25, 2018 at 11:28
  • One of my nodeMCUs is a server. I am not using any WebServer. Jun 25, 2018 at 11:29
  • sorry WifiServer
    – Juraj
    Jun 25, 2018 at 11:31
  • wifi_softap_get_station_num() is a count of stations if I understand it correctly
    – Juraj
    Jun 25, 2018 at 11:32
  • Precisely. The number of clients connected to the server. Jun 25, 2018 at 11:35

2 Answers 2

1

I found the error. The if(client) is to be closed before the while(stat_info) otherwise the loop will run only if it finds a new client. It is running fine now. Thank you everyone for the suggestions. :)

0

It's vital that either loop() return or that you call yield() or delay() in your loop() handler.

Your client code as it's written doesn't do that.

You don't need the while(true) at all. Take it out and leave the body of it in the if statement. loop() will be continuously re-entered and your code will keep running. loop() is already an infinite loop.

Leaving while(true) inside loop() means that loop() never returns. When it doesn't return, the SDK doesn't get to perform certain housekeeping functions that are necessary for its proper operation. In particular, networking functions may stop working correctly, so your call to client.readStringUntil() may not work correctly.

5
  • On removing the while(true), the program executes fine but does not run perpetually. I require this because the analogRead() signals will be changing and I want to observe the changes in the output without having to re-run the code. Jun 26, 2018 at 16:58
  • There's something weird going on if it doesn't continue running.The whole purpose of loop() is to be called over and over again, in an infinite loop. Try doing some debugging, put some Serial.println()'s inside loop() to confirm what's actually happening. There is no way it will ever operate correctly if you have a while(true) inside loop().
    – romkey
    Jun 27, 2018 at 16:01
  • Is there an alternative to while(true)? Any other way to create an infinite loop within the void(loop)? I've been through the program several times and am not finding any clues whatsoever. Jun 28, 2018 at 9:03
  • loop() IS an infinite loop. If it's not, something is broken somewhere else. Have you tried putting debugging Serial.println()s to confirm that you're not re-entering loop() after it returns? If something is so broken that loop() isn't reentering it's best not to make assumptions about what's running. So something like: void loop() { Serial.println("entered loop"); if(WiFi.status() == WL_CONNECTED){ //Check WiFi connection status Serial.println("wifi connected"); int duty = analogRead(A0); ... (comments are too short to hold all the code)
    – romkey
    Jun 29, 2018 at 13:29
  • I have done that. Loop never runs again. Jun 29, 2018 at 18:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.