Here is a little program to demonstrate fetching data from Cayenne using REST-API on a ESP 8266 – similar to the Insomnia, Node-Red, Thunkable above.
This gets a current value, and a history series.
It might be used to find the state of a machine after a 8266 reboots, or is replaced, and it does not have the state of the system in EEPROM, or to get current values from other devices at cayenne or non-cayenne REST databases.
This example fetches the value of a slider, and the changes to that slider over the last 24 hours – it is part of my internet quickness monitor:
- Cayenne
Note 1: I see I am using ArduinoJSON version 5, rather then the current version 6.
Note 2: Obviously there is a tiny amount of memory in an 8266, so you cannot fetch 1000’s of samples of history without slowly consuming and discarding them. I use this to find “events” that only trigger a couple times a day, rather then every 15 seconds, so the json buffers and memory used for Strings does not kill the 8266.
/*
* cayenne_rest_demo
*
* James Zahary Nov 15, 2019
*
* This shows how to access current values and history from the mydevices.com database using REST API on a esp8266
*
*/
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <CayenneMQTTESP8266.h>
#include <ArduinoJson.h>
/*
Using library ESP8266WiFi at version 1.0 in folder: C:\Users\James\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.6.0\libraries\ESP8266WiFi
Using library ESP8266HTTPClient at version 1.2 in folder: C:\Users\James\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.6.0\libraries\ESP8266HTTPClient
Using library CayenneMQTT at version 1.3.0 in folder: C:\Users\James\Documents\Arduino\libraries\CayenneMQTT
Using library ArduinoJson at version 5.13.5 in folder: C:\Users\James\Documents\Arduino\libraries\ArduinoJson
*/
// your wifi name and password
const char ssid[] = "your_wifi";
const char wifipassword[] = "wifi_pass";
// cayenne username and password for MQTT
const char cayusername[] = "97XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXce";
const char caypassword[] = "257XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX94";
// cayenne device name and sensor name
const char cayclientID[] = "ea767930-5b0f-11e8-9907-5defa4aa8de2";
const char caycycles[] = "a59b1650-6810-11e8-a25e-d5e347246797";
// cayenne server names
const char cayaddr[] = "mqtt.mydevices.com";
const char cayserver[] = "platform.mydevices.com";
const char cayauthserver[] = "accounts.mydevices.com";
// cayenne username and password to access REST API
const char client_id[] = "1XXXXXX5";
const char client_secret[] = "d1XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX10";
const char username[] = "mrpeanut@gmail.com";
const char password[] = "peanutpassword";
// the access token JWT for actual access
char access_token[1200] = "";
char refresh_token[700] = "";
// global variables to return the data
int channel = 0;
double v = 0;
String ts = "";
String unit = "";
String device_type = "";
// functions below
void do_access_token(); // get access token using REST API credentials above
// get currect value of device and sensor, returned in global variables v, ts, unit, device_type
int rest_query_cayenne(const char caydev[], const char caysen[]);
// get a day of history of the device and sensor -- just print it out
int rest_query_cayenne_day(const char caydev[], const char caysen[]);
void setup() {
Serial.begin(115200);
Serial.println("");
Serial.println("");
Serial.println("\n>>>>> cayenne_rest_demo Nov 13, 2019 -jz");
Serial.println("\n>>>>> Starting Cayenne ...");
Cayenne.begin( cayusername, caypassword, cayclientID, ssid, wifipassword);
Serial.println("\n>>>>> Get access token for REST API access ...");
do_access_token();
Serial.println("\n>>>>> Query cayenne for state of slider ");
if ( rest_query_cayenne( cayclientID, caycycles) == 1) { // return in global variables v, ts, device_type, unit
Serial.println("");
Serial.println(" Device: " + String(cayclientID));
Serial.println(" Sensor: " + String(caycycles));
Serial.println("");
Serial.println("Results from cayenne ");
Serial.println(" v = " + String(v));
Serial.println(" ts = " + String(ts));
Serial.println(" device = " + String(device_type));
Serial.println(" unit = " + String(unit));
Serial.println("");
} else {
Serial.println("Couldn't access REST API");
}
Serial.println("\n>>>>> Getting last 24 hours history of cycle slider changes ");
rest_query_cayenne_day( cayclientID, caycycles );
Serial.println("\n>>>>> Only this, and nothing more. ");
}
void loop() {
Cayenne.loop();
}
void do_access_token() {
WiFiClientSecure cayclient;
HTTPClient cayhttp;
cayclient.setInsecure();
if (cayclient.connect(cayauthserver, 443)) {
if (cayhttp.begin(cayclient, "https://accounts.mydevices.com/auth/realms/cayenne/protocol/openid-connect/token")) {
cayhttp.addHeader("Content-Type", "application/x-www-form-urlencoded");
cayhttp.addHeader("cache-control", "no-cache");
String body = "grant_type=password&client_id=" + String(client_id) + "&client_secret=" + String(client_secret) + "&username=" + String(username) + "&password=" + String(password) ;
int httpCode = cayhttp.POST(body);
if (httpCode > 0) {
// HTTP header has been send and Server response header has been handled
//Serial.printf("[HTTPS] POST... code: %d\n", httpCode);
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
String payload = cayhttp.getString();
//Serial.println(payload);
DynamicJsonBuffer jsonBuffer(2000);
JsonObject& root = jsonBuffer.parseObject(payload);
if (!root.success()) {
Serial.println("parseObject failed");
return ;
} else {
String at = root["access_token"];
String rt = root["refresh_token"];
Serial.println("access token =" + at);
//Serial.println("");
//Serial.println("refresh token =" + rt);
at.toCharArray(access_token, 1200);
rt.toCharArray(refresh_token, 700);
}
} else {
Serial.printf("[HTTPS] POST... failed, error: %s\n", cayhttp.errorToString(httpCode).c_str());
}
}
cayhttp.end();
} else {
Serial.printf("[HTTPS] Unable to connect\n");
}
} else {
Serial.println("Cay Auth Server failed to connect");
}
cayclient.stop();
}
int rest_query_cayenne(const char caydev[], const char caysen[]) {
// results v, ts, device, unit
WiFiClientSecure cayclient;
HTTPClient cayhttp;
cayclient.setInsecure();
int ret = 0;
if (!cayclient.connect(cayserver, 443)) {
Serial.println("Cayserver failed to connect");
} else {
String get = "https://platform.mydevices.com/v1.1/telemetry/" + String(caydev) + "/sensors/" + String(caysen) + "/summaries?endDateLatest=true&type=latest";
//Serial.println(get);
if (cayhttp.begin(cayclient, get)) {
cayhttp.addHeader("Authorization" , "Bearer " + String(access_token));
int httpCode = cayhttp.GET();
if (httpCode > 0) {
//Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
String payload = cayhttp.getString();
//Serial.println(payload);
int payload_length = payload.length();
Serial.print("Payload length is "); Serial.println(payload_length);
// [{"v":"1526700604","ts":"2018-05-19T03:30:05.283Z","unit":"seconds","device_type":"analog"}]
DynamicJsonBuffer arrayBuffer(100);
DynamicJsonBuffer jsonBuffer(100);
JsonArray& array = arrayBuffer.parseArray(payload, 2);
int size = array.size();
Serial.print("Array Size is "); Serial.println(size);
String onejson = array[0];
JsonObject& root = jsonBuffer.parseObject(onejson);
if (!root.success()) {
Serial.println("parseObject failed");
} else {
double xv = root["v"];
String xts = root["ts"];
String xdevice_type = root["device_type"];
String xunit = root["unit"];
v = xv;
ts = xts;
device_type = xdevice_type;
unit = xunit;
return 1;
}
jsonBuffer.clear();
}
} else {
String payload = cayhttp.getString();
Serial.println(httpCode);
Serial.println(payload);
}
}
}
cayhttp.end();
cayclient.stop();
}
int rest_query_cayenne_day(const char caydev[], const char caysen[]) {
// results v, ts, device, unit
WiFiClientSecure cayclient;
HTTPClient cayhttp;
cayclient.setInsecure();
int ret = 0;
if (!cayclient.connect(cayserver, 443)) {
Serial.println("Cayserver failed to connect");
} else {
String get = "https://platform.mydevices.com/v1.1/telemetry/" + String(caydev) + "/sensors/" + String(caysen) + "/summaries?endDateLatest=true&type=day";
//Serial.println(get);
if (cayhttp.begin(cayclient, get)) {
cayhttp.addHeader("Authorization" , "Bearer " + String(access_token));
int httpCode = cayhttp.GET();
if (httpCode > 0) {
//Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
String payload = cayhttp.getString();
//Serial.println(payload);
int payload_length = payload.length();
Serial.print("Payload length is "); Serial.println(payload_length);
// [{"v":"1526700604","ts":"2018-05-19T03:30:05.283Z"},{"v":"1526700604","ts":"2018-05-19T03:30:05.283Z"}]
DynamicJsonBuffer arrayBuffer(500);
DynamicJsonBuffer jsonBuffer(100);
JsonArray& array = arrayBuffer.parseArray(payload, 2);
int size = array.size();
Serial.print("Array Size is "); Serial.println(size);
for (int ii = 0; ii < size; ii++ ) {
String onejson = array[ii];
JsonObject& root = jsonBuffer.parseObject(onejson);
//Serial.print(ii); Serial.print(" >"); Serial.print(onejson); Serial.println("<");
if (!root.success()) {
Serial.println("parseObject failed");
} else {
double xv = root["v"];
String xts = root["ts"];
Serial.print("index "); Serial.print(ii);
Serial.print("\t v "); Serial.print(xv);
Serial.print("\t ts "); Serial.print(xts);
Serial.println("");
v = xv;
ts = xts;
}
}
}
} else {
String payload = cayhttp.getString();
Serial.println(httpCode);
Serial.println(payload);
}
}
}
cayhttp.end();
cayclient.stop();
}
CAYENNE_OUT_DEFAULT() {
}
CAYENNE_IN_DEFAULT()
{
}