Need help getting a SparkFun ESP8266 connecting to a URL - arduino

I've been trying to get a piece of code that sends a text message to a phone when an IFTTT applet site is visited, I've been following this tutorial regarding the text message itself and this one for the WiFi shield for the ability to connect to a webpage and an HTTP request.
Basically, my problem is that it will connect to any "simple" site like google.com but it can't for "longer/complex" links. I was wondering if you would have any idea how would I solve this problem and get this to work. I've tried just using the addition symbol to combine the "simple" link and the rest of my desired link but that doesn't work either.
#include <SoftwareSerial.h> // Include software serial library, ESP8266 library dependency
#include <SparkFunESP8266WiFi.h> // Include the ESP8266 AT library
void setup() {
Serial.begin(9600);
String url = "/trigger/ESP/with/key/dwSukgpyQsyampQMkXXXX";
Serial.print (url);
// put your setup code here, to run once:
if (esp8266.begin()) // Initialize the ESP8266 and check it's return status
Serial.println("ESP8266 ready to go!"); // Communication and setup successful
else
Serial.println("Unable to communicate with the ESP8266 :(");
int retVal;
retVal = esp8266.connect("network", "networkpassword");
if (retVal < 0)
{
Serial.print(F("Error connecting: "));
Serial.println(retVal);
}
IPAddress myIP = esp8266.localIP(); // Get the ESP8266's local IP
Serial.print(F("My IP is: ")); Serial.println(myIP);
ESP8266Client client; // Create a client object
retVal = client.connect("maker.ifttt.com" + url, 80); // Connect to sparkfun (HTTP port)
if (retVal > 0)
Serial.println("Successfully connected!");
client.print("GET / HTTP/1.1\nHost: maker.ifttt.com" + url + "\nConnection: close\n\n");
while (client.available()) // While there's data available
Serial.write(client.read()); // Read it and print to serial
}
void loop() {
// put your main code here, to run repeatedly:
}
Thanks, any help would be very much appreciated!

First, the connect function requires a server(name) to connect to. In your case: maker.ifttt.com. Anything after the .com will make the connection fail (because it's not a correct servername).
Second: this function needs an IP address (like 54.175.81.255) or an array of characters. You cannot concatenate.
After you've established the connection, you can send and receive data to a specific part of this website, using the print function.
Also, in this function you can't concatenate.
Luckily, there is a String class where we easily can concatenate.
So, after you've created the client object (ESP8266Client client;), this could be the code:
String url;
char host[] = "maker.ifttt.com";
retVal = client.connect(host, 80);
if (retVal > 0) {
Serial.println("Successfully connected!");
}
url = "GET / HTTP/1.1\r\nHost: ";
url += host;
url += "/trigger/ESP/with/key/dwSukgpyQsyampQMkXXXX";
url += "\nConnection: close\n\n";
client.print(url);
while (client.connected() && !client.available());
while (client.available()) {
Serial.write(client.read());
}

Related

How to have multiple connections to a Arduino webserver?

I have an Arduino running a webserver that is receiving data every 2 seconds. I CAN connect to its IP address by typing into the browser. I also created a web app that pulls data from this IP address every time new data comes in. The issue is that I need to access the IP address with the web app while another program is accessing it. Currently only one program can access at a time. I would like to have a Python script pulling data from the IP address constantly and still allow the web app to connect to view it live. How can I achieve this?
Arduino code with a lot of other stuff removed...
WiFiServer server(80); //server socket
WiFiClient client_1 = server.available();
void setup() {
Serial.begin(9600);
enable_WiFi(); // function to enable wifi
connect_WiFi(); // function to connect to wifi
server.begin();
}
void loop() {
client_1 = server.available();
if (client_1) {
printWEB(client_1); // this posts the data as text to the web IP address
}
delay(2000);
}
void printWEB(WiFiClient client) {
if (client) { // if you get a client,
Serial.println("new client"); // print a message out the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Access-Control-Allow-Origin: *");
client.println("Access-Control-Allow-Methods: GET");
client.println("Content-type: application/json");
client.println();
moistureReading = analogRead(A1);
tmpString = dataPosted;
tmpString.replace("%moistureData%", String(moistureReading) );
client.flush();
client.print( tmpString );
// The HTTP response ends with another blank line:
client.println();
// break out of the while loop:
break;
}
else { // if you got a newline, then clear currentLine:
currentLine = "";
}
}
else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// close the connection:
client.stop();
Serial.println("client disconnected");
}
}
The solution here was to take the delay off of the arduino code by simply removing the sleep function (Turns out this is not required). I then had to create a delay in all of my fetching codes. The React.js needed a sleep function and the python script needed a sleep function. This allows the two platforms to collect data from the same IP Address simultaneously. I needed a minimum of about 5-10 second sleep for both apps in order for this to work. I initially tried 1 second for each and it didn't work.
The webserver as programmed on your Arduino can only serve one request from a client at a time, not two simultaneously.
If two clients are doing requests in a loop, and are doing that fairly quickly, there will be situations where one client is blocking access for the other.
Try making the two clients much slower, i.e. retrieve information at a much lower frequency, just to see if the Arduino can keep up then.
Also, make the webserver on the Arduino as fast as possible, and call it as often as possible.
So, don't put delay()s in the loop, or anywhere else, and try to do the analogread() and the return string preparation outside of the webserver code and in the loop() every x seconds using millis(), so as little time as possible is spent in the webserver code.

Send data from ESP32 to Processing via wifi

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.

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.

How can I make the WifiClient.connect work in Arduino?

I would like to know if WifiClient.connect does not allow the locally running server to be connected (e.g. http://localhost:8080). I discovered that WifiClient.connect works when the url is anything public (e.g. www.google.com). Please help if there may be something I can programmatically change in order to connect the localhost server. The code below is a portion of setup().
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 info about the connection:
else {
Serial.println("Connected to network");
}
// configure the uri to be called
char apiURL[] = "127.0.0.1";
uint16_t port = 8080;
if (client.connect(apiURL, port)){
Serial.println("connected to " + String(apiURL));
// it always prints this statement
}else{
Serial.println("not calling " + String(apiURL));
}
One more (and maybe silly) thing I would like to ask: would Bluetooth be a better option than Wifi when I want my Arduino to send data to server (e.g. making POST request)?

Arduino Uno + ESP8266 reading server's response

I'm sending a GET request from Arduino Uno using ESP8266. The request is sent, but I'm unable to print the received response.
I'm using code from https://elementztechblog.wordpress.com/2015/05/13/esp8266-based-temperature-data-logger-using-arduino/
I have changed the code for connecting to my server and I can see the GET request is received on my server's log.
I tried putting
while (ser.available())
{
Serial.write(ser.read());
}
after the Serial.println("AT+CIPCLOSE"); statement.
BUT I'm not getting anything on Serial monitor after "AT+CIPCLOSE"
EDIT:
Here's my entire code:
// connect 10 to TX of Serial USB
// connect 11 to RX of serial USB
SoftwareSerial ser(10, 11); // TX, RX
// this runs once
void setup()
{
// enable debug serial
Serial.begin(9600);
// enable software serial
ser.begin(9600);
// reset ESP8266
ser.println("AT+RST");
}
// the loop
void loop()
{
// TCP connection
String cmd = "AT+CIPSTART=\"TCP\",\"";
cmd += "192.168.0.25";
cmd += "\",3000";
ser.println(cmd);
if(ser.find("Error"))
{
Serial.println("AT+CIPSTART error");
return;
}
// prepare GET string
String getStr = "GET /api/myservice";
getStr += "\r\n\r\n";
// send data length
cmd = "AT+CIPSEND=";
cmd += String(getStr.length());
ser.println(cmd);
if(ser.find(">")){
ser.print(getStr);
}
else
{
ser.println("AT+CIPCLOSE");
// alert user
Serial.println("AT+CIPCLOSE");
// CODE I FOUND FOR READING THE REPLY FROM SERVER:
while (ser.available())
{
// char c = ser.read();
Serial.write(ser.read());
// if (c == '\r') Serial.print('\n');
}
}
delay(1000);
}
ESP Details:
ESP-01
AT version: 0.40.0.0
If you are only struggling to read a response then the answer is simple;
You are closing the TCP connection before you try to read:
ser.println("AT+CIPCLOSE");
// alert user
Serial.println("AT+CIPCLOSE");
// CODE I FOUND FOR READING THE REPLY FROM SERVER:
while (ser.available())
{
Move the reading while into the above block just beneath ser.print(getStr); but add a delay between the two as well.

Resources