Calling nest api with esp8266 using arduinoEDK

2019-03-05 11:32发布

问题:

I'm trying to connect to the nest_API (thermostat) using ESP8266 and the Arduino EDK. But so far with no result.

I've seen somebody asking the same question here before. But the answer to his problem didn't help me.

So here's my code:

Code

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>

const char* ssid = "xxxxx";
const char* password = "xxxxx";

const char* host = "developer-api.nest.com";
const int httpsPort = 443;
const char* BearerKey = "xxxxxxxuB0QSbgw2nsT85dJEHRpwvR7rSyrLHm2E54QpC9vnSzB5PV8OtGDPm0mAh96wgM0MwApmS";

//declaring GPIO's
int gpio13Led = 13;
int gpio12Relay = 12;

// Use web browser to view and copy
// SHA1 fingerprint of the certificate
const char* fingerprint = "87:CB:F2:E6:44:C0:AA:F2:4C:28:B2:97:85:70:18:92:45:1B:A4:57";

void setup() {
// preparing GPIOs
  pinMode(gpio13Led, OUTPUT);
  digitalWrite(gpio13Led, HIGH);

  pinMode(gpio12Relay, OUTPUT);
  digitalWrite(gpio12Relay, HIGH);

  Serial.begin(115200);
  Serial.println();
  Serial.print("connecting to ");
  Serial.println(ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  // Use WiFiClientSecure class to create TLS connection
  WiFiClientSecure client;
  Serial.print("connecting to ");
  Serial.println(host);
  if (!client.connect(host, httpsPort)) {
    Serial.println("connection failed");
    return;
  }

  if (client.verify(fingerprint, host)) {
    Serial.println("certificate matches");
    digitalWrite(gpio13Led, LOW);
  } else {
    Serial.println("certificate doesn't match");
  }

  String url = "/";
  Serial.print("requesting URL: ");
  Serial.println(url);

  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Content-Type: application/json\r\n" + 
               "Authorization: Bearer " + BearerKey + "\r\n\r\n"
               );

  Serial.println("request sent");
  while (client.connected()) {
    String line = client.readStringUntil('\n');
    Serial.println(line);
    if (line == "\r") {
      Serial.println("headers received");
      break;
    }
  }

 while (client.available()) {
    String line = client.readStringUntil('\n');
    Serial.println("reply was:");
    Serial.println("==========");
    Serial.println(line);
    Serial.println("==========");
    Serial.println("closing connection");
 }  
}

void loop() {
}   

I never get any result from the server. But when I'm using postman, it works. So I wonder. Do I need to use the "host: " + host + ... line?

And is there a way to catch some errors with the WiFiClientSecure.h library. I also once changed the url for host in the get string. Then I received one error from the server. I was already happy there was a response after all.

Serial output

connecting to xxxxx
........
WiFi connected
IP address: 
xxxxx
connecting to developer-api.nest.com
certificate matches
requesting URL: /
request sent
HTTP/1.1 307 Temporary Redirect

Content-Type: application/json; charset=UTF-8

Access-Control-Allow-Origin: *

Cache-Control: private, no-cache, no-store, max-age=0

Pragma: no-cache

Location: https://firebase-apiserver10-tah01-iad01.dapi.production.nest.com:9553/

Connection: close

Authorization: Bearer xxxxx

content-length: 0



headers received
reply was:
==========

==========
closing connection

Now I'm completely stuck. It would be nice if somebody could help me further out. thx

回答1:

Wow. Holy smoke! I've got a response! You're tip made it work @gre_gor.

I've changed the host name and the port because my reply said something like this.

Here's my final code:

CODE:

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>

const char* ssid = "xxxxx";
const char* password = "xxxxx";

const char* host = "firebase-apiserver10-tah01-iad01.dapi.production.nest.com";
const int httpsPort = 9553; //443;
const char* BearerKey = "xxxxx";

//declaring GPIO's
int gpio13Led = 13;
int gpio12Relay = 12;

// Use web browser to view and copy
// SHA1 fingerprint of the certificate
const char* fingerprint = "87:CB:F2:E6:44:C0:AA:F2:4C:28:B2:97:85:70:18:92:45:1B:A4:57";

void setup() {
// preparing GPIOs
  pinMode(gpio13Led, OUTPUT);
  digitalWrite(gpio13Led, HIGH);

  pinMode(gpio12Relay, OUTPUT);
  digitalWrite(gpio12Relay, HIGH);

  Serial.begin(115200);
  Serial.println();
  Serial.print("connecting to ");
  Serial.println(ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  // Use WiFiClientSecure class to create TLS connection
  WiFiClientSecure client;
  Serial.print("connecting to ");
  Serial.println(host);
  if (!client.connect(host, httpsPort)) {
    Serial.println("connection failed");
    return;
  }

  if (client.verify(fingerprint, host)) {
    Serial.println("certificate matches");
    digitalWrite(gpio13Led, LOW);
  } else {
    Serial.println("certificate doesn't match");
  }

  String url = "/";
  Serial.print("requesting URL: ");
  Serial.println(url);


  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Content-Type: application/json\r\n" + 
               "Authorization: Bearer " + BearerKey + "\r\n\r\n"
               );

  Serial.println("request sent");
  while (client.connected()) {
    String line = client.readStringUntil('\n');
    Serial.println(line);
    if (line == "\r") {
      Serial.println("headers received");
      break;
    }
  }

 while (client.available()) {
    String line = client.readStringUntil('\n');
    Serial.println("reply was:");
    Serial.println("==========");
    Serial.println(line);
    Serial.println("==========");
    Serial.println("closing connection");
 }  
}

void loop() {
}

Serial monitor:

connecting to xxxxx
...........
WiFi connected
IP address: 
xxxxx
connecting to firebase-apiserver10-tah01-iad01.dapi.production.nest.com
certificate doesn't match
requesting URL: /
request sent
HTTP/1.1 200 OK

Content-Type: application/json; charset=UTF-8

Access-Control-Allow-Origin: *

Cache-Control: private, no-cache, no-store, max-age=0

Pragma: no-cache

Connection: close

content-length: 8060



headers received
reply was:
==========
{"devices":{"thermostats":{"exxx":{"humidity":40,"locale":"nl-NL","temperature_scale":"C","is_using_emergency_heat":false,"has_fan":false,"software_version":"5.6.6-4","has_leaf":true,"where_id":"YygkopgUUc_cIFnCNG7GRDIIQnENO0ScVx9Pa78qfG7XyH-9WDdVgA","device_id":"e97ayjdpIOkPa4vZFxHggZMXiHKfhsyU","name":"Downstairs","can_heat":true,"can_cool":false,"target_temperature_c":15.0,"target_temperature_f":59,"target_temperature_high_c":24.0,"target_temperature_high_f":75,"target_temperature_low_c":20.0,"target_temperature_low_f":68,"ambient_temperature_c":15.5,"ambient_temperature_f":61,"away_temperature_high_c":24.0,"away_temperature_high_f":76,"away_temperature_low_c":8.5,"away_temperature_low_f":48,"eco_temperature_high_c":24.0,"eco_temperature_high_f":76,"eco_temperature_low_c":8.5,"eco_temperature_low_f":48,"is_locked":false,"locked_temp_min_c":20.0,"locked_temp_min_f":68,"locked_temp_max_c":22.0,"locked_temp_max_f":72,"sunlight_correction_active":false,"sunlight_correction_enabled":true,"structure_id":"vEJb634MNif-xxx{"access_token":"xxxx","client_version":2,"user_id":"xxxx"}}
==========
closing connection

The weird thing is that my fingerprint doesn't match but that it still proceeds to give me information.

Next step is to read this response and use the data I want. :-)