Stumped, trying to send link with NodeMCU

Hi,
I'm having a weird problem. I am trying to send a link that contains string variables with NodeMCU. I don't know if I'm putting the link together properly. I keep getting a 400 response error when I run it. Although if I print the made up link, it shows up the way it should be.
The problem piece of Code:

  String test = "http://api.callmebot.com/whatsapp.php?phone=+440000000000&text=Lakehouse+power+restored&apikey=000000";
  String test1 = "http://api.callmebot.com/whatsapp.php?phone=+440000000000&text=Lakehouse+power+restored&apikey=000000";

  mainNumbermessagesetup = "http://api.callmebot.com/whatsapp.php?phone=" + emNumber + "&text=Lakehouse+power+restored&apikey=" + emNumberAPI;
  delay(50);
  backupNumbermessagesetup = "http://api.callmebot.com/whatsapp.php?phone=" + ebNumber + "&text=Lakehouse+power+restored&apikey=" + ebNumberAPI;
  delay(50);
  mainNumbermessage = "http://api.callmebot.com/whatsapp.php?phone=" + emNumber + "&text=Lakehouse+power+failure&apikey=" + emNumberAPI;
  delay(50);
  backupNumbermessage = "http://api.callmebot.com/whatsapp.php?phone=" + ebNumber + "&text=Lakehouse+power+failure&apikey=" + ebNumberAPI;
  delay(50);
  Serial.println(mainNumbermessagesetup);
  Serial.println(backupNumbermessagesetup);
  Serial.println(mainNumbermessage);
  Serial.println(backupNumbermessage);

  delay(1000);

//Message to Dave
  if(WiFi.status()== WL_CONNECTED){
    WiFiClient client;
    HTTPClient http;
      
    // Your Domain name with URL path or IP address with path
    http.begin(client, test1);
    
    // Send HTTP GET request
    int httpResponseCode = http.GET();
      
    if (httpResponseCode>0) {
      Serial.print("HTTP Response code: ");
      Serial.println(httpResponseCode);
      String payload = http.getString();
      Serial.println(payload);
    }
    else {
      Serial.print("Error code: ");
      Serial.println(httpResponseCode);
    }
    // Free resources
    http.end();
    delay(100);
  }

Things get stranger with test and test1. The link text in the variable test was copied from Serial monitor of the output of building the link by adding the variables. The link for test1 was copied from a previous version of the program.

If i use test in the httpbegin line I get a 201 response, that says I'm missing api.
If I use test1 in the httpbegin line I get a 200 response and everything works.
To me both those links look identical. Am I missing something?

But in the end I want to be able to build the links with variables and text. Is this how its done?

Thanks.

Damien.

That is not a complete sketch... It is always better to post the entire thing.

As for the Strings, they look fine. A 201 response means a resource was created - The text message?

I hope you didn't publish your real apikey...

:face_with_hand_over_mouth: :shushing_face:

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
#include <WiFiClient.h>

const int InPin = D2; 
int sensorValue = 0;

//Variables
int i = 0;
int statusCode;
const char* ssid = "Default SSID";
const char* password = "Default passord";
String st;
String content;
String esid;
String epass = "";
String emNumber = "";
String emNumberAPI = "";
String ebNumber = "";
String ebNumberAPI = "";

//Function Decalration
bool testWifi(void);
void launchWeb(void);
void setupAP(void);

//Establishing Local server at port 80
ESP8266WebServer server(80);

//Your Domain name with URL path or IP address with path
String mainNumbermessagesetup = "";
String mainNumbermessage = "";

String backupNumbermessagesetup = "";
String backupNumbermessage = "";

void setup()
{
  
  Serial.begin(115200); //Initialising if(DEBUG)Serial Monitor
  Serial.println();
  Serial.println("Disconnecting current wifi connection");
  WiFi.disconnect();
  EEPROM.begin(512); //Initialasing EEPROM
  delay(10);
  pinMode(D3, INPUT);
  pinMode(InPin, INPUT);
  Serial.println();
  Serial.println();
  Serial.println("Startup");

  //---------------------------------------- Read eeprom for ssid and pass
  Serial.println("Reading EEPROM ssid");


  for (int i = 0; i < 20; ++i)
  {
    esid += char(EEPROM.read(i));
  }
  Serial.println();
  Serial.print("SSID: ");
  Serial.println(esid);
  Serial.println("Reading EEPROM pass");

  for (int i = 20; i < 40; ++i)
  {
    epass += char(EEPROM.read(i));
  }
  Serial.print("PASS: ");
  Serial.println(epass);

  for (int i = 40; i < 60; ++i)
  {
    emNumber += char(EEPROM.read(i));
  }
  Serial.print("Main Number: ");
  Serial.println(emNumber);

  for (int i = 60; i < 80; ++i)
  {
    emNumberAPI += char(EEPROM.read(i));
  }
  Serial.print("Main Number API: ");
  Serial.println(emNumberAPI);

  for (int i = 80; i < 100; ++i)
  {
    ebNumber += char(EEPROM.read(i));
  }
  Serial.print("Backup Number: ");
  Serial.println(ebNumber);

  for (int i = 100; i < 120; ++i)
  {
    ebNumberAPI += char(EEPROM.read(i));
  }
  Serial.print("Backup Number API: ");
  Serial.println(ebNumberAPI);


  WiFi.begin(esid.c_str(), epass.c_str());
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    if (digitalRead(D3) == LOW)
    {
      Serial.println("Turning the HotSpot On");
      launchWeb();
      setupAP();// Setup HotSpot

      while ((WiFi.status() != WL_CONNECTED))
      {
        Serial.print(".");
        delay(100);
        server.handleClient();
      }
    }
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());

  String test = "http://api.callmebot.com/whatsapp.php?phone=+440000000000&text=Lakehouse+power+restored&apikey=000000";
String test1 = "http://api.callmebot.com/whatsapp.php?phone=+440000000000&text=Lakehouse+power+restored&apikey=000000";

mainNumbermessagesetup = "http://api.callmebot.com/whatsapp.php?phone=" + emNumber + "&text=Lakehouse+power+restored&apikey=" + emNumberAPI;
  delay(50);
  backupNumbermessagesetup = "http://api.callmebot.com/whatsapp.php?phone=" + ebNumber + "&text=Lakehouse+power+restored&apikey=" + ebNumberAPI;
  delay(50);
  mainNumbermessage = "http://api.callmebot.com/whatsapp.php?phone=" + emNumber + "&text=Lakehouse+power+failure&apikey=" + emNumberAPI;
  delay(50);
  backupNumbermessage = "http://api.callmebot.com/whatsapp.php?phone=" + ebNumber + "&text=Lakehouse+power+failure&apikey=" + ebNumberAPI;
  delay(50);
  Serial.println(mainNumbermessagesetup);
  Serial.println(backupNumbermessagesetup);
  Serial.println(mainNumbermessage);
  Serial.println(backupNumbermessage);

  delay(1000);

//Message to Dave
  if(WiFi.status()== WL_CONNECTED){
    WiFiClient client;
    HTTPClient http;
      
    // Your Domain name with URL path or IP address with path
    http.begin(client, test1);
    
    // Send HTTP GET request
    int httpResponseCode = http.GET();
      
    if (httpResponseCode>0) {
      Serial.print("HTTP Response code: ");
      Serial.println(httpResponseCode);
      String payload = http.getString();
      Serial.println(payload);
    }
    else {
      Serial.print("Error code: ");
      Serial.println(httpResponseCode);
    }
    // Free resources
    http.end();
    delay(100);
  }
  //Message to Mary
  if(WiFi.status()== WL_CONNECTED){
    WiFiClient client;
    HTTPClient http;
      
    // Your Domain name with URL path or IP address with path
    http.begin(client, backupNumbermessagesetup);
      
    // Send HTTP GET request
    int httpResponseCode = http.GET();
      
    if (httpResponseCode>0) {
      Serial.print("HTTP Response code: ");
      Serial.println(httpResponseCode);
      String payload = http.getString();
      Serial.println(payload);
    }
    else {
      Serial.print("Error code: ");
      Serial.println(httpResponseCode);
    }
    // Free resources
    http.end();
    delay(5000);
  }
}

void loop() {
sensorValue = digitalRead(InPin);
Serial.println(sensorValue);
if(sensorValue == 0){
  //Message to Dave
  //Check WiFi connection status
  if ((WiFi.status() == WL_CONNECTED))
  {
    WiFiClient client;
    HTTPClient http;
      
    // Your Domain name with URL path or IP address with path
    http.begin(client, mainNumbermessage);
      
    // Send HTTP GET request
    int httpResponseCode = http.GET();
      
    if (httpResponseCode>0) {
      Serial.print("HTTP Response code: ");
      Serial.println(httpResponseCode);
      String payload = http.getString();
      Serial.println(payload);
    }
    else {
      Serial.print("Error code: ");
      Serial.println(httpResponseCode);
    }
    // Free resources
    http.end();
    delay(50);
  }
  else
  {
    Serial.println("No Wifi");
    delay(100);
  }

  //Message to Mary
  if(WiFi.status()== WL_CONNECTED){
    WiFiClient client;
    HTTPClient http;
      
    // Your Domain name with URL path or IP address with path
    http.begin(client, backupNumbermessage);
      
    // Send HTTP GET request
    int httpResponseCode = http.GET();
      
    if (httpResponseCode>0) {
      Serial.print("HTTP Response code: ");
      Serial.println(httpResponseCode);
      String payload = http.getString();
      Serial.println(payload);
    }
    else {
      Serial.print("Error code: ");
      Serial.println(httpResponseCode);
    }
    // Free resources
    http.end();
    delay(10000);
  }
 }

 if ((WiFi.status() == WL_CONNECTED))
  {
    Serial.print("Connected to ");
    Serial.print(esid);
    Serial.println(" Successfully");
    delay(100);
  }
  else
  {
    Serial.println("No Wifi");
    delay(100);
  }

  if (digitalRead(D3) == LOW)
  {
    Serial.println("Turning the HotSpot On");
    launchWeb();
    setupAP();// Setup HotSpot

    while ((WiFi.status() != WL_CONNECTED))
    {
      Serial.print(".");
      delay(100);
      server.handleClient();
    }
  }
}


//----------------------------------------------- Fuctions used for WiFi credentials saving and connecting to it which you do not need to change

void launchWeb()
{
  Serial.println("");
  if (WiFi.status() == WL_CONNECTED)
    Serial.println("WiFi connected");
  Serial.print("Local IP: ");
  Serial.println(WiFi.localIP());
  Serial.print("SoftAP IP: ");
  Serial.println(WiFi.softAPIP());
  createWebServer();
  // Start the server
  server.begin();
  Serial.println("Server started");
}

void setupAP(void)
{
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  int n = WiFi.scanNetworks();
  Serial.println("scan done");
  if (n == 0)
    Serial.println("no networks found");
  else
  {
    Serial.print(n);
    Serial.println(" networks found");
    for (int i = 0; i < n; ++i)
    {
      // Print SSID and RSSI for each network found
      Serial.print(i + 1);
      Serial.print(": ");
      Serial.print(WiFi.SSID(i));
      Serial.print(" (");
      Serial.print(WiFi.RSSI(i));
      Serial.print(")");
      //Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? " " : "*");
      delay(10);
    }
  }
  Serial.println("");
  st = "<ol>";
  for (int i = 0; i < n; ++i)
  {
    // Print SSID and RSSI for each network found
    st += "<li>";
    st += WiFi.SSID(i);
    st += " (";
    st += WiFi.RSSI(i);

    st += ")";
    //st += (WiFi.encryptionType(i) == ENC_TYPE_NONE) ? " " : "*";
    st += "</li>";
  }
  st += "</ol>";
  delay(100);
  WiFi.softAP("Powerfailuresetup", "");
  Serial.println("Initializing_softap_for_wifi credentials_modification");
  launchWeb();
  Serial.println("over");
}

void createWebServer()
{
  {
    server.on("/", []() {

      IPAddress ip = WiFi.softAPIP();
      String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
      content = "<!DOCTYPE HTML>\r\n<html>Welcome to setup page";
      content += "<form action=\"/scan\" method=\"POST\"><input type=\"submit\" value=\"scan\"></form>";
      content += ipStr;
      content += "<p>";
      content += st;
      content += "</p><form method='get' action='setting'><label>SSID: </label><input name='ssid' length=20><label>PASSWORD: </label><input name='pass' length=20><br><label>Main Number: </label><input name='mNumber' length=20><label>API: </label><input name='mNumberAPI' length=20><br><label>Backup Number: </label><input name='bNumber' length=20><label>API: </label><input name='bNumberAPI' length=20><input type='submit'></form>";
      content += "</html>";
      server.send(200, "text/html", content);
    });
    server.on("/scan", []() {
      //setupAP();
      IPAddress ip = WiFi.softAPIP();
      String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);

      content = "<!DOCTYPE HTML>\r\n<html>go back";
      server.send(200, "text/html", content);
    });

    server.on("/setting", []() {
      String qsid = server.arg("ssid");
      String qpass = server.arg("pass");
      String mNumber = server.arg("mNumber");
      String mNumberAPI = server.arg("mNumberAPI");
      String bNumber = server.arg("bNumber");
      String bNumberAPI = server.arg("bNumberAPI");
      if (qsid.length() > 0 && qpass.length() > 0) {
        Serial.println("clearing eeprom");
        for (int i = 0; i < 120; ++i) {
          EEPROM.write(i, 0);
        }
        Serial.println(qsid);
        Serial.println("");
        Serial.println(qpass);
        Serial.println("");
        Serial.println(mNumber);
        Serial.println("");
        Serial.println(mNumberAPI);
        Serial.println("");
        Serial.println(bNumber);
        Serial.println("");
        Serial.println(bNumberAPI);
        Serial.println("");

        Serial.println("writing eeprom ssid:");
        for (int i = 0; i < qsid.length(); ++i)
        {
          EEPROM.write(i, qsid[i]);
          Serial.print("Wrote: ");
          Serial.println(qsid[i]);
        }
        Serial.println("writing eeprom pass:");
        for (int i = 0; i < qpass.length(); ++i)
        {
          EEPROM.write(20 + i, qpass[i]);
          Serial.print("Wrote: ");
          Serial.println(qpass[i]);
        }
        Serial.println("writing eeprom Main Number:");
        for (int i = 0; i < mNumber.length(); ++i)
        {
          EEPROM.write(40 + i, mNumber[i]);
          Serial.print("Wrote: ");
          Serial.println(mNumber[i]);
        }
        Serial.println("writing eeprom Main Number API:");
        for (int i = 0; i < mNumberAPI.length(); ++i)
        {
          EEPROM.write(60 + i, mNumberAPI[i]);
          Serial.print("Wrote: ");
          Serial.println(mNumberAPI[i]);
        }
        Serial.println("writing eeprom Backup Number:");
        for (int i = 0; i < bNumber.length(); ++i)
        {
          EEPROM.write(80 + i, bNumber[i]);
          Serial.print("Wrote: ");
          Serial.println(bNumber[i]);
        }
        Serial.println("writing eeprom Backup Number API:");
        for (int i = 0; i < bNumberAPI.length(); ++i)
        {
          EEPROM.write(100 + i, bNumberAPI[i]);
          Serial.print("Wrote: ");
          Serial.println(bNumberAPI[i]);
        }
        EEPROM.commit();

        content = "{\"Success\":\"saved to eeprom... reset to boot into new wifi\"}";
        statusCode = 200;
        ESP.restart();
      } else {
        content = "{\"Error\":\"404 not found\"}";
        statusCode = 404;
        Serial.println("Sending 404");
      }
      server.sendHeader("Access-Control-Allow-Origin", "*");
      server.send(statusCode, "application/json", content);

    });
  }
}

That's the whole code

Are you sure http.begin() is successful? You are not checking the return value unlike the library examples.

yes it works if I use String test1 I get a 200 response with a message saying message will be received soon, and the message comes through on my phone. But if I use String test or any of the mainNumber and backupNumber strings it doesnt work.

String test gives me a 201 response and message saying missing api.

This is the response from the mainNumbermessagesetup string:

HTTP Response code: 400
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
</p>
<hr>
<address>Apache/2.4.29 (Ubuntu) Server at 127.0.0.1 Port 80</address>
</body></html>

I still don't get why test1 works and test doesn't

Those other numbers you are reading from EEPROM are a fixed 20 chars, not a nil '\0' terminated array of characters. I would do some debug prints to see what the length of mainNumbermessagesetup is. It would also be better to read these numbers in until you read a '\0'. You may find that these numbers have multiple nil chars at the end which mess things up.

Just a bit of speculation on my parts that that bit of code smells the fishiest.

This is the full serial output. I print out the built links before sending them.

http://api.callmebot.com/whatsapp.php?phone=+440000000000&text=Lakehouse+power+restored&apikey=000000
http://api.callmebot.com/whatsapp.php?phone=+440000000000&text=Lakehouse+power+restored&apikey=111111
HTTP Response code: 400
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
</p>
<hr>
<address>Apache/2.4.29 (Ubuntu) Server at 127.0.0.1 Port 80</address>
</body></html>

Thing is if I copy this link from serial monitor and paste it into web browser, it sends the message to my phone. Should this not mean that the link is correct? If there were more zeros on those strings would they not show up on serial monitor?

Thanks for helping

They would not show up on the serial monitor. That is why I suggested printing out the length. It is a function of the String class

Thanks I'll try tomorrow

You are correct. Each string is 20 long. From what I've read the IDE adds the null character automatically when saving string to eeprom(flash), so how do I stop reading when I reach the null character?

Thanks

Just stop reading when you read a 0. Apply this to ALL your code (or make a function)

for (int i = 0; i < 20; ++i)  {
  char c = EEPROM.read(i);  // or you can use EEPROM[i]
  if ( c )   esid += c;
  else break;
 }

That did it, thank you so much.
So is it the

if ( c )   esid += c;
  else break;

that sees the null character. Like if c isn't a normal letter or number?

Is it zero or a null character that its seeing? Will this effect a number in string ending with zero?

Thanks again :smiley:

a null character is ascii value 0 which terminates a string. A string with the char '0' is ascii value 48.

So a char is 2 bytes and the null character is just one which brakes the if statement, is that correct?
I don't see where it says stop reading if 0

Sorry

Translation: I have absolutely no idea what you mean. It's clearer to write:

if ( c != '\0' )   esid += c;
  else break;

That makes sense now, sorry for being stupid. Thanks

It's not stupid, there are different C styles. C was designed to allow a lot of (many people think too much) brevity. You are seeing one of them, any non-zero expression including a single variable in the conditional test, counts as a 'true' value. Hence, 'if (c)' is the same as ' if (c != 0)' if c is signed, or 'if (c > 0)' or 'if (c != 0)' c is unsigned.

The machines that C was designed on and for, often had extreme memory limitations, so both the syntax and the vocabulary were made very compact. It was not solely an aesthetic decision, they were trying to keep source code files small.

a char is 1 byte 0..127

And sorry for the brevity. @aarg set you straight.