/*
Edited by ChuggingAlong 02/13/2020
*/
#include <EEPROM.h>
#include <ArduinoJson.h>
#include <SPI.h>
#include <ArduinoHttpClient.h>
#include <WiFiNINA.h>
#include "arduino_secrets.h"
//===== please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password (use for WPA)
//===== EEProm addresses =========
// A token refresh immediately expires the previously issued access and refresh tokens and issues brand new tokens.
// EEProm is used to alway store the latest tokens
//addr 0-31 refresh_token
const int address_refresh_token = 0;
//addr 32 '\0' null termination char
const int address_null_termination = 32; // used to check if EEProm is initialized
String access_token = "";
String refresh_token = "";
String ecobeePin = "";
String code = "";
int LivingRoomTemp = 0;
int DesiredRoomTemp = 0;
int status = WL_IDLE_STATUS;
const size_t MAX_CONTENT_SIZE = 1600;
int statuscode = 0;
String response = "";
char server[] = "api.ecobee.com";
WiFiSSLClient wifiClient;
HttpClient client = HttpClient(wifiClient, server, 443);
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
// check for the WiFi module:
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("Communication with WiFi module failed!");
// don't continue
while (true);
}
String fv = WiFi.firmwareVersion();
if (fv < "1.0.0") {
Serial.println("Please upgrade the firmware");
}
// attempt to connect to Wifi network:
while (status != WL_CONNECTED) { // Connect to WPA/WPA2 network:
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass);
delay(10000); // wait 10 seconds for connection:
}
Serial.println("You're connected to the network");
//printCurrentNet(); Leave for Debug
//printWifiData();
Serial.println("Starting connection to server..."); // if you get a connection, report back via serial:
client.beginRequest();
//======= get latest refresh code from EEProm to use for refresh tokens ===================
refresh_token = readEEstring(address_refresh_token);
client.post("https://api.ecobee.com/token?grant_type=refresh_token&refresh_token=" + refresh_token + "&client_id=" + SECRET_Client_ID);
client.endRequest();
// read the status code and body of the response
int statusCode = client.responseStatusCode();
if (statusCode == 200)
{
String response = client.responseBody();
Serial.print("Refresh Status code: ");
Serial.println(statusCode);
Serial.print("Refresh Response: ");
Serial.println(response);
Extract_Json_Strings(response, access_token, "access_token", refresh_token, "refresh_token");
writeEEstring (address_refresh_token, refresh_token); // Save for next running of Setup/Refresh
Serial.print ("refresh_token: ");
Serial.println (refresh_token );
Serial.print ("access_token: ");
Serial.println (access_token );
} else {
Serial.println ("Error in obtaining access code, need to run create_new_refresh_keys ()");
create_new_refresh_keys (refresh_token, access_token);
}
//======= Send Request for Ecobee rooom temperature & Desired temperature ===================
String postData = "{\"selection\":{\"selectionType\":\"registered\",\"selectionMatch\":\"\",\"includeRuntime\":true}}";
client.beginRequest();
client.get("https://api.ecobee.com/1/thermostat?format=json&body=" + postData); //moved postData here & changed to a GET
client.sendHeader("Authorization", ("Bearer " + access_token));
Serial.println("Bearer " + access_token);
client.sendHeader("Content-Type", "text/json");
client.endRequest();
// ======== read the status code and body of the response ===========
statusCode = client.responseStatusCode();
response = client.responseBody();
Serial.print("StatusCode: ");
Serial.println(statusCode);
Serial.print("Response: ");
Serial.println(response);
// ======= Extract temperature and desired temperature ========= Using String functions, easier than ArduinoJSON calls.
int StartOf = response.indexOf ("actualTemperature");
String actual_Temperature_Str (response.substring((StartOf + 20), StartOf + 23));
LivingRoomTemp = actual_Temperature_Str.toInt();
float x = LivingRoomTemp;
x = x / 10;
Serial.print("LivingRoomTemp: ");
Serial.println (x, 1);
StartOf = response.indexOf ("desiredHeat");
String Disired_Heat_Str = (response.substring((StartOf + 14), StartOf + 17));
DesiredRoomTemp = Disired_Heat_Str.toInt();
x = DesiredRoomTemp;
x = x / 10;
Serial.print("Disired Temp: ");
Serial.println (x, 1);
}
void loop() {
while (true);
}
void printWifiData() {
// print your board's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
Serial.println(ip);
// print your MAC address:
byte mac[6];
WiFi.macAddress(mac);
Serial.print("MAC address: ");
printMacAddress(mac);
}
void printCurrentNet() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print the MAC address of the router you're attached to:
byte bssid[6];
WiFi.BSSID(bssid);
Serial.print("BSSID: ");
printMacAddress(bssid);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.println(rssi);
// print the encryption type:
byte encryption = WiFi.encryptionType();
Serial.print("Encryption Type:");
Serial.println(encryption, HEX);
Serial.println();
}
void printMacAddress(byte mac[]) {
for (int i = 5; i >= 0; i--) {
if (mac[i] < 16) {
Serial.print("0");
}
Serial.print(mac[i], HEX);
if (i > 0) {
Serial.print(":");
}
}
Serial.println();
}
void writeEEstring(char add, String data) {
int _size = data.length();
int i;
for (i = 0; i < _size; i++)
{
EEPROM.write(add + i, data[i]);
}
EEPROM.write(add + _size, '\0'); //Add termination null character for String Data
// EEPROM.commit();
}
String readEEstring(char add) {
int i;
char data[100]; //Max 100 Bytes
int len = 0;
unsigned char k;
k = EEPROM.read(add);
while (k != '\0' && len < 500) //Read until null character
{
k = EEPROM.read(add + len);
data[len] = k;
len++;
}
data[len] = '\0';
return String(data);
}
void Extract_Json_Strings (String data, String & Var_1, String Var_1_json, String & Var_2, String Var_2_json) { // use of ampersand passes pointers
StaticJsonDocument <500> jsonDoc;
auto error = deserializeJson(jsonDoc, data);
if (error) {
Serial.print(F("deserializeJson() failed with code "));
Serial.println(error.c_str());
}
else {
String tmp1 = jsonDoc[Var_1_json];
Var_1 = tmp1 ; // this is the only way I could get this access_token updated
String tmp2 = jsonDoc[Var_2_json];
Var_2 = tmp2 ; // this is the only way I could get this access_token updated
/*
Serial.print (Var_1_json);
Serial.print (": ");
Serial.println (Var_1);
Serial.print (Var_2_json);
Serial.print (": ");
Serial.println (Var_2);
*/
}
}
void create_new_refresh_keys (String & refresh_token_loc, String & access_token_loc) {
client.beginRequest();
//======= get ecobeePin ===================
// converted from JavaScript: https://www.ecobee.com/home/developer/api/examples/ex1.shtml
client.get("https://api.ecobee.com/authorize?response_type=ecobeePin&client_id=dRc7CqSwIxKI7pNp3ZMDqJGPY7aT9akm&scope=smartWrite");
client.endRequest();
// read the status code and body of the response
int statusCode = client.responseStatusCode();
String response = client.responseBody();
Serial.print("ecobeePin Status code: ");
Serial.println(statusCode);
Serial.print("Refresh Response: ");
Serial.println(response);
Extract_Json_Strings(response, ecobeePin, "ecobeePin", code, "code");
writeEEstring (address_refresh_token, refresh_token); // Save for next running of Setup/Refresh
Serial.print ("Aurthorization code: ");
Serial.println (code );
Serial.print ("ecobeePin: ");
Serial.println (ecobeePin );
Serial.println ("go to ecobee.com MY APPS");
Serial.println ("click add appliaction & paste ecobeePin into autorization code");
Serial.println ("click add app in lower right corner");
//======= get ecobee Aurthorization code, final step to get Access and Refresh codes ===================
// converted from JavaScript: https://www.ecobee.com/home/developer/api/examples/ex1.shtml
refresh_token = "null";
delay (20000);
int i = 0;
while (refresh_token == "null" || i == 6) {
client.post("https://api.ecobee.com/token?grant_type=ecobeePin&code=" + code + "&client_id=" + SECRET_Client_ID);
client.endRequest();
// read the status code and body of the response
statusCode = client.responseStatusCode();
response = client.responseBody();
Serial.print("Aurthorization Status code: ");
Serial.println(statusCode);
Serial.print("Refresh Response: ");
Serial.println(response);
Extract_Json_Strings(response, access_token_loc, "access_token", refresh_token_loc, "refresh_token");
writeEEstring (address_refresh_token, refresh_token_loc); // Save for next running of Setup/Refresh
Serial.print ("refresh_token: ");
Serial.println (refresh_token_loc );
Serial.print ("access_token: ");
Serial.println (access_token_loc );
delay (10000); //10 Second Delay
if (i == 6) {
Serial.println("Time out error > 1 minute");
Serial.println("press reset to retry");
while (true);
}
}
}
Comments
Please log in or sign up to comment.