I am trying to communicate multiple clients to a server, all using nodeMCUs. I am getting a weird run time error at the Server Serial Monitor of Arduino IDE when I upload the code.
Here's my server code:
#include <ESP8266WiFi.h>
#define Max_Clients 5
WiFiServer server(80);
WiFiClient *clients[Max_Clients] = {NULL};
String inputs [Max_Clients] = {""}; //Initializing to store the string received from clients
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
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
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]){
clients[i] = new WiFiClient(client); //nothing in clients[i] means it is a new client
break;
}
}
}
for(int i=0 ; i<Max_Clients ; ++i){ //For available clients
if (NULL != clients[i] && clients[i]->available()){
String request = clients[i]->readStringUntil('\r');
Serial.println("The string of client "+String(i+1)); //Print client's message
inputs[i] = request;
Serial.println(inputs[i]);
int duty[4];
duty[i] = inputs[i].toInt();
if (i == 0){
analogWrite(D1, duty[i]);
clients[i]->println("To client 1.\r");
}
if (i == 1){
analogWrite(D2, duty[i]);
clients[i]->println("To client 2.\r");
}
if (i == 2){
analogWrite(D3, duty[i]);
clients[i]->println("To client 3.\r");
}
clients[i]->flush(); //Waiting for transmission to complete
clients[i]->stop();
}
}
} //void loop closure
Here's my client code (which will be same for all clients):
#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
int sense = 200;
client.println(sense+"\r"); //Client's message to the server
String answer = client.readStringUntil('\r'); //Reading response from the server
Serial.println("from server: " + answer); //Printing the response
client.flush();
delay(3600000);
}
else{
Serial.println("Error in WiFi connection");
}
}
On uploading this code, the Serial Monitor at the server shows:
A new Client has connected :) The string of client 1 nt8_t* BufferedStreamDataSource::get_buffer(size_t) [with TStream =>ProgmemStream; uint8_t = unsigned char; size_t = unsigned int] The string of client 1
While the Serial Monitor at the client shows:
Connecting... Connecting... Connecting... Connecting... Connecting... Connecting... Connecting... Connected. from server: To client 1.
I have no clue of the source of this error. Any help is appreciated.
Thanks in advance.
-
do not use port 80 if it is not HTTP. use port 23 or 2323, which indicates plain socket communication (telnet). and you can test the server from a telnet client.Juraj– Juraj ♦2018年06月20日 14:18:29 +00:00Commented Jun 20, 2018 at 14:18
-
You shouldn't use 23 since that implies an interactive connection. You should use any port but 80 - ideally not use a port associated with any known protocol. But it really doesn't matter on an embedded system what port you use... Btw - telnet can connect to any port - even 80.Majenko– Majenko2018年06月20日 14:43:03 +00:00Commented Jun 20, 2018 at 14:43
-
Well, I have used the port successfully before to establish the connection. What other ports are available?Dingodudesir– Dingodudesir2018年06月21日 10:09:27 +00:00Commented Jun 21, 2018 at 10:09
-
ports until 1023 are reserved en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbersJuraj– Juraj ♦2018年06月22日 14:15:25 +00:00Commented Jun 22, 2018 at 14:15
2 Answers 2
I suspect the problem stems from the client side. This line:
client.println(sense+"\r"); //Client's message to the server
doesn't do what you think it does.
sense
is a number (200). "\r"
is a string constant located at an address in memory. When you add the two together you are not concatenating two strings, but you are adding 200 to the address of the string constant - and then sending whatever it finds at that location.
The "\r" is actually redundant anyway, since you are using println
which adds \r\n
to the end of a print. However if you do want to do it manually you just need to split it into two prints:
client.print(sense);
clienr.print("\r");
-
Can I just make 'sense' a string? It should pass as a String and will make changes at the client.Dingodudesir– Dingodudesir2018年06月21日 10:10:04 +00:00Commented Jun 21, 2018 at 10:10
-
You could, but why? It's wasteful of resources and would have no benefit.Majenko– Majenko2018年06月21日 10:12:55 +00:00Commented Jun 21, 2018 at 10:12
Research WL_CONNECTED, I think you find that is the connection state to your Access Point not the state if a device has connected, also their are issues with this variable. It doesn't change state when the connection is dropped.
to make a connection you need to make a GET or POST request to a page on your server something like...
if (client.connect(server, httpPort)) { // connected to resource // send data client.print("GET /myfile"); client.println(" HTTP/1.1"); client.println("Host: IPADDRESS"); client.println("Connection: close"); client.println(); } else { // No connection to server // should maybe keep retrying else waits till next call } // end if connect
Your server code needs to server a page and keep checking for connection with
webServer.on("/", doRoot);
Then have a function that writes the HTML back to client like...
void doRoot() { // write HTML String html; html = ""; html += "
My Page
"; // and send it webServer.send(200, "text/html", html); }
-
Sorry I cant work the formatting out for this site, I use enter code and it says enter code here but when pasted its trashBrian Moreau– Brian Moreau2018年06月20日 14:00:36 +00:00Commented Jun 20, 2018 at 14:00
-
Yes, code blocks and enumerated lists don't work well together.Majenko– Majenko2018年06月20日 14:10:45 +00:00Commented Jun 20, 2018 at 14:10
-
WiFiClient is a TCP socket. it can be used as it is. there is no need to use HTTP protocol between two devices. but it is not nice to use port 80 which is in standard reserved for HTTP.2018年06月20日 14:14:47 +00:00Commented Jun 20, 2018 at 14:14
-
This might work good for web server based communication. However, in my case, one of the nodeMCUs is the server.Dingodudesir– Dingodudesir2018年06月21日 10:12:10 +00:00Commented Jun 21, 2018 at 10:12