Banco de dados com Google planilhas com ESP32 / ESP8266

Banco de dados com Google planilhas - ESP

O Google planilhas é um "Excel online", que te permite criar tabelas e coisas do tipo, online, sem a necessidade de instalar no seu computador. Podemos compartilhar essa tabela para outras pessoas visualizarem ou edita-las. Nesse tutorial aprenderemos como usar o Google Planilhas para criar um banco de dados online, gratuito e simples, visto que não precisamos ter um servidor dedicado à hospedar o serviço. Esta primeira parte será ensinado apenas a enviar os dados usando um ESP.

[toc]

Banco de dados

Banco de dados é um conjunto de dados, normalmente relacionados entre si, como por exemplo: dados de clientes, LOG de temperaturas e coisas similares. Normalmente são dados organizados por colunas e linhas (matriz/tabela) para fácil entendimento por nós.

Poderíamos usar MySQL ou Firebase, que nos permite criar banco de dados de forma eficiente e confiável, entretanto,  é preciso ter um servidor apenas para hospedar seu banco de dados sempre disponível.

Você pode ler mais sobre Banco de dados e o uso do MySQL no tutorial: Arduino e MySQL – Registrando temperatura em um banco de dados usando o Shield Ethernet W5100

O Google planilhas oferece uma solução simples e gratuita para o armazenamento dos dados coletados. Podemos criar essas tabelas em conjunto do Google Forms, para enviar os dados dos nossos sensores, clientes e etc., sem a necessidade de um computador ou servidor pago hospedando o banco de dados, já que a Google se encarrega totalmente do serviço.

Obtendo os recursos necessários

Para usar esse incrível recurso precisaremos de uma conta no Google, e com ela criaremos dois arquivos, um de Planilha e outro Form.

Iremos através do formulário, enviar dados para a planilha (os dados do formulário irão para a planilha).

Passo 1-) Vá ao seu Google Drive e crie uma Planilha.

Passo 2-) Altere o nome da sua planilha para ser de fácil identificação nos próximos passos.

Figura 3 - Alterando o nome da planilha.
Figura 3 - Alterando o nome da planilha.

Passo 3-) Volte no Drive e crie um formulário.

Passo 4-) Altere o titulo do seu formulário para o desejado, e configure as perguntas.

Na planilha, os títulos das perguntas serão as colunas, e as respostas serão as linhas. Usaremos a opção "Resposta curta", que permite adicionar números e textos pequenos.

Passo 5-) Vá em "Respostas", vamos atribuir o formulário à planilha criada anteriormente. Clique nas "três bolinhas", e "Selecionar destino da resposta".

Passo 6-) Selecione a planilha desejada e estará pronto para receber nossos dados.

Agora, nosso formulário esta pronto para receber os dados e automaticamente transmitir para a planilha.

Para testar o formulário, clique no "Olho" ao canto superior direito, para abrir o link do formulário.

Figura 7 - Abrindo o link do formulário.
Figura 7 - Abrindo o link do formulário.

Após digitar o numero e clicar em "Enviar", será mostrado o aviso que a resposta foi registrada.

Figura 8 - Resposta enviada.
Figura 8 - Resposta enviada.

Agora, volte à sua Planilha, e veja que os resultados já estão aparecendo!

A coluna "Carimbo de data/hora" é preenchida automaticamente pelo sistema do Google, poupando imenso trabalho e requisitos do nosso sistema, dispensando até mesmo RTCs. A outra coluna "Numero" é o titulo da nossa pergunta, e a linha é a resposta que inseri.

Figura 9 - Resposta do formulário na planilha.
Figura 9 - Resposta do formulário na planilha.

Agora que aprendemos a utilizar o formulário em conjunto com a planilha, precisamos apenas integrar no Microcontrolador.


Mãos à obra

Componentes necessários

Conheça um pouco mais sobre ESP:

Código do projeto

Atenção: Não copie e cole o código inteiro, precisamos fazer algumas alterações no link utilizado. Será explicado logo abaixo em "Entendendo a fundo".

Caso esteja usando o ESP32, altere as bibliotecas removendo a ESP8266WiFi.h e incluindo as bibliotecas WiFi.h e WiFiClientSecure.h

Alguns usuário relatam erro com as versões mais novas do core esp8266 (quando você instala pelo menu (ferramentas > placa > gerenciar placas). A solução é instalar e usar a versão 2.4.0

// Código Banco de dados com Google planilhas com ESP - Vida de Silício

#include <ESP8266WiFi.h> 
// Alterar a linha anterior por #include <WiFi.h> se estiver usando ESP32
// #include <WiFiClientSecure.h> // Incluir esta biblioteca se estiver usando ESP32

WiFiClientSecure client;//Cria um cliente seguro (para ter acesso ao HTTPS)
String textFix = "GET /forms/d/e/1FAIpQLSdm6M_0mTVx_LKHLB1J3u_hjaag_hBtMfDHQlTIKe0EoatfsQ/formResponse?ifq&entry.717212213=";
//Essa String sera uma auxiliar contendo o link utilizado pelo GET, para nao precisar ficar re-escrevendo toda hora


void setup()
{
    Serial.begin(115200);//Inicia a comunicacao serial
    WiFi.mode(WIFI_STA);//Habilita o modo estaçao
    WiFi.begin("SUA REDE", "SUA SENHA");//Conecta na rede
    
    delay(2000);//Espera um tempo para se conectar no WiFi

}


void loop()
{
    if (client.connect("docs.google.com", 443) == 1)//Tenta se conectar ao servidor do Google docs na porta 443 (HTTPS)
    {
        String toSend = textFix;//Atribuimos a String auxiliar na nova String que sera enviada
        toSend += random(0, 501);//Adicionamos um valor aleatorio
        toSend += "&submit=Submit HTTP/1.1";//Completamos o metodo GET para nosso formulario.

        client.println(toSend);//Enviamos o GET ao servidor-
        client.println("Host: docs.google.com");//-
        client.println();//-
        client.stop();//Encerramos a conexao com o servidor
        Serial.println("Dados enviados.");//Mostra no monitor que foi enviado
    }
    else
    {
        Serial.println("Erro ao se conectar");//Se nao for possivel conectar no servidor, ira avisar no monitor.
    }

    delay(5000);
}

Colocando para funcionar

Após a editar o código com as suas informações, tudo irá funcionar corretamente. Veja como ficou o nosso, enviando valores aleatórios para nossa planilha a cada ~5 Segundos.


Entendendo a fundo

Precisamos fazer algumas alterações para o funcionamento do sistema com sua planilha. Sem isso, você irá enviar dados para nossa planilha de teste! (hehe)

Passo 1-)  Abra seu formulário (Figura 7).

Passo 2-) Copie todo o link entre "docs.google.com" e "/viewform". Salve isso em algum lugar, já iremos utilizar.

O nosso ficou "/forms/d/e/1FAIpQLSdm6M_0mTVx_LKHLB1J3u_hjaag_hBtMfDHQlTIKe0EoatfsQ".

Passo 3-)  Clique com o direito no "Input Text Box" e "inspecionar elemento".

Passo 4-) Agora, iremos pegar o nome desse Input Text Box.

O nosso é "entry.717212213".

Agora, devemos alterar esses dois valores no código, pois são os valores da sua planilha, e no código demonstrado de exemplo, foi utilizado nossos dados.

Obs: Altere apenas as partes destacadas, o restante é necessário para o correto funcionamento.

Atualização por contribuição do leitor Anselmo:

Caso tenha dificuldade em encontrar os entry, bastar seguir os seguintes passos:

    1. Clique no formulário com o botão direito do mouse e selecione "Exibir código fonte da pagina" (Ctrl+U);
    2. Agora pesquise pelo nome do campo inserido no formulário usando a ferramenta de pesquisa do navegador (Ctrl+F);
    3. No final do código vai encontra algo parecido com:  FB_PUBLIC_LOAD_DATA_ = [null,[null,[[490158642,"nome do campo",null,0,[[12345678,null,0,null,[[1,9,[""];
    4. O entry vai ser o numero após o colchete “12345678”,
    5. Inclua "entry." antes do número, fincando “entry.12345678”;
    6. Se você tiver outros campos, os outros entry do formulário vão estar na sequencia.

Exemplo: Campo do formulário: Teste var 1

    • Procure por “Teste var” (Ctrl+F);
    • No final do código vai encontra algo parecido com: "teste var 1",null,0,[[278629525,null,0,null,[[1,9,[""]
    • Copie o número após o colchete “278629525”
    • basta agora incluir "entry." antes do número , ficando “entry.278629525”

 

Passo 5-) Vá no começo do código e altere esta parte destacada, pelo que você copiou no item 2.

Esta parte é o "ID/KEY" do seu formulário, cada formulário tem o seu.

Passo 6-) Nessa mesma parte do código, altere essa outra parte destacada, pelo valor copiado no item 4.

Se você tiver mais de uma entrada para dados, a String ficaria por exemplo:

"GET /forms/d/e/1FAIpQLSdm6M_0mTVx_LKHLB1J3u_hjaag_hBtMfDHQlTIKe0EoatfsQ/formResponse?ifq&entry.717212213=123&entry.312212717=1234"

Os dados em negrito são os dados que você adicionaria, sendo de sensores, temperatura e etc.

Se você quiser testar com nossa planilha, sinta-se livre. Entretanto, é permitido apenas a visualização. Link da nossa planilha.

Software

- String auxiliar

String textFix = "GET /forms/d/e/1FAIpQLSdm6M_0mTVx_LKHLB1J3u_hjaag_hBtMfDHQlTIKe0EoatfsQ/formResponse?ifq&entry.717212213=";

Essa String textFix é uma auxiliar para nao precisar ficar reescrevendo toda hora, desde que essa parte é FIXA. O único valor que iremos alterar é após o  igual "=", que será o valor enviado à planilha.

- Função WiFiClient::connect()

if (client.connect("docs.google.com", 443) == 1)

Precisamos antes de enviar o método GET, se conectar no servidor. Essa função se conecta à URL (IP), na porta desejada.

- Corpo restante do GET

String toSend = textFix;//Atribuimos a String auxiliar na nova String que sera enviada
toSend += random(0, 501);//Adicionamos um valor aleatorio
toSend += "&submit=Submit HTTP/1.1";//Completamos o metodo GET para nosso formulario.

client.println(toSend);//Enviamos o GET ao servidor-
client.println("Host: docs.google.com");//-
client.println();//-
client.stop();//Encerramos a conexao com o servidor
Serial.println("Dados enviados.");//Mostra no monitor que foi enviado

Após a conexão com o servidor, adicionamos um valor aleatório na String final à ser enviada, e também terminamos o restante do necessário a ser enviado.


Desafio

Foi demonstrado apenas o envio de uma variável para a planilha, entretanto em qualquer projeto pode ser necessário o envio de diversas. Faça as alterações necessárias, adicionando os novos "Input Text Box" e tente enviar varias variáveis para sua planilha!

Fechamento

Em diversos projetos precisamos enviar dados ou guarda-los para analise, e um banco de dados como SQL pode ser desnecessário, uma vez que precisamos de um servidor para hospedar o banco de dados; com este método é possível facilmente criar seu banco de dados online, compartilhar com amigos e etc.

Na parte 1 foi mostrado apenas o procedimento para envio dos dados, entretanto, podemos precisar pegar valores da tabela para uso. Já a parte 2, você aprenderá como ler os valores da planilha para manipulação de dados ou até criar comandos de controle para o MCU: Lendo dados do Google planilhas com ESP – Banco de dados

Referências

  • https://developers.google.com/sheets/api/guides/values

Segurança de dados com AES

Segurança de dados

A segurança é algo essêncial em muitos projetos, principalmente nos conectados à Internet. Desde esconder senhas ou mensagens para que ninguém além do destino possa ler, a segurança faz parte do nosso cotidiano e iremos aprender a implementa-la nos Microcontroladores. Aprenderemos usar a criptografia AES (Advanced Encryption Standard) com foco em apenas sobre sigilo do dado, o download dela estará ao fim do tutorial. Esta biblioteca para criptografia com AES, funciona tanto para Arduino, quanto para ESP8266 ou ESP32.

 

 

Um pouco sobre segurança

Antes de entrar em detalhes sobre o AES, um resumo sobre a segurança de dados.

 

-Codificação

A codificação é possivelmente o método mais simples e antigo, trata-se da troca de uma linguagem, para outro padrão. É necessário conhecer os caracteres codificados para poder decodificar. O objetivo da codificação não é tornar a mensagem secreta. Exemplo: Morse(Fig 1), que converte os caracteres para pulsos elétricos, sons, luzes, etc.

-Criptografia simétrica

A criptografia simétrica faz o uso de uma chave privada que deve ser mantida em segredo, já que é usada tanto para encriptação, quanto para desencriptação. Esta é mais simples e leve que a criptografia assimétrica. Exemplo: AES, DES.

-Criptografia assimétrica

A criptografia assimétrica faz o uso de duas chaves, uma pública e outra privada. A pública pode ser usada para encriptação e a privada para desencriptação. Esta é mais pesada e lenta. Exemplo: RSA.

O uso delas é bem diferente e logo, a comparação direta não faz sentido. Por exemplo, a assimétrica permite autenticidade dos dados e pode garantir que o dado recebido é de uma pessoa autorizada e não de alguém re-enviando o dado.

 

 

-Hash

Hash é um algoritmo de uma via, ou seja, é irreversível. É muito usado com senhas da seguinte forma: Primeiramente é gerado um Hash da senha e este, será apenas comparado ao Hash armazenado no destino. Caso os Hash's sejam iguais, logo a senha é igual. Exemplo: MD5, SHA-1.

Clique AQUI para mais informações sobre Hash.

 

-AES

AES (Advanced Encryption Standard), é uma criptografia de blocos com chave simétrica (cifra de bloco) e será usado AES-128 no exemplo deste tutorial. AES trabalha com o sistema de blocos de 16 Bytes. É possível utilizar valores de entrada menores sem problemas, mas maiores será necessário dividir em blocos de 16B.

 

 

Imagine que você use dois micro controladores para transmissão de mensagens (Exemplo: Whatsapp, Facebook...), muito provavelmente você deseja que ninguém consiga ler as mensagens, isto pode ser feito com a encriptação, que irá cifrar (embaralhar) a mensagem e deixa-la ilegível para qualquer pessoa sem a chave, garantindo que apenas as pessoas com a chave, consigam ler.

Também pode ser usada para protocolos de comunicação entre dispositivos Wireless ou Wired, para preservar a integridade do mesmo e evitar "curiosos de plantão".


Mãos à obra

Código do projeto

#include <AES.h>//Biblioteca do AES.

AES aes;//Cria a classe aes.
byte key[16], out[16], inp[32];//Cria arrays (vetores) para a chave, input e output de dados.
const char pass[] = "abc";//Define a chave usada, neste exemplo usamos AES128, então precisa ser <= 16 Bytes.


void setup()
{
   Serial.begin(115200);//Habilita a serial.
   Serial.println();//Limpa o monitor.

   enc128("vida de silicio", 1);//Faz a função de encriptação e retorna o HEX encriptado.
}

void loop()
{

}


void enc128(const char txt[], bool db)//Argumentos: (texto e debug)
{
   if (strlen(pass) > 16)//Verifica se a chave tem o tamanho limite de 16 caracteres.
   {
      if (db == true)
      {
         Serial.println("Chave para AES128 <= 16 Bytes");
      }
      return;//Se a chave for maior, irá sair da função.
   }

   if (strlen(txt) > 16)//Verifica se o texto tem o tamanho limite de 16 caracteres.
   {
      if (db == true)
      {
         Serial.println("Frase/numero para AES <= 16 Bytes / bloco");
      }
      return;//Se o texto for maior, irá sair da função.
   }

   for (byte i = 0; i < strlen(pass); i++)//Adiciona a chave(pass) na array key.
   {
      key[i] = pass[i];
   }

   for (byte i = 0; i < strlen(txt); i++)//Adiciona o texto na array input.
   {
      inp[i] = txt[i];
   }

   //Adiciona a chave ao algoritimo.
   if (aes.set_key(key, 16) != 0)//Verifica se a chave esta correta, caso nao, sairá da função.
   {
      if (db == true)
      {
         Serial.println("Erro ao configurar chave");
      }
      return;//Sai da função
   }

   //Faz a encriptação da array INPUT e retorna o HEXA na array OUTPUT.
   if (aes.encrypt(inp, out) != 0)//Verifica se a encriptação esta correta, se não, sairá da função.
   {
      if (db == true)
      {
         Serial.println("Erro ao encriptar");
      }
      return;//Sai da função
   }

   if (db == true)//Se o debug estiver on (1), irá mostrar o HEXA no serial monitor.
   {
      for (byte i = 0; i < 16; i++)
      {
         Serial.print(out[i], HEX);
         Serial.print(" ");
      }
      Serial.println();
   }

   aes.clean();//Limpa a chave e residuos sensiveis da encriptação.
}

Entendendo a fundo

Software

A função que desenvolvemos enc128() torna o uso muito simples, mas você deve estudar mais sobre o AES e a biblioteca usada para entender melhor o funcionamento. Aqui será mostrado apenas a encriptação, mas também é possível fazer a desencriptação da mesma forma, este será o desafio de vocês para aprendizado.


 

-Variaveis usadas

byte key[16], out[16], inp[32];

Criamos os vetores (Arrays) para alocar a CHAVE e mensagens de INPUT e OUTPUT do buffer AES.

 

-Definindo a chave

char pass[] = "abc";

Definimos a Key (chave) da nossa criptografia. Deve ter no mínimo 1 caractere, e no máximo 16 (AES 128).  0 < Key <= 16. Aqui usamos "abc", mas é aconselhado o uso de letras e números aleatórios.

Você deve usar chaves grandes e aleatórias. Sem isso, seu sistema estará em grandes riscos. Usamos uma chave simples para fácil entendimento.

 

-Função enc128()

enc128("vida de silicio", 1);

enc128(texto, debug);

A função criada para encriptação dos dados torna o processo bem fácil. Os parâmetros necessários para ela é o texto que deseja encriptar, e em seguida, o debug, que mostra no serial monitor possíveis erros e por fim, o HEX da encriptação.

O texto para encriptação deve estar entre aspas e ser menor que 17 caracteres (bytes). 0 < texto <= 16.

O debug é ativado com 1 e desativado com 0, aconselhamos a sempre usar 1 para caso aconteça erros.

 

-Função AES::set_key()

aes.set_key(key, 16);

Com esta função, é adicionado a nossa chave ao sistema de criptografia interno.

Obs: A chave para AES é 128/192/256b, porém, para ser didático, foi usado apenas 3 caracteres. Tome cuidado ao usar chaves de outros tamanhos, alguns lugares não aceitam!

 

-Função AES::encrypt()

aes.encrypt(inp, out);

Esta função, faz a encriptação dos dados que estão dentro do vetor INP, e retorna os valores dentro do vetor OUT.


Colocando para funcionar

Ao testar o código que foi mostrado aqui, será gerado exatamente este código em hexadecimal "4A 38 3A 94 FC FB C4 C6 E1 4F D2 5D 34 7B B5 80", este código hexadecimal é a nossa mensagem encriptada. Encontrei um site bem legal que faz a encriptação e desencriptação dos dados AES, usarei ele.

Coloquei a nossa chave "abc" e o código hexadecimal gerado pelo micro controlador. Após clicar para desencriptar, é mostrado a mensagem original, e como podemos ver, funcionou.

o AES permite vários métodos de encriptação, a mais simples é a ECB, a biblioteca usada no tutorial também permite a CBC que é mais segura, porém mais complicada.

Clique AQUI para ir ao site.


Desafio

O desafio para vocês é que façam a desencriptação de um código hex, estudem sobre o assunto e veja as funções da biblioteca! Vocês podem desencriptar o próprio hex gerado da sua encriptação, ou usar o site indicado anteriormente para obter um hex e ver se a desencriptação funciona. Lembrando que esta biblioteca funciona para Arduino, ESP8266 e ESP32.

Download da biblioteca: https://github.com/spaniakos/AES

 

Fechamento

A segurança é extremamente importante em IoT e nao deve ser esquecida. Sempre adicione caso seja necessário em seu projeto, e principalmente em produtos comerciais. Tem dúvidas? sugestões? críticas? Comente abaixo!