I have a server-client arrangement (ESP32/8266 - to - ESP32/8266) where the client sends a request and gets data back.
Is it possible to get data from the client to the server ("client to server, data packet for you")?
Just an int (or a float, maybe a string).
Sure, client to server is easy..
client connects, send a request..
but to have server to client can be a bit tricky..
depends on the server..
could use udp, server could broadcast the request for data..
~q
To re-cap, I can get data from server to client already.
server.on("/bigTime", HTTP_GET, [](AsyncWebServerRequest *request)
{
timeData();
request->send_P(200, "text/plain", bufr);
});
That makes the server look at its millis() and send it back to the client.
Perhaps there's a way for the client to send its data to the server as part of its request?
All I can think of is having URL paths for every contingency - which would be clunky, verging on impractical.
http, haven't worked with AsyncWebServer..
if they have a file upload example, maybe look into it..
~q
omg
Maybe HTTP POST would do what you want. Info at randomnerd.
I tend to use websockets for 2 way communication with my ESP32 web server, but that's for a relatively complicated interactive WEB UI for a preamp. For just a little data, perhaps HTTP POST would be more appropriate
Use query parameters
/bigTime?one=2&three=four&etc=etal
Have a common routine to extract and parse those. Fallback: custom request headers.
More formally, a GET
is supposed to be idempotent, so if the client data changes something on the server side, it should be a POST
, even one with no body. But if you've already got all the server->client set up and just want to add those client->server parameters, no one else would know.
I based the server-client that I'm using on RNT's example, though I had to pick it apart on my own. He's really stuck on BME temp sensor and structs. I had been looking for something more 'hello world'. His http_post article is wrapped up in node-red, another complication.
Idempotence asidemy plan for the data from the client would be something simple - put up on a display the server might have or a microSD.
I'm not sure if I understand your problem right so I apologise in advance. Are you askin how to recognize URL text sent by client based ob server.on function? I guess this may be a little difficult.
One way to get around it is using basic WiFiServer like WiFiServer webServer (80); You can read the whole HTTP request in a String (the whole URL would be in the first line of HTTP request) before sending the reply. Then you can parse it as you wish.
#include <WiFi.h>
WiFiServer webServer (80);
void loop () {
WiFiClient webClient = webServer.accept ();
if (webClient) {
String httpRequest = "";
while (webClient.connected ()) {
if (webClient.available ()) {
char c = webClient.read ();
if (c == '\n' || c == '\r') { // read the HTTP request only until the first \n and discard the rest (although this information may be useful)
Serial.println ("Beginning of HTTP request from " + webClient.remoteIP ().toString () + ":\r\n" + httpRequest);
String httpReplyBody = "<HTML><BODY>This page has been accessed.</BODY></HTML>"; // always send a similar reply
Serial.println ("Body of HTTP reply:\r\n" + httpReplyBody);
webClient.print ("HTTP/1.1 200 OK\r\n"
"Content-type: text/html\r\n"
"Connection: close\r\n"
"Content-Length: " + String (httpReplyBody.length ()) + "\r\n"
"\r\n" +
httpReplyBody);
webClient.stop ();
return;
}
// else keep reading the httpRequest
httpRequest += c;
}
}
}
}
The dilemma is fundamental: how to send a char from the client to the server, assuming such a thing is possible.
All I can think of, to send 'X' or 'Y' (keeping things elementary) would be the client initiating some httpGETrequest accordingly --
// either, as appropriate . . .
httpGETRequest ("http://192.168.4.1/Xchar");
httpGETRequest ("http://192.168.4.1/Ychar");
The server would get the request, note the 'X' (or the 'Y') and then go on awaiting further opportunities to be of service --
server.on("/Xchar", HTTP_GET, [](AsyncWebServerRequest *request)
{
// X_counter ++; OR (??) print an X on OLED ??
//request->send_P(200, "text/plain", bufr);
});
server.on("/Ychar", HTTP_GET, [](AsyncWebServerRequest *request)
{
// Y_counter ++; OR (??) print a Y on OLED ??
//request->send_P(200, "text/plain", bufr);
});
Seems it should work, but I haven't tried it.
Wondering if there might be a better way.
Use query parameters
httpGETRequest("http://192.168.4.1/?thatonechar=X");
httpGETRequest("http://192.168.4.1/?thatonechar=Y");
httpGETRequest("http://192.168.4.1/bigTime?thatonechar=X");
httpGETRequest("http://192.168.4.1/bigTime?thatonechar=Y");
So the client can send one character along with an actual request like /bigTime
; or if it needs to send only, you could do that on the empty request path /
.
You should pick a better name for the query parameter than thatonechar
. You can also send any number of query parameters, separated by &
. If the single char you are sending has a "reserved purpose" in the query string of an URL, like '&
' or '%
', then it must be percent-encoded
The SimpleServer example shows how to read a query parameter with hasParam
and getParam
// Send a GET request to <IP>/get?message=<message>
server.on("/get", HTTP_GET, [](AsyncWebServerRequest* request) {
String message;
if (request->hasParam(PARAM_MESSAGE)) {
message = request->getParam(PARAM_MESSAGE)->value();
} else {
message = "No message sent";
}
request->send(200, "text/plain", "Hello, GET: " + message);
});