banner

IA com DialogFlow e App Fernando K



Volto a falar hoje de Inteligência Artificial, ou melhor, de um projeto de automação no qual usamos o Google Home Mini, DialogFlow e o ESP32. Hoje vamos fazer a integração com o App Fernando K com o Google Home Mini, além de focar, principalmente, no DialogFlow. Esse vídeo, portanto, é uma continuação do já lançado “Inteligência Artificialcom Google Home Mini e ESP32”. Daqui para frente quero falar bastante sobre Machine Learning, Deep Learning, e outros assuntos que fazem parte da integração da inteligência artificial com a Internet das Coisas.





Recursos usados

  • ESP-WROOM-32 DevKit (30 pinos)
  • Celular com APP Fernando K






Criar Realtime Database


Já criamos o banco de dados no Firebase nesse vídeo: Automação com App Fernando K e Firebase sem precisar deDDNS.



DialogFlow

Banco utilizado no projeto:





Conectar o Google Home Mini


Antes é necessário conectar o Google Home Mini a rede Wi-Fi e também parear com a mesma conta do google utilizada no DialogFlow, Firebase e Google Actions.






Setup DialogFlow


Criando conta DialogFlow

Clique em “Go to Console”.



Clique em “Google” e faça seu login.



Clique em “Permitir”.



Aceitei os termos de serviço e clique em “Accept”.



Welcome to DialogFlow:




Criar Agent



Coloque o nome do Agente, escolha a linguagem dos diálogos e clique em “Create”.



Criar Entidades
Clique em “Entities”



Clique em “Create Entity”




Entidades

Como se fosse entidade de banco de dados é definido um nome da entidade, como, por exemplo, devices para simbolizar todos os dispositivos a serem controlados. E, embaixo, são definidos os dispositivos com seus respectivos nomes e sinônimos.



Criar Entidades
Coloque o nome da Entidade como “dispositivos”



Adicione o nome do dispositivo e clique em Enter. Após adicionar cliquem em “Save”.




Entidades – Sinônimos

Os sinônimos podem ser adicionados na parte direita da tabela. Para adicionar vários basta colocar o sinônimo e depois em Tab.



Criar Entidades
Crie mais uma entidade, só que agora com o nome “status” com os seguintes valores:



Criar Intenções
Clique em “Intents” e depois clique em “Create Intent”



  • Contexto - pode ser usado para lembrar valores de parâmetros, para que possam ser passados entre intenções
  • Eventos - maneira opcional de acionar a intenção sem a necessidade de texto correspondente ou entrada falada. Use eventos específicos da plataforma predefinidos ou defina ou personalizados
  • Frases de Treinos - frases que você pode esperar dos usuários, que irão desencadear a intenção
  • Respostas – resposta do google home



Adicione um nome para a intenção, nome utilizado foi: “controlaFirebaseAppFernandoK”





Intenções - Frases de Treino

As frases são as expressões que o google home vai treinar para contextualizar as entidades existentes.



Adicione as possíveis frases que o google home vai receber. Perceba que vai reconhecer as entidades criadas anteriormente.



Para mudar a entidade ou criar uma nova clique na palavra com o botão direito do mouse e selecione.



Selecione led na entidade “dispositivos”



Adicione todas as frases possíveis para o treino, adicionando sempre as entidades para assim ter o maior controle.



Como sempre algo é relacionado com dispositivos, marque dispositivos na seção “Action and parameters” como “Required”.



Em fulffilment clique em “disable webhook call for this intent” para habilitar o fulffilment utilizado no passo seguinte.





Uso DialogFlow

É possível adicionar novas intenções e entidades para controle do banco de dados.
Primeiro crie uma entidade e depois faça o controle da entidade com o uso das intenções.
Exemplo de intenção citando entidades:





DialogFlow Fulfillment

Clique em “Save” para salvar a intenção e depois clique em “Fulfillment” na esquerda.



Vamos usar o Inline Editor para usarmos o cloud functions do Firebase.
Clique em “Disable” para habilitar.




 
Código Fulfillment DialogFlow



//Imports
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
//Inicializaão do Firebase
const admin = require('firebase-admin');
admin.initializeApp({
  credential: admin.credential.applicationDefault(),
  databaseURL: 'ws://NOMEDOPROJETOFB.firebaseio.com/',
  projectId: "NOMEDOPROJETOFB",
});

process.env.DEBUG = 'dialogflow:debug';


exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {   
  //Instanciando Webhook
  const agent = new WebhookClient({ request, response });  
  console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
  console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
    //função que lida com os dispositivos
    function handleDevice(agent) {
      //variáveis com os parâmetros reconhecidos pela voz
      const pegar = agent.parameters.get;
      const device = agent.parameters.dispositivos;
      const status = agent.parameters.status;
      //se tiver dispositivo e status significa que ele vai mudar
        if(device && status){     
            var novoStatus;      
            //Se receber comando ligar, mudar valor para ligado
            if(status == "ligar" || status == 'on')
              novoStatus="ligado";
            else  //Se receber comando desligar, mudar valor para desligado
              novoStatus="desligado";            
            //setar o valor do dispositivo NO FIREBASE
            admin.database().ref('automation/'+device).set(novoStatus);
            //manda uma resposta para o cliente por voz 
            agent.add(`Feito!`);
        }                
        else{
          //se não tiver o status e somente o dispositivo, ou seja, ta pedindo informação
            if(device){
              //busca o status do dispositivo
              
                return admin.database().ref('/automation/'+device).once('value').then(function(snapshot) {
                //recebe o valor do status
                var valor = snapshot.val();
                console.log('valor ='+valor);
                console.log('device = '+device);   
                //se pedir informação sobre o led   
                if(device=="led"){
                    //manda uma resposta para o cliente por voz 
                    agent.add(`O led está `+valor);
                }  
              });
            }
            //Se não tiver nenhum dispositivo não reconhece o comando
            else{
                //manda uma resposta para o cliente por voz 
                agent.add(`Desculpe, não entendi`);
            }
           
        }   
  }
  //executa o manipulador de função apropriado com base no nome da intenção correspondente do Dialogflow
  let intentMap = new Map(); // relaciona uma função com uma intenção
  intentMap.set('controlaFirebaseAppFernandoK', handleDevice);// relaciona a função handleDevice com as intenções (controlaFirebaseAppFernandoK)
  agent.handleRequest(intentMap); // Passa o intentMap Quando Google Home é requisitado 
});


DialogFlow Fulfillment

Coloque o código no editor e clique em “Deploy”.



Após terminar vai exibir uma mensagem.
Para ver o log clique em “View execution logs in the firebase console”



Clique em “Integrations”.





Integração com Google Assistant


Clique em Integration Settings




Action Google

Clique em “MANAGE ASSISTANT APP” e será direcionado pra outra página do Actions on Google.



Aceite os termos e clique em “Agree and Continue”.



Para fazer o deploy da sua action é necessário cumprir todos os requisitos e preencher todos os campos obrigatórios.



Clique em “Decide how your Actions is invoked”.



Escolha o nome como deseja chamar, escolha a voz da assistente e clique em Save



Preencha todas as informações do “Directory Information” e clique em “Save”



Após preencher todas as informações obrigatórias clique em “Release” no canto esquerdo da tela.
Agora para testar iremos enviar a versão Alpha, então clique em “Submit for Alpha”.



Aceite os termos e clique em “Submit”.
Demora cerca de 3 horas para ser aceito caso tudo esteja certo.





Simulações no Actions on Google

Clique em “Simulator” no canto esquerdo para abrir o simulador.



Basta simular diálogos para fazer melhorias. Mudando as intenções, entidades ou código para obter melhor resultado em suas aplicações.





APP Fernando K com Firebase


Link para download do Aplicativo:




Como utilizar o aplicativo Fernando K

Confira esse vídeo utilizando o aplicativo Fernando K e o Firebase: Automação com App Fernando K eFirebase sem precisar de DDNS.




Adicionar nova Conexão

1.       Clique no Botão Menu
2.       Clique em Connection
3.       Clique no botão “+”



Tipos de conexões:
1.       Conexão por Socket.
2.       Conexão por Firebase.
Clique em “Firebase”




Conexão por Firebase

Para ter uma conexão com o Firebase, primeiramente é necessário obter a “databaseURL” utilizado para conectar ao aplicativo.
Coloque a databaseURL e um nome para a conexão e clique em “Add”.




Conectar

Para conectar, clique na conexão.




Firebase fbpath

O Firebase é um banco, e para ter uma visualização melhor o comando “fbpath” consegue entrar dentro das “tabelas” para conseguir ver o escopo correto.
Para esse projeto, utilizamos o “ fbpath /automation” para visualizar apenas as mudanças lá que se encontra o led.



 Comunicação Aplicativo - ESP

Após estar conectado, é possível se comunicar  com o ESP.
O Padrão de comunicação programado no ESP é o nome do comando, seguido por um valor.
Exemplos:
·         led ligado
·         led desligado





Código – ESP32

Configurações

Bibliotecas necessárias


Fluxograma do código fonte




Declarações e variáveis

#include <Arduino.h>
#include "esp_task_wdt.h" // Lib do watchdog
#include <IOXhop_FirebaseESP32.h> // Lib do Firebase

// Url do Firebase 
#define FIREBASE_HOST "NOMEDOPROJETOFIREBASE.firebaseio.com/" 
#define FIREBASE_AUTH "" 

// Nome da rede WiFi e senha
const char *ssid     = "NOMEDOWIFI"; 
const char *password = "SENHADOWIFI"; 

// Pino LED
const int luzLed = 2;



Setup

void setup() 
{  
  // Iniciamos a serial
  Serial.begin(115200);

  // Inicializamos o watchdog com 15 segundos de timeout
  esp_task_wdt_init(15, true);

  // Setamos os pinos dos relés como saída
  pinMode(luzLed, OUTPUT);    
  digitalWrite(luzLed,HIGH);
  delay(500);
  digitalWrite(luzLed,LOW);
  // Iniciamos o WiFi
  wifiBegin();
  // Iniciamos a conexão com o Firebase
  firebaseBegin();
}


FirebaseBegin

// Função que inicia a conexão com o Firebase
void firebaseBegin()
{
  // Iniciamos a comunicação Firebase
  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);  
  
  // Setamos o callback (Executado a cada alteração do firebase)
  Firebase.stream("/", [](FirebaseStream stream) 
  {
    String path, value;  

    // Se o evento que vem do callback é de alteração "put"
    if(stream.getEvent() == "put") 
    {     
      // Obtemos os valores de path e value
      path = stream.getPath();
      value = stream.getDataString();   

      // Deixamos em maiúsculo
      path.toUpperCase();         
      value.toUpperCase();



      Serial.println(path);
      // Se for a mensagem inicial enviada pelo firebase assim que o ESP inicia sua comunicação
      if(value.startsWith("{\"AUTOMATION\""))
      {
        // Sincronizamos as saídas parao pino de acordo com a mensagem recebida
        syncFirebase(value);        
        Serial.println("Firebase sincronizado");
      }
      else{
          // executamos um comando e exibimos na serial      
          Serial.println(executeCommandFromFirebase(path, value));
      }
      
    }    
  });
}


SyncFirebase

// Função que ativa/desativa todos os relés de acordo com a mensagem recebida ao iniciar o Firebase (Sincronizando as saídas do ESP com os valores atuais do Firebase)
void syncFirebase(String value)
{
  /*
  EXEMPLO DE MENSAGEM RECEBIDA:
  {"AUTOMATION":{"LED":"DESLIGADO"}}
  */
  // Obtendo a substring referente a lampada led
  String aux = value.substring(value.indexOf("LED"));

  int posVar = aux.indexOf("LED\":\"")+6;
  String status = "";
  
  for(int i = posVar; aux.charAt(i)!='\"'; i++)
    status += aux.charAt(i);
  
  Serial.println("Status LED:"+status);

  // Sincronizando saída referente a lampada led
  if(status.equals("LIGADO"))
    digitalWrite(luzLed, HIGH);
  else
  if(status.equals("DESLIGADO"))
    digitalWrite(luzLed, LOW);
    
  status = "";    
}


ExecuteCommandFromFirebase


// Função que executa um comando ativando e desativando os relés
String executeCommandFromFirebase(String cmd, String value)
{
  // Retira a primeira barra
  if(cmd.charAt(0) == '/')
    cmd = cmd.substring(1);

  // Exibe na serial o comando e o valor
  Serial.println("CMD "+cmd);
  Serial.println("VALUE "+value);
  
  
  // Caso for um comando referente o led
  if(cmd.equals("AUTOMATION/LED"))
  {    
    if(value.equals("LIGADO"))
      // Ativamos o relé (lógica inversa)
      digitalWrite(luzLed, HIGH);
    else // Caso contrário desativamos o relé
      digitalWrite(luzLed, LOW);
  }
  else // Se não entrou em nenhum "if" acima, retornamos uma mensagem de comando inválido 
    return "Invalid command";

  // Se for um comando válido retornamos a mensagem "OK"
  return  "OK";
}


WifiBegin

// Função que inicia o WiFi
void wifiBegin()
{
  // Iniciamos o WiFi
  WiFi.begin(ssid, password);  
    
  Serial.println("Wifi Connecting");

  // Enquanto não estiver conectado exibimos um ponto
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    esp_task_wdt_reset();
    delay(1000);
  }
  // Exibimos "OK"
  Serial.println("OK");
}


Loop

void loop() 
{
  
}


Configurações de compilação/upload






FAÇA O DOWNLOAD DOS ARQUIVOS








Um comentário:

  1. Fala Fernando, blz?

    Montei um projeto em casa para automação, mas construí meus próprios interruptores touch com NodeMCU-32s, interligados com Blynk, Firebase e Google Home Mini, seguindo seus vídeos, mas estou com um problema que não consigo resolver. Os dispositivos se reiniciam com frequência e não voltam a 'ler' o Stream do Firebase.

    Tentei reiniciar via ESP.restart() quando detectado Firebase.failed(), uso WiFiManager, não consigo estabilidade por nada. Teria alguma dica?! Acredita que o WatchDog faria alguma diferença no meu caso?

    Obrigado por compartilhar tanto conhecimento.

    ResponderExcluir

Tecnologia do Blogger.