Controle sua casa por voz de
qualquer lugar do planeta utilizando Inteligência Artificial. Para isso, basta
usar o Google Home, Dialogflow e Firebase. Sei que temos outros programas já
prontos que podem facilitar um projeto, mas tenho em mente aqui os engenheiros,
desenvolvedores de produtos, que querem, por exemplo, conectar o Google Home
com uma máquina de visão artificial, uma rede neural convolucional, isso é
possível com esses programas que escolhi.
Portanto, vamos fazer uma automação
com Google Home Mini via comando de voz. Além de conectar o Google Home Mini,
vamos criar Realtime Database no Firebase, setar o DialogFlow, criar Entidades
e Intenções e, por fim, setar o Google Actions.
Recursos usados
·
ESP32S WROOM (38 pinos)
·
Sensor HTU21D
·
Módulo de 4 Relés
·
Protoboard
·
Jumpers
·
2 Lâmpadas
·
Extensão de Tomadas
·
Cabos
·
Assistente Pessoal Google Home Mini
Montagem
Criar Realtime Database
Já criamos o banco de dados no
Firebase nesse vídeo:
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
DialogFlow é uma plataforma
para construir interfaces de conversação para bots, aplicativos e dispositivos.
·
Possui uma das melhores interfaces para
construção de aplicações com NLU (Natural Language Understanding)
·
É 100% grátis
Primeiro, entre no site do
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
Clique em “Create Agente”
Coloque o nome do Agente,
escolha a linguagem dos diálogos e clique em “Create”
Import Intenções e Entidades
Clique na ferramenta ao lado
do nome do Agent
Clique em “Export and Import”
Selecione o arquivo .zip
escreva “IMPORT” no campo de texto e depois clique em “IMPORT”. Assim importará
um projeto pronto com as entidades e intenções já criadas.
OBS: Vou fazer um vídeo para
falar sobre criar entidades e intenções.
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
Fulfillmente é o processo
total, que começa ao cliente falar algo, e termina até receber uma resposta.
Clique em Fulffilment.
Vamos usar o Inline Editor
para usarmos o cloud functions do Firebase.
Clique em “Disable” para
habilitar.
Código Fulfillment DialogFlow
Código Fulfillment
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const admin = require('firebase-admin');
admin.initializeApp({
credential: admin.credential.applicationDefault(),
databaseURL: 'ws://teste-1172b.firebaseio.com/',
projectId: "teste-1172b",
});
process.env.DEBUG = 'dialogflow:debug';
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
function handleDevice(agent) {
const pegar = agent.parameters.pegar;
const device = agent.parameters.devices;
const status = agent.parameters.status;
if(device && status){
if(device=='tudo'){
var novoLuz,novoLed,novoVentilador;
if(status =='ligar' || status =='on'){
novoLuz='ligada';
novoLed='ligado';
novoVentilador='ligado';
}
else{
novoLuz='desligada';
novoLed='desligado';
novoVentilador='desligado';
}
admin.database().ref('automation/luz').set({
status: novoLuz,
});
admin.database().ref('automation/led').set({
status: novoLed,
});
admin.database().ref('automation/ventilador').set({
status: novoVentilador,
});
agent.add(`Feito!`);
}
else{
var novo;
if(device == 'luz'){
if(status == "ligar" || status == 'on')
novo="ligada";
else
novo="desligada";
}
else{
if(status == "ligar" || status == 'on')
novo="ligado";
else
novo="desligado";
}
admin.database().ref('automation/'+device).set({
status: novo,
});
agent.add(`Feito!`);
}
}
else{
if(device){
return admin.database().ref('/automation/'+device+'/status').once('value').then(function(snapshot) {
var valor = snapshot.val();
console.log('valor ='+valor);
console.log('device = '+device);
if(device =="temperatura"){
console.log('entrou');
agent.add('O valor da temperatura é de '+valor+' graus Celsius');
}
else{
if(device == "umidade"){
agent.add(`O valor da umidade é de `+valor+` porcento`);
}
else{
if(device=="luz"){
agent.add(`A luz está `+valor);
}
else{
if(device=="led"){
agent.add(`O led está `+valor);
}
else{
if(device=="ventilador"){
agent.add(`O ventilador está `+valor);
}
}
}
}
}
});
}
else{
agent.add(`Desculpe, não entendi`);
}
}
}
// Run the proper function handler based on the matched Dialogflow intent name
let intentMap = new Map();
intentMap.set('controla', handleDevice);
agent.handleRequest(intentMap);
});
DialogFlow Fulfillment
Coloque o código na caixa de
texto e clique em “DEPLOY”
Clique em “Integrations”
Integração com Google Assistent
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.
Código - Configurações
Bibliotecas necessárias
Biblioteca do Firebase
Biblioteca do sensor HTU21D
Fluxograma – 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 #include <Wire.h> // Lib necessária para comunicação i2c #include <SparkFunHTU21D.h> // Lib do sensor HTU21D // Pinos do sensor (i2c - canal 1) #define SDA 21 #define SCL 22 // Objeto referente ao sensor HTU21D htudSensor; // Objeto de conexão (wire) do sensor (O sensor usará o canal 1) TwoWire wireSensor = TwoWire(1); // Intervalo de envios de temperatura e umidade (5 segundos) #define SEND_DATA_INTERVAL 5000 // Url do Firebase #define FIREBASE_HOST "NOMEDOPROJETO.firebaseio.com/" #define FIREBASE_AUTH "" // Nome da rede WiFi e senha const char *ssid = "SSIDWiFi"; const char *password = "SenhaWiFi"; // Pinos dos relés const int luzLed = 19, luz = 18, ventilador = 5; // Valores de temperatura e umidade que serão enviados para o Firebase String temp = "", humd = "";
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(luz, OUTPUT);
pinMode(luzLed, OUTPUT);
pinMode(ventilador, OUTPUT);
// Iniciamos o sensor
htu21Begin();
// Iniciamos o WiFi
wifiBegin();
// Iniciamos a conexão com o Firebase
firebaseBegin();
// Iniciamos a task de envio de temperatura e umidade
xTaskCreatePinnedToCore(sendSensorData, "sendSensorData", 10000, NULL, 1, NULL, 0);
}
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();
// Se for a mensagem inicial enviada pelo firebase assim que o ESP inicia sua comunicação
if(value.startsWith("{\"AUTOMATION\""))
{
// Sincronizamos as saídas para os relés de acordo com a mensagem recebida
syncFirebase(value);
Serial.println("Firebase sincronizado");
}
else
// Se não for uma mensagem referente a temperatura e umidade, executamos um comando e exibimos na serial
if(!path.equals("/AUTOMATION/UMIDADE/STATUS") && !path.equals("/AUTOMATION/TEMPERATURA/STATUS"))
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:
"LED":{"STATUS":"LIGADO"},"LUZ":{"STATUS":"LIGADA"},"TEMPERATURA":{"STATUS":"26.27"},"UMIDADE":{"STATUS":"36.76"},"VENTILADOR":{"STATUS":"LIGADO"}}}
*/
// Obtendo a substring referente a lampada led
String aux = value.substring(value.indexOf("LED"));
int posVar = aux.indexOf("STATUS\":\"")+9;
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, LOW);
else
if(status.equals("DESLIGADO"))
digitalWrite(luzLed, HIGH);
status = "";
// Obtendo a substring referente a lampada incandescente
aux = value.substring(value.indexOf("LUZ"));
posVar = aux.indexOf("STATUS\":\"")+9;
for(int i = posVar; aux.charAt(i)!='\"'; i++)
status += aux.charAt(i);
Serial.println("Status LUZ:"+status);
// Sincronizando saída referente a lampada incandescente
if(status.equals("LIGADA"))
digitalWrite(luz, LOW);
else
if(status.equals("DESLIGADA"))
digitalWrite(luz, HIGH);
status = "";
// Obtendo a substring referente ao ventilador
aux = value.substring(value.indexOf("VENTILADOR"));
posVar = aux.indexOf("STATUS\":\"")+9;
for(int i = posVar; aux.charAt(i)!='\"'; i++)
status += aux.charAt(i);
Serial.println("Status VENTILADOR:"+status);
// Sincronizando saída referente ao ventilador
if(status.equals("LIGADO"))
digitalWrite(ventilador, LOW);
else
if(status.equals("DESLIGADO"))
digitalWrite(ventilador, HIGH);
}
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);
Serial.println(value);
// Caso for um comando referente a lampada incandescente
if(cmd.equals("AUTOMATION/LUZ"))
{
// Se o valor for "LIGADA"
if(value.equals("{\"STATUS\":\"LIGADA\"}"))
// Ativamos o relé (lógica inversa)
digitalWrite(luz, LOW);
else // Caso contrário desativamos o relé
// Desativamos o relé (lógica inversa)
digitalWrite(luz, HIGH);
}
else
// Caso for um comando referente a lampada led
if(cmd.equals("AUTOMATION/LED"))
{
if(value.equals("{\"STATUS\":\"LIGADO\"}"))
// Ativamos o relé (lógica inversa)
digitalWrite(luzLed, LOW);
else // Caso contrário desativamos o relé
digitalWrite(luzLed, HIGH);
}
else
if(cmd.equals("AUTOMATION/VENTILADOR"))
{
if(value.equals("{\"STATUS\":\"LIGADO\"}"))
// Ativamos o relé (lógica inversa)
digitalWrite(ventilador, LOW);
else // Caso contrário desativamos o relé
digitalWrite(ventilador, HIGH);
}
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";
}
sendSensorData
// Task que envia os dados de temperatura e umidadade para o Firebase de tempo em tempo
void sendSensorData(void *p)
{
// Adicionamos a tarefa na lista de monitoramento do watchdog
esp_task_wdt_add(NULL);
while(true)
{
// Resetamos o watchdog
esp_task_wdt_reset();
// Lê os valores do sensor
readClimate();
// Se foi possível ler o sensor
if(temp != "" && humd != "")
{
// Enviamos para o Firebase
Firebase.setString("/automation/temperatura/status", temp);
Firebase.setString("/automation/umidade/status", humd);
Serial.println("sent");
}
// Aguardamos um tempo de 5 segundos
delay(SEND_DATA_INTERVAL);
}
}
readClimate
// Função que lê os valores do sensor
void readClimate()
{
// Retorna 999 caso dê erro de leitura
float h = htudSensor.readHumidity();
float t = htudSensor.readTemperature();
if(t < 900)
temp = String(t);
else
temp = "";
if(h < 900)
humd = String(h);
else
humd = "";
}
htu21Begin e WifiBegin
// Função que inicializa o sensor HTU21D
void htu21Begin()
{
// Iniciamos a comunicação i2c
wireSensor.begin(SDA, SCL, 400000);
// Inicializamos o sensor
htudSensor.begin(wireSensor);
}
// 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()
{
}
















































20 Comentários
Boa noite Fernando, acompanho todos seus canais. Parabéns pelo belo trabalho.
ResponderExcluirAté a que distância o Google Home Mini reconhece os comandos? Um TV ligada interfere muito no reconhecimento?
EU TENHO GOOGLE HOME E ELE CAPTA TUDO MESMO COM BARULHO
ExcluirBoa noite Fernando, mais um vídeo fantástico. Só uma dúvida os arquivos INO e JS estão com mensagem de erro ao tentar abrir com o winrar. Obrigado
ResponderExcluirestou afim de fazer o projeto mas falta o vídeo de inteções
ResponderExcluirShow Fernando!
ResponderExcluirObrigado Carlos !
Excluirmais uma excelente aula mestre!!!!
ResponderExcluirestava querendo muito criar um protocolo de comunicação cambus para pegar algumas informações da central dos veiculos e criar uma interface intuitiva, sei que ja existe um negocio no ml por 30 reais mas quero desenvolver!!!!! curto muito desenvolver algo ainda que seja o mais simples possivel!
Sim David,
Excluiresse espírito de desenvolver as coisas é que levam a melhoria dos produtos e novas abordagens.
A tecnologia melhora porque sempre podemos criar algo novo ou também melhorar o que existe.
continue com essa forma de pensar. Abraços !
Onde encontro o arquivo .zip que vai no intent do dialogflow?
ResponderExcluirFernando, não encontrei o arquivo automation.zip com o projeto pronto com as entidades e intenções já criadas para fazer o download no Dialogflow. Onde posso encontrá-lo?
ResponderExcluirBeleza Fernado, como posso fazer que meu device ative o dialogflow para eu escutar a mensagem? por exemplo, quero que quando a temperatura passe de 40C, ele "fale" um alerta tipo "temperatura alta, cuidado".Abraço
ResponderExcluirFernando, não encontrei o arquivo automation.zip com o projeto pronto com as entidades e intenções já criadas para fazer o download no Dialogflow. Onde posso encontrá-lo?
ResponderExcluirFernando,onde está o arquivo .zip ??
ResponderExcluirCara todo mundo já te perguntou, e como tu não respondeu, vou perguntar novamente: ONDE ESTÁ O ARQUIVO .ZIP QUE ESTÁ NO DIALOGFLOW???
ResponderExcluirboa noite fernando, se possível poderia atualizar o tutorial, algumas coisas mudaram e estou com dificuldades de realizar o tutorial.
ResponderExcluirBoa dia, alguém foi respondido? deviam postar a resposta pq tenho a mesma pergunta.
ResponderExcluirExiste algum tutorial que possamos fazer a comunicação com o firebase via cabo, usando uma shield w5500? Tenho um esp32 que conecto ao roteador via cabo, e gostaria de acessar o firebase desta forma.... alguém ?
ResponderExcluirOla acompanho muito o seu trabalho.Obrigado pela dedicação e seu prazer em compartilhar seus conhecimentos com a gente. Tô tentando fazer com que o Google ligue um dispositivo e avise que foi ligado ,após um determinado tempo ele desligue sozinho e o Google avisa..tô tentando adaptar esse projeto que vc compartilhou com a gente
ResponderExcluirGostei bastante do material, porem vejo que não existe resposta para as pessoas que estão tentando baixar os arquivos. Alguem poderia por favor disponibilizar os arquivos .rar e também o arquivo de entidade e intenções? Grato.
ResponderExcluirMuito bom! Tem muito esforço nesse projeto. Misericórdia...Bom demais..
ResponderExcluir