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);
}
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.
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".
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 ?
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 ?
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 ?
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.
// 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();
}
}