API HTTP request

I have an Arduino Nano with a webpage with relays and inputs

I want to sent a http request to the Fibaro HC2 for the status of the relays and inputs from my arduino nano

When i enter this command in a normal webbrowser. Then it will switch the global variable in my HC2 Fibaro from Auto to ON:
http://test:test@192.168.1.201/api/callAction?deviceID=201&name=pressButton&arg1=3
It will display a blank page with "{}" in the browser page.

When I add a href link to the webpage from the arduino nano, the it will accomplish the same result:
client.println(F("

<a href=http://test:test@192.168.1.201/api/callAction?deviceID=201&name=pressButton&arg1=3 >Relay 2 ON

"));

Now i want to make a http request to do the same, after the relay has switched from Auto to ON
but it doesn't work, what i am doing wrong ??

above void setup i posted:
char HC2[] = "http://192.168.1.201";

below void loop i posted:

void Relay2_ON(EthernetClient cl)
{
// attempt to connect
Serial.println(F("Connecting to HC2..."));

if (cl.connect(HC2, 80)) {
Serial.println(F("Making HTTP Request to HC2..."));
// Make a HTTP GET Request to HC2:
cl.print(F("GET http://192.168.1.201/api/callAction?deviceID=201&name=pressButton&arg1=3"));
cl.println(F(" HTTP/1.1"));
cl.println(F("Host: 192.168.1.201"));
cl.println(F("Authorization: Basic test:test"));
cl.println(F("Content-Type: text/html"));
cl.print(F("Connection: close"));
cl.println();

Serial.println(F("HTTP Request Send to HC2"));
}
else {
Serial.println(F("Connection Failed."));
}
}

char HC2[] =           "http://10.0.1.150";

What is HC2 supposed to represent? That is not an IP address. It is not a server name.

cl.print(F("GET http://192.168.1.201:80/api/callAction?deviceID=201&name=pressButton&arg1=3"));

The GET request knows that it is using the http protocol. It is talking to the server that it is connected to. So, the http://192.168.1.201 part of the string is wrong.

The URL that works for you contains data before the IP address. Presumably, that is user id and password. None of your attempts supply that same information, so I doubt that even fixing the issues above will help.

sorry HC2 is an ipaddress from an home controller from fibaro

HC2 = 192.168.1.201 (not 10.0.1.150)

All ip = 192.168.1.201

test:test = userid: password

need to be able to login by the http request to change global variable in HC2

i edited my first post, for the correct ip addresses. that was a mistake in the text not in the arduino sketch!

Based on the http protocol specification, http requests are composed by an header and a body. The header must terminate by two new lines (/n/r/n/r) and the body length must be declared by the header.

Here you are sending only a header and no body (that's correct) but your header isn't terminated porperly. So basically, your endpoint is waiting for the full header, until it reaches a time out.

The problem lies here:

      cl.println(F("Content-Type: text/html"));
      cl.print(F("Connection: close"));
      cl.println();

On the second line, you send the last header statement, but no newline. Then on the third line you send a newline alone.

Just make sure you temrinate every statement by a newline, then add an empty line to terminate request.

So, given it's the only problem, that code will work:

      cl.println(F("Content-Type: text/html"));
      cl.println(F("Connection: close"));
      cl.println();

Good luck for your project ! :wink:

Ok thanks, Just trying to catch what you are trying to say:

  1. cl.println(); = is used for a newline only ?
  2. What is then the empty line, maybe this one: cl.println(""); ?

void Relay2_ON(EthernetClient cl)
{
// attempt to connect
Serial.println(F("Connecting to HC2..."));

if (cl.connect(HC2, 80)) {
Serial.println(F("Making HTTP Request to HC2..."));
// Make a HTTP GET Request to HC2:
cl.print(F("GET http://192.168.1.201/api/callAction?deviceID=201&name=pressButton&arg1=3"));
cl.println(F(" HTTP/1.1"));
cl.println(F("Host: 192.168.1.201"));
cl.println(F("Authorization: Basic test:test"));
cl.println(F("Content-Type: text/html"));
cl.println(F("Connection: close"));
cl.println();

Serial.println(F("HTTP Request Send to HC2"));
//cl.stop();
//cl.flush();
//Serial.println(F("Connection Closed"));

}
else {
Serial.println(F("Connection Failed."));
}
}

  1. code above, is this correct?
  2. As you said: add a new line between every statement as below, like:

cl.print(F("GET http://192.168.1.201/api/callAction?deviceID=201&name=pressButton&arg1=3"));
cl.println();
cl.println(F(" HTTP/1.1"));
cl.println();
cl.println(F("Host: 192.168.1.201"));
cl.println();
cl.println(F("Authorization: Basic test:test"));
cl.println();
cl.println(F("Content-Type: text/html"));
cl.println();
cl.println(F("Connection: close"));
cl.printlnl);

What about the cl.print(F("GET http://192.168.1.201/api/callAction?deviceID=201&name=pressButton&arg1=3"));
5. should this be like: cl.print and not with a cl.println, correct?

  1. You said: "and the body length must be declared by the header." Do i have to add this too ?

  2. Can i add the below code too:
    Serial.println(F("HTTP Request Send to HC2"));
    //cl.stop(); or use //cl.flush();

  3. Or isn't' that necessary?

I numbered the questions, so it's easier to answer them.
I am pretty new about this. Learning on the job. thanks for your patient.

  1. cl.println(); = is used for a newline only ?
  2. What is then the empty line, maybe this one: cl.println(""); ?

Both statements send exactly the same thing - a carriage return and a line feed.

  1. code above, is this correct?

If it worked, yes. If it didn't, no. But, you already knew that.

  1. As you said: add a new line between every statement as below, like:

NO! Pay attention to the difference between print() and println(). You should send every COMPLETE statement with println(). You should send partial statements with print() for all but the last part of the statement, which you send with println().

What about the cl.print(F("GET http://192.168.1.201/api/callAction?deviceID=201&name=pressButton&arg1=3"));
5. should this be like: cl.print and not with a cl.println, correct?

Yes, because the statement is not a complete statement. The part that completes the statement is sent with println().

  1. You said: "and the body length must be declared by the header." Do i have to add this too ?

No. The body length matters only for a POST statement or a multi-part (MIME) transmission (which usually involves POST).

  1. Can i add the below code too:
    Serial.println(F("HTTP Request Send to HC2"));

You can. It will have no impact on what is sent to the client.

//cl.stop(); or use //cl.flush();

Or

// My dogs name is Jake.

Commented out code is not code.

  1. Or isn't' that necessary?

Commented out code is not necessary.

I numbered the questions, so it's easier to answer them.

Actually, the numbering did not make the questions easier. 8)

//cl.stop(); or use //cl.flush();
i understand. i meant...
do i have to add this
in the http request
as:

cl.stop // using this at the end or
cl.flush // at the end!

void Relay2_ON(EthernetClient cl)
{
// attempt to connect
Serial.println(F("Connecting to HC2..."));

if (cl.connect(HC2, 80)) {
Serial.println(F("Making HTTP Request to HC2..."));
// Make a HTTP GET Request to HC2:
cl.print(F("GET http://192.168.1.201/api/callAction?deviceID=201&name=pressButton&arg1=3"));
cl.println(F(" HTTP/1.1"));
cl.println(F("Host: 192.168.1.201"));
cl.println(F("Authorization: Basic test:test"));
cl.println(F("Content-Type: text/html"));
cl.println(F("Connection: close"));
cl.println();

Serial.println(F("HTTP Request Send to HC2"));

//Serial.println(F("Connection Closed"));

}
else {
Serial.println(F("Connection Failed."));
}
}

Ok understand. but still not working.

in a normal browser this works:
http://test:test@192.168.1.201/api/callAction?deviceID=201&name=pressButton&arg1=3

It will display a blank page with "{}" in the browser page.

What I am doing wrong, how can i debug this, to make it working. Is there another way?

do i have to add this
in the http request

They are not part of the GET request. They control what happens after the server responds.

Ok understand. but still not working.

Because your GET request is STILL wrong.

in a normal browser this works:

Do you have a clue what the test:test@ part of that statement is for? Where, in your code, are you doing the equivalent? Nowhere is the WRONG answer.

ok, about the cl.stop and cl.flush is clear :slight_smile:

http://test:test@192.168.1.201/api/callAction?deviceID=201&name=pressButton&arg1=3
in a normal browser the test:test
userid = test
password = test
this is to login to my home automation. otherwise i get a popup down where i have type my userid, password. !!

i guess this is part of it, what you find in the http request. is this the correct way of doing this?
cl.println(F("Authorization: Basic test:test"));

char HC2[] = "192.168.1.201"; is this correct, or is there a better way?

i got it working, yeah :slight_smile:

void Relay2_ON(EthernetClient cl)
{
// attempt to connect
Serial.println(F("Connecting to HC2..."));

if (cl.connect(HC2, 80)) {
Serial.println(F("Making HTTP Request to HC2..."));
// Make a HTTP GET Request to HC2:
cl.print(F("GET /api/callAction?deviceID=201&name=pressButton&arg1=3"));
cl.println(F(" HTTP/1.1"));
cl.println(F("Host: 192.168.1.201"));
cl.println(F("Authorization: Basic dGVzdDp0ZXN0==")); // Authorization: Basic test:test
cl.println(F("Content-Type: text/html"));
cl.println(F("Connection: close"));
cl.println();

cl.flush(); //
}
else {
Serial.println(F("Connection Failed."));
}
}

Authorization: Basic test:test needed to be Base 64 format and i had to add "==" after the Base 64 decode
cl.println(F("Authorization: Basic dGVzdDp0ZXN0=="));

In the GET line... had to be /api/call.... and not http://192.168.1.201/api/call...

I am very happy :slight_smile:

I am very happy :slight_smile:

So am I.