Calling nest API from Arduino - arduino

I am trying to call an nest api to get room temperature using C code in Arduino.
When I call the api using postman, I get perfect response:
However when I write the code to get the temperature data, I get the following response:
request sent
The request is HTTP/1.1 400 Bad Request.
Here is my code, can anyone help me what's wrong with my request:
const char* ssid = "linksys";
const char* password = "XXXXX";
const char* host = "firebase-apiserver07-tah01-iad01.dapi.production.nest.com"; // "developer-api.nest.com"; // "api.github.com";
const int httpsPort = 9553; //443 9553;
String url = "";
.......
.......
.......
if (!client.connect(host, httpsPort)) {
Serial.println("connection failed");
return;
} else {
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Authorization: Bearer c.SbsgvTBcsJREMOVED_CODE_FOR_SECURITY_REASON\r\n" +
"Content-Type: application/json\r\n\r\n"
);
Serial.println("request sent");
}
Thanks,
Shab

If you're getting a 400, you should check that the URL is actually set to /. Your code doesn't have the value of the url variable shown.

I figured in my case there was a delay in receiving the response. I just had to wait to get the response. And for sure url has to be "/"
String url = "/"
Thanks,
Shab

Related

Can't get public IP address from ESP8266 using ipify

I'm using NodeMCU to use ESP8266 and I want to use ipify to get public IP address.
But I get -1 on httpCode. Why is that?
If I type api.ipify.org, it gets my public IP address properly.
void loop() {
Serial.println(WiFi.status());
if (WiFi.status() == WL_CONNECTED) { //Check WiFi connection status
Serial.println("az");
HTTPClient http; //Declare an object of class HTTPClient
http.begin("https://api.ipify.org/?format=json"); //Specify request destination
int httpCode = http.GET(); //Send the request
Serial.println(httpCode); //<<---- Here I get -1
if (httpCode > 0) { //Check the returning code
String payload = http.getString(); //Get the request response payload
Serial.println(payload); //Print the response payload
}
http.end(); //Close connection
}
delay(10000); //Send a request every 30 seconds
}
http.begin("https://api.ipify.org/?format=json");
You are using your HTTPClient to browse a HTTPS website (HTTP + SSL/TLS tunnel), but you're using the wrong .begin() call. The begin(String url call expects a http:// URL, not a https://. If you want to securely browse the website using HTTPS, you need to use the function begin(String url, String httpsFingerprint) (link). You can find the needed httpsFingerprint by following this guide. Using HTTPS will induce a whole lot of memory overhead and processing time, though. For the case of browsing a "what is my public IP" website, I would just advise to browse the http:// version instead, since the response is not confidential information.
So, you could just do
http.begin("http://api.ipify.org/?format=json");
You can try:
String getIp()
{
WiFiClient client;
if (client.connect("api.ipify.org", 80))
{
Serial.println("connected");
client.println("GET / HTTP/1.0");
client.println("Host: api.ipify.org");
client.println();
} else {
Serial.println("Connection to ipify.org failed");
return String();
}
delay(5000);
String line;
while(client.available())
{
line = client.readStringUntil('\n');
Serial.println(line);
}
return line;
}

How do I connect to HTTP server with content type after requesting a specific file from directory?

I wrote a function that checks for file type (using Content Type) for HTTP server. However, I have this as global variable, but I blocked out the HTTP and content-type lines.
char * request_str; //= "HTTP/1.0 200 OK\r\n"
//"Content-type: text/html; charset=UTF-8\r\n\r\n";
The function that checks for file types as such as html, png, txt, etc. It has filename, filetype, and request_str as arguments. I'm hoping the request_str would return after reading the filename/filetype, but I guess it doesn't work.
void get_filetype(char *filename, char *filetype, char *request_str)
{
if(strstr(filename, ".html"))
{
strcpy(filetype, "text/html");
request_str = "HTTP/1.0 200 OK\r\n"
"Content-type: text/html; charset=UTF-8\r\n\r\n";
return request_str;
}
else if(strstr(filename, ".gif"))
{
strcpy(filetype, "image/gif");
request_str = "HTTP/1.0 200 OK\r\n"
"Content-type: image/gif; charset=UTF-8\r\n\r\n";
return request_str;
}
else if(strstr(filename, ".png"))
{
strcpy(filetype, "image/png");
request_str = "HTTP/1.0 200 OK\r\n"
"Content-type: image/png; charset=UTF-8\r\n\r\n";
return request_str;
}
else if(strstr(filename, ".jpg"))
{
strcpy(filetype, "image/jpg");
request_str = "HTTP/1.0 200 OK\r\n"
"Content-type: image/jpg; charset=UTF-8\r\n\r\n";
return request_str;
}
else
{
strcpy(filetype, "text/plain");
request_str = "HTTP/1.0 200 OK\r\n"
"Content-type: text/plain; charset=UTF-8\r\n\r\n";
return request_str;
}
}
I have this function in the server request function when it attempts to connect to server. The problem I'm approaching is it wouldn't connect to the web server when I test it on my browser so I cannot see anything. Am I supposed to check the file type before attemtpting to connect to the server? Thank you guys in advance.
while(1){
file_offset += recv(client_fd,&client_buf[file_offset],4096,0);
if(strstr(client_buf,"\r\n\r\n"))
break;
}
requested_file = parseRequest(client_buf);
if(stat(filename, &for_filename) < 0)
{
clienterror(client_fd, filename, "404", "Not found", "Webserver couldn't find this file");
return;
}
get_filetype(filename, file_type, request_str);
send(client_fd,request_str,strlen(request_str),0);
// take requested_file, add a . to beginning, open that file
filename[0] = '.';
strncpy(&filename[1],requested_file,4095);
read_fd = open(filename,0,0);
Am I supposed to check the file type before attemtpting to connect to
the server?
First of all, unless you're doing it as an exercise, you should really use an HTTP client library instead of building request strings yourself.
Second, in HTTP, you can specify multiple accepted formats in a single request. Browsers use a list of default values which you can see here. For instance, when Firefox doesn't know in advance the type of data it's supposed to request, it uses the string text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8. If it knows that it's a video, then it uses a different string audio/webm, audio/ogg, audio/wav, audio/*;q=0.9, application/ogg;q=0.7, video/*;q=0.6; */*;q=0.5. There are additional request string for other types such as images, and scripts.

Arduino mega + esp 8266 sending get request

i have a php script which help to store data into google firebase.
i am using this url to access my php scipt and input the data:
arduino.byethost22.com/FirebaseTest.php?slot1_data=empty&slot2_data=occupied
i have tried it and it is able to store slot1_data as empty and slot2_data as occupied. However i need to use arduino to send this url. i am using this code currently
#include "SoftwareSerial.h"
#define DEBUG false // turn debug message on or off in serial
String server = "arduino.byethost22.com";
String uri = "/FirebaseTest.php?slot1_data=empty&slot2_data=occupied";
void setup() {
Serial3.begin(115200); //serial3 for esp8266
Serial.begin(115200);
sendData("AT+RST\r\n",2000,DEBUG); // reset module
sendData("AT+CWMODE=3\r\n",1000,DEBUG); // configure as access point
//sendData("AT+CWJAP=\"WifiName\",\"Password\"\r\n",3000,DEBUG);
//delay(20000);
sendData("AT+CIFSR\r\n",1000,DEBUG); // get ip address
sendData("AT+CIPMUX=0\r\n",1000,DEBUG); // configure for single connections
}
void loop() {
Serial3.println("AT+CIPSTART=\"TCP\",\"" + server + "\",80");//start a TCP connection.
if( Serial3.find("OK")) {
Serial.println("TCP connection ready");
}
delay(1000);
String getRequest = "GET " + uri + " HTTP/1.1\r\n" +
"Host: " + server + "\r\n\r\n";
String sendCmd = "AT+CIPSEND=";//determine the number of caracters to be sent.
Serial3.print(sendCmd);
Serial3.println(getRequest.length() );
delay(500);
if(Serial3.find(">")) {
Serial.println("Sending..");
}
Serial3.print(getRequest);
if( Serial3.find("SEND OK")) {
Serial.println("Packet sent");
}
while (Serial3.available()) {
String tmpResp = Serial3.readString();
Serial.println(tmpResp);
}
delay(20000);
}
String sendData(String command, const int timeout, boolean debug)
{
String response = "";
Serial3.print(command); // send the read character to the esp8266
long int time = millis();
while( (time+timeout) > millis())
{
while(Serial3.available())
{
// The esp has data so display its output to the serial window
char c = Serial3.read(); // read the next character.
response+=c;
}
}
//if(debug)
//{
Serial.print(response);
//}
return response;
}
it seems that it have problem sending the get request to the php script.
i am getting packet sent in the serial monitor but nothing changed in the firebase data
i am also getting
+IPD,1104:HTTP/1.1 200 OK
Server: nginx
Date: Sat, 15 Oct 2016 09:21:34 GMT
Content-Type: text/html
Content-Length: 875
Connection: keep-alive
Vary: Accept-Encoding
Expires: Thu, 01 Jan 1970 00:00:01 GMT
Cache-Control: no-cache
<html><body><script type="text/javascript" src="/aes.js" ></script><script>function toNumbers(d){var e=[];d.replace(/(..)/g,function(d){e.push(parseInt(d,16))});return e}function toHex(){for(var d=[],d=1==arguments.length&&arguments[0].constructor==Array?arguments[0]:arguments,e="",f=0;f<d.length;f++)e+=(16>d[f]?"0":"")+d[f].toString(16);return e.toLowerCase()}var a=toNumbers("f655ba9d09a112d4968c63579db590b4"),b=toNumbers("98344c2eee86c3994890592585b49f80"),c=toNumbers("b5ebc3b806c39a4a7fc1e4cecb45feab");document.cookie="__test="+toHex(slowAES.decrypt(c,2,a,b))+"; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/"; location.href="http://arduino.byethost22.com/FirebaseTest.php?slot1_data=0&slot2_data=1&i=1";</script><noscript>This site requires Javascript to work, please enable Javascript in your browser or use a browser with Javascript support</noscript></body></html>
It asked me to enable javascript in my browser, but i am using arduino, how do i do it?
When i key in the same uri in google chrome, the data can be updated
how do i solve this problem?
My code finally can work and send data online. i change to use 000webhost as my host server instead of byethost and the data manage to be updated.
i dont really know why but i guess that byethost dont support javascript.

Authentication with net/http in Go isn't working

I have a problem, I have a server that logs into another server and gets some data.
The login works in NodeJS like this:
var data = {
login_act: "username",
login_pwd: "password"
};
request.post({url: 'https://example.com', form: data}, callback())`
and in Java like this:
try {
URL mUrl = new URL("https://example.com");
HttpURLConnection connection = (HttpURLConnection) mUrl.openConnection();
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(false);
String urlParameters = "login_act=" + username + "&login_pwd=" + password;
byte[] postData = urlParameters.getBytes("UTF-8");
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
try( DataOutputStream wr = new DataOutputStream( connection.getOutputStream())) {
wr.write( postData );
}
}
I also made a C++ implementation of the same situation:
QNetworkAccessManager *vManager = new QNetworkAccessManager;
QNetworkRequest req;
req.setUrl(QUrl("https://example.com"));
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QByteArray postData;
postData.append("login_act=" + username + "&");
postData.append("login_pwd=" + password + "");
connect(vManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(authFinished(QNetworkReply*)));
QNetworkReply *reply = vManager->post(req, postData);
reply->ignoreSslErrors();
But when I try to do the same in Go it refuses to log in:
resp, error := http.PostForm("https://example.com", url.Values{"login_act": {"username"}, "login_pwd": {"password"}})
The site is build in such a way that, when login fails it just returns the standard site with the login form and if login suceeds it returns a 302 statuscode.
Maybe someone can help me I'm new to the go programming language and maybe I just miss something important.
Thanks in advance.

HTTP/1/1 400 Bad Request in a keep alive connection using sockets

Hi I am getting this error from the server. This is a TCP socket connection to an external IP using a tunnel. From our source IP we send a request to the destination server IP, port. This is the information provided to us on how to connect.
Your software opens a socket from your client platform to connect our server platform.
Our server will respond by starting the “keep alive” dialog.
Your software will send an X12 transmission packet with a single eligibility request.
Our server will check the recipient’s information and send a response to allow or reject the eligibility
This is my client code to connect, send, receive to and from messages. I am not sure about one thing. The way I am doing the HTTP Post.
They gave us a sample request. This is how it looks like
POST /OKMMISPOS HTTP/5.1
Content-Length: 521
ISA*00*__________*00*__________*ZZ*500000330______*ZZ*731476619______*090303*1414*U*004
--------------This is the X12 Content of the message-------------------------------------
private void button1_Click(object sender, EventArgs e)
{
try
{
//create a new client socket ...
string szIPSelected = "127.0.0.1";
int szPort = 57000;
if (textBox1.Text != "")
szIPSelected = textBox1.Text;
if (textBox2.Text != "")
szPort = Int32.Parse(textBox2.Text);
m_socClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
System.Net.IPAddress remoteIPAddress = System.Net.IPAddress.Parse(szIPSelected);
System.Net.IPEndPoint remoteEndPoint = new System.Net.IPEndPoint(remoteIPAddress, szPort);
m_socClient.Connect(remoteEndPoint);
if (m_socClient.Connected)
{
toolStripStatusLabel1.Text = "Connected to " + szIPSelected + ":" + szPort;
statusStrip1.Refresh();
SendRequest(m_socClient);
toolStripStatusLabel1.Text = "Sending Request to " + szIPSelected + ":" + szPort;
statusStrip1.Refresh();
}
Thread.Sleep(3000);
byte[] bytes = new byte[1024];
int bytesRec = m_socClient.Receive(bytes);
txtResponse271.Text =
Encoding.ASCII.GetString(bytes, 0, bytesRec);
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}
private void SendRequest(Socket m_socClient)
{
string resource = "/OKMMISPOS";
var header = String.Format("POST {0} HTTP/1.1\r\n", resource);
String body = Query270;
byte[] bodyBytes = Encoding.ASCII.GetBytes(body);
header += "Content-Length: " + (body.Length + 1)+ "\r\n" + "\r\n";
string request = String.Concat(header,body);
textBox3.Text = request;
textBox3.Refresh();
byte[] requestBytes= Encoding.ASCII.GetBytes(request);
m_socClient.Send(requestBytes);
}
My code sends a request similar to their but I am getting a HTTP 400 bad request. On wireshark, the request starts out using TCP protocol. This is the screenshot from wireshark. HTTP 400.
Also not sure if this is imp, the request starts out with TCP and the response comes back as HTTP
Request
Response

Resources