Wifi communication between server and client arduino boards

Hi, I am trying to program an Arduino board as server and another Arduino as client. They are going to communicate data with each other. Server requests data from client and in response client sends a string message to the server. Then, server analyses the message and responds to client.
The issue is that my client very unstably connects to server and mostly it fails to connect to server.
Codes are Attached (I used VS, so the functions are defined after the main body of the code).
// Client:
// This code designed to enable server and client board to communicate with each other
// by calling their name and exchanging messages over wifi

#include <Arduino.h>
#include <WiFi.h>
const char *ssid = "ESP32-Access-Point";
const char *password = "123456789";
unsigned long previousMillis = 0;
int interval = 500;
String CLIENT_NAME = "SENSOR1";
WiFiClient client;
// IP Address of the server
IPAddress server(192, 168, 4, 1);
String ServerMessage;
void setup()
{
  Serial.begin(9600);
  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(50);
    Serial.print(".");
    Serial.println("");
    Serial.print("Connected to WiFi network with IP Address: ");
    Serial.println(WiFi.localIP());
  }
}
void loop()
{
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval)
  {
    Serial.println("Attemting to connect");
    // Check WiFi connection status
    if (WiFi.status() == WL_CONNECTED)
    {
      Serial.println("wifi status connected");
      client.connect(server, 80);
      while (client.connected())
      {
        Serial.println("client connected");
        String data = client.readStringUntil('\r');
        if (data != "\0")
        {
          Serial.print("Received data from Server:");
          Serial.println(data);
          int Index = data.indexOf(':');
          String CLIENT = data.substring(0, Index);
          String ACTION = data.substring(Index + 1);
          if (CLIENT == CLIENT_NAME)
          {
            if (ACTION == "TEMPERATURE?")
            {
              client.println("ACK:10");
              Serial.println("This is Client: ACK10 was sent to server");
            }
          }
          else if (CLIENT == "OUTPUT1")
          {
            if (ACTION == "ON" || ACTION == "OFF")
            {
              Serial.println("This is Client: server is sending output1 On or Off command");
            }
          }
          client.flush();
          data = "\0";
        }
      }
    }
    previousMillis = millis();
  }
}
// Server:
// This code designed to enable server and client board to communicate with each other
// by calling their name and exchanging messages over wifi
#include <Arduino.h>
#include "WiFi.h"
#define NUM_CLIENTS 2
String data;
String CLIENT;
String ACTION;
const char *ssid = "ESP32-Access-Point";
const char *password = "123456789";
WiFiServer server(80);
WiFiClient *clients[NUM_CLIENTS] = {NULL};
void clientCommand(String input)
{
  for (int i = 0; i < NUM_CLIENTS; i++)
  {
    WiFiClient client = server.available();
    if (client)
    {
      if (client.connected())
      {
        client.println(input);
        delay(10);
      }
    }
  }
  delay(100);
}
String clientRequest(String input)
{
  String response = "\0";
  for (int i = 0; i < NUM_CLIENTS; i++)
  {
    WiFiClient client = server.available();
    client.setTimeout(100);
    if (client)
    {
      if (client.connected())
      {
        client.println(input);
        data = client.readStringUntil('\r'); // received the server's answer
        if (data != "\0")
        {
          int Index = data.indexOf(':');
          CLIENT = data.substring(0, Index);
          ACTION = data.substring(Index + 1);
          if (CLIENT == "ACK")
          {
            response = ACTION;
          }
          // ? Research to see if you can save a matrix of clients connected without needing to flush them
          client.flush();
          data = "\0";
        }
      }
    }
  }
  delay(200);
  return response;
}
void connect_wifi()
{
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(100);
  }
}
void setup()
{
  Serial.begin(9600);
  //Start Server
  Serial.println();
  Serial.print("Setting soft AP (Access Point)…");
  // Remove the password parameter, if you want the AP (Access Point) to be open
  WiFi.mode(WIFI_AP);
  WiFi.softAP(ssid, password);
  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(IP);
  server.begin();
  //End: Server
}
void loop()
{
  if ((clientRequest("SENSOR1:TEMPERATURE?").toInt()) > 30) //Request the temperature from SENSOR1
  {
    clientCommand("OUTPUT1:ON"); //Sets the output on OUTPUT1
    Serial.println("This is Server: Output1:On was sent to client");
  }
  else
  {
    clientCommand("OUTPUT1:OFF"); //Sets the output on OUTPUT1
    Serial.println("This is Server: Output1:Off was sent to client");
  }
  delay(1000);
}

I am not much pro in this type of issues. But can I know what sort of communication protocol being used for this ?

Please read the Forum guidelines How to get the best out of this forum - Using Arduino / Programming Questions - Arduino Forum. Format your code using the arduino IDE and T and then paste it using code tags - that way it is far easier for everyone to read and in a form we are all used to.

What sort of Arduinos are you using, and are you using an ESP32 as the Access Point for both?

This code is based on different methods used in other projects I found on Internet. I am using library <wifi.h> to create a soft Access Point for the server and communicate between client and server over a local wifi with no access to Internet. I really don’t have the proper answer to your question.

1 Like

Maybe I’m missing something, but I cannot see how the server works. To start with it does not appear to have an IP Address so nothing would be able to make contact with it. Second I cannot see where Wifi.Begin is ever called. There is a function connect_wifi but I cannot see anything that calls it.

Have you included all the code? Have I simply missed these pieces?

In Void Setup section of Server Code, IP address of the server is printed and I used the same IP to connect to server. For the second question, Instead of WiFi.begin I am using server.begin.

Every example I have seen has Wifi.begin() before server.begin(). Wifi.begin starts up the network whereas server.begin starts up server using that network. Arduino - WiFiServerBegin

Only one piece of code has the IP Address defined, where does the other code get the IP Address from?

Thanks @countrypaul , I modified my code based on your comment. I added below pieces to my code, and I can see they are connected but it seems client reads data from server only once and after that client is only getting data = “\0”.

Added to the server code:

IPAddress local_IP(192, 168, 4, 1);
IPAddress gateway(192, 168, 4, 9);
IPAddress subnet(255, 255, 255, 0);

WiFi.begin();

My monitor window shows the result as follows:

Setting soft AP (Access Point)…AP IP address: 192.168.4.1
[E][WiFiClient.cpp:288] setSocketOption(): 1006 : 9
[E][WiFiClient.cpp:288] setSocketOption(): 1006 : 9
This is Server: Output1:Off was sent to client
[E][WiFiClient.cpp:288] setSocketOption(): 1006 : 9
[E][WiFiClient.cpp:288] setSocketOption(): 1006 : 9
This is Server: Output1:Off was sent to client

My Client Monitor shows:

Connected to WiFi network with IP Address: 192.168.4.2
Attemting to connect
wifi status connected
client connected
SENSOR1:TEMPERATURE?
Received data from Server:SENSOR1:TEMPERATURE?
This is Client: ACK10 was sent to server
[E][WiFiClient.cpp:485] flush(): fail on fd 54, errno: 11, “No more processes”
Attemting to connect
wifi status connected
client connected
client connected

Thanks for the information. Really sorry for that I am not good on the server client programming. And I hope you are using the arduino boards with wifi enabled, esp8266. Can you mention the names of the boards being used ?

OK, that should make things more stable. I will have a look at the “\0” issue later, but it may be tomorrow (I’m in UK).

These are customized developing kit of with espressif ESP32-WROOM-32D micro controller.

1 Like

Thanks for that. I thinks @countrypaul has suggested the suitable changes related to the ip address and the subnet. Although do I need to work with public only right ?

Thanks :pray:

If you are asking about IP, it’s a private (local) network. Im not sure if I understood your question

1 Like

Yeah I got it. I have asked about the ip whether it is an private or public. So for this operation both the boards has to be connected to the same network right ?

The server board is actually the one which creates the wifi network. Client board connects to the wifi which has been created by server board.

1 Like

Ok fine great. And any doubts regarding this I will look into this.

You have Delay() at the end of many of your routines, the use of delay effectively disables interupts and that can cause things to get missed. I think you should remove the Delay() at the end of clientCommand and clientRequest and the long delay at the end of loop(). These are Ok for testing and Ok in Setup when starting WIfi but can be very detrimental when you have effectively background work needing to take place as you have with a network running.

On clientRequest you attempt to create a new WifiClient then set its timeout then check whether it was created. Move the setTimeout to inside “if (client)” block.

If you look at server.available() documentation it says::
“Gets a client that is connected to the server and has data available for reading. The connection persists when the returned client object goes out of scope; you can close it by calling client .stop().”

This suggests in your case that the connection persists after you leave clientRequest and each time you call clientRequest you attempt to create another connection! I suggest you put a client.stop() at the end of the for loop. The same applies to clientCommand.

You have “WiFiClient *clients[NUM_CLIENTS] = {NULL};” which suggests to me that you intended to create the clients once and resuse them, but changed your approach - the above declaration never appears to be made use of. You said you got the code from elsewhere, it might be helpful it you can give a link to the original source.

From past experience it is worth posting you code again once you have made changes. If someone else want to check something it if far easier for them to spot mistakes with the right code than trying to work out what has been changed in the old code from the various messages that follow it. It also makes it less likely that I have made a suggestion that is ambiguous and leads to a change that was not intended.

Great job @countrypaul , I followed your instructions and made necessary changes. Now the code is working perfect; server and client are communicating flawlessly. I added the final version of the codes here.
Updated Server and Client Codes are attached.

Following links were my main references to start this code:
multiple client server over wifi
esp32-server-and-many-esp8266-clients-controlled-over-wifi

Version 0.1 of Server Code:

// Server:
// This code designed to enable server and client board to communicate with each other
// by calling their name and exchanging messages over wifi

#include <Arduino.h>
#include "WiFi.h"

#define NUM_CLIENTS 2
String data;
String CLIENT;
String ACTION;

const char *ssid = "ESP32-Access-Point";
const char *password = "123456789";
IPAddress local_IP(192, 168, 4, 1);
IPAddress gateway(192, 168, 4, 9);
IPAddress subnet(255, 255, 255, 0);
WiFiServer server(80);
// This matrix is defined for further development, it has not been used in the code
WiFiClient *clients[NUM_CLIENTS] = {NULL};

void clientCommand(String input)
{
  for (int i = 0; i < NUM_CLIENTS; i++)
  {
    WiFiClient client = server.available();
    if (client)
    {
      if (client.connected())
      {
        client.println(input);
        delay(10);
      }
    }
    client.stop();
  }
}

String clientRequest(String input)
{
  String response = "\0";
  for (int i = 0; i < NUM_CLIENTS; i++)
  {
    WiFiClient client = server.available();
    if (client)
    {
      client.setTimeout(50);
      if (client.connected())
      {
        client.println(input);

        data = client.readStringUntil('\r'); // received the server's answer
        if (data != "\0")
        {
          int Index = data.indexOf(':');

          CLIENT = data.substring(0, Index);
          ACTION = data.substring(Index + 1);

          if (CLIENT == "ACK")
          {
            response = ACTION;
          }
          data = "\0";
        }
      }
    }
  }
  return response;
}

// This void is for further developmets and has not ben used
void connect_wifi()
{
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    //delay(100);
  }
}

void setup()
{
  Serial.begin(9600);

  //Start Server
  Serial.println();
  Serial.print("Setting soft AP (Access Point)…");
  // Remove the password parameter, if you want the AP (Access Point) to be open
  WiFi.mode(WIFI_AP);
  WiFi.softAPConfig(local_IP, gateway, subnet);
  WiFi.softAP(ssid, password);
  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(IP);
  WiFi.begin();
  server.begin();
  //End: Server
}

void loop()
{
  if ((clientRequest("SENSOR1:TEMPERATURE?").toInt()) > 30) //Request the temperature from SENSOR1
  {
    clientCommand("OUTPUT1:ON"); //Sets the output on OUTPUT1
    Serial.println("This is Server: Output1:On was sent to client");
  }
  else
  {
    clientCommand("OUTPUT1:OFF"); //Sets the output on OUTPUT1
    Serial.println("This is Server: Output1:Off was sent to client");
  }
}

Version 0.1 of Client Code:

// Client:
// This code designed to enable server and client board to communicate with each other
// by calling their name and exchanging messages over wifi
#include <Arduino.h>
#include <WiFi.h>

const char *ssid = "ESP32-Access-Point";
const char *password = "123456789";

unsigned long previousMillis = 0;
int interval = 500;

String CLIENT_NAME = "SENSOR1";
WiFiClient client;

// IP Address of the server
IPAddress server(192, 168, 4, 1);

String ServerMessage;

void setup()
{
  Serial.begin(9600);
  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(50);
    Serial.print(".");
    Serial.println("");
    Serial.print("Connected to WiFi network with IP Address: ");
    Serial.println(WiFi.localIP());
  }
}

void loop()
{
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval)
  {
    Serial.println("Attemting to connect");
    // Check WiFi connection status
    if (WiFi.status() == WL_CONNECTED)
    {
      Serial.println("wifi status connected");
      client.connect(server, 80);
      while (client.connected())
      {
        Serial.println("client connected");
        String data = client.readStringUntil('\r');
        Serial.println(data);
        if (data != "\0")
        {
          Serial.print("Received data from Server:");
          Serial.println(data);
          int Index = data.indexOf(':');
          String CLIENT = data.substring(0, Index);
          String ACTION = data.substring(Index + 1);
          if (CLIENT == CLIENT_NAME)
          {
            if (ACTION == "TEMPERATURE?")
            {
              client.println("ACK:10");
              Serial.println("This is Client: ACK10 was sent to server");
            }
          }
          else if (CLIENT == "OUTPUT1")
          {
            if (ACTION == "ON" || ACTION == "OFF")
            {
              Serial.println("This is Client: server is sending output1 On or Off command");
            }
          }

          client.stop();
          data = "\0";
        }
      }
    }
    previousMillis = millis();
  }
}