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:
Exemplos:
·
led ligado
·
led desligado
Código – ESP32
Configurações
Bibliotecas necessárias
Biblioteca do Firebase: https://github.com/ioxhop/IOXhop_FirebaseESP32
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
1 Comentários
Fala Fernando, blz?
ResponderExcluirMontei 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.