How to access Cayenne API using Insomnia, Node-red and Thunkable

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()
{
}
2 Likes