Como chamar a API JSON HTTPS Rest usando ESP8266: Exemplo da API ClimaCell

Tempo de leitura: 5 minutes

Muitas vezes, é necessário chamar a API Rest JSON usando o ESP8266. É o caso em que é necessário chamar alguma API Rest JSON para integrar serviços com o ESP8266.

Basicamente, é necessário desenvolver um cliente HTTPS do ESP8266 que lida com as chamadas da API Rest JSON. Vamos descobrir como fazê-lo nas seguintes partes deste tutorial. Para entender melhor as etapas a seguir ao invocar uma API Rest JSON de um ESP8266, usaremos, como exemplo, uma API HTTPS do ClimaCell que retorna a poluição do ar. Portanto, criaremos um cliente HTTPS ESP8266 simples que chama a API deste ClimaCell e analisa o resultado JSON. Usando esse resultado, o ESP8266 gerencia uma faixa de LEDs que usa cores para visualizar a qualidade do ar.

Cenário do projeto

Queremos que o ESP8266 chame a API Web / API Rest para enviar e receber dados. Por exemplo, o ESP8266 precisa chamar um serviço meteorológico (como ClimaCell) para obter informações meteorológicas. Portanto, esse é um cenário comum e é útil entender como chamar a API HTTPS Rest usando ESP8266

Etapas chamam uma API JSON HTTPS Rest de ESP8266

Para chamar uma API JSON HTTPS Rest do ESP8266, é necessário seguir estas etapas:

  • Obtenha o token OAuth2 para ter acesso à API
  • Desenvolver um cliente HTTPS ESP8266
  • Chame a API JSON
  • Analisar o resultado JSON

Como obter o token OAuth2

Normalmente, uma API Rest JSON usa o protocolo OAuth2 para gerenciar o processo de autorização. Antes de prosseguir neste tutorial, você precisa obter seu token do ClimaCell. Você pode criar uma conta no ClimaCell gratuita por 14 dias. Depois de criar sua conta, você obterá o token para usar na chamada da API do ESP8266.

Este tutorial pressupõe que você já conhece o OAuth2, mas se você é novo neste protocolo, pode pular todos os detalhes do protocolo e concentrar sua atenção apenas no token.

Normalmente, o cliente Rest JSON precisa enviar esse token no cabeçalho HTTP. Veremos mais adiante como fazê-lo. Você pode consultar a documentação da API do provedor para saber mais sobre a API.

Como desenvolver um cliente HTTS ESP8266

O cliente ESP8266 Rest gerenciará todos os detalhes da conexão HTTPS. Portanto, para realizar essa tarefa, usaremos a Biblioteca HTTP ESP8266, para que não seja necessário implementar todo o cliente HTTP ESP8266 manualmente.

Conectando o ESP8266 ao WiFi

Em primeiro lugar, o ESP8266 deve se conectar ao Wifi. Eu apenas escrevo o código sem explicações porque é trivial:

boolean connectWifi() {
  // Vamos nos conectar ao WiFi
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(5000);
    Serial.print(".");
  }
  Serial.println(".......");
  Serial.println("WiFi conectado .... Endereço IP:");
  Serial.println(WiFi.localIP());
  return true;
}

onde ssid e senha (password) dependem do seu WiFi.

Conectando a uma API JSON HTTPS do ESP8266

Embora invocar uma API HTTP seja muito simples, invocar uma API HTTPS pode ser bastante complexo. Infelizmente, quase a API disponível usa o protocolo HTTPS. Então, o que precisamos fazer para implementar um ESP8266 Rest Client para chamar e a API HTTPS? O código abaixo mostra como fazê-lo:

#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>
const char *server = "https://api.climacell.co/v3/weather/realtime";
HTTPClient http;
void loop() {
  Serial.println("Conectando ao servidor HTTP ....");
  std::unique_ptrclient(new BearSSL::WiFiClientSecure);
  client->setInsecure();
  char apiURL[1024];
  Serial.println("Building URL...");
  sprintf(apiURL, "%s?lat=%f&lon=%f&fields=%s", server, lat,lon, fields );
  
  Serial.printf("API URL=%s\r\n",apiURL);
  if (http.begin(*client, apiURL)) {
    Serial.println("Connected");
    http.addHeader("Accept", "application/json");
    http.addHeader("apikey", API_KEY);
    int code = http.GET();
    Serial.printf("HTTP Code [%d]", code);
    if (code > 0) {
      if (code == HTTP_CODE_OK || code == HTTP_CODE_MOVED_PERMANENTLY) {
        Serial.println("GET OK");
        String payload = http.getString();
        Serial.println(payload);
        Serial.println("...JSON..");
      }
    }
    else {
      Serial.printf("[HTTP] GET... failed, error: %s", http.errorToString(code).c_str());
    }
  }

Algumas coisas a serem observadas no código acima:

>> nas linhas 7 e 8, um truque simples para chamar uma API Rest JSON por HTTPS sem usar o certificado.

>> Na linha 11, criamos o URL para chamar a passagem dos parâmetros de consulta de acordo com a API PM10.

>> Nas linhas 16 e 17, o cliente ESP8266 HTTPS transmite o token OAuth2 no cabeçalho usando a chave apikey

>> Finalmente, na linha 18, o ESP8266 faz a solicitação HTTP usando GET

>> Linha 23, obtemos a resposta. Esta resposta contém os dados JSON como resultado da chamada da API. Analisaremos essa carga útil para obter o valor que procuramos que representa a qualidade do ar

Como analisar a carga útil da API JSON usando o ESP8266

Geralmente, quando invocamos a API JSON Rest e temos a carga útil como resultado, podemos analisar o JSON para extrair os dados que estamos procurando.

Se o JSON for simples, podemos analisá-lo manualmente, mas sugiro usar a Biblioteca JSON do Arduino. Esta biblioteca simplifica o processo de serialização e desserialização. Vamos adicionar a seguinte linha no início:

#include <ArduinoJson.h>

Em seguida, é necessário definir o tamanho do objeto que desserializará o JSON. Para isso, é necessário conhecer a resposta da API JSON. O JSON abaixo é um exemplo de carga útil:

{
  "lat": 40.7127281,
  "lon": -74.0060152,
  "pm10": {
    "value": 18,
    "units": "µg/m3"
  },
  "observation_time": {
    "value": "2020-01-21T20:56:39.000Z"
  }
}

Na resposta, existem quatro objetos e um objeto possui dois valores internos, enquanto o outro possui apenas um valor. A dimensão que procuramos é:

const int jsonSize = JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(2) 
                     + JSON_OBJECT_SIZE(1);

Para analisar a resposta JSON retornada pela API Rest JSON, precisamos do seguinte código:

double parseJson(String jsonDoc) {
  Serial.println("Parsing JSON...");
  DynamicJsonDocument doc(jsonSize);
  deserializeJson(doc, jsonDoc);
  float value = doc["pm10"]["value"];
  return value;
}

>> na linha 3, definimos um DynamicJsonDocument com o tamanho do valor que calculamos na etapa anterior. Este é o analisador JSON que usamos para desserializar o documento JSON.

>> na linha 5, recuperamos o valor que representa a concentração de PM10.

Como controlar LEDs usando a API Rest JSON

Nesta última etapa, usaremos a poluição do ar (PM10) para gerenciar uma faixa de LED. Dessa forma, é possível visualizar a qualidade do ar usando cores. Esta etapa é bastante fácil e nós a cobrimos várias vezes. O esquema é mostrado abaixo:

Esp8266

Adicione o seguinte código para selecionar a cor dos LEDs:

#include <Adafruit_NeoPixel.h>
 
#define PIN D2
#define NUM_LEDS 12
// LEDs
Adafruit_NeoPixel pixelsRing(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);
void setLedColor(int range) {
   switch (range) {
      case 0:
        pixelsRing.fill(pixelsRing.Color(0x50,0xF0,0xE6));
        break;
      case 1:
        pixelsRing.fill(pixelsRing.Color(0x50,0xCC,0xAA));
        break;
     case 2:
        pixelsRing.fill(pixelsRing.Color(0xF0,0xE6,0x41));
        break;
     case 3:
        pixelsRing.fill(pixelsRing.Color(0xFA,0x50,0x50));
        break;
      case 4:
        pixelsRing.fill(pixelsRing.Color(0x96,0x00,0x32));
        break;
   }
   pixelsRing.show();
}
void loop() {
 ......
 if (http.begin(*client, apiURL)) {
   Serial.println("Connected");
   http.addHeader("Accept", "application/json");
   http.addHeader("apikey", API_KEY);
 
   int code = http.GET();
   Serial.printf("HTTP Code [%d]", code);
   if (code > 0) {
     if (code == HTTP_CODE_OK || code == HTTP_CODE_MOVED_PERMANENTLY) {
       Serial.println("GET OK");
       String payload = http.getString();
       Serial.println(payload);
       Serial.println("...JSON..");
       double value = parseJson(payload);
       Serial.printf("PM10 Value [%f]\r\n", value);
       if (value < 20)
          setLedColor(0);
       else if (value >= 20 && value < 35)
          setLedColor(1);
       else if (value >= 35 && value < 50)
          setLedColor(2);
       else if (value >= 50 && value < 100)
          setLedColor(3);
       else if (value >= 100)
          setLedColor(4);   
     }
   }
   else {
     Serial.printf("[HTTP] GET... failed, error: %s", http.errorToString(code).c_str());
   }
 }
 
 http.end();
 delay(60 * 1000);
}

Empacotando…

Por fim, no final deste tutorial, você aprendeu como desenvolver um ESP8266 Rest Client para chamar uma API Rest JSON. Isso é muito útil, pois acontece com bastante frequência que queremos integrar um serviço externo que fornece um conjunto de API. Existem outras maneiras de integrar o ESP8266 a sistemas externos. Outra maneira interessante é usar o protocolo MQTT com ESP8266 para publicar e assinar canais MQTT onde os dados são enviados e recebidos.

Neste tutorial, exploramos todas as etapas que precisamos seguir para chamar uma API JSON.

TAGS : API, ESP8266, IoT, JSON API

Visits: 3 Visits: 1199105