0

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 Jun 20 '18 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 Jun 20 '18 at 14:43
  • Well, I have used the port successfully before to establish the connection. What other ports are available? – Dingodudesir Jun 21 '18 at 10:09
  • ports until 1023 are reserved en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers – Juraj Jun 22 '18 at 14:15
1

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 Jun 21 '18 at 10:10
  • You could, but why? It's wasteful of resources and would have no benefit. – Majenko Jun 21 '18 at 10:12
-1
  1. 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.

  2. 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

  3. Your server code needs to server a page and keep checking for connection with

    webServer.on("/", doRoot);

  4. 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 trash – Brian Moreau Jun 20 '18 at 14:00
  • Yes, code blocks and enumerated lists don't work well together. – Majenko Jun 20 '18 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. – Juraj Jun 20 '18 at 14:14
  • This might work good for web server based communication. However, in my case, one of the nodeMCUs is the server. – Dingodudesir Jun 21 '18 at 10:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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