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.
-
why do you think there is a relation between client returned by the WebServer and client station number from soft AP?Juraj– Juraj ♦2018年06月25日 11:28:42 +00:00Commented Jun 25, 2018 at 11:28
-
One of my nodeMCUs is a server. I am not using any WebServer.Dingodudesir– Dingodudesir2018年06月25日 11:29:48 +00:00Commented Jun 25, 2018 at 11:29
-
sorry WifiServerJuraj– Juraj ♦2018年06月25日 11:31:06 +00:00Commented Jun 25, 2018 at 11:31
-
wifi_softap_get_station_num() is a count of stations if I understand it correctlyJuraj– Juraj ♦2018年06月25日 11:32:01 +00:00Commented Jun 25, 2018 at 11:32
-
Precisely. The number of clients connected to the server.Dingodudesir– Dingodudesir2018年06月25日 11:35:57 +00:00Commented Jun 25, 2018 at 11:35
2 Answers 2
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. :)
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.
-
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.Dingodudesir– Dingodudesir2018年06月26日 16:58:36 +00:00Commented 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– romkey2018年06月27日 16:01:24 +00:00Commented 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.Dingodudesir– Dingodudesir2018年06月28日 09:03:23 +00:00Commented 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– romkey2018年06月29日 13:29:49 +00:00Commented Jun 29, 2018 at 13:29
-
I have done that. Loop never runs again.Dingodudesir– Dingodudesir2018年06月29日 18:50:03 +00:00Commented Jun 29, 2018 at 18:50
Explore related questions
See similar questions with these tags.