Send data from ESP32 to Processing via wifi - arduino

I was trying to connect ESP32 (client)-Processing (server) and I think I made it work, but server doesn't receive or print anything. Why processing doesn't recognise when client is connected? I am new to Processing and trying to undrestand how it works.
Processing:
import processing.net.*;
Server myServer;
void setup() {
size(400, 400);
// Starts a myServer on port 5204
myServer = new Server(this, 5204);
println(Server.ip());
}
void serverEvent(Server someServer, Client someClient) {
println("We have a new client: " + someClient.ip());
}
ESP32:
#include <WiFi.h>
const char* ssid = "myNetwork";
const char* pass = "myPassword";
void setup()
{
Serial.begin(115200);
delay(10);
WiFi.begin(ssid,pass);
Serial.print("Connecting.");
while(WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.print("WiFi connected - IP address: ");
Serial.println(WiFi.localIP());
delay(500);
}
void loop()
{
const uint16_t port = 5204;
const char * host = "10.0.26.xx";
Serial.print("Connecting to ");
Serial.println(host);
// Use WiFiClient class to create TCP connections
WiFiClient client;
if (client.connect(host, port)){
Serial.println("Sending data"); // printed on serial monitor
client.print("Hello");
}
// This will send a request to the server
client.print("Send this data to the server");
Serial.println("Closing connection.");
client.stop();
}
EDITED
It gives the same prints even if I don't run the processing program. So is it connected somewhere else instead of the server?
At the processing I am getting only that "The value of parameter someServer is not used"

Well, I figured out. It was a firewall issue. I disable the firewall and then it worked. Also, before that I created a new rule for the Processing and the Port but for some reason it didn't work I don't undrestand why. Disabled it was the solution to my problem.

Your processing code is missing the part where you retrieve data from the client.
You need to add something like this:
void draw() {
// Get the next available client
Client thisClient = myServer.available();
// If the client is not null, and says something, display what it said
if (thisClient != null) {
String whatClientSaid = thisClient.readString();
if (whatClientSaid != null) {
println(thisClient.ip() + "t" + whatClientSaid);
}
}
}
Source
I don't see any other obvious issues but I cannot test something similar to your setup right now. Maybe you can give it a try.

Related

ESP32: Send a simple TCP Message and receive the response

I want to do the same request as with the netcat "nc" command on my computer with an ESP32:
Computer:
$ nc tcpbin.com 4242
Test
Test
What I've tried so far:
Create a wifi client and listen to an answer:
Connect to a tcp server
write a message
wait and read the answer
#include <Arduino.h>
#include <WiFi.h>
WiFiClient localClient;
const char* ssid = "...";
const char* password = "...";
const uint port = 4242;
const char* ip = "45.79.112.203"; // tcpbin.com's ip
void setup() {
Serial.begin(115200);
Serial.println("Connect Wlan");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(WiFi.localIP());
}
void loop() {
sendRequest();
delay(200);
}
void sendRequest() {
if(!localClient.connected()) {
if (localClient.connect(ip, port)) {
Serial.println("localClient connected");
localClient.write('A'); //Single char
Serial.println("msg sent");
}
}
if(localClient.connected()) {
Serial.println("Start reading");
if (localClient.available() > 0) {
char c = localClient.read();
Serial.print(c);
}
Serial.println("Stop reading");
}
}
I'm pretty sure that I misunderstood something of the tcp concept during the implementation. However, after various approaches and trying other code snippets, I can't come up with a solution.
thank you in advance
regards
Leon
There are several issues with your code.
If you test nc, you will notice that the server will not acknowledge back until your press 'return'. You are sending a single byte without termination in your code, so the server is waiting for subsequent data. To terminate the data, you need to send a '\n', or instead of using client.write('A'), use client.println('A').
A network response take time, your current code expecting immediate response without waiting with if (localClient.available() > 0).
Here is the code that will work:
void sendRequest() {
if (localClient.connect(ip, port)) { // Establish a connection
if (localClient.connected()) {
localClient.println('A'); // send data
Serial.println("[Tx] A");
}
while (!localClient.available()); // wait for response
String str = localClient.readStringUntil('\n'); // read entire response
Serial.print("[Rx] ");
Serial.println(str);
}
}

ERR_CONNECTION_REFUSED when communicating with my ESP8266 over WiFi

Derived from the following code.
I uploaded that code to my ESP8266 and it's all good and okay when I communicate with it with my laptop while my laptop is connected to my network with a LAN cable.
The problem is: when I try to communicate with the ESP with my laptop or phone over Wi-Fi I get ERR_CONNECTION_REFUSED though they rarely work and communicate. I tried another phone another router, and did a factory reset to my router, and all the same.
I know that there is an option in the router that is called AP Isolation and it's been checked and it's disabled.
My question is: What could possibly be the reason for this error ERR_CONNECTION_REFUSED when I communicate with ESP8266 with that code?
If someone could help me I would be pleased as I am stuck in this situation.
The ESP code (same as the link):
#include <ESP8266WiFi.h>
const char* ssid = "*****";
const char* password = "*******";
WiFiServer server(80);
void setup() {
Serial.begin(115200);
Serial.println();
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" connected");
server.begin();
Serial.printf("Web server started, open %s in a web browser\n", WiFi.localIP().toString().c_str());
}
// prepare a web page to be send to a client (web browser)
// the connection will be closed after completion of the response
// the page will be refreshed automatically every 5 sec
String prepareHtmlPage() {
String htmlPage = String("HTTP/1.1 200 OK\r\n") +
"Content-Type: text/html\r\n" +
"Connection: close\r\n" +
"Refresh: 5\r\n" + "\r\n" +
"<!DOCTYPE HTML>" + "<html>" +
"Analog input: " + String(analogRead(A0)) +
"</html>" + "\r\n";
return htmlPage;
}
void loop() {
WiFiClient client = server.available();
// wait for a client (web browser) to connect
if (client) {
Serial.println("\n[Client connected]");
while (client.connected()) {
// read line by line what the client (web browser) is requesting
if (client.available()) {
String line = client.readStringUntil('\r');
Serial.print(line);
// wait for end of client's request, that is marked with an empty line
if (line.length() == 1 && line[0] == '\n') {
client.println(prepareHtmlPage());
break;
}
}
}
delay(1); // give the web browser time to receive the data
// close the connection:
client.stop();
Serial.println("[Client disconnected]");
}
}
I hope its not too late and it helps someone in need.
You need to do 2 things
Before WiFi.begin(), you need to add
WiFi.mode(WIFI_STA);
Second, you need to
#include <ESP8266mDNS.h>
in setup()
if (MDNS.begin("esp8266")) {
Serial.println("MDNS responder started");
}
and in loop()
MDNS.update();
Lastly, do not forget to add the following in every server response. Else, you will hit CORS error.
server.sendHeader("Access-Control-Allow-Origin", "*");
Please dont forget to add supporting libraries. Let me know if it works. Demo code would look like the below
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
const char* ssid = "<your SSID>";
const char* password = "<your WIFI Password>>";
int serverPort = 80;
int boardBaud = 115200;
ESP8266WebServer server(serverPort);
void handleRoot() {
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/html", "<h1>Hello World</h1>");
}
void handleNotFound() {
if (server.method() == HTTP_OPTIONS)
{
server.sendHeader("Access-Control-Allow-Origin", "*");
server.sendHeader("Access-Control-Max-Age", "10000");
server.sendHeader("Access-Control-Allow-Methods", "PUT,POST,GET,OPTIONS");
server.sendHeader("Access-Control-Allow-Headers", "*");
server.send(204);
}
else
{
server.send(404, "text/plain", "Error");
}
}
void setup(void) {
Serial.begin(boardBaud);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
if (MDNS.begin("esp8266")) {
Serial.println("MDNS responder started");
}
server.on("/", handleRoot);
server.onNotFound(handleNotFound);
server.begin();
Serial.println("HTTP server started");
}
void loop(void) {
server.handleClient();
MDNS.update();
}

Configure WiFi on ESP8266 uing WIFI_AP_STA mode

I am trying to program my NodeMCU (Lolin v3) board in such a way that I can use it to configure the WiFi settings without having to hard code the credentials. I know there is a WiFiManager Library, but I don't intend to use that since I need to do my own implementation, not use the UI that the library provides. The credentials provided by the user are stored in a file using SPIFFS, used to check whether to start the board in AP_STA mode or STA mode only.
Below is the logic I use:
void connectWiFi(String ssid, String password, boolean staOnly = false) {
boolean state = true;
int i = 0;
if(staOnly)
WiFi.mode(WIFI_STA);
WiFi.begin(ssid.c_str(), password.c_str());
while (WiFi.status() != WL_CONNECTED) {
delay(500);
if (i > 10) {
state = false;
break;
}
i++;
}
return state;
}
void join() {
String ssid = setupServer.arg("ssid");
String password = setupServer.arg("password");
result = connectWifi(ssid, password);
if(result) {
Serial.println("Connected");
// **THIS IS THE PROBLEMATIC PART**
setupServer.send(200, "text/plain", WiFi.localIP().toString());
// save credentials to a file
Serial.println("Conf saved");
delay(2000);
ESP.restart();
} else
setupServer.send(200, "text/plain", "fail");
}
void setup() {
Serial.begin(115200);
WiFi.disconnect(true);
boolean fileExists = SPIFFS.exists(WIFI_CONF_FILE);
if(!fileExists) {
WiFi.mode(WIFI_AP_STA);
WiFi.softAP("AP", "password");
IPAddress myIP = WiFi.softAPIP();
setupServer = ESP8266WebServer(myIP, 8888);
setupServer.on("/join", join);
setupServer.begin();
} else {
// read file contents for ssid and password
connectWifi(ssid, password, true);
// do some work here
}
}
void loop() {
setupServer.handleClient();
}
So now when I do a fresh boot, the board enters AP_STA mode and starts with SSID AP. I connect to it and open http://192.169.4.1/join?ssid=mywifi&password=12345678 in the browser. Somehow the connection gets terminated and I get "Destination Unreachable" in my browser. But the serial monitor prints 'Connected' and 'Conf saved'.
I want to know why it isn't returning the success response to the browser. I need the localIP after it has connected to the WiFi. It returns the failed response correctly in case it fails. How can I ensure it will always return the IP address assigned to it back to the client that connected to it before restarting?
Any help is appreciated.
Thanks!
Looks like it is bound to happen as radio module is shared between two modes.
Found the explaination for this issue here: https://github.com/esp8266/Arduino/issues/3282
This is related to the fact that STA will switch to the channel of the AP it is trying to connect to, and SoftAP will have to switch to the same channel. So the client (PC or smartphone connected to the SoftAP) will have to reconnect to the SoftAP on its new channel. In most cases this causes TCP connections to be reset.

MQTT on Arduino not working

I'm using Arduino Uno and Wi-Fi shield. I'm trying to implement MQTT protocol for communication and I tried two libraries for Arduino. First one is Knolleary's PubSubClient: http://pubsubclient.knolleary.net/ . I modified original example a little bit to use WiFi module instead of ethernet. Sending works but not every time (sometimes, the message is sent and sometimes not). But receiving via callback function doesn't work at all.
Here is my code:
/*
Basic MQTT example with Authentication
- connects to an MQTT server, providing username
and password
- publishes "hello world" to the desired topic
- subscribes to the desired topic
*/
#include <WiFi.h>
#include <PubSubClient.h>
char ssid[] = "[DELETED]"; // your network SSID (name)
char pass[] = "[DELETED]"; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status
// Update these with values suitable for your network.
IPAddress server(85, 119, 83, 194);
WiFiClient WifiClient;
void callbackFunc(char* topic, byte* payload, unsigned int length) {
Serial.println("test message received");
/*Serial.println();
Serial.println("=============== MESSAGE RECEIVED ================================");
Serial.print("Topic: ");
Serial.print(topic);
Serial.println();
Serial.println((const char *) payload);*/
}
PubSubClient client(server, 1883, callbackFunc, WifiClient);
void setup()
{
delay(2000);
Serial.begin(9600);
Serial.println("Starting....");
Serial.println("Initializing Wifi...");
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
}
// attempt to connect using WPA2 encryption:
Serial.println("Attempting to connect to WPA network...");
status = WiFi.begin(ssid, pass);
// if you're not connected, stop here:
if (status != WL_CONNECTED) {
Serial.println("Couldn't get a wifi connection");
while(true);
}
// If you are connected, print out success message
else
Serial.println("Connected to network");
if (client.connect("arduinoClient")) {
Serial.println("Connected to server! Sending message...");
client.publish("randy/test","hello world");
client.subscribe("randy/test");
Serial.println("Sent!");
}
else
{
Serial.println("ERROR: Cannot connect to MQTT server!");
Serial.println(client.state());
}
}
void loop()
{
client.loop();
delay(1000);
if (!client.connected())
{
if(!client.connect("arduinoClient"))
{
Serial.println("ERROR: Cannot connect to MQTT server!");
Serial.println(client.state());
}
else
{
client.subscribe("randy/test");
Serial.println("INFO: reconnected!");
}
}
}
As you can see, I'm using http://test.mosquitto.org/ for testing. I'm also using mosquitto on Ubuntu where I'm subscribed to the same topic and from where (another terminal window) I'm publishing to the same topic. Here is the picture of both windows:
As you can see, "hello world" message from Arduino is received successfully (but not every time), and when I publish "bla" message from another window, it's successfully received on mosquitto (on image) but NOT on Arduino. Is there something wrong with my code or? I found similar problem here: Arduino Knolleary PubSubClient will publish messages but can't receive them
It's worth noticing that it keeps getting reconnected all the time. As you can see, in loop() I put a part of code which will connect and subscribe again if connection is lost. On Serial Monitor I get "INFO: Reconnected!" message every 2-3 seconds.
Adafruit library
Then I tried the Adafruit library, but it won't connect at all! I tried with test.mosquitto.org and with io.adafruit.com from their example, but I just keep getting "Connection failed!" error. I tried making many changes and combinations but no luck so far. Once I managed to get "Failed to subscribe" instead of "Connection failed" but this was only once and next time with the same code I get "Connection failed" again.
Here's my code:
/*
Basic MQTT example with Authentication
- connects to an MQTT server, providing username
and password
- publishes "hello world" to the topic "outTopic"
- subscribes to the topic "inTopic"
*/
#include <WiFi.h>
#include <PubSubClient.h>
char ssid[] = "[DELETED]"; // your network SSID (name)
char pass[] = "[DELETED]"; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status
// Update these with values suitable for your network.
IPAddress server(85, 119, 83, 194);
WiFiClient WifiClient;
void callbackFunc(char* topic, byte* payload, unsigned int length) {
Serial.println("test message received");
/*Serial.println();
Serial.println("=============== MESSAGE RECEIVED ================================");
Serial.print("Topic: ");
Serial.print(topic);
Serial.println();
Serial.println((const char *) payload);*/
}
PubSubClient client(server, 1883, callbackFunc, WifiClient);
void setup()
{
delay(2000);
Serial.begin(9600);
Serial.println("Starting....");
Serial.println("Initializing Wifi...");
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
}
// attempt to connect using WPA2 encryption:
Serial.println("Attempting to connect to WPA network...");
status = WiFi.begin(ssid, pass);
// if you're not connected, stop here:
if (status != WL_CONNECTED) {
Serial.println("Couldn't get a wifi connection");
while(true);
}
// Ff you are connected, print out success message
else
Serial.println("Connected to network");
if (client.connect("arduinoClient")) {
Serial.println("Connected to server! Sending message...");
client.publish("randy/test","hello world");
client.subscribe("randy/test");
Serial.println("Sent!");
}
else
{
Serial.println("ERROR: Cannot connect to MQTT server!");
Serial.println(client.state());
}
}
void loop()
{
client.loop();
delay(1000);
if (!client.connected())
{
if(!client.connect("arduinoClient"))
{
Serial.println("ERROR: Cannot connect to MQTT server!");
Serial.println(client.state());
}
else
{
client.subscribe("randy/test");
Serial.println("INFO: reconnected!");
}
}
}
Any idea what's wrong with those libraries or my code?
As mentioned in the comments
When using example code on public brokers make sure you change the client id to something random as the odds of clashing with somebody else are pretty high. Because client ids have to be unique else they will cause a reconnection storm

ethernet webserver example, client.stop causes lag time issues

Using the ethernet WebServer example code, I've got my arduino to host a website stored on an SD card. The website uses jquery to post the position of the mouse in the webbrowser back to the arduino. I would ultimately like to use this info to control a servo motor, however, the problem I have is that the client.stop line in each iteration of the void loop causes a large lag time in between when the mouse moves and when the arduino gets the information.
Is there a way to make this code only use the execute the stop.client line when the mouse stops moving. So effectively when there no information being sent from the to the arduino via the post method?
Here is my code.
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
String POST = "";
int count = 0;
const int chipSelect = 4;
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,178,30);
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
EthernetClient client;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
Serial.setTimeout(10);
//start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
client.setTimeout(1);
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
//SD card stuff
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// don't do anything more:
return;
}
Serial.println("card initialized.");
}
void loop() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
String POST = "";
while(client.available()){
c = client.read();
// save the variables somewhere
POST += c;
}
if(POST != ""){
Serial.println(POST);
}
//load html/css/js for website only once
if (count <= 0){
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
//client.println("Refresh: 5"); // refresh the page automatically every 5 sec
client.println();
File dataFile = SD.open("site.txt");
// if the file is available, write to it:
if (dataFile) {
while (dataFile.available()) {
//Serial.write(dataFile.read());
client.write(dataFile.read());
}
dataFile.close();
}
// if the file isn't open, pop up an error:
else {
Serial.println("error opening site.txt");
}
}
//count = 1;
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
if (count == 0){
delay(500);
}
else{
delay(1);
}
count=1;
// close the connection:
client.stop();
Serial.println("client disonnected");
}
}
yes, is possible but realy hard as you have to implement HTTP\1.1, also this will reamin slow as for every mouse position, browser have to send a full HTTP request, arduino read and intepretate it.
Best solution is to use websocket (there are already some serbsocket server lybrary for arduino), once a websocket is setted-up, you have a two way communication exactly like a Serial!

Resources