Desenvolvimento

21 dez, 2017

Android Things + Firebase + Google Assistant – Parte 02

Publicidade

Agora vamos ao que interessa: Implementar o hardware da dispensadora e integrar com o Firebase e Google Home.

Se você ainda não viu a parte 1 que fala sobre Firebase, Cloud Functions e permissões, clique aqui.

Android Things

A nova plataforma do Google para Internet da Coisas (IoT) baseada em Android, permite construir aplicativos em Java que tem acesso não apenas ao stack Android, mas também aos recursos de hardware dos dispositivos compatíveis. É possível utilizar RaspberryPi 3, NXP, entre outros (a plataforma Intel Edison não está mais nessa lista, infelizmente).

Você utilizará o Android Studio como IDE de desenvolvimento e fará o deploy pela USB ou via rede, conforme o dispositivo que utilizar. O RaspiberryPi pode ser configurado via WiFi, mas a primeira conexão é sempre pela rede.

O processo de gravação da imagem do Raspi é bem documentado e existem vários tutoriais, portanto não vou detalhá-lo aqui.

Lista de Equipamentos

  • RaspiberryPi 3
  • Cartão de Memória Micro-SD (mínimo de 8GB)
  • Fonte de Energia 5V para Raspi (micro-usb)
  • Fonte de Energia 5V para Dispensadora
  • Dispensadora Automática (Amazon)
  • Módulo de Relé 5V (com acionamento no HIGH)
  • Fios e conectores

Escolha da Conectividade

Eu acabei fazendo a escolha pelo RaspiberryPi 3, uma vez que utilizaria um roteador WiFi independente configurado como cliente de uma rede WiFi existente. Isso me permitiu utilizar redes de 5.0 GHz (o Raspi e o Edison só conectam em 2.4Ghz) e ter uma infra-estrutura mais maleável.

Eletrônica

Para o circuito eletrônico acabei utilizando um módulo de relé, que acionava uma dispensadora automática que pode ser encontrada na Amazon e algumas vezes no Mercado Livre aqui no Brasil. Para utilizá-la, basta ligar a alimentação do motor diretamente em 5 volts e utilizar um módulo de relé para interromper o circuito. Utilize um módulo pronto que já tenha o circuito de proteção e nunca ligue diretamente um relé no raspberryPi sem esse circuito!

Configurando a Plataforma

Para acesso ao Firebase e ativação dos serviços de autenticação, é necessário que você crie o arquivo google-services.json no seu projeto do Android Studio. Esse arquivo é gerado pelo próprio Firebase, quando você configura um aplicativo Android. Para fazer o processo e/ou baixar o arquivo, vá na engrenagem dentro do seu projeto e clique em “Configurações do Projeto”. Na sequência, faça o processo para configurar seu app Android ou baixar o arquivo google-services.json caso já tenha feito esse processo. Salve o arquivo na pasta “/app”.

Acesso ao Firebase

Uma das funcionalidades que ainda não está prevista no Android Things é a parte de autenticação. Eu acredito que seja porque o dispositivo ainda não implementa nenhum processo relacionado a propriedade do dispositivo, como acontecia antes com o Brillo, aonde você tinha um aplicativo de configuração.

Isso não quer dizer que a parte de autenticação do Firebase está completamente bloqueada e que você precisa deixar os parâmetros de gravação do realtime database sempre com permissão completa de leitura e escrita (o que é algo muito sério e que abre uma brecha para que qualquer usuário possa reescrever sua base de dados).

Eu fiz uma tentativa que resultou em sucesso que foi ativar a autenticação por e-mail e senha e criar um registro específico nessa modalidade para ser utilizado pelos dispositivos. Assim eu poderia criar permissões específicas para este usuário, como por exemplo, a remoção de um nó específico que indica a ativação da dispensadora, além da consulta do intervalo que ela fica ativa liberando doces, entre outras coisas.

Google Assistant

A pirotecnia fica mais divertida com Silvio Santos e o Peão do Baú!

Esta funcionalidade faz parte da plataforma “Actions on Google” e é possível criar um serviço de bot para o Google Assistant (que roda hoje na plataforma Android e no Google Home).

Ao criar um bot, você precisa pensar em quais serão as conversas disponíveis no seu serviço e desenhar esse processo de conversação.

Você pode desenvolver seu serviço de forma semi-automática através da plataforma API.ai ou construir seu serviço do zero.

Veja detalhes de design aqui.

Neste projeto, utilizaremos a opção do Cloud Functions. Existe um exemplo base pronto para isso que adaptaremos e criaremos nosso “sorteador do Baú!”.

Para rodar o projeto você precisa:

  • Ter o projeto do Firebase criado e adicionar o módulo “actions-on-google” no projeto do Functions. Rodar o “npm install — save actions-on-google”.
  • Fazer o download do gaction CLI.
/**
 * Endpoint which handles requests for a Google Assistant action which asks users to say a number
 * and read out the ordinal of that number.
 * e.g. If the user says "Twelve" the action will say "The ordinal of twelve is twelfth".
 */
exports.raffleUser = functions.https.onRequest((req, res) => {
  const assistant = new ActionsSdkAssistant({request: req, response: res});

  // List of re-prompts that are used when we did not understand a number from the user.
  const reprompts = [
    'You can say <break time="3"/>Yes, sure or go'
  ];

  const actions = [
  	'yes',
  	'sure',
  	'let\s do this',
  	'go'
  ];

  const ending = [
  	'no',
  	'bye'
  ];


  const WELCOME_MESSAGE = `<speak>
        Hi Capivaras! <break time="1"/>
        Do you like to raffle a new swag?.
      </speak>`;


  const actionMap = new Map();

  actionMap.set(assistant.StandardIntents.MAIN, assistant => {
    const inputPrompt = assistant.buildInputPrompt(true, WELCOME_MESSAGE, reprompts
    );
    assistant.ask(inputPrompt);
  });

  actionMap.set(assistant.StandardIntents.TEXT, assistant => {
    const rawInput = assistant.getRawInput();

    if (actions.indexOf(rawInput.toLowerCase()) >= 0) {
    	//https://www.myinstants.com/media/sounds/piao-do-bau-com-musica.mp3
    	//https://estudenaudacity.firebaseapp.com/piao-do-bau-com-musica.wav
    	//https://actions.google.com/sounds/v1/cartoon/magic_chime.ogg

    	var raffled_user = raffle();
    	console.log("SORTEEI ", raffled_user);
    	if(!raffled_user) {
			assistant.tell('Sorry. I can\'t find any user to raffle!');

    	} else {
			var user_displayName = raffled_user.displayName || "NAME NOT DEFINED";

			const message = `<speak><audio src="https://estudenaudacity.firebaseapp.com/piao-do-bau-com-musica.wav"></audio><break time="3"/>
				The user is  <break time="3"/>` +
				user_displayName +
				` <break time="3"/>Whould you like to receive another one?</speak>`;
			
			// sortear usuario e avisar
			const inputPrompt = assistant.buildInputPrompt(true, message, reprompts);
	    	// avisar que não entendeu
	    	assistant.ask(inputPrompt);

    	}



    } else if (ending.indexOf(rawInput.toLowerCase()) >= 0) {
		assistant.tell('Goodbye!');
    } else {
      		const inputPrompt = assistant.buildInputPrompt(true, WELCOME_MESSAGE, reprompts);
			//TODO: avisar que não entendeu
			assistant.ask(inputPrompt);
    }

  });

  assistant.handleRequest(actionMap);

});

Você precisa mapear suas ações, são dois Intents padrões:

  • StandardIntents.MAIN: intent de entrada e que é utilizado quando você aciona pelo comando “talk to ____”.
  • StandardIntents.TEXT: acionado quando você recebe algum parâmetro de texto.

Ao construir uma mensagem com um prompt de resposta você pode incluir também mensagens de “reprompt”. Elas são sintetizadas quando o assistente não consegue entender o que foi informado ou quando não ocorre uma resposta.

Estruturando os Comandos

O objetivo desse app é apenas realizar o sorteio dos participantes que fizeram o cadastro no sistema e estão listados no nó “users”. Por isso deixei a funcionalidade mais simples e o sistema apenas faz o sorteio e pergunta se é necessário continuar sorteando.

Para evitar um sorteio de um mesmo participante, após escolher o sorteado, o sistema marca ele e retira da lista.

Mantendo um diálogo ou finalizando uma conversa

Para gerar uma mensagem, utilize o comando assistant.ask() caso queira obter uma reposta, ou assistant.tell() caso deseje finalizar a conversação.

Para tratar o texto de resposta, utilize o método assistant.getRawInput().

Eu não fiz um teste mais elaborado do acionamento do menu principal. Em breve faço um artigo especificamente sobre este tópico.

Realizando o sorteio e avisando o vencedor

Neste caso a função precisa apenas alterar o parâmetro “sorteado” no registro do usuário para “true”. A parte de notificação (implementada apenas a interface web) é feita pelo navegador. Também seria possível criar um gatilho no Cloud Functions para gerar uma notificação do Cloud Messaging.

Fazendo o deploy e testando o assistente

Para que seu projeto fique disponível em todos os assistentes, você precisa realizar a publicação e aprovação do seu projeto, mas é possível criar e testar sua integração de uma versão de teste. Basta usar o comando:

E para testar, nem precisa ter um dispositivo, você pode utilizar um “Simulador Web do Assistant”. Envie a mensagem “talk to capivara” para ativar o assistente. Observe que o comando de preview funciona durante 15 minutos (E APENAS PARA SUA CONTA). Após esse tempo é necessário ativar novamente.

É possível testar seu serviço através do Web Simulator!

Conclusão

Fiquei muito feliz com o resultado e com o tempo de resposta da aplicação. O Marcelo Quinta, que foi meu “assistente de palco”, sofreu um pouco enquanto a galera na plateia freneticamente informava o token e ativava a dispensadora enquanto ele tentava encaixar os copinhos.

O procedimento de sorteio também funcionou de forma super tranquila ao mesmo tempo que notificava os participantes que foram sorteados. Embora os 160 usuários conectados não representem um número significativo (se pensarmos em apps escaláveis), conseguimos ver o poder do “Realtime Database” e criar uma aplicação prática e divertida para demonstrar a plataforma, além de levantarmos todas as questões importantes para desenvolver apps com Firebase.

Faça você mesmo!

Se você quer testar este app, o código de todo o projeto está no GitHub! Caso você implemente, poste sua demo nas redes sociais com a hashtag #vendingdoleao.

Happy hacking!